diff options
author | Peter Marko <peter.marko@siemens.com> | 2025-01-08 08:45:12 +0100 |
---|---|---|
committer | Armin Kuster <akuster808@gmail.com> | 2025-01-20 19:31:55 -0500 |
commit | d793d2d876f6219eb33aeb0179b3e83aa899716c (patch) | |
tree | 843f6d5b846a7765d2eb5f80ed43b7efaba26d41 | |
parent | 20239ef5ce5bb1097fd2f13ff917d6e6613f8860 (diff) | |
download | meta-openembedded-d793d2d876f6219eb33aeb0179b3e83aa899716c.tar.gz |
thrift: fix c++ generated code compilation with clang
Backport PR merged to thrift v0.21.0 to be able to compile thrift
generated c++ code with C++20 clang 15+.
Signed-off-by: Stanislav Angelovic <stanislav.angelovic.ext@siemens.com>
Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r-- | meta-oe/recipes-connectivity/thrift/thrift/0001-thrift-pr2755.patch | 599 | ||||
-rw-r--r-- | meta-oe/recipes-connectivity/thrift/thrift_0.20.0.bb | 4 |
2 files changed, 602 insertions, 1 deletions
diff --git a/meta-oe/recipes-connectivity/thrift/thrift/0001-thrift-pr2755.patch b/meta-oe/recipes-connectivity/thrift/thrift/0001-thrift-pr2755.patch new file mode 100644 index 0000000000..b685d42728 --- /dev/null +++ b/meta-oe/recipes-connectivity/thrift/thrift/0001-thrift-pr2755.patch | |||
@@ -0,0 +1,599 @@ | |||
1 | From f02ac2fb573bed72e9a2d1875807c6ff7ac19ec8 Mon Sep 17 00:00:00 2001 | ||
2 | From: Lukas Barth <mail@tinloaf.de> | ||
3 | Date: Wed, 8 Feb 2023 09:33:03 +0100 | ||
4 | Subject: [PATCH 1/5] Move default constructor and operator== implementation to | ||
5 | CPP file | ||
6 | |||
7 | Both the default constructor and operator== implementations reference | ||
8 | certain member functions of the class' members. As an example, the default | ||
9 | constructor references (i.e., "uses") the default constructors of its | ||
10 | members. | ||
11 | |||
12 | If a class contains a std::vector<Foo>, and Foo has only been *forward*- | ||
13 | declared (which happens often in Thrift-generated code), this creates | ||
14 | undefined behavior: The std::vector specification states that as long as | ||
15 | Foo is an incomplete type, it is fine to reference std::vector<Foo>, but | ||
16 | not any members (such as its default constructor). | ||
17 | |||
18 | Thus, we must defer our default constructor's implementation (which references | ||
19 | the default constructor of std::vector<Foo>) to a point where Foo is a | ||
20 | complete type. That is the case in the .cpp file. | ||
21 | |||
22 | The same holds for operator==. | ||
23 | |||
24 | Upstream-Status: Backport [https://github.com/apache/thrift/pull/2755] | ||
25 | |||
26 | Signed-off-by: Stanislav Angelovic <stanislav.angelovic.ext@siemens.com> | ||
27 | Signed-off-by: Peter Marko <peter.marko@siemens.com> | ||
28 | --- | ||
29 | .../src/thrift/generate/t_cpp_generator.cc | 187 +++++++++++------- | ||
30 | 1 file changed, 121 insertions(+), 66 deletions(-) | ||
31 | |||
32 | diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
33 | index 9724fae80..fecfa4bb5 100644 | ||
34 | --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
35 | +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
36 | @@ -146,11 +146,13 @@ public: | ||
37 | bool is_user_struct = false); | ||
38 | void generate_copy_constructor(std::ostream& out, t_struct* tstruct, bool is_exception); | ||
39 | void generate_move_constructor(std::ostream& out, t_struct* tstruct, bool is_exception); | ||
40 | + void generate_default_constructor(std::ostream& out, t_struct* tstruct, bool is_exception); | ||
41 | void generate_constructor_helper(std::ostream& out, | ||
42 | t_struct* tstruct, | ||
43 | bool is_excpetion, | ||
44 | bool is_move); | ||
45 | void generate_assignment_operator(std::ostream& out, t_struct* tstruct); | ||
46 | + void generate_equality_operator(std::ostream& out, t_struct* tstruct); | ||
47 | void generate_move_assignment_operator(std::ostream& out, t_struct* tstruct); | ||
48 | void generate_assignment_helper(std::ostream& out, t_struct* tstruct, bool is_move); | ||
49 | void generate_struct_reader(std::ostream& out, t_struct* tstruct, bool pointers = false); | ||
50 | @@ -914,6 +916,10 @@ void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) | ||
51 | generate_struct_reader(out, tstruct); | ||
52 | generate_struct_writer(out, tstruct); | ||
53 | generate_struct_swap(f_types_impl_, tstruct); | ||
54 | + if (!gen_no_default_operators_) { | ||
55 | + generate_equality_operator(f_types_impl_, tstruct); | ||
56 | + } | ||
57 | + generate_default_constructor(f_types_impl_, tstruct, is_exception); | ||
58 | generate_copy_constructor(f_types_impl_, tstruct, is_exception); | ||
59 | if (gen_moveable_) { | ||
60 | generate_move_constructor(f_types_impl_, tstruct, is_exception); | ||
61 | @@ -934,6 +940,117 @@ void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) | ||
62 | has_members_ = true; | ||
63 | } | ||
64 | |||
65 | +void t_cpp_generator::generate_equality_operator(std::ostream& out, t_struct* tstruct) { | ||
66 | + // Get members | ||
67 | + vector<t_field*>::const_iterator m_iter; | ||
68 | + const vector<t_field*>& members = tstruct->get_members(); | ||
69 | + | ||
70 | + out << indent() << "bool " << tstruct->get_name() | ||
71 | + << "::operator==(const " << tstruct->get_name() << " & " | ||
72 | + << (members.size() > 0 ? "rhs" : "/* rhs */") << ") const" << endl; | ||
73 | + scope_up(out); | ||
74 | + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
75 | + // Most existing Thrift code does not use isset or optional/required, | ||
76 | + // so we treat "default" fields as required. | ||
77 | + if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { | ||
78 | + out << indent() << "if (!(" << (*m_iter)->get_name() << " == rhs." | ||
79 | + << (*m_iter)->get_name() << "))" << endl << indent() << " return false;" << endl; | ||
80 | + } else { | ||
81 | + out << indent() << "if (__isset." << (*m_iter)->get_name() << " != rhs.__isset." | ||
82 | + << (*m_iter)->get_name() << ")" << endl << indent() << " return false;" << endl | ||
83 | + << indent() << "else if (__isset." << (*m_iter)->get_name() << " && !(" | ||
84 | + << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name() << "))" << endl | ||
85 | + << indent() << " return false;" << endl; | ||
86 | + } | ||
87 | + } | ||
88 | + indent(out) << "return true;" << endl; | ||
89 | + scope_down(out); | ||
90 | + out << "\n"; | ||
91 | +} | ||
92 | + | ||
93 | +void t_cpp_generator::generate_default_constructor(ostream& out, | ||
94 | + t_struct* tstruct, | ||
95 | + bool is_exception) { | ||
96 | + // Get members | ||
97 | + vector<t_field*>::const_iterator m_iter; | ||
98 | + const vector<t_field*>& members = tstruct->get_members(); | ||
99 | + | ||
100 | + // TODO(barth) this is duplicated from generate_struct_declaration | ||
101 | + bool has_default_value = false; | ||
102 | + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
103 | + t_type* t = get_true_type((*m_iter)->get_type()); | ||
104 | + if (is_reference(*m_iter) || t->is_string()) { | ||
105 | + t_const_value* cv = (*m_iter)->get_value(); | ||
106 | + if (cv != nullptr) { | ||
107 | + has_default_value = true; | ||
108 | + break; | ||
109 | + } | ||
110 | + } | ||
111 | + } | ||
112 | + | ||
113 | + std::string clsname_ctor = tstruct->get_name() + "::" + tstruct->get_name() + "()"; | ||
114 | + indent(out) << clsname_ctor << (has_default_value ? "" : " noexcept"); | ||
115 | + | ||
116 | + if (has_default_value || is_exception) { | ||
117 | + // We need an initializer block | ||
118 | + | ||
119 | + bool init_ctor = false; | ||
120 | + std::string args_indent(" "); | ||
121 | + | ||
122 | + // Default-initialize TException, if it is our base type | ||
123 | + if (is_exception) | ||
124 | + { | ||
125 | + out << "\n"; | ||
126 | + indent(out) << " : "; | ||
127 | + out << "TException()"; | ||
128 | + init_ctor = true; | ||
129 | + } | ||
130 | + | ||
131 | + // Default-initialize all members that should be initialized in | ||
132 | + // the initializer block | ||
133 | + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
134 | + t_type* t = get_true_type((*m_iter)->get_type()); | ||
135 | + if (t->is_base_type() || t->is_enum() || is_reference(*m_iter)) { | ||
136 | + string dval; | ||
137 | + t_const_value* cv = (*m_iter)->get_value(); | ||
138 | + if (cv != nullptr) { | ||
139 | + dval += render_const_value(out, (*m_iter)->get_name(), t, cv); | ||
140 | + } else if (t->is_enum()) { | ||
141 | + dval += "static_cast<" + type_name(t) + ">(0)"; | ||
142 | + } else { | ||
143 | + dval += (t->is_string() || is_reference(*m_iter)) ? "" : "0"; | ||
144 | + } | ||
145 | + if (!init_ctor) { | ||
146 | + out << "\n"; | ||
147 | + indent(out) << " : "; | ||
148 | + init_ctor = true; | ||
149 | + } else { | ||
150 | + out << ",\n"; | ||
151 | + indent(out) << args_indent; | ||
152 | + } | ||
153 | + | ||
154 | + out << (*m_iter)->get_name() << "(" << dval << ")"; | ||
155 | + } | ||
156 | + } | ||
157 | + out << " {" << endl; | ||
158 | + indent_up(); | ||
159 | + // TODO(dreiss): When everything else in Thrift is perfect, | ||
160 | + // do more of these in the initializer list. | ||
161 | + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
162 | + t_type* t = get_true_type((*m_iter)->get_type()); | ||
163 | + if (!t->is_base_type() && !t->is_enum() && !is_reference(*m_iter)) { | ||
164 | + t_const_value* cv = (*m_iter)->get_value(); | ||
165 | + if (cv != nullptr) { | ||
166 | + print_const_value(out, (*m_iter)->get_name(), t, cv); | ||
167 | + } | ||
168 | + } | ||
169 | + } | ||
170 | + scope_down(out); | ||
171 | + } else { | ||
172 | + out << " {}\n"; | ||
173 | + } | ||
174 | +} | ||
175 | + | ||
176 | void t_cpp_generator::generate_copy_constructor(ostream& out, | ||
177 | t_struct* tstruct, | ||
178 | bool is_exception) { | ||
179 | @@ -1168,52 +1285,7 @@ void t_cpp_generator::generate_struct_declaration(ostream& out, | ||
180 | |||
181 | // Default constructor | ||
182 | std::string clsname_ctor = tstruct->get_name() + "()"; | ||
183 | - indent(out) << clsname_ctor << (has_default_value ? "" : " noexcept"); | ||
184 | - | ||
185 | - bool init_ctor = false; | ||
186 | - std::string args_indent( | ||
187 | - indent().size() + clsname_ctor.size() + (has_default_value ? 3 : -1), ' '); | ||
188 | - | ||
189 | - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
190 | - t_type* t = get_true_type((*m_iter)->get_type()); | ||
191 | - if (t->is_base_type() || t->is_enum() || is_reference(*m_iter)) { | ||
192 | - string dval; | ||
193 | - t_const_value* cv = (*m_iter)->get_value(); | ||
194 | - if (cv != nullptr) { | ||
195 | - dval += render_const_value(out, (*m_iter)->get_name(), t, cv); | ||
196 | - } else if (t->is_enum()) { | ||
197 | - dval += "static_cast<" + type_name(t) + ">(0)"; | ||
198 | - } else { | ||
199 | - dval += (t->is_string() || is_reference(*m_iter)) ? "" : "0"; | ||
200 | - } | ||
201 | - if (!init_ctor) { | ||
202 | - init_ctor = true; | ||
203 | - if(has_default_value) { | ||
204 | - out << " : "; | ||
205 | - } else { | ||
206 | - out << '\n' << args_indent << ": "; | ||
207 | - args_indent.append(" "); | ||
208 | - } | ||
209 | - } else { | ||
210 | - out << ",\n" << args_indent; | ||
211 | - } | ||
212 | - out << (*m_iter)->get_name() << "(" << dval << ")"; | ||
213 | - } | ||
214 | - } | ||
215 | - out << " {" << endl; | ||
216 | - indent_up(); | ||
217 | - // TODO(dreiss): When everything else in Thrift is perfect, | ||
218 | - // do more of these in the initializer list. | ||
219 | - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
220 | - t_type* t = get_true_type((*m_iter)->get_type()); | ||
221 | - if (!t->is_base_type() && !t->is_enum() && !is_reference(*m_iter)) { | ||
222 | - t_const_value* cv = (*m_iter)->get_value(); | ||
223 | - if (cv != nullptr) { | ||
224 | - print_const_value(out, (*m_iter)->get_name(), t, cv); | ||
225 | - } | ||
226 | - } | ||
227 | - } | ||
228 | - scope_down(out); | ||
229 | + indent(out) << clsname_ctor << (has_default_value ? "" : " noexcept") << ";" << endl; | ||
230 | } | ||
231 | |||
232 | if (tstruct->annotations_.find("final") == tstruct->annotations_.end()) { | ||
233 | @@ -1254,27 +1326,10 @@ void t_cpp_generator::generate_struct_declaration(ostream& out, | ||
234 | if (!pointers) { | ||
235 | // Should we generate default operators? | ||
236 | if (!gen_no_default_operators_) { | ||
237 | - // Generate an equality testing operator. Make it inline since the compiler | ||
238 | - // will do a better job than we would when deciding whether to inline it. | ||
239 | + // Generate an equality testing operator. | ||
240 | out << indent() << "bool operator == (const " << tstruct->get_name() << " & " | ||
241 | - << (members.size() > 0 ? "rhs" : "/* rhs */") << ") const" << endl; | ||
242 | - scope_up(out); | ||
243 | - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
244 | - // Most existing Thrift code does not use isset or optional/required, | ||
245 | - // so we treat "default" fields as required. | ||
246 | - if ((*m_iter)->get_req() != t_field::T_OPTIONAL) { | ||
247 | - out << indent() << "if (!(" << (*m_iter)->get_name() << " == rhs." | ||
248 | - << (*m_iter)->get_name() << "))" << endl << indent() << " return false;" << endl; | ||
249 | - } else { | ||
250 | - out << indent() << "if (__isset." << (*m_iter)->get_name() << " != rhs.__isset." | ||
251 | - << (*m_iter)->get_name() << ")" << endl << indent() << " return false;" << endl | ||
252 | - << indent() << "else if (__isset." << (*m_iter)->get_name() << " && !(" | ||
253 | - << (*m_iter)->get_name() << " == rhs." << (*m_iter)->get_name() << "))" << endl | ||
254 | - << indent() << " return false;" << endl; | ||
255 | - } | ||
256 | - } | ||
257 | - indent(out) << "return true;" << endl; | ||
258 | - scope_down(out); | ||
259 | + << (members.size() > 0 ? "rhs" : "/* rhs */") << ") const;" << endl; | ||
260 | + | ||
261 | out << indent() << "bool operator != (const " << tstruct->get_name() << " &rhs) const {" | ||
262 | << endl << indent() << " return !(*this == rhs);" << endl << indent() << "}" << endl | ||
263 | << endl; | ||
264 | |||
265 | From cedcd0e6424a08dd6feeb2533810054c9aca2a9e Mon Sep 17 00:00:00 2001 | ||
266 | From: Lukas Barth <mail@tinloaf.de> | ||
267 | Date: Wed, 8 Feb 2023 10:11:48 +0100 | ||
268 | Subject: [PATCH 2/5] Factor out duplicated code into helper function | ||
269 | |||
270 | --- | ||
271 | .../src/thrift/generate/t_cpp_generator.cc | 43 ++++++++++--------- | ||
272 | 1 file changed, 23 insertions(+), 20 deletions(-) | ||
273 | |||
274 | diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
275 | index fecfa4bb5..a77982f61 100644 | ||
276 | --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
277 | +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
278 | @@ -302,6 +302,12 @@ public: | ||
279 | */ | ||
280 | bool is_struct_storage_not_throwing(t_struct* tstruct) const; | ||
281 | |||
282 | + /** | ||
283 | + * Helper function to determine whether any of the members of our struct | ||
284 | + * has a default value. | ||
285 | + */ | ||
286 | + bool has_field_with_default_value(t_struct* tstruct); | ||
287 | + | ||
288 | private: | ||
289 | /** | ||
290 | * Returns the include prefix to use for a file generated by program, or the | ||
291 | @@ -968,26 +974,33 @@ void t_cpp_generator::generate_equality_operator(std::ostream& out, t_struct* ts | ||
292 | out << "\n"; | ||
293 | } | ||
294 | |||
295 | -void t_cpp_generator::generate_default_constructor(ostream& out, | ||
296 | - t_struct* tstruct, | ||
297 | - bool is_exception) { | ||
298 | - // Get members | ||
299 | +bool t_cpp_generator::has_field_with_default_value(t_struct* tstruct) | ||
300 | +{ | ||
301 | vector<t_field*>::const_iterator m_iter; | ||
302 | const vector<t_field*>& members = tstruct->get_members(); | ||
303 | |||
304 | - // TODO(barth) this is duplicated from generate_struct_declaration | ||
305 | - bool has_default_value = false; | ||
306 | for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
307 | t_type* t = get_true_type((*m_iter)->get_type()); | ||
308 | if (is_reference(*m_iter) || t->is_string()) { | ||
309 | t_const_value* cv = (*m_iter)->get_value(); | ||
310 | if (cv != nullptr) { | ||
311 | - has_default_value = true; | ||
312 | - break; | ||
313 | + return true; | ||
314 | } | ||
315 | } | ||
316 | } | ||
317 | |||
318 | + return false; | ||
319 | +} | ||
320 | + | ||
321 | +void t_cpp_generator::generate_default_constructor(ostream& out, | ||
322 | + t_struct* tstruct, | ||
323 | + bool is_exception) { | ||
324 | + // Get members | ||
325 | + vector<t_field*>::const_iterator m_iter; | ||
326 | + const vector<t_field*>& members = tstruct->get_members(); | ||
327 | + | ||
328 | + bool has_default_value = has_field_with_default_value(tstruct); | ||
329 | + | ||
330 | std::string clsname_ctor = tstruct->get_name() + "::" + tstruct->get_name() + "()"; | ||
331 | indent(out) << clsname_ctor << (has_default_value ? "" : " noexcept"); | ||
332 | |||
333 | @@ -1271,18 +1284,8 @@ void t_cpp_generator::generate_struct_declaration(ostream& out, | ||
334 | << endl; | ||
335 | } | ||
336 | |||
337 | - bool has_default_value = false; | ||
338 | - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
339 | - t_type* t = get_true_type((*m_iter)->get_type()); | ||
340 | - if (is_reference(*m_iter) || t->is_string()) { | ||
341 | - t_const_value* cv = (*m_iter)->get_value(); | ||
342 | - if (cv != nullptr) { | ||
343 | - has_default_value = true; | ||
344 | - break; | ||
345 | - } | ||
346 | - } | ||
347 | - } | ||
348 | - | ||
349 | + bool has_default_value = has_field_with_default_value(tstruct); | ||
350 | + | ||
351 | // Default constructor | ||
352 | std::string clsname_ctor = tstruct->get_name() + "()"; | ||
353 | indent(out) << clsname_ctor << (has_default_value ? "" : " noexcept") << ";" << endl; | ||
354 | |||
355 | From 16105fa1a1bb9ae633b805fcb7af3c7757beb6e0 Mon Sep 17 00:00:00 2001 | ||
356 | From: Lukas Barth <mail@tinloaf.de> | ||
357 | Date: Fri, 24 Feb 2023 13:46:58 +0100 | ||
358 | Subject: [PATCH 3/5] Move generate_default_constructor call into | ||
359 | generate_struct_definition | ||
360 | |||
361 | This makes sure that helper structs like _args and _result also have | ||
362 | their default constructors defined. | ||
363 | --- | ||
364 | .../src/thrift/generate/t_cpp_generator.cc | 19 +++++++++++++------ | ||
365 | 1 file changed, 13 insertions(+), 6 deletions(-) | ||
366 | |||
367 | diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
368 | index a77982f61..ccb79bc48 100644 | ||
369 | --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
370 | +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
371 | @@ -143,7 +143,8 @@ public: | ||
372 | std::ostream& force_cpp_out, | ||
373 | t_struct* tstruct, | ||
374 | bool setters = true, | ||
375 | - bool is_user_struct = false); | ||
376 | + bool is_user_struct = false, | ||
377 | + bool pointers = false); | ||
378 | void generate_copy_constructor(std::ostream& out, t_struct* tstruct, bool is_exception); | ||
379 | void generate_move_constructor(std::ostream& out, t_struct* tstruct, bool is_exception); | ||
380 | void generate_default_constructor(std::ostream& out, t_struct* tstruct, bool is_exception); | ||
381 | @@ -916,7 +917,7 @@ void t_cpp_generator::generate_forward_declaration(t_struct* tstruct) { | ||
382 | */ | ||
383 | void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) { | ||
384 | generate_struct_declaration(f_types_, tstruct, is_exception, false, true, true, true, true); | ||
385 | - generate_struct_definition(f_types_impl_, f_types_impl_, tstruct, true, true); | ||
386 | + generate_struct_definition(f_types_impl_, f_types_impl_, tstruct, true, true, false); | ||
387 | |||
388 | std::ostream& out = (gen_templates_ ? f_types_tcc_ : f_types_impl_); | ||
389 | generate_struct_reader(out, tstruct); | ||
390 | @@ -925,7 +926,6 @@ void t_cpp_generator::generate_cpp_struct(t_struct* tstruct, bool is_exception) | ||
391 | if (!gen_no_default_operators_) { | ||
392 | generate_equality_operator(f_types_impl_, tstruct); | ||
393 | } | ||
394 | - generate_default_constructor(f_types_impl_, tstruct, is_exception); | ||
395 | generate_copy_constructor(f_types_impl_, tstruct, is_exception); | ||
396 | if (gen_moveable_) { | ||
397 | generate_move_constructor(f_types_impl_, tstruct, is_exception); | ||
398 | @@ -1408,7 +1408,8 @@ void t_cpp_generator::generate_struct_definition(ostream& out, | ||
399 | ostream& force_cpp_out, | ||
400 | t_struct* tstruct, | ||
401 | bool setters, | ||
402 | - bool is_user_struct) { | ||
403 | + bool is_user_struct, | ||
404 | + bool pointers) { | ||
405 | // Get members | ||
406 | vector<t_field*>::const_iterator m_iter; | ||
407 | const vector<t_field*>& members = tstruct->get_members(); | ||
408 | @@ -1423,6 +1424,11 @@ void t_cpp_generator::generate_struct_definition(ostream& out, | ||
409 | force_cpp_out << indent() << "}" << endl << endl; | ||
410 | } | ||
411 | |||
412 | + if (!pointers) | ||
413 | + { | ||
414 | + generate_default_constructor(out, tstruct, false); | ||
415 | + } | ||
416 | + | ||
417 | // Create a setter function for each field | ||
418 | if (setters) { | ||
419 | for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
420 | @@ -2058,9 +2064,10 @@ void t_cpp_generator::generate_service_helpers(t_service* tservice) { | ||
421 | generate_struct_definition(out, f_service_, ts, false); | ||
422 | generate_struct_reader(out, ts); | ||
423 | generate_struct_writer(out, ts); | ||
424 | + | ||
425 | ts->set_name(tservice->get_name() + "_" + (*f_iter)->get_name() + "_pargs"); | ||
426 | generate_struct_declaration(f_header_, ts, false, true, false, true); | ||
427 | - generate_struct_definition(out, f_service_, ts, false); | ||
428 | + generate_struct_definition(out, f_service_, ts, false, false, true); | ||
429 | generate_struct_writer(out, ts, true); | ||
430 | ts->set_name(name_orig); | ||
431 | |||
432 | @@ -3508,7 +3515,7 @@ void t_cpp_generator::generate_function_helpers(t_service* tservice, t_function* | ||
433 | |||
434 | result.set_name(tservice->get_name() + "_" + tfunction->get_name() + "_presult"); | ||
435 | generate_struct_declaration(f_header_, &result, false, true, true, gen_cob_style_); | ||
436 | - generate_struct_definition(out, f_service_, &result, false); | ||
437 | + generate_struct_definition(out, f_service_, &result, false, false, true); | ||
438 | generate_struct_reader(out, &result, true); | ||
439 | if (gen_cob_style_) { | ||
440 | generate_struct_writer(out, &result, true); | ||
441 | |||
442 | From 4f56007baf46d4aa87eb7f8e5e34b773235c729a Mon Sep 17 00:00:00 2001 | ||
443 | From: Lukas Barth <mail@tinloaf.de> | ||
444 | Date: Mon, 6 Mar 2023 11:37:09 +0100 | ||
445 | Subject: [PATCH 4/5] Always generate an initializer list | ||
446 | |||
447 | --- | ||
448 | .../src/thrift/generate/t_cpp_generator.cc | 102 +++++++++--------- | ||
449 | 1 file changed, 54 insertions(+), 48 deletions(-) | ||
450 | |||
451 | diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
452 | index ccb79bc48..2a65bfb96 100644 | ||
453 | --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
454 | +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
455 | @@ -1004,64 +1004,70 @@ void t_cpp_generator::generate_default_constructor(ostream& out, | ||
456 | std::string clsname_ctor = tstruct->get_name() + "::" + tstruct->get_name() + "()"; | ||
457 | indent(out) << clsname_ctor << (has_default_value ? "" : " noexcept"); | ||
458 | |||
459 | - if (has_default_value || is_exception) { | ||
460 | - // We need an initializer block | ||
461 | + // | ||
462 | + // Start generating initializer list | ||
463 | + // | ||
464 | |||
465 | - bool init_ctor = false; | ||
466 | - std::string args_indent(" "); | ||
467 | + bool init_ctor = false; | ||
468 | + std::string args_indent(" "); | ||
469 | |||
470 | - // Default-initialize TException, if it is our base type | ||
471 | - if (is_exception) | ||
472 | - { | ||
473 | - out << "\n"; | ||
474 | - indent(out) << " : "; | ||
475 | - out << "TException()"; | ||
476 | - init_ctor = true; | ||
477 | - } | ||
478 | + // Default-initialize TException, if it is our base type | ||
479 | + if (is_exception) | ||
480 | + { | ||
481 | + out << "\n"; | ||
482 | + indent(out) << " : "; | ||
483 | + out << "TException()"; | ||
484 | + init_ctor = true; | ||
485 | + } | ||
486 | |||
487 | - // Default-initialize all members that should be initialized in | ||
488 | - // the initializer block | ||
489 | - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
490 | - t_type* t = get_true_type((*m_iter)->get_type()); | ||
491 | - if (t->is_base_type() || t->is_enum() || is_reference(*m_iter)) { | ||
492 | - string dval; | ||
493 | - t_const_value* cv = (*m_iter)->get_value(); | ||
494 | - if (cv != nullptr) { | ||
495 | - dval += render_const_value(out, (*m_iter)->get_name(), t, cv); | ||
496 | - } else if (t->is_enum()) { | ||
497 | - dval += "static_cast<" + type_name(t) + ">(0)"; | ||
498 | - } else { | ||
499 | - dval += (t->is_string() || is_reference(*m_iter)) ? "" : "0"; | ||
500 | - } | ||
501 | - if (!init_ctor) { | ||
502 | - out << "\n"; | ||
503 | - indent(out) << " : "; | ||
504 | - init_ctor = true; | ||
505 | + // Default-initialize all members that should be initialized in | ||
506 | + // the initializer block | ||
507 | + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
508 | + t_type* t = get_true_type((*m_iter)->get_type()); | ||
509 | + if (t->is_base_type() || t->is_enum() || is_reference(*m_iter)) { | ||
510 | + string dval; | ||
511 | + t_const_value* cv = (*m_iter)->get_value(); | ||
512 | + if (cv != nullptr) { | ||
513 | + dval += render_const_value(out, (*m_iter)->get_name(), t, cv); | ||
514 | + } else if (t->is_enum()) { | ||
515 | + dval += "static_cast<" + type_name(t) + ">(0)"; | ||
516 | + } else { | ||
517 | + dval += (t->is_string() || is_reference(*m_iter)) ? "" : "0"; | ||
518 | + } | ||
519 | + if (!init_ctor) { | ||
520 | + init_ctor = true; | ||
521 | + if(has_default_value) { | ||
522 | + out << " : "; | ||
523 | } else { | ||
524 | - out << ",\n"; | ||
525 | - indent(out) << args_indent; | ||
526 | + out << '\n' << args_indent << ": "; | ||
527 | + args_indent.append(" "); | ||
528 | } | ||
529 | - | ||
530 | - out << (*m_iter)->get_name() << "(" << dval << ")"; | ||
531 | + } else { | ||
532 | + out << ",\n" << args_indent; | ||
533 | } | ||
534 | + | ||
535 | + out << (*m_iter)->get_name() << "(" << dval << ")"; | ||
536 | } | ||
537 | - out << " {" << endl; | ||
538 | - indent_up(); | ||
539 | - // TODO(dreiss): When everything else in Thrift is perfect, | ||
540 | - // do more of these in the initializer list. | ||
541 | - for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
542 | - t_type* t = get_true_type((*m_iter)->get_type()); | ||
543 | - if (!t->is_base_type() && !t->is_enum() && !is_reference(*m_iter)) { | ||
544 | - t_const_value* cv = (*m_iter)->get_value(); | ||
545 | - if (cv != nullptr) { | ||
546 | - print_const_value(out, (*m_iter)->get_name(), t, cv); | ||
547 | - } | ||
548 | + } | ||
549 | + | ||
550 | + // | ||
551 | + // Start generating body | ||
552 | + // | ||
553 | + | ||
554 | + out << " {" << endl; | ||
555 | + indent_up(); | ||
556 | + // TODO(dreiss): When everything else in Thrift is perfect, | ||
557 | + // do more of these in the initializer list. | ||
558 | + for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) { | ||
559 | + t_type* t = get_true_type((*m_iter)->get_type()); | ||
560 | + if (!t->is_base_type() && !t->is_enum() && !is_reference(*m_iter)) { | ||
561 | + t_const_value* cv = (*m_iter)->get_value(); | ||
562 | + if (cv != nullptr) { | ||
563 | + print_const_value(out, (*m_iter)->get_name(), t, cv); | ||
564 | } | ||
565 | } | ||
566 | - scope_down(out); | ||
567 | - } else { | ||
568 | - out << " {}\n"; | ||
569 | } | ||
570 | + scope_down(out); | ||
571 | } | ||
572 | |||
573 | void t_cpp_generator::generate_copy_constructor(ostream& out, | ||
574 | |||
575 | From 9bd8f1e1acb23cb3ef134291e56b2605a7356b04 Mon Sep 17 00:00:00 2001 | ||
576 | From: Lukas Barth <mail@tinloaf.de> | ||
577 | Date: Tue, 4 Apr 2023 16:25:06 +0200 | ||
578 | Subject: [PATCH 5/5] Fix ODR violations in cases where templates are involved | ||
579 | |||
580 | --- | ||
581 | compiler/cpp/src/thrift/generate/t_cpp_generator.cc | 5 ++++- | ||
582 | 1 file changed, 4 insertions(+), 1 deletion(-) | ||
583 | |||
584 | diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
585 | index 2a65bfb96..a085ada0e 100644 | ||
586 | --- a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
587 | +++ b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc | ||
588 | @@ -1432,7 +1432,10 @@ void t_cpp_generator::generate_struct_definition(ostream& out, | ||
589 | |||
590 | if (!pointers) | ||
591 | { | ||
592 | - generate_default_constructor(out, tstruct, false); | ||
593 | + // 'force_cpp_out' always goes into the .cpp file, and never into a .tcc | ||
594 | + // file in case templates are involved. Since the constructor is not templated, | ||
595 | + // putting it into the (later included) .tcc file would cause ODR violations. | ||
596 | + generate_default_constructor(force_cpp_out, tstruct, false); | ||
597 | } | ||
598 | |||
599 | // Create a setter function for each field | ||
diff --git a/meta-oe/recipes-connectivity/thrift/thrift_0.20.0.bb b/meta-oe/recipes-connectivity/thrift/thrift_0.20.0.bb index 23db052b9e..c908eab7b3 100644 --- a/meta-oe/recipes-connectivity/thrift/thrift_0.20.0.bb +++ b/meta-oe/recipes-connectivity/thrift/thrift_0.20.0.bb | |||
@@ -9,7 +9,9 @@ LIC_FILES_CHKSUM = "file://LICENSE;md5=c40a383cb3f747e0c7abbf1482f194f0 \ | |||
9 | DEPENDS = "thrift-native boost flex-native bison-native openssl zlib" | 9 | DEPENDS = "thrift-native boost flex-native bison-native openssl zlib" |
10 | 10 | ||
11 | SRC_URI = "https://downloads.apache.org/${BPN}/${PV}/${BP}.tar.gz \ | 11 | SRC_URI = "https://downloads.apache.org/${BPN}/${PV}/${BP}.tar.gz \ |
12 | file://0001-DefineInstallationPaths.cmake-Define-libdir-in-terms.patch" | 12 | file://0001-DefineInstallationPaths.cmake-Define-libdir-in-terms.patch \ |
13 | file://0001-thrift-pr2755.patch \ | ||
14 | " | ||
13 | SRC_URI[sha256sum] = "b5d8311a779470e1502c027f428a1db542f5c051c8e1280ccd2163fa935ff2d6" | 15 | SRC_URI[sha256sum] = "b5d8311a779470e1502c027f428a1db542f5c051c8e1280ccd2163fa935ff2d6" |
14 | 16 | ||
15 | BBCLASSEXTEND = "native nativesdk" | 17 | BBCLASSEXTEND = "native nativesdk" |