Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ Bug Fixes to Attribute Support
- Fix a crash when the function name is empty in the `swift_name` attribute. (#GH157075)
- Fixes crashes or missing diagnostics with the `device_kernel` attribute. (#GH161905)
- Fix handling of parameter indexes when an attribute is applied to a C++23 explicit object member function.
- Fixed several false positives and false negatives in function effect (`nonblocking`) analysis. (#GH166078) (#GH166101) (#GH166110)

Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/Sema/SemaFunctionEffects.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1271,7 +1271,15 @@ class Analyzer {
const CXXConstructorDecl *Ctor = Construct->getConstructor();
CallableInfo CI(*Ctor);
followCall(CI, Construct->getLocation());
return true;
}

bool VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *BTE) override {
const CXXDestructorDecl *Dtor = BTE->getTemporary()->getDestructor();
if (Dtor != nullptr) {
CallableInfo CI(*Dtor);
followCall(CI, BTE->getBeginLoc());
}
return true;
}

Expand Down
27 changes: 27 additions & 0 deletions clang/test/Sema/attr-nonblocking-constraints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,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'}}
Expand Down