Skip to content

Commit 38f7df4

Browse files
committed
C++ front-end: fix global constructor and member initialization
1. Store default values: Modified compound type declarator handling to preserve C++11 default member initializers in the AST using `ID_C_default_value`. 2. Generate constructors when needed: Modified compound body type checking to generate default constructors for classes with default member initializers, ensuring static initialization occurs. 3. Apply default values: Modified constructor member initialization to check for stored default values and create appropriate member initializers. Fixes: #537
1 parent 1505c36 commit 38f7df4

File tree

4 files changed

+78
-1
lines changed

4 files changed

+78
-1
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#include <assert.h>
2+
3+
class C
4+
{
5+
public:
6+
int x;
7+
8+
C() : x(7)
9+
{
10+
}
11+
};
12+
13+
C c1;
14+
15+
class D
16+
{
17+
public:
18+
int x = 7;
19+
};
20+
21+
int main()
22+
{
23+
assert(c1.x == 7); // Fails
24+
25+
C c2;
26+
assert(c2.x == 7); // Succeeds
27+
28+
D d;
29+
assert(d.x == 7); // C++11 Class Member Initialization Fails
30+
31+
return 0;
32+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.cpp
3+
--cpp11
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring

src/cpp/cpp_typecheck_compound_type.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -754,6 +754,13 @@ void cpp_typecheckt::typecheck_compound_declarator(
754754
}
755755
}
756756

757+
// Handle C++11 default member initializers for non-static members
758+
if(!is_static && !is_method && value.is_not_nil())
759+
{
760+
// Store the default initializer value in the component
761+
component.add(ID_C_default_value) = value;
762+
}
763+
757764
// array members must have fixed size
758765
check_fixed_size_array(component.type());
759766

@@ -1097,7 +1104,25 @@ void cpp_typecheckt::typecheck_compound_body(symbolt &symbol)
10971104
if(symbol.type.id()==ID_struct)
10981105
do_virtual_table(symbol);
10991106

1100-
if(!found_ctor && !cpp_is_pod(symbol.type))
1107+
// Check if any component has a C++11 default member initializer
1108+
bool has_default_member_initializer = false;
1109+
for(const auto &component : type.components())
1110+
{
1111+
if(
1112+
!component.get_bool(ID_from_base) && component.type().id() != ID_code &&
1113+
!component.get_bool(ID_is_type) && !component.get_bool(ID_is_static) &&
1114+
component.find(ID_C_default_value).is_not_nil())
1115+
{
1116+
has_default_member_initializer = true;
1117+
break;
1118+
}
1119+
}
1120+
1121+
// Generate a default constructor if:
1122+
// - No constructor was found, AND
1123+
// - Either the type is not POD OR it has C++11 default member initializers
1124+
if(
1125+
!found_ctor && (!cpp_is_pod(symbol.type) || has_default_member_initializer))
11011126
{
11021127
// it's public!
11031128
exprt cpp_public("cpp-public");

src/cpp/cpp_typecheck_constructor.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,18 @@ void cpp_typecheckt::full_member_initialization(
752752
mem_init.set(ID_member, cppname);
753753
final_initializers.move_to_sub(mem_init);
754754
}
755+
// Handle C++11 default member initializers for POD types
756+
else if(
757+
!found && cpp_is_pod(c.type()) && c.find(ID_C_default_value).is_not_nil())
758+
{
759+
cpp_namet cppname(mem_name);
760+
761+
codet mem_init(ID_member_initializer);
762+
mem_init.set(ID_member, cppname);
763+
mem_init.copy_to_operands(
764+
static_cast<const exprt &>(c.find(ID_C_default_value)));
765+
final_initializers.move_to_sub(mem_init);
766+
}
755767
}
756768

757769
initializers.swap(final_initializers);

0 commit comments

Comments
 (0)