diff --git a/include/cpp2util.h b/include/cpp2util.h index d8b701318a..eba99ccefa 100644 --- a/include/cpp2util.h +++ b/include/cpp2util.h @@ -268,6 +268,15 @@ #define CPP2_TYPEOF(x) std::remove_cvref_t +#if __cplusplus >= 202302L && \ + ( \ + (defined(__clang_major__) && __clang_major__ >= 15) \ + || (defined(__GNUC__) && __GNUC__ >= 12) \ + ) +#define CPP2_COPY(x) auto(x) +#else +#define CPP2_COPY(x) CPP2_TYPEOF(x)(x) +#endif #define CPP2_FORWARD(x) std::forward(x) #define CPP2_PACK_EMPTY(x) (sizeof...(x) == 0) #define CPP2_CONTINUE_BREAK(NAME) goto CONTINUE_##NAME; CONTINUE_##NAME: continue; goto BREAK_##NAME; BREAK_##NAME: break; @@ -340,6 +349,10 @@ struct aligned_storage { alignas(Align) unsigned char data[Len]; }; +template + requires requires { *std::declval(); } +using deref_t = decltype(*std::declval()); + //----------------------------------------------------------------------- // @@ -450,13 +463,13 @@ auto inline Testing = contract_group( // Check for invalid dereference or indirection which would result in undefined behavior. -// +// // - Null pointer // - std::unique_ptr that owns nothing // - std::shared_ptr with no managed object // - std::optional with no value // - std::expected containing an unexpected value -// +// // Note: For naming simplicity we consider all the above cases to be "null" states so that // we can write: `*assert_not_null(object)`. // @@ -1112,44 +1125,39 @@ constexpr auto is( T const& ) -> bool { // Types // template< typename C, typename X > -auto is( X const& ) -> bool { - return false; -} - -template< typename C, typename X > - requires std::is_same_v -auto is( X const& ) -> bool { - return true; -} - -template< typename C, typename X > - requires (std::is_base_of_v && !std::is_same_v) -auto is( X const& ) -> bool { - return true; -} - -template< typename C, typename X > - requires ( - ( 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; -} - -template< typename C, typename X > - requires ( - ( 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; -} - -template< typename C, typename X > - requires (requires (X x) { *x; X(); } && std::is_same_v) auto is( X const& x ) -> bool { - return x == X(); + if constexpr ( + std::is_same_v + || std::is_base_of_v + ) + { + return true; + } + else if constexpr ( + std::is_base_of_v + || ( + std::is_polymorphic_v + && std::is_polymorphic_v + ) + ) + { + if constexpr (std::is_pointer_v) { + return Dynamic_cast(x) != nullptr; + } + else { + return Dynamic_cast(&x) != nullptr; + } + } + else if constexpr ( + requires { *x; X(); } + && std::is_same_v + ) + { + return x == X(); + } + else { + return false; + } } @@ -1217,11 +1225,6 @@ inline constexpr bool is_castable_v = // As // -template< typename C > -auto as(auto const&) -> auto { - return nonesuch; -} - template< typename C, auto x > requires (std::is_arithmetic_v && std::is_arithmetic_v) inline constexpr auto as() -> auto @@ -1233,108 +1236,83 @@ inline constexpr auto as() -> auto } } -template< typename C > -inline constexpr auto as(auto const& x) -> auto - requires ( +template< typename C, typename X > +auto as(X const& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> decltype(auto) { + if constexpr ( std::is_floating_point_v && std::is_floating_point_v && sizeof(CPP2_TYPEOF(x)) > sizeof(C) ) -{ - return nonesuch; -} - -// Signed/unsigned conversions to a not-smaller type are handled as a precondition, -// and trying to cast from a value that is in the half of the value space that isn't -// representable in the target type C is flagged as a Type safety contract violation -template< typename C > -inline constexpr auto as(auto const& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> auto - requires ( + { + return CPP2_COPY(nonesuch); + } + // Signed/unsigned conversions to a not-smaller type are handled as a precondition, + // and trying to cast from a value that is in the half of the value space that isn't + // representable in the target type C is flagged as a Type safety contract violation + else if constexpr ( std::is_integral_v && std::is_integral_v && std::is_signed_v != std::is_signed_v && sizeof(CPP2_TYPEOF(x)) <= sizeof(C) ) -{ - const C c = static_cast(x); - Type.enforce( // precondition check: must be round-trippable => not lossy - static_cast(c) == x && (c < C{}) == (x < CPP2_TYPEOF(x){}), - "dynamic lossy narrowing conversion attempt detected" CPP2_SOURCE_LOCATION_ARG - ); - return c; -} - -template< typename C, typename X > - requires std::is_same_v -auto as( X const& x ) -> decltype(auto) { - return x; -} - -template< typename C, typename X > - requires std::is_same_v -auto as( X& x ) -> decltype(auto) { - return x; -} - - -template< typename C, typename X > -auto as(X const& x) -> C - requires (std::is_same_v && std::is_integral_v) -{ - return cpp2::to_string(x); -} - - -template< typename C, typename X > -auto as( X const& x ) -> auto - requires (!std::is_same_v && !std::is_base_of_v && requires { C{x}; } - && !(std::is_same_v && std::is_integral_v) // exclude above case - ) -{ - // Experiment: Recognize the nested `::value_type` pattern for some dynamic library types - // like std::optional, and try to prevent accidental narrowing conversions even when - // those types themselves don't defend against them - if constexpr( requires { requires std::is_convertible_v; } ) { - if constexpr( is_narrowing_v) { - return nonesuch; + { + const C c = static_cast(x); + Type.enforce( // precondition check: must be round-trippable => not lossy + static_cast(c) == x && (c < C{}) == (x < CPP2_TYPEOF(x){}), + "dynamic lossy narrowing conversion attempt detected" CPP2_SOURCE_LOCATION_ARG + ); + return CPP2_COPY(c); + } + else if constexpr (std::is_same_v && std::is_integral_v) { + return cpp2::to_string(x); + } + else if constexpr (std::is_same_v) { + return x; + } + else if constexpr (std::is_base_of_v) { + return static_cast(x); + } + else if constexpr (std::is_base_of_v) { + return Dynamic_cast(x); + } + else if constexpr ( + std::is_pointer_v + && std::is_pointer_v + && requires { requires std::is_base_of_v, deref_t>; } + ) + { + return Dynamic_cast(x); + } + else if constexpr (requires { C{x}; }) { + // Experiment: Recognize the nested `::value_type` pattern for some dynamic library types + // like std::optional, and try to prevent accidental narrowing conversions even when + // those types themselves don't defend against them + if constexpr( requires { requires std::is_convertible_v; } ) { + if constexpr( is_narrowing_v) { + return nonesuch; + } } + return C{x}; + } + else { + return nonesuch; } - return C{x}; -} - -template< typename C, typename X > - requires (std::is_base_of_v && !std::is_same_v) -auto as( X& x ) -> C& { - return x; -} - -template< typename C, typename X > - requires (std::is_base_of_v && !std::is_same_v) -auto as( X const& x ) -> C const& { - return x; -} - -template< typename C, typename X > - requires (std::is_base_of_v && !std::is_same_v) -auto as( X& x ) -> C& { - return Dynamic_cast(x); -} - -template< typename C, typename X > - requires (std::is_base_of_v && !std::is_same_v) -auto as( X const& x ) -> C const& { - return Dynamic_cast(x); } template< typename C, typename X > - requires ( - std::is_pointer_v - && std::is_pointer_v - && std::is_base_of_v()), CPP2_TYPEOF(*std::declval())> - && !std::is_same_v - ) -auto as( X x ) -> C { - return Dynamic_cast(x); +auto as( X& x ) -> decltype(auto) { + if constexpr (std::is_same_v) { + return x; + } + else if constexpr (std::is_base_of_v) { + return static_cast(x); + } + else if constexpr (std::is_base_of_v) { + return Dynamic_cast(x); + } + else { + return as(std::as_const(x)); + } } diff --git a/regression-tests/test-results/clang-12/mixed-bugfix-for-ufcs-non-local.cpp.output b/regression-tests/test-results/clang-12/mixed-bugfix-for-ufcs-non-local.cpp.output index ab250896a4..5754955099 100644 --- a/regression-tests/test-results/clang-12/mixed-bugfix-for-ufcs-non-local.cpp.output +++ b/regression-tests/test-results/clang-12/mixed-bugfix-for-ufcs-non-local.cpp.output @@ -1,118 +1,118 @@ mixed-bugfix-for-ufcs-non-local.cpp2:13:12: error: a lambda expression cannot appear in this context template UnnamedTypeParam1_1> bool inline constexpr v0 = false;// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context) ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:15:3: error: a lambda expression cannot appear in this context t inline constexpr v1 = t();// Fails on Clang 12 (lambda in unevaluated context). ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:21:12: error: a lambda expression cannot appear in this context template UnnamedTypeParam1_2> auto g() -> void; ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:23:36: error: a lambda expression cannot appear in this context auto g([[maybe_unused]] cpp2::in> unnamed_param_1) -> void; ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:27:29: error: a lambda expression cannot appear in this context [[nodiscard]] auto h() -> t; ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:31:12: error: a lambda expression cannot appear in this context template UnnamedTypeParam1_3> using a = bool;// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context) ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:33:12: error: a lambda expression cannot appear in this context template UnnamedTypeParam1_4> auto inline constexpr b = false;// Fails on GCC ([GCC109781][]). ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:35:13: error: a lambda expression cannot appear in this context using c = t;// Fails on Clang 12 (lambda in unevaluated context) and Clang 12 (a lambda expression cannot appear in this context) ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:37:29: error: a lambda expression cannot appear in this context auto inline constexpr d = t();// Fails on Clang 12 (lambda in unevaluated context). ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:21:12: error: a lambda expression cannot appear in this context template UnnamedTypeParam1_2> auto g() -> void{}// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context) ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:23:36: error: a lambda expression cannot appear in this context auto g([[maybe_unused]] cpp2::in> unnamed_param_1) -> void{}// Fails on Clang 12 (lambda in unevaluated context). ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:27:29: error: a lambda expression cannot appear in this context [[nodiscard]] auto h() -> t { return o; }// Fails on Clang 12 (lambda in unevaluated context). ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ mixed-bugfix-for-ufcs-non-local.cpp2:41:79: error: lambda expression in an unevaluated operand inline CPP2_CONSTEXPR bool u::c = [](cpp2::in> x) mutable -> auto { return x; }(true);// Fails on Clang 12 (lambda in unevaluated context). ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ 13 errors generated. diff --git a/regression-tests/test-results/clang-12/pure2-bugfix-for-ufcs-noexcept.cpp.output b/regression-tests/test-results/clang-12/pure2-bugfix-for-ufcs-noexcept.cpp.output index d09f185f4f..12f7abc9fa 100644 --- a/regression-tests/test-results/clang-12/pure2-bugfix-for-ufcs-noexcept.cpp.output +++ b/regression-tests/test-results/clang-12/pure2-bugfix-for-ufcs-noexcept.cpp.output @@ -1,10 +1,10 @@ pure2-bugfix-for-ufcs-noexcept.cpp2:5:26: error: lambda expression in an unevaluated operand static_assert(noexcept(CPP2_UFCS(swap)(t(), t())));// Fails on Clang 12 (lambda in unevaluated context) and GCC 10 (static assertion failed) ^ -../../../include/cpp2util.h:928:59: note: expanded from macro 'CPP2_UFCS' +../../../include/cpp2util.h:941:59: note: expanded from macro 'CPP2_UFCS' #define CPP2_UFCS(...) CPP2_UFCS_(&,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ 1 error generated. diff --git a/regression-tests/test-results/clang-12/pure2-bugfix-for-ufcs-sfinae.cpp.output b/regression-tests/test-results/clang-12/pure2-bugfix-for-ufcs-sfinae.cpp.output index 7802c9ba22..8d5dd58565 100644 --- a/regression-tests/test-results/clang-12/pure2-bugfix-for-ufcs-sfinae.cpp.output +++ b/regression-tests/test-results/clang-12/pure2-bugfix-for-ufcs-sfinae.cpp.output @@ -1,19 +1,19 @@ pure2-bugfix-for-ufcs-sfinae.cpp2:1:78: error: lambda expression in an unevaluated operand template [[nodiscard]] auto f() -> std::type_identity_t; ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ pure2-bugfix-for-ufcs-sfinae.cpp2:1:78: error: lambda expression in an unevaluated operand template [[nodiscard]] auto f() -> std::type_identity_t{}// Fails on Clang 12 (lambda in unevaluated context). ^ -../../../include/cpp2util.h:931:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:944:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:912:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:925:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ 2 errors generated. diff --git a/regression-tests/test-results/gcc-10/pure2-bugfix-for-requires-clause-in-forward-declaration.cpp.output b/regression-tests/test-results/gcc-10/pure2-bugfix-for-requires-clause-in-forward-declaration.cpp.output index 2cdc3cf4ce..05137fd219 100644 --- a/regression-tests/test-results/gcc-10/pure2-bugfix-for-requires-clause-in-forward-declaration.cpp.output +++ b/regression-tests/test-results/gcc-10/pure2-bugfix-for-requires-clause-in-forward-declaration.cpp.output @@ -6,12 +6,12 @@ pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:46: error: expect In file included from pure2-bugfix-for-requires-clause-in-forward-declaration.cpp:7: ../../../include/cpp2util.h:10005:47: error: static assertion failed: GCC 11 or higher is required to support variables and type-scope functions that have a 'requires' clause. This includes a type-scope 'forward' parameter of non-wildcard type, such as 'func: (this, forward s: std::string)', which relies on being able to add a 'requires' clause - in that case, use 'forward s: _' instead if you need the result to compile with GCC 10. pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:4:1: note: in expansion of macro ‘CPP2_REQUIRES_’ -pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:3: error: no declaration matches ‘element::element(auto:94&&) requires is_same_v::type>::type, std::__cxx11::string>’ +pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:3: error: no declaration matches ‘element::element(auto:91&&) requires is_same_v::type>::type, std::__cxx11::string>’ pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:5:11: note: candidates are: ‘element::element(const element&)’ -pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:20: note: ‘template element::element(auto:92&&)’ +pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:20: note: ‘template element::element(auto:89&&)’ pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:1:7: note: ‘class element’ defined here pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:5:78: error: expected unqualified-id before ‘{’ token -pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:8: error: no declaration matches ‘element& element::operator=(auto:95&&) requires is_same_v::type>::type, std::__cxx11::string>’ +pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:8: error: no declaration matches ‘element& element::operator=(auto:92&&) requires is_same_v::type>::type, std::__cxx11::string>’ pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:6:16: note: candidates are: ‘void element::operator=(const element&)’ -pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:16: note: ‘template element& element::operator=(auto:93&&)’ +pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:3:16: note: ‘template element& element::operator=(auto:90&&)’ pure2-bugfix-for-requires-clause-in-forward-declaration.cpp2:1:7: note: ‘class element’ defined here diff --git a/regression-tests/test-results/gcc-10/pure2-print.cpp.output b/regression-tests/test-results/gcc-10/pure2-print.cpp.output index 24fb639f37..add4c62c5a 100644 --- a/regression-tests/test-results/gcc-10/pure2-print.cpp.output +++ b/regression-tests/test-results/gcc-10/pure2-print.cpp.output @@ -9,8 +9,8 @@ pure2-print.cpp2:68:1: note: in expansion of macro ‘CPP2_REQUIRES_’ pure2-print.cpp2:97:1: note: in expansion of macro ‘CPP2_REQUIRES_’ pure2-print.cpp2:9:41: error: ‘constexpr const T outer::object_alias’ is not a static data member of ‘class outer’ pure2-print.cpp2:9:48: error: template definition of non-template ‘constexpr const T outer::object_alias’ -pure2-print.cpp2:67:14: error: no declaration matches ‘void outer::mytype::variadic(const auto:93& ...) requires (is_convertible_v::type>::type, int> && ...)’ -pure2-print.cpp2:67:29: note: candidate is: ‘template static void outer::mytype::variadic(const auto:92& ...)’ +pure2-print.cpp2:67:14: error: no declaration matches ‘void outer::mytype::variadic(const auto:90& ...) requires (is_convertible_v::type>::type, int> && ...)’ +pure2-print.cpp2:67:29: note: candidate is: ‘template static void outer::mytype::variadic(const auto:89& ...)’ pure2-print.cpp2:10:19: note: ‘class outer::mytype’ defined here pure2-print.cpp2:96:37: error: no declaration matches ‘void outer::print(std::ostream&, const Args& ...) requires cpp2::cmp_greater_eq(sizeof ... (Args ...), 0)’ pure2-print.cpp2:96:37: note: no functions named ‘void outer::print(std::ostream&, const Args& ...) requires cpp2::cmp_greater_eq(sizeof ... (Args ...), 0)’ diff --git a/regression-tests/test-results/gcc-13/mixed-bugfix-for-ufcs-non-local.cpp.output b/regression-tests/test-results/gcc-13/mixed-bugfix-for-ufcs-non-local.cpp.output index d089661938..50d1dd852b 100644 --- a/regression-tests/test-results/gcc-13/mixed-bugfix-for-ufcs-non-local.cpp.output +++ b/regression-tests/test-results/gcc-13/mixed-bugfix-for-ufcs-non-local.cpp.output @@ -1,41 +1,41 @@ In file included from mixed-bugfix-for-ufcs-non-local.cpp:6: -../../../include/cpp2util.h:913:1: error: lambda-expression in template parameter type - 913 | [LAMBDADEFCAPT]< \ +../../../include/cpp2util.h:926:1: error: lambda-expression in template parameter type + 926 | [LAMBDADEFCAPT]< \ | ^ -../../../include/cpp2util.h:931:59: note: in expansion of macro ‘CPP2_UFCS_’ - 931 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) +../../../include/cpp2util.h:944:59: note: in expansion of macro ‘CPP2_UFCS_’ + 944 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) | ^~~~~~~~~~ mixed-bugfix-for-ufcs-non-local.cpp2:13:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:13:36: error: template argument 1 is invalid -../../../include/cpp2util.h:913:1: error: lambda-expression in template parameter type - 913 | [LAMBDADEFCAPT]< \ +../../../include/cpp2util.h:926:1: error: lambda-expression in template parameter type + 926 | [LAMBDADEFCAPT]< \ | ^ -../../../include/cpp2util.h:931:59: note: in expansion of macro ‘CPP2_UFCS_’ - 931 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) +../../../include/cpp2util.h:944:59: note: in expansion of macro ‘CPP2_UFCS_’ + 944 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) | ^~~~~~~~~~ mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid -../../../include/cpp2util.h:913:1: error: lambda-expression in template parameter type - 913 | [LAMBDADEFCAPT]< \ +../../../include/cpp2util.h:926:1: error: lambda-expression in template parameter type + 926 | [LAMBDADEFCAPT]< \ | ^ -../../../include/cpp2util.h:931:59: note: in expansion of macro ‘CPP2_UFCS_’ - 931 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) +../../../include/cpp2util.h:944:59: note: in expansion of macro ‘CPP2_UFCS_’ + 944 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) | ^~~~~~~~~~ mixed-bugfix-for-ufcs-non-local.cpp2:31:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:31:36: error: template argument 1 is invalid -../../../include/cpp2util.h:913:1: error: lambda-expression in template parameter type - 913 | [LAMBDADEFCAPT]< \ +../../../include/cpp2util.h:926:1: error: lambda-expression in template parameter type + 926 | [LAMBDADEFCAPT]< \ | ^ -../../../include/cpp2util.h:931:59: note: in expansion of macro ‘CPP2_UFCS_’ - 931 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) +../../../include/cpp2util.h:944:59: note: in expansion of macro ‘CPP2_UFCS_’ + 944 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) | ^~~~~~~~~~ mixed-bugfix-for-ufcs-non-local.cpp2:33:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:33:36: error: template argument 1 is invalid -../../../include/cpp2util.h:913:1: error: lambda-expression in template parameter type - 913 | [LAMBDADEFCAPT]< \ +../../../include/cpp2util.h:926:1: error: lambda-expression in template parameter type + 926 | [LAMBDADEFCAPT]< \ | ^ -../../../include/cpp2util.h:931:59: note: in expansion of macro ‘CPP2_UFCS_’ - 931 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) +../../../include/cpp2util.h:944:59: note: in expansion of macro ‘CPP2_UFCS_’ + 944 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) | ^~~~~~~~~~ mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’ mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid