summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Marko <peter.marko@siemens.com>2025-01-08 08:45:12 +0100
committerArmin Kuster <akuster808@gmail.com>2025-01-20 19:31:55 -0500
commitd793d2d876f6219eb33aeb0179b3e83aa899716c (patch)
tree843f6d5b846a7765d2eb5f80ed43b7efaba26d41
parent20239ef5ce5bb1097fd2f13ff917d6e6613f8860 (diff)
downloadmeta-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.patch599
-rw-r--r--meta-oe/recipes-connectivity/thrift/thrift_0.20.0.bb4
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 @@
1From f02ac2fb573bed72e9a2d1875807c6ff7ac19ec8 Mon Sep 17 00:00:00 2001
2From: Lukas Barth <mail@tinloaf.de>
3Date: Wed, 8 Feb 2023 09:33:03 +0100
4Subject: [PATCH 1/5] Move default constructor and operator== implementation to
5 CPP file
6
7Both the default constructor and operator== implementations reference
8certain member functions of the class' members. As an example, the default
9constructor references (i.e., "uses") the default constructors of its
10members.
11
12If a class contains a std::vector<Foo>, and Foo has only been *forward*-
13declared (which happens often in Thrift-generated code), this creates
14undefined behavior: The std::vector specification states that as long as
15Foo is an incomplete type, it is fine to reference std::vector<Foo>, but
16not any members (such as its default constructor).
17
18Thus, we must defer our default constructor's implementation (which references
19the default constructor of std::vector<Foo>) to a point where Foo is a
20complete type. That is the case in the .cpp file.
21
22The same holds for operator==.
23
24Upstream-Status: Backport [https://github.com/apache/thrift/pull/2755]
25
26Signed-off-by: Stanislav Angelovic <stanislav.angelovic.ext@siemens.com>
27Signed-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
32diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
33index 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
265From cedcd0e6424a08dd6feeb2533810054c9aca2a9e Mon Sep 17 00:00:00 2001
266From: Lukas Barth <mail@tinloaf.de>
267Date: Wed, 8 Feb 2023 10:11:48 +0100
268Subject: [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
274diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
275index 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
355From 16105fa1a1bb9ae633b805fcb7af3c7757beb6e0 Mon Sep 17 00:00:00 2001
356From: Lukas Barth <mail@tinloaf.de>
357Date: Fri, 24 Feb 2023 13:46:58 +0100
358Subject: [PATCH 3/5] Move generate_default_constructor call into
359 generate_struct_definition
360
361This makes sure that helper structs like _args and _result also have
362their default constructors defined.
363---
364 .../src/thrift/generate/t_cpp_generator.cc | 19 +++++++++++++------
365 1 file changed, 13 insertions(+), 6 deletions(-)
366
367diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
368index 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
442From 4f56007baf46d4aa87eb7f8e5e34b773235c729a Mon Sep 17 00:00:00 2001
443From: Lukas Barth <mail@tinloaf.de>
444Date: Mon, 6 Mar 2023 11:37:09 +0100
445Subject: [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
451diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
452index 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
575From 9bd8f1e1acb23cb3ef134291e56b2605a7356b04 Mon Sep 17 00:00:00 2001
576From: Lukas Barth <mail@tinloaf.de>
577Date: Tue, 4 Apr 2023 16:25:06 +0200
578Subject: [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
584diff --git a/compiler/cpp/src/thrift/generate/t_cpp_generator.cc b/compiler/cpp/src/thrift/generate/t_cpp_generator.cc
585index 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 \
9DEPENDS = "thrift-native boost flex-native bison-native openssl zlib" 9DEPENDS = "thrift-native boost flex-native bison-native openssl zlib"
10 10
11SRC_URI = "https://downloads.apache.org/${BPN}/${PV}/${BP}.tar.gz \ 11SRC_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"
13SRC_URI[sha256sum] = "b5d8311a779470e1502c027f428a1db542f5c051c8e1280ccd2163fa935ff2d6" 15SRC_URI[sha256sum] = "b5d8311a779470e1502c027f428a1db542f5c051c8e1280ccd2163fa935ff2d6"
14 16
15BBCLASSEXTEND = "native nativesdk" 17BBCLASSEXTEND = "native nativesdk"