|
5 | 5 | // This diagnostic is re-enabled and exercised in isolation later in this file. |
6 | 6 | #pragma clang diagnostic ignored "-Wperf-constraint-implies-noexcept" |
7 | 7 |
|
| 8 | +typedef __SIZE_TYPE__ size_t; |
| 9 | + |
8 | 10 | // --- CONSTRAINTS --- |
9 | 11 |
|
10 | 12 | void nb1() [[clang::nonblocking]] |
@@ -430,6 +432,44 @@ struct HasDtor { |
430 | 432 | ~HasDtor() {} |
431 | 433 | }; |
432 | 434 |
|
| 435 | +struct SafeDeleteUnsafeDestroy { |
| 436 | + static unsigned char storage[256]; |
| 437 | + |
| 438 | + void* operator new(size_t) { return storage; } |
| 439 | + void operator delete(void* ptr) {} |
| 440 | + |
| 441 | + void* operator new[](size_t sz) { return storage; } |
| 442 | + void operator delete[](void* ptr) {} |
| 443 | + |
| 444 | + SafeDeleteUnsafeDestroy(); // expected-note 2 {{declaration cannot be inferred 'nonblocking' because it has no definition in this translation unit}} |
| 445 | + ~SafeDeleteUnsafeDestroy(); // expected-note 2 {{declaration cannot be inferred 'nonblocking' because it has no definition in this translation unit}} |
| 446 | +}; |
| 447 | + |
| 448 | +void testSafeDeleteUnsafeDestroy() [[clang::nonblocking]] |
| 449 | +{ |
| 450 | + auto *ptr = new SafeDeleteUnsafeDestroy; // expected-warning {{function with 'nonblocking' attribute must not call non-'nonblocking' constructor 'SafeDeleteUnsafeDestroy::SafeDeleteUnsafeDestroy'}} |
| 451 | + delete ptr; // expected-warning {{function with 'nonblocking' attribute must not call non-'nonblocking' destructor 'SafeDeleteUnsafeDestroy::~SafeDeleteUnsafeDestroy'}} |
| 452 | + |
| 453 | + auto *arr = new SafeDeleteUnsafeDestroy[2]; // expected-warning {{function with 'nonblocking' attribute must not call non-'nonblocking' constructor 'SafeDeleteUnsafeDestroy::SafeDeleteUnsafeDestroy'}} |
| 454 | + delete[] arr; // expected-warning {{function with 'nonblocking' attribute must not call non-'nonblocking' destructor 'SafeDeleteUnsafeDestroy::~SafeDeleteUnsafeDestroy'}} |
| 455 | +} |
| 456 | + |
| 457 | +namespace std { |
| 458 | +struct destroying_delete_t { explicit destroying_delete_t() = default; }; |
| 459 | +inline constexpr destroying_delete_t destroying_delete{}; |
| 460 | +} |
| 461 | + |
| 462 | +struct DestroyingDelete { |
| 463 | + ~DestroyingDelete(); |
| 464 | + void operator delete(DestroyingDelete*, std::destroying_delete_t) { |
| 465 | + // do nothing |
| 466 | + } |
| 467 | +}; |
| 468 | + |
| 469 | +void testDestroyingDelete(DestroyingDelete* d) [[clang::nonblocking]] { |
| 470 | + delete d; |
| 471 | +} |
| 472 | + |
433 | 473 | template <typename T> |
434 | 474 | struct Optional { |
435 | 475 | union { |
|
0 commit comments