Skip to content

Commit f1985d5

Browse files
authored
[clang] Ensure type aware allocators handle transparent decl contexts (llvm#138616)
We were testing the immediate DeclContext for found new and delete operators, which is incorrect if the declarations are contained by a transparent decl as can be induced with extern or export statements.
1 parent ffc5f79 commit f1985d5

File tree

2 files changed

+56
-8
lines changed

2 files changed

+56
-8
lines changed

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3070,18 +3070,24 @@ bool Sema::FindAllocationFunctions(
30703070
Filter.done();
30713071
}
30723072

3073+
auto GetRedeclContext = [](Decl *D) {
3074+
return D->getDeclContext()->getRedeclContext();
3075+
};
3076+
3077+
DeclContext *OperatorNewContext = GetRedeclContext(OperatorNew);
3078+
30733079
bool FoundGlobalDelete = FoundDelete.empty();
30743080
bool IsClassScopedTypeAwareNew =
30753081
isTypeAwareAllocation(IAP.PassTypeIdentity) &&
3076-
OperatorNew->getDeclContext()->isRecord();
3082+
OperatorNewContext->isRecord();
30773083
auto DiagnoseMissingTypeAwareCleanupOperator = [&](bool IsPlacementOperator) {
30783084
assert(isTypeAwareAllocation(IAP.PassTypeIdentity));
30793085
if (Diagnose) {
30803086
Diag(StartLoc, diag::err_mismatching_type_aware_cleanup_deallocator)
30813087
<< OperatorNew->getDeclName() << IsPlacementOperator << DeleteName;
30823088
Diag(OperatorNew->getLocation(), diag::note_type_aware_operator_declared)
30833089
<< OperatorNew->isTypeAwareOperatorNewOrDelete()
3084-
<< OperatorNew->getDeclName() << OperatorNew->getDeclContext();
3090+
<< OperatorNew->getDeclName() << OperatorNewContext;
30853091
}
30863092
};
30873093
if (IsClassScopedTypeAwareNew && FoundDelete.empty()) {
@@ -3224,15 +3230,15 @@ bool Sema::FindAllocationFunctions(
32243230
// deallocation function will be called.
32253231
if (Matches.size() == 1) {
32263232
OperatorDelete = Matches[0].second;
3233+
DeclContext *OperatorDeleteContext = GetRedeclContext(OperatorDelete);
32273234
bool FoundTypeAwareOperator =
32283235
OperatorDelete->isTypeAwareOperatorNewOrDelete() ||
32293236
OperatorNew->isTypeAwareOperatorNewOrDelete();
32303237
if (Diagnose && FoundTypeAwareOperator) {
32313238
bool MismatchedTypeAwareness =
32323239
OperatorDelete->isTypeAwareOperatorNewOrDelete() !=
32333240
OperatorNew->isTypeAwareOperatorNewOrDelete();
3234-
bool MismatchedContext =
3235-
OperatorDelete->getDeclContext() != OperatorNew->getDeclContext();
3241+
bool MismatchedContext = OperatorDeleteContext != OperatorNewContext;
32363242
if (MismatchedTypeAwareness || MismatchedContext) {
32373243
FunctionDecl *Operators[] = {OperatorDelete, OperatorNew};
32383244
bool TypeAwareOperatorIndex =
@@ -3241,16 +3247,15 @@ bool Sema::FindAllocationFunctions(
32413247
<< Operators[TypeAwareOperatorIndex]->getDeclName()
32423248
<< isPlacementNew
32433249
<< Operators[!TypeAwareOperatorIndex]->getDeclName()
3244-
<< Operators[TypeAwareOperatorIndex]->getDeclContext();
3250+
<< GetRedeclContext(Operators[TypeAwareOperatorIndex]);
32453251
Diag(OperatorNew->getLocation(),
32463252
diag::note_type_aware_operator_declared)
32473253
<< OperatorNew->isTypeAwareOperatorNewOrDelete()
3248-
<< OperatorNew->getDeclName() << OperatorNew->getDeclContext();
3254+
<< OperatorNew->getDeclName() << OperatorNewContext;
32493255
Diag(OperatorDelete->getLocation(),
32503256
diag::note_type_aware_operator_declared)
32513257
<< OperatorDelete->isTypeAwareOperatorNewOrDelete()
3252-
<< OperatorDelete->getDeclName()
3253-
<< OperatorDelete->getDeclContext();
3258+
<< OperatorDelete->getDeclName() << OperatorDeleteContext;
32543259
}
32553260
}
32563261

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++26 -fexceptions -DTRANSPARENT_DECL=0
2+
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++26 -fexceptions -DTRANSPARENT_DECL=1
3+
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++26 -fexceptions -DTRANSPARENT_DECL=2
4+
5+
// expected-no-diagnostics
6+
#if TRANSPARENT_DECL==2
7+
export module Testing;
8+
#endif
9+
10+
namespace std {
11+
template <class T> struct type_identity {};
12+
using size_t = __SIZE_TYPE__;
13+
enum class align_val_t : size_t {};
14+
struct destroying_delete_t { explicit destroying_delete_t() = default; };
15+
}
16+
17+
#if TRANSPARENT_DECL==0
18+
#define BEGIN_TRANSPARENT_DECL extern "C" {
19+
#define END_TRANSPARENT_DECL }
20+
#elif TRANSPARENT_DECL==1
21+
#define BEGIN_TRANSPARENT_DECL extern "C++" {
22+
#define END_TRANSPARENT_DECL }
23+
#elif TRANSPARENT_DECL==2
24+
#define BEGIN_TRANSPARENT_DECL export {
25+
#define END_TRANSPARENT_DECL }
26+
#else
27+
#error unexpected decl kind
28+
#endif
29+
30+
BEGIN_TRANSPARENT_DECL
31+
void *operator new(std::type_identity<int>, std::size_t, std::align_val_t);
32+
void operator delete[](std::type_identity<int>, void*, std::size_t, std::align_val_t);
33+
END_TRANSPARENT_DECL
34+
35+
void *operator new[](std::type_identity<int>, std::size_t, std::align_val_t);
36+
void operator delete(std::type_identity<int>, void*, std::size_t, std::align_val_t);
37+
38+
void foo() {
39+
int *iptr = new int;
40+
delete iptr;
41+
int *iarray = new int[5];
42+
delete [] iarray;
43+
}

0 commit comments

Comments
 (0)