Skip to content

Commit f3f3339

Browse files
committed
fix(cpp1): apply memberwise semantics to base assignment
1 parent 454bd3c commit f3f3339

7 files changed

+140
-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, that) = { }
12+
}
13+
14+
main: () = {
15+
d := Derived();
16+
d2 := d;
17+
d2 = d;
18+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
c++ (GCC) 13.1.1 20230429
2+
Copyright (C) 2023 Free Software Foundation, Inc.
3+
This is free software; see the source for copying conditions. There is NO
4+
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5+
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 const& that) -> 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 const& that) -> Derived& {
82+
Base::operator= ( static_cast<Base const&>(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
@@ -4551,23 +4551,34 @@ class cppfront
45514551
// Otherwise, use a default... for a non-copy/move that's the member initializer
45524552
// (for which we don't need to emit anything special because it will get used),
45534553
// and for a copy/move function we default to "= that.same_member" (or, if this
4554-
// is a base type, just "= that")
4554+
// is a base type, "= std::forward_like<decltype(this)>(that)")
45554555
if (!found_explicit_init)
45564556
{
4557-
if (emitting_move_that_function)
4557+
if (emitting_that_function && (*object)->has_name("this"))
45584558
{
4559-
initializer = "std::move(that)";
4560-
if (!(*object)->has_name("this")) {
4561-
initializer += "." + object_name;
4559+
auto pass = std::string{" const&"};
4560+
if (emitting_move_that_function) {
4561+
pass = "&&";
45624562
}
4563+
initializer =
4564+
"static_cast<"
4565+
+ object_name
4566+
+ pass
4567+
+ ">(that)";
4568+
found_default_init = true;
4569+
}
4570+
else if (emitting_move_that_function)
4571+
{
4572+
initializer =
4573+
"std::move(that)."
4574+
+ object_name;
45634575
found_default_init = true;
45644576
}
45654577
else if (emitting_that_function)
45664578
{
4567-
initializer = "that";
4568-
if (!(*object)->has_name("this")) {
4569-
initializer += "." + object_name;
4570-
}
4579+
initializer =
4580+
"that."
4581+
+ object_name;
45714582
found_default_init = true;
45724583
}
45734584
else if ((*object)->initializer)

0 commit comments

Comments
 (0)