diff options
Diffstat (limited to 'clang/test/Sema/attr-nonblocking-constraints.cpp')
| -rw-r--r-- | clang/test/Sema/attr-nonblocking-constraints.cpp | 60 |
1 files changed, 53 insertions, 7 deletions
diff --git a/clang/test/Sema/attr-nonblocking-constraints.cpp b/clang/test/Sema/attr-nonblocking-constraints.cpp index b26a945..881e816 100644 --- a/clang/test/Sema/attr-nonblocking-constraints.cpp +++ b/clang/test/Sema/attr-nonblocking-constraints.cpp @@ -235,16 +235,35 @@ void nb13() [[clang::nonblocking]] { nb12(); } // C++ member function pointers struct PTMFTester { typedef void (PTMFTester::*ConvertFunction)() [[clang::nonblocking]]; - - void convert() [[clang::nonblocking]]; + typedef void (PTMFTester::*BlockingFunction)(); ConvertFunction mConvertFunc; -}; -void PTMFTester::convert() [[clang::nonblocking]] -{ - (this->*mConvertFunc)(); -} + void convert() [[clang::nonblocking]] + { + (this->*mConvertFunc)(); // This should not generate a warning. + } + + template <typename T> + struct Holder { + T value; + + T& operator*() { return value; } + }; + + + void ptmfInExpr(Holder<ConvertFunction>& holder) [[clang::nonblocking]] + { + (this->*(*holder))(); // Should not generate a warning. + ((*this).*(*holder))(); // Should not generate a warning. + } + + void ptmfInExpr(Holder<BlockingFunction>& holder) [[clang::nonblocking]] + { + (this->*(*holder))(); // expected-warning {{function with 'nonblocking' attribute must not call non-'nonblocking' expression}} + ((*this).*(*holder))(); // expected-warning {{function with 'nonblocking' attribute must not call non-'nonblocking' expression}} + } +}; // Allow implicit conversion from array to pointer. void nb14(unsigned idx) [[clang::nonblocking]] @@ -354,6 +373,33 @@ struct Unsafe { Unsafe(float y) [[clang::nonblocking]] : Unsafe(int(y)) {} // expected-warning {{constructor with 'nonblocking' attribute must not call non-'nonblocking' constructor 'Unsafe::Unsafe'}} }; +// Exercise cases of a temporary with a safe constructor and unsafe destructor. +void nb23() +{ + struct X { + int *ptr = nullptr; + X() {} + ~X() { delete ptr; } // expected-note 2 {{destructor cannot be inferred 'nonblocking' because it allocates or deallocates memory}} + }; + + auto inner = []() [[clang::nonblocking]] { + X(); // expected-warning {{lambda with 'nonblocking' attribute must not call non-'nonblocking' destructor 'nb23()::X::~X'}} + }; + + auto inner2 = [](X x) [[clang::nonblocking]] { // expected-warning {{lambda with 'nonblocking' attribute must not call non-'nonblocking' destructor 'nb23()::X::~X'}} + }; + +} + +struct S2 { ~S2(); }; // expected-note 2 {{declaration cannot be inferred 'nonblocking' because it has no definition in this translation unit}} +void nb24() { + S2 s; + [&]() [[clang::nonblocking]] { + [s]{ auto x = &s; }(); // expected-warning {{lambda with 'nonblocking' attribute must not call non-'nonblocking' destructor}} expected-note {{destructor cannot be inferred 'nonblocking' because it calls non-'nonblocking' destructor 'S2::~S2'}} + [=]{ auto x = &s; }(); // expected-warning {{lambda with 'nonblocking' attribute must not call non-'nonblocking' destructor}} expected-note {{destructor cannot be inferred 'nonblocking' because it calls non-'nonblocking' destructor 'S2::~S2'}} + }(); +} + struct DerivedFromUnsafe : public Unsafe { DerivedFromUnsafe() [[clang::nonblocking]] {} // expected-warning {{constructor with 'nonblocking' attribute must not call non-'nonblocking' constructor 'Unsafe::Unsafe'}} DerivedFromUnsafe(int x) [[clang::nonblocking]] : Unsafe(x) {} // expected-warning {{constructor with 'nonblocking' attribute must not call non-'nonblocking' constructor 'Unsafe::Unsafe'}} |
