Author: Mariya Podchishchaeva Date: 2025-04-10T15:02:21+02:00 New Revision: 2b3aa56fd742775c5b05c3053778832aa76c0feb
URL: https://github.com/llvm/llvm-project/commit/2b3aa56fd742775c5b05c3053778832aa76c0feb DIFF: https://github.com/llvm/llvm-project/commit/2b3aa56fd742775c5b05c3053778832aa76c0feb.diff LOG: [MS][clang] Error about ambiguous operator delete[] only when required (#135041) And issue was reported in https://github.com/llvm/llvm-project/pull/133950#issuecomment-2787510484 . Since we don't always emit vector deleting dtors, only error out about ambiguous operator delete[] when it will be required for vector deleting dtor emission. Added: Modified: clang/lib/Sema/SemaDeclCXX.cpp clang/lib/Sema/SemaExprCXX.cpp clang/test/SemaCXX/gh134265.cpp Removed: ################################################################################ diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index b86f7118e0b34..721f61ca409ab 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -11045,15 +11045,23 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) { DiagnoseUseOfDecl(OperatorDelete, Loc); MarkFunctionReferenced(Loc, OperatorDelete); Destructor->setOperatorDelete(OperatorDelete, ThisArg); - // Lookup delete[] too in case we have to emit a vector deleting dtor; - DeclarationName VDeleteName = - Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete); - FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor( - Loc, RD, VDeleteName, /*Diagnose=*/false); - // delete[] in the TU will make sure the operator is referenced and its - // uses diagnosed, otherwise vector deleting dtor won't be called anyway, - // so just record it in the destructor. - Destructor->setOperatorArrayDelete(ArrOperatorDelete); + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + // Lookup delete[] too in case we have to emit a vector deleting dtor; + DeclarationName VDeleteName = + Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete); + // Diagnose if there is no available operator delete[] found and the + // destructor is exported. Vector deleting dtor body emission requires + // operator delete[] to be present. Whenever the destructor is exported, + // we just always emit vector deleting dtor body, because we don't know + // if new[] will be used with the type outside of the library. Otherwise + // when the dtor is not exported then new[]/delete[] in the TU will make + // sure the operator is referenced and its uses diagnosed. + bool Diagnose = + Destructor->hasAttr<DLLExportAttr>() && Destructor->isDefined(); + FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor( + Loc, RD, VDeleteName, Diagnose); + Destructor->setOperatorArrayDelete(ArrOperatorDelete); + } } } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 42bc4db20e818..247cd02b23522 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -2789,8 +2789,19 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, return true; } + // new[] will force emission of vector deleting dtor which needs delete[]. + bool MaybeVectorDeletingDtor = false; + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + if (AllocElemType->isRecordType() && IsArray) { + auto *RD = + cast<CXXRecordDecl>(AllocElemType->castAs<RecordType>()->getDecl()); + CXXDestructorDecl *DD = RD->getDestructor(); + MaybeVectorDeletingDtor = DD && DD->isVirtual() && !DD->isDeleted(); + } + } + // We don't need an operator delete if we're running under -fno-exceptions. - if (!getLangOpts().Exceptions) { + if (!getLangOpts().Exceptions && !MaybeVectorDeletingDtor) { OperatorDelete = nullptr; return false; } @@ -3290,8 +3301,11 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, // Try to find operator delete/operator delete[] in class scope. LookupQualifiedName(Found, RD); - if (Found.isAmbiguous()) + if (Found.isAmbiguous()) { + if (!Diagnose) + Found.suppressDiagnostics(); return true; + } Found.suppressDiagnostics(); diff --git a/clang/test/SemaCXX/gh134265.cpp b/clang/test/SemaCXX/gh134265.cpp index c7bdeb2add0cc..baef10bec8bff 100644 --- a/clang/test/SemaCXX/gh134265.cpp +++ b/clang/test/SemaCXX/gh134265.cpp @@ -1,4 +1,6 @@ -// RUN: %clang_cc1 %s -verify -fsyntax-only +// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -triple=x86_64-unknown-linux-gnu +// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -triple=x86_64-unknown-linux-gnu -std=c++20 +// RUN: %clang_cc1 %s -verify=expected,ms -fms-extensions -fms-compatibility -triple=x86_64-pc-windows-msvc -DMS struct Foo { virtual ~Foo() {} // expected-error {{attempt to use a deleted function}} @@ -13,10 +15,46 @@ struct Bar { struct Baz { virtual ~Baz() {} - static void operator delete[](void* ptr) = delete; // expected-note {{explicitly marked deleted here}} + static void operator delete[](void* ptr) = delete; // expected-note {{explicitly marked deleted here}}\ + ms-note{{explicitly marked deleted here}}} +}; + +struct BarBaz { + ~BarBaz() {} + static void operator delete[](void* ptr) = delete; }; void foobar() { - Baz *B = new Baz[10](); + Baz *B = new Baz[10](); // ms-error {{attempt to use a deleted function}} delete [] B; // expected-error {{attempt to use a deleted function}} + BarBaz *BB = new BarBaz[10](); +} + +struct BaseDelete1 { + void operator delete[](void *); //ms-note 3{{member found by ambiguous name lookup}} +}; +struct BaseDelete2 { + void operator delete[](void *); //ms-note 3{{member found by ambiguous name lookup}} +}; +struct BaseDestructor { + BaseDestructor() {} + virtual ~BaseDestructor() = default; +}; +struct Final : BaseDelete1, BaseDelete2, BaseDestructor { + Final() {} +}; +struct FinalExplicit : BaseDelete1, BaseDelete2, BaseDestructor { + FinalExplicit() {} + inline ~FinalExplicit() {} +}; + +#ifdef MS +struct Final1 : BaseDelete1, BaseDelete2, BaseDestructor { + __declspec(dllexport) ~Final1() {} // ms-error {{member 'operator delete[]' found in multiple base classes of diff erent types}} +}; +#endif // MS + +void foo() { + Final* a = new Final[10](); // ms-error {{member 'operator delete[]' found in multiple base classes of diff erent types}} + FinalExplicit* b = new FinalExplicit[10](); // ms-error {{member 'operator delete[]' found in multiple base classes of diff erent types}} } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits