diff --git a/include/cpp2util.h b/include/cpp2util.h index ad4f3af5c5..3113090948 100644 --- a/include/cpp2util.h +++ b/include/cpp2util.h @@ -116,7 +116,7 @@ // in our -pure-cpp2 "import std;" simulation mode... if you need this, // use mixed mode (not -pure-cpp2) and #include all the headers you need // including this one - // + // // #include #ifdef __cpp_lib_expected #include @@ -526,7 +526,7 @@ template auto Typeid() -> decltype(auto) { #ifdef CPP2_NO_RTTI Type.expects( - !"'any' dynamic casting is disabled with -fno-rtti", // more likely to appear on console + !"'any' dynamic casting is disabled with -fno-rtti", // more likely to appear on console "'any' dynamic casting is disabled with -fno-rtti" // make message available to hooked handlers ); #else @@ -575,7 +575,7 @@ struct { template [[nodiscard]] auto cpp2_new(auto&& ...args) const -> std::shared_ptr { // Prefer { } to ( ) as noted for unique.new - // + // // Note this does mean we don't get the make_shared optimization a lot // of the time -- we can restore that as soon as make_shared improves to // allow list initialization. But the make_shared optimization isn't a @@ -745,13 +745,22 @@ class out { // //----------------------------------------------------------------------- // +// Workaround . +#define CPP2_FORCE_INLINE_LAMBDA_CLANG /* empty */ + #if defined(_MSC_VER) && !defined(__clang_major__) - #define CPP2_FORCE_INLINE __forceinline - #define CPP2_FORCE_INLINE_LAMBDA [[msvc::forceinline]] + #define CPP2_FORCE_INLINE __forceinline + #define CPP2_FORCE_INLINE_LAMBDA [[msvc::forceinline]] #define CPP2_LAMBDA_NO_DISCARD #else - #define CPP2_FORCE_INLINE __attribute__((always_inline)) - #define CPP2_FORCE_INLINE_LAMBDA __attribute__((always_inline)) + #define CPP2_FORCE_INLINE __attribute__((always_inline)) + #if defined(__clang__) + #define CPP2_FORCE_INLINE_LAMBDA /* empty */ + #undef CPP2_FORCE_INLINE_LAMBDA_CLANG + #define CPP2_FORCE_INLINE_LAMBDA_CLANG __attribute__((always_inline)) + #else + #define CPP2_FORCE_INLINE_LAMBDA __attribute__((always_inline)) + #endif #if defined(__clang_major__) // Also check __cplusplus, only to satisfy Clang -pedantic-errors @@ -776,85 +785,45 @@ class out { #endif #endif +#define CPP2_UFCS_IS_NOTHROW(TEMPKW,...) \ + requires { requires requires { std::declval().TEMPKW __VA_ARGS__(std::declval()...); }; \ + requires noexcept(std::declval().TEMPKW __VA_ARGS__(std::declval()...)); } \ +|| requires { requires !requires { std::declval().TEMPKW __VA_ARGS__(std::declval()...); }; \ + requires noexcept(__VA_ARGS__(std::declval(), std::declval()...)); } +#define CPP2_UFCS_IS_NOTHROW_PARAM(TEMPKW,...) /*empty*/ +#define CPP2_UFCS_IS_NOTHROW_ARG(TEMPKW,...) CPP2_UFCS_IS_NOTHROW(TEMPKW,__VA_ARGS__) +#if defined(__GNUC__) && !defined(__clang__) + // Workaround . + // This isn't the default because Clang also ICEs on an application. + #undef CPP2_UFCS_IS_NOTHROW_PARAM + #undef CPP2_UFCS_IS_NOTHROW_ARG + #define CPP2_UFCS_IS_NOTHROW_PARAM(TEMPKW,...) , bool IsNothrow = CPP2_UFCS_IS_NOTHROW(TEMPKW,__VA_ARGS__) + #define CPP2_UFCS_IS_NOTHROW_ARG(TEMPKW,...) IsNothrow + #if __GNUC__ < 11 + #undef CPP2_UFCS_IS_NOTHROW_PARAM + #undef CPP2_UFCS_IS_NOTHROW_ARG + #define CPP2_UFCS_IS_NOTHROW_PARAM(...) /*empty*/ + #define CPP2_UFCS_IS_NOTHROW_ARG(...) false // GCC 10 UFCS is always potentially-throwing. + #endif +#endif -// Note: [&] is because a nested UFCS might be viewed as trying to capture 'this' - -#define CPP2_UFCS(FUNCNAME,PARAM1,...) \ -[&] CPP2_LAMBDA_NO_DISCARD (auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \ - if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(CPP2_FORWARD(params)...); }) { \ - return CPP2_FORWARD(obj).FUNCNAME(CPP2_FORWARD(params)...); \ - } else { \ - return FUNCNAME(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \ - } \ -}(PARAM1, __VA_ARGS__) - -#define CPP2_UFCS_0(FUNCNAME,PARAM1) \ -[&] CPP2_LAMBDA_NO_DISCARD (auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \ - if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(); }) { \ - return CPP2_FORWARD(obj).FUNCNAME(); \ - } else { \ - return FUNCNAME(CPP2_FORWARD(obj)); \ - } \ -}(PARAM1) - -#define CPP2_UFCS_REMPARENS(...) __VA_ARGS__ - -#define CPP2_UFCS_TEMPLATE(FUNCNAME,TEMPARGS,PARAM1,...) \ -[&] CPP2_LAMBDA_NO_DISCARD (auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \ - if constexpr (requires{ CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(params)...); }) { \ - return CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(params)...); \ - } else { \ - return FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \ - } \ -}(PARAM1, __VA_ARGS__) - -#define CPP2_UFCS_TEMPLATE_0(FUNCNAME,TEMPARGS,PARAM1) \ -[&] CPP2_LAMBDA_NO_DISCARD (auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \ - if constexpr (requires{ CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); }) { \ - return CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); \ - } else { \ - return FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(obj)); \ - } \ -}(PARAM1) - - -// But for non-local lambdas [&] is not allowed - -#define CPP2_UFCS_NONLOCAL(FUNCNAME,PARAM1,...) \ -[] CPP2_LAMBDA_NO_DISCARD (auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \ - if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(CPP2_FORWARD(params)...); }) { \ - return CPP2_FORWARD(obj).FUNCNAME(CPP2_FORWARD(params)...); \ - } else { \ - return FUNCNAME(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \ - } \ -}(PARAM1, __VA_ARGS__) - -#define CPP2_UFCS_0_NONLOCAL(FUNCNAME,PARAM1) \ -[] CPP2_LAMBDA_NO_DISCARD (auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \ - if constexpr (requires{ CPP2_FORWARD(obj).FUNCNAME(); }) { \ - return CPP2_FORWARD(obj).FUNCNAME(); \ - } else { \ - return FUNCNAME(CPP2_FORWARD(obj)); \ - } \ -}(PARAM1) - -#define CPP2_UFCS_TEMPLATE_NONLOCAL(FUNCNAME,TEMPARGS,PARAM1,...) \ -[] CPP2_LAMBDA_NO_DISCARD (auto&& obj, auto&& ...params) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \ - if constexpr (requires{ CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(params)...); }) { \ - return CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(params)...); \ +#define CPP2_UFCS_(LAMBDADEFCAPT,TEMPKW,...) \ +[LAMBDADEFCAPT] \ + CPP2_LAMBDA_NO_DISCARD (Obj&& obj, Params&& ...params) CPP2_FORCE_INLINE_LAMBDA_CLANG \ + noexcept(CPP2_UFCS_IS_NOTHROW_ARG(TEMPKW,__VA_ARGS__)) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) \ + requires requires { CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); } \ + || requires { __VA_ARGS__(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); } { \ + if constexpr (requires{ CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); }) { \ + return CPP2_FORWARD(obj).TEMPKW __VA_ARGS__(CPP2_FORWARD(params)...); \ } else { \ - return FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \ + return __VA_ARGS__(CPP2_FORWARD(obj), CPP2_FORWARD(params)...); \ } \ -}(PARAM1, __VA_ARGS__) +} -#define CPP2_UFCS_TEMPLATE_0_NONLOCAL(FUNCNAME,TEMPARGS,PARAM1) \ -[] CPP2_LAMBDA_NO_DISCARD (auto&& obj) CPP2_FORCE_INLINE_LAMBDA -> decltype(auto) { \ - if constexpr (requires{ CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); }) { \ - return CPP2_FORWARD(obj).template FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (); \ - } else { \ - return FUNCNAME CPP2_UFCS_REMPARENS TEMPARGS (CPP2_FORWARD(obj)); \ - } \ -}(PARAM1) +#define CPP2_UFCS(...) CPP2_UFCS_(&,,__VA_ARGS__) +#define CPP2_UFCS_TEMPLATE(...) CPP2_UFCS_(&,template,__VA_ARGS__) +#define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,,__VA_ARGS__) +#define CPP2_UFCS_TEMPLATE_NONLOCAL(...) CPP2_UFCS_(,template,__VA_ARGS__) //----------------------------------------------------------------------- @@ -914,7 +883,7 @@ inline auto to_string(std::string const& s) -> std::string const& template inline auto to_string(T const& sv) -> std::string - requires (std::is_convertible_v + requires (std::is_convertible_v && !std::is_convertible_v) { return std::string{sv}; @@ -1054,8 +1023,8 @@ auto is( X const& ) -> bool { template< typename C, typename X > requires ( - ( std::is_base_of_v || - ( std::is_polymorphic_v && std::is_polymorphic_v) + ( std::is_base_of_v || + ( std::is_polymorphic_v && std::is_polymorphic_v) ) && !std::is_same_v) auto is( X const& x ) -> bool { return Dynamic_cast(&x) != nullptr; @@ -1063,8 +1032,8 @@ auto is( X const& x ) -> bool { template< typename C, typename X > requires ( - ( std::is_base_of_v || - ( std::is_polymorphic_v && std::is_polymorphic_v) + ( std::is_base_of_v || + ( std::is_polymorphic_v && std::is_polymorphic_v) ) && !std::is_same_v) auto is( X const* x ) -> bool { return Dynamic_cast(x) != nullptr; @@ -1726,7 +1695,7 @@ constexpr auto unsafe_narrow( X&& x ) noexcept -> decltype(auto) // Returns a function object that takes a 'value' of the same type as // 'flags', and evaluates to true if and only if 'value' has set all of // the bits set in 'flags' -// +// //----------------------------------------------------------------------- // template diff --git a/regression-tests/mixed-bugfix-for-ufcs-non-local.cpp2 b/regression-tests/mixed-bugfix-for-ufcs-non-local.cpp2 new file mode 100644 index 0000000000..40496af061 --- /dev/null +++ b/regression-tests/mixed-bugfix-for-ufcs-non-local.cpp2 @@ -0,0 +1,43 @@ +namespace ns { + +template struct t { }; +constexpr bool f(const t&) { return true; } +constexpr t o{}; + +} // namespace ns + +ns: namespace = { + +// Variables. + +v0: <_: t> bool == false; // Fails on GCC ([GCC109781][]). + +v1: t == t(); // Fails on Clang 12 (lambda in unevaluated context). + +v2: bool == o.f(); + +// Functions. + +g: <_: t> () = { } // Fails on GCC ([GCC109781][]). + +g: (_: t) = { } // Fails on Clang 12 (lambda in unevaluated context). + +g: () pre(o.f()) = { } + +h: () -> t = o; // Fails on Clang 12 (lambda in unevaluated context). + +// Aliases. + +a: <_: t> type == bool; // Fails on GCC ([GCC109781][]). + +b: <_: t> _ == false; // Fails on GCC ([GCC109781][]). + +c: type == t; // Fails on Clang 12 (lambda in unevaluated context). + +d: _ == t(); // Fails on Clang 12 (lambda in unevaluated context). + +} // namespace ns + +main: () = { } + +// [GCC109781]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109781 diff --git a/regression-tests/pure2-bugfix-for-ufcs-arguments.cpp2 b/regression-tests/pure2-bugfix-for-ufcs-arguments.cpp2 new file mode 100644 index 0000000000..b154d2d17f --- /dev/null +++ b/regression-tests/pure2-bugfix-for-ufcs-arguments.cpp2 @@ -0,0 +1,51 @@ +print_res: (x: i32) -> i32 = { + std::cout << x; + if x == 9 { std::cout << '\n'; } + return x; +} + +t: @struct type = { + f: (inout this) -> i32 = print_res(0); + f: (inout this, _) -> i32 = print_res(1); + f: <_> (inout this) -> i32 = print_res(2); + f: <_> (inout this, _) -> i32 = print_res(3); + f: <_, U> (inout this, _, _) -> i32 = print_res(4); +} + +f: (_: t) -> i32 = print_res(5); +f: (_: t, _) -> i32 = print_res(6); +f: <_> (_: t) -> i32 = print_res(7); +f: <_> (_: t, _) -> i32 = print_res(8); +f: <_, U> (_: t, _, _) -> i32 = print_res(9); + +m: t = (); +n: const t = (); +a: <_, U> _ == n; + +_: i32 = m.f(); +_: i32 = m.f(0); +_: i32 = m.f(); +_: i32 = m.f(0); +_: i32 = m.f(0, 0); +_: i32 = n.f(); +_: i32 = n.f(0); +_: i32 = n.f(); +_: i32 = n.f(0); +_: i32 = n.f(0, 0); +_: i32 = a.f(0, 0); + +main: () = { + _ = m.f(); + _ = m.f(0); + _ = m.f(); + _ = m.f(0); + _ = m.f(0, 0); + _ = n.f(); + _ = n.f(0); + _ = n.f(); + _ = n.f(0); + _ = n.f(0, 0); + _ = a.f(0, 0); + + _ = :(a, f) = { _ = a.f(a).f(); }; +} diff --git a/regression-tests/pure2-bugfix-for-ufcs-name-lookup.cpp2 b/regression-tests/pure2-bugfix-for-ufcs-name-lookup.cpp2 new file mode 100644 index 0000000000..700e964552 --- /dev/null +++ b/regression-tests/pure2-bugfix-for-ufcs-name-lookup.cpp2 @@ -0,0 +1,107 @@ +identity: @struct type = { + operator(): (this, forward x) -> forward _ == x; +} + +t: @struct type = { + f: (this) -> int == 0; +} + +u: @struct type = { } + +ns: namespace = { +f: (_) -> int == 1; +} // namespace ns + +// v: @struct type = { +// f :== :(_) 0; // Pending on #706. +// g: (i) i.f(); +// } + +main: () = { + { + f := t().f(); + assert(f == 0); + } + { + f: _ = t().f(); + assert(f == 0); + } + (f := t().f()) assert(f == 0); + (f: _ = t().f()) assert(f == 0); + { + f :== t().f(); + static_assert(f == 0); + } + { + f: _ == t().f(); + static_assert(f == 0); + } + { + f := :(f) -> _ = { + assert(t().f() == 0); + return u().f(); + }(identity()); + _ = f; + } + { // Rejected by MSVC. + // f := : (copy _: std::integral_constant) -> _ = { + // assert(t().f() == 0); + // return u().f(); + // }(:std::integral_constant = ()); + // _ = f; + } + { + f := :() = { + (f: identity = identity()) assert(t().f() == 0); + (f: identity = identity()) _ = u().f(); + }; + _ = f; + } + { + f := :() = { + using ns::f; + static_assert(t().f() == 0); + static_assert(u().f() == 1); + }; + _ = f; + } + { + f := :() = { + static_assert(t().f() == 0); + g := : (_: T) -> std::void_t = {}; + static_assert(!std::is_invocable_v); + using ns::f; + }; + _ = f; + } + { + f := :() = { + using ns::f; + _ = :() = { + static_assert(t().f() == 0); + static_assert(u().f() == 1); + }; + { + static_assert(t().f() == 0); + static_assert(u().f() == 1); + } + }; + _ = f; + } + { + f := :() = { + _ = :() = { + static_assert(t().f() == 0); + g := : (_: T) -> std::void_t = {}; + static_assert(!std::is_invocable_v); + }; + { + static_assert(t().f() == 0); + g := : (_: T) -> std::void_t = {}; + static_assert(!std::is_invocable_v); + } + using ns::f; + }; + _ = f; + } +} diff --git a/regression-tests/pure2-bugfix-for-ufcs-noexcept.cpp2 b/regression-tests/pure2-bugfix-for-ufcs-noexcept.cpp2 new file mode 100644 index 0000000000..b92059d2c8 --- /dev/null +++ b/regression-tests/pure2-bugfix-for-ufcs-noexcept.cpp2 @@ -0,0 +1,6 @@ +t: type = { + swap: (virtual inout this, that) = { } // Non-`virtual` blocked on #508, idiomatic form on #507. +} +main: () = { + static_assert(noexcept(t().swap(t()))); // Fails on Clang 12 (lambda in unevaluated context). +} diff --git a/regression-tests/pure2-bugfix-for-ufcs-sfinae.cpp2 b/regression-tests/pure2-bugfix-for-ufcs-sfinae.cpp2 new file mode 100644 index 0000000000..fbd6edb5c6 --- /dev/null +++ b/regression-tests/pure2-bugfix-for-ufcs-sfinae.cpp2 @@ -0,0 +1,8 @@ +f: () -> std::type_identity_t = { } // Fails on Clang 12 (lambda in unevaluated context). + +B: type = { } + +main: () = { + g := : (_: T) -> std::void_t())> = {}; + static_assert(!std::is_invocable_v); +} diff --git a/regression-tests/test-results/clang-18/mixed-bugfix-for-ufcs-non-local.cpp.execution b/regression-tests/test-results/clang-18/mixed-bugfix-for-ufcs-non-local.cpp.execution new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/clang-18/mixed-bugfix-for-ufcs-non-local.cpp.output b/regression-tests/test-results/clang-18/mixed-bugfix-for-ufcs-non-local.cpp.output new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-arguments.cpp.execution b/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-arguments.cpp.execution new file mode 100644 index 0000000000..0e41b78197 --- /dev/null +++ b/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-arguments.cpp.execution @@ -0,0 +1,4 @@ +0123456789 +9 +0123456789 +9 diff --git a/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-arguments.cpp.output b/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-arguments.cpp.output new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-name-lookup.cpp.execution b/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-name-lookup.cpp.execution new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-name-lookup.cpp.output b/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-name-lookup.cpp.output new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-noexcept.cpp.execution b/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-noexcept.cpp.execution new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-noexcept.cpp.output b/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-noexcept.cpp.output new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-sfinae.cpp.execution b/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-sfinae.cpp.execution new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-sfinae.cpp.output b/regression-tests/test-results/clang-18/pure2-bugfix-for-ufcs-sfinae.cpp.output new file mode 100644 index 0000000000..e69de29bb2 diff --git a/regression-tests/test-results/mixed-bounds-check.cpp b/regression-tests/test-results/mixed-bounds-check.cpp index 70c25cd1f6..91c26a71d4 100644 --- a/regression-tests/test-results/mixed-bounds-check.cpp +++ b/regression-tests/test-results/mixed-bounds-check.cpp @@ -26,7 +26,7 @@ std::set_terminate(std::abort); std::vector v {1, 2, 3, 4, 5, -999}; - CPP2_UFCS_0(pop_back, v); + CPP2_UFCS(pop_back)(v); std::cout << CPP2_ASSERT_IN_BOUNDS(std::move(v), 5) << "\n"; } diff --git a/regression-tests/test-results/mixed-bounds-safety-with-assert-2.cpp b/regression-tests/test-results/mixed-bounds-safety-with-assert-2.cpp index 25537d4d8a..b23b224459 100644 --- a/regression-tests/test-results/mixed-bounds-safety-with-assert-2.cpp +++ b/regression-tests/test-results/mixed-bounds-safety-with-assert-2.cpp @@ -40,7 +40,7 @@ auto add_42_to_subrange(auto& rng, cpp2::in start, cpp2::in end) -> vo auto add_42_to_subrange(auto& rng, cpp2::in start, cpp2::in end) -> void { cpp2::Bounds.expects(cpp2::cmp_less_eq(0,start), ""); - cpp2::Bounds.expects(cpp2::cmp_less_eq(end,CPP2_UFCS_0(ssize, rng)), ""); + cpp2::Bounds.expects(cpp2::cmp_less_eq(end,CPP2_UFCS(ssize)(rng)), ""); auto count {0}; for ( diff --git a/regression-tests/test-results/mixed-bounds-safety-with-assert.cpp b/regression-tests/test-results/mixed-bounds-safety-with-assert.cpp index 28376f1cfa..3f1c032b66 100644 --- a/regression-tests/test-results/mixed-bounds-safety-with-assert.cpp +++ b/regression-tests/test-results/mixed-bounds-safety-with-assert.cpp @@ -38,7 +38,7 @@ auto print_subrange(auto const& rng, cpp2::in start, cpp2::in end) -> auto print_subrange(auto const& rng, cpp2::in start, cpp2::in end) -> void{ cpp2::Bounds.expects(cpp2::cmp_less_eq(0,start), ""); - cpp2::Bounds.expects(cpp2::cmp_less_eq(end,CPP2_UFCS_0(ssize, rng)), ""); + cpp2::Bounds.expects(cpp2::cmp_less_eq(end,CPP2_UFCS(ssize)(rng)), ""); auto count {0}; for ( diff --git a/regression-tests/test-results/mixed-bugfix-for-ufcs-non-local.cpp b/regression-tests/test-results/mixed-bugfix-for-ufcs-non-local.cpp new file mode 100644 index 0000000000..fddc73198b --- /dev/null +++ b/regression-tests/test-results/mixed-bugfix-for-ufcs-non-local.cpp @@ -0,0 +1,88 @@ + + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "mixed-bugfix-for-ufcs-non-local.cpp2" + +#line 9 "mixed-bugfix-for-ufcs-non-local.cpp2" +namespace ns { + +#line 39 "mixed-bugfix-for-ufcs-non-local.cpp2" +} + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "mixed-bugfix-for-ufcs-non-local.cpp2" +namespace ns { + +template struct t { }; +constexpr bool f(const t&) { return true; } +constexpr t o{}; + +} // namespace ns + +#line 9 "mixed-bugfix-for-ufcs-non-local.cpp2" +namespace ns { + +// Variables. + +template _> bool inline constexpr v0 = false;// Fails on GCC ([GCC109781][]). + +t inline constexpr v1 = t();// Fails on Clang 12 (lambda in unevaluated context). + +bool inline constexpr v2 = CPP2_UFCS_NONLOCAL(f)(o); + +// Functions. + +template _> auto g() -> void; + +auto g([[maybe_unused]] cpp2::in> unnamed_param_1) -> void; + +auto g() -> void; + +[[nodiscard]] auto h() -> t; + +// Aliases. + +template _> using a = bool;// Fails on GCC ([GCC109781][]). + +template _> auto inline constexpr b = false;// Fails on GCC ([GCC109781][]). + +using c = t;// Fails on Clang 12 (lambda in unevaluated context). + +auto inline constexpr d = t();// Fails on Clang 12 (lambda in unevaluated context). + +} // namespace ns + +auto main() -> int; + +// [GCC109781]: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109781 + + +//=== Cpp2 function definitions ================================================= + +#line 1 "mixed-bugfix-for-ufcs-non-local.cpp2" + +#line 9 "mixed-bugfix-for-ufcs-non-local.cpp2" +namespace ns { + +#line 21 "mixed-bugfix-for-ufcs-non-local.cpp2" +template _> auto g() -> void{}// Fails on GCC ([GCC109781][]). + +auto g([[maybe_unused]] cpp2::in> unnamed_param_1) -> void{}// Fails on Clang 12 (lambda in unevaluated context). + +auto g() -> void{ + cpp2::Default.expects(CPP2_UFCS_NONLOCAL(f)(o), ""); } + +#line 27 "mixed-bugfix-for-ufcs-non-local.cpp2" +[[nodiscard]] auto h() -> t { return o; }// Fails on Clang 12 (lambda in unevaluated context). + +#line 39 "mixed-bugfix-for-ufcs-non-local.cpp2" +} + +auto main() -> int{} + diff --git a/regression-tests/test-results/mixed-bugfix-for-ufcs-non-local.cpp2.output b/regression-tests/test-results/mixed-bugfix-for-ufcs-non-local.cpp2.output new file mode 100644 index 0000000000..560fb3c5c0 --- /dev/null +++ b/regression-tests/test-results/mixed-bugfix-for-ufcs-non-local.cpp2.output @@ -0,0 +1,2 @@ +mixed-bugfix-for-ufcs-non-local.cpp2... ok (mixed Cpp1/Cpp2, Cpp2 code passes safety checks) + diff --git a/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp b/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp index c8d25f39ca..289b277f08 100644 --- a/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp +++ b/regression-tests/test-results/mixed-captures-in-expressions-and-postconditions.cpp @@ -47,9 +47,9 @@ auto insert_at(cpp2::in where, cpp2::in val) -> void #line 22 "mixed-captures-in-expressions-and-postconditions.cpp2" { cpp2::finally_presuccess cpp2_finally_presuccess; - cpp2::Default.expects(cpp2::cmp_less_eq(0,where) && cpp2::cmp_less_eq(where,CPP2_UFCS_0(ssize, vec)), ""); - cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS_0(ssize, vec)]{cpp2::Default.expects(CPP2_UFCS_0(ssize, vec) == _1 + 1, "");} ); + cpp2::Default.expects(cpp2::cmp_less_eq(0,where) && cpp2::cmp_less_eq(where,CPP2_UFCS_NONLOCAL(ssize)(vec)), ""); + cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS_NONLOCAL(ssize)(vec)]{cpp2::Default.expects(CPP2_UFCS_NONLOCAL(ssize)(vec) == _1 + 1, "");} ); #line 23 "mixed-captures-in-expressions-and-postconditions.cpp2" - static_cast(CPP2_UFCS(insert, vec, CPP2_UFCS_0(begin, vec) + where, val)); + static_cast(CPP2_UFCS(insert)(vec, CPP2_UFCS(begin)(vec) + where, val)); } diff --git a/regression-tests/test-results/mixed-fixed-type-aliases.cpp b/regression-tests/test-results/mixed-fixed-type-aliases.cpp index f73fa042d2..9fb424959e 100644 --- a/regression-tests/test-results/mixed-fixed-type-aliases.cpp +++ b/regression-tests/test-results/mixed-fixed-type-aliases.cpp @@ -57,7 +57,7 @@ auto test(auto const& x) -> void{ test(std::move(z)); for ( auto const& arg : args ) - std::cout << CPP2_UFCS_0(filename, std::filesystem::path(arg)) << "\n"; + std::cout << CPP2_UFCS(filename)(std::filesystem::path(arg)) << "\n"; std::cout << cpp2::to_string(mytype::myvalue) + "\n"; } diff --git a/regression-tests/test-results/mixed-function-expression-with-pointer-capture.cpp b/regression-tests/test-results/mixed-function-expression-with-pointer-capture.cpp index 6e3df47f93..a9a5d06ff6 100644 --- a/regression-tests/test-results/mixed-function-expression-with-pointer-capture.cpp +++ b/regression-tests/test-results/mixed-function-expression-with-pointer-capture.cpp @@ -32,7 +32,7 @@ std::string y {"\n"}; std::ranges::for_each(vec, [_0 = (&y)](auto const& x) -> void { - std::cout << CPP2_UFCS_0(c_str, (*cpp2::assert_not_null(_0))) << x << *cpp2::assert_not_null(_0); } + std::cout << CPP2_UFCS(c_str)((*cpp2::assert_not_null(_0))) << x << *cpp2::assert_not_null(_0); } ); auto callback {[](auto& x) -> void { x += "-ish"; }}; diff --git a/regression-tests/test-results/mixed-initialization-safety-3-contract-violation.cpp b/regression-tests/test-results/mixed-initialization-safety-3-contract-violation.cpp index 59273a7443..5fca33a0a8 100644 --- a/regression-tests/test-results/mixed-initialization-safety-3-contract-violation.cpp +++ b/regression-tests/test-results/mixed-initialization-safety-3-contract-violation.cpp @@ -61,9 +61,9 @@ auto fill( ) -> void { - cpp2::Default.expects(cpp2::cmp_greater_eq(CPP2_UFCS_0(ssize, value),count), "fill: value must contain at least count elements"); + cpp2::Default.expects(cpp2::cmp_greater_eq(CPP2_UFCS_NONLOCAL(ssize)(value),count), "fill: value must contain at least count elements"); #line 25 "mixed-initialization-safety-3-contract-violation.cpp2" - x.construct(CPP2_UFCS(substr, value, 0, count)); + x.construct(CPP2_UFCS(substr)(value, 0, count)); } auto print_decorated(auto const& x) -> void { std::cout << ">> [" << x << "]\n"; } diff --git a/regression-tests/test-results/mixed-initialization-safety-3.cpp b/regression-tests/test-results/mixed-initialization-safety-3.cpp index 537ad68968..eea1361ee4 100644 --- a/regression-tests/test-results/mixed-initialization-safety-3.cpp +++ b/regression-tests/test-results/mixed-initialization-safety-3.cpp @@ -55,9 +55,9 @@ auto fill( ) -> void { - cpp2::Default.expects(cpp2::cmp_greater_eq(CPP2_UFCS_0(ssize, value),count), "fill: value must contain at least count elements"); + cpp2::Default.expects(cpp2::cmp_greater_eq(CPP2_UFCS_NONLOCAL(ssize)(value),count), "fill: value must contain at least count elements"); #line 23 "mixed-initialization-safety-3.cpp2" - x.construct(CPP2_UFCS(substr, value, 0, count)); + x.construct(CPP2_UFCS(substr)(value, 0, count)); } auto print_decorated(auto const& x) -> void { std::cout << ">> [" << x << "]\n"; } diff --git a/regression-tests/test-results/mixed-lifetime-safety-and-null-contracts.cpp b/regression-tests/test-results/mixed-lifetime-safety-and-null-contracts.cpp index 20f619d6f2..6695daa92d 100644 --- a/regression-tests/test-results/mixed-lifetime-safety-and-null-contracts.cpp +++ b/regression-tests/test-results/mixed-lifetime-safety-and-null-contracts.cpp @@ -34,7 +34,7 @@ auto call_my_framework(char const* msg) -> void; #line 6 "mixed-lifetime-safety-and-null-contracts.cpp2" [[nodiscard]] auto main() -> int{ - CPP2_UFCS(set_handler, cpp2::Null, &call_my_framework); + CPP2_UFCS(set_handler)(cpp2::Null, &call_my_framework); try_pointer_stuff(); std::cout << "done\n"; } diff --git a/regression-tests/test-results/mixed-postexpression-with-capture.cpp b/regression-tests/test-results/mixed-postexpression-with-capture.cpp index 786216c8b5..c3e6d70f1d 100644 --- a/regression-tests/test-results/mixed-postexpression-with-capture.cpp +++ b/regression-tests/test-results/mixed-postexpression-with-capture.cpp @@ -58,10 +58,10 @@ auto insert_at(cpp2::in where, cpp2::in val) -> void #line 19 "mixed-postexpression-with-capture.cpp2" { cpp2::finally_presuccess cpp2_finally_presuccess; - cpp2::Default.expects(cpp2::cmp_less_eq(0,where) && cpp2::cmp_less_eq(where,CPP2_UFCS_0(ssize, vec)), ""); - cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS_0(size, vec)]{cpp2::Default.expects(CPP2_UFCS_0(size, vec) == _1 + 1, "");} ); + cpp2::Default.expects(cpp2::cmp_less_eq(0,where) && cpp2::cmp_less_eq(where,CPP2_UFCS_NONLOCAL(ssize)(vec)), ""); + cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS_NONLOCAL(size)(vec)]{cpp2::Default.expects(CPP2_UFCS_NONLOCAL(size)(vec) == _1 + 1, "");} ); #line 20 "mixed-postexpression-with-capture.cpp2" - CPP2_UFCS(push_back, vec, val); + CPP2_UFCS(push_back)(vec, val); } [[nodiscard]] auto make_string() -> make_string_ret @@ -69,7 +69,7 @@ auto insert_at(cpp2::in where, cpp2::in val) -> void { cpp2::finally_presuccess cpp2_finally_presuccess; std::string ret {"xyzzy"}; - cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS_0(length, ret)]{cpp2::Default.expects(CPP2_UFCS_0(length, ret) == _1 + 5, "");} ); + cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS_NONLOCAL(length)(ret)]{cpp2::Default.expects(CPP2_UFCS_NONLOCAL(length)(ret) == _1 + 5, "");} ); #line 26 "mixed-postexpression-with-capture.cpp2" ret += " and "; cpp2_finally_presuccess.run(); return std::move(ret); } @@ -81,7 +81,7 @@ cpp2_finally_presuccess.run(); return std::move(ret); } cpp2::finally_presuccess cpp2_finally_presuccess; std::string a {"xyzzy"}; std::string b {"plugh"}; -cpp2_finally_presuccess.add([&]{cpp2::Default.expects([_0 = CPP2_UFCS_0(length, a), _1 = CPP2_UFCS_0(length, b), _2 = 5]{ return _0==_1 && _1==_2; }(), "");} ); +cpp2_finally_presuccess.add([&]{cpp2::Default.expects([_0 = CPP2_UFCS_NONLOCAL(length)(a), _1 = CPP2_UFCS_NONLOCAL(length)(b), _2 = 5]{ return _0==_1 && _1==_2; }(), "");} ); #line 30 "mixed-postexpression-with-capture.cpp2" cpp2_finally_presuccess.run(); return { std::move(a), std::move(b) }; diff --git a/regression-tests/test-results/mixed-postfix-expression-custom-formatting.cpp b/regression-tests/test-results/mixed-postfix-expression-custom-formatting.cpp index 57ca722e6a..84d7c27a7f 100644 --- a/regression-tests/test-results/mixed-postfix-expression-custom-formatting.cpp +++ b/regression-tests/test-results/mixed-postfix-expression-custom-formatting.cpp @@ -29,12 +29,12 @@ auto call([[maybe_unused]] auto const& unnamed_param_1, [[maybe_unused]] auto co [[nodiscard]] auto test(auto const& a) -> std::string{ return call(a, - ++*cpp2::assert_not_null(CPP2_UFCS(b, a, a.c)), "hello", /* polite + ++*cpp2::assert_not_null(CPP2_UFCS(b)(a, a.c)), "hello", /* polite greeting goes here */" there", - CPP2_UFCS(e, a.d, ++CPP2_UFCS_0(g, *cpp2::assert_not_null(a.f)), // because f is foobar - CPP2_UFCS_0(i, a.h), - CPP2_UFCS(j, a, a.k, a.l)) + CPP2_UFCS(e)(a.d, ++CPP2_UFCS(g)(*cpp2::assert_not_null(a.f)), // because f is foobar + CPP2_UFCS(i)(a.h), + CPP2_UFCS(j)(a, a.k, a.l)) ); } diff --git a/regression-tests/test-results/mixed-string-interpolation.cpp b/regression-tests/test-results/mixed-string-interpolation.cpp index 336af2ac2d..322f0bd1ff 100644 --- a/regression-tests/test-results/mixed-string-interpolation.cpp +++ b/regression-tests/test-results/mixed-string-interpolation.cpp @@ -32,7 +32,7 @@ struct custom_struct_with_no_stringize_customization { } custom; std::cout << "a = " + cpp2::to_string(a) + ", b = " + cpp2::to_string(b) + "\n"; b = 42; - std::cout << "a^2 + b = " + cpp2::to_string(a * std::move(a) + CPP2_UFCS_0(value, std::move(b))) + "\n"; + std::cout << "a^2 + b = " + cpp2::to_string(a * std::move(a) + CPP2_UFCS(value)(std::move(b))) + "\n"; std::string_view sv {"my string_view"}; std::cout << "sv = " + cpp2::to_string(std::move(sv)) + "\n"; diff --git a/regression-tests/test-results/mixed-type-safety-1.cpp b/regression-tests/test-results/mixed-type-safety-1.cpp index a1e4b43a86..6f77b35e69 100644 --- a/regression-tests/test-results/mixed-type-safety-1.cpp +++ b/regression-tests/test-results/mixed-type-safety-1.cpp @@ -57,7 +57,7 @@ auto print(cpp2::in msg, cpp2::in b) -> void print( "1 is int? ", cpp2::is(1)); auto c {cpp2_new()}; // safe by construction - Shape* s {CPP2_UFCS_0(get, std::move(c))}; // safe by Lifetime + Shape* s {CPP2_UFCS(get)(std::move(c))}; // safe by Lifetime print("\ns* is Shape? ", cpp2::is(*cpp2::assert_not_null(s))); print( "s* is Circle? ", cpp2::is(*cpp2::assert_not_null(s))); print( "s* is Square? ", cpp2::is(*cpp2::assert_not_null(std::move(s)))); diff --git a/regression-tests/test-results/mixed-ufcs-multiple-template-arguments.cpp b/regression-tests/test-results/mixed-ufcs-multiple-template-arguments.cpp index 35d8198584..b0e49b28a7 100644 --- a/regression-tests/test-results/mixed-ufcs-multiple-template-arguments.cpp +++ b/regression-tests/test-results/mixed-ufcs-multiple-template-arguments.cpp @@ -41,6 +41,6 @@ struct X { std::cout << substr<4,8>(test_string) << "\n"; X x {std::move(test_string)}; - std::cout << CPP2_UFCS_TEMPLATE_0(substr, (<4,8>), std::move(x)) << "\n"; + std::cout << CPP2_UFCS_TEMPLATE(substr<4,8>)(std::move(x)) << "\n"; } diff --git a/regression-tests/test-results/pure2-bounds-safety-span.cpp b/regression-tests/test-results/pure2-bounds-safety-span.cpp index fe8957d96f..17966588e7 100644 --- a/regression-tests/test-results/pure2-bounds-safety-span.cpp +++ b/regression-tests/test-results/pure2-bounds-safety-span.cpp @@ -35,7 +35,7 @@ auto print_and_decorate(auto const& thing) -> void; static_cast(std::move(words)); auto i {0}; - for( ; cpp2::cmp_less(i,CPP2_UFCS_0(ssize, s)); ++i ) { + for( ; cpp2::cmp_less(i,CPP2_UFCS(ssize)(s)); ++i ) { print_and_decorate(CPP2_ASSERT_IN_BOUNDS(s, i)); } } diff --git a/regression-tests/test-results/pure2-bugfix-for-ufcs-arguments.cpp b/regression-tests/test-results/pure2-bugfix-for-ufcs-arguments.cpp new file mode 100644 index 0000000000..89a847e093 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-ufcs-arguments.cpp @@ -0,0 +1,108 @@ + +#define CPP2_IMPORT_STD Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-bugfix-for-ufcs-arguments.cpp2" + +#line 7 "pure2-bugfix-for-ufcs-arguments.cpp2" +class t; + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-bugfix-for-ufcs-arguments.cpp2" +[[nodiscard]] auto print_res(cpp2::in x) -> cpp2::i32; + +#line 7 "pure2-bugfix-for-ufcs-arguments.cpp2" +class t { + public: [[nodiscard]] auto f() & -> cpp2::i32; + public: [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32; + public: template [[nodiscard]] auto f() & -> cpp2::i32; + public: template [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32; + public: template [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) & -> cpp2::i32; +}; + +[[nodiscard]] auto f([[maybe_unused]] cpp2::in unnamed_param_1) -> cpp2::i32; +[[nodiscard]] auto f([[maybe_unused]] cpp2::in unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32; +template [[nodiscard]] auto f([[maybe_unused]] cpp2::in unnamed_param_1) -> cpp2::i32; +template [[nodiscard]] auto f([[maybe_unused]] cpp2::in unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32; +template [[nodiscard]] auto f([[maybe_unused]] cpp2::in unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) -> cpp2::i32; + +extern t m; +extern t const n; +template auto inline constexpr a = n; + +extern cpp2::i32 auto_25_1; +extern cpp2::i32 auto_26_1; +extern cpp2::i32 auto_27_1; +extern cpp2::i32 auto_28_1; +extern cpp2::i32 auto_29_1; +extern cpp2::i32 auto_30_1; +extern cpp2::i32 auto_31_1; +extern cpp2::i32 auto_32_1; +extern cpp2::i32 auto_33_1; +extern cpp2::i32 auto_34_1; +extern cpp2::i32 auto_35_1; + +auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-bugfix-for-ufcs-arguments.cpp2" +[[nodiscard]] auto print_res(cpp2::in x) -> cpp2::i32{ +#line 2 "pure2-bugfix-for-ufcs-arguments.cpp2" + std::cout << x; + if (x == 9) {std::cout << '\n'; } + return x; +} + +#line 8 "pure2-bugfix-for-ufcs-arguments.cpp2" + [[nodiscard]] auto t::f() & -> cpp2::i32 { return print_res(0); } + [[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32 { return print_res(1); } + template [[nodiscard]] auto t::f() & -> cpp2::i32 { return print_res(2); } + template [[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2) & -> cpp2::i32 { return print_res(3); } + template [[nodiscard]] auto t::f([[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) & -> cpp2::i32 { return print_res(4); } + +#line 15 "pure2-bugfix-for-ufcs-arguments.cpp2" +[[nodiscard]] auto f([[maybe_unused]] cpp2::in unnamed_param_1) -> cpp2::i32 { return print_res(5); } +[[nodiscard]] auto f([[maybe_unused]] cpp2::in unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32 { return print_res(6); } +template [[nodiscard]] auto f([[maybe_unused]] cpp2::in unnamed_param_1) -> cpp2::i32 { return print_res(7); } +template [[nodiscard]] auto f([[maybe_unused]] cpp2::in unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2) -> cpp2::i32 { return print_res(8); } +template [[nodiscard]] auto f([[maybe_unused]] cpp2::in unnamed_param_1, [[maybe_unused]] auto const& unnamed_param_2, [[maybe_unused]] auto const& unnamed_param_3) -> cpp2::i32 { return print_res(9); } + +t m {}; +t const n {}; + +#line 25 "pure2-bugfix-for-ufcs-arguments.cpp2" +cpp2::i32 auto_25_1 {CPP2_UFCS_NONLOCAL(f)(m)}; +cpp2::i32 auto_26_1 {CPP2_UFCS_NONLOCAL(f)(m, 0)}; +cpp2::i32 auto_27_1 {CPP2_UFCS_TEMPLATE_NONLOCAL(f)(m)}; +cpp2::i32 auto_28_1 {CPP2_UFCS_TEMPLATE_NONLOCAL(f)(m, 0)}; +cpp2::i32 auto_29_1 {CPP2_UFCS_TEMPLATE_NONLOCAL(f)(m, 0, 0)}; +cpp2::i32 auto_30_1 {CPP2_UFCS_NONLOCAL(f)(n)}; +cpp2::i32 auto_31_1 {CPP2_UFCS_NONLOCAL(f)(n, 0)}; +cpp2::i32 auto_32_1 {CPP2_UFCS_TEMPLATE_NONLOCAL(f)(n)}; +cpp2::i32 auto_33_1 {CPP2_UFCS_TEMPLATE_NONLOCAL(f)(n, 0)}; +cpp2::i32 auto_34_1 {CPP2_UFCS_TEMPLATE_NONLOCAL(f)(n, 0, 0)}; +cpp2::i32 auto_35_1 {CPP2_UFCS_TEMPLATE_NONLOCAL(f)(a, 0, 0)}; + +auto main() -> int{ + static_cast(CPP2_UFCS(f)(m)); + static_cast(CPP2_UFCS(f)(m, 0)); + static_cast(CPP2_UFCS_TEMPLATE(f)(m)); + static_cast(CPP2_UFCS_TEMPLATE(f)(m, 0)); + static_cast(CPP2_UFCS_TEMPLATE(f)(m, 0, 0)); + static_cast(CPP2_UFCS(f)(n)); + static_cast(CPP2_UFCS(f)(n, 0)); + static_cast(CPP2_UFCS_TEMPLATE(f)(n)); + static_cast(CPP2_UFCS_TEMPLATE(f)(n, 0)); + static_cast(CPP2_UFCS_TEMPLATE(f)(n, 0, 0)); + static_cast(CPP2_UFCS_TEMPLATE(f)(a, 0, 0)); + + static_cast([](auto const& a, auto const& f) -> void{static_cast(CPP2_UFCS(f)(CPP2_UFCS(f)(a, a))); }); +} + diff --git a/regression-tests/test-results/pure2-bugfix-for-ufcs-arguments.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-ufcs-arguments.cpp2.output new file mode 100644 index 0000000000..e230534bf5 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-ufcs-arguments.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-ufcs-arguments.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/test-results/pure2-bugfix-for-ufcs-name-lookup.cpp b/regression-tests/test-results/pure2-bugfix-for-ufcs-name-lookup.cpp new file mode 100644 index 0000000000..ec5029ab5f --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-ufcs-name-lookup.cpp @@ -0,0 +1,173 @@ + +#define CPP2_IMPORT_STD Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-bugfix-for-ufcs-name-lookup.cpp2" +class identity; +#line 2 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + + +#line 5 "pure2-bugfix-for-ufcs-name-lookup.cpp2" +class t; + + +#line 9 "pure2-bugfix-for-ufcs-name-lookup.cpp2" +class u; + +namespace ns { + +} + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-bugfix-for-ufcs-name-lookup.cpp2" +class identity { +#line 2 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + public: [[nodiscard]] constexpr auto operator()(auto&& x) const& -> auto&&; +}; + +class t { + public: [[nodiscard]] constexpr auto f() const& -> int; +}; + +class u {}; + +namespace ns { +[[nodiscard]] constexpr auto f([[maybe_unused]] auto const& unnamed_param_1) -> int; +} // namespace ns + +// v: @struct type = { +// f :== :(_) 0; // Pending on #706. +// g: (i) i.f(); +// } + +auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + +#line 2 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + [[nodiscard]] constexpr auto identity::operator()(auto&& x) const& -> auto&& { return CPP2_FORWARD(x); } + +#line 6 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + [[nodiscard]] constexpr auto t::f() const& -> int { return 0; } + +#line 11 "pure2-bugfix-for-ufcs-name-lookup.cpp2" +namespace ns { +[[nodiscard]] constexpr auto f([[maybe_unused]] auto const& unnamed_param_1) -> int { return 1; } +} + +#line 20 "pure2-bugfix-for-ufcs-name-lookup.cpp2" +auto main() -> int{ + { + auto f {t().f()}; + cpp2::Default.expects(std::move(f) == 0, ""); + } + { + auto f {t().f()}; + cpp2::Default.expects(std::move(f) == 0, ""); + } +{ +auto const& f = t().f(); +#line 29 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + cpp2::Default.expects(f == 0, ""); +} +{ +auto const& f = t().f(); +#line 30 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + cpp2::Default.expects(f == 0, ""); +} +#line 31 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + { + auto constexpr f = t().f(); + static_assert(f == 0); + } + { + auto constexpr f = t().f(); + static_assert(f == 0); + } + { + auto f {[](auto const& f) -> auto{ + cpp2::Default.expects(CPP2_UFCS(f)(t()) == 0, ""); + return CPP2_UFCS(f)(u()); + }(identity())}; + static_cast(std::move(f)); + } + { // Rejected by MSVC. + // f := : (copy _: std::integral_constant) -> _ = { + // assert(t().f() == 0); + // return u().f(); + // }(:std::integral_constant = ()); + // _ = f; + } + { + auto f {[]() -> void{ +{ +cpp2::in f = identity(); +#line 55 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + cpp2::Default.expects(CPP2_UFCS(f)(t()) == 0, ""); +} +{ +cpp2::in f = identity(); +#line 56 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + static_cast(CPP2_UFCS(f)(u())); +} +#line 57 "pure2-bugfix-for-ufcs-name-lookup.cpp2" + }}; + static_cast(std::move(f)); + } + { + auto f {[]() -> void{ + using ns::f; + static_assert(CPP2_UFCS(f)(t()) == 0); + static_assert(CPP2_UFCS(f)(u()) == 1); + }}; + static_cast(std::move(f)); + } + { + auto f {[]() -> void{ + static_assert(t().f() == 0); + auto g {[]([[maybe_unused]] T const& unnamed_param_1) -> std::void_t{}}; + static_assert(!(std::is_invocable_v)); + using ns::f; + }}; + static_cast(std::move(f)); + } + { + auto f {[]() -> void{ + using ns::f; + static_cast([]() -> void{ + static_assert(CPP2_UFCS(f)(t()) == 0); + static_assert(CPP2_UFCS(f)(u()) == 1); + }); + { + static_assert(CPP2_UFCS(f)(t()) == 0); + static_assert(CPP2_UFCS(f)(u()) == 1); + } + }}; + static_cast(std::move(f)); + } + { + auto f {[]() -> void{ + static_cast([]() -> void{ + static_assert(t().f() == 0); + auto g {[]([[maybe_unused]] T const& unnamed_param_1) -> std::void_t{}}; + static_assert(!(std::is_invocable_v)); + }); + { + static_assert(t().f() == 0); + auto g {[]([[maybe_unused]] T const& unnamed_param_1) -> std::void_t{}}; + static_assert(!(std::is_invocable_v)); + } + using ns::f; + }}; + static_cast(std::move(f)); + } +} + diff --git a/regression-tests/test-results/pure2-bugfix-for-ufcs-name-lookup.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-ufcs-name-lookup.cpp2.output new file mode 100644 index 0000000000..3b1880cad2 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-ufcs-name-lookup.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-ufcs-name-lookup.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/test-results/pure2-bugfix-for-ufcs-noexcept.cpp b/regression-tests/test-results/pure2-bugfix-for-ufcs-noexcept.cpp new file mode 100644 index 0000000000..3082355f01 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-ufcs-noexcept.cpp @@ -0,0 +1,38 @@ + +#define CPP2_IMPORT_STD Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-bugfix-for-ufcs-noexcept.cpp2" +class t; +#line 2 "pure2-bugfix-for-ufcs-noexcept.cpp2" + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-bugfix-for-ufcs-noexcept.cpp2" +class t { +#line 2 "pure2-bugfix-for-ufcs-noexcept.cpp2" + public: virtual auto swap([[maybe_unused]] t const& that) noexcept -> void; + public: t() = default; + public: t(t const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(t const&) -> void = delete; + +#line 3 "pure2-bugfix-for-ufcs-noexcept.cpp2" +}; +auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-bugfix-for-ufcs-noexcept.cpp2" + +#line 2 "pure2-bugfix-for-ufcs-noexcept.cpp2" + auto t::swap([[maybe_unused]] t const& that) noexcept -> void{}// Non-`virtual` blocked on #508, idiomatic form on #507. + +auto main() -> int{ + static_assert(noexcept(CPP2_UFCS(swap)(t(), t())));// Fails on Clang 12 (lambda in unevaluated context). +} + diff --git a/regression-tests/test-results/pure2-bugfix-for-ufcs-noexcept.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-ufcs-noexcept.cpp2.output new file mode 100644 index 0000000000..6ff4d0ebb6 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-ufcs-noexcept.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-ufcs-noexcept.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/test-results/pure2-bugfix-for-ufcs-sfinae.cpp b/regression-tests/test-results/pure2-bugfix-for-ufcs-sfinae.cpp new file mode 100644 index 0000000000..e050b9ffe5 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-ufcs-sfinae.cpp @@ -0,0 +1,40 @@ + +#define CPP2_IMPORT_STD Yes + +//=== Cpp2 type declarations ==================================================== + + +#include "cpp2util.h" + +#line 1 "pure2-bugfix-for-ufcs-sfinae.cpp2" + +#line 3 "pure2-bugfix-for-ufcs-sfinae.cpp2" +class B; + + +//=== Cpp2 type definitions and function declarations =========================== + +#line 1 "pure2-bugfix-for-ufcs-sfinae.cpp2" +template [[nodiscard]] auto f() -> std::type_identity_t; + +#line 3 "pure2-bugfix-for-ufcs-sfinae.cpp2" +class B { + public: B() = default; + public: B(B const&) = delete; /* No 'that' constructor, suppress copy */ + public: auto operator=(B const&) -> void = delete; +}; +#line 4 "pure2-bugfix-for-ufcs-sfinae.cpp2" + +auto main() -> int; + +//=== Cpp2 function definitions ================================================= + +#line 1 "pure2-bugfix-for-ufcs-sfinae.cpp2" +template [[nodiscard]] auto f() -> std::type_identity_t{}// Fails on Clang 12 (lambda in unevaluated context). + +#line 5 "pure2-bugfix-for-ufcs-sfinae.cpp2" +auto main() -> int{ + auto g {[]([[maybe_unused]] T const& unnamed_param_1) -> std::void_t())>{}}; + static_assert(!(std::is_invocable_v)); +} + diff --git a/regression-tests/test-results/pure2-bugfix-for-ufcs-sfinae.cpp2.output b/regression-tests/test-results/pure2-bugfix-for-ufcs-sfinae.cpp2.output new file mode 100644 index 0000000000..9d817f3073 --- /dev/null +++ b/regression-tests/test-results/pure2-bugfix-for-ufcs-sfinae.cpp2.output @@ -0,0 +1,2 @@ +pure2-bugfix-for-ufcs-sfinae.cpp2... ok (all Cpp2, passes safety checks) + diff --git a/regression-tests/test-results/pure2-enum.cpp b/regression-tests/test-results/pure2-enum.cpp index 496db02a53..31b802e61a 100644 --- a/regression-tests/test-results/pure2-enum.cpp +++ b/regression-tests/test-results/pure2-enum.cpp @@ -234,7 +234,7 @@ inline CPP2_CONSTEXPR file_attributes file_attributes::none = 0; #line 28 "pure2-enum.cpp2" auto main() -> int{ auto j {janus::past}; - CPP2_UFCS_0(flip, j); + CPP2_UFCS(flip)(j); static_cast(std::move(j)); // x : skat_game = 9; // error, can't construct skat_game from integer @@ -246,8 +246,8 @@ auto main() -> int{ // if x == 9 { } // error, can't compare skat_game and integer // if x == rgb::red { } // error, can't compare skat_game and rgb color - std::cout << "x.to_string() is " + cpp2::to_string(CPP2_UFCS_0(to_string, x)) + "\n"; - std::cout << "x2.to_string() is " + cpp2::to_string(CPP2_UFCS_0(to_string, std::move(x2))) + "\n"; + std::cout << "x.to_string() is " + cpp2::to_string(CPP2_UFCS(to_string)(x)) + "\n"; + std::cout << "x2.to_string() is " + cpp2::to_string(CPP2_UFCS(to_string)(std::move(x2))) + "\n"; std::cout << "with if else: "; if (x == skat_game::diamonds) { // ok, can compare two skat_games @@ -279,41 +279,41 @@ auto main() -> int{ x = skat_game::diamonds; // ok, can assign one skat_game from another - std::cout << "file_attributes::cached.get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, file_attributes::cached)) + "\n"; - std::cout << "file_attributes::current.get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, file_attributes::current)) + "\n"; - std::cout << "file_attributes::obsolete.get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, file_attributes::obsolete)) + "\n"; - std::cout << "file_attributes::cached_and_current.get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, file_attributes::cached_and_current)) + "\n"; + std::cout << "file_attributes::cached.get_raw_value() is " + cpp2::to_string(CPP2_UFCS(get_raw_value)(file_attributes::cached)) + "\n"; + std::cout << "file_attributes::current.get_raw_value() is " + cpp2::to_string(CPP2_UFCS(get_raw_value)(file_attributes::current)) + "\n"; + std::cout << "file_attributes::obsolete.get_raw_value() is " + cpp2::to_string(CPP2_UFCS(get_raw_value)(file_attributes::obsolete)) + "\n"; + std::cout << "file_attributes::cached_and_current.get_raw_value() is " + cpp2::to_string(CPP2_UFCS(get_raw_value)(file_attributes::cached_and_current)) + "\n"; file_attributes f {file_attributes::cached_and_current}; f &= file_attributes::cached | file_attributes::obsolete; - std::cout << "f. get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, f)) + "\n"; + std::cout << "f. get_raw_value() is " + cpp2::to_string(CPP2_UFCS(get_raw_value)(f)) + "\n"; auto f2 {file_attributes::cached}; - std::cout << "f2.get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, f2)) + "\n"; + std::cout << "f2.get_raw_value() is " + cpp2::to_string(CPP2_UFCS(get_raw_value)(f2)) + "\n"; - std::cout << "f is " << CPP2_UFCS_0(to_string, f) << "\n"; - std::cout << "f2 is " << CPP2_UFCS_0(to_string, f2) << "\n"; + std::cout << "f is " << CPP2_UFCS(to_string)(f) << "\n"; + std::cout << "f2 is " << CPP2_UFCS(to_string)(f2) << "\n"; - CPP2_UFCS(clear, f2, f2); - std::cout << "f2 is " << CPP2_UFCS_0(to_string, f2) << "\n"; - CPP2_UFCS(set, f2, file_attributes::cached); - std::cout << "f2 is " << CPP2_UFCS_0(to_string, f2) << "\n"; + CPP2_UFCS(clear)(f2, f2); + std::cout << "f2 is " << CPP2_UFCS(to_string)(f2) << "\n"; + CPP2_UFCS(set)(f2, file_attributes::cached); + std::cout << "f2 is " << CPP2_UFCS(to_string)(f2) << "\n"; - std::cout << "f. get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, f)) + "\n"; - std::cout << "f2.get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, f2)) + "\n"; + std::cout << "f. get_raw_value() is " + cpp2::to_string(CPP2_UFCS(get_raw_value)(f)) + "\n"; + std::cout << "f2.get_raw_value() is " + cpp2::to_string(CPP2_UFCS(get_raw_value)(f2)) + "\n"; std::cout << "f is (f2) is " + cpp2::to_string(cpp2::is(f, (f2))) + "\n"; std::cout << "f2 is (f ) is " + cpp2::to_string(cpp2::is(f2, (f))) + "\n\n"; - CPP2_UFCS(clear, f, f2); - CPP2_UFCS(set, f, file_attributes::current | f2); + CPP2_UFCS(clear)(f, f2); + CPP2_UFCS(set)(f, file_attributes::current | f2); f |= file_attributes::obsolete; f2 |= file_attributes::current; - std::cout << "f is " << CPP2_UFCS_0(to_string, f) << "\n"; - std::cout << "f2 is " << CPP2_UFCS_0(to_string, f2) << "\n"; - std::cout << "f. get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, f)) + "\n"; - std::cout << "f2.get_raw_value() is " + cpp2::to_string(CPP2_UFCS_0(get_raw_value, f2)) + "\n"; + std::cout << "f is " << CPP2_UFCS(to_string)(f) << "\n"; + std::cout << "f2 is " << CPP2_UFCS(to_string)(f2) << "\n"; + std::cout << "f. get_raw_value() is " + cpp2::to_string(CPP2_UFCS(get_raw_value)(f)) + "\n"; + std::cout << "f2.get_raw_value() is " + cpp2::to_string(CPP2_UFCS(get_raw_value)(f2)) + "\n"; std::cout << "f == f2 is " + cpp2::to_string(f == f2 ) + "\n"; std::cout << "f is (f2) is " + cpp2::to_string(cpp2::is(f, (f2))) + "\n"; std::cout << "f2 is (f ) is " + cpp2::to_string(cpp2::is(f2, (f))) + "\n"; diff --git a/regression-tests/test-results/pure2-initialization-safety-with-else-if.cpp b/regression-tests/test-results/pure2-initialization-safety-with-else-if.cpp index 1d23607bf2..bca795385b 100644 --- a/regression-tests/test-results/pure2-initialization-safety-with-else-if.cpp +++ b/regression-tests/test-results/pure2-initialization-safety-with-else-if.cpp @@ -27,10 +27,10 @@ auto main(int const argc_, char** argv_) -> int{ auto c {3}; auto d {4}; - if (CPP2_UFCS_0(size, args) == 3) { + if (CPP2_UFCS(size)(args) == 3) { p.construct(&a); }else {if (true) { - if (CPP2_UFCS_0(size, args) == 2) { + if (CPP2_UFCS(size)(args) == 2) { p.construct(&c); }else {if (cpp2::cmp_greater(std::move(b),0)) { p.construct(&a); diff --git a/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp b/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp index c8efedd8cd..7db678fe93 100644 --- a/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp +++ b/regression-tests/test-results/pure2-inspect-expression-in-generic-function-multiple-types.cpp @@ -31,7 +31,7 @@ auto test_generic(auto const& x, auto const& msg) -> void; test_generic(a, "any"); test_generic(o, "optional"); - static_cast(CPP2_UFCS_TEMPLATE(emplace, (<0>), v, 1)); + static_cast(CPP2_UFCS_TEMPLATE(emplace<0>)(v, 1)); a = 2; o = 3; test_generic(42, "int"); diff --git a/regression-tests/test-results/pure2-interpolation.cpp b/regression-tests/test-results/pure2-interpolation.cpp index accfacaed4..9659c51349 100644 --- a/regression-tests/test-results/pure2-interpolation.cpp +++ b/regression-tests/test-results/pure2-interpolation.cpp @@ -61,9 +61,9 @@ auto const& x = item(); #line 25 "pure2-interpolation.cpp2" { - std::cout << std::left << std::setw(20) << CPP2_UFCS_0(name, x) << " color " << std::left << std::setw(10) << CPP2_UFCS_0(color, x) << " price " << std::setw(10) << std::setprecision(3) << CPP2_UFCS_0(price, x) << " in stock = " << std::boolalpha << (cpp2::cmp_greater(CPP2_UFCS_0(count, x),0)) << "\n"; + std::cout << std::left << std::setw(20) << CPP2_UFCS(name)(x) << " color " << std::left << std::setw(10) << CPP2_UFCS(color)(x) << " price " << std::setw(10) << std::setprecision(3) << CPP2_UFCS(price)(x) << " in stock = " << std::boolalpha << (cpp2::cmp_greater(CPP2_UFCS(count)(x),0)) << "\n"; - std::cout << cpp2::to_string(CPP2_UFCS_0(name, x), "{:20}") + " color " + cpp2::to_string(CPP2_UFCS_0(color, x), "{:10}") + " price " + cpp2::to_string(CPP2_UFCS_0(price, x), "{: <10.2f}") + " in stock = " + cpp2::to_string(cpp2::cmp_greater(CPP2_UFCS_0(count, x),0)) + "\n"; + std::cout << cpp2::to_string(CPP2_UFCS(name)(x), "{:20}") + " color " + cpp2::to_string(CPP2_UFCS(color)(x), "{:10}") + " price " + cpp2::to_string(CPP2_UFCS(price)(x), "{: <10.2f}") + " in stock = " + cpp2::to_string(cpp2::cmp_greater(CPP2_UFCS(count)(x),0)) + "\n"; } } diff --git a/regression-tests/test-results/pure2-intro-example-hello-2022.cpp b/regression-tests/test-results/pure2-intro-example-hello-2022.cpp index 4b41c06d87..5fcc86c9c1 100644 --- a/regression-tests/test-results/pure2-intro-example-hello-2022.cpp +++ b/regression-tests/test-results/pure2-intro-example-hello-2022.cpp @@ -36,7 +36,7 @@ auto print_it(auto const& x, auto const& len) -> void; [[nodiscard]] auto decorate(auto& thing) -> int{ thing = "[" + thing + "]"; - return CPP2_UFCS_0(ssize, thing); + return CPP2_UFCS(ssize)(thing); } auto print_it(auto const& x, auto const& len) -> void { diff --git a/regression-tests/test-results/pure2-intro-example-three-loops.cpp b/regression-tests/test-results/pure2-intro-example-three-loops.cpp index 9ea76e0b0a..02bce27abb 100644 --- a/regression-tests/test-results/pure2-intro-example-three-loops.cpp +++ b/regression-tests/test-results/pure2-intro-example-three-loops.cpp @@ -44,7 +44,7 @@ auto decorate_and_print(auto& thing) -> void{ std::span view {words}; auto i {cpp2_new(0)}; - for( ; cpp2::cmp_less(*cpp2::assert_not_null(i),CPP2_UFCS_0(ssize, view)); ++*cpp2::assert_not_null(i) ) { + for( ; cpp2::cmp_less(*cpp2::assert_not_null(i),CPP2_UFCS(ssize)(view)); ++*cpp2::assert_not_null(i) ) { print(CPP2_ASSERT_IN_BOUNDS(view, *cpp2::assert_not_null(i))); } diff --git a/regression-tests/test-results/pure2-print.cpp b/regression-tests/test-results/pure2-print.cpp index 5aa201184f..d19d5a2a45 100644 --- a/regression-tests/test-results/pure2-print.cpp +++ b/regression-tests/test-results/pure2-print.cpp @@ -99,11 +99,11 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias = 42; if (cpp2::cmp_less(*cpp2::assert_not_null(p),0)) { ret = -*cpp2::assert_not_null(std::move(p)); } - ret += strlen(s) - 10 + CPP2_UFCS_0(strlen, std::move(s)) * (16 / (3 & 2)) % 3; + ret += strlen(s) - 10 + CPP2_UFCS(strlen)(std::move(s)) * (16 / (3 & 2)) % 3; map m {}; CPP2_ASSERT_IN_BOUNDS(m, 0) = cpp2::as_("har"); - ret -= CPP2_UFCS_0(length, h("x", m)); + ret -= CPP2_UFCS(length)(h("x", m)); static_cast(std::move(m)); return ret; @@ -113,22 +113,22 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias = 42; #line 34 "pure2-print.cpp2" { - cpp2::Default.expects(CPP2_UFCS_0(empty, m) == false || false, "message"); - cpp2::Bounds.expects([_0 = 0, _1 = CPP2_UFCS_0(ssize, m), _2 = 100]{ return cpp2::cmp_less(_0,_1) && cpp2::cmp_less(_1,_2); }() && true != false, ""); + cpp2::Default.expects(CPP2_UFCS(empty)(m) == false || false, "message"); + cpp2::Bounds.expects([_0 = 0, _1 = CPP2_UFCS(ssize)(m), _2 = 100]{ return cpp2::cmp_less(_0,_1) && cpp2::cmp_less(_1,_2); }() && true != false, ""); #line 35 "pure2-print.cpp2" auto a {[]() -> void{}}; auto b {[]() -> void{}}; auto c {[]() -> void{}}; - for( ; CPP2_UFCS_0(empty, s); a() ) {break; } + for( ; CPP2_UFCS(empty)(s); a() ) {break; } - do {} while ( CPP2_UFCS_0(empty, s) && [&]{ b() ; return true; }() ); + do {} while ( CPP2_UFCS(empty)(s) && [&]{ b() ; return true; }() ); for ( [[maybe_unused]] auto const& unnamed_param_1 : m ) { { do {goto CONTINUE_43_13; } while (false); c(); } CPP2_CONTINUE_BREAK(43_13) } #line 45 "pure2-print.cpp2" - if (cpp2::is(!(CPP2_UFCS_0(empty, s)), (true))) {std::move(a)(); } - else {if (!(CPP2_UFCS_0(empty, m))) {std::move(b)(); } + if (cpp2::is(!(CPP2_UFCS(empty)(s)), (true))) {std::move(a)(); } + else {if (!(CPP2_UFCS(empty)(m))) {std::move(b)(); } else {std::move(c)(); }} cpp2::Default.expects(true, ""); @@ -167,9 +167,9 @@ requires ((std::is_convertible_v && ...)) {(std::cout << .. #line 80 "pure2-print.cpp2" ::outer::mytype var {}; - cout << CPP2_UFCS(g, var, 42) << "\n"; + cout << CPP2_UFCS(g)(var, 42) << "\n"; - cout << [&] () -> namespace_alias::string { auto&& _expr = CPP2_UFCS(g, std::move(var), 42); + cout << [&] () -> namespace_alias::string { auto&& _expr = CPP2_UFCS(g)(std::move(var), 42); if (cpp2::is(_expr, 43)) { if constexpr( requires{"forty-and-three";} ) if constexpr( std::is_convertible_v ) return "forty-and-three"; else return namespace_alias::string{}; else return namespace_alias::string{}; } else return "default case"; } () << "\n"; diff --git a/regression-tests/test-results/pure2-stdio-with-raii.cpp b/regression-tests/test-results/pure2-stdio-with-raii.cpp index 5ff84f1f4a..288673a879 100644 --- a/regression-tests/test-results/pure2-stdio-with-raii.cpp +++ b/regression-tests/test-results/pure2-stdio-with-raii.cpp @@ -26,6 +26,6 @@ [[nodiscard]] auto main() -> int{ std::string s {"Fred"}; auto myfile {cpp2::fopen("xyzzy", "w")}; - static_cast(CPP2_UFCS(fprintf, std::move(myfile), "Hello %s with UFCS!", CPP2_UFCS_0(c_str, std::move(s)))); + static_cast(CPP2_UFCS(fprintf)(std::move(myfile), "Hello %s with UFCS!", CPP2_UFCS(c_str)(std::move(s)))); } diff --git a/regression-tests/test-results/pure2-stdio.cpp b/regression-tests/test-results/pure2-stdio.cpp index b274a9e907..4ae3e58ae0 100644 --- a/regression-tests/test-results/pure2-stdio.cpp +++ b/regression-tests/test-results/pure2-stdio.cpp @@ -29,7 +29,7 @@ [[nodiscard]] auto main() -> int{ std::string s {"Fred"}; auto myfile {fopen("xyzzy", "w")}; - static_cast(CPP2_UFCS(fprintf, myfile, "Hello %s with UFCS!", CPP2_UFCS_0(c_str, std::move(s)))); - static_cast(CPP2_UFCS_0(fclose, std::move(myfile))); + static_cast(CPP2_UFCS(fprintf)(myfile, "Hello %s with UFCS!", CPP2_UFCS(c_str)(std::move(s)))); + static_cast(CPP2_UFCS(fclose)(std::move(myfile))); } diff --git a/regression-tests/test-results/pure2-type-safety-1.cpp b/regression-tests/test-results/pure2-type-safety-1.cpp index c8b2d26ffb..5475cb418e 100644 --- a/regression-tests/test-results/pure2-type-safety-1.cpp +++ b/regression-tests/test-results/pure2-type-safety-1.cpp @@ -43,7 +43,7 @@ auto print(cpp2::in msg, cpp2::in b) -> void; std::cout << "\n"; - static_cast(CPP2_UFCS_TEMPLATE(emplace, (<1>), v, 1)); + static_cast(CPP2_UFCS_TEMPLATE(emplace<1>)(v, 1)); a = 2; o = 3; test_generic(42, "int"); diff --git a/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp b/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp index acd3c5d5c9..f504f31411 100644 --- a/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp +++ b/regression-tests/test-results/pure2-type-safety-2-with-inspect-expression.cpp @@ -31,7 +31,7 @@ auto test_generic(auto const& x, auto const& msg) -> void; test_generic(a, "any"); test_generic(o, "optional"); - static_cast(CPP2_UFCS_TEMPLATE(emplace, (<2>), v, 1)); + static_cast(CPP2_UFCS_TEMPLATE(emplace<2>)(v, 1)); a = 2; o = 3; test_generic(42, "int"); diff --git a/regression-tests/test-results/pure2-types-basics.cpp b/regression-tests/test-results/pure2-types-basics.cpp index b8f3773413..36923c68da 100644 --- a/regression-tests/test-results/pure2-types-basics.cpp +++ b/regression-tests/test-results/pure2-types-basics.cpp @@ -177,19 +177,19 @@ namespace N { auto main() -> int{ N::myclass x {1}; - CPP2_UFCS(f, x, 53); + CPP2_UFCS(f)(x, 53); N::myclass::nested::g(); - std::cout << "f1: " + cpp2::to_string(CPP2_UFCS(f1, x, 1, 1)) + "\n"; - std::cout << "f2: " + cpp2::to_string(CPP2_UFCS(f2, x, 2, 2)) + "\n"; - std::cout << "f3: " + cpp2::to_string(CPP2_UFCS_TEMPLATE_0(f3, (<3,3>), x)) + "\n"; - std::cout << "f4: " + cpp2::to_string(CPP2_UFCS_TEMPLATE_0(f4, (<4,4>), x)) + "\n"; + std::cout << "f1: " + cpp2::to_string(CPP2_UFCS(f1)(x, 1, 1)) + "\n"; + std::cout << "f2: " + cpp2::to_string(CPP2_UFCS(f2)(x, 2, 2)) + "\n"; + std::cout << "f3: " + cpp2::to_string(CPP2_UFCS_TEMPLATE(f3<3,3>)(x)) + "\n"; + std::cout << "f4: " + cpp2::to_string(CPP2_UFCS_TEMPLATE(f4<4,4>)(x)) + "\n"; N::myclass auto_74_5 {"abracadabra"}; N::myclass auto_75_5 {}; N::myclass auto_76_5 {1, "hair"}; // Invoke the single-param operator=s as actual assignments std::cout << "x's state before assignments: "; - CPP2_UFCS_0(print, x); + CPP2_UFCS(print)(x); x = 84; x = "syzygy"; x = 84; diff --git a/regression-tests/test-results/pure2-types-down-upcast.cpp b/regression-tests/test-results/pure2-types-down-upcast.cpp index 8efea7e256..04773a6933 100644 --- a/regression-tests/test-results/pure2-types-down-upcast.cpp +++ b/regression-tests/test-results/pure2-types-down-upcast.cpp @@ -77,18 +77,18 @@ auto func_const(cpp2::in b) -> void{std::cout << "Call B const: " + cpp2::to_ auto test_const_foo() -> void{ A s {}; A const* sC {&s}; - CPP2_UFCS_0(const_foo, s); - CPP2_UFCS_0(const_foo, (*cpp2::assert_not_null(sC))); - CPP2_UFCS_0(const_foo, (cpp2::as_(s))); - CPP2_UFCS_0(const_foo, (cpp2::as_(*cpp2::assert_not_null(sC)))); + CPP2_UFCS(const_foo)(s); + CPP2_UFCS(const_foo)((*cpp2::assert_not_null(sC))); + CPP2_UFCS(const_foo)((cpp2::as_(s))); + CPP2_UFCS(const_foo)((cpp2::as_(*cpp2::assert_not_null(sC)))); static_cast(std::move(s)); static_cast(std::move(sC)); } auto test_mut_foo() -> void{ A s {}; - CPP2_UFCS_0(mut_foo, s); - CPP2_UFCS_0(mut_foo, (cpp2::as_(s))); + CPP2_UFCS(mut_foo)(s); + CPP2_UFCS(mut_foo)((cpp2::as_(s))); static_cast(std::move(s)); } diff --git a/regression-tests/test-results/pure2-types-inheritance.cpp b/regression-tests/test-results/pure2-types-inheritance.cpp index 6053247428..200fe752dd 100644 --- a/regression-tests/test-results/pure2-types-inheritance.cpp +++ b/regression-tests/test-results/pure2-types-inheritance.cpp @@ -128,18 +128,18 @@ namespace N { #line 38 "pure2-types-inheritance.cpp2" auto make_speak(cpp2::in h) -> void{ std::cout << "-> [vcall: make_speak] "; - CPP2_UFCS_0(speak, h); + CPP2_UFCS(speak)(h); } auto do_work(cpp2::in> m) -> void{ std::cout << "-> [vcall: do_work] "; - CPP2_UFCS_0(work, m); + CPP2_UFCS(work)(m); } auto main() -> int{ Cyborg c {"Parsnip"}; - CPP2_UFCS_0(print, c); - CPP2_UFCS_0(make_speak, c); - CPP2_UFCS_0(do_work, std::move(c)); + CPP2_UFCS(print)(c); + CPP2_UFCS(make_speak)(c); + CPP2_UFCS(do_work)(std::move(c)); } 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 96b0499e31..d7ffd838b6 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 @@ -152,7 +152,7 @@ namespace N { // Exercise '_' anonymous objects too while we're at it cpp2::finally auto_37_9 {[&]() -> void { std::cout << "leaving call to 'why(" + cpp2::to_string(count) + ")'\n"; }}; if (cpp2::cmp_less(count,5)) { - CPP2_UFCS(why, (*cpp2::assert_not_null(py)), count + 1);// use Y object from X + CPP2_UFCS(why)((*cpp2::assert_not_null(py)), count + 1);// use Y object from X } } @@ -166,7 +166,7 @@ namespace N { #line 51 "pure2-types-order-independence-and-nesting.cpp2" auto Y::why(cpp2::in count) const& -> void { - CPP2_UFCS(exx, (*cpp2::assert_not_null(px)), count + 1); }// use X object from Y + CPP2_UFCS(exx)((*cpp2::assert_not_null(px)), count + 1); }// use X object from Y #line 55 "pure2-types-order-independence-and-nesting.cpp2" namespace M { @@ -186,7 +186,7 @@ auto main() -> int N::X x {cpp2::out(&y)}; // construct y and x, and point them at each other // now have the two objects call each other back and forth a few times - CPP2_UFCS(exx, std::move(x), 1); + CPP2_UFCS(exx)(std::move(x), 1); // and test a nested template out-of-line definition N::M::A::B<42>::f("welt"); 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 93bbb2edd3..51eb83cb9d 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 @@ -120,24 +120,24 @@ auto main() -> int{ std::cout << "---------------------- ------------ ------------------------------------------------------\n"; myclass x {"Henry"}; - CPP2_UFCS(print, x, " construct ", "\n"); + CPP2_UFCS(print)(x, " construct ", "\n"); x = "Clara"; - CPP2_UFCS(print, x, " assign ", "\n"); + CPP2_UFCS(print)(x, " assign ", "\n"); auto y {x}; - CPP2_UFCS(print, y, " cp-construct ", " <- "); - CPP2_UFCS(print, x, "", "\n"); + CPP2_UFCS(print)(y, " cp-construct ", " <- "); + CPP2_UFCS(print)(x, "", "\n"); auto z {std::move(x)}; - CPP2_UFCS(print, z, " mv-construct ", " <- "); - CPP2_UFCS(print, std::move(x), "", "\n"); + CPP2_UFCS(print)(z, " mv-construct ", " <- "); + CPP2_UFCS(print)(std::move(x), "", "\n"); z = y; - CPP2_UFCS(print, z, " cp-assign ", " <- "); - CPP2_UFCS(print, y, "", "\n"); + CPP2_UFCS(print)(z, " cp-assign ", " <- "); + CPP2_UFCS(print)(y, "", "\n"); z = { std::move(y) }; - CPP2_UFCS(print, std::move(z), " mv-assign ", " <- "); - CPP2_UFCS(print, std::move(y), "", "\n"); + CPP2_UFCS(print)(std::move(z), " mv-assign ", " <- "); + CPP2_UFCS(print)(std::move(y), "", "\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 e277b12bde..0184f7b9da 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 @@ -125,24 +125,24 @@ auto main() -> int{ std::cout << "---------------------- ------------ ------------------------------------------------------\n"; myclass x {"Henry"}; - CPP2_UFCS(print, x, " construct ", "\n"); + CPP2_UFCS(print)(x, " construct ", "\n"); x = "Clara"; - CPP2_UFCS(print, x, " assign ", "\n"); + CPP2_UFCS(print)(x, " assign ", "\n"); auto y {x}; - CPP2_UFCS(print, y, " cp-construct ", " <- "); - CPP2_UFCS(print, x, "", "\n"); + CPP2_UFCS(print)(y, " cp-construct ", " <- "); + CPP2_UFCS(print)(x, "", "\n"); auto z {std::move(x)}; - CPP2_UFCS(print, z, " mv-construct ", " <- "); - CPP2_UFCS(print, std::move(x), "", "\n"); + CPP2_UFCS(print)(z, " mv-construct ", " <- "); + CPP2_UFCS(print)(std::move(x), "", "\n"); z = y; - CPP2_UFCS(print, z, " cp-assign ", " <- "); - CPP2_UFCS(print, y, "", "\n"); + CPP2_UFCS(print)(z, " cp-assign ", " <- "); + CPP2_UFCS(print)(y, "", "\n"); z = { std::move(y) }; - CPP2_UFCS(print, std::move(z), " mv-assign ", " <- "); - CPP2_UFCS(print, std::move(y), "", "\n"); + CPP2_UFCS(print)(std::move(z), " mv-assign ", " <- "); + CPP2_UFCS(print)(std::move(y), "", "\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 8ee8527bb2..4176a137cd 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 @@ -124,24 +124,24 @@ auto main() -> int{ std::cout << "---------------------- ------------ ------------------------------------------------------\n"; myclass x {"Henry"}; - CPP2_UFCS(print, x, " construct ", "\n"); + CPP2_UFCS(print)(x, " construct ", "\n"); x = "Clara"; - CPP2_UFCS(print, x, " assign ", "\n"); + CPP2_UFCS(print)(x, " assign ", "\n"); auto y {x}; - CPP2_UFCS(print, y, " cp-construct ", " <- "); - CPP2_UFCS(print, x, "", "\n"); + CPP2_UFCS(print)(y, " cp-construct ", " <- "); + CPP2_UFCS(print)(x, "", "\n"); auto z {std::move(x)}; - CPP2_UFCS(print, z, " mv-construct ", " <- "); - CPP2_UFCS(print, std::move(x), "", "\n"); + CPP2_UFCS(print)(z, " mv-construct ", " <- "); + CPP2_UFCS(print)(std::move(x), "", "\n"); z = y; - CPP2_UFCS(print, z, " cp-assign ", " <- "); - CPP2_UFCS(print, y, "", "\n"); + CPP2_UFCS(print)(z, " cp-assign ", " <- "); + CPP2_UFCS(print)(y, "", "\n"); z = { std::move(y) }; - CPP2_UFCS(print, std::move(z), " mv-assign ", " <- "); - CPP2_UFCS(print, std::move(y), "", "\n"); + CPP2_UFCS(print)(std::move(z), " mv-assign ", " <- "); + CPP2_UFCS(print)(std::move(y), "", "\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 d2be0d5605..daeb6165f7 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 @@ -124,24 +124,24 @@ auto main() -> int{ std::cout << "---------------------- ------------ ------------------------------------------------------\n"; myclass x {"Henry"}; - CPP2_UFCS(print, x, " construct ", "\n"); + CPP2_UFCS(print)(x, " construct ", "\n"); x = "Clara"; - CPP2_UFCS(print, x, " assign ", "\n"); + CPP2_UFCS(print)(x, " assign ", "\n"); auto y {x}; - CPP2_UFCS(print, y, " cp-construct ", " <- "); - CPP2_UFCS(print, x, "", "\n"); + CPP2_UFCS(print)(y, " cp-construct ", " <- "); + CPP2_UFCS(print)(x, "", "\n"); auto z {std::move(x)}; - CPP2_UFCS(print, z, " mv-construct ", " <- "); - CPP2_UFCS(print, std::move(x), "", "\n"); + CPP2_UFCS(print)(z, " mv-construct ", " <- "); + CPP2_UFCS(print)(std::move(x), "", "\n"); z = y; - CPP2_UFCS(print, z, " cp-assign ", " <- "); - CPP2_UFCS(print, y, "", "\n"); + CPP2_UFCS(print)(z, " cp-assign ", " <- "); + CPP2_UFCS(print)(y, "", "\n"); z = { std::move(y) }; - CPP2_UFCS(print, std::move(z), " mv-assign ", " <- "); - CPP2_UFCS(print, std::move(y), "", "\n"); + CPP2_UFCS(print)(std::move(z), " mv-assign ", " <- "); + CPP2_UFCS(print)(std::move(y), "", "\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 2f658ba124..359cdcb1f9 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 @@ -130,24 +130,24 @@ auto main() -> int{ std::cout << "---------------------- ------------ ------------------------------------------------------\n"; myclass x {"Henry"}; - CPP2_UFCS(print, x, " construct ", "\n"); + CPP2_UFCS(print)(x, " construct ", "\n"); x = "Clara"; - CPP2_UFCS(print, x, " assign ", "\n"); + CPP2_UFCS(print)(x, " assign ", "\n"); auto y {x}; - CPP2_UFCS(print, y, " cp-construct ", " <- "); - CPP2_UFCS(print, x, "", "\n"); + CPP2_UFCS(print)(y, " cp-construct ", " <- "); + CPP2_UFCS(print)(x, "", "\n"); auto z {std::move(x)}; - CPP2_UFCS(print, z, " mv-construct ", " <- "); - CPP2_UFCS(print, std::move(x), "", "\n"); + CPP2_UFCS(print)(z, " mv-construct ", " <- "); + CPP2_UFCS(print)(std::move(x), "", "\n"); z = y; - CPP2_UFCS(print, z, " cp-assign ", " <- "); - CPP2_UFCS(print, y, "", "\n"); + CPP2_UFCS(print)(z, " cp-assign ", " <- "); + CPP2_UFCS(print)(y, "", "\n"); z = { std::move(y) }; - CPP2_UFCS(print, std::move(z), " mv-assign ", " <- "); - CPP2_UFCS(print, std::move(y), "", "\n"); + CPP2_UFCS(print)(std::move(z), " mv-assign ", " <- "); + CPP2_UFCS(print)(std::move(y), "", "\n"); } diff --git a/regression-tests/test-results/pure2-types-that-parameters.cpp b/regression-tests/test-results/pure2-types-that-parameters.cpp index 5df1797c63..5fb031b397 100644 --- a/regression-tests/test-results/pure2-types-that-parameters.cpp +++ b/regression-tests/test-results/pure2-types-that-parameters.cpp @@ -85,16 +85,16 @@ auto main() -> int; #line 25 "pure2-types-that-parameters.cpp2" auto main() -> int{ myclass x {}; - CPP2_UFCS_0(print, x); + CPP2_UFCS(print)(x); std::cout << "-----\n"; auto y {x}; - CPP2_UFCS_0(print, x); - CPP2_UFCS_0(print, std::move(y)); + CPP2_UFCS(print)(x); + CPP2_UFCS(print)(std::move(y)); std::cout << "-----\n"; auto z {std::move(x)}; - CPP2_UFCS_0(print, std::move(x)); - CPP2_UFCS_0(print, std::move(z)); + CPP2_UFCS(print)(std::move(x)); + CPP2_UFCS(print)(std::move(z)); } diff --git a/regression-tests/test-results/pure2-ufcs-member-access-and-chaining.cpp b/regression-tests/test-results/pure2-ufcs-member-access-and-chaining.cpp index b04ddeffd5..592a89e3ed 100644 --- a/regression-tests/test-results/pure2-ufcs-member-access-and-chaining.cpp +++ b/regression-tests/test-results/pure2-ufcs-member-access-and-chaining.cpp @@ -38,27 +38,27 @@ extern int y; [[nodiscard]] auto main() -> int{ #line 2 "pure2-ufcs-member-access-and-chaining.cpp2" auto i {42}; - static_cast(CPP2_UFCS_0(ufcs, std::move(i))); + static_cast(CPP2_UFCS(ufcs)(std::move(i))); auto j {fun()}; - static_cast(CPP2_UFCS_0(ufcs, j)); + static_cast(CPP2_UFCS(ufcs)(j)); - static_cast(CPP2_UFCS_0(ufcs, fun())); + static_cast(CPP2_UFCS(ufcs)(fun())); auto k {fun()}; - static_cast(CPP2_UFCS_0(ufcs, std::move(k))); + static_cast(CPP2_UFCS(ufcs)(std::move(k))); - static_cast(CPP2_UFCS_0(ufcs, get_i(j))); + static_cast(CPP2_UFCS(ufcs)(get_i(j))); - static_cast(CPP2_UFCS_0(ufcs, get_i(fun()))); + static_cast(CPP2_UFCS(ufcs)(get_i(fun()))); - auto res {CPP2_UFCS_0(ufcs, (42))}; + auto res {CPP2_UFCS(ufcs)((42))}; - static_cast(CPP2_UFCS_0(ufcs, (std::move(j)))); + static_cast(CPP2_UFCS(ufcs)((std::move(j)))); - CPP2_UFCS_0(no_return, 42); + CPP2_UFCS(no_return)(42); - CPP2_UFCS_0(no_return, std::move(res)); + CPP2_UFCS(no_return)(std::move(res)); } auto no_return([[maybe_unused]] auto const& unnamed_param_1) -> void{} @@ -80,5 +80,5 @@ auto no_return([[maybe_unused]] auto const& unnamed_param_1) -> void{} #line 42 "pure2-ufcs-member-access-and-chaining.cpp2" [[nodiscard]] auto f([[maybe_unused]] auto const& unnamed_param_1) -> int { return 0; } -int y {CPP2_UFCS_0_NONLOCAL(f, 0)}; +int y {CPP2_UFCS_NONLOCAL(f)(0)}; diff --git a/regression-tests/test-results/pure2-union.cpp b/regression-tests/test-results/pure2-union.cpp index 484ced7333..e11a7a6b7a 100644 --- a/regression-tests/test-results/pure2-union.cpp +++ b/regression-tests/test-results/pure2-union.cpp @@ -107,26 +107,26 @@ name_or_number::name_or_number(){} name_or_number::name_or_number(name_or_number const& that) : _storage{ } , _discriminator{ -1 }{ -if (CPP2_UFCS_0(is_name, that)) {set_name(CPP2_UFCS_0(name, that));} -if (CPP2_UFCS_0(is_num, that)) {set_num(CPP2_UFCS_0(num, that));} +if (CPP2_UFCS(is_name)(that)) {set_name(CPP2_UFCS(name)(that));} +if (CPP2_UFCS(is_num)(that)) {set_num(CPP2_UFCS(num)(that));} } name_or_number::name_or_number(name_or_number&& that) noexcept : _storage{ } , _discriminator{ -1 }{ -if (CPP2_UFCS_0(is_name, std::move(that))) {set_name(CPP2_UFCS_0(name, std::move(that)));} -if (CPP2_UFCS_0(is_num, std::move(that))) {set_num(CPP2_UFCS_0(num, std::move(that)));} +if (CPP2_UFCS(is_name)(std::move(that))) {set_name(CPP2_UFCS(name)(std::move(that)));} +if (CPP2_UFCS(is_num)(std::move(that))) {set_num(CPP2_UFCS(num)(std::move(that)));} } auto name_or_number::operator=(name_or_number const& that) -> name_or_number& { -if (CPP2_UFCS_0(is_name, that)) {set_name(CPP2_UFCS_0(name, that));} -if (CPP2_UFCS_0(is_num, that)) {set_num(CPP2_UFCS_0(num, that));} +if (CPP2_UFCS(is_name)(that)) {set_name(CPP2_UFCS(name)(that));} +if (CPP2_UFCS(is_num)(that)) {set_num(CPP2_UFCS(num)(that));} return *this; } auto name_or_number::operator=(name_or_number&& that) noexcept -> name_or_number& { -if (CPP2_UFCS_0(is_name, std::move(that))) {set_name(CPP2_UFCS_0(name, std::move(that)));} -if (CPP2_UFCS_0(is_num, std::move(that))) {set_num(CPP2_UFCS_0(num, std::move(that)));} +if (CPP2_UFCS(is_name)(std::move(that))) {set_name(CPP2_UFCS(name)(std::move(that)));} +if (CPP2_UFCS(is_num)(std::move(that))) {set_num(CPP2_UFCS(num)(std::move(that)));} return *this; } #line 12 "pure2-union.cpp2" @@ -163,33 +163,33 @@ template name_or_other::name_or_other(){} template name_or_other::name_or_other(name_or_other const& that) : _storage{ } , _discriminator{ -1 }{ - if (CPP2_UFCS_0(is_name, that)) {set_name(CPP2_UFCS_0(name, that));} - if (CPP2_UFCS_0(is_other, that)) {set_other(CPP2_UFCS_0(other, that));} + if (CPP2_UFCS(is_name)(that)) {set_name(CPP2_UFCS(name)(that));} + if (CPP2_UFCS(is_other)(that)) {set_other(CPP2_UFCS(other)(that));} } template name_or_other::name_or_other(name_or_other&& that) noexcept : _storage{ } , _discriminator{ -1 }{ - if (CPP2_UFCS_0(is_name, std::move(that))) {set_name(CPP2_UFCS_0(name, std::move(that)));} - if (CPP2_UFCS_0(is_other, std::move(that))) {set_other(CPP2_UFCS_0(other, std::move(that)));} + if (CPP2_UFCS(is_name)(std::move(that))) {set_name(CPP2_UFCS(name)(std::move(that)));} + if (CPP2_UFCS(is_other)(std::move(that))) {set_other(CPP2_UFCS(other)(std::move(that)));} } template auto name_or_other::operator=(name_or_other const& that) -> name_or_other& { - if (CPP2_UFCS_0(is_name, that)) {set_name(CPP2_UFCS_0(name, that));} - if (CPP2_UFCS_0(is_other, that)) {set_other(CPP2_UFCS_0(other, that));} + if (CPP2_UFCS(is_name)(that)) {set_name(CPP2_UFCS(name)(that));} + if (CPP2_UFCS(is_other)(that)) {set_other(CPP2_UFCS(other)(that));} return *this; } template auto name_or_other::operator=(name_or_other&& that) noexcept -> name_or_other& { - if (CPP2_UFCS_0(is_name, std::move(that))) {set_name(CPP2_UFCS_0(name, std::move(that)));} - if (CPP2_UFCS_0(is_other, std::move(that))) {set_other(CPP2_UFCS_0(other, std::move(that)));} + if (CPP2_UFCS(is_name)(std::move(that))) {set_name(CPP2_UFCS(name)(std::move(that)));} + if (CPP2_UFCS(is_other)(std::move(that))) {set_other(CPP2_UFCS(other)(std::move(that)));} return *this; } #line 19 "pure2-union.cpp2" auto print_name(cpp2::in non) -> void{ - if (CPP2_UFCS_0(is_name, non)) { - std::cout << CPP2_UFCS_0(name, non) << "\n"; + if (CPP2_UFCS(is_name)(non)) { + std::cout << CPP2_UFCS(name)(non) << "\n"; } else { std::cout << "(not a name)\n"; @@ -200,16 +200,16 @@ auto main() -> int{ name_or_number x {}; std::cout << "sizeof(x) is " + cpp2::to_string(sizeof(x)) + "\n"; - CPP2_UFCS_0(print_name, x); + CPP2_UFCS(print_name)(x); - CPP2_UFCS(set_name, x, "xyzzy", cpp2::as_()); + CPP2_UFCS(set_name)(x, "xyzzy", cpp2::as_()); - CPP2_UFCS_0(print_name, std::move(x)); + CPP2_UFCS(print_name)(std::move(x)); { name_or_other val {}; - CPP2_UFCS(set_other, val, 42); - std::cout << CPP2_UFCS_0(to_string, std::move(val)); + CPP2_UFCS(set_other)(val, 42); + std::cout << CPP2_UFCS(to_string)(std::move(val)); } } diff --git a/source/parse.h b/source/parse.h index 103f9ce392..b0454c9a80 100644 --- a/source/parse.h +++ b/source/parse.h @@ -4981,6 +4981,10 @@ class parser std::unique_ptr parse_tree = {}; + // Store declarations generated in a metafunction. Append them after the declaration for the meta function has been + // finished. + std::vector> metafunction_declarations = {}; + // Keep a stack of current capture groups (contracts/decls still being parsed) std::vector current_capture_groups = {}; @@ -5152,6 +5156,22 @@ class parser } + auto parse_one_prepare( + std::vector const& tokens_, + std::deque& generated_tokens_ + ) + -> void + { + parse_kind = "source string during code generation"; + + // Set per-parse state for the duration of this call + tokens = &tokens_; + generated_tokens = &generated_tokens_; + + pos = 0; + } + + //----------------------------------------------------------------------- // parse_one_statement // @@ -5160,22 +5180,17 @@ class parser // // Each call parses one statement and returns its parse tree. // - auto parse_one_declaration( + auto parse_one_statement( std::vector const& tokens_, std::deque& generated_tokens_ ) -> std::unique_ptr { - parse_kind = "source string during code generation"; - - // Set per-parse state for the duration of this call - tokens = &tokens_; - generated_tokens = &generated_tokens_; + parse_one_prepare(tokens_, generated_tokens_); // Parse one declaration - we succeed if the parse succeeded, // and there were no new errors, and all tokens were consumed auto errors_size = std::ssize(errors); - pos = 0; if (auto d = statement(); d && std::ssize(errors) == errors_size @@ -5188,6 +5203,35 @@ class parser return {}; } + //----------------------------------------------------------------------- + // parse_one_declaration + // + // tokens input tokens for this section of Cpp2 source code + // generated_tokens a shared place to store generated tokens + // + // Each call parses one declaration and returns its parse tree. + // + auto parse_one_declaration( + std::vector const& tokens_, + std::deque& generated_tokens_ + ) + -> std::unique_ptr + { + parse_one_prepare(tokens_, generated_tokens_); + + auto errors_size = std::ssize(errors); + if (auto d = declaration(); + d + && std::ssize(errors) == errors_size + && done() + ) + { + return d; + } + + return {}; + } + //----------------------------------------------------------------------- // Get a set of pointers to just the declarations in the given token map section @@ -5210,7 +5254,8 @@ class parser if (decl->position().lineno > last_line) { break; } - if (decl->position().lineno >= first_line) { + if (decl->position().lineno >= first_line || + decl->position().lineno < 0) { // Add generated declarations from metafunctions ret.push_back( decl.get() ); } } @@ -8720,6 +8765,13 @@ class parser auto n = std::make_unique(); for (auto d = declaration(); d; d = declaration()) { n->declarations.push_back( std::move(d) ); + + // Add declarations generated by metafunctions. + for(auto& md : metafunction_declarations) { + n->declarations.push_back( std::move(md)); + } + + metafunction_declarations.clear(); } return n; } diff --git a/source/reflect.h b/source/reflect.h index 6998680d99..f428fa1ca8 100644 --- a/source/reflect.h +++ b/source/reflect.h @@ -18,28 +18,28 @@ namespace meta { #line 32 "reflect.h2" class compiler_services; -#line 193 "reflect.h2" +#line 229 "reflect.h2" class declaration_base; -#line 219 "reflect.h2" +#line 255 "reflect.h2" class declaration; -#line 301 "reflect.h2" +#line 337 "reflect.h2" class function_declaration; -#line 358 "reflect.h2" +#line 394 "reflect.h2" class object_declaration; -#line 394 "reflect.h2" +#line 430 "reflect.h2" class type_declaration; -#line 507 "reflect.h2" +#line 550 "reflect.h2" class alias_declaration; -#line 846 "reflect.h2" +#line 889 "reflect.h2" class value_member_info; -#line 1340 "reflect.h2" +#line 1383 "reflect.h2" } } @@ -85,6 +85,7 @@ class compiler_services private: std::vector* errors; private: int errors_original_size; private: std::deque* generated_tokens; + private: std::vector>* generated_declarations; private: cpp2::parser parser; private: std::string metafunction_name {}; private: std::vector metafunction_args {}; @@ -93,42 +94,55 @@ class compiler_services public: explicit compiler_services( std::vector* errors_, - std::deque* generated_tokens_ + std::deque* generated_tokens_, + std::vector>* generated_declarations_ ); -#line 54 "reflect.h2" +#line 57 "reflect.h2" public: auto set_metafunction_name(cpp2::in name, cpp2::in> args) & -> void; -#line 60 "reflect.h2" +#line 63 "reflect.h2" public: [[nodiscard]] auto get_metafunction_name() const& -> std::string_view; public: [[nodiscard]] auto get_argument(cpp2::in index) & -> std::string; -#line 70 "reflect.h2" +#line 73 "reflect.h2" public: [[nodiscard]] auto arguments_were_used() const& -> bool; + protected: [[nodiscard]] auto tokenize( + + std::string_view source + ) & -> auto; + +#line 118 "reflect.h2" protected: [[nodiscard]] auto parse_statement( std::string_view source ) & -> std::unique_ptr; -#line 120 "reflect.h2" +#line 134 "reflect.h2" + protected: [[nodiscard]] auto parse_and_add_declaration( + + std::string_view source + ) & -> bool; + +#line 156 "reflect.h2" public: [[nodiscard]] virtual auto position() const -> source_position; -#line 126 "reflect.h2" +#line 162 "reflect.h2" public: auto require( cpp2::in b, cpp2::in msg ) const& -> void; -#line 137 "reflect.h2" +#line 173 "reflect.h2" public: auto error(cpp2::in msg) const& -> void; public: virtual ~compiler_services() noexcept; public: compiler_services(compiler_services const& that); -#line 145 "reflect.h2" +#line 181 "reflect.h2" }; /* @@ -167,7 +181,7 @@ type_id: @polymorphic_base @copyable type = } */ -#line 184 "reflect.h2" +#line 220 "reflect.h2" //----------------------------------------------------------------------- // // Declarations @@ -180,7 +194,7 @@ type_id: @polymorphic_base @copyable type = class declaration_base : public compiler_services { -#line 197 "reflect.h2" +#line 233 "reflect.h2" protected: declaration_node* n; protected: explicit declaration_base( @@ -189,31 +203,31 @@ class declaration_base cpp2::in s ); -#line 210 "reflect.h2" +#line 246 "reflect.h2" public: [[nodiscard]] auto position() const -> source_position override; public: [[nodiscard]] auto print() const& -> std::string; public: virtual ~declaration_base() noexcept; public: declaration_base(declaration_base const& that); -#line 213 "reflect.h2" +#line 249 "reflect.h2" }; -#line 216 "reflect.h2" +#line 252 "reflect.h2" //----------------------------------------------------------------------- // All declarations // class declaration : public declaration_base { -#line 223 "reflect.h2" +#line 259 "reflect.h2" public: explicit declaration( declaration_node* n_, cpp2::in s ); -#line 232 "reflect.h2" +#line 268 "reflect.h2" public: [[nodiscard]] auto is_public() const& -> bool; public: [[nodiscard]] auto is_protected() const& -> bool; public: [[nodiscard]] auto is_private() const& -> bool; @@ -232,7 +246,7 @@ class declaration public: [[nodiscard]] auto name() const& -> std::string_view; -#line 253 "reflect.h2" +#line 289 "reflect.h2" public: [[nodiscard]] auto has_initializer() const& -> bool; public: [[nodiscard]] auto is_global() const& -> bool; @@ -275,24 +289,24 @@ public: declaration(declaration const& that); // this precondition should be sufficient ... -#line 295 "reflect.h2" +#line 331 "reflect.h2" }; -#line 298 "reflect.h2" +#line 334 "reflect.h2" //----------------------------------------------------------------------- // Function declarations // class function_declaration : public declaration { -#line 305 "reflect.h2" +#line 341 "reflect.h2" public: explicit function_declaration( declaration_node* n_, cpp2::in s ); -#line 315 "reflect.h2" +#line 351 "reflect.h2" public: [[nodiscard]] auto index_of_parameter_named(cpp2::in s) const& -> int; public: [[nodiscard]] auto has_parameter_named(cpp2::in s) const& -> bool; public: [[nodiscard]] auto has_in_parameter_named(cpp2::in s) const& -> bool; @@ -332,100 +346,103 @@ class function_declaration public: [[nodiscard]] auto make_virtual() & -> bool; public: function_declaration(function_declaration const& that); -#line 352 "reflect.h2" +#line 388 "reflect.h2" }; -#line 355 "reflect.h2" +#line 391 "reflect.h2" //----------------------------------------------------------------------- // Object declarations // class object_declaration : public declaration { -#line 362 "reflect.h2" +#line 398 "reflect.h2" public: explicit object_declaration( declaration_node* n_, cpp2::in s ); -#line 372 "reflect.h2" +#line 408 "reflect.h2" public: [[nodiscard]] auto is_const() const& -> bool; public: [[nodiscard]] auto has_wildcard_type() const& -> bool; public: [[nodiscard]] auto type() const& -> std::string; -#line 382 "reflect.h2" +#line 418 "reflect.h2" public: [[nodiscard]] auto initializer() const& -> std::string; public: object_declaration(object_declaration const& that); -#line 388 "reflect.h2" +#line 424 "reflect.h2" }; -#line 391 "reflect.h2" +#line 427 "reflect.h2" //----------------------------------------------------------------------- // Type declarations // class type_declaration : public declaration { -#line 398 "reflect.h2" +#line 434 "reflect.h2" public: explicit type_declaration( declaration_node* n_, cpp2::in s ); -#line 408 "reflect.h2" +#line 444 "reflect.h2" public: auto reserve_names(cpp2::in name, auto&& ...etc) const& -> void; -#line 420 "reflect.h2" +#line 456 "reflect.h2" public: [[nodiscard]] auto is_polymorphic() const& -> bool; public: [[nodiscard]] auto is_final() const& -> bool; public: [[nodiscard]] auto make_final() & -> bool; public: [[nodiscard]] auto get_member_functions() const& -> std::vector; -#line 434 "reflect.h2" +#line 470 "reflect.h2" public: [[nodiscard]] auto get_member_objects() const& -> std::vector; -#line 444 "reflect.h2" +#line 480 "reflect.h2" public: [[nodiscard]] auto get_member_types() const& -> std::vector; -#line 454 "reflect.h2" +#line 490 "reflect.h2" public: [[nodiscard]] auto get_member_aliases() const& -> std::vector; -#line 464 "reflect.h2" +#line 500 "reflect.h2" public: [[nodiscard]] auto get_members() const& -> std::vector; struct query_declared_value_set_functions_ret { bool out_this_in_that; bool out_this_move_that; bool inout_this_in_that; bool inout_this_move_that; }; -#line 474 "reflect.h2" +#line 510 "reflect.h2" public: [[nodiscard]] auto query_declared_value_set_functions() const& -> query_declared_value_set_functions_ret; -#line 489 "reflect.h2" +#line 525 "reflect.h2" public: auto add_member(cpp2::in source) & -> void; -#line 497 "reflect.h2" +#line 533 "reflect.h2" + public: auto add_declaration_to_parent_namespace(cpp2::in source) & -> void; + +#line 540 "reflect.h2" public: auto remove_marked_members() & -> void; public: auto remove_all_members() & -> void; public: auto disable_member_function_generation() & -> void; public: type_declaration(type_declaration const& that); -#line 501 "reflect.h2" +#line 544 "reflect.h2" }; -#line 504 "reflect.h2" +#line 547 "reflect.h2" //----------------------------------------------------------------------- // Alias declarations // class alias_declaration : public declaration { -#line 511 "reflect.h2" +#line 554 "reflect.h2" public: explicit alias_declaration( declaration_node* n_, @@ -434,10 +451,10 @@ class alias_declaration public: alias_declaration(alias_declaration const& that); -#line 520 "reflect.h2" +#line 563 "reflect.h2" }; -#line 523 "reflect.h2" +#line 566 "reflect.h2" //----------------------------------------------------------------------- // // Metafunctions - these are hardwired for now until we get to the @@ -452,7 +469,7 @@ class alias_declaration // auto add_virtual_destructor(meta::type_declaration& t) -> void; -#line 541 "reflect.h2" +#line 584 "reflect.h2" //----------------------------------------------------------------------- // // "... an abstract base class defines an interface ..." @@ -467,7 +484,7 @@ auto add_virtual_destructor(meta::type_declaration& t) -> void; // auto interface(meta::type_declaration& t) -> void; -#line 580 "reflect.h2" +#line 623 "reflect.h2" //----------------------------------------------------------------------- // // "C.35: A base class destructor should be either public and @@ -489,7 +506,7 @@ auto interface(meta::type_declaration& t) -> void; // auto polymorphic_base(meta::type_declaration& t) -> void; -#line 624 "reflect.h2" +#line 667 "reflect.h2" //----------------------------------------------------------------------- // // "... A totally ordered type ... requires operator<=> that @@ -515,7 +532,7 @@ auto ordered_impl( cpp2::in ordering// must be "strong_ordering" etc. ) -> void; -#line 668 "reflect.h2" +#line 711 "reflect.h2" //----------------------------------------------------------------------- // ordered - a totally ordered type // @@ -523,19 +540,19 @@ auto ordered_impl( // auto ordered(meta::type_declaration& t) -> void; -#line 678 "reflect.h2" +#line 721 "reflect.h2" //----------------------------------------------------------------------- // weakly_ordered - a weakly ordered type // auto weakly_ordered(meta::type_declaration& t) -> void; -#line 686 "reflect.h2" +#line 729 "reflect.h2" //----------------------------------------------------------------------- // partially_ordered - a partially ordered type // auto partially_ordered(meta::type_declaration& t) -> void; -#line 695 "reflect.h2" +#line 738 "reflect.h2" //----------------------------------------------------------------------- // // "A value is ... a regular type. It must have all public @@ -554,7 +571,7 @@ auto partially_ordered(meta::type_declaration& t) -> void; // auto copyable(meta::type_declaration& t) -> void; -#line 732 "reflect.h2" +#line 775 "reflect.h2" //----------------------------------------------------------------------- // // basic_value @@ -564,7 +581,7 @@ auto copyable(meta::type_declaration& t) -> void; // auto basic_value(meta::type_declaration& t) -> void; -#line 757 "reflect.h2" +#line 800 "reflect.h2" //----------------------------------------------------------------------- // // "A 'value' is a totally ordered basic_value..." @@ -577,13 +594,13 @@ auto basic_value(meta::type_declaration& t) -> void; // auto value(meta::type_declaration& t) -> void; -#line 773 "reflect.h2" +#line 816 "reflect.h2" auto weakly_ordered_value(meta::type_declaration& t) -> void; -#line 779 "reflect.h2" +#line 822 "reflect.h2" auto partially_ordered_value(meta::type_declaration& t) -> void; -#line 786 "reflect.h2" +#line 829 "reflect.h2" //----------------------------------------------------------------------- // // "By definition, a `struct` is a `class` in which members @@ -611,7 +628,7 @@ auto partially_ordered_value(meta::type_declaration& t) -> void; // auto cpp2_struct(meta::type_declaration& t) -> void; -#line 829 "reflect.h2" +#line 872 "reflect.h2" //----------------------------------------------------------------------- // // "C enumerations constitute a curiously half-baked concept. ... @@ -641,7 +658,7 @@ auto basic_enum( cpp2::in bitwise ) -> void; -#line 1021 "reflect.h2" +#line 1064 "reflect.h2" //----------------------------------------------------------------------- // // "An enum[...] is a totally ordered value type that stores a @@ -653,7 +670,7 @@ auto basic_enum( // auto cpp2_enum(meta::type_declaration& t) -> void; -#line 1047 "reflect.h2" +#line 1090 "reflect.h2" //----------------------------------------------------------------------- // // "flag_enum expresses an enumeration that stores values @@ -666,7 +683,7 @@ auto cpp2_enum(meta::type_declaration& t) -> void; // auto flag_enum(meta::type_declaration& t) -> void; -#line 1079 "reflect.h2" +#line 1122 "reflect.h2" //----------------------------------------------------------------------- // // "As with void*, programmers should know that unions [...] are @@ -693,14 +710,14 @@ auto flag_enum(meta::type_declaration& t) -> void; auto cpp2_union(meta::type_declaration& t) -> void; -#line 1226 "reflect.h2" +#line 1269 "reflect.h2" //----------------------------------------------------------------------- // // print - output a pretty-printed visualization of t // auto print(cpp2::in t) -> void; -#line 1236 "reflect.h2" +#line 1279 "reflect.h2" //----------------------------------------------------------------------- // // apply_metafunctions @@ -711,7 +728,7 @@ auto print(cpp2::in t) -> void; auto const& error ) -> bool; -#line 1340 "reflect.h2" +#line 1383 "reflect.h2" } } @@ -726,33 +743,35 @@ namespace cpp2 { namespace meta { -#line 42 "reflect.h2" +#line 43 "reflect.h2" compiler_services::compiler_services( std::vector* errors_, - std::deque* generated_tokens_ + std::deque* generated_tokens_, + std::vector>* generated_declarations_ ) : errors{ errors_ } , errors_original_size{ cpp2::unsafe_narrow(std::ssize(*cpp2::assert_not_null(errors))) } , generated_tokens{ generated_tokens_ } + , generated_declarations{ generated_declarations_ } , parser{ *cpp2::assert_not_null(errors) } -#line 47 "reflect.h2" +#line 49 "reflect.h2" { -#line 52 "reflect.h2" +#line 55 "reflect.h2" } auto compiler_services::set_metafunction_name(cpp2::in name, cpp2::in> args) & -> void{ metafunction_name = name; metafunction_args = args; - metafunctions_used = CPP2_UFCS_0(empty, args); + metafunctions_used = CPP2_UFCS(empty)(args); } [[nodiscard]] auto compiler_services::get_metafunction_name() const& -> std::string_view { return metafunction_name; } [[nodiscard]] auto compiler_services::get_argument(cpp2::in index) & -> std::string{ metafunctions_used = true; - if (([_0 = 0, _1 = index, _2 = CPP2_UFCS_0(ssize, metafunction_args)]{ return cpp2::cmp_less_eq(_0,_1) && cpp2::cmp_less(_1,_2); }())) { + if (([_0 = 0, _1 = index, _2 = CPP2_UFCS(ssize)(metafunction_args)]{ return cpp2::cmp_less_eq(_0,_1) && cpp2::cmp_less(_1,_2); }())) { return CPP2_ASSERT_IN_BOUNDS(metafunction_args, index); } return ""; @@ -760,59 +779,92 @@ namespace meta { [[nodiscard]] auto compiler_services::arguments_were_used() const& -> bool { return metafunctions_used; } - [[nodiscard]] auto compiler_services::parse_statement( + [[nodiscard]] auto compiler_services::tokenize( std::string_view source - ) & -> std::unique_ptr + ) & -> auto { - CPP2_UFCS(push_back, generated_lines, std::vector()); - auto lines {&CPP2_UFCS_0(back, generated_lines)}; + CPP2_UFCS(push_back)(generated_lines, std::vector()); + auto lines {&CPP2_UFCS(back)(generated_lines)}; auto add_line {[&, _1 = lines](cpp2::in s) -> void{ - static_cast(CPP2_UFCS(emplace_back, (*cpp2::assert_not_null(_1)), s, source_line::category::cpp2)); + static_cast(CPP2_UFCS(emplace_back)((*cpp2::assert_not_null(_1)), s, source_line::category::cpp2)); }}; { -auto newline_pos = CPP2_UFCS(find, source, '\n'); +auto newline_pos = CPP2_UFCS(find)(source, '\n'); // First split this string into source_lines // -#line 88 "reflect.h2" - if ( cpp2::cmp_greater(CPP2_UFCS_0(ssize, source),1) +#line 91 "reflect.h2" + if ( cpp2::cmp_greater(CPP2_UFCS(ssize)(source),1) && newline_pos != source.npos) { while( newline_pos != std::string_view::npos ) { - add_line(CPP2_UFCS(substr, source, 0, newline_pos)); - CPP2_UFCS(remove_prefix, source, newline_pos + 1); - newline_pos = CPP2_UFCS(find, source, '\n'); + add_line(CPP2_UFCS(substr)(source, 0, newline_pos)); + CPP2_UFCS(remove_prefix)(source, newline_pos + 1); + newline_pos = CPP2_UFCS(find)(source, '\n'); } } } -#line 99 "reflect.h2" - if (!(CPP2_UFCS_0(empty, source))) { +#line 102 "reflect.h2" + if (!(CPP2_UFCS(empty)(source))) { std::move(add_line)(std::move(source)); } // Now lex this source fragment to generate // a single grammar_map entry, whose .second // is the vector of tokens - static_cast(CPP2_UFCS(emplace_back, generated_lexers, *cpp2::assert_not_null(errors))); - auto tokens {&CPP2_UFCS_0(back, generated_lexers)}; - CPP2_UFCS(lex, (*cpp2::assert_not_null(tokens)), *cpp2::assert_not_null(std::move(lines)), true); + static_cast(CPP2_UFCS(emplace_back)(generated_lexers, *cpp2::assert_not_null(errors))); + auto tokens {&CPP2_UFCS(back)(generated_lexers)}; + CPP2_UFCS(lex)((*cpp2::assert_not_null(tokens)), *cpp2::assert_not_null(std::move(lines)), true); + + cpp2::Default.expects(std::ssize(CPP2_UFCS(get_map)((*cpp2::assert_not_null(tokens)))) == 1, ""); - cpp2::Default.expects(std::ssize(CPP2_UFCS_0(get_map, (*cpp2::assert_not_null(tokens)))) == 1, ""); + return tokens; + } + + [[nodiscard]] auto compiler_services::parse_statement( + + std::string_view source + ) & -> std::unique_ptr + + { + auto tokens {tokenize(std::move(source))}; // Now parse this single declaration from // the lexed tokens - return CPP2_UFCS(parse_one_declaration, parser, - (*cpp2::assert_not_null(CPP2_UFCS_0(begin, CPP2_UFCS_0(get_map, *cpp2::assert_not_null(std::move(tokens)))))).second, + return CPP2_UFCS(parse_one_statement)(parser, + (*cpp2::assert_not_null(CPP2_UFCS(begin)(CPP2_UFCS(get_map)(*cpp2::assert_not_null(std::move(tokens)))))).second, *cpp2::assert_not_null(generated_tokens) ); } + [[nodiscard]] auto compiler_services::parse_and_add_declaration( + + std::string_view source + ) & -> bool + + { + auto tokens {tokenize(std::move(source))}; + + // Now parse this single declaration from + // the lexed tokens + auto decl {CPP2_UFCS(parse_one_declaration)(parser, + (*cpp2::assert_not_null(CPP2_UFCS(begin)(CPP2_UFCS(get_map)(*cpp2::assert_not_null(std::move(tokens)))))).second, + *cpp2::assert_not_null(generated_tokens) + )}; + + if (decl) { + CPP2_UFCS(push_back)((*cpp2::assert_not_null(generated_declarations)), std::move(decl)); + return true; + } + return false; + } + [[nodiscard]] auto compiler_services::position() const -> source_position { @@ -833,10 +885,10 @@ auto newline_pos = CPP2_UFCS(find, source, '\n'); auto compiler_services::error(cpp2::in msg) const& -> void { auto message {cpp2::as_(msg)}; - if (!(CPP2_UFCS_0(empty, metafunction_name))) { + if (!(CPP2_UFCS(empty)(metafunction_name))) { message = "while applying @" + metafunction_name + " - " + message; } - static_cast(CPP2_UFCS(emplace_back, (*cpp2::assert_not_null(errors)), position(), std::move(message))); + static_cast(CPP2_UFCS(emplace_back)((*cpp2::assert_not_null(errors)), position(), std::move(message))); } compiler_services::~compiler_services() noexcept{} @@ -844,12 +896,13 @@ compiler_services::compiler_services(compiler_services const& that) : errors{ that.errors } , errors_original_size{ that.errors_original_size } , generated_tokens{ that.generated_tokens } + , generated_declarations{ that.generated_declarations } , parser{ that.parser } , metafunction_name{ that.metafunction_name } , metafunction_args{ that.metafunction_args } , metafunctions_used{ that.metafunctions_used }{} -#line 199 "reflect.h2" +#line 235 "reflect.h2" declaration_base::declaration_base( declaration_node* n_, @@ -857,71 +910,71 @@ compiler_services::compiler_services(compiler_services const& that) ) : compiler_services{ s } , n{ n_ } -#line 204 "reflect.h2" +#line 240 "reflect.h2" { -#line 207 "reflect.h2" +#line 243 "reflect.h2" cpp2::Default.expects(n, "a meta::declaration must point to a valid declaration_node, not null"); } - [[nodiscard]] auto declaration_base::position() const -> source_position { return CPP2_UFCS_0(position, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration_base::position() const -> source_position { return CPP2_UFCS(position)((*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration_base::print() const& -> std::string { return CPP2_UFCS(pretty_print_visualize, (*cpp2::assert_not_null(n)), 0); } + [[nodiscard]] auto declaration_base::print() const& -> std::string { return CPP2_UFCS(pretty_print_visualize)((*cpp2::assert_not_null(n)), 0); } declaration_base::~declaration_base() noexcept{} declaration_base::declaration_base(declaration_base const& that) : compiler_services{ static_cast(that) } , n{ that.n }{} -#line 223 "reflect.h2" +#line 259 "reflect.h2" declaration::declaration( declaration_node* n_, cpp2::in s ) : declaration_base{ n_, s } -#line 228 "reflect.h2" +#line 264 "reflect.h2" { } - [[nodiscard]] auto declaration::is_public() const& -> bool { return CPP2_UFCS_0(is_public, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_protected() const& -> bool { return CPP2_UFCS_0(is_protected, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_private() const& -> bool { return CPP2_UFCS_0(is_private, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_default_access() const& -> bool { return CPP2_UFCS_0(is_default_access, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_public() const& -> bool { return CPP2_UFCS(is_public)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_protected() const& -> bool { return CPP2_UFCS(is_protected)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_private() const& -> bool { return CPP2_UFCS(is_private)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_default_access() const& -> bool { return CPP2_UFCS(is_default_access)((*cpp2::assert_not_null(n))); } - auto declaration::default_to_public() & -> void { static_cast(CPP2_UFCS_0(make_public, (*cpp2::assert_not_null(n)))); } - auto declaration::default_to_protected() & -> void { static_cast(CPP2_UFCS_0(make_protected, (*cpp2::assert_not_null(n)))); } - auto declaration::default_to_private() & -> void { static_cast(CPP2_UFCS_0(make_private, (*cpp2::assert_not_null(n)))); } + auto declaration::default_to_public() & -> void { static_cast(CPP2_UFCS(make_public)((*cpp2::assert_not_null(n)))); } + auto declaration::default_to_protected() & -> void { static_cast(CPP2_UFCS(make_protected)((*cpp2::assert_not_null(n)))); } + auto declaration::default_to_private() & -> void { static_cast(CPP2_UFCS(make_private)((*cpp2::assert_not_null(n)))); } - [[nodiscard]] auto declaration::make_public() & -> bool { return CPP2_UFCS_0(make_public, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::make_protected() & -> bool { return CPP2_UFCS_0(make_protected, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::make_private() & -> bool { return CPP2_UFCS_0(make_private, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::make_public() & -> bool { return CPP2_UFCS(make_public)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::make_protected() & -> bool { return CPP2_UFCS(make_protected)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::make_private() & -> bool { return CPP2_UFCS(make_private)((*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::has_name() const& -> bool { return CPP2_UFCS_0(has_name, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::has_name(cpp2::in s) const& -> bool { return CPP2_UFCS(has_name, (*cpp2::assert_not_null(n)), s); } + [[nodiscard]] auto declaration::has_name() const& -> bool { return CPP2_UFCS(has_name)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::has_name(cpp2::in s) const& -> bool { return CPP2_UFCS(has_name)((*cpp2::assert_not_null(n)), s); } [[nodiscard]] auto declaration::name() const& -> std::string_view{ - if (has_name()) {return CPP2_UFCS_0(as_string_view, (*cpp2::assert_not_null(CPP2_UFCS_0(name, *cpp2::assert_not_null(n))))); } + if (has_name()) {return CPP2_UFCS(as_string_view)((*cpp2::assert_not_null(CPP2_UFCS(name)(*cpp2::assert_not_null(n))))); } else { return ""; } } - [[nodiscard]] auto declaration::has_initializer() const& -> bool { return CPP2_UFCS_0(has_initializer, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::has_initializer() const& -> bool { return CPP2_UFCS(has_initializer)((*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_global() const& -> bool { return CPP2_UFCS_0(is_global, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_function() const& -> bool { return CPP2_UFCS_0(is_function, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_object() const& -> bool { return CPP2_UFCS_0(is_object, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_base_object() const& -> bool { return CPP2_UFCS_0(is_base_object, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_member_object() const& -> bool { return CPP2_UFCS_0(is_member_object, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_type() const& -> bool { return CPP2_UFCS_0(is_type, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_namespace() const& -> bool { return CPP2_UFCS_0(is_namespace, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_alias() const& -> bool { return CPP2_UFCS_0(is_alias, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_global() const& -> bool { return CPP2_UFCS(is_global)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_function() const& -> bool { return CPP2_UFCS(is_function)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_object() const& -> bool { return CPP2_UFCS(is_object)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_base_object() const& -> bool { return CPP2_UFCS(is_base_object)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_member_object() const& -> bool { return CPP2_UFCS(is_member_object)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_type() const& -> bool { return CPP2_UFCS(is_type)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_namespace() const& -> bool { return CPP2_UFCS(is_namespace)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_alias() const& -> bool { return CPP2_UFCS(is_alias)((*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_type_alias() const& -> bool { return CPP2_UFCS_0(is_type_alias, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_namespace_alias() const& -> bool { return CPP2_UFCS_0(is_namespace_alias, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_object_alias() const& -> bool { return CPP2_UFCS_0(is_object_alias, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_type_alias() const& -> bool { return CPP2_UFCS(is_type_alias)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_namespace_alias() const& -> bool { return CPP2_UFCS(is_namespace_alias)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_object_alias() const& -> bool { return CPP2_UFCS(is_object_alias)((*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::is_function_expression() const& -> bool { return CPP2_UFCS_0(is_function_expression, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::is_function_expression() const& -> bool { return CPP2_UFCS(is_function_expression)((*cpp2::assert_not_null(n))); } [[nodiscard]] auto declaration::as_function() const& -> function_declaration { return function_declaration(n, (*this)); } [[nodiscard]] auto declaration::as_object() const& -> object_declaration { return object_declaration(n, (*this)); } @@ -930,24 +983,24 @@ declaration_base::declaration_base(declaration_base const& that) [[nodiscard]] auto declaration::get_parent() const& -> declaration { return declaration(n, (*this)); } - [[nodiscard]] auto declaration::parent_is_function() const& -> bool { return CPP2_UFCS_0(parent_is_function, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::parent_is_object() const& -> bool { return CPP2_UFCS_0(parent_is_object, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::parent_is_type() const& -> bool { return CPP2_UFCS_0(parent_is_type, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::parent_is_namespace() const& -> bool { return CPP2_UFCS_0(parent_is_namespace, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::parent_is_alias() const& -> bool { return CPP2_UFCS_0(parent_is_alias, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::parent_is_function() const& -> bool { return CPP2_UFCS(parent_is_function)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::parent_is_object() const& -> bool { return CPP2_UFCS(parent_is_object)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::parent_is_type() const& -> bool { return CPP2_UFCS(parent_is_type)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::parent_is_namespace() const& -> bool { return CPP2_UFCS(parent_is_namespace)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::parent_is_alias() const& -> bool { return CPP2_UFCS(parent_is_alias)((*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::parent_is_type_alias() const& -> bool { return CPP2_UFCS_0(parent_is_type_alias, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::parent_is_namespace_alias() const& -> bool { return CPP2_UFCS_0(parent_is_namespace_alias, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::parent_is_object_alias() const& -> bool { return CPP2_UFCS_0(parent_is_object_alias, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::parent_is_type_alias() const& -> bool { return CPP2_UFCS(parent_is_type_alias)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::parent_is_namespace_alias() const& -> bool { return CPP2_UFCS(parent_is_namespace_alias)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::parent_is_object_alias() const& -> bool { return CPP2_UFCS(parent_is_object_alias)((*cpp2::assert_not_null(n))); } - [[nodiscard]] auto declaration::parent_is_polymorphic() const& -> bool { return CPP2_UFCS_0(parent_is_polymorphic, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto declaration::parent_is_polymorphic() const& -> bool { return CPP2_UFCS(parent_is_polymorphic)((*cpp2::assert_not_null(n))); } auto declaration::mark_for_removal_from_enclosing_type() & -> void { cpp2::Type.expects(parent_is_type(), ""); -#line 292 "reflect.h2" - auto test {CPP2_UFCS_0(type_member_mark_for_removal, (*cpp2::assert_not_null(n)))}; +#line 328 "reflect.h2" + auto test {CPP2_UFCS(type_member_mark_for_removal)((*cpp2::assert_not_null(n)))}; cpp2::Default.expects(std::move(test), ""); // ... to ensure this assert is true } @@ -955,85 +1008,85 @@ declaration_base::declaration_base(declaration_base const& that) declaration::declaration(declaration const& that) : declaration_base{ static_cast(that) }{} -#line 305 "reflect.h2" +#line 341 "reflect.h2" function_declaration::function_declaration( declaration_node* n_, cpp2::in s ) : declaration{ n_, s } -#line 310 "reflect.h2" +#line 346 "reflect.h2" { - cpp2::Default.expects(CPP2_UFCS_0(is_function, (*cpp2::assert_not_null(n))), ""); + cpp2::Default.expects(CPP2_UFCS(is_function)((*cpp2::assert_not_null(n))), ""); } - [[nodiscard]] auto function_declaration::index_of_parameter_named(cpp2::in s) const& -> int { return CPP2_UFCS(index_of_parameter_named, (*cpp2::assert_not_null(n)), s); } - [[nodiscard]] auto function_declaration::has_parameter_named(cpp2::in s) const& -> bool { return CPP2_UFCS(has_parameter_named, (*cpp2::assert_not_null(n)), s); } - [[nodiscard]] auto function_declaration::has_in_parameter_named(cpp2::in s) const& -> bool { return CPP2_UFCS(has_in_parameter_named, (*cpp2::assert_not_null(n)), s); } - [[nodiscard]] auto function_declaration::has_out_parameter_named(cpp2::in s) const& -> bool { return CPP2_UFCS(has_out_parameter_named, (*cpp2::assert_not_null(n)), s); } - [[nodiscard]] auto function_declaration::has_move_parameter_named(cpp2::in s) const& -> bool { return CPP2_UFCS(has_move_parameter_named, (*cpp2::assert_not_null(n)), s); } + [[nodiscard]] auto function_declaration::index_of_parameter_named(cpp2::in s) const& -> int { return CPP2_UFCS(index_of_parameter_named)((*cpp2::assert_not_null(n)), s); } + [[nodiscard]] auto function_declaration::has_parameter_named(cpp2::in s) const& -> bool { return CPP2_UFCS(has_parameter_named)((*cpp2::assert_not_null(n)), s); } + [[nodiscard]] auto function_declaration::has_in_parameter_named(cpp2::in s) const& -> bool { return CPP2_UFCS(has_in_parameter_named)((*cpp2::assert_not_null(n)), s); } + [[nodiscard]] auto function_declaration::has_out_parameter_named(cpp2::in s) const& -> bool { return CPP2_UFCS(has_out_parameter_named)((*cpp2::assert_not_null(n)), s); } + [[nodiscard]] auto function_declaration::has_move_parameter_named(cpp2::in s) const& -> bool { return CPP2_UFCS(has_move_parameter_named)((*cpp2::assert_not_null(n)), s); } [[nodiscard]] auto function_declaration::has_parameter_with_name_and_pass(cpp2::in s, cpp2::in pass) const& -> bool { - return CPP2_UFCS(has_parameter_with_name_and_pass, (*cpp2::assert_not_null(n)), s, pass); } - [[nodiscard]] auto function_declaration::is_function_with_this() const& -> bool { return CPP2_UFCS_0(is_function_with_this, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_virtual() const& -> bool { return CPP2_UFCS_0(is_virtual_function, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_defaultable() const& -> bool { return CPP2_UFCS_0(is_defaultable_function, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_constructor() const& -> bool { return CPP2_UFCS_0(is_constructor, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_default_constructor() const& -> bool { return CPP2_UFCS_0(is_default_constructor, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_move() const& -> bool { return CPP2_UFCS_0(is_move, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_swap() const& -> bool { return CPP2_UFCS_0(is_swap, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_constructor_with_that() const& -> bool { return CPP2_UFCS_0(is_constructor_with_that, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_constructor_with_in_that() const& -> bool { return CPP2_UFCS_0(is_constructor_with_in_that, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_constructor_with_move_that() const& -> bool { return CPP2_UFCS_0(is_constructor_with_move_that, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_assignment() const& -> bool { return CPP2_UFCS_0(is_assignment, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_assignment_with_that() const& -> bool { return CPP2_UFCS_0(is_assignment_with_that, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_assignment_with_in_that() const& -> bool { return CPP2_UFCS_0(is_assignment_with_in_that, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_assignment_with_move_that() const& -> bool { return CPP2_UFCS_0(is_assignment_with_move_that, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_destructor() const& -> bool { return CPP2_UFCS_0(is_destructor, (*cpp2::assert_not_null(n))); } + return CPP2_UFCS(has_parameter_with_name_and_pass)((*cpp2::assert_not_null(n)), s, pass); } + [[nodiscard]] auto function_declaration::is_function_with_this() const& -> bool { return CPP2_UFCS(is_function_with_this)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_virtual() const& -> bool { return CPP2_UFCS(is_virtual_function)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_defaultable() const& -> bool { return CPP2_UFCS(is_defaultable_function)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_constructor() const& -> bool { return CPP2_UFCS(is_constructor)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_default_constructor() const& -> bool { return CPP2_UFCS(is_default_constructor)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_move() const& -> bool { return CPP2_UFCS(is_move)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_swap() const& -> bool { return CPP2_UFCS(is_swap)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_constructor_with_that() const& -> bool { return CPP2_UFCS(is_constructor_with_that)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_constructor_with_in_that() const& -> bool { return CPP2_UFCS(is_constructor_with_in_that)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_constructor_with_move_that() const& -> bool { return CPP2_UFCS(is_constructor_with_move_that)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_assignment() const& -> bool { return CPP2_UFCS(is_assignment)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_assignment_with_that() const& -> bool { return CPP2_UFCS(is_assignment_with_that)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_assignment_with_in_that() const& -> bool { return CPP2_UFCS(is_assignment_with_in_that)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_assignment_with_move_that() const& -> bool { return CPP2_UFCS(is_assignment_with_move_that)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_destructor() const& -> bool { return CPP2_UFCS(is_destructor)((*cpp2::assert_not_null(n))); } [[nodiscard]] auto function_declaration::is_copy_or_move() const& -> bool { return is_constructor_with_that() || is_assignment_with_that(); } - [[nodiscard]] auto function_declaration::has_declared_return_type() const& -> bool { return CPP2_UFCS_0(has_declared_return_type, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::has_bool_return_type() const& -> bool { return CPP2_UFCS_0(has_bool_return_type, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::has_non_void_return_type() const& -> bool { return CPP2_UFCS_0(has_non_void_return_type, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::has_declared_return_type() const& -> bool { return CPP2_UFCS(has_declared_return_type)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::has_bool_return_type() const& -> bool { return CPP2_UFCS(has_bool_return_type)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::has_non_void_return_type() const& -> bool { return CPP2_UFCS(has_non_void_return_type)((*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::unnamed_return_type() const& -> std::string { return CPP2_UFCS_0(unnamed_return_type_to_string, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::unnamed_return_type() const& -> std::string { return CPP2_UFCS(unnamed_return_type_to_string)((*cpp2::assert_not_null(n))); } - [[nodiscard]] auto function_declaration::is_binary_comparison_function() const& -> bool { return CPP2_UFCS_0(is_binary_comparison_function, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::is_binary_comparison_function() const& -> bool { return CPP2_UFCS(is_binary_comparison_function)((*cpp2::assert_not_null(n))); } - auto function_declaration::default_to_virtual() & -> void { static_cast(CPP2_UFCS_0(make_function_virtual, (*cpp2::assert_not_null(n)))); } + auto function_declaration::default_to_virtual() & -> void { static_cast(CPP2_UFCS(make_function_virtual)((*cpp2::assert_not_null(n)))); } - [[nodiscard]] auto function_declaration::make_virtual() & -> bool { return CPP2_UFCS_0(make_function_virtual, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto function_declaration::make_virtual() & -> bool { return CPP2_UFCS(make_function_virtual)((*cpp2::assert_not_null(n))); } function_declaration::function_declaration(function_declaration const& that) : declaration{ static_cast(that) }{} -#line 362 "reflect.h2" +#line 398 "reflect.h2" object_declaration::object_declaration( declaration_node* n_, cpp2::in s ) : declaration{ n_, s } -#line 367 "reflect.h2" +#line 403 "reflect.h2" { - cpp2::Default.expects(CPP2_UFCS_0(is_object, (*cpp2::assert_not_null(n))), ""); + cpp2::Default.expects(CPP2_UFCS(is_object)((*cpp2::assert_not_null(n))), ""); } - [[nodiscard]] auto object_declaration::is_const() const& -> bool { return CPP2_UFCS_0(is_const, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto object_declaration::has_wildcard_type() const& -> bool { return CPP2_UFCS_0(has_wildcard_type, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto object_declaration::is_const() const& -> bool { return CPP2_UFCS(is_const)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto object_declaration::has_wildcard_type() const& -> bool { return CPP2_UFCS(has_wildcard_type)((*cpp2::assert_not_null(n))); } [[nodiscard]] auto object_declaration::type() const& -> std::string{ - auto ret {CPP2_UFCS_0(object_type, (*cpp2::assert_not_null(n)))}; + auto ret {CPP2_UFCS(object_type)((*cpp2::assert_not_null(n)))}; require(!(contains(ret, "(*ERROR*)")), "cannot to_string this type: " + ret); return ret; } [[nodiscard]] auto object_declaration::initializer() const& -> std::string{ - auto ret {CPP2_UFCS_0(object_initializer, (*cpp2::assert_not_null(n)))}; + auto ret {CPP2_UFCS(object_initializer)((*cpp2::assert_not_null(n)))}; require(!(contains(ret, "(*ERROR*)")), "cannot to_string this initializer: " + ret); return ret; @@ -1042,24 +1095,24 @@ declaration::declaration(declaration const& that) object_declaration::object_declaration(object_declaration const& that) : declaration{ static_cast(that) }{} -#line 398 "reflect.h2" +#line 434 "reflect.h2" type_declaration::type_declaration( declaration_node* n_, cpp2::in s ) : declaration{ n_, s } -#line 403 "reflect.h2" +#line 439 "reflect.h2" { - cpp2::Default.expects(CPP2_UFCS_0(is_type, (*cpp2::assert_not_null(n))), ""); + cpp2::Default.expects(CPP2_UFCS(is_type)((*cpp2::assert_not_null(n))), ""); } auto type_declaration::reserve_names(cpp2::in name, auto&& ...etc) const& -> void { // etc is not declared ':string_view' for compatibility with GCC 10.x for ( auto const& m : get_members() ) { - CPP2_UFCS(require, m, !(CPP2_UFCS(has_name, m, name)), + CPP2_UFCS(require)(m, !(CPP2_UFCS(has_name)(m, name)), "in a '" + cpp2::to_string(get_metafunction_name()) + "' type, the name '" + cpp2::to_string(name) + "' is reserved for use by the '" + cpp2::to_string(get_metafunction_name()) + "' implementation"); } if constexpr (!(CPP2_PACK_EMPTY(etc))) { @@ -1067,16 +1120,16 @@ declaration::declaration(declaration const& that) } } - [[nodiscard]] auto type_declaration::is_polymorphic() const& -> bool { return CPP2_UFCS_0(is_polymorphic, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto type_declaration::is_final() const& -> bool { return CPP2_UFCS_0(is_type_final, (*cpp2::assert_not_null(n))); } - [[nodiscard]] auto type_declaration::make_final() & -> bool { return CPP2_UFCS_0(make_type_final, (*cpp2::assert_not_null(n))); } + [[nodiscard]] auto type_declaration::is_polymorphic() const& -> bool { return CPP2_UFCS(is_polymorphic)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto type_declaration::is_final() const& -> bool { return CPP2_UFCS(is_type_final)((*cpp2::assert_not_null(n))); } + [[nodiscard]] auto type_declaration::make_final() & -> bool { return CPP2_UFCS(make_type_final)((*cpp2::assert_not_null(n))); } [[nodiscard]] auto type_declaration::get_member_functions() const& -> std::vector { std::vector ret {}; - for ( auto const& d : CPP2_UFCS(get_type_scope_declarations, (*cpp2::assert_not_null(n)), declaration_node::functions) ) { - static_cast(CPP2_UFCS(emplace_back, ret, d, (*this))); + for ( auto const& d : CPP2_UFCS(get_type_scope_declarations)((*cpp2::assert_not_null(n)), declaration_node::functions) ) { + static_cast(CPP2_UFCS(emplace_back)(ret, d, (*this))); } return ret; } @@ -1085,8 +1138,8 @@ declaration::declaration(declaration const& that) { std::vector ret {}; - for ( auto const& d : CPP2_UFCS(get_type_scope_declarations, (*cpp2::assert_not_null(n)), declaration_node::objects) ) { - static_cast(CPP2_UFCS(emplace_back, ret, d, (*this))); + for ( auto const& d : CPP2_UFCS(get_type_scope_declarations)((*cpp2::assert_not_null(n)), declaration_node::objects) ) { + static_cast(CPP2_UFCS(emplace_back)(ret, d, (*this))); } return ret; } @@ -1095,8 +1148,8 @@ declaration::declaration(declaration const& that) { std::vector ret {}; - for ( auto const& d : CPP2_UFCS(get_type_scope_declarations, (*cpp2::assert_not_null(n)), declaration_node::types) ) { - static_cast(CPP2_UFCS(emplace_back, ret, d, (*this))); + for ( auto const& d : CPP2_UFCS(get_type_scope_declarations)((*cpp2::assert_not_null(n)), declaration_node::types) ) { + static_cast(CPP2_UFCS(emplace_back)(ret, d, (*this))); } return ret; } @@ -1105,8 +1158,8 @@ declaration::declaration(declaration const& that) { std::vector ret {}; - for ( auto const& d : CPP2_UFCS(get_type_scope_declarations, (*cpp2::assert_not_null(n)), declaration_node::aliases) ) { - static_cast(CPP2_UFCS(emplace_back, ret, d, (*this))); + for ( auto const& d : CPP2_UFCS(get_type_scope_declarations)((*cpp2::assert_not_null(n)), declaration_node::aliases) ) { + static_cast(CPP2_UFCS(emplace_back)(ret, d, (*this))); } return ret; } @@ -1115,22 +1168,22 @@ declaration::declaration(declaration const& that) { std::vector ret {}; - for ( auto const& d : CPP2_UFCS(get_type_scope_declarations, (*cpp2::assert_not_null(n)), declaration_node::all) ) { - static_cast(CPP2_UFCS(emplace_back, ret, d, (*this))); + for ( auto const& d : CPP2_UFCS(get_type_scope_declarations)((*cpp2::assert_not_null(n)), declaration_node::all) ) { + static_cast(CPP2_UFCS(emplace_back)(ret, d, (*this))); } return ret; } [[nodiscard]] auto type_declaration::query_declared_value_set_functions() const& -> query_declared_value_set_functions_ret -#line 481 "reflect.h2" +#line 517 "reflect.h2" { cpp2::deferred_init out_this_in_that; cpp2::deferred_init out_this_move_that; cpp2::deferred_init inout_this_in_that; cpp2::deferred_init inout_this_move_that; -#line 482 "reflect.h2" - auto declared {CPP2_UFCS_0(find_declared_value_set_functions, (*cpp2::assert_not_null(n)))}; +#line 518 "reflect.h2" + auto declared {CPP2_UFCS(find_declared_value_set_functions)((*cpp2::assert_not_null(n)))}; out_this_in_that.construct(declared.out_this_in_that != nullptr); out_this_move_that.construct(declared.out_this_move_that != nullptr); inout_this_in_that.construct(declared.inout_this_in_that != nullptr); @@ -1140,94 +1193,101 @@ declaration::declaration(declaration const& that) auto type_declaration::add_member(cpp2::in source) & -> void { auto decl {parse_statement(source)}; - if (!(decl) || !(CPP2_UFCS(add_type_member, (*cpp2::assert_not_null(n)), std::move(decl)))) { + if (!(decl) || !(CPP2_UFCS(add_type_member)((*cpp2::assert_not_null(n)), std::move(decl)))) { error(std::string("error attempting to add member:\n") + source); } } - auto type_declaration::remove_marked_members() & -> void { CPP2_UFCS_0(type_remove_marked_members, (*cpp2::assert_not_null(n))); } - auto type_declaration::remove_all_members() & -> void { CPP2_UFCS_0(type_remove_all_members, (*cpp2::assert_not_null(n))); } + auto type_declaration::add_declaration_to_parent_namespace(cpp2::in source) & -> void + { + if (!(parse_and_add_declaration(source))) { + error(std::string("error attempting to add declaration:\n") + source); + } + } - auto type_declaration::disable_member_function_generation() & -> void { CPP2_UFCS_0(type_disable_member_function_generation, (*cpp2::assert_not_null(n))); } + auto type_declaration::remove_marked_members() & -> void { CPP2_UFCS(type_remove_marked_members)((*cpp2::assert_not_null(n))); } + auto type_declaration::remove_all_members() & -> void { CPP2_UFCS(type_remove_all_members)((*cpp2::assert_not_null(n))); } + + auto type_declaration::disable_member_function_generation() & -> void { CPP2_UFCS(type_disable_member_function_generation)((*cpp2::assert_not_null(n))); } type_declaration::type_declaration(type_declaration const& that) : declaration{ static_cast(that) }{} -#line 511 "reflect.h2" +#line 554 "reflect.h2" alias_declaration::alias_declaration( declaration_node* n_, cpp2::in s ) : declaration{ n_, s } -#line 516 "reflect.h2" +#line 559 "reflect.h2" { - cpp2::Default.expects(CPP2_UFCS_0(is_alias, (*cpp2::assert_not_null(n))), ""); + cpp2::Default.expects(CPP2_UFCS(is_alias)((*cpp2::assert_not_null(n))), ""); } alias_declaration::alias_declaration(alias_declaration const& that) : declaration{ static_cast(that) }{} -#line 535 "reflect.h2" +#line 578 "reflect.h2" auto add_virtual_destructor(meta::type_declaration& t) -> void { - CPP2_UFCS(add_member, t, "operator=: (virtual move this) = { }"); + CPP2_UFCS(add_member)(t, "operator=: (virtual move this) = { }"); } -#line 553 "reflect.h2" +#line 596 "reflect.h2" auto interface(meta::type_declaration& t) -> void { auto has_dtor {false}; - for ( auto& m : CPP2_UFCS_0(get_members, t) ) + for ( auto& m : CPP2_UFCS(get_members)(t) ) { - CPP2_UFCS(require, m, !(CPP2_UFCS_0(is_object, m)), + CPP2_UFCS(require)(m, !(CPP2_UFCS(is_object)(m)), "interfaces may not contain data objects"); - if (CPP2_UFCS_0(is_function, m)) { - auto mf {CPP2_UFCS_0(as_function, m)}; - CPP2_UFCS(require, mf, !(CPP2_UFCS_0(is_copy_or_move, mf)), + if (CPP2_UFCS(is_function)(m)) { + auto mf {CPP2_UFCS(as_function)(m)}; + CPP2_UFCS(require)(mf, !(CPP2_UFCS(is_copy_or_move)(mf)), "interfaces may not copy or move; consider a virtual clone() instead"); - CPP2_UFCS(require, mf, !(CPP2_UFCS_0(has_initializer, mf)), + CPP2_UFCS(require)(mf, !(CPP2_UFCS(has_initializer)(mf)), "interface functions must not have a function body; remove the '=' initializer"); - CPP2_UFCS(require, mf, CPP2_UFCS_0(make_public, mf), + CPP2_UFCS(require)(mf, CPP2_UFCS(make_public)(mf), "interface functions must be public"); - CPP2_UFCS_0(default_to_virtual, mf); - has_dtor |= CPP2_UFCS_0(is_destructor, mf); + CPP2_UFCS(default_to_virtual)(mf); + has_dtor |= CPP2_UFCS(is_destructor)(mf); } } if (!(std::move(has_dtor))) { - CPP2_UFCS_0(add_virtual_destructor, t); + CPP2_UFCS(add_virtual_destructor)(t); } } -#line 599 "reflect.h2" +#line 642 "reflect.h2" auto polymorphic_base(meta::type_declaration& t) -> void { auto has_dtor {false}; - for ( auto& mf : CPP2_UFCS_0(get_member_functions, t) ) + for ( auto& mf : CPP2_UFCS(get_member_functions)(t) ) { - if (CPP2_UFCS_0(is_default_access, mf)) { - CPP2_UFCS_0(default_to_public, mf); + if (CPP2_UFCS(is_default_access)(mf)) { + CPP2_UFCS(default_to_public)(mf); } - CPP2_UFCS(require, mf, !(CPP2_UFCS_0(is_copy_or_move, mf)), + CPP2_UFCS(require)(mf, !(CPP2_UFCS(is_copy_or_move)(mf)), "polymorphic base types may not copy or move; consider a virtual clone() instead"); - if (CPP2_UFCS_0(is_destructor, mf)) { + if (CPP2_UFCS(is_destructor)(mf)) { has_dtor = true; - CPP2_UFCS(require, mf, ((CPP2_UFCS_0(is_public, mf) || CPP2_UFCS_0(is_default_access, mf)) && CPP2_UFCS_0(is_virtual, mf)) - || (CPP2_UFCS_0(is_protected, mf) && !(CPP2_UFCS_0(is_virtual, mf))), + CPP2_UFCS(require)(mf, ((CPP2_UFCS(is_public)(mf) || CPP2_UFCS(is_default_access)(mf)) && CPP2_UFCS(is_virtual)(mf)) + || (CPP2_UFCS(is_protected)(mf) && !(CPP2_UFCS(is_virtual)(mf))), "a polymorphic base type destructor must be public and virtual, or protected and nonvirtual"); } } if (!(std::move(has_dtor))) { - CPP2_UFCS_0(add_virtual_destructor, t); + CPP2_UFCS(add_virtual_destructor)(t); } } -#line 644 "reflect.h2" +#line 687 "reflect.h2" auto ordered_impl( meta::type_declaration& t, cpp2::in ordering @@ -1235,49 +1295,49 @@ auto ordered_impl( { auto has_spaceship {false}; - for ( auto& mf : CPP2_UFCS_0(get_member_functions, t) ) + for ( auto& mf : CPP2_UFCS(get_member_functions)(t) ) { - if (CPP2_UFCS(has_name, mf, "operator<=>")) { + if (CPP2_UFCS(has_name)(mf, "operator<=>")) { has_spaceship = true; - auto return_name {CPP2_UFCS_0(unnamed_return_type, mf)}; - if (CPP2_UFCS(find, return_name, ordering) == return_name.npos) + auto return_name {CPP2_UFCS(unnamed_return_type)(mf)}; + if (CPP2_UFCS(find)(return_name, ordering) == return_name.npos) { - CPP2_UFCS(error, mf, "operator<=> must return std::" + cpp2::as_(ordering)); + CPP2_UFCS(error)(mf, "operator<=> must return std::" + cpp2::as_(ordering)); } } } if (!(std::move(has_spaceship))) { - CPP2_UFCS(add_member, t, "operator<=>: (this, that) -> std::" + (cpp2::as_(ordering)) + ";"); + CPP2_UFCS(add_member)(t, "operator<=>: (this, that) -> std::" + (cpp2::as_(ordering)) + ";"); } } -#line 673 "reflect.h2" +#line 716 "reflect.h2" auto ordered(meta::type_declaration& t) -> void { ordered_impl(t, "strong_ordering"); } -#line 681 "reflect.h2" +#line 724 "reflect.h2" auto weakly_ordered(meta::type_declaration& t) -> void { ordered_impl(t, "weak_ordering"); } -#line 689 "reflect.h2" +#line 732 "reflect.h2" auto partially_ordered(meta::type_declaration& t) -> void { ordered_impl(t, "partial_ordering"); } -#line 711 "reflect.h2" +#line 754 "reflect.h2" auto copyable(meta::type_declaration& t) -> void { // If the user explicitly wrote any of the copy/move functions, // they must also have written the most general one - we can't // assume we can safely generate it for them since they've opted // into customized semantics - auto smfs {CPP2_UFCS_0(query_declared_value_set_functions, t)}; + auto smfs {CPP2_UFCS(query_declared_value_set_functions)(t)}; if ( !(smfs.out_this_in_that) && ( smfs.out_this_move_that @@ -1285,70 +1345,70 @@ auto copyable(meta::type_declaration& t) -> void || smfs.inout_this_move_that)) { - 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"); + 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(add_member, t, "operator=: (out this, that) = { }"); + CPP2_UFCS(add_member)(t, "operator=: (out this, that) = { }"); }} } -#line 739 "reflect.h2" +#line 782 "reflect.h2" auto basic_value(meta::type_declaration& t) -> void { - CPP2_UFCS_0(copyable, t); + CPP2_UFCS(copyable)(t); auto has_default_ctor {false}; - for ( auto& mf : CPP2_UFCS_0(get_member_functions, t) ) { - has_default_ctor |= CPP2_UFCS_0(is_default_constructor, mf); - CPP2_UFCS(require, mf, !(CPP2_UFCS_0(is_protected, mf)) && !(CPP2_UFCS_0(is_virtual, mf)), + for ( auto& mf : CPP2_UFCS(get_member_functions)(t) ) { + has_default_ctor |= CPP2_UFCS(is_default_constructor)(mf); + CPP2_UFCS(require)(mf, !(CPP2_UFCS(is_protected)(mf)) && !(CPP2_UFCS(is_virtual)(mf)), "a value type may not have a protected or virtual function"); - CPP2_UFCS(require, mf, !(CPP2_UFCS_0(is_destructor, mf)) || CPP2_UFCS_0(is_public, mf) || CPP2_UFCS_0(is_default_access, mf), + CPP2_UFCS(require)(mf, !(CPP2_UFCS(is_destructor)(mf)) || CPP2_UFCS(is_public)(mf) || CPP2_UFCS(is_default_access)(mf), "a value type may not have a non-public destructor"); } if (!(std::move(has_default_ctor))) { - CPP2_UFCS(add_member, t, "operator=: (out this) = { }"); + CPP2_UFCS(add_member)(t, "operator=: (out this) = { }"); } } -#line 767 "reflect.h2" +#line 810 "reflect.h2" auto value(meta::type_declaration& t) -> void { - CPP2_UFCS_0(ordered, t); - CPP2_UFCS_0(basic_value, t); + CPP2_UFCS(ordered)(t); + CPP2_UFCS(basic_value)(t); } auto weakly_ordered_value(meta::type_declaration& t) -> void { - CPP2_UFCS_0(weakly_ordered, t); - CPP2_UFCS_0(basic_value, t); + CPP2_UFCS(weakly_ordered)(t); + CPP2_UFCS(basic_value)(t); } auto partially_ordered_value(meta::type_declaration& t) -> void { - CPP2_UFCS_0(partially_ordered, t); - CPP2_UFCS_0(basic_value, t); + CPP2_UFCS(partially_ordered)(t); + CPP2_UFCS(basic_value)(t); } -#line 811 "reflect.h2" +#line 854 "reflect.h2" auto cpp2_struct(meta::type_declaration& t) -> void { - for ( auto& m : CPP2_UFCS_0(get_members, t) ) + for ( auto& m : CPP2_UFCS(get_members)(t) ) { - CPP2_UFCS(require, m, CPP2_UFCS_0(make_public, m), + CPP2_UFCS(require)(m, CPP2_UFCS(make_public)(m), "all struct members must be public"); - if (CPP2_UFCS_0(is_function, m)) { - auto mf {CPP2_UFCS_0(as_function, m)}; - CPP2_UFCS(require, t, !(CPP2_UFCS_0(is_virtual, mf)), + if (CPP2_UFCS(is_function)(m)) { + auto mf {CPP2_UFCS(as_function)(m)}; + CPP2_UFCS(require)(t, !(CPP2_UFCS(is_virtual)(mf)), "a struct may not have a virtual function"); - CPP2_UFCS(require, t, !(CPP2_UFCS(has_name, mf, "operator=")), + CPP2_UFCS(require)(t, !(CPP2_UFCS(has_name)(mf, "operator=")), "a struct may not have a user-defined operator="); } } - CPP2_UFCS_0(disable_member_function_generation, t); + CPP2_UFCS(disable_member_function_generation)(t); } -#line 852 "reflect.h2" +#line 895 "reflect.h2" auto basic_enum( meta::type_declaration& t, auto const& nextval, @@ -1360,38 +1420,38 @@ auto basic_enum( cpp2::i64 max_value {}; cpp2::deferred_init underlying_type; - CPP2_UFCS(reserve_names, t, "operator=", "operator<=>"); + CPP2_UFCS(reserve_names)(t, "operator=", "operator<=>"); if (bitwise) { - CPP2_UFCS(reserve_names, t, "has", "set", "clear", "to_string", "get_raw_value", "none"); + CPP2_UFCS(reserve_names)(t, "has", "set", "clear", "to_string", "get_raw_value", "none"); } // 1. Gather: The names of all the user-written members, and find/compute the type - underlying_type.construct(CPP2_UFCS(get_argument, t, 0));// use the first template argument, if there was one + underlying_type.construct(CPP2_UFCS(get_argument)(t, 0));// use the first template argument, if there was one auto found_non_numeric {false}; { std::string value = "-1"; -#line 875 "reflect.h2" +#line 918 "reflect.h2" for ( - auto const& m : CPP2_UFCS_0(get_members, t) ) - if ( CPP2_UFCS_0(is_member_object, m)) + auto const& m : CPP2_UFCS(get_members)(t) ) + if ( CPP2_UFCS(is_member_object)(m)) { - CPP2_UFCS(require, m, CPP2_UFCS_0(is_public, m) || CPP2_UFCS_0(is_default_access, m), + CPP2_UFCS(require)(m, CPP2_UFCS(is_public)(m) || CPP2_UFCS(is_default_access)(m), "an enumerator cannot be protected or private"); - auto mo {CPP2_UFCS_0(as_object, m)}; - if (!(CPP2_UFCS_0(has_wildcard_type, mo))) { - CPP2_UFCS(error, mo, "an explicit underlying type should be specified as a template argument to the metafunction - try 'enum' or 'flag_enum'"); + auto mo {CPP2_UFCS(as_object)(m)}; + if (!(CPP2_UFCS(has_wildcard_type)(mo))) { + CPP2_UFCS(error)(mo, "an explicit underlying type should be specified as a template argument to the metafunction - try 'enum' or 'flag_enum'"); } - auto init {CPP2_UFCS_0(initializer, mo)}; + auto init {CPP2_UFCS(initializer)(mo)}; auto is_default_or_numeric {is_empty_or_a_decimal_number(init)}; - found_non_numeric |= !(CPP2_UFCS_0(empty, init)) && !(is_default_or_numeric); - CPP2_UFCS(require, m, !(is_default_or_numeric) || !(found_non_numeric) || CPP2_UFCS(has_name, mo, "none"), - cpp2::to_string(CPP2_UFCS_0(name, mo)) + ": enumerators with non-numeric values must come after all default and numeric values"); + found_non_numeric |= !(CPP2_UFCS(empty)(init)) && !(is_default_or_numeric); + CPP2_UFCS(require)(m, !(is_default_or_numeric) || !(found_non_numeric) || CPP2_UFCS(has_name)(mo, "none"), + cpp2::to_string(CPP2_UFCS(name)(mo)) + ": enumerators with non-numeric values must come after all default and numeric values"); nextval(value, init); @@ -1404,18 +1464,18 @@ std::string value = "-1"; } // Adding local variable 'e' to work around a Clang warning - value_member_info e {cpp2::as_(CPP2_UFCS_0(name, mo)), "", value}; - CPP2_UFCS(push_back, enumerators, e); + value_member_info e {cpp2::as_(CPP2_UFCS(name)(mo)), "", value}; + CPP2_UFCS(push_back)(enumerators, e); - CPP2_UFCS_0(mark_for_removal_from_enclosing_type, mo); + CPP2_UFCS(mark_for_removal_from_enclosing_type)(mo); } } // Compute the default underlying type, if it wasn't explicitly specified -#line 912 "reflect.h2" +#line 955 "reflect.h2" if (underlying_type.value() == "") { - CPP2_UFCS(require, t, !(std::move(found_non_numeric)), + CPP2_UFCS(require)(t, !(std::move(found_non_numeric)), "if you write an enumerator with a non-numeric-literal value, you must specify the enumeration's underlying type"); if (!(bitwise)) { @@ -1432,7 +1492,7 @@ std::string value = "-1"; underlying_type.value() = "i64"; } else { - CPP2_UFCS(error, t, "values are outside the range representable by the largest supported underlying signed type (i64)"); + CPP2_UFCS(error)(t, "values are outside the range representable by the largest supported underlying signed type (i64)"); }}}} } else { @@ -1452,46 +1512,46 @@ std::string value = "-1"; } } -#line 952 "reflect.h2" +#line 995 "reflect.h2" // 2. Replace: Erase the contents and replace with modified contents // // Note that most values and functions are declared as '==' compile-time values, i.e. Cpp1 'constexpr' - CPP2_UFCS_0(remove_marked_members, t); + CPP2_UFCS(remove_marked_members)(t); // Generate all the common material: value and common functions - CPP2_UFCS(add_member, t, " _value : " + cpp2::to_string(underlying_type.value()) + ";"); - CPP2_UFCS(add_member, t, " private operator= : (implicit out this, _val: i64) == _value = cpp2::unsafe_narrow<" + cpp2::to_string(underlying_type.value()) + ">(_val);"); - CPP2_UFCS(add_member, t, " get_raw_value : (this) -> " + cpp2::to_string(std::move(underlying_type.value())) + " == _value;"); - CPP2_UFCS(add_member, t, " operator= : (out this, that) == { }"); - CPP2_UFCS(add_member, t, " operator<=> : (this, that) -> std::strong_ordering;"); + CPP2_UFCS(add_member)(t, " _value : " + cpp2::to_string(underlying_type.value()) + ";"); + CPP2_UFCS(add_member)(t, " private operator= : (implicit out this, _val: i64) == _value = cpp2::unsafe_narrow<" + cpp2::to_string(underlying_type.value()) + ">(_val);"); + CPP2_UFCS(add_member)(t, " get_raw_value : (this) -> " + cpp2::to_string(std::move(underlying_type.value())) + " == _value;"); + CPP2_UFCS(add_member)(t, " operator= : (out this, that) == { }"); + CPP2_UFCS(add_member)(t, " operator<=> : (this, that) -> std::strong_ordering;"); // Generate the bitwise operations and 'none' value, if appropriate if (bitwise) { value_member_info e {"none", "", "0"}; - CPP2_UFCS(push_back, enumerators, std::move(e)); - - CPP2_UFCS(add_member, t, " operator|=: ( inout this, that ) == _value |= that._value;"); - CPP2_UFCS(add_member, t, " operator&=: ( inout this, that ) == _value &= that._value;"); - CPP2_UFCS(add_member, t, " operator^=: ( inout this, that ) == _value ^= that._value;"); - CPP2_UFCS(add_member, t, " operator| : ( this, that ) -> " + cpp2::to_string(CPP2_UFCS_0(name, t)) + " == _value | that._value;"); - CPP2_UFCS(add_member, t, " operator& : ( this, that ) -> " + cpp2::to_string(CPP2_UFCS_0(name, t)) + " == _value & that._value;"); - CPP2_UFCS(add_member, t, " operator^ : ( this, that ) -> " + cpp2::to_string(CPP2_UFCS_0(name, t)) + " == _value ^ that._value;"); - CPP2_UFCS(add_member, t, " has : ( inout this, that ) -> bool == _value & that._value;"); - CPP2_UFCS(add_member, t, " set : ( inout this, that ) == _value |= that._value;"); - CPP2_UFCS(add_member, t, " clear : ( inout this, that ) == _value &= that._value~;"); + CPP2_UFCS(push_back)(enumerators, std::move(e)); + + CPP2_UFCS(add_member)(t, " operator|=: ( inout this, that ) == _value |= that._value;"); + CPP2_UFCS(add_member)(t, " operator&=: ( inout this, that ) == _value &= that._value;"); + CPP2_UFCS(add_member)(t, " operator^=: ( inout this, that ) == _value ^= that._value;"); + CPP2_UFCS(add_member)(t, " operator| : ( this, that ) -> " + cpp2::to_string(CPP2_UFCS(name)(t)) + " == _value | that._value;"); + CPP2_UFCS(add_member)(t, " operator& : ( this, that ) -> " + cpp2::to_string(CPP2_UFCS(name)(t)) + " == _value & that._value;"); + CPP2_UFCS(add_member)(t, " operator^ : ( this, that ) -> " + cpp2::to_string(CPP2_UFCS(name)(t)) + " == _value ^ that._value;"); + CPP2_UFCS(add_member)(t, " has : ( inout this, that ) -> bool == _value & that._value;"); + CPP2_UFCS(add_member)(t, " set : ( inout this, that ) == _value |= that._value;"); + CPP2_UFCS(add_member)(t, " clear : ( inout this, that ) == _value &= that._value~;"); } // Add the enumerators for ( auto const& e : enumerators ) { - CPP2_UFCS(add_member, t, " " + cpp2::to_string(e.name) + " : " + cpp2::to_string(CPP2_UFCS_0(name, t)) + " == " + cpp2::to_string(e.value) + ";"); + CPP2_UFCS(add_member)(t, " " + cpp2::to_string(e.name) + " : " + cpp2::to_string(CPP2_UFCS(name)(t)) + " == " + cpp2::to_string(e.value) + ";"); } { std::string to_string = " to_string: (this) -> std::string = { \n"; // Provide a 'to_string' function to print enumerator name(s) -#line 988 "reflect.h2" +#line 1031 "reflect.h2" { if (bitwise) { to_string += " _ret : std::string = \"(\";\n"; @@ -1517,22 +1577,22 @@ std::string to_string = " to_string: (this) -> std::string = { \n"; to_string += " return _ret+\")\";\n}\n"; } else { - to_string += " return \"invalid " + cpp2::to_string(CPP2_UFCS_0(name, t)) + " value\";\n}\n"; + to_string += " return \"invalid " + cpp2::to_string(CPP2_UFCS(name)(t)) + " value\";\n}\n"; } - CPP2_UFCS(add_member, t, std::move(to_string)); + CPP2_UFCS(add_member)(t, std::move(to_string)); } } -#line 1018 "reflect.h2" +#line 1061 "reflect.h2" } -#line 1030 "reflect.h2" +#line 1073 "reflect.h2" auto cpp2_enum(meta::type_declaration& t) -> void { // Let basic_enum do its thing, with an incrementing value generator - CPP2_UFCS(basic_enum, t, + CPP2_UFCS(basic_enum)(t, [](std::string& value, cpp2::in specified_value) -> void{ - if (!(CPP2_UFCS_0(empty, specified_value))) { + if (!(CPP2_UFCS(empty)(specified_value))) { value = specified_value; }else { auto v {std::strtoll(&CPP2_ASSERT_IN_BOUNDS(value, 0), nullptr, 10)}; @@ -1543,13 +1603,13 @@ auto cpp2_enum(meta::type_declaration& t) -> void ); } -#line 1057 "reflect.h2" +#line 1100 "reflect.h2" auto flag_enum(meta::type_declaration& t) -> void { // Let basic_enum do its thing, with a power-of-two value generator - CPP2_UFCS(basic_enum, t, + CPP2_UFCS(basic_enum)(t, [](std::string& value, cpp2::in specified_value) -> void{ - if (!(CPP2_UFCS_0(empty, specified_value))) { + if (!(CPP2_UFCS(empty)(specified_value))) { value = specified_value; }else { auto v {std::strtoll(&CPP2_ASSERT_IN_BOUNDS(value, 0), nullptr, 10)}; @@ -1565,7 +1625,7 @@ auto flag_enum(meta::type_declaration& t) -> void ); } -#line 1103 "reflect.h2" +#line 1146 "reflect.h2" auto cpp2_union(meta::type_declaration& t) -> void { std::vector alternatives {}; @@ -1574,61 +1634,61 @@ auto value = 0; // 1. Gather: All the user-written members, and find/compute the max size -#line 1110 "reflect.h2" +#line 1153 "reflect.h2" for ( - auto const& m : CPP2_UFCS_0(get_members, t) ) { do - if ( CPP2_UFCS_0(is_member_object, m)) + auto const& m : CPP2_UFCS(get_members)(t) ) { do + if ( CPP2_UFCS(is_member_object)(m)) { - CPP2_UFCS(require, m, CPP2_UFCS_0(is_public, m) || CPP2_UFCS_0(is_default_access, m), + CPP2_UFCS(require)(m, CPP2_UFCS(is_public)(m) || CPP2_UFCS(is_default_access)(m), "a union alternative cannot be protected or private"); - CPP2_UFCS(require, m, !(CPP2_UFCS(starts_with, CPP2_UFCS_0(name, m), "is_")) - && !(CPP2_UFCS(starts_with, CPP2_UFCS_0(name, m), "set_")), + CPP2_UFCS(require)(m, !(CPP2_UFCS(starts_with)(CPP2_UFCS(name)(m), "is_")) + && !(CPP2_UFCS(starts_with)(CPP2_UFCS(name)(m), "set_")), "a union alternative's name cannot start with 'is_' or 'set_' - that could cause user confusion with the 'is_alternative' and 'set_alternative' generated functions"); - auto mo {CPP2_UFCS_0(as_object, m)}; - CPP2_UFCS(require, mo, CPP2_UFCS_0(empty, CPP2_UFCS_0(initializer, mo)), + auto mo {CPP2_UFCS(as_object)(m)}; + CPP2_UFCS(require)(mo, CPP2_UFCS(empty)(CPP2_UFCS(initializer)(mo)), "a union alternative cannot have an initializer"); // Adding local variable 'e' to work around a Clang warning - value_member_info e {cpp2::as_(CPP2_UFCS_0(name, mo)), CPP2_UFCS_0(type, mo), cpp2::as_(value)}; - CPP2_UFCS(push_back, alternatives, e); + value_member_info e {cpp2::as_(CPP2_UFCS(name)(mo)), CPP2_UFCS(type)(mo), cpp2::as_(value)}; + CPP2_UFCS(push_back)(alternatives, e); - CPP2_UFCS_0(mark_for_removal_from_enclosing_type, mo); + CPP2_UFCS(mark_for_removal_from_enclosing_type)(mo); } while (false); ++value; } } -#line 1133 "reflect.h2" +#line 1176 "reflect.h2" std::string discriminator_type {}; - if (cpp2::cmp_less(CPP2_UFCS_0(ssize, alternatives),std::numeric_limits::max())) { + if (cpp2::cmp_less(CPP2_UFCS(ssize)(alternatives),std::numeric_limits::max())) { discriminator_type = "i8"; } - else {if (cpp2::cmp_less(CPP2_UFCS_0(ssize, alternatives),std::numeric_limits::max())) { + else {if (cpp2::cmp_less(CPP2_UFCS(ssize)(alternatives),std::numeric_limits::max())) { discriminator_type = "i16"; } - else {if (cpp2::cmp_less(CPP2_UFCS_0(ssize, alternatives),std::numeric_limits::max())) { + else {if (cpp2::cmp_less(CPP2_UFCS(ssize)(alternatives),std::numeric_limits::max())) { discriminator_type = "i32"; } else { discriminator_type = "i64"; }}} -#line 1148 "reflect.h2" +#line 1191 "reflect.h2" // 2. Replace: Erase the contents and replace with modified contents - CPP2_UFCS_0(remove_marked_members, t); + CPP2_UFCS(remove_marked_members)(t); { std::string storage = " _storage: std::aligned_storage_t bool = _discriminator == " + cpp2::to_string(a.value) + ";\n"); + CPP2_UFCS(add_member)(t, " is_" + cpp2::to_string(a.name) + ": (this) -> bool = _discriminator == " + cpp2::to_string(a.value) + ";\n"); - CPP2_UFCS(add_member, t, " " + cpp2::to_string(a.name) + ": (this) -> forward " + cpp2::to_string(a.type) + " pre(is_" + cpp2::to_string(a.name) + "()) = reinterpret_cast<* const " + cpp2::to_string(a.type) + ">(_storage&)*;\n"); + CPP2_UFCS(add_member)(t, " " + cpp2::to_string(a.name) + ": (this) -> forward " + cpp2::to_string(a.type) + " pre(is_" + cpp2::to_string(a.name) + "()) = reinterpret_cast<* const " + cpp2::to_string(a.type) + ">(_storage&)*;\n"); - CPP2_UFCS(add_member, t, " " + cpp2::to_string(a.name) + ": (inout this) -> forward " + cpp2::to_string(a.type) + " pre(is_" + cpp2::to_string(a.name) + "()) = reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)*;\n"); + CPP2_UFCS(add_member)(t, " " + cpp2::to_string(a.name) + ": (inout this) -> forward " + cpp2::to_string(a.type) + " pre(is_" + cpp2::to_string(a.name) + "()) = reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)*;\n"); - CPP2_UFCS(add_member, t, " set_" + cpp2::to_string(a.name) + ": (inout this, _value: " + cpp2::to_string(a.type) + ") = { if !is_" + cpp2::to_string(a.name) + "() { _destroy(); std::construct_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&), _value); } else { reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)* = _value; } _discriminator = " + cpp2::to_string(a.value) + "; }\n"); + CPP2_UFCS(add_member)(t, " set_" + cpp2::to_string(a.name) + ": (inout this, _value: " + cpp2::to_string(a.type) + ") = { if !is_" + cpp2::to_string(a.name) + "() { _destroy(); std::construct_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&), _value); } else { reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)* = _value; } _discriminator = " + cpp2::to_string(a.value) + "; }\n"); - CPP2_UFCS(add_member, t, " set_" + cpp2::to_string(a.name) + ": (inout this, forward _args...: _) = { if !is_" + cpp2::to_string(a.name) + "() { _destroy(); std::construct_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&), _args...); } else { reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)* = :" + cpp2::to_string(a.type) + " = (_args...); } _discriminator = " + cpp2::to_string(a.value) + "; }\n"); + CPP2_UFCS(add_member)(t, " set_" + cpp2::to_string(a.name) + ": (inout this, forward _args...: _) = { if !is_" + cpp2::to_string(a.name) + "() { _destroy(); std::construct_at( reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&), _args...); } else { reinterpret_cast<*" + cpp2::to_string(a.type) + ">(_storage&)* = :" + cpp2::to_string(a.type) + " = (_args...); } _discriminator = " + cpp2::to_string(a.value) + "; }\n"); } { std::string destroy = " private _destroy: (inout this) = {\n"; // Add destroy -#line 1186 "reflect.h2" +#line 1229 "reflect.h2" { for ( auto const& a : alternatives ) { @@ -1674,22 +1734,22 @@ std::string destroy = " private _destroy: (inout this) = {\n"; destroy += " _discriminator = -1;\n"; destroy += " }\n"; - CPP2_UFCS(add_member, t, std::move(destroy)); + CPP2_UFCS(add_member)(t, std::move(destroy)); } } // Add the destructor -#line 1198 "reflect.h2" - CPP2_UFCS(add_member, t, " operator=: (move this) = { _destroy(); }"); +#line 1241 "reflect.h2" + CPP2_UFCS(add_member)(t, " operator=: (move this) = { _destroy(); }"); // Add default constructor - CPP2_UFCS(add_member, t, " operator=: (out this) = { }"); + CPP2_UFCS(add_member)(t, " operator=: (out this) = { }"); { std::string value_set = ""; // Add copy/move construction and assignment -#line 1205 "reflect.h2" +#line 1248 "reflect.h2" { for ( auto const& a : alternatives ) { @@ -1697,28 +1757,28 @@ std::string value_set = ""; } value_set += " }\n"; - CPP2_UFCS(add_member, t, std::string(" operator=: (out this, that) = {\n") + CPP2_UFCS(add_member)(t, std::string(" operator=: (out this, that) = {\n") + " _storage = ();\n" + " _discriminator = -1;\n" + value_set ); - CPP2_UFCS(add_member, t, std::string(" operator=: (inout this, that) = {\n") + CPP2_UFCS(add_member)(t, std::string(" operator=: (inout this, that) = {\n") + " _storage = _;\n" + " _discriminator = _;\n" + std::move(value_set) ); } } -#line 1223 "reflect.h2" +#line 1266 "reflect.h2" } -#line 1230 "reflect.h2" +#line 1273 "reflect.h2" auto print(cpp2::in t) -> void { - std::cout << CPP2_UFCS_0(print, t) << "\n"; + std::cout << CPP2_UFCS(print)(t) << "\n"; } -#line 1240 "reflect.h2" +#line 1283 "reflect.h2" [[nodiscard]] auto apply_metafunctions( declaration_node& n, type_declaration& rtype, @@ -1726,13 +1786,13 @@ auto print(cpp2::in t) -> void ) -> bool { - cpp2::Default.expects(CPP2_UFCS_0(is_type, n), ""); + cpp2::Default.expects(CPP2_UFCS(is_type)(n), ""); // Check for _names reserved for the metafunction implementation for ( - auto const& m : CPP2_UFCS_0(get_members, rtype) ) + auto const& m : CPP2_UFCS(get_members)(rtype) ) { - CPP2_UFCS(require, m, !(CPP2_UFCS(starts_with, CPP2_UFCS_0(name, m), "_")) || cpp2::cmp_greater(CPP2_UFCS_0(ssize, CPP2_UFCS_0(name, m)),1), + CPP2_UFCS(require)(m, !(CPP2_UFCS(starts_with)(CPP2_UFCS(name)(m), "_")) || cpp2::cmp_greater(CPP2_UFCS(ssize)(CPP2_UFCS(name)(m)),1), "a type that applies a metafunction cannot have a body that declares a name that starts with '_' - those names are reserved for the metafunction implementation"); } @@ -1742,15 +1802,15 @@ auto print(cpp2::in t) -> void { // Convert the name and any template arguments to strings // and record that in rtype - auto name {CPP2_UFCS_0(to_string, (*cpp2::assert_not_null(meta)))}; - name = CPP2_UFCS(substr, name, 0, CPP2_UFCS(find, name, '<')); + auto name {CPP2_UFCS(to_string)((*cpp2::assert_not_null(meta)))}; + name = CPP2_UFCS(substr)(name, 0, CPP2_UFCS(find)(name, '<')); std::vector args {}; for ( - auto const& arg : CPP2_UFCS_0(template_arguments, (*cpp2::assert_not_null(meta))) ) - CPP2_UFCS(push_back, args, CPP2_UFCS_0(to_string, arg)); + auto const& arg : CPP2_UFCS(template_arguments)((*cpp2::assert_not_null(meta))) ) + CPP2_UFCS(push_back)(args, CPP2_UFCS(to_string)(arg)); - CPP2_UFCS(set_metafunction_name, rtype, name, args); + CPP2_UFCS(set_metafunction_name)(rtype, name, args); // Dispatch // @@ -1806,8 +1866,8 @@ auto print(cpp2::in t) -> void }}}}}}}}}}}}}}} if (( - !(CPP2_UFCS_0(empty, args)) - && !(CPP2_UFCS_0(arguments_were_used, rtype)))) + !(CPP2_UFCS(empty)(args)) + && !(CPP2_UFCS(arguments_were_used)(rtype)))) { error(name + " did not use its template arguments - did you mean to write '" + name + " <" + CPP2_ASSERT_IN_BOUNDS(args, 0) + "> type' (with the spaces)?"); @@ -1818,7 +1878,7 @@ auto print(cpp2::in t) -> void return true; } -#line 1340 "reflect.h2" +#line 1383 "reflect.h2" } } diff --git a/source/reflect.h2 b/source/reflect.h2 index 22d97dd2f2..e09fbb8eb1 100644 --- a/source/reflect.h2 +++ b/source/reflect.h2 @@ -34,6 +34,7 @@ compiler_services: @polymorphic_base @copyable type = errors : *std::vector; errors_original_size : int; generated_tokens : *std::deque; + generated_declarations: *std::vector>; parser : cpp2::parser; metafunction_name : std::string = (); metafunction_args : std::vector = (); @@ -42,12 +43,14 @@ compiler_services: @polymorphic_base @copyable type = operator=: ( out this, errors_ : *std::vector, - generated_tokens_: *std::deque + generated_tokens_: *std::deque, + generated_declarations_: *std::vector> ) = { errors = errors_; errors_original_size = cpp2::unsafe_narrow(std::ssize(errors*)); generated_tokens = generated_tokens_; + generated_declarations = generated_declarations_; parser = errors*; } @@ -69,11 +72,11 @@ compiler_services: @polymorphic_base @copyable type = arguments_were_used: (this) -> bool = metafunctions_used; - protected parse_statement: ( + protected tokenize: ( inout this, copy source: std::string_view ) - -> std::unique_ptr + -> _ = { generated_lines.push_back( std::vector() ); lines := generated_lines.back()&; @@ -84,7 +87,7 @@ compiler_services: @polymorphic_base @copyable type = // First split this string into source_lines // - (copy newline_pos := source.find('\n')) + (copy newline_pos := source.find('\n')) if source.ssize() > 1 && newline_pos != source.npos { @@ -109,14 +112,47 @@ compiler_services: @polymorphic_base @copyable type = assert( std::ssize(tokens* .get_map()) == 1 ); + return tokens; + } + + protected parse_statement: ( + inout this, + copy source: std::string_view + ) + -> std::unique_ptr + = { + tokens := tokenize(source); + // Now parse this single declaration from // the lexed tokens - return parser.parse_one_declaration( + return parser.parse_one_statement( tokens*.get_map().begin()*.second, generated_tokens* ); } + protected parse_and_add_declaration: ( + inout this, + copy source: std::string_view + ) + -> bool + = { + tokens := tokenize(source); + + // Now parse this single declaration from + // the lexed tokens + decl := parser.parse_one_declaration( + tokens*.get_map().begin()*.second, + generated_tokens* + ); + + if decl { + generated_declarations*.push_back(decl); + return true; + } + return false; + } + position: (virtual this) -> source_position = { @@ -494,6 +530,13 @@ type_declaration: @copyable type = } } + add_declaration_to_parent_namespace: (inout this, source: std::string_view) + = { + if !parse_and_add_declaration(source) { + error( std::string("error attempting to add declaration:\n") + source ); + } + } + remove_marked_members: (inout this) = n*.type_remove_marked_members(); remove_all_members : (inout this) = n*.type_remove_all_members(); diff --git a/source/sema.h b/source/sema.h index 9826236731..56deed4b98 100644 --- a/source/sema.h +++ b/source/sema.h @@ -29,7 +29,7 @@ auto parser::apply_type_metafunctions( declaration_node& n ) assert(n.is_type()); // Get the reflection state ready to pass to the function - auto cs = meta::compiler_services{ &errors, generated_tokens }; + auto cs = meta::compiler_services{ &errors, generated_tokens, &metafunction_declarations }; auto rtype = meta::type_declaration{ &n, cs }; return apply_metafunctions( diff --git a/source/to_cpp1.h b/source/to_cpp1.h index 4d27cfcb05..40844ccd16 100644 --- a/source/to_cpp1.h +++ b/source/to_cpp1.h @@ -1029,6 +1029,8 @@ class cppfront bool violates_initialization_safety = false; bool suppress_move_from_last_use = false; + declaration_node const* having_signature_emitted = {}; + declaration_node const* generating_assignment_from = {}; declaration_node const* generating_move_from = {}; bool emitting_that_function = false; @@ -1041,7 +1043,22 @@ class cppfront }; std::vector current_args = { {} }; + struct cpp1_using_declaration { + token const* identifier = {}; + + explicit cpp1_using_declaration(using_statement_node const& n) { + if (auto id = get_if(&n.id->id)) { + identifier = (*id)->ids.back().id->identifier; + } + } + }; + std::vector current_declarations = { {} }; + // Like `current_declarations`, but for syntatic name lookup. + // So it also includes the following entities that are in scope. + // - Parameters. + // - Cpp1 using declarations. + std::vector> seen_declarations = { {} }; // Maintain a stack of the functions we're currently processing, which can // be up to MaxNestedFunctions in progress (if we run out, bump the Max). @@ -2471,6 +2488,8 @@ class cppfront if (n.for_namespace) { printer.print_cpp2(" namespace", n.position()); + } else { + seen_declarations.push_back(cpp1_using_declaration{n}); } printer.print_cpp2(" " + print_to_string(*n.id) + ";", n.position()); @@ -2772,6 +2791,65 @@ class cppfront return is_pointer_declaration(decl, deref_cnt, addr_cnt); } + + auto ufcs_possible(id_expression_node const& n) + -> bool + { + auto id = get_if(&n.id); + if (!id) + { + return true; + } + + for ( + auto first = seen_declarations.rbegin(), last = seen_declarations.rend() - 1; + first != last; + ++first + ) + { + if ( + auto decl = get_if(&*first); + decl + && *decl + && (*decl)->has_name(*(*id)->identifier) + ) + { + if ( + !(*decl)->is_object() + && !(*decl)->is_object_alias() + ) + { + return true; + } + + // Disable UFCS if name lookup would hard-error (#550) + // (when it finds that the function identifier being called + // is a variable with placeholder type and we are in its initializer. + if ((*decl)->is_object()) { + auto type = &**get_if(&(*decl)->type); + return !type->is_wildcard() + || !contains(current_declarations, *decl); + } + auto const& type = (**get_if(&(*decl)->type)).type_id; + return (type + && !type->is_wildcard() + ) + || !contains(current_declarations, *decl); + } + else if ( + auto using_ = get_if(&*first); + using_ + && using_->identifier + && *using_->identifier == *(*id)->identifier + ) + { + return true; + } + } + + return true; + } + //----------------------------------------------------------------------- // auto emit( @@ -3027,6 +3105,7 @@ class cppfront else if( i->op->type() == lexeme::Dot && args + && ufcs_possible(*i->id_expr) ) { auto funcname = print_to_string(*i->id_expr); @@ -3038,17 +3117,6 @@ class cppfront // If there are template arguments, use the _TEMPLATE version if (std::ssize(i->id_expr->template_arguments()) > 0) { ufcs_string += "_TEMPLATE"; - // we need to replace "fun" to "fun, ()" to be able to generate - // from obj.fun(1,2) this CPP2_UFCS_TEMPLATE(fun, (), obj, 1, 2) - auto split = funcname.find('<'); assert(split != std::string::npos); - funcname.insert(split, ", ("); - assert(funcname.back() == '>'); - funcname += ')'; - } - - // If there are no additional arguments, use the _0 version - if (args.value().text_chunks.empty()) { - ufcs_string += "_0"; } // If we're in an object declaration (i.e., initializer) @@ -3060,7 +3128,14 @@ class cppfront if ( current_declarations.back()->is_namespace() || ( - current_declarations.back()->is_object() + ( + current_declarations.back()->is_object() + || current_declarations.back()->is_alias() + || ( + current_declarations.back()->is_function() + && current_declarations.back() == having_signature_emitted + ) + ) && current_declarations.back()->parent_is_namespace() ) ) @@ -3070,7 +3145,7 @@ class cppfront // Second, emit the UFCS argument list - prefix.emplace_back(ufcs_string + "(" + funcname + ", ", args.value().open_pos ); + prefix.emplace_back(ufcs_string + "(" + funcname + ")(", args.value().open_pos ); suffix.emplace_back(")", args.value().close_pos ); if (!args.value().text_chunks.empty()) { for (auto&& e: args.value().text_chunks) { @@ -3820,6 +3895,49 @@ class cppfront } + template + auto stack_value( + T& var, + std::type_identity_t const& value + ) + -> auto + { + return finally([&var, old = std::exchange(var, value)]() { + var = old; + }); + } + + template + auto stack_element( + std::vector& cont, + std::type_identity_t const& value + ) + -> auto + { + cont.push_back(value); + return finally([&]{ cont.pop_back(); }); + } + + template + auto stack_size(std::vector& cont) + -> auto + { + return finally([&, size = cont.size()]{ cont.resize(size); }); + } + + template + auto stack_size_if( + std::vector& cont, + bool cond + ) + -> std::optional + { + if (cond) { + return stack_size(cont); + } + return {}; + } + //----------------------------------------------------------------------- // auto emit( @@ -3841,6 +3959,7 @@ class cppfront && n.parameters ; + auto stack = stack_size_if(seen_declarations, emit_parameters); if (emit_parameters) { printer.print_extra( "\n"); printer.print_extra( "{"); @@ -3968,6 +4087,8 @@ class cppfront } } + seen_declarations.push_back(&*n.declaration); + //----------------------------------------------------------------------- // Skip 'this' parameters @@ -4252,6 +4373,7 @@ class cppfront && n.declaration->initializer ) { + auto stack = stack_element(current_declarations, &*n.declaration); printer.print_cpp2( " = ", n.declaration->initializer->position() ); emit(*n.declaration->initializer); } @@ -5124,6 +5246,11 @@ class cppfront printer.print_extra("\n"); } + auto stack0 = stack_value(having_signature_emitted, &n); + auto stack1 = stack_element(current_declarations, &n); + seen_declarations.push_back(&n); + auto stack2 = stack_size_if(seen_declarations, n.is_function()); + // Handle aliases if (n.is_alias()) @@ -5321,8 +5448,6 @@ class cppfront return; } - current_declarations.push_back(&n); - auto guard = finally([&]{ current_declarations.pop_back(); }); // If this is a function that has multiple return values, // first we need to emit the struct that contains the returns @@ -5760,6 +5885,8 @@ class cppfront ); auto guard = finally([&]{ current_functions.pop(); }); + auto stack = stack_size(seen_declarations); + // If this is at expression scope, we can't emit "[[nodiscard]] auto name" // so print the provided intro instead, which will be a Cpp1 lambda-introducer if (capture_intro != "") @@ -6144,6 +6271,7 @@ class cppfront emit_requires_clause(); + having_signature_emitted = nullptr; emit( *n.initializer, true, func->position(), func->returns.index() == function_type_node::empty,