Skip to content

Commit a981011

Browse files
committed
Add support for default member initializers in constructors
If the constructor doesn't explicitly initialize a data member, use the member initializer Also, fix a bug where initially I was emitting just a single-token initializer... initialization with general expressions should all work now
1 parent ec8021d commit a981011

File tree

7 files changed

+71
-28
lines changed

7 files changed

+71
-28
lines changed

regression-tests/pure2-types-basics.cpp2

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,27 @@ myclass : type = {
55

66
operator=: (implicit out this, x: int) = {
77
data = x;
8-
more = "xyzzy";
8+
// use default initializer for this.more
99
std::cout << "myclass: implicit constructor from int\n";
10+
print();
1011
}
1112

1213
operator=: (out this, s: std::string) = {
1314
this.data = 99;
1415
this.more = "plugh";
1516
std::cout << "myclass: explicit constructor from string\n";
17+
print();
1618
}
1719

1820
operator=: (out this) = {
19-
data = -3;
20-
more = "-3";
21+
// use default initializer for this.data
22+
more = std::to_string(3.14159);
2123
std::cout << "myclass: default constructor\n";
24+
print();
25+
}
26+
27+
print: (this) = {
28+
std::cout << " data: (data)$, more: (more)$\n";
2229
}
2330

2431
operator=: (move this) = {
@@ -29,8 +36,8 @@ myclass : type = {
2936
std::cout << "N::myclass::f with (x)$\n";
3037
}
3138

32-
data: int;
33-
more: std::string;
39+
data: int = 42 * 12;
40+
more: std::string = std::to_string(42 * 12);
3441

3542
nested : type = {
3643
g: () = std::cout << "N::myclass::nested::g\n";
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
myclass: implicit constructor from int
2+
data: 1, more: 504
23
N::myclass::f with 53
34
N::myclass::nested::g
45
f1: 2
56
f2: 4
67
f3: 6
78
f4: 8
89
myclass: explicit constructor from string
10+
data: 99, more: plugh
911
myclass: default constructor
12+
data: 504, more: 3.141590
1013
myclass: destructor
1114
myclass: destructor
1215
myclass: destructor
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
myclass: implicit constructor from int
2+
data: 1, more: 504
23
N::myclass::f with 53
34
N::myclass::nested::g
45
f1: 2
56
f2: 4
67
f3: 6
78
f4: 8
89
myclass: explicit constructor from string
10+
data: 99, more: plugh
911
myclass: default constructor
12+
data: 504, more: 3.141590
1013
myclass: destructor
1114
myclass: destructor
1215
myclass: destructor
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
myclass: implicit constructor from int
2+
data: 1, more: 504
23
N::myclass::f with 53
34
N::myclass::nested::g
45
f1: 2
56
f2: 4
67
f3: 6
78
f4: 8
89
myclass: explicit constructor from string
10+
data: 99, more: plugh
911
myclass: default constructor
12+
data: 504, more: 3.141590
1013
myclass: destructor
1114
myclass: destructor
1215
myclass: destructor

regression-tests/test-results/pure2-types-basics.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
namespace N {
99
class myclass;
1010
};
11-
#line 48 "pure2-types-basics.cpp2"
11+
#line 55 "pure2-types-basics.cpp2"
1212
auto main() -> int;
1313

1414
//=== Cpp2 definitions ==========================================================
@@ -21,29 +21,36 @@ class myclass {
2121

2222
public: myclass(cpp2::in<int> x)
2323
: data{ x }
24-
, more{ "xyzzy" }
24+
, more{ std::to_string(42 * 12) }
2525
#line 7 "pure2-types-basics.cpp2"
2626
{
27-
27+
// use default initializer for this.more
2828
std::cout << "myclass: implicit constructor from int\n";
29+
print();
2930
}
3031

3132
public: explicit myclass(cpp2::in<std::string> s)
3233
: data{ 99 }
3334
, more{ "plugh" }
34-
#line 13 "pure2-types-basics.cpp2"
35+
#line 14 "pure2-types-basics.cpp2"
3536
{
3637

3738
std::cout << "myclass: explicit constructor from string\n";
39+
print();
3840
}
3941

4042
public: myclass()
41-
: data{ 3 }
42-
, more{ "-3" }
43-
#line 19 "pure2-types-basics.cpp2"
44-
{
43+
: data{ 42 * 12 }
44+
, more{ std::to_string(3.14159) }
45+
#line 21 "pure2-types-basics.cpp2"
46+
{ // use default initializer for this.data
4547

4648
std::cout << "myclass: default constructor\n";
49+
print();
50+
}
51+
52+
public: auto print() const -> void{
53+
std::cout << " data: " + cpp2::to_string(data) + ", more: " + cpp2::to_string(more) + "\n";
4754
}
4855

4956
public: ~myclass(){
@@ -54,8 +61,8 @@ class myclass {
5461
std::cout << "N::myclass::f with " + cpp2::to_string(x) + "\n";
5562
}
5663

57-
private: int data;
58-
private: std::string more;
64+
private: int data {42 * 12};
65+
private: std::string more {std::to_string(42 * 12)};
5966

6067
public: class nested {
6168
public: static auto g() -> void { std::cout << "N::myclass::nested::g\n"; }

source/cppfront.cpp

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3715,7 +3715,10 @@ class cppfront
37153715
auto exprs = (*statement)->get_lhs_rhs_if_simple_assignment();
37163716

37173717
assert(!exprs.lhs || exprs.lhs->expr);
3718-
auto is_match = false;
3718+
auto is_match = false;
3719+
auto stmt_pos = (*statement)->position();
3720+
auto initializer = std::string{};
3721+
37193722
if (exprs.lhs)
37203723
{
37213724
// First, see if it's an assignment 'name = something'
@@ -3734,30 +3737,47 @@ class cppfront
37343737
is_match = true;
37353738
}
37363739
}
3737-
}
3740+
3741+
if (is_match)
3742+
{
3743+
assert(exprs.rhs);
3744+
initializer = print_to_string( *exprs.rhs );
3745+
3746+
// We've used this statement, so note that
3747+
// and move 'statement' forward
3748+
(*statement)->emitted = true;
3749+
++statement;
3750+
}
3751+
}
3752+
3753+
// Otherwise, if the member has an initializer, we can use that
3754+
if (!is_match &&
3755+
(*object)->initializer
3756+
)
3757+
{
3758+
is_match = true;
3759+
initializer = print_to_string( *(*object)->initializer, false );
3760+
}
37383761

37393762
// If this is not an assignment to *object, complain
37403763
if (!is_match)
37413764
{
37423765
errors.emplace_back(
3743-
(*statement)->position(),
3766+
stmt_pos,
37443767
"expected '" + (*object)->name()->to_string(true) + " = ...' initialization statement - " + error_msg
37453768
);
37463769
return;
37473770
}
37483771

3749-
assert(exprs.rhs && exprs.rhs->expr);
37503772
current_function_info.back().prolog.mem_inits.push_back(
37513773
separator +
37523774
(*object)->name()->to_string(true) +
37533775
"{ " +
3754-
exprs.rhs->expr->get_token()->to_string(true) +
3776+
initializer +
37553777
" }"
37563778
);
3757-
(*statement)->emitted = true;
37583779

37593780
++object;
3760-
++statement;
37613781
separator = ", ";
37623782
}
37633783

source/parse.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ struct literal_node {
179179
struct postfix_expression_node;
180180

181181
struct postfix_expression_node_pair {
182-
postfix_expression_node const* lhs;
183-
postfix_expression_node const* rhs;
182+
postfix_expression_node * lhs;
183+
postfix_expression_node * rhs;
184184
};
185185

186186

@@ -190,7 +190,7 @@ struct prefix_expression_node
190190
std::unique_ptr<postfix_expression_node> expr;
191191

192192
auto get_postfix_expression_node() const
193-
-> postfix_expression_node const*
193+
-> postfix_expression_node *
194194
{
195195
assert(expr);
196196
return expr.get();
@@ -218,15 +218,15 @@ struct binary_expression_node
218218

219219
// Get left-hand postfix-expression
220220
auto get_postfix_expression_node() const
221-
-> postfix_expression_node const*
221+
-> postfix_expression_node *
222222
{
223223
assert(expr);
224224
return expr->get_postfix_expression_node();
225225
}
226226

227227
// Get first right-hand postfix-expression, if there is one
228228
auto get_second_postfix_expression_node() const
229-
-> postfix_expression_node const*
229+
-> postfix_expression_node *
230230
{
231231
if (!terms.empty()) {
232232
assert(terms.front().expr);
@@ -756,7 +756,7 @@ struct is_as_expression_node
756756
std::vector<term> ops;
757757

758758
auto get_postfix_expression_node() const
759-
-> postfix_expression_node const*
759+
-> postfix_expression_node *
760760
{
761761
assert(expr);
762762
return expr->get_postfix_expression_node();

0 commit comments

Comments
 (0)