diff --git a/include/cpp2util.h b/include/cpp2util.h index c824bf08c2..6a040dee8e 100644 --- a/include/cpp2util.h +++ b/include/cpp2util.h @@ -391,11 +391,14 @@ class contract_group { public: using handler = void (*)(CPP2_MESSAGE_PARAM msg CPP2_SOURCE_LOCATION_PARAM); - constexpr contract_group (handler h) : reporter{h} { } - constexpr auto set_handler(handler h); + constexpr contract_group (handler h = {}) : reporter{h} { } + constexpr auto set_handler(handler h = {}) { reporter = h; } constexpr auto get_handler() const -> handler { return reporter; } + constexpr auto has_handler() const -> bool { return reporter != handler{}; } constexpr auto expects (bool b, CPP2_MESSAGE_PARAM msg = "" CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) -> void { if (!b) reporter(msg CPP2_SOURCE_LOCATION_ARG); } + constexpr auto violation (CPP2_MESSAGE_PARAM msg = "" CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT) + -> void { reporter(msg CPP2_SOURCE_LOCATION_ARG); } private: handler reporter; }; @@ -441,11 +444,6 @@ auto inline Testing = contract_group( } ); -constexpr auto contract_group::set_handler(handler h) { - Default.expects(h); - reporter = h; -} - // Null pointer deref checking // diff --git a/regression-tests/pure2-contracts.cpp2 b/regression-tests/pure2-contracts.cpp2 index 4915c9c6b1..0b551243f2 100644 --- a/regression-tests/pure2-contracts.cpp2 +++ b/regression-tests/pure2-contracts.cpp2 @@ -1,5 +1,13 @@ +test_condition_evaluation: (tag) -> bool = { std::cout << tag << "\n"; return true; } + main: () = { assert( 1 != 2, "ack, arithmetic is buggy" ); assert( typeid(int) != typeid(double), "ack, C types are broken" ); - assert( any-grammatical.kind(of, nonsense * here) is "all ignored" ); + assert( any-grammatical.kind(of, nonsense * here) is "all ignored" ); + + assert( test_condition_evaluation(1), "default" ); // evaluated: prints "1" + assert( test_condition_evaluation(2), "type" ); // evaluated: prints "2" + cpp2::Type.set_handler(); + assert( test_condition_evaluation(3), "type" ); // not evaluated + assert( test_condition_evaluation(4) ); // not evaluated } \ No newline at end of file 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 a6a39e2f58..6a0278ebe2 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 _> bool inline constexpr v0 = false;// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context) ^ -../../../include/cpp2util.h:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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 _> auto g() -> void; ^ -../../../include/cpp2util.h:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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 _> using a = bool;// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context) ^ -../../../include/cpp2util.h:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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 _> auto inline constexpr b = false;// Fails on GCC ([GCC109781][]). ^ -../../../include/cpp2util.h:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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 _> auto g() -> void{}// Fails on GCC ([GCC109781][]) and Clang 12 (a lambda expression cannot appear in this context) ^ -../../../include/cpp2util.h:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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 ecfe967c7b..1d64ed4515 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:859:59: note: expanded from macro 'CPP2_UFCS' +../../../include/cpp2util.h:857:59: note: expanded from macro 'CPP2_UFCS' #define CPP2_UFCS(...) CPP2_UFCS_(&,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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 4245555035..1363283786 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:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841: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:862:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' +../../../include/cpp2util.h:860:59: note: expanded from macro 'CPP2_UFCS_NONLOCAL' #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) ^ -../../../include/cpp2util.h:843:53: note: expanded from macro 'CPP2_UFCS_' +../../../include/cpp2util.h:841:53: note: expanded from macro 'CPP2_UFCS_' #define CPP2_UFCS_(LAMBDADEFCAPT,QUALID,TEMPKW,...) \ ^ 2 errors generated. diff --git a/regression-tests/test-results/clang-12/pure2-bugfix-for-unbraced-function-expression.cpp.output b/regression-tests/test-results/clang-12/pure2-bugfix-for-unbraced-function-expression.cpp.output index 04047528ca..e69de29bb2 100644 --- a/regression-tests/test-results/clang-12/pure2-bugfix-for-unbraced-function-expression.cpp.output +++ b/regression-tests/test-results/clang-12/pure2-bugfix-for-unbraced-function-expression.cpp.output @@ -1,7 +0,0 @@ -pure2-bugfix-for-unbraced-function-expression.cpp2:2:34: warning: unused parameter 'f' [-Wunused-parameter] - auto t::operator[](auto const& f) const& -> void{} - ^ -pure2-bugfix-for-unbraced-function-expression.cpp2:9:65: warning: expression result unused [-Wunused-value] - cpp2::Default.expects(!((cpp2::is([]() mutable -> void { 0; }))), ""); - ^ -2 warnings generated. diff --git a/regression-tests/test-results/clang-12/pure2-contracts.cpp.execution b/regression-tests/test-results/clang-12/pure2-contracts.cpp.execution index e69de29bb2..1191247b6d 100644 --- a/regression-tests/test-results/clang-12/pure2-contracts.cpp.execution +++ b/regression-tests/test-results/clang-12/pure2-contracts.cpp.execution @@ -0,0 +1,2 @@ +1 +2 diff --git a/regression-tests/test-results/gcc-10/pure2-bugfix-for-unbraced-function-expression.cpp.output b/regression-tests/test-results/gcc-10/pure2-bugfix-for-unbraced-function-expression.cpp.output index d76ed67cc6..e69de29bb2 100644 --- a/regression-tests/test-results/gcc-10/pure2-bugfix-for-unbraced-function-expression.cpp.output +++ b/regression-tests/test-results/gcc-10/pure2-bugfix-for-unbraced-function-expression.cpp.output @@ -1,6 +0,0 @@ -pure2-bugfix-for-unbraced-function-expression.cpp2: In instantiation of ‘void t::operator[](const auto:90&) const & [with auto:89 = main()::]’: -pure2-bugfix-for-unbraced-function-expression.cpp2:6:4: required from here -pure2-bugfix-for-unbraced-function-expression.cpp2:2:34: warning: unused parameter ‘f’ [-Wunused-parameter] -pure2-bugfix-for-unbraced-function-expression.cpp2: In instantiation of ‘void t::operator[](const auto:90&) const & [with auto:89 = main()::]’: -pure2-bugfix-for-unbraced-function-expression.cpp2:7:4: required from here -pure2-bugfix-for-unbraced-function-expression.cpp2:2:34: warning: unused parameter ‘f’ [-Wunused-parameter] diff --git a/regression-tests/test-results/gcc-10/pure2-contracts.cpp.execution b/regression-tests/test-results/gcc-10/pure2-contracts.cpp.execution index e69de29bb2..1191247b6d 100644 --- a/regression-tests/test-results/gcc-10/pure2-contracts.cpp.execution +++ b/regression-tests/test-results/gcc-10/pure2-contracts.cpp.execution @@ -0,0 +1,2 @@ +1 +2 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 154e3d0057..123198b731 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:844:1: error: lambda-expression in template parameter type - 844 | [LAMBDADEFCAPT]< \ +../../../include/cpp2util.h:842:1: error: lambda-expression in template parameter type + 842 | [LAMBDADEFCAPT]< \ | ^ -../../../include/cpp2util.h:862:59: note: in expansion of macro ‘CPP2_UFCS_’ - 862 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) +../../../include/cpp2util.h:860:59: note: in expansion of macro ‘CPP2_UFCS_’ + 860 | #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:844:1: error: lambda-expression in template parameter type - 844 | [LAMBDADEFCAPT]< \ +../../../include/cpp2util.h:842:1: error: lambda-expression in template parameter type + 842 | [LAMBDADEFCAPT]< \ | ^ -../../../include/cpp2util.h:862:59: note: in expansion of macro ‘CPP2_UFCS_’ - 862 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) +../../../include/cpp2util.h:860:59: note: in expansion of macro ‘CPP2_UFCS_’ + 860 | #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:844:1: error: lambda-expression in template parameter type - 844 | [LAMBDADEFCAPT]< \ +../../../include/cpp2util.h:842:1: error: lambda-expression in template parameter type + 842 | [LAMBDADEFCAPT]< \ | ^ -../../../include/cpp2util.h:862:59: note: in expansion of macro ‘CPP2_UFCS_’ - 862 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) +../../../include/cpp2util.h:860:59: note: in expansion of macro ‘CPP2_UFCS_’ + 860 | #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:844:1: error: lambda-expression in template parameter type - 844 | [LAMBDADEFCAPT]< \ +../../../include/cpp2util.h:842:1: error: lambda-expression in template parameter type + 842 | [LAMBDADEFCAPT]< \ | ^ -../../../include/cpp2util.h:862:59: note: in expansion of macro ‘CPP2_UFCS_’ - 862 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) +../../../include/cpp2util.h:860:59: note: in expansion of macro ‘CPP2_UFCS_’ + 860 | #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:844:1: error: lambda-expression in template parameter type - 844 | [LAMBDADEFCAPT]< \ +../../../include/cpp2util.h:842:1: error: lambda-expression in template parameter type + 842 | [LAMBDADEFCAPT]< \ | ^ -../../../include/cpp2util.h:862:59: note: in expansion of macro ‘CPP2_UFCS_’ - 862 | #define CPP2_UFCS_NONLOCAL(...) CPP2_UFCS_(,(),,__VA_ARGS__) +../../../include/cpp2util.h:860:59: note: in expansion of macro ‘CPP2_UFCS_’ + 860 | #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 diff --git a/regression-tests/test-results/gcc-13/pure2-bugfix-for-unbraced-function-expression.cpp.output b/regression-tests/test-results/gcc-13/pure2-bugfix-for-unbraced-function-expression.cpp.output index 46a4999992..e69de29bb2 100644 --- a/regression-tests/test-results/gcc-13/pure2-bugfix-for-unbraced-function-expression.cpp.output +++ b/regression-tests/test-results/gcc-13/pure2-bugfix-for-unbraced-function-expression.cpp.output @@ -1,6 +0,0 @@ -pure2-bugfix-for-unbraced-function-expression.cpp2: In instantiation of ‘void t::operator[](const auto:100&) const & [with auto:99 = main()::]’: -pure2-bugfix-for-unbraced-function-expression.cpp2:6:4: required from here -pure2-bugfix-for-unbraced-function-expression.cpp2:2:34: warning: unused parameter ‘f’ [-Wunused-parameter] -pure2-bugfix-for-unbraced-function-expression.cpp2: In instantiation of ‘void t::operator[](const auto:100&) const & [with auto:99 = main()::]’: -pure2-bugfix-for-unbraced-function-expression.cpp2:7:4: required from here -pure2-bugfix-for-unbraced-function-expression.cpp2:2:34: warning: unused parameter ‘f’ [-Wunused-parameter] diff --git a/regression-tests/test-results/gcc-13/pure2-contracts.cpp.execution b/regression-tests/test-results/gcc-13/pure2-contracts.cpp.execution index e69de29bb2..1191247b6d 100644 --- a/regression-tests/test-results/gcc-13/pure2-contracts.cpp.execution +++ b/regression-tests/test-results/gcc-13/pure2-contracts.cpp.execution @@ -0,0 +1,2 @@ +1 +2 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 b23b224459..94cd9f304a 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 @@ -39,8 +39,8 @@ 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(ssize)(rng)), ""); + if (cpp2::Bounds.has_handler() && !(cpp2::cmp_less_eq(0,start)) ) { cpp2::Bounds.violation(""); } + if (cpp2::Bounds.has_handler() && !(cpp2::cmp_less_eq(end,CPP2_UFCS(ssize)(rng))) ) { cpp2::Bounds.violation(""); } 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 3f1c032b66..f097298eca 100644 --- a/regression-tests/test-results/mixed-bounds-safety-with-assert.cpp +++ b/regression-tests/test-results/mixed-bounds-safety-with-assert.cpp @@ -37,8 +37,8 @@ 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(ssize)(rng)), ""); + if (cpp2::Bounds.has_handler() && !(cpp2::cmp_less_eq(0,start)) ) { cpp2::Bounds.violation(""); } + if (cpp2::Bounds.has_handler() && !(cpp2::cmp_less_eq(end,CPP2_UFCS(ssize)(rng))) ) { cpp2::Bounds.violation(""); } auto count {0}; for ( diff --git a/regression-tests/test-results/mixed-bugfix-for-literal-as-nttp.cpp b/regression-tests/test-results/mixed-bugfix-for-literal-as-nttp.cpp index 64ba12369a..3676fc33c2 100644 --- a/regression-tests/test-results/mixed-bugfix-for-literal-as-nttp.cpp +++ b/regression-tests/test-results/mixed-bugfix-for-literal-as-nttp.cpp @@ -21,8 +21,8 @@ auto main() -> int; #line 3 "mixed-bugfix-for-literal-as-nttp.cpp2" auto main() -> int{ - cpp2::Default.expects(cpp2::as_() == 10, ""); - cpp2::Default.expects(cpp2::as_() == 10, ""); - cpp2::Default.expects(cpp2::as_(10s) == 10s, ""); + if (cpp2::Default.has_handler() && !(cpp2::as_() == 10) ) { cpp2::Default.violation(""); } + if (cpp2::Default.has_handler() && !(cpp2::as_() == 10) ) { cpp2::Default.violation(""); } + if (cpp2::Default.has_handler() && !(cpp2::as_(10s) == 10s) ) { cpp2::Default.violation(""); } } 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 index 1482528fd1..2274d536d5 100644 --- a/regression-tests/test-results/mixed-bugfix-for-ufcs-non-local.cpp +++ b/regression-tests/test-results/mixed-bugfix-for-ufcs-non-local.cpp @@ -86,7 +86,7 @@ template _> auto g() -> void{}// Fails on GCC ([GCC1 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(f)(o), ""); } + if (cpp2::Default.has_handler() && !(CPP2_UFCS(f)(o)) ) { cpp2::Default.violation(""); }} #line 27 "mixed-bugfix-for-ufcs-non-local.cpp2" [[nodiscard]] auto h() -> t { return o; }// Fails on Clang 12 (lambda in unevaluated context). @@ -95,7 +95,7 @@ auto g() -> void{ inline CPP2_CONSTEXPR bool u::b = CPP2_UFCS_NONLOCAL(f)(o); inline CPP2_CONSTEXPR bool u::c = [](cpp2::in> x) mutable -> auto { return x; }(true);// Fails on Clang 12 (lambda in unevaluated context). auto u::g(auto const& s, auto const& sz) -> void{ - cpp2::Default.expects(CPP2_UFCS(sz)(s) != 0, ""); } + if (cpp2::Default.has_handler() && !(CPP2_UFCS(sz)(s) != 0) ) { cpp2::Default.violation(""); }} #line 45 "mixed-bugfix-for-ufcs-non-local.cpp2" } 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 52076d5c8b..9fca84abc6 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,8 +47,8 @@ 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(ssize)(vec)), ""); - cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS(ssize)(vec)]{cpp2::Default.expects(CPP2_UFCS(ssize)(vec) == _1 + 1, "");} ); + if (cpp2::Default.has_handler() && !(cpp2::cmp_less_eq(0,where) && cpp2::cmp_less_eq(where,CPP2_UFCS(ssize)(vec))) ) { cpp2::Default.violation(""); } + cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS(ssize)(vec)]{if (cpp2::Default.has_handler() && !(CPP2_UFCS(ssize)(vec) == _1 + 1) ) { cpp2::Default.violation(""); }} ); #line 23 "mixed-captures-in-expressions-and-postconditions.cpp2" static_cast(CPP2_UFCS(insert)(vec, CPP2_UFCS(begin)(vec) + where, val)); } 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 5d5ac18632..b4d8326866 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,7 +61,7 @@ auto fill( ) -> void { - cpp2::Default.expects(cpp2::cmp_greater_eq(CPP2_UFCS(ssize)(value),count), "fill: value must contain at least count elements"); + if (cpp2::Default.has_handler() && !(cpp2::cmp_greater_eq(CPP2_UFCS(ssize)(value),count)) ) { cpp2::Default.violation("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)); } diff --git a/regression-tests/test-results/mixed-initialization-safety-3.cpp b/regression-tests/test-results/mixed-initialization-safety-3.cpp index 87ed59800f..d8806f0c41 100644 --- a/regression-tests/test-results/mixed-initialization-safety-3.cpp +++ b/regression-tests/test-results/mixed-initialization-safety-3.cpp @@ -55,7 +55,7 @@ auto fill( ) -> void { - cpp2::Default.expects(cpp2::cmp_greater_eq(CPP2_UFCS(ssize)(value),count), "fill: value must contain at least count elements"); + if (cpp2::Default.has_handler() && !(cpp2::cmp_greater_eq(CPP2_UFCS(ssize)(value),count)) ) { cpp2::Default.violation("fill: value must contain at least count elements"); } #line 23 "mixed-initialization-safety-3.cpp2" x.construct(CPP2_UFCS(substr)(value, 0, count)); } diff --git a/regression-tests/test-results/mixed-postexpression-with-capture.cpp b/regression-tests/test-results/mixed-postexpression-with-capture.cpp index c826a236de..3c69f68563 100644 --- a/regression-tests/test-results/mixed-postexpression-with-capture.cpp +++ b/regression-tests/test-results/mixed-postexpression-with-capture.cpp @@ -58,8 +58,8 @@ 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(ssize)(vec)), ""); - cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS(size)(vec)]{cpp2::Default.expects(CPP2_UFCS(size)(vec) == _1 + 1, "");} ); + if (cpp2::Default.has_handler() && !(cpp2::cmp_less_eq(0,where) && cpp2::cmp_less_eq(where,CPP2_UFCS(ssize)(vec))) ) { cpp2::Default.violation(""); } + cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS(size)(vec)]{if (cpp2::Default.has_handler() && !(CPP2_UFCS(size)(vec) == _1 + 1) ) { cpp2::Default.violation(""); }} ); #line 20 "mixed-postexpression-with-capture.cpp2" CPP2_UFCS(push_back)(vec, val); } @@ -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(length)(ret)]{cpp2::Default.expects(CPP2_UFCS(length)(ret) == _1 + 5, "");} ); + cpp2_finally_presuccess.add([&, _1 = CPP2_UFCS(length)(ret)]{if (cpp2::Default.has_handler() && !(CPP2_UFCS(length)(ret) == _1 + 5) ) { cpp2::Default.violation(""); }} ); #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(length)(a), _1 = CPP2_UFCS(length)(b), _2 = 5]{ return _0==_1 && _1==_2; }(), "");} ); +cpp2_finally_presuccess.add([&]{if (cpp2::Default.has_handler() && !([_0 = CPP2_UFCS(length)(a), _1 = CPP2_UFCS(length)(b), _2 = 5]{ return _0==_1 && _1==_2; }()) ) { cpp2::Default.violation(""); }} ); #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/msvc-2022/pure2-contracts.cpp.execution b/regression-tests/test-results/msvc-2022/pure2-contracts.cpp.execution index e69de29bb2..1191247b6d 100644 --- a/regression-tests/test-results/msvc-2022/pure2-contracts.cpp.execution +++ b/regression-tests/test-results/msvc-2022/pure2-contracts.cpp.execution @@ -0,0 +1,2 @@ +1 +2 diff --git a/regression-tests/test-results/pure2-bugfix-for-assign-expression-list.cpp b/regression-tests/test-results/pure2-bugfix-for-assign-expression-list.cpp index cea3ff1401..e30b88571b 100644 --- a/regression-tests/test-results/pure2-bugfix-for-assign-expression-list.cpp +++ b/regression-tests/test-results/pure2-bugfix-for-assign-expression-list.cpp @@ -22,10 +22,10 @@ auto main() -> int{ using vec = std::vector; vec v {0}; v = { }; - cpp2::Default.expects(v == vec{}, ""); + if (cpp2::Default.has_handler() && !(v == vec{}) ) { cpp2::Default.violation(""); } v = { 1 }; - cpp2::Default.expects(v == vec{1}, ""); + if (cpp2::Default.has_handler() && !(v == vec{1}) ) { cpp2::Default.violation(""); } v = { 2, 3 }; - cpp2::Default.expects(std::move(v) == vec{2, 3}, ""); + if (cpp2::Default.has_handler() && !(std::move(v) == vec{2, 3}) ) { cpp2::Default.violation(""); } } diff --git a/regression-tests/test-results/pure2-bugfix-for-non-local-initialization.cpp b/regression-tests/test-results/pure2-bugfix-for-non-local-initialization.cpp index c9cc1ee296..8cc41c442f 100644 --- a/regression-tests/test-results/pure2-bugfix-for-non-local-initialization.cpp +++ b/regression-tests/test-results/pure2-bugfix-for-non-local-initialization.cpp @@ -28,7 +28,7 @@ auto main() -> int; #line 5 "pure2-bugfix-for-non-local-initialization.cpp2" auto main() -> int{ - cpp2::Testing.expects(CPP2_ASSERT_IN_BOUNDS(t::value, 0) == 17, ""); - cpp2::Testing.expects(CPP2_ASSERT_IN_BOUNDS(t::value, 1) == 29, ""); + if (cpp2::Testing.has_handler() && !(CPP2_ASSERT_IN_BOUNDS(t::value, 0) == 17) ) { cpp2::Testing.violation(""); } + if (cpp2::Testing.has_handler() && !(CPP2_ASSERT_IN_BOUNDS(t::value, 1) == 29) ) { cpp2::Testing.violation(""); } } 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 index 82f964e1f4..4d10d81ba7 100644 --- a/regression-tests/test-results/pure2-bugfix-for-ufcs-name-lookup.cpp +++ b/regression-tests/test-results/pure2-bugfix-for-ufcs-name-lookup.cpp @@ -67,25 +67,25 @@ namespace ns { auto main() -> int{ { int f {CPP2_UFCS(f)(t())}; - cpp2::Default.expects(std::move(f) == 0, ""); + if (cpp2::Default.has_handler() && !(std::move(f) == 0) ) { cpp2::Default.violation(""); } } { auto f {t().f()}; - cpp2::Default.expects(std::move(f) == 0, ""); + if (cpp2::Default.has_handler() && !(std::move(f) == 0) ) { cpp2::Default.violation(""); } } { auto f {t().f()}; - cpp2::Default.expects(std::move(f) == 0, ""); + if (cpp2::Default.has_handler() && !(std::move(f) == 0) ) { cpp2::Default.violation(""); } } { auto const& f = t().f(); #line 33 "pure2-bugfix-for-ufcs-name-lookup.cpp2" - cpp2::Default.expects(f == 0, ""); + if (cpp2::Default.has_handler() && !(f == 0) ) { cpp2::Default.violation(""); } } { auto const& f = t().f(); #line 34 "pure2-bugfix-for-ufcs-name-lookup.cpp2" - cpp2::Default.expects(f == 0, ""); + if (cpp2::Default.has_handler() && !(f == 0) ) { cpp2::Default.violation(""); } } #line 35 "pure2-bugfix-for-ufcs-name-lookup.cpp2" { @@ -98,7 +98,7 @@ auto const& f = t().f(); } { auto f {[](auto const& f) mutable -> auto{ - cpp2::Default.expects(CPP2_UFCS(f)(t()) == 0, ""); + if (cpp2::Default.has_handler() && !(CPP2_UFCS(f)(t()) == 0) ) { cpp2::Default.violation(""); } return CPP2_UFCS(f)(u()); }(identity())}; static_cast(std::move(f)); @@ -115,7 +115,7 @@ auto const& f = t().f(); { cpp2::in f = identity(); #line 59 "pure2-bugfix-for-ufcs-name-lookup.cpp2" - cpp2::Default.expects(CPP2_UFCS(f)(t()) == 0, ""); + if (cpp2::Default.has_handler() && !(CPP2_UFCS(f)(t()) == 0) ) { cpp2::Default.violation(""); } } { cpp2::in f = identity(); diff --git a/regression-tests/test-results/pure2-bugfix-for-unbraced-function-expression.cpp b/regression-tests/test-results/pure2-bugfix-for-unbraced-function-expression.cpp index 9a59f198f2..e7b21150b2 100644 --- a/regression-tests/test-results/pure2-bugfix-for-unbraced-function-expression.cpp +++ b/regression-tests/test-results/pure2-bugfix-for-unbraced-function-expression.cpp @@ -16,7 +16,7 @@ class t; #line 1 "pure2-bugfix-for-unbraced-function-expression.cpp2" class t { #line 2 "pure2-bugfix-for-unbraced-function-expression.cpp2" - public: auto operator[](auto const& f) const& -> void; + public: auto operator[]([[maybe_unused]] auto const& unnamed_param_2) const& -> void; public: t() = default; public: t(t const&) = delete; /* No 'that' constructor, suppress copy */ public: auto operator=(t const&) -> void = delete; @@ -35,7 +35,7 @@ extern cpp2::i32 y; #line 1 "pure2-bugfix-for-unbraced-function-expression.cpp2" #line 2 "pure2-bugfix-for-unbraced-function-expression.cpp2" - auto t::operator[](auto const& f) const& -> void{} + auto t::operator[]([[maybe_unused]] auto const& unnamed_param_2) const& -> void{} #line 5 "pure2-bugfix-for-unbraced-function-expression.cpp2" [[nodiscard]] auto main() -> int{ @@ -51,7 +51,7 @@ auto const& x = t(); } #line 9 "pure2-bugfix-for-unbraced-function-expression.cpp2" - cpp2::Default.expects(!((cpp2::is([]() mutable -> void { 0; }))), ""); + if (cpp2::Default.has_handler() && !(!((cpp2::is([]() mutable -> auto { return 0; })))) ) { cpp2::Default.violation(""); } return cpp2::i32{0}; } diff --git a/regression-tests/test-results/pure2-concept-definition.cpp b/regression-tests/test-results/pure2-concept-definition.cpp index ba3e301567..24d76efc06 100644 --- a/regression-tests/test-results/pure2-concept-definition.cpp +++ b/regression-tests/test-results/pure2-concept-definition.cpp @@ -22,7 +22,7 @@ auto main() -> int; #line 2 "pure2-concept-definition.cpp2" auto main() -> int { - cpp2::Testing.expects(arithmetic, ""); - cpp2::Testing.expects(arithmetic, ""); + if (cpp2::Testing.has_handler() && !(arithmetic) ) { cpp2::Testing.violation(""); } + if (cpp2::Testing.has_handler() && !(arithmetic) ) { cpp2::Testing.violation(""); } } diff --git a/regression-tests/test-results/pure2-contracts.cpp b/regression-tests/test-results/pure2-contracts.cpp index b22fca88c2..90e828fee5 100644 --- a/regression-tests/test-results/pure2-contracts.cpp +++ b/regression-tests/test-results/pure2-contracts.cpp @@ -12,15 +12,26 @@ //=== Cpp2 type definitions and function declarations =========================== #line 1 "pure2-contracts.cpp2" +[[nodiscard]] auto test_condition_evaluation(auto const& tag) -> bool; + +#line 3 "pure2-contracts.cpp2" auto main() -> int; //=== Cpp2 function definitions ================================================= #line 1 "pure2-contracts.cpp2" -auto main() -> int{ -#line 2 "pure2-contracts.cpp2" - cpp2::Default.expects(1 != 2, "ack, arithmetic is buggy"); - cpp2::Type.expects(typeid(int) != typeid(double), "ack, C types are broken"); +[[nodiscard]] auto test_condition_evaluation(auto const& tag) -> bool{std::cout << tag << "\n"; return true; } +#line 3 "pure2-contracts.cpp2" +auto main() -> int{ + if (cpp2::Default.has_handler() && !(1 != 2) ) { cpp2::Default.violation("ack, arithmetic is buggy"); } + if (cpp2::Type.has_handler() && !(typeid(int) != typeid(double)) ) { cpp2::Type.violation("ack, C types are broken"); } + +#line 8 "pure2-contracts.cpp2" + if (cpp2::Default.has_handler() && !(test_condition_evaluation(1)) ) { cpp2::Default.violation("default"); }// evaluated: prints "1" + if (cpp2::Type.has_handler() && !(test_condition_evaluation(2)) ) { cpp2::Type.violation("type"); }// evaluated: prints "2" + CPP2_UFCS(set_handler)(cpp2::Type); + if (cpp2::Type.has_handler() && !(test_condition_evaluation(3)) ) { cpp2::Type.violation("type"); }// not evaluated + // not evaluated } diff --git a/regression-tests/test-results/pure2-forward-return.cpp b/regression-tests/test-results/pure2-forward-return.cpp index 19757c3591..ba4b3577df 100644 --- a/regression-tests/test-results/pure2-forward-return.cpp +++ b/regression-tests/test-results/pure2-forward-return.cpp @@ -28,7 +28,7 @@ extern int const global; #line 2 "pure2-forward-return.cpp2" [[nodiscard]] auto first(auto&& rng) -> auto&& { - cpp2::Bounds.expects(!(std::empty(rng)), ""); + if (cpp2::Bounds.has_handler() && !(!(std::empty(rng))) ) { cpp2::Bounds.violation(""); } #line 5 "pure2-forward-return.cpp2" return *cpp2::assert_not_null(std::begin(CPP2_FORWARD(rng))); } diff --git a/regression-tests/test-results/pure2-more-wildcards.cpp b/regression-tests/test-results/pure2-more-wildcards.cpp index 23a368073e..cb06bb1756 100644 --- a/regression-tests/test-results/pure2-more-wildcards.cpp +++ b/regression-tests/test-results/pure2-more-wildcards.cpp @@ -30,7 +30,7 @@ auto const x {2}; auto* p {&x}; auto const* q {&p}; - cpp2::Default.expects(std::move(q), ""); + if (cpp2::Default.has_handler() && !(std::move(q)) ) { cpp2::Default.violation(""); } if (cpp2::is(x, (less_than(20)))) { std::cout << "yes, less\n"; diff --git a/regression-tests/test-results/pure2-print.cpp b/regression-tests/test-results/pure2-print.cpp index d5fa375c84..8983a9435f 100644 --- a/regression-tests/test-results/pure2-print.cpp +++ b/regression-tests/test-results/pure2-print.cpp @@ -113,8 +113,8 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias = 42; #line 34 "pure2-print.cpp2" { - 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, ""); + if (cpp2::Default.has_handler() && !(CPP2_UFCS(empty)(m) == false || false) ) { cpp2::Default.violation("message"); } + if (cpp2::Bounds.has_handler() && !([_0 = 0, _1 = CPP2_UFCS(ssize)(m), _2 = 100]{ return cpp2::cmp_less(_0,_1) && cpp2::cmp_less(_1,_2); }() && true != false) ) { cpp2::Bounds.violation(""); } #line 35 "pure2-print.cpp2" auto a {[]() mutable -> void{}}; auto b {[]() mutable -> void{}}; @@ -131,7 +131,7 @@ requires (true) inline CPP2_CONSTEXPR T outer::object_alias = 42; else {if (!(CPP2_UFCS(empty)(m))) {std::move(b)(); } else {std::move(c)(); }} - cpp2::Default.expects(true, ""); + if (cpp2::Default.has_handler() && !(true) ) { cpp2::Default.violation(""); } return [_0 = (s + CPP2_ASSERT_IN_BOUNDS(m, 0))]() mutable -> std::string { return _0; }(); } diff --git a/regression-tests/test-results/pure2-union.cpp b/regression-tests/test-results/pure2-union.cpp index 6051b7479f..5ec953c881 100644 --- a/regression-tests/test-results/pure2-union.cpp +++ b/regression-tests/test-results/pure2-union.cpp @@ -84,16 +84,16 @@ auto main() -> int; #line 1 "pure2-union.cpp2" [[nodiscard]] auto name_or_number::is_name() const& -> bool { return _discriminator == 0; } [[nodiscard]] auto name_or_number::name() const& -> std::string const& { - cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + if (cpp2::Default.has_handler() && !(is_name()) ) { cpp2::Default.violation(""); }return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } [[nodiscard]] auto name_or_number::name() & -> std::string& { - cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + if (cpp2::Default.has_handler() && !(is_name()) ) { cpp2::Default.violation(""); }return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } auto name_or_number::set_name(cpp2::in _value) & -> void{if (!(is_name())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _value);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = _value;}_discriminator = 0;} auto name_or_number::set_name(auto&& ..._args) & -> void{if (!(is_name())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _args...);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = std::string{_args...};}_discriminator = 0;} [[nodiscard]] auto name_or_number::is_num() const& -> bool { return _discriminator == 1; } [[nodiscard]] auto name_or_number::num() const& -> cpp2::i32 const& { - cpp2::Default.expects(is_num(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + if (cpp2::Default.has_handler() && !(is_num()) ) { cpp2::Default.violation(""); }return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } [[nodiscard]] auto name_or_number::num() & -> cpp2::i32& { - cpp2::Default.expects(is_num(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + if (cpp2::Default.has_handler() && !(is_num()) ) { cpp2::Default.violation(""); }return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } auto name_or_number::set_num(cpp2::in _value) & -> void{if (!(is_num())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _value);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = _value;}_discriminator = 1;} auto name_or_number::set_num(auto&& ..._args) & -> void{if (!(is_num())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _args...);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = cpp2::i32{_args...};}_discriminator = 1;} auto name_or_number::_destroy() & -> void{ @@ -140,16 +140,16 @@ if (CPP2_UFCS(is_num)(std::move(that))) {set_num(CPP2_UFCS(num)(std::move(that)) template [[nodiscard]] auto name_or_other::is_name() const& -> bool { return _discriminator == 0; } template [[nodiscard]] auto name_or_other::name() const& -> std::string const& { - cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + if (cpp2::Default.has_handler() && !(is_name()) ) { cpp2::Default.violation(""); }return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } template [[nodiscard]] auto name_or_other::name() & -> std::string& { - cpp2::Default.expects(is_name(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + if (cpp2::Default.has_handler() && !(is_name()) ) { cpp2::Default.violation(""); }return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } template auto name_or_other::set_name(cpp2::in _value) & -> void{if (!(is_name())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _value);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = _value;}_discriminator = 0;} template auto name_or_other::set_name(auto&& ..._args) & -> void{if (!(is_name())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _args...);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = std::string{_args...};}_discriminator = 0;} template [[nodiscard]] auto name_or_other::is_other() const& -> bool { return _discriminator == 1; } template [[nodiscard]] auto name_or_other::other() const& -> T const& { - cpp2::Default.expects(is_other(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + if (cpp2::Default.has_handler() && !(is_other()) ) { cpp2::Default.violation(""); }return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } template [[nodiscard]] auto name_or_other::other() & -> T& { - cpp2::Default.expects(is_other(), "");return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } + if (cpp2::Default.has_handler() && !(is_other()) ) { cpp2::Default.violation(""); }return *cpp2::assert_not_null(reinterpret_cast(&_storage)); } template auto name_or_other::set_other(cpp2::in _value) & -> void{if (!(is_other())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _value);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = _value;}_discriminator = 1;} template auto name_or_other::set_other(auto&& ..._args) & -> void{if (!(is_other())) {_destroy();std::construct_at(reinterpret_cast(&_storage), _args...);}else {*cpp2::assert_not_null(reinterpret_cast(&_storage)) = T{_args...};}_discriminator = 1;} template auto name_or_other::_destroy() & -> void{ diff --git a/regression-tests/test-results/version b/regression-tests/test-results/version index 21015bed30..fded15a42f 100644 --- a/regression-tests/test-results/version +++ b/regression-tests/test-results/version @@ -1,5 +1,5 @@ -cppfront compiler v0.3.0 Build 8C16:2054 +cppfront compiler v0.3.0 Build 8C17:0658 Copyright(c) Herb Sutter All rights reserved SPDX-License-Identifier: CC-BY-NC-ND-4.0 diff --git a/source/build.info b/source/build.info index 824799a300..181826b177 100644 --- a/source/build.info +++ b/source/build.info @@ -1 +1 @@ -"8C16:2054" \ No newline at end of file +"8C17:0658" \ No newline at end of file diff --git a/source/reflect.h b/source/reflect.h index d1410315ff..99f4563d8d 100644 --- a/source/reflect.h +++ b/source/reflect.h @@ -18,28 +18,28 @@ namespace meta { #line 32 "reflect.h2" class compiler_services; -#line 218 "reflect.h2" +#line 223 "reflect.h2" class declaration_base; -#line 244 "reflect.h2" +#line 249 "reflect.h2" class declaration; -#line 326 "reflect.h2" +#line 331 "reflect.h2" class function_declaration; -#line 413 "reflect.h2" +#line 418 "reflect.h2" class object_declaration; -#line 449 "reflect.h2" +#line 454 "reflect.h2" class type_declaration; -#line 584 "reflect.h2" +#line 589 "reflect.h2" class alias_declaration; -#line 923 "reflect.h2" +#line 928 "reflect.h2" class value_member_info; -#line 1438 "reflect.h2" +#line 1443 "reflect.h2" } } @@ -129,6 +129,7 @@ using parse_statement_ret = std::unique_ptr; #line 142 "reflect.h2" // Error diagnosis and handling, integrated with compiler output + // Unlike a contract violation, .requires continues further processing // public: auto require( @@ -136,20 +137,24 @@ using parse_statement_ret = std::unique_ptr; cpp2::in msg ) const& -> void; -#line 155 "reflect.h2" +#line 156 "reflect.h2" public: auto error(cpp2::in msg) const& -> void; -#line 164 "reflect.h2" - // Enable custom contracts on this object +#line 165 "reflect.h2" + // Enable custom contracts on this object, integrated with compiler output + // Unlike .requires, a contract violation stops further processing // - public: auto expects(auto const& b, auto const& msg) const& -> void; + public: auto violation(auto const& msg) const& -> void; + +#line 173 "reflect.h2" + public: [[nodiscard]] auto has_handler() const& -> auto; public: virtual ~compiler_services() noexcept; public: compiler_services(compiler_services const& that); - -#line 170 "reflect.h2" +#line 174 "reflect.h2" }; +#line 177 "reflect.h2" /* //----------------------------------------------------------------------- // @@ -186,7 +191,7 @@ type_id: @polymorphic_base @copyable type = } */ -#line 209 "reflect.h2" +#line 214 "reflect.h2" //----------------------------------------------------------------------- // // Declarations @@ -199,7 +204,7 @@ type_id: @polymorphic_base @copyable type = class declaration_base : public compiler_services { -#line 222 "reflect.h2" +#line 227 "reflect.h2" protected: declaration_node* n; protected: explicit declaration_base( @@ -208,31 +213,31 @@ class declaration_base cpp2::in s ); -#line 235 "reflect.h2" +#line 240 "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 238 "reflect.h2" +#line 243 "reflect.h2" }; -#line 241 "reflect.h2" +#line 246 "reflect.h2" //----------------------------------------------------------------------- // All declarations // class declaration : public declaration_base { -#line 248 "reflect.h2" +#line 253 "reflect.h2" public: explicit declaration( declaration_node* n_, cpp2::in s ); -#line 257 "reflect.h2" +#line 262 "reflect.h2" public: [[nodiscard]] auto is_public() const& -> bool; public: [[nodiscard]] auto is_protected() const& -> bool; public: [[nodiscard]] auto is_private() const& -> bool; @@ -251,7 +256,7 @@ class declaration public: [[nodiscard]] auto name() const& -> std::string_view; -#line 278 "reflect.h2" +#line 283 "reflect.h2" public: [[nodiscard]] auto has_initializer() const& -> bool; public: [[nodiscard]] auto is_global() const& -> bool; @@ -294,24 +299,24 @@ public: declaration(declaration const& that); // this precondition should be sufficient ... -#line 320 "reflect.h2" +#line 325 "reflect.h2" }; -#line 323 "reflect.h2" +#line 328 "reflect.h2" //----------------------------------------------------------------------- // Function declarations // class function_declaration : public declaration { -#line 330 "reflect.h2" +#line 335 "reflect.h2" public: explicit function_declaration( declaration_node* n_, cpp2::in s ); -#line 340 "reflect.h2" +#line 345 "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; @@ -348,7 +353,7 @@ class function_declaration public: [[nodiscard]] auto get_parameters() const& -> std::vector; -#line 384 "reflect.h2" +#line 389 "reflect.h2" public: [[nodiscard]] auto is_binary_comparison_function() const& -> bool; public: auto default_to_virtual() & -> void; @@ -359,103 +364,103 @@ class function_declaration public: function_declaration(function_declaration const& that); -#line 407 "reflect.h2" +#line 412 "reflect.h2" }; -#line 410 "reflect.h2" +#line 415 "reflect.h2" //----------------------------------------------------------------------- // Object declarations // class object_declaration : public declaration { -#line 417 "reflect.h2" +#line 422 "reflect.h2" public: explicit object_declaration( declaration_node* n_, cpp2::in s ); -#line 427 "reflect.h2" +#line 432 "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 437 "reflect.h2" +#line 442 "reflect.h2" public: [[nodiscard]] auto initializer() const& -> std::string; public: object_declaration(object_declaration const& that); -#line 443 "reflect.h2" +#line 448 "reflect.h2" }; -#line 446 "reflect.h2" +#line 451 "reflect.h2" //----------------------------------------------------------------------- // Type declarations // class type_declaration : public declaration { -#line 453 "reflect.h2" +#line 458 "reflect.h2" public: explicit type_declaration( declaration_node* n_, cpp2::in s ); -#line 463 "reflect.h2" +#line 468 "reflect.h2" public: auto reserve_names(cpp2::in name, auto&& ...etc) const& -> void; -#line 475 "reflect.h2" +#line 480 "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 490 "reflect.h2" +#line 495 "reflect.h2" public: [[nodiscard]] auto get_member_functions_needing_initializer() const& -> std::vector; -#line 505 "reflect.h2" +#line 510 "reflect.h2" public: [[nodiscard]] auto get_member_objects() const& -> std::vector; -#line 515 "reflect.h2" +#line 520 "reflect.h2" public: [[nodiscard]] auto get_member_types() const& -> std::vector; -#line 525 "reflect.h2" +#line 530 "reflect.h2" public: [[nodiscard]] auto get_member_aliases() const& -> std::vector; -#line 535 "reflect.h2" +#line 540 "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 545 "reflect.h2" +#line 550 "reflect.h2" public: [[nodiscard]] auto query_declared_value_set_functions() const& -> query_declared_value_set_functions_ret; -#line 560 "reflect.h2" +#line 565 "reflect.h2" public: auto add_member(cpp2::in source) & -> void; -#line 574 "reflect.h2" +#line 579 "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 578 "reflect.h2" +#line 583 "reflect.h2" }; -#line 581 "reflect.h2" +#line 586 "reflect.h2" //----------------------------------------------------------------------- // Alias declarations // class alias_declaration : public declaration { -#line 588 "reflect.h2" +#line 593 "reflect.h2" public: explicit alias_declaration( declaration_node* n_, @@ -464,10 +469,10 @@ class alias_declaration public: alias_declaration(alias_declaration const& that); -#line 597 "reflect.h2" +#line 602 "reflect.h2" }; -#line 600 "reflect.h2" +#line 605 "reflect.h2" //----------------------------------------------------------------------- // // Metafunctions - these are hardwired for now until we get to the @@ -482,7 +487,7 @@ class alias_declaration // auto add_virtual_destructor(meta::type_declaration& t) -> void; -#line 618 "reflect.h2" +#line 623 "reflect.h2" //----------------------------------------------------------------------- // // "... an abstract base class defines an interface ..." @@ -497,7 +502,7 @@ auto add_virtual_destructor(meta::type_declaration& t) -> void; // auto interface(meta::type_declaration& t) -> void; -#line 657 "reflect.h2" +#line 662 "reflect.h2" //----------------------------------------------------------------------- // // "C.35: A base class destructor should be either public and @@ -519,7 +524,7 @@ auto interface(meta::type_declaration& t) -> void; // auto polymorphic_base(meta::type_declaration& t) -> void; -#line 701 "reflect.h2" +#line 706 "reflect.h2" //----------------------------------------------------------------------- // // "... A totally ordered type ... requires operator<=> that @@ -545,7 +550,7 @@ auto ordered_impl( cpp2::in ordering// must be "strong_ordering" etc. ) -> void; -#line 745 "reflect.h2" +#line 750 "reflect.h2" //----------------------------------------------------------------------- // ordered - a totally ordered type // @@ -553,19 +558,19 @@ auto ordered_impl( // auto ordered(meta::type_declaration& t) -> void; -#line 755 "reflect.h2" +#line 760 "reflect.h2" //----------------------------------------------------------------------- // weakly_ordered - a weakly ordered type // auto weakly_ordered(meta::type_declaration& t) -> void; -#line 763 "reflect.h2" +#line 768 "reflect.h2" //----------------------------------------------------------------------- // partially_ordered - a partially ordered type // auto partially_ordered(meta::type_declaration& t) -> void; -#line 772 "reflect.h2" +#line 777 "reflect.h2" //----------------------------------------------------------------------- // // "A value is ... a regular type. It must have all public @@ -584,7 +589,7 @@ auto partially_ordered(meta::type_declaration& t) -> void; // auto copyable(meta::type_declaration& t) -> void; -#line 809 "reflect.h2" +#line 814 "reflect.h2" //----------------------------------------------------------------------- // // basic_value @@ -594,7 +599,7 @@ auto copyable(meta::type_declaration& t) -> void; // auto basic_value(meta::type_declaration& t) -> void; -#line 834 "reflect.h2" +#line 839 "reflect.h2" //----------------------------------------------------------------------- // // "A 'value' is a totally ordered basic_value..." @@ -607,13 +612,13 @@ auto basic_value(meta::type_declaration& t) -> void; // auto value(meta::type_declaration& t) -> void; -#line 850 "reflect.h2" +#line 855 "reflect.h2" auto weakly_ordered_value(meta::type_declaration& t) -> void; -#line 856 "reflect.h2" +#line 861 "reflect.h2" auto partially_ordered_value(meta::type_declaration& t) -> void; -#line 863 "reflect.h2" +#line 868 "reflect.h2" //----------------------------------------------------------------------- // // "By definition, a `struct` is a `class` in which members @@ -641,7 +646,7 @@ auto partially_ordered_value(meta::type_declaration& t) -> void; // auto cpp2_struct(meta::type_declaration& t) -> void; -#line 906 "reflect.h2" +#line 911 "reflect.h2" //----------------------------------------------------------------------- // // "C enumerations constitute a curiously half-baked concept. ... @@ -671,7 +676,7 @@ auto basic_enum( cpp2::in bitwise ) -> void; -#line 1110 "reflect.h2" +#line 1115 "reflect.h2" //----------------------------------------------------------------------- // // "An enum[...] is a totally ordered value type that stores a @@ -683,7 +688,7 @@ auto basic_enum( // auto cpp2_enum(meta::type_declaration& t) -> void; -#line 1136 "reflect.h2" +#line 1141 "reflect.h2" //----------------------------------------------------------------------- // // "flag_enum expresses an enumeration that stores values @@ -696,7 +701,7 @@ auto cpp2_enum(meta::type_declaration& t) -> void; // auto flag_enum(meta::type_declaration& t) -> void; -#line 1168 "reflect.h2" +#line 1173 "reflect.h2" //----------------------------------------------------------------------- // // "As with void*, programmers should know that unions [...] are @@ -723,14 +728,14 @@ auto flag_enum(meta::type_declaration& t) -> void; auto cpp2_union(meta::type_declaration& t) -> void; -#line 1324 "reflect.h2" +#line 1329 "reflect.h2" //----------------------------------------------------------------------- // // print - output a pretty-printed visualization of t // auto print(cpp2::in t) -> void; -#line 1334 "reflect.h2" +#line 1339 "reflect.h2" //----------------------------------------------------------------------- // // apply_metafunctions @@ -741,7 +746,7 @@ auto print(cpp2::in t) -> void; auto const& error ) -> bool; -#line 1438 "reflect.h2" +#line 1443 "reflect.h2" } } @@ -843,7 +848,7 @@ auto newline_pos = CPP2_UFCS(find)(source, '\n'); 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, ""); + if (cpp2::Default.has_handler() && !(std::ssize(CPP2_UFCS(get_map)((*cpp2::assert_not_null(tokens)))) == 1) ) { cpp2::Default.violation(""); } // Now parse this single declaration from // the lexed tokens @@ -862,7 +867,7 @@ auto newline_pos = CPP2_UFCS(find)(source, '\n'); return { }; } -#line 144 "reflect.h2" +#line 145 "reflect.h2" auto compiler_services::require( cpp2::in b, @@ -883,12 +888,14 @@ auto newline_pos = CPP2_UFCS(find)(source, '\n'); static_cast(CPP2_UFCS(emplace_back)((*cpp2::assert_not_null(errors)), position(), std::move(message))); } -#line 166 "reflect.h2" - auto compiler_services::expects(auto const& b, auto const& msg) const& -> void{ - require(b, msg); - if (!(b)) {throw(std::runtime_error(" ==> programming bug found in metafunction @" + cpp2::to_string(metafunction_name) + " - precondition violation - see previous errors")); } +#line 168 "reflect.h2" + auto compiler_services::violation(auto const& msg) const& -> void{ + error(msg); + throw(std::runtime_error(" ==> programming bug found in metafunction @" + cpp2::to_string(metafunction_name) + " - precondition violation - see previous errors")); } + [[nodiscard]] auto compiler_services::has_handler() const& -> auto { return true; } + compiler_services::~compiler_services() noexcept{} compiler_services::compiler_services(compiler_services const& that) : errors{ that.errors } @@ -899,7 +906,7 @@ compiler_services::compiler_services(compiler_services const& that) , metafunction_args{ that.metafunction_args } , metafunctions_used{ that.metafunctions_used }{} -#line 224 "reflect.h2" +#line 229 "reflect.h2" declaration_base::declaration_base( declaration_node* n_, @@ -907,11 +914,11 @@ compiler_services::compiler_services(compiler_services const& that) ) : compiler_services{ s } , n{ n_ } -#line 229 "reflect.h2" +#line 234 "reflect.h2" { -#line 232 "reflect.h2" - cpp2::Default.expects(n, "a meta::declaration must point to a valid declaration_node, not null"); +#line 237 "reflect.h2" + if (cpp2::Default.has_handler() && !(n) ) { cpp2::Default.violation("a meta::declaration must point to a valid declaration_node, not null"); } } [[nodiscard]] auto declaration_base::position() const -> source_position { return CPP2_UFCS(position)((*cpp2::assert_not_null(n))); } @@ -923,14 +930,14 @@ declaration_base::declaration_base(declaration_base const& that) : compiler_services{ static_cast(that) } , n{ that.n }{} -#line 248 "reflect.h2" +#line 253 "reflect.h2" declaration::declaration( declaration_node* n_, cpp2::in s ) : declaration_base{ n_, s } -#line 253 "reflect.h2" +#line 258 "reflect.h2" { } @@ -995,27 +1002,27 @@ declaration_base::declaration_base(declaration_base const& that) auto declaration::mark_for_removal_from_enclosing_type() & -> void { - cpp2::Type.expects(parent_is_type(), ""); -#line 317 "reflect.h2" + if (cpp2::Type.has_handler() && !(parent_is_type()) ) { cpp2::Type.violation(""); } +#line 322 "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 + if (cpp2::Default.has_handler() && !(std::move(test)) ) { cpp2::Default.violation(""); }// ... to ensure this assert is true } declaration::~declaration() noexcept{} declaration::declaration(declaration const& that) : declaration_base{ static_cast(that) }{} -#line 330 "reflect.h2" +#line 335 "reflect.h2" function_declaration::function_declaration( declaration_node* n_, cpp2::in s ) : declaration{ n_, s } -#line 335 "reflect.h2" +#line 340 "reflect.h2" { - cpp2::Default.expects(CPP2_UFCS(is_function)((*cpp2::assert_not_null(n))), ""); + if (cpp2::Default.has_handler() && !(CPP2_UFCS(is_function)((*cpp2::assert_not_null(n)))) ) { cpp2::Default.violation(""); } } [[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); } @@ -1070,16 +1077,16 @@ declaration::declaration(declaration const& that) auto function_declaration::add_initializer(cpp2::in source) & -> void -#line 393 "reflect.h2" +#line 398 "reflect.h2" { - (*this).expects(!(has_initializer()), "cannot add an initializer to a function that already has one"); - (*this).expects(parent_is_type(), "cannot add an initializer to a function that isn't in a type scope"); + if ((*this).has_handler() && !(!(has_initializer())) ) { (*this).violation("cannot add an initializer to a function that already has one"); } + if ((*this).has_handler() && !(parent_is_type()) ) { (*this).violation("cannot add an initializer to a function that isn't in a type scope"); } //require( !has_initializer(), // "cannot add an initializer to a function that already has one"); //require( parent_is_type(), // "cannot add an initializer to a function that isn't in a type scope"); -#line 399 "reflect.h2" +#line 404 "reflect.h2" auto stmt {parse_statement(source)}; if (!((cpp2::as_(stmt)))) { error("cannot add an initializer that is not a valid statement"); @@ -1092,17 +1099,17 @@ declaration::declaration(declaration const& that) function_declaration::function_declaration(function_declaration const& that) : declaration{ static_cast(that) }{} -#line 417 "reflect.h2" +#line 422 "reflect.h2" object_declaration::object_declaration( declaration_node* n_, cpp2::in s ) : declaration{ n_, s } -#line 422 "reflect.h2" +#line 427 "reflect.h2" { - cpp2::Default.expects(CPP2_UFCS(is_object)((*cpp2::assert_not_null(n))), ""); + if (cpp2::Default.has_handler() && !(CPP2_UFCS(is_object)((*cpp2::assert_not_null(n)))) ) { cpp2::Default.violation(""); } } [[nodiscard]] auto object_declaration::is_const() const& -> bool { return CPP2_UFCS(is_const)((*cpp2::assert_not_null(n))); } @@ -1125,17 +1132,17 @@ declaration::declaration(declaration const& that) object_declaration::object_declaration(object_declaration const& that) : declaration{ static_cast(that) }{} -#line 453 "reflect.h2" +#line 458 "reflect.h2" type_declaration::type_declaration( declaration_node* n_, cpp2::in s ) : declaration{ n_, s } -#line 458 "reflect.h2" +#line 463 "reflect.h2" { - cpp2::Default.expects(CPP2_UFCS(is_type)((*cpp2::assert_not_null(n))), ""); + if (cpp2::Default.has_handler() && !(CPP2_UFCS(is_type)((*cpp2::assert_not_null(n)))) ) { cpp2::Default.violation(""); } } auto type_declaration::reserve_names(cpp2::in name, auto&& ...etc) const& -> void @@ -1222,13 +1229,13 @@ declaration::declaration(declaration const& that) [[nodiscard]] auto type_declaration::query_declared_value_set_functions() const& -> query_declared_value_set_functions_ret -#line 552 "reflect.h2" +#line 557 "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 553 "reflect.h2" +#line 558 "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); @@ -1258,29 +1265,29 @@ declaration::declaration(declaration const& that) type_declaration::type_declaration(type_declaration const& that) : declaration{ static_cast(that) }{} -#line 588 "reflect.h2" +#line 593 "reflect.h2" alias_declaration::alias_declaration( declaration_node* n_, cpp2::in s ) : declaration{ n_, s } -#line 593 "reflect.h2" +#line 598 "reflect.h2" { - cpp2::Default.expects(CPP2_UFCS(is_alias)((*cpp2::assert_not_null(n))), ""); + if (cpp2::Default.has_handler() && !(CPP2_UFCS(is_alias)((*cpp2::assert_not_null(n)))) ) { cpp2::Default.violation(""); } } alias_declaration::alias_declaration(alias_declaration const& that) : declaration{ static_cast(that) }{} -#line 612 "reflect.h2" +#line 617 "reflect.h2" auto add_virtual_destructor(meta::type_declaration& t) -> void { CPP2_UFCS(add_member)(t, "operator=: (virtual move this) = { }"); } -#line 630 "reflect.h2" +#line 635 "reflect.h2" auto interface(meta::type_declaration& t) -> void { auto has_dtor {false}; @@ -1307,7 +1314,7 @@ auto interface(meta::type_declaration& t) -> void } } -#line 676 "reflect.h2" +#line 681 "reflect.h2" auto polymorphic_base(meta::type_declaration& t) -> void { auto has_dtor {false}; @@ -1332,7 +1339,7 @@ auto polymorphic_base(meta::type_declaration& t) -> void } } -#line 721 "reflect.h2" +#line 726 "reflect.h2" auto ordered_impl( meta::type_declaration& t, cpp2::in ordering @@ -1357,25 +1364,25 @@ auto ordered_impl( } } -#line 750 "reflect.h2" +#line 755 "reflect.h2" auto ordered(meta::type_declaration& t) -> void { ordered_impl(t, "strong_ordering"); } -#line 758 "reflect.h2" +#line 763 "reflect.h2" auto weakly_ordered(meta::type_declaration& t) -> void { ordered_impl(t, "weak_ordering"); } -#line 766 "reflect.h2" +#line 771 "reflect.h2" auto partially_ordered(meta::type_declaration& t) -> void { ordered_impl(t, "partial_ordering"); } -#line 788 "reflect.h2" +#line 793 "reflect.h2" auto copyable(meta::type_declaration& t) -> void { // If the user explicitly wrote any of the copy/move functions, @@ -1397,7 +1404,7 @@ auto copyable(meta::type_declaration& t) -> void }} } -#line 816 "reflect.h2" +#line 821 "reflect.h2" auto basic_value(meta::type_declaration& t) -> void { CPP2_UFCS(copyable)(t); @@ -1416,7 +1423,7 @@ auto basic_value(meta::type_declaration& t) -> void } } -#line 844 "reflect.h2" +#line 849 "reflect.h2" auto value(meta::type_declaration& t) -> void { CPP2_UFCS(ordered)(t); @@ -1435,7 +1442,7 @@ auto partially_ordered_value(meta::type_declaration& t) -> void CPP2_UFCS(basic_value)(t); } -#line 888 "reflect.h2" +#line 893 "reflect.h2" auto cpp2_struct(meta::type_declaration& t) -> void { for ( auto& m : CPP2_UFCS(get_members)(t) ) @@ -1453,7 +1460,7 @@ auto cpp2_struct(meta::type_declaration& t) -> void CPP2_UFCS(disable_member_function_generation)(t); } -#line 929 "reflect.h2" +#line 934 "reflect.h2" auto basic_enum( meta::type_declaration& t, auto const& nextval, @@ -1478,7 +1485,7 @@ auto basic_enum( { std::string value = "-1"; -#line 952 "reflect.h2" +#line 957 "reflect.h2" for ( auto const& m : CPP2_UFCS(get_members)(t) ) if ( CPP2_UFCS(is_member_object)(m)) @@ -1516,7 +1523,7 @@ std::string value = "-1"; } } -#line 988 "reflect.h2" +#line 993 "reflect.h2" CPP2_UFCS(require)(t, !(CPP2_UFCS(empty)(enumerators)), "an enumeration must contain at least one enumerator value"); @@ -1560,7 +1567,7 @@ std::string value = "-1"; } } -#line 1032 "reflect.h2" +#line 1037 "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' @@ -1608,7 +1615,7 @@ std::string to_string = " to_string: (this) -> std::string = { \n"; // Provide a 'to_string' function to print enumerator name(s) -#line 1077 "reflect.h2" +#line 1082 "reflect.h2" { if (bitwise) { to_string += " _ret : std::string = \"(\";\n"; @@ -1640,10 +1647,10 @@ std::string to_string = " to_string: (this) -> std::string = { \n"; CPP2_UFCS(add_member)(t, std::move(to_string)); } } -#line 1107 "reflect.h2" +#line 1112 "reflect.h2" } -#line 1119 "reflect.h2" +#line 1124 "reflect.h2" auto cpp2_enum(meta::type_declaration& t) -> void { // Let basic_enum do its thing, with an incrementing value generator @@ -1660,7 +1667,7 @@ auto cpp2_enum(meta::type_declaration& t) -> void ); } -#line 1146 "reflect.h2" +#line 1151 "reflect.h2" auto flag_enum(meta::type_declaration& t) -> void { // Let basic_enum do its thing, with a power-of-two value generator @@ -1682,7 +1689,7 @@ auto flag_enum(meta::type_declaration& t) -> void ); } -#line 1192 "reflect.h2" +#line 1197 "reflect.h2" auto cpp2_union(meta::type_declaration& t) -> void { std::vector alternatives {}; @@ -1691,7 +1698,7 @@ auto value = 0; // 1. Gather: All the user-written members, and find/compute the max size -#line 1199 "reflect.h2" +#line 1204 "reflect.h2" for ( auto const& m : CPP2_UFCS(get_members)(t) ) { do @@ -1716,7 +1723,7 @@ auto value = 0; } while (false); ++value; } } -#line 1222 "reflect.h2" +#line 1227 "reflect.h2" std::string discriminator_type {}; if (cpp2::cmp_less(CPP2_UFCS(ssize)(alternatives),std::numeric_limits::max())) { discriminator_type = "i8"; @@ -1731,7 +1738,7 @@ auto value = 0; discriminator_type = "i64"; }}} -#line 1237 "reflect.h2" +#line 1242 "reflect.h2" // 2. Replace: Erase the contents and replace with modified contents CPP2_UFCS(remove_marked_members)(t); @@ -1740,12 +1747,12 @@ std::string storage = " _storage: cpp2::aligned_storage t) -> void { std::cout << CPP2_UFCS(print)(t) << "\n"; } -#line 1338 "reflect.h2" +#line 1343 "reflect.h2" [[nodiscard]] auto apply_metafunctions( declaration_node& n, type_declaration& rtype, @@ -1856,7 +1863,7 @@ auto print(cpp2::in t) -> void ) -> bool { - cpp2::Default.expects(CPP2_UFCS(is_type)(n), ""); + if (cpp2::Default.has_handler() && !(CPP2_UFCS(is_type)(n)) ) { cpp2::Default.violation(""); } // Check for _names reserved for the metafunction implementation for ( @@ -1948,7 +1955,7 @@ auto print(cpp2::in t) -> void return true; } -#line 1438 "reflect.h2" +#line 1443 "reflect.h2" } } diff --git a/source/reflect.h2 b/source/reflect.h2 index 93d96a585b..3002e786da 100644 --- a/source/reflect.h2 +++ b/source/reflect.h2 @@ -140,6 +140,7 @@ compiler_services: @polymorphic_base @copyable type = } // Error diagnosis and handling, integrated with compiler output + // Unlike a contract violation, .requires continues further processing // require:( this, @@ -161,14 +162,18 @@ compiler_services: @polymorphic_base @copyable type = _ = errors*.emplace_back( position(), message); } - // Enable custom contracts on this object + // Enable custom contracts on this object, integrated with compiler output + // Unlike .requires, a contract violation stops further processing // - expects:(this, b, msg) = { - require(b, msg); - if !b { throw( std::runtime_error(" ==> programming bug found in metafunction @(metafunction_name)$ - precondition violation - see previous errors") ); } + violation:(this, msg) = { + error(msg); + throw( std::runtime_error(" ==> programming bug found in metafunction @(metafunction_name)$ - precondition violation - see previous errors") ); } + + has_handler:(this) true; } + /* //----------------------------------------------------------------------- // diff --git a/source/to_cpp1.h b/source/to_cpp1.h index 9d733b9c3f..400f27fca3 100644 --- a/source/to_cpp1.h +++ b/source/to_cpp1.h @@ -4531,10 +4531,28 @@ class cppfront { STACKINSTR assert (n.kind); - // "Axiom"s are for static analysis only, and are never evaluated, so just skip them - // (The only requirement for an Axiom condition is that it parses; and even that's - // easy to relax if we ever want to allow arbitrary tokens in an Axiom condition) - if (n.group && n.group->to_string() == "Axiom") { + // If this is one of Cpp2's predefined contract groups, + // make it convenient to use without cpp2:: qualification + auto name = std::string{"cpp2::Default"}; + if (n.group) + { + name = print_to_string(*n.group); + if ( + name == "Default" + || name == "Bounds" + || name == "Null" + || name == "Type" + || name == "Testing" + ) + { + name.insert(0, "cpp2::"); + } + } + + // "Unevaluated" is for static analysis only, and are never evaluated, so just skip them + // (The only requirement for an Unevaluated condition is that it parses; and even that's + // easy to relax if we ever want to allow arbitrary tokens in an Unevaluated condition) + if (n.group && n.group->to_string() == "Unevaluated") { return; } @@ -4549,48 +4567,19 @@ class cppfront ); } - // Emit the contract group name (defaults to cpp2::Default) + // Emit the contract group name + // and invoke .expects on that contract group // - if (n.group) { - // If this is one of Cpp2's predefined contract groups, - // make it convenient to use without cpp2:: qualification - if (auto uid = std::get_if(&n.group->id)) { - assert (*uid && (**uid).identifier); - if ( - *(**uid).identifier == "Default" - || *(**uid).identifier == "Bounds" - || *(**uid).identifier == "Null" - || *(**uid).identifier == "Type" - || *(**uid).identifier == "Testing" - ) - { - printer.print_cpp2("cpp2::", n.position()); - } - } - - printer.preempt_position_push(n.position()); - printer.add_pad_in_this_line(-20); - emit(*n.group); - printer.preempt_position_pop(); - } - else { - printer.print_cpp2("cpp2::Default", n.position()); - printer.add_pad_in_this_line(-8); - } - - // And invoke .expects on that contract group - // - printer.print_cpp2(".expects(", n.position()); assert(n.condition); - emit (*n.condition); - printer.print_cpp2(", ", n.position()); + auto message = std::string{"\"\""}; if (n.message) { - emit (*n.message); - } - else { - printer.print_cpp2("\"\"", n.position()); + message = print_to_string(*n.message); } - printer.print_cpp2(");", n.position()); + + printer.print_cpp2( + "if (" + name + ".has_handler() && !(" + print_to_string(*n.condition) + ") ) " + + "{ " + name + ".violation(" + message + "); }", n.position() + ); // For a postcondition, close out the lambda //