Skip to content

Commit f761445

Browse files
committed
fix(cpp1): apply memberwise semantics to base assignment
1 parent 52a2798 commit f761445

6 files changed

+135
-9
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
Base: type = {
2+
operator=: (out this) = { }
3+
operator=: (out this, that) = std::cout << "(out this, that)\n";
4+
operator=: (implicit out this, x) = std::cout << "(implicit out this, x)\n";
5+
}
6+
7+
Derived: type = {
8+
this: Base = ();
9+
operator=: (out this) = { }
10+
operator=: (out this, that) = { }
11+
operator=: (inout this, move that) = { }
12+
}
13+
14+
main: () = {
15+
d := Derived();
16+
d2 := d;
17+
d2 = d;
18+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
(out this, that)
2+
(out this, that)

regression-tests/test-results/gcc-13/pure2-bugfix-for-memberwise-base-assignment.cpp.output

Whitespace-only changes.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
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-memberwise-base-assignment.cpp2"
10+
class Base;
11+
12+
13+
#line 7 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
14+
class Derived;
15+
16+
17+
//=== Cpp2 type definitions and function declarations ===========================
18+
19+
#line 1 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
20+
class Base {
21+
public: explicit Base();
22+
public: Base(Base const& that);
23+
24+
#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
25+
public: auto operator=(Base const& that) -> Base& ;
26+
27+
#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
28+
public: Base(Base&& that) noexcept;
29+
30+
#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
31+
public: auto operator=(Base&& that) noexcept -> Base& ;
32+
public: Base(auto const& x);
33+
#line 4 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
34+
public: auto operator=(auto const& x) -> Base& ;
35+
};
36+
37+
class Derived: public Base {
38+
39+
public: explicit Derived();
40+
public: Derived(Derived const& that);
41+
public: auto operator=(Derived&& that) noexcept -> Derived& ;
42+
};
43+
44+
auto main() -> int;
45+
46+
47+
//=== Cpp2 function definitions =================================================
48+
49+
50+
#line 2 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
51+
Base::Base(){}
52+
Base::Base (Base const& that) { std::cout << "(out this, that)\n"; }
53+
#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
54+
auto Base::operator=(Base const& that) -> Base& { std::cout << "(out this, that)\n";
55+
return *this;
56+
#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
57+
}
58+
#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
59+
Base::Base (Base&& that) noexcept { std::cout << "(out this, that)\n"; }
60+
#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
61+
auto Base::operator=(Base&& that) noexcept -> Base& { std::cout << "(out this, that)\n";
62+
return *this;
63+
#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
64+
}
65+
Base::Base(auto const& x) { std::cout << "(implicit out this, x)\n"; }
66+
#line 4 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
67+
auto Base::operator=(auto const& x) -> Base& { std::cout << "(implicit out this, x)\n";
68+
return *this;
69+
#line 4 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
70+
}
71+
72+
#line 9 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
73+
Derived::Derived()
74+
: Base{ }
75+
#line 9 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
76+
{}
77+
Derived::Derived(Derived const& that)
78+
: Base{ static_cast<Base const&>(that) }
79+
#line 10 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
80+
{}
81+
auto Derived::operator=(Derived&& that) noexcept -> Derived& {
82+
Base::operator= ( static_cast<Base&&>(that) );
83+
return *this;
84+
#line 11 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
85+
}
86+
87+
#line 14 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
88+
auto main() -> int{
89+
auto d {Derived()};
90+
auto d2 {d};
91+
d2 = std::move(d);
92+
}
93+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-bugfix-for-memberwise-base-assignment.cpp2... ok (all Cpp2, passes safety checks)
2+

source/cppfront.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4584,23 +4584,34 @@ class cppfront
45844584
// Otherwise, use a default... for a non-copy/move that's the member initializer
45854585
// (for which we don't need to emit anything special because it will get used),
45864586
// and for a copy/move function we default to "= that.same_member" (or, if this
4587-
// is a base type, just "= that")
4587+
// is a base type, to assigning from the lowered base subobject)
45884588
if (!found_explicit_init)
45894589
{
4590-
if (emitting_move_that_function)
4590+
if (emitting_that_function && (*object)->has_name("this"))
45914591
{
4592-
initializer = "std::move(that)";
4593-
if (!(*object)->has_name("this")) {
4594-
initializer += "." + object_name;
4592+
auto pass = std::string{" const&"};
4593+
if (emitting_move_that_function) {
4594+
pass = "&&";
45954595
}
4596+
initializer =
4597+
"static_cast<"
4598+
+ object_name
4599+
+ pass
4600+
+ ">(that)";
4601+
found_default_init = true;
4602+
}
4603+
else if (emitting_move_that_function)
4604+
{
4605+
initializer =
4606+
"std::move(that)."
4607+
+ object_name;
45964608
found_default_init = true;
45974609
}
45984610
else if (emitting_that_function)
45994611
{
4600-
initializer = "that";
4601-
if (!(*object)->has_name("this")) {
4602-
initializer += "." + object_name;
4603-
}
4612+
initializer =
4613+
"that."
4614+
+ object_name;
46044615
found_default_init = true;
46054616
}
46064617
else if ((*object)->initializer)

0 commit comments

Comments
 (0)