Author: Oliver Hunt Date: 2025-05-05T22:39:17-07:00 New Revision: f1985d583d283fc662c94ef39feeb58bed19ac2c
URL: https://github.com/llvm/llvm-project/commit/f1985d583d283fc662c94ef39feeb58bed19ac2c DIFF: https://github.com/llvm/llvm-project/commit/f1985d583d283fc662c94ef39feeb58bed19ac2c.diff LOG: [clang] Ensure type aware allocators handle transparent decl contexts (#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. Added: clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp Modified: clang/lib/Sema/SemaExprCXX.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 235ea1529b0b8..5bfd608afba04 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -3070,10 +3070,16 @@ bool Sema::FindAllocationFunctions( Filter.done(); } + auto GetRedeclContext = [](Decl *D) { + return D->getDeclContext()->getRedeclContext(); + }; + + DeclContext *OperatorNewContext = GetRedeclContext(OperatorNew); + bool FoundGlobalDelete = FoundDelete.empty(); bool IsClassScopedTypeAwareNew = isTypeAwareAllocation(IAP.PassTypeIdentity) && - OperatorNew->getDeclContext()->isRecord(); + OperatorNewContext->isRecord(); auto DiagnoseMissingTypeAwareCleanupOperator = [&](bool IsPlacementOperator) { assert(isTypeAwareAllocation(IAP.PassTypeIdentity)); if (Diagnose) { @@ -3081,7 +3087,7 @@ bool Sema::FindAllocationFunctions( << OperatorNew->getDeclName() << IsPlacementOperator << DeleteName; Diag(OperatorNew->getLocation(), diag::note_type_aware_operator_declared) << OperatorNew->isTypeAwareOperatorNewOrDelete() - << OperatorNew->getDeclName() << OperatorNew->getDeclContext(); + << OperatorNew->getDeclName() << OperatorNewContext; } }; if (IsClassScopedTypeAwareNew && FoundDelete.empty()) { @@ -3224,6 +3230,7 @@ bool Sema::FindAllocationFunctions( // deallocation function will be called. if (Matches.size() == 1) { OperatorDelete = Matches[0].second; + DeclContext *OperatorDeleteContext = GetRedeclContext(OperatorDelete); bool FoundTypeAwareOperator = OperatorDelete->isTypeAwareOperatorNewOrDelete() || OperatorNew->isTypeAwareOperatorNewOrDelete(); @@ -3231,8 +3238,7 @@ bool Sema::FindAllocationFunctions( bool MismatchedTypeAwareness = OperatorDelete->isTypeAwareOperatorNewOrDelete() != OperatorNew->isTypeAwareOperatorNewOrDelete(); - bool MismatchedContext = - OperatorDelete->getDeclContext() != OperatorNew->getDeclContext(); + bool MismatchedContext = OperatorDeleteContext != OperatorNewContext; if (MismatchedTypeAwareness || MismatchedContext) { FunctionDecl *Operators[] = {OperatorDelete, OperatorNew}; bool TypeAwareOperatorIndex = @@ -3241,16 +3247,15 @@ bool Sema::FindAllocationFunctions( << Operators[TypeAwareOperatorIndex]->getDeclName() << isPlacementNew << Operators[!TypeAwareOperatorIndex]->getDeclName() - << Operators[TypeAwareOperatorIndex]->getDeclContext(); + << GetRedeclContext(Operators[TypeAwareOperatorIndex]); Diag(OperatorNew->getLocation(), diag::note_type_aware_operator_declared) << OperatorNew->isTypeAwareOperatorNewOrDelete() - << OperatorNew->getDeclName() << OperatorNew->getDeclContext(); + << OperatorNew->getDeclName() << OperatorNewContext; Diag(OperatorDelete->getLocation(), diag::note_type_aware_operator_declared) << OperatorDelete->isTypeAwareOperatorNewOrDelete() - << OperatorDelete->getDeclName() - << OperatorDelete->getDeclContext(); + << OperatorDelete->getDeclName() << OperatorDeleteContext; } } diff --git a/clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp b/clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp new file mode 100644 index 0000000000000..7c0b967a3c03f --- /dev/null +++ b/clang/test/SemaCXX/type-aware-new-delete-transparent-contexts.cpp @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++26 -fexceptions -DTRANSPARENT_DECL=0 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++26 -fexceptions -DTRANSPARENT_DECL=1 +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++26 -fexceptions -DTRANSPARENT_DECL=2 + +// expected-no-diagnostics +#if TRANSPARENT_DECL==2 +export module Testing; +#endif + +namespace std { + template <class T> struct type_identity {}; + using size_t = __SIZE_TYPE__; + enum class align_val_t : size_t {}; + struct destroying_delete_t { explicit destroying_delete_t() = default; }; +} + +#if TRANSPARENT_DECL==0 +#define BEGIN_TRANSPARENT_DECL extern "C" { +#define END_TRANSPARENT_DECL } +#elif TRANSPARENT_DECL==1 +#define BEGIN_TRANSPARENT_DECL extern "C++" { +#define END_TRANSPARENT_DECL } +#elif TRANSPARENT_DECL==2 +#define BEGIN_TRANSPARENT_DECL export { +#define END_TRANSPARENT_DECL } +#else +#error unexpected decl kind +#endif + +BEGIN_TRANSPARENT_DECL + void *operator new(std::type_identity<int>, std::size_t, std::align_val_t); + void operator delete[](std::type_identity<int>, void*, std::size_t, std::align_val_t); +END_TRANSPARENT_DECL + +void *operator new[](std::type_identity<int>, std::size_t, std::align_val_t); +void operator delete(std::type_identity<int>, void*, std::size_t, std::align_val_t); + +void foo() { + int *iptr = new int; + delete iptr; + int *iarray = new int[5]; + delete [] iarray; +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits