diff --git a/libcxx/test/std/contracts/exceptions-test.pass.cpp b/libcxx/test/std/contracts/exceptions-test.pass.cpp index 8ba3d61b6d097..c4d8a548d3c80 100644 --- a/libcxx/test/std/contracts/exceptions-test.pass.cpp +++ b/libcxx/test/std/contracts/exceptions-test.pass.cpp @@ -1,24 +1,59 @@ +// ADDITIONAL_COMPILE_FLAGS: -std=c++26 -Xclang -fcontracts -fcontract-evaluation-semantic=enforce -fcontract-group-evaluation-semantic=observe=observe,enforce=enforce + + #include -#include "contracts_test.h" #include "nttp_string.h" #include "contracts_support.h" #include "contracts_handler.h" +#include "test_register.h" +#include +#include -struct A : CAliveCounter<"A"> { +namespace exception_handling { +#define OBSERVE [[clang::contract_group("observe")]] +void foo() { -}; + contract_assert [[clang::contract_group("observe")]] ((true) ? throw 42 : true); + + +} -int main() { - ContractHandlerInstaller installer; - installer.install([&]() { - installer.uninstall(); +REGISTER_TEST(test_ex_handling) { + ContractHandlerInstaller CHI; + int called = 0; + CHI.install([&]() { + ++called; + assert(std::current_exception()); + }); + contract_assert OBSERVE ((true) ? throw 42 : true); + assert(called); + called = 0; - }) - { - A a; - { - A a2; + CHI.install([&]() { + ++called; + assert(!std::current_exception()); + assert(KV<"Local"> == 1); + assert(KV<"Local2"> == 0); - } + throw 42; + }); + + try { + + [] { + CAliveCounter<"Local"> Local; + contract_assert((CAliveCounter<"Local2">{}, false)); + assert(KV<"Local2"> == 1); + }(); + assert(false); + } catch (int) { + KV<"InCatch">++; } -} + assert(called == 1); + assert(NC<"Local"> == 0); + assert(KV<"Local2"> == 0); + assert(NC<"InCatch">.consume() == 1); + +}; + +} // namespace exception_handling diff --git a/libcxx/test/std/contracts/member_function_tests.pass.cpp b/libcxx/test/std/contracts/member_function_tests.pass.cpp index 767ed3b2262c1..8c766cb859181 100644 --- a/libcxx/test/std/contracts/member_function_tests.pass.cpp +++ b/libcxx/test/std/contracts/member_function_tests.pass.cpp @@ -1,10 +1,11 @@ // ADDITIONAL_COMPILE_FLAGS: -std=c++26 -Xclang -fcontracts -fcontract-evaluation-semantic=enforce -fcontract-group-evaluation-semantic=observe=observe,enforce=enforce #include "nttp_string.h" -#include "contracts_test.h" +#include "contracts_support.h" #include "test_register.h" #include "contracts_handler.h" + namespace fn_template_test { template void f(T v) pre(++KV<"Pre">&& v != 1024) post(++KV<"Post">) pre(++KV ? "Int" : "NotInt">) { @@ -198,51 +199,3 @@ REGISTER_TEST(order_test) { }; } // namespace order_test - -namespace exception_handling { - -void foo(int x) { - - contract_assert [[clang::contract_group("observe")]] ((true) ? throw 42 : true); - - -} - -REGISTER_TEST(test_ex_handling) { - ContractHandlerInstaller CHI; - int called = 0; - CHI.install([&]() { - ++called; - assert(std::current_exception()); - }); - foo(0); - assert(called); - called = 0; - - CHI.install([&]() { - ++called; - assert(!std::current_exception()); - assert(KV<"Local"> == 1); - assert(KV<"Local2"> == 0); - - throw 42; - }); - - try { - - []() { - CAliveCounter<"Local"> Local; - contract_assert((CAliveCounter<"Local2">{}, false)); - }(); - assert(false); - } catch (int) { - KV<"InCatch">++; - } - assert(called == 1); - assert(KV<"Local"> == 0); - assert(KV<"Local2"> == 0); - assert(KV<"InCatch"> == 1); - -}; - -} // namespace exception_handling diff --git a/libcxx/test/support/contracts_support.h b/libcxx/test/support/contracts_support.h index 37522f27aa331..9ec8edbd0d514 100644 --- a/libcxx/test/support/contracts_support.h +++ b/libcxx/test/support/contracts_support.h @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -15,10 +16,18 @@ #include #include #include - +#include +#include #include "dump_struct.h" #include "nttp_string.h" +#pragma clang diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#pragma GCC diagnostic ignored "-Wunused" +#pragma GCC diagnostic ignored "-Wunused-template" +#pragma GCC diagnostic ignored "-Wunused-parameter" + + #define COUNTERS_EQ(list, ...) assert(eq(list, {__VA_ARGS__})) #define SLOC(name) std::source_location name = std::source_location::current() @@ -564,6 +573,7 @@ template auto& KV = get_or_insert(Str.str()); struct NamedCounter { + constexpr NamedCounter(const char* name, int* counter, SLOC(loc)) : Name(get_global_string(name ? name : "")), Counter(counter), LastLoc(loc) {} constexpr NamedCounter(const char* name, SLOC(loc)) : Name(get_global_string( name ? name : "")), Counter(&get_or_insert(std::string(Name))), LastLoc(loc) {} constexpr NamedCounter(TStr name, SLOC(loc)) : Name(get_global_string(name.sv())), Counter(&get_or_insert(name.str())), LastLoc(loc) {} @@ -608,8 +618,23 @@ struct NamedCounter { return LHS; } - friend auto operator<=>(NamedCounter& LHS, int RHS) { - return *LHS.Counter <=> RHS; + friend NamedCounter& operator-=(NamedCounter& LHS, int RHS) { + *LHS.Counter -= RHS; + return LHS; + } + + bool operator==(int RHS) const { + return *Counter == RHS; + } + + auto operator<=>(int RHS) const { + return *Counter <=> RHS; + } + + int consume() { + int tmp = *Counter; + *Counter = 0; + return tmp; } bool assert_eq(int RHS, SLOC(loc)) { @@ -657,7 +682,7 @@ struct NamedCounter { template -auto NC = NamedCounter{Key.str(), &KV}; +auto NC = NamedCounter{get_global_string(Key.str()).data(), &KV}; inline bool count(bool value) { @@ -734,39 +759,44 @@ template auto CounterGroup = std::tuple...>{GetCounterStore()[Key.str()]...}; struct AliveCounter { - explicit AliveCounter(const char* key) : Counter(&CounterStore[key]) { - assert(Counter && *Counter >= 0); - *Counter += 1; + explicit AliveCounter(NamedCounter counter, SLOC(loc)) : Counter(counter) { + assert(Counter >= 0); + Counter += 1; + } + explicit AliveCounter(const char* key, SLOC(loc)) : Counter(key, loc) { + assert(Counter >= 0); + Counter += 1; } AliveCounter(nullptr_t) = delete; AliveCounter(void*) = delete; - constexpr AliveCounter(int* dest) : Counter(dest) { - assert(Counter && *Counter >= 0); - *Counter += 1; + constexpr AliveCounter(int* dest, SLOC(loc)) : Counter("", dest, loc) { + assert(Counter >= 0); + Counter += 1; } constexpr AliveCounter(AliveCounter const& RHS) : Counter(RHS.Counter) { - assert(Counter && *Counter >= 0); - *Counter += 1; + assert(Counter >= 0); + Counter += 1; } ~AliveCounter() { - assert(*Counter >= 1); - *Counter -= 1; + assert(Counter >= 1); + Counter -= 1; } - int* Counter; + NamedCounter Counter; }; template struct CAliveCounter : private AliveCounter { - CAliveCounter() : AliveCounter(&KV) {} + CAliveCounter(SLOC(loc)) : AliveCounter(Key.sv().data(), loc) {} CAliveCounter(CAliveCounter const& RHS) : AliveCounter(RHS) {} ~CAliveCounter() = default; }; +#pragma clang diagnostic pop #endif // LIBCXX_TEST_CONTRACTS_SUPPORT_H \ No newline at end of file diff --git a/libcxx/test/support/contracts_test.h b/libcxx/test/support/contracts_test.h deleted file mode 100644 index 74763187c6106..0000000000000 --- a/libcxx/test/support/contracts_test.h +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "test_macros.h" -#include "nttp_string.h" -#include "contracts_support.h" - -#pragma GCC diagnostic ignored "-Wunused-variable" -#pragma GCC diagnostic ignored "-Wunused" -#pragma GCC diagnostic ignored "-Wunused-template" -#pragma GCC diagnostic ignored "-Wunused-parameter" - -#define STR2(x) #x -#define STR(x) STR2(x) -#define CONCAT1(x, y) x##y -#define CONCAT(x, y) CONCAT1(x, y) -#define REGISTER_TEST(test) static ::TestRegistrar ANON_VAR(test) = []() -#define ANON_VAR(id) CONCAT(anon_var_, CONCAT(id, __LINE__)) -#define COUNTERS_EQ(list, ...) assert(eq(list, {__VA_ARGS__})) -