diff --git a/regression-tests/pure2-bugfix-for-memberwise-base-assignment.cpp2 b/regression-tests/pure2-bugfix-for-memberwise-base-assignment.cpp2
new file mode 100644
index 000000000..c27d68b51
--- /dev/null
+++ b/regression-tests/pure2-bugfix-for-memberwise-base-assignment.cpp2
@@ -0,0 +1,18 @@
+Base: type = {
+ operator=: (out this) = { }
+ operator=: (out this, that) = std::cout << "(out this, that)\n";
+ operator=: (implicit out this, x) = std::cout << "(implicit out this, x)\n";
+}
+
+Derived: type = {
+ this: Base = ();
+ operator=: (out this) = { }
+ operator=: (out this, that) = { }
+ operator=: (inout this, move that) = { }
+}
+
+main: () = {
+ d := Derived();
+ d2 := d;
+ d2 = d;
+}
diff --git a/regression-tests/test-results/gcc-13/pure2-bugfix-for-memberwise-base-assignment.cpp.execution b/regression-tests/test-results/gcc-13/pure2-bugfix-for-memberwise-base-assignment.cpp.execution
new file mode 100644
index 000000000..566837e51
--- /dev/null
+++ b/regression-tests/test-results/gcc-13/pure2-bugfix-for-memberwise-base-assignment.cpp.execution
@@ -0,0 +1,2 @@
+(out this, that)
+(out this, that)
diff --git a/regression-tests/test-results/gcc-13/pure2-bugfix-for-memberwise-base-assignment.cpp.output b/regression-tests/test-results/gcc-13/pure2-bugfix-for-memberwise-base-assignment.cpp.output
new file mode 100644
index 000000000..e69de29bb
diff --git a/regression-tests/test-results/pure2-bugfix-for-memberwise-base-assignment.cpp b/regression-tests/test-results/pure2-bugfix-for-memberwise-base-assignment.cpp
new file mode 100644
index 000000000..187cfa4a0
--- /dev/null
+++ b/regression-tests/test-results/pure2-bugfix-for-memberwise-base-assignment.cpp
@@ -0,0 +1,93 @@
+
+#define CPP2_USE_MODULES Yes
+
+//=== Cpp2 type declarations ====================================================
+
+
+#include "cpp2util.h"
+
+#line 1 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+class Base;
+
+
+#line 7 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+class Derived;
+
+
+//=== Cpp2 type definitions and function declarations ===========================
+
+#line 1 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+class Base {
+ public: explicit Base();
+ public: Base(Base const& that);
+
+#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ public: auto operator=(Base const& that) -> Base& ;
+
+#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ public: Base(Base&& that) noexcept;
+
+#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ public: auto operator=(Base&& that) noexcept -> Base& ;
+ public: Base(auto const& x);
+#line 4 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ public: auto operator=(auto const& x) -> Base& ;
+};
+
+class Derived: public Base {
+
+ public: explicit Derived();
+ public: Derived(Derived const& that);
+ public: auto operator=(Derived&& that) noexcept -> Derived& ;
+};
+
+auto main() -> int;
+
+
+//=== Cpp2 function definitions =================================================
+
+
+#line 2 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ Base::Base(){}
+ Base::Base (Base const& that) { std::cout << "(out this, that)\n"; }
+#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ auto Base::operator=(Base const& that) -> Base& { std::cout << "(out this, that)\n";
+ return *this;
+#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ }
+#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ Base::Base (Base&& that) noexcept { std::cout << "(out this, that)\n"; }
+#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ auto Base::operator=(Base&& that) noexcept -> Base& { std::cout << "(out this, that)\n";
+ return *this;
+#line 3 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ }
+ Base::Base(auto const& x) { std::cout << "(implicit out this, x)\n"; }
+#line 4 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ auto Base::operator=(auto const& x) -> Base& { std::cout << "(implicit out this, x)\n";
+ return *this;
+#line 4 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ }
+
+#line 9 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ Derived::Derived()
+ : Base{ }
+#line 9 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ {}
+ Derived::Derived(Derived const& that)
+ : Base{ static_cast(that) }
+#line 10 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ {}
+ auto Derived::operator=(Derived&& that) noexcept -> Derived& {
+ Base::operator= ( static_cast(that) );
+ return *this;
+#line 11 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+ }
+
+#line 14 "pure2-bugfix-for-memberwise-base-assignment.cpp2"
+auto main() -> int{
+ auto d {Derived()};
+ auto d2 {d};
+ d2 = std::move(d);
+}
+
diff --git a/regression-tests/test-results/pure2-bugfix-for-memberwise-base-assignment.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-memberwise-base-assignment.cpp2.output
new file mode 100644
index 000000000..551cca17f
--- /dev/null
+++ b/regression-tests/test-results/pure2-bugfix-for-memberwise-base-assignment.cpp2.output
@@ -0,0 +1,2 @@
+pure2-bugfix-for-memberwise-base-assignment.cpp2... ok (all Cpp2, passes safety checks)
+
diff --git a/source/cppfront.cpp b/source/cppfront.cpp
index 1bad85a53..b9e754671 100644
--- a/source/cppfront.cpp
+++ b/source/cppfront.cpp
@@ -4584,23 +4584,34 @@ class cppfront
// Otherwise, use a default... for a non-copy/move that's the member initializer
// (for which we don't need to emit anything special because it will get used),
// and for a copy/move function we default to "= that.same_member" (or, if this
- // is a base type, just "= that")
+ // is a base type, to assigning from the lowered base subobject)
if (!found_explicit_init)
{
- if (emitting_move_that_function)
+ if (emitting_that_function && (*object)->has_name("this"))
{
- initializer = "std::move(that)";
- if (!(*object)->has_name("this")) {
- initializer += "." + object_name;
+ auto pass = std::string{" const&"};
+ if (emitting_move_that_function) {
+ pass = "&&";
}
+ initializer =
+ "static_cast<"
+ + object_name
+ + pass
+ + ">(that)";
+ found_default_init = true;
+ }
+ else if (emitting_move_that_function)
+ {
+ initializer =
+ "std::move(that)."
+ + object_name;
found_default_init = true;
}
else if (emitting_that_function)
{
- initializer = "that";
- if (!(*object)->has_name("this")) {
- initializer += "." + object_name;
- }
+ initializer =
+ "that."
+ + object_name;
found_default_init = true;
}
else if ((*object)->initializer)