diff --git a/regression-tests/pure2-types-smf-and-that-1-provide-everything.cpp2 b/regression-tests/pure2-types-smf-and-that-1-provide-everything.cpp2 index 7972b1fe3..537cae2a4 100644 --- a/regression-tests/pure2-types-smf-and-that-1-provide-everything.cpp2 +++ b/regression-tests/pure2-types-smf-and-that-1-provide-everything.cpp2 @@ -2,20 +2,24 @@ myclass : type = { operator=: (out this, that) = { + this = that; std::cout << "ctor - copy (GENERAL)"; } operator=: (out this, move that) = { + this = that; name = that.name + "(CM)"; std::cout << "ctor - move "; } operator=: (inout this, that) = { + this = that; addr = that.addr + "(AC)"; std::cout << "assign - copy "; } operator=: (inout this, move that) = { + this = that; std::cout << "assign - move "; } diff --git a/regression-tests/pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2 b/regression-tests/pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2 index 8432d7560..cbb70fc70 100644 --- a/regression-tests/pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2 +++ b/regression-tests/pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2 @@ -2,20 +2,24 @@ myclass : type = { operator=: (out this, that) = { + this = that; std::cout << "ctor - copy (GENERAL)"; } operator=: (out this, move that) = { + this = that; name = that.name + "(CM)"; std::cout << "ctor - move "; } operator=: (inout this, that) = { + this = that; addr = that.addr + "(AC)"; std::cout << "assign - copy "; } // operator=: (inout this, move that) = { + // this = that; // std::cout << "assign - move "; // } diff --git a/regression-tests/pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2 b/regression-tests/pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2 index 192f92185..817c05c32 100644 --- a/regression-tests/pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2 +++ b/regression-tests/pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2 @@ -2,20 +2,24 @@ myclass : type = { operator=: (out this, that) = { + this = that; std::cout << "ctor - copy (GENERAL)"; } operator=: (out this, move that) = { + this = that; name = that.name + "(CM)"; std::cout << "ctor - move "; } // operator=: (inout this, that) = { + // this = that; // addr = that.addr + "(AC)"; // std::cout << "assign - copy "; // } operator=: (inout this, move that) = { + this = that; std::cout << "assign - move "; } diff --git a/regression-tests/pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2 b/regression-tests/pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2 index 87d2c048b..6572963a6 100644 --- a/regression-tests/pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2 +++ b/regression-tests/pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2 @@ -2,20 +2,24 @@ myclass : type = { operator=: (out this, that) = { + this = that; std::cout << "ctor - copy (GENERAL)"; } // operator=: (out this, move that) = { + // this = that; // name = that.name + "(CM)"; // std::cout << "ctor - move "; // } operator=: (inout this, that) = { + this = that; addr = that.addr + "(AC)"; std::cout << "assign - copy "; } operator=: (inout this, move that) = { + this = that; std::cout << "assign - move "; } diff --git a/regression-tests/pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2 b/regression-tests/pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2 index 4d4bd6585..2033af113 100644 --- a/regression-tests/pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2 +++ b/regression-tests/pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2 @@ -2,20 +2,24 @@ myclass : type = { operator=: (out this, that) = { + this = that; std::cout << "ctor - copy (GENERAL)"; } // operator=: (out this, move that) = { + // this = that; // name = that.name + "(CM)"; // std::cout << "ctor - move "; // } // operator=: (inout this, that) = { + // this = that; // addr = that.addr + "(AC)"; // std::cout << "assign - copy "; // } // operator=: (inout this, move that) = { + // this = that; // std::cout << "assign - move "; // } diff --git a/regression-tests/pure2-types-smf-statements-between-member-inits.cpp2 b/regression-tests/pure2-types-smf-statements-between-member-inits.cpp2 new file mode 100644 index 000000000..cd0f4d379 --- /dev/null +++ b/regression-tests/pure2-types-smf-statements-between-member-inits.cpp2 @@ -0,0 +1,158 @@ +f: (a1: i32) = { + _ = a1; +} + +t1: type = { + m1: i32 = 123; + m2: i32 = 456; + + operator=: (out this, that) = { + // m1 = 123 implied + // m2 = 456 implied + f(1); + f(2); + } +} + +t2: type = { + m1: i32 = 123; + m2: i32 = 456; + + operator=: (out this, that) = { + f(1); + f(2); + m1 = 3; + // m2 = 456 implied + f(4); + f(5); + } +} + +t3: type = { + m1: i32 = 123; + m2: i32 = 456; + + operator=: (out this, that) = { + // m1 = 123 implied + f(1); + f(2); + m2 = 3; + f(4); + f(5); + } +} + +t4: type = { + m1: i32 = 123; + m2: i32 = 456; + + operator=: (out this, that) = { + f(1); + f(2); + m1 = 3; + f(4); + f(5); + m2 = 6; + f(7); + f(8); + } +} + +t5: type = { + m1: i32 = 123; + m2: i32 = 456; + + operator=: (out this, that) = { + f(1); + f(2); + this = that; + // m1 = that.m1 implied + // m2 = that.m2 implied + // This comment should show up before f(3) + f(3); + f(4); + } +} + +t6: type = { + m1: i32 = 123; + m2: i32 = 456; + + operator=: (out this, that) = { + f(1); + f(2); + this = that; + f(3); + f(4); + m1 = 5; + // m2 = that.m2 implied + // This comment should show up before f(6) + f(6); + f(7); + } +} + +t7: type = { + m1: i32 = 123; + m2: i32 = 456; + + operator=: (out this, that) = { + f(1); + f(2); + this = that; + // m1 = that.m1 implied + f(3); + f(4); + m2 = 5; + // This comment should show up before f(6) + f(6); + f(7); + } +} + +t8: type = { + m1: i32 = 123; + m2: i32 = 456; + + operator=: (out this, that) = { + f(1); + f(2); + this = that; + f(3); + f(4); + m1 = 5; + f(6); + f(7); + m2 = 8; + // This comment should show up before f(9) + f(9); + f(10); + } +} + +t9: type = { + m1: i32 = 123; + m2: i32 = 456; + + operator=: (implicit out this, a1: i32) = { + _ = a1; + f(1); + f(2); + m1 = 3; + f(4); + f(5); + m2 = 6; + // This comment should show up before f(7) + f(7); + f(8); + } + + operator=: (inout this, that) = { + // This function shouldn't contain any member assignments. + // While it's a special member function that uses 'that', + // it's explicitly an assignment operator because of 'inout this', + // so we let the programmer avoid member assignment if they choose. + f(1); + f(2); + } +} diff --git a/regression-tests/test-results/pure2-types-order-independence-and-nesting.cpp b/regression-tests/test-results/pure2-types-order-independence-and-nesting.cpp index 2020cd3b2..919820ea1 100644 --- a/regression-tests/test-results/pure2-types-order-independence-and-nesting.cpp +++ b/regression-tests/test-results/pure2-types-order-independence-and-nesting.cpp @@ -114,7 +114,10 @@ namespace N { #line 10 "pure2-types-order-independence-and-nesting.cpp2" X::X(cpp2::out y) - : py{(y.construct(&(*this)), &y.value() )} + : py{ [&]() -> decltype(auto) { + y.construct(&(*this)); + return &y.value(); + }() } #line 10 "pure2-types-order-independence-and-nesting.cpp2" { // === The following comments will stay close to, but not exactly at, diff --git a/regression-tests/test-results/pure2-types-smf-and-that-1-provide-everything.cpp b/regression-tests/test-results/pure2-types-smf-and-that-1-provide-everything.cpp index 5e659de8e..2e4f48fb6 100644 --- a/regression-tests/test-results/pure2-types-smf-and-that-1-provide-everything.cpp +++ b/regression-tests/test-results/pure2-types-smf-and-that-1-provide-everything.cpp @@ -20,26 +20,26 @@ class myclass { public: myclass(myclass const& that); -#line 8 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 9 "pure2-types-smf-and-that-1-provide-everything.cpp2" public: myclass(myclass&& that) noexcept; -#line 13 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 15 "pure2-types-smf-and-that-1-provide-everything.cpp2" public: auto operator=(myclass const& that) -> myclass& ; -#line 18 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 21 "pure2-types-smf-and-that-1-provide-everything.cpp2" public: auto operator=(myclass&& that) noexcept -> myclass& ; -#line 22 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 26 "pure2-types-smf-and-that-1-provide-everything.cpp2" public: explicit myclass(cpp2::in x); -#line 22 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 26 "pure2-types-smf-and-that-1-provide-everything.cpp2" public: auto operator=(cpp2::in x) -> myclass& ; -#line 27 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 31 "pure2-types-smf-and-that-1-provide-everything.cpp2" private: std::string name {"Henry"}; private: std::string addr {"123 Ford Dr."}; @@ -49,7 +49,7 @@ class myclass { cpp2::in suffix ) const -> void; -#line 37 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 41 "pure2-types-smf-and-that-1-provide-everything.cpp2" }; auto main() -> int; @@ -64,15 +64,17 @@ auto main() -> int; , addr{ that.addr } #line 4 "pure2-types-smf-and-that-1-provide-everything.cpp2" { + std::cout << "ctor - copy (GENERAL)"; } myclass::myclass(myclass&& that) noexcept : name{ std::move(that).name + "(CM)" } , addr{ std::move(that).addr } -#line 8 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 9 "pure2-types-smf-and-that-1-provide-everything.cpp2" { +#line 12 "pure2-types-smf-and-that-1-provide-everything.cpp2" std::cout << "ctor - move "; } @@ -80,40 +82,41 @@ auto main() -> int; name = that.name; addr = that.addr + "(AC)"; -#line 15 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 18 "pure2-types-smf-and-that-1-provide-everything.cpp2" std::cout << "assign - copy "; return *this; -#line 16 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 19 "pure2-types-smf-and-that-1-provide-everything.cpp2" } auto myclass::operator=(myclass&& that) noexcept -> myclass& { name = std::move(that).name; addr = std::move(that).addr; -#line 19 "pure2-types-smf-and-that-1-provide-everything.cpp2" + +#line 23 "pure2-types-smf-and-that-1-provide-everything.cpp2" std::cout << "assign - move "; return *this; -#line 20 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 24 "pure2-types-smf-and-that-1-provide-everything.cpp2" } myclass::myclass(cpp2::in x) : name{ x } -#line 22 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 26 "pure2-types-smf-and-that-1-provide-everything.cpp2" { std::cout << "ctor - from string "; } -#line 22 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 26 "pure2-types-smf-and-that-1-provide-everything.cpp2" auto myclass::operator=(cpp2::in x) -> myclass& { name = x; addr = "123 Ford Dr."; -#line 24 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 28 "pure2-types-smf-and-that-1-provide-everything.cpp2" std::cout << "ctor - from string "; return *this; -#line 25 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 29 "pure2-types-smf-and-that-1-provide-everything.cpp2" } -#line 30 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 34 "pure2-types-smf-and-that-1-provide-everything.cpp2" auto myclass::print( cpp2::in prefix, @@ -121,7 +124,7 @@ auto main() -> int; ) const -> void { std::cout << prefix << "[ " + cpp2::to_string(name) + " | " + cpp2::to_string(addr) + " ]" << suffix; } -#line 39 "pure2-types-smf-and-that-1-provide-everything.cpp2" +#line 43 "pure2-types-smf-and-that-1-provide-everything.cpp2" auto main() -> int{ std::cout << "Function invoked Call syntax Results\n"; std::cout << "---------------------- ------------ ------------------------------------------------------\n"; diff --git a/regression-tests/test-results/pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp b/regression-tests/test-results/pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp index a6c54323c..aab75e87a 100644 --- a/regression-tests/test-results/pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp +++ b/regression-tests/test-results/pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp @@ -20,29 +20,30 @@ class myclass { public: myclass(myclass const& that); -#line 8 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 9 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" public: myclass(myclass&& that) noexcept; -#line 13 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 15 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" public: auto operator=(myclass const& that) -> myclass& ; -#line 13 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 15 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" public: auto operator=(myclass&& that) noexcept -> myclass& ; -#line 18 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 21 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" // operator=: (inout this, move that) = { + // this = that; // std::cout << "assign - move "; // } public: explicit myclass(cpp2::in x); -#line 22 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 26 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" public: auto operator=(cpp2::in x) -> myclass& ; -#line 27 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 31 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" private: std::string name {"Henry"}; private: std::string addr {"123 Ford Dr."}; @@ -52,7 +53,7 @@ class myclass { cpp2::in suffix ) const -> void; -#line 37 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 41 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" }; auto main() -> int; @@ -67,15 +68,17 @@ auto main() -> int; , addr{ that.addr } #line 4 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" { + std::cout << "ctor - copy (GENERAL)"; } myclass::myclass(myclass&& that) noexcept : name{ std::move(that).name + "(CM)" } , addr{ std::move(that).addr } -#line 8 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 9 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" { +#line 12 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" std::cout << "ctor - move "; } @@ -83,42 +86,42 @@ auto main() -> int; name = that.name; addr = that.addr + "(AC)"; -#line 15 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 18 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" std::cout << "assign - copy "; return *this; -#line 16 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 19 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" } -#line 13 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 15 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" auto myclass::operator=(myclass&& that) noexcept -> myclass& { name = std::move(that).name; addr = std::move(that).addr + "(AC)"; -#line 15 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 18 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" std::cout << "assign - copy "; return *this; -#line 16 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 19 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" } -#line 22 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 26 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" myclass::myclass(cpp2::in x) : name{ x } -#line 22 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 26 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" { std::cout << "ctor - from string "; } -#line 22 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 26 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" auto myclass::operator=(cpp2::in x) -> myclass& { name = x; addr = "123 Ford Dr."; -#line 24 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 28 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" std::cout << "ctor - from string "; return *this; -#line 25 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 29 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" } -#line 30 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 34 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" auto myclass::print( cpp2::in prefix, @@ -126,7 +129,7 @@ auto main() -> int; ) const -> void { std::cout << prefix << "[ " + cpp2::to_string(name) + " | " + cpp2::to_string(addr) + " ]" << suffix; } -#line 39 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" +#line 43 "pure2-types-smf-and-that-2-provide-mvconstruct-and-cpassign.cpp2" auto main() -> int{ std::cout << "Function invoked Call syntax Results\n"; std::cout << "---------------------- ------------ ------------------------------------------------------\n"; diff --git a/regression-tests/test-results/pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp b/regression-tests/test-results/pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp index e17b83c9c..9a6f8c894 100644 --- a/regression-tests/test-results/pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp +++ b/regression-tests/test-results/pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp @@ -23,12 +23,13 @@ class myclass { public: auto operator=(myclass const& that) -> myclass& ; -#line 8 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 9 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" public: myclass(myclass&& that) noexcept; -#line 13 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 15 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" // operator=: (inout this, that) = { + // this = that; // addr = that.addr + "(AC)"; // std::cout << "assign - copy "; // } @@ -36,14 +37,14 @@ class myclass { public: auto operator=(myclass&& that) noexcept -> myclass& ; -#line 22 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 26 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" public: explicit myclass(cpp2::in x); -#line 22 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 26 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" public: auto operator=(cpp2::in x) -> myclass& ; -#line 27 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 31 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" private: std::string name {"Henry"}; private: std::string addr {"123 Ford Dr."}; @@ -53,7 +54,7 @@ class myclass { cpp2::in suffix ) const -> void; -#line 37 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 41 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" }; auto main() -> int; @@ -68,56 +69,60 @@ auto main() -> int; , addr{ that.addr } #line 4 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" { + std::cout << "ctor - copy (GENERAL)"; } #line 4 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" auto myclass::operator=(myclass const& that) -> myclass& { name = that.name; addr = that.addr; -#line 5 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" + +#line 6 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" std::cout << "ctor - copy (GENERAL)"; return *this; -#line 6 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 7 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" } myclass::myclass(myclass&& that) noexcept : name{ std::move(that).name + "(CM)" } , addr{ std::move(that).addr } -#line 8 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 9 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" { +#line 12 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" std::cout << "ctor - move "; } -#line 18 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 21 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" auto myclass::operator=(myclass&& that) noexcept -> myclass& { name = std::move(that).name; addr = std::move(that).addr; -#line 19 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" + +#line 23 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" std::cout << "assign - move "; return *this; -#line 20 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 24 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" } myclass::myclass(cpp2::in x) : name{ x } -#line 22 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 26 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" { std::cout << "ctor - from string "; } -#line 22 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 26 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" auto myclass::operator=(cpp2::in x) -> myclass& { name = x; addr = "123 Ford Dr."; -#line 24 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 28 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" std::cout << "ctor - from string "; return *this; -#line 25 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 29 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" } -#line 30 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 34 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" auto myclass::print( cpp2::in prefix, @@ -125,7 +130,7 @@ auto main() -> int; ) const -> void { std::cout << prefix << "[ " + cpp2::to_string(name) + " | " + cpp2::to_string(addr) + " ]" << suffix; } -#line 39 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" +#line 43 "pure2-types-smf-and-that-3-provide-mvconstruct-and-mvassign.cpp2" auto main() -> int{ std::cout << "Function invoked Call syntax Results\n"; std::cout << "---------------------- ------------ ------------------------------------------------------\n"; diff --git a/regression-tests/test-results/pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp b/regression-tests/test-results/pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp index 80ea3cf34..2cdd2f83b 100644 --- a/regression-tests/test-results/pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp +++ b/regression-tests/test-results/pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp @@ -23,8 +23,9 @@ class myclass { public: myclass(myclass&& that) noexcept; -#line 8 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 9 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" // operator=: (out this, move that) = { + // this = that; // name = that.name + "(CM)"; // std::cout << "ctor - move "; // } @@ -32,18 +33,18 @@ class myclass { public: auto operator=(myclass const& that) -> myclass& ; -#line 18 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 21 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" public: auto operator=(myclass&& that) noexcept -> myclass& ; -#line 22 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 26 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" public: explicit myclass(cpp2::in x); -#line 22 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 26 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" public: auto operator=(cpp2::in x) -> myclass& ; -#line 27 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 31 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" private: std::string name {"Henry"}; private: std::string addr {"123 Ford Dr."}; @@ -53,7 +54,7 @@ class myclass { cpp2::in suffix ) const -> void; -#line 37 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 41 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" }; auto main() -> int; @@ -68,6 +69,7 @@ auto main() -> int; , addr{ that.addr } #line 4 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" { + std::cout << "ctor - copy (GENERAL)"; } #line 4 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" @@ -76,48 +78,50 @@ auto main() -> int; , addr{ std::move(that).addr } #line 4 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" { + std::cout << "ctor - copy (GENERAL)"; } -#line 13 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 15 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" auto myclass::operator=(myclass const& that) -> myclass& { name = that.name; addr = that.addr + "(AC)"; -#line 15 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 18 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" std::cout << "assign - copy "; return *this; -#line 16 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 19 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" } auto myclass::operator=(myclass&& that) noexcept -> myclass& { name = std::move(that).name; addr = std::move(that).addr; -#line 19 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" + +#line 23 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" std::cout << "assign - move "; return *this; -#line 20 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 24 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" } myclass::myclass(cpp2::in x) : name{ x } -#line 22 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 26 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" { std::cout << "ctor - from string "; } -#line 22 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 26 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" auto myclass::operator=(cpp2::in x) -> myclass& { name = x; addr = "123 Ford Dr."; -#line 24 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 28 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" std::cout << "ctor - from string "; return *this; -#line 25 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 29 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" } -#line 30 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 34 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" auto myclass::print( cpp2::in prefix, @@ -125,7 +129,7 @@ auto main() -> int; ) const -> void { std::cout << prefix << "[ " + cpp2::to_string(name) + " | " + cpp2::to_string(addr) + " ]" << suffix; } -#line 39 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" +#line 43 "pure2-types-smf-and-that-4-provide-cpassign-and-mvassign.cpp2" auto main() -> int{ std::cout << "Function invoked Call syntax Results\n"; std::cout << "---------------------- ------------ ------------------------------------------------------\n"; diff --git a/regression-tests/test-results/pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp b/regression-tests/test-results/pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp index aae06789d..61e88b165 100644 --- a/regression-tests/test-results/pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp +++ b/regression-tests/test-results/pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp @@ -29,28 +29,31 @@ class myclass { public: auto operator=(myclass&& that) noexcept -> myclass& ; -#line 8 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 9 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" // operator=: (out this, move that) = { + // this = that; // name = that.name + "(CM)"; // std::cout << "ctor - move "; // } // operator=: (inout this, that) = { + // this = that; // addr = that.addr + "(AC)"; // std::cout << "assign - copy "; // } // operator=: (inout this, move that) = { + // this = that; // std::cout << "assign - move "; // } public: explicit myclass(cpp2::in x); -#line 22 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 26 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" public: auto operator=(cpp2::in x) -> myclass& ; -#line 27 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 31 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" private: std::string name {"Henry"}; private: std::string addr {"123 Ford Dr."}; @@ -60,7 +63,7 @@ class myclass { cpp2::in suffix ) const -> void; -#line 37 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 41 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" }; auto main() -> int; @@ -75,16 +78,18 @@ auto main() -> int; , addr{ that.addr } #line 4 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" { + std::cout << "ctor - copy (GENERAL)"; } #line 4 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" auto myclass::operator=(myclass const& that) -> myclass& { name = that.name; addr = that.addr; -#line 5 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" + +#line 6 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" std::cout << "ctor - copy (GENERAL)"; return *this; -#line 6 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 7 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" } #line 4 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" myclass::myclass(myclass&& that) noexcept @@ -92,38 +97,40 @@ auto main() -> int; , addr{ std::move(that).addr } #line 4 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" { + std::cout << "ctor - copy (GENERAL)"; } #line 4 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" auto myclass::operator=(myclass&& that) noexcept -> myclass& { name = std::move(that).name; addr = std::move(that).addr; -#line 5 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" + +#line 6 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" std::cout << "ctor - copy (GENERAL)"; return *this; -#line 6 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 7 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" } -#line 22 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 26 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" myclass::myclass(cpp2::in x) : name{ x } -#line 22 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 26 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" { std::cout << "ctor - from string "; } -#line 22 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 26 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" auto myclass::operator=(cpp2::in x) -> myclass& { name = x; addr = "123 Ford Dr."; -#line 24 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 28 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" std::cout << "ctor - from string "; return *this; -#line 25 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 29 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" } -#line 30 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 34 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" auto myclass::print( cpp2::in prefix, @@ -131,7 +138,7 @@ auto main() -> int; ) const -> void { std::cout << prefix << "[ " + cpp2::to_string(name) + " | " + cpp2::to_string(addr) + " ]" << suffix; } -#line 39 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" +#line 43 "pure2-types-smf-and-that-5-provide-nothing-but-general-case.cpp2" auto main() -> int{ std::cout << "Function invoked Call syntax Results\n"; std::cout << "---------------------- ------------ ------------------------------------------------------\n"; diff --git a/regression-tests/test-results/pure2-types-smf-statements-between-member-inits.cpp b/regression-tests/test-results/pure2-types-smf-statements-between-member-inits.cpp new file mode 100644 index 000000000..30dbaaa49 --- /dev/null +++ b/regression-tests/test-results/pure2-types-smf-statements-between-member-inits.cpp @@ -0,0 +1,789 @@ + +#define CPP2_USE_MODULES Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + + +#line 5 "pure2-types-smf-statements-between-member-inits.cpp2" +class t1; + + +#line 17 "pure2-types-smf-statements-between-member-inits.cpp2" +class t2; + + +#line 31 "pure2-types-smf-statements-between-member-inits.cpp2" +class t3; + + +#line 45 "pure2-types-smf-statements-between-member-inits.cpp2" +class t4; + + +#line 61 "pure2-types-smf-statements-between-member-inits.cpp2" +class t5; + + +#line 77 "pure2-types-smf-statements-between-member-inits.cpp2" +class t6; + + +#line 95 "pure2-types-smf-statements-between-member-inits.cpp2" +class t7; + + +#line 113 "pure2-types-smf-statements-between-member-inits.cpp2" +class t8; + + +#line 133 "pure2-types-smf-statements-between-member-inits.cpp2" +class t9; + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-types-smf-statements-between-member-inits.cpp2" +auto f(cpp2::in a1) -> void; + + +#line 5 "pure2-types-smf-statements-between-member-inits.cpp2" +class t1 { + private: cpp2::i32 m1 {123}; + private: cpp2::i32 m2 {456}; + + public: t1(t1 const& that); + +#line 9 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t1 const& that) -> t1& ; + +#line 9 "pure2-types-smf-statements-between-member-inits.cpp2" + public: t1(t1&& that) noexcept; + +#line 9 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t1&& that) noexcept -> t1& ; + + +#line 15 "pure2-types-smf-statements-between-member-inits.cpp2" +}; + +class t2 { + private: cpp2::i32 m1 {123}; + private: cpp2::i32 m2 {456}; + + public: t2(t2 const& that); + +#line 21 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t2 const& that) -> t2& ; + +#line 21 "pure2-types-smf-statements-between-member-inits.cpp2" + public: t2(t2&& that) noexcept; + +#line 21 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t2&& that) noexcept -> t2& ; + + +#line 29 "pure2-types-smf-statements-between-member-inits.cpp2" +}; + +class t3 { + private: cpp2::i32 m1 {123}; + private: cpp2::i32 m2 {456}; + + public: t3(t3 const& that); + +#line 35 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t3 const& that) -> t3& ; + +#line 35 "pure2-types-smf-statements-between-member-inits.cpp2" + public: t3(t3&& that) noexcept; + +#line 35 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t3&& that) noexcept -> t3& ; + + +#line 43 "pure2-types-smf-statements-between-member-inits.cpp2" +}; + +class t4 { + private: cpp2::i32 m1 {123}; + private: cpp2::i32 m2 {456}; + + public: t4(t4 const& that); + +#line 49 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t4 const& that) -> t4& ; + +#line 49 "pure2-types-smf-statements-between-member-inits.cpp2" + public: t4(t4&& that) noexcept; + +#line 49 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t4&& that) noexcept -> t4& ; + + +#line 59 "pure2-types-smf-statements-between-member-inits.cpp2" +}; + +class t5 { + private: cpp2::i32 m1 {123}; + private: cpp2::i32 m2 {456}; + + public: t5(t5 const& that); + +#line 65 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t5 const& that) -> t5& ; + +#line 65 "pure2-types-smf-statements-between-member-inits.cpp2" + public: t5(t5&& that) noexcept; + +#line 65 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t5&& that) noexcept -> t5& ; + + +#line 75 "pure2-types-smf-statements-between-member-inits.cpp2" +}; + +class t6 { + private: cpp2::i32 m1 {123}; + private: cpp2::i32 m2 {456}; + + public: t6(t6 const& that); + +#line 81 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t6 const& that) -> t6& ; + +#line 81 "pure2-types-smf-statements-between-member-inits.cpp2" + public: t6(t6&& that) noexcept; + +#line 81 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t6&& that) noexcept -> t6& ; + + +#line 93 "pure2-types-smf-statements-between-member-inits.cpp2" +}; + +class t7 { + private: cpp2::i32 m1 {123}; + private: cpp2::i32 m2 {456}; + + public: t7(t7 const& that); + +#line 99 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t7 const& that) -> t7& ; + +#line 99 "pure2-types-smf-statements-between-member-inits.cpp2" + public: t7(t7&& that) noexcept; + +#line 99 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t7&& that) noexcept -> t7& ; + + +#line 111 "pure2-types-smf-statements-between-member-inits.cpp2" +}; + +class t8 { + private: cpp2::i32 m1 {123}; + private: cpp2::i32 m2 {456}; + + public: t8(t8 const& that); + +#line 117 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t8 const& that) -> t8& ; + +#line 117 "pure2-types-smf-statements-between-member-inits.cpp2" + public: t8(t8&& that) noexcept; + +#line 117 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t8&& that) noexcept -> t8& ; + + +#line 131 "pure2-types-smf-statements-between-member-inits.cpp2" +}; + +class t9 { + private: cpp2::i32 m1 {123}; + private: cpp2::i32 m2 {456}; + + public: t9(cpp2::in a1); + +#line 137 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(cpp2::in a1) -> t9& ; + + +#line 150 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t9 const& that) -> t9& ; + +#line 150 "pure2-types-smf-statements-between-member-inits.cpp2" + public: auto operator=(t9&& that) noexcept -> t9& ; + + public: t9(t9 const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(t9 const&) -> void = delete; + + +#line 158 "pure2-types-smf-statements-between-member-inits.cpp2" +}; + + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-types-smf-statements-between-member-inits.cpp2" +auto f(cpp2::in a1) -> void{ + (void) a1; +} + +#line 9 "pure2-types-smf-statements-between-member-inits.cpp2" + t1::t1(t1 const& that){ + // m1 = 123 implied + // m2 = 456 implied + f(1); + f(2); + } +#line 9 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t1::operator=(t1 const& that) -> t1& { + m1 = 123; + m2 = 456; + +#line 12 "pure2-types-smf-statements-between-member-inits.cpp2" + f(1); + f(2); + return *this; +#line 14 "pure2-types-smf-statements-between-member-inits.cpp2" + } +#line 9 "pure2-types-smf-statements-between-member-inits.cpp2" + t1::t1(t1&& that) noexcept{ + +#line 12 "pure2-types-smf-statements-between-member-inits.cpp2" + f(1); + f(2); + } +#line 9 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t1::operator=(t1&& that) noexcept -> t1& { + m1 = 123; + m2 = 456; + +#line 12 "pure2-types-smf-statements-between-member-inits.cpp2" + f(1); + f(2); + return *this; +#line 14 "pure2-types-smf-statements-between-member-inits.cpp2" + } + +#line 21 "pure2-types-smf-statements-between-member-inits.cpp2" + t2::t2(t2 const& that) + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + return 3; + }() } +#line 21 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 25 "pure2-types-smf-statements-between-member-inits.cpp2" + // m2 = 456 implied + f(4); + f(5); + } +#line 21 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t2::operator=(t2 const& that) -> t2& { + f(1); + f(2); + m1 = 3; + m2 = 456; + +#line 26 "pure2-types-smf-statements-between-member-inits.cpp2" + f(4); + f(5); + return *this; +#line 28 "pure2-types-smf-statements-between-member-inits.cpp2" + } +#line 21 "pure2-types-smf-statements-between-member-inits.cpp2" + t2::t2(t2&& that) noexcept + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + return 3; + }() } +#line 21 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 26 "pure2-types-smf-statements-between-member-inits.cpp2" + f(4); + f(5); + } +#line 21 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t2::operator=(t2&& that) noexcept -> t2& { + f(1); + f(2); + m1 = 3; + m2 = 456; + +#line 26 "pure2-types-smf-statements-between-member-inits.cpp2" + f(4); + f(5); + return *this; +#line 28 "pure2-types-smf-statements-between-member-inits.cpp2" + } + +#line 35 "pure2-types-smf-statements-between-member-inits.cpp2" + t3::t3(t3 const& that) + : m2{ [&]() -> decltype(auto) { + f(1); + f(2); + return 3; + }() } +#line 35 "pure2-types-smf-statements-between-member-inits.cpp2" + { + // m1 = 123 implied + +#line 40 "pure2-types-smf-statements-between-member-inits.cpp2" + f(4); + f(5); + } +#line 35 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t3::operator=(t3 const& that) -> t3& { + m1 = 123; + f(1); + f(2); + m2 = 3; + +#line 40 "pure2-types-smf-statements-between-member-inits.cpp2" + f(4); + f(5); + return *this; +#line 42 "pure2-types-smf-statements-between-member-inits.cpp2" + } +#line 35 "pure2-types-smf-statements-between-member-inits.cpp2" + t3::t3(t3&& that) noexcept + : m2{ [&]() -> decltype(auto) { + f(1); + f(2); + return 3; + }() } +#line 35 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 40 "pure2-types-smf-statements-between-member-inits.cpp2" + f(4); + f(5); + } +#line 35 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t3::operator=(t3&& that) noexcept -> t3& { + m1 = 123; + f(1); + f(2); + m2 = 3; + +#line 40 "pure2-types-smf-statements-between-member-inits.cpp2" + f(4); + f(5); + return *this; +#line 42 "pure2-types-smf-statements-between-member-inits.cpp2" + } + +#line 49 "pure2-types-smf-statements-between-member-inits.cpp2" + t4::t4(t4 const& that) + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + return 3; + }() } + , m2{ [&]() -> decltype(auto) { + f(4); + f(5); + return 6; + }() } +#line 49 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 56 "pure2-types-smf-statements-between-member-inits.cpp2" + f(7); + f(8); + } +#line 49 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t4::operator=(t4 const& that) -> t4& { + f(1); + f(2); + m1 = 3; + f(4); + f(5); + m2 = 6; + +#line 56 "pure2-types-smf-statements-between-member-inits.cpp2" + f(7); + f(8); + return *this; +#line 58 "pure2-types-smf-statements-between-member-inits.cpp2" + } +#line 49 "pure2-types-smf-statements-between-member-inits.cpp2" + t4::t4(t4&& that) noexcept + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + return 3; + }() } + , m2{ [&]() -> decltype(auto) { + f(4); + f(5); + return 6; + }() } +#line 49 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 56 "pure2-types-smf-statements-between-member-inits.cpp2" + f(7); + f(8); + } +#line 49 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t4::operator=(t4&& that) noexcept -> t4& { + f(1); + f(2); + m1 = 3; + f(4); + f(5); + m2 = 6; + +#line 56 "pure2-types-smf-statements-between-member-inits.cpp2" + f(7); + f(8); + return *this; +#line 58 "pure2-types-smf-statements-between-member-inits.cpp2" + } + +#line 65 "pure2-types-smf-statements-between-member-inits.cpp2" + t5::t5(t5 const& that) + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + return that.m1; + }() } + , m2{ that.m2 } +#line 65 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 69 "pure2-types-smf-statements-between-member-inits.cpp2" + // m1 = that.m1 implied + // m2 = that.m2 implied + // This comment should show up before f(3) + f(3); + f(4); + } +#line 65 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t5::operator=(t5 const& that) -> t5& { + f(1); + f(2); + m1 = that.m1; + m2 = that.m2; + +#line 72 "pure2-types-smf-statements-between-member-inits.cpp2" + f(3); + f(4); + return *this; +#line 74 "pure2-types-smf-statements-between-member-inits.cpp2" + } +#line 65 "pure2-types-smf-statements-between-member-inits.cpp2" + t5::t5(t5&& that) noexcept + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + return std::move(that).m1; + }() } + , m2{ std::move(that).m2 } +#line 65 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 72 "pure2-types-smf-statements-between-member-inits.cpp2" + f(3); + f(4); + } +#line 65 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t5::operator=(t5&& that) noexcept -> t5& { + f(1); + f(2); + m1 = std::move(that).m1; + m2 = std::move(that).m2; + +#line 72 "pure2-types-smf-statements-between-member-inits.cpp2" + f(3); + f(4); + return *this; +#line 74 "pure2-types-smf-statements-between-member-inits.cpp2" + } + +#line 81 "pure2-types-smf-statements-between-member-inits.cpp2" + t6::t6(t6 const& that) + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + f(3); + f(4); + return 5; + }() } + , m2{ that.m2 } +#line 81 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 88 "pure2-types-smf-statements-between-member-inits.cpp2" + // m2 = that.m2 implied + // This comment should show up before f(6) + f(6); + f(7); + } +#line 81 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t6::operator=(t6 const& that) -> t6& { + f(1); + f(2); + f(3); + f(4); + m1 = 5; + m2 = that.m2; + +#line 90 "pure2-types-smf-statements-between-member-inits.cpp2" + f(6); + f(7); + return *this; +#line 92 "pure2-types-smf-statements-between-member-inits.cpp2" + } +#line 81 "pure2-types-smf-statements-between-member-inits.cpp2" + t6::t6(t6&& that) noexcept + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + f(3); + f(4); + return 5; + }() } + , m2{ std::move(that).m2 } +#line 81 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 90 "pure2-types-smf-statements-between-member-inits.cpp2" + f(6); + f(7); + } +#line 81 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t6::operator=(t6&& that) noexcept -> t6& { + f(1); + f(2); + f(3); + f(4); + m1 = 5; + m2 = std::move(that).m2; + +#line 90 "pure2-types-smf-statements-between-member-inits.cpp2" + f(6); + f(7); + return *this; +#line 92 "pure2-types-smf-statements-between-member-inits.cpp2" + } + +#line 99 "pure2-types-smf-statements-between-member-inits.cpp2" + t7::t7(t7 const& that) + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + return that.m1; + }() } + , m2{ [&]() -> decltype(auto) { + f(3); + f(4); + return 5; + }() } +#line 99 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 103 "pure2-types-smf-statements-between-member-inits.cpp2" + // m1 = that.m1 implied + +#line 107 "pure2-types-smf-statements-between-member-inits.cpp2" + // This comment should show up before f(6) + f(6); + f(7); + } +#line 99 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t7::operator=(t7 const& that) -> t7& { + f(1); + f(2); + m1 = that.m1; + f(3); + f(4); + m2 = 5; + +#line 108 "pure2-types-smf-statements-between-member-inits.cpp2" + f(6); + f(7); + return *this; +#line 110 "pure2-types-smf-statements-between-member-inits.cpp2" + } +#line 99 "pure2-types-smf-statements-between-member-inits.cpp2" + t7::t7(t7&& that) noexcept + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + return std::move(that).m1; + }() } + , m2{ [&]() -> decltype(auto) { + f(3); + f(4); + return 5; + }() } +#line 99 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 108 "pure2-types-smf-statements-between-member-inits.cpp2" + f(6); + f(7); + } +#line 99 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t7::operator=(t7&& that) noexcept -> t7& { + f(1); + f(2); + m1 = std::move(that).m1; + f(3); + f(4); + m2 = 5; + +#line 108 "pure2-types-smf-statements-between-member-inits.cpp2" + f(6); + f(7); + return *this; +#line 110 "pure2-types-smf-statements-between-member-inits.cpp2" + } + +#line 117 "pure2-types-smf-statements-between-member-inits.cpp2" + t8::t8(t8 const& that) + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + f(3); + f(4); + return 5; + }() } + , m2{ [&]() -> decltype(auto) { + f(6); + f(7); + return 8; + }() } +#line 117 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 127 "pure2-types-smf-statements-between-member-inits.cpp2" + // This comment should show up before f(9) + f(9); + f(10); + } +#line 117 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t8::operator=(t8 const& that) -> t8& { + f(1); + f(2); + f(3); + f(4); + m1 = 5; + f(6); + f(7); + m2 = 8; + +#line 128 "pure2-types-smf-statements-between-member-inits.cpp2" + f(9); + f(10); + return *this; +#line 130 "pure2-types-smf-statements-between-member-inits.cpp2" + } +#line 117 "pure2-types-smf-statements-between-member-inits.cpp2" + t8::t8(t8&& that) noexcept + : m1{ [&]() -> decltype(auto) { + f(1); + f(2); + f(3); + f(4); + return 5; + }() } + , m2{ [&]() -> decltype(auto) { + f(6); + f(7); + return 8; + }() } +#line 117 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 128 "pure2-types-smf-statements-between-member-inits.cpp2" + f(9); + f(10); + } +#line 117 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t8::operator=(t8&& that) noexcept -> t8& { + f(1); + f(2); + f(3); + f(4); + m1 = 5; + f(6); + f(7); + m2 = 8; + +#line 128 "pure2-types-smf-statements-between-member-inits.cpp2" + f(9); + f(10); + return *this; +#line 130 "pure2-types-smf-statements-between-member-inits.cpp2" + } + +#line 137 "pure2-types-smf-statements-between-member-inits.cpp2" + t9::t9(cpp2::in a1) + : m1{ [&]() -> decltype(auto) { + (void) a1; + f(1); + f(2); + return 3; + }() } + , m2{ [&]() -> decltype(auto) { + f(4); + f(5); + return 6; + }() } +#line 137 "pure2-types-smf-statements-between-member-inits.cpp2" + { + +#line 145 "pure2-types-smf-statements-between-member-inits.cpp2" + // This comment should show up before f(7) + f(7); + f(8); + } +#line 137 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t9::operator=(cpp2::in a1) -> t9& { + (void) a1; + f(1); + f(2); + m1 = 3; + f(4); + f(5); + m2 = 6; + +#line 146 "pure2-types-smf-statements-between-member-inits.cpp2" + f(7); + f(8); + return *this; +#line 148 "pure2-types-smf-statements-between-member-inits.cpp2" + } + + auto t9::operator=(t9 const& that) -> t9& { + // This function shouldn't contain any member assignments. + // While it's a special member function that uses 'that', + // it's explicitly an assignment operator because of 'inout this', + // so we let the programmer avoid member assignment if they choose. + f(1); + f(2); + return *this; +#line 157 "pure2-types-smf-statements-between-member-inits.cpp2" + } +#line 150 "pure2-types-smf-statements-between-member-inits.cpp2" + auto t9::operator=(t9&& that) noexcept -> t9& { + +#line 155 "pure2-types-smf-statements-between-member-inits.cpp2" + f(1); + f(2); + return *this; +#line 157 "pure2-types-smf-statements-between-member-inits.cpp2" + } + diff --git a/regression-tests/test-results/pure2-types-smf-statements-between-member-inits.cpp2.output b/regression-tests/test-results/pure2-types-smf-statements-between-member-inits.cpp2.output new file mode 100644 index 000000000..4981c8c5e --- /dev/null +++ b/regression-tests/test-results/pure2-types-smf-statements-between-member-inits.cpp2.output @@ -0,0 +1,2 @@ +pure2-types-smf-statements-between-member-inits.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/source/cppfront.cpp b/source/cppfront.cpp index 38d88cc7f..038070cfd 100644 --- a/source/cppfront.cpp +++ b/source/cppfront.cpp @@ -4492,15 +4492,21 @@ class cppfront // If this constructor's type has data members, handle their initialization // - objects is the list of this type's declarations - // - statements is the list of this constructor's statements - auto objects = n.parent_declaration->get_type_scope_declarations(n.objects); - auto statements = n.get_initializer_statements(); - auto out_inits = std::vector{}; + // - body_statements is the list of statements in this constructor's body + // - pending_statements is the list of statements to insert before the next (possibly implicit) member initializer + // - deferred_statements is the list of statements to insert before the next explicit member initializer + auto objects = n.parent_declaration->get_type_scope_declarations(n.objects); + auto body_statements = n.get_initializer_statements(); + auto pending_statements = std::vector{}; + auto deferred_statements = std::vector{}; auto object = objects.begin(); - auto statement = statements.begin(); + auto statement = body_statements.begin(); auto separator = std::string{": "}; + auto found_that_init = false; + auto default_until_object = objects.end(); // objects.end() means we're not yet skipping to anything + while (object != objects.end()) { auto object_name = canonize_object_name(*object); @@ -4514,12 +4520,17 @@ class cppfront auto initializer = std::string{}; - // If we're at an assignment statement, get the lhs and rhs - if (statement != statements.end()) + if (default_until_object == object) + { + default_until_object = objects.end(); // objects.end() means we're no longer skipping to anything + } + + if (default_until_object == objects.end() && statement != body_statements.end()) { assert (*statement); stmt_pos = (*statement)->position(); + // If we're at an assignment statement, get the lhs and rhs auto lhs = std::string{}; auto rhs = std::string{}; { @@ -4537,36 +4548,61 @@ class cppfront } } - // If this is an initialization of an 'out' parameter, stash it - if (n.has_out_parameter_named(lhs)){ - out_inits.push_back( print_to_string(**statement, false) ); - (*statement)->emitted = true; - ++statement; - continue; - } - - // Now we're ready to check whether this is an assignment to *object - + // Now we're ready to check whether this is a member assignment if (!lhs.empty()) { - // First, see if it's an assignment 'name = something' - found_explicit_init = object_name == lhs; - - // Otherwise, see if it's 'this.name = something' - if (!found_explicit_init) + // First, check if it's 'this = that' + if (lhs == "this" && rhs == (emitting_move_that_function ? "std::move(that)" : "that")) { - // If it's of the form 'this.name', check 'name' - if ( - starts_with( lhs, "(*this).") - && object_name == lhs.substr(8) - ) + if (!emitting_that_function) { - found_explicit_init = true; + errors.emplace_back( + stmt_pos, + "'this = that' can only be used in functions where 'that' is a parameter" + ); + return; + } + else if (object != objects.begin()) + { + errors.emplace_back( + stmt_pos, + "'this = that' must appear before all other member initializers" + ); + return; + } + else if (found_that_init) + { + errors.emplace_back( + stmt_pos, + "'this = that' may only appear once" + ); + return; + } + else + { + // All the statements before 'this = that' need to be inserted + // before the first member initializer whether or not it's explicit + assert(pending_statements.empty()); + pending_statements.swap(deferred_statements); + + found_that_init = true; + (*statement)->emitted = true; + ++statement; + continue; } } - if (found_explicit_init) + // Second, check if it's an assignment 'member = something' or 'this.member = something' + auto lhs_name = lhs.substr(starts_with(lhs, "(*this).") ? 8 : 0); + auto lhs_object = std::find_if( + objects.begin(), objects.end(), + [&](auto o) { return canonize_object_name(o) == lhs_name; } + ); + + // Is it the current member? + if (lhs_object == object) { + found_explicit_init = true; initializer = rhs; // We've used this statement, so note it @@ -4574,30 +4610,48 @@ class cppfront (*statement)->emitted = true; ++statement; } + // Is it a future member? + else if (lhs_object != objects.end() && lhs_object > object) + { + // Default-initialize all the members before it + default_until_object = lhs_object; + continue; + } + } + + // Not an explicit init for the current member? + if (!found_explicit_init) + { + // Queue it up to insert before the next explicit initializer + deferred_statements.push_back( *statement ); + ++statement; + continue; } } + // If explicit, upgrade deferred statements to pending + if (found_explicit_init) + { + pending_statements.insert( + pending_statements.end(), + std::make_move_iterator(deferred_statements.begin()), + std::make_move_iterator(deferred_statements.end()) + ); + deferred_statements.clear(); + } + // 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") + // and for a copy/move function with 'this = that' we default to "= that.same_member" + // (or, if this is a base type, just "= that") if (!found_explicit_init) { - if (emitting_move_that_function) + if (found_that_init) { - initializer = "std::move(that)"; + initializer = emitting_move_that_function ? "std::move(that)" : "that"; if (!(*object)->has_name("this")) { initializer += "." + object_name; } - found_default_init = true; - } - else if (emitting_that_function) - { - initializer = "that"; - if (!(*object)->has_name("this")) { - initializer += "." + object_name; - } - found_default_init = true; } else if ((*object)->initializer) { @@ -4607,10 +4661,12 @@ class cppfront } // If this is not an assignment to *object, - // and there was no member initializer, complain + // and there was no 'this = that' or member initializer, complain if ( !found_explicit_init + && !found_that_init && !found_default_init + && !n.is_assignment() ) { errors.emplace_back( @@ -4622,7 +4678,9 @@ class cppfront assert( found_explicit_init + || found_that_init || found_default_init + || n.is_assignment() ); // Emit the initializer... @@ -4631,48 +4689,58 @@ class cppfront initializer = "{}"; } - // (a) ... if this is assignment, emit it in all cases + // (a) ... if this is assignment, emit if explicit or 'this = that' + // or we're generating from a constructor definition if (is_assignment) { - assert ((*object)->name()); + if ( + found_explicit_init + || found_that_init + || n.is_constructor()) + { + assert ((*object)->name()); - // Flush any 'out' parameter initializations - for (auto& init : out_inits) { - current_functions.back().prolog.statements.push_back(init + ";"); - } - out_inits = {}; + // Flush any pending statements + for (auto statement : pending_statements) { + current_functions.back().prolog.statements.push_back( + print_to_string(*statement, false) + ";" + ); + statement->emitted = true; + } + pending_statements.clear(); - // Then add this statement + // Then add this statement - // Use ::operator= for base classes - if ((*object)->has_name("this")) { - current_functions.back().prolog.statements.push_back( - print_to_string( *(*object)->get_object_type() ) + - "::operator= ( " + - initializer + - " );" - ); - } - // Else just use infix assignment - else { - current_functions.back().prolog.statements.push_back( - object_name + - " = " + - initializer + - ";" - ); + // Use ::operator= for base classes + if ((*object)->has_name("this")) { + current_functions.back().prolog.statements.push_back( + print_to_string( *(*object)->get_object_type() ) + + "::operator= ( " + + initializer + + " );" + ); + } + // Else just use infix assignment + else { + current_functions.back().prolog.statements.push_back( + object_name + + " = " + + initializer + + ";" + ); + } } } // (b) ... if this isn't assignment, only need to emit it if it was - // explicit, or is a base type or 'that' initializer + // explicit or 'this = that' or is a base type else if ( found_explicit_init + || found_that_init || is_object_before_base || ( (*object)->has_name("this") && !initializer.empty() ) - || emitting_that_function ) { if (is_object_before_base) { @@ -4684,40 +4752,27 @@ class cppfront + "_as_base"; } - // Flush any 'out' parameter initializations - auto out_inits_with_commas = [&]() -> std::string { - auto ret = std::string{}; - for (auto& init : out_inits) { - ret += init + ", "; + // If there are any pending statements, wedge them into + // this initializer using an immediately invoked lambda + auto& mem_inits = current_functions.back().prolog.mem_inits; + if (!pending_statements.empty()) + { + mem_inits.push_back(separator + object_name + "{ [&]() -> decltype(auto) {"); + for (auto statement : pending_statements) { + mem_inits.push_back( + " " + print_to_string(*statement, false) + ";" + ); + statement->emitted = true; } - out_inits = {}; - return ret; - }(); - - // If there were any, wedge them into this initializer - // using (holds nose) the comma operator and extra parens - // as we add this statement - if (!out_inits_with_commas.empty()) { - current_functions.back().prolog.mem_inits.push_back( - separator + - object_name + - "{(" + - out_inits_with_commas + - initializer + - " )}" - ); + pending_statements.clear(); + mem_inits.push_back(" return " + initializer + ";"); + mem_inits.push_back(" }() }"); } else { if (initializer == "{}") { initializer = ""; } - current_functions.back().prolog.mem_inits.push_back( - separator + - object_name + - "{ " + - initializer + - " }" - ); + mem_inits.push_back(separator + object_name + "{ " + initializer + " }"); } separator = ", "; } @@ -4735,11 +4790,6 @@ class cppfront ); return; } - - // Flush any possible remaining 'out' parameters - for (auto& init : out_inits) { - current_functions.back().prolog.statements.push_back(init + ";"); - } } // For a constructor, print the type name instead of the operator= function name diff --git a/source/reflect.h b/source/reflect.h index 1d8dfdef6..c558e4758 100644 --- a/source/reflect.h +++ b/source/reflect.h @@ -1063,7 +1063,7 @@ auto copyable(meta::type_declaration& t) -> void CPP2_UFCS(error, t, "this type is partially copyable/movable - when you provide any of the more-specific operator= signatures, you must also provide the one with the general signature (out this, that); alternatively, consider removing all the operator= functions and let them all be generated for you with default memberwise semantics"); } else {if (!(std::move(smfs).out_this_in_that)) { - CPP2_UFCS(require, t, CPP2_UFCS(add_member, t, "operator=: (out this, that) = { }"), + CPP2_UFCS(require, t, CPP2_UFCS(add_member, t, "operator=: (out this, that) = { this = that; }"), "could not add general operator=:(out this, that)"); }} } diff --git a/source/reflect.h2 b/source/reflect.h2 index 85aa6cc2c..d0f001263 100644 --- a/source/reflect.h2 +++ b/source/reflect.h2 @@ -597,7 +597,7 @@ copyable: (inout t: meta::type_declaration) = t.error( "this type is partially copyable/movable - when you provide any of the more-specific operator= signatures, you must also provide the one with the general signature (out this, that); alternatively, consider removing all the operator= functions and let them all be generated for you with default memberwise semantics" ); } else if !smfs.out_this_in_that { - t.require( t.add_member( "operator=: (out this, that) = { }"), + t.require( t.add_member( "operator=: (out this, that) = { this = that; }"), "could not add general operator=:(out this, that)"); } }