Skip to content

Commit 707d3b0

Browse files
committed
fix(cpp1): account for initializers of this members
1 parent 9584fcc commit 707d3b0

File tree

7 files changed

+213
-35
lines changed

7 files changed

+213
-35
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
base: type = {
2+
public x: i32 = -1;
3+
operator=: (out this) = { }
4+
operator=: (out this, y: i32) = x = y;
5+
}
6+
derived: type = {
7+
y: i32 = 2;
8+
this: base = 42;
9+
}
10+
main: () = {
11+
[[assert: derived().y == 2]]
12+
[[assert: derived().x == 42]]
13+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
2+
#define CPP2_USE_MODULES Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
#line 1 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
10+
class base;
11+
12+
#line 6 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
13+
class derived;
14+
15+
16+
//=== Cpp2 type definitions and function declarations ===========================
17+
18+
#line 1 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
19+
class base {
20+
public: cpp2::i32 x {-1};
21+
public: explicit base();
22+
public: explicit base(cpp2::in<cpp2::i32> y);
23+
#line 4 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
24+
public: auto operator=(cpp2::in<cpp2::i32> y) -> base& ;
25+
26+
public: base(base const&) = delete; /* No 'that' constructor, suppress copy */
27+
public: auto operator=(base const&) -> void = delete;
28+
#line 5 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
29+
};
30+
31+
struct derived_y_as_base { cpp2::i32 y; };
32+
#line 6 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
33+
class derived: public derived_y_as_base, public base {
34+
public: explicit derived();
35+
36+
public: derived(derived const&) = delete; /* No 'that' constructor, suppress copy */
37+
public: auto operator=(derived const&) -> void = delete;
38+
39+
40+
#line 9 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
41+
};
42+
auto main() -> int;
43+
44+
45+
//=== Cpp2 function definitions =================================================
46+
47+
48+
#line 3 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
49+
base::base(){}
50+
base::base(cpp2::in<cpp2::i32> y)
51+
: x{ y }
52+
#line 4 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
53+
{ }
54+
#line 4 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
55+
auto base::operator=(cpp2::in<cpp2::i32> y) -> base& {
56+
x = y;
57+
return *this;
58+
#line 4 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
59+
}
60+
61+
derived::derived()
62+
: derived_y_as_base{ 2 }
63+
, base{ 42 }{}
64+
65+
#line 10 "pure2-bugfix-for-default-constructor-this-initializer.cpp2"
66+
auto main() -> int{
67+
cpp2::Default.expects(derived().y==2, "");
68+
cpp2::Default.expects(derived().x==42, "");
69+
}
70+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-bugfix-for-default-constructor-this-initializer.cpp2... ok (all Cpp2, passes safety checks)
2+

source/cppfront.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4927,11 +4927,8 @@ class cppfront
49274927
{
49284928
auto& decl = std::get<statement_node::declaration>(stmt->statement);
49294929
assert(decl);
4930-
assert(decl->name());
4931-
auto emit_as_base =
4932-
decl->get_decl_if_type_scope_object_name_before_a_base_type(*decl->name());
49334930

4934-
if (emit_as_base) {
4931+
if (decl->emit_data_member_as_base()) {
49354932
printer.print_extra(
49364933
"\nstruct "
49374934
+ print_to_string(*decl->parent_declaration->name())
@@ -5086,12 +5083,7 @@ class cppfront
50865083

50875084
// First we'll encounter the base types == subobjects named "this"
50885085
// and any data members declared before them that we push into private bases
5089-
assert(decl->name());
5090-
auto emit_as_base =
5091-
decl->get_decl_if_type_scope_object_name_before_a_base_type(*decl->name())
5092-
|| decl->has_name("this")
5093-
;
5094-
if (emit_as_base)
5086+
if (decl->emit_as_base())
50955087
{
50965088
// Do the sema check for these declarations here, because we're
50975089
// handling them here instead of going through emit() for them

source/parse.h

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <memory>
2323
#include <variant>
2424
#include <iostream>
25+
#include <functional>
2526

2627

2728
namespace cpp2 {
@@ -2283,6 +2284,56 @@ struct declaration_node
22832284
}
22842285

22852286

2287+
auto emit_data_member_as_base() const
2288+
-> bool
2289+
{
2290+
assert(name());
2291+
return get_decl_if_type_scope_object_name_before_a_base_type(*name());
2292+
}
2293+
2294+
2295+
auto emit_as_base() const
2296+
-> bool
2297+
{
2298+
return emit_data_member_as_base() || has_name("this");
2299+
}
2300+
2301+
2302+
auto should_add_default_constructor() const
2303+
-> bool
2304+
{
2305+
if (
2306+
!is_type()
2307+
|| !initializer
2308+
|| !initializer->is_compound()
2309+
)
2310+
{
2311+
return false;
2312+
}
2313+
2314+
auto const any_statement = [&](auto pred) {
2315+
auto& statements = std::get<statement_node::compound>(initializer->statement)->statements;
2316+
return std::any_of
2317+
(
2318+
statements.begin(),
2319+
statements.end(),
2320+
[pred]( auto& stmt )
2321+
{
2322+
const auto decl = std::get_if<statement_node::declaration>(&stmt->statement);
2323+
return decl && std::invoke(pred, decl->get());
2324+
}
2325+
);
2326+
};
2327+
2328+
if ( any_statement( &declaration_node::is_constructor ) )
2329+
{
2330+
return false;
2331+
}
2332+
2333+
return any_statement( &declaration_node::emit_as_base );
2334+
}
2335+
2336+
22862337
auto get_decl_if_type_scope_object_name_before_a_base_type( std::string_view s ) const
22872338
-> declaration_node const*
22882339
{

0 commit comments

Comments
 (0)