You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Clang] FunctionEffect analysis was missing a CXXBindTemporaryExpr's implicit call to a destructor. (#166110)
This example is reduced from a discovery: resetting a shared pointer
from a nonblocking function is not diagnosed.
```
void nb23()
{
struct X {
int *ptr = nullptr;
X() {}
~X() { delete ptr; }
};
auto inner = []() [[clang::nonblocking]] {
X();
};
}
```
`shared_ptr<T>::reset()` creates a temporary `shared_ptr` and swaps it
with its current state. The temporary `shared_ptr` constructor is
nonblocking but its destructor potentially deallocates memory and is
unsafe.
Analysis was ignoring the implicit call in the AST to destroy the
temporary.
---------
Co-authored-by: Doug Wyatt <[email protected]>
Copy file name to clipboardExpand all lines: clang/test/Sema/attr-nonblocking-constraints.cpp
+27Lines changed: 27 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -373,6 +373,33 @@ struct Unsafe {
373
373
Unsafe(float y) [[clang::nonblocking]] : Unsafe(int(y)) {} // expected-warning {{constructor with 'nonblocking' attribute must not call non-'nonblocking' constructor 'Unsafe::Unsafe'}}
374
374
};
375
375
376
+
// Exercise cases of a temporary with a safe constructor and unsafe destructor.
377
+
voidnb23()
378
+
{
379
+
structX {
380
+
int *ptr = nullptr;
381
+
X() {}
382
+
~X() { delete ptr; } // expected-note 2 {{destructor cannot be inferred 'nonblocking' because it allocates or deallocates memory}}
383
+
};
384
+
385
+
auto inner = []() [[clang::nonblocking]] {
386
+
X(); // expected-warning {{lambda with 'nonblocking' attribute must not call non-'nonblocking' destructor 'nb23()::X::~X'}}
387
+
};
388
+
389
+
auto inner2 = [](X x) [[clang::nonblocking]] { // expected-warning {{lambda with 'nonblocking' attribute must not call non-'nonblocking' destructor 'nb23()::X::~X'}}
390
+
};
391
+
392
+
}
393
+
394
+
structS2 { ~S2(); }; // expected-note 2 {{declaration cannot be inferred 'nonblocking' because it has no definition in this translation unit}}
395
+
voidnb24() {
396
+
S2 s;
397
+
[&]() [[clang::nonblocking]] {
398
+
[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'}}
399
+
[=]{ 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'}}
400
+
}();
401
+
}
402
+
376
403
structDerivedFromUnsafe : publicUnsafe {
377
404
DerivedFromUnsafe() [[clang::nonblocking]] {} // expected-warning {{constructor with 'nonblocking' attribute must not call non-'nonblocking' constructor 'Unsafe::Unsafe'}}
378
405
DerivedFromUnsafe(int x) [[clang::nonblocking]] : Unsafe(x) {} // expected-warning {{constructor with 'nonblocking' attribute must not call non-'nonblocking' constructor 'Unsafe::Unsafe'}}
0 commit comments