================ @@ -0,0 +1,256 @@ +// RUN: %clang_cc1 -fsyntax-only -fblocks -fcxx-exceptions -std=c++20 -verify %s +// These are in a separate file because errors (e.g. incompatible attributes) currently prevent +// the FXAnalysis pass from running at all. + +// This diagnostic is re-enabled and exercised in isolation later in this file. +#pragma clang diagnostic ignored "-Wperf-constraint-implies-noexcept" + +// --- CONSTRAINTS --- + +void nb1() [[clang::nonblocking]] +{ + int *pInt = new int; // expected-warning {{'nonblocking' function must not allocate or deallocate memory}} + delete pInt; // expected-warning {{'nonblocking' function must not allocate or deallocate memory}} +} + +void nb2() [[clang::nonblocking]] +{ + static int global; // expected-warning {{'nonblocking' function must not have static locals}} +} + +void nb3() [[clang::nonblocking]] +{ + try { + throw 42; // expected-warning {{'nonblocking' function must not throw or catch exceptions}} + } + catch (...) { // expected-warning {{'nonblocking' function must not throw or catch exceptions}} + } +} + +void nb4_inline() {} +void nb4_not_inline(); // expected-note {{declaration cannot be inferred 'nonblocking' because it has no definition in this translation unit}} + +void nb4() [[clang::nonblocking]] +{ + nb4_inline(); // OK + nb4_not_inline(); // expected-warning {{'nonblocking' function must not call non-'nonblocking' function}} +} + + +struct HasVirtual { + virtual void unsafe(); // expected-note {{virtual method cannot be inferred 'nonblocking'}} +}; + +void nb5() [[clang::nonblocking]] +{ + HasVirtual hv; + hv.unsafe(); // expected-warning {{'nonblocking' function must not call non-'nonblocking' function}} +} + +void nb6_unsafe(); // expected-note {{declaration cannot be inferred 'nonblocking' because it has no definition in this translation unit}} +void nb6_transitively_unsafe() +{ + nb6_unsafe(); // expected-note {{function cannot be inferred 'nonblocking' because it calls non-'nonblocking' function}} +} + +void nb6() [[clang::nonblocking]] +{ + nb6_transitively_unsafe(); // expected-warning {{'nonblocking' function must not call non-'nonblocking' function}} +} + +thread_local int tl_var{ 42 }; + +bool tl_test() [[clang::nonblocking]] +{ + return tl_var > 0; // expected-warning {{'nonblocking' function must not use thread-local variables}} +} + +void nb7() +{ + // Make sure we verify blocks + auto blk = ^() [[clang::nonblocking]] { + throw 42; // expected-warning {{'nonblocking' function must not throw or catch exceptions}} + }; +} + +void nb8() +{ + // Make sure we verify lambdas + auto lambda = []() [[clang::nonblocking]] { + throw 42; // expected-warning {{'nonblocking' function must not throw or catch exceptions}} + }; +} + +void nb8a() [[clang::nonblocking]] +{ + // A blocking lambda shouldn't make the outer function unsafe. + auto unsafeLambda = []() { + throw 42; + }; +} + +void nb8b() [[clang::nonblocking]] +{ + // An unsafe lambda capture makes the outer function unsafe. + auto unsafeCapture = [foo = new int]() { // expected-warning {{'nonblocking' function must not allocate or deallocate memory}} + delete foo; ---------------- Sirraide wrote:
Maybe add a test for `__builtin_operator_new`/`__builtin_operator_delete` too. https://github.com/llvm/llvm-project/pull/99656 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits