https://github.com/Fznamznon updated https://github.com/llvm/llvm-project/pull/102605
>From eb97afb9cade7b496ec55acdd4f02a915c4a4955 Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Fri, 9 Aug 2024 05:20:37 -0700 Subject: [PATCH 1/2] [clang] Avoid triggering vtable instantiation for C++23 constexpr dtor In C++23 anything can be constexpr, including a dtor of a class whose members and bases don't have constexpr dtors. Avoid early triggering of vtable instantiation int this case. Fixes https://github.com/llvm/llvm-project/issues/102293 --- clang/lib/Sema/SemaDeclCXX.cpp | 28 +++++++++++++++++++++++++++- clang/test/SemaCXX/gh102293.cpp | 22 ++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/gh102293.cpp diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index b07e555afcaccf..63d2131acdd650 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7042,12 +7042,38 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { } } + bool EffectivelyConstexprDestructor = true; + // Avoid triggering vtable instantiation due to a dtor that is not + // "effectively constexpr" for better compatibility. + if (isa<CXXDestructorDecl>(M)) { + auto Check = [](QualType T, auto &&Check) -> bool { + const CXXRecordDecl *RD = + T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl(); + if (!RD || !RD->isCompleteDefinition()) + return true; + + if (!RD->hasConstexprDestructor()) + return false; + + for (const CXXBaseSpecifier &B : RD->bases()) + if (!Check(B.getType(), Check)) + return false; + for (const FieldDecl *FD : RD->fields()) + if (!Check(FD->getType(), Check)) + return false; + return true; + }; + EffectivelyConstexprDestructor = + Check(QualType(Record->getTypeForDecl(), 0), Check); + } + // Define defaulted constexpr virtual functions that override a base class // function right away. // FIXME: We can defer doing this until the vtable is marked as used. if (CSM != CXXSpecialMemberKind::Invalid && !M->isDeleted() && M->isDefaulted() && M->isConstexpr() && M->size_overridden_methods()) - DefineDefaultedFunction(*this, M, M->getLocation()); + if (EffectivelyConstexprDestructor) + DefineDefaultedFunction(*this, M, M->getLocation()); if (!Incomplete) CheckCompletedMemberFunction(M); diff --git a/clang/test/SemaCXX/gh102293.cpp b/clang/test/SemaCXX/gh102293.cpp new file mode 100644 index 00000000000000..30629fc03bf6a9 --- /dev/null +++ b/clang/test/SemaCXX/gh102293.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s +// expected-no-diagnostics + +template <typename T> static void destroy() { + T t; + ++t; +} + +struct Incomplete; + +template <typename = int> struct HasD { + ~HasD() { destroy<Incomplete*>(); } +}; + +struct HasVT { + virtual ~HasVT(); +}; + +struct S : HasVT { + HasD<> v; +}; + >From 41857fe433eb141720b24e12a07e5a5fc57d87fa Mon Sep 17 00:00:00 2001 From: "Podchishchaeva, Mariya" <mariya.podchishcha...@intel.com> Date: Fri, 9 Aug 2024 07:17:51 -0700 Subject: [PATCH 2/2] Add issue link, merge ifs --- clang/lib/Sema/SemaDeclCXX.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 63d2131acdd650..c87edf41f35cee 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7045,6 +7045,7 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { bool EffectivelyConstexprDestructor = true; // Avoid triggering vtable instantiation due to a dtor that is not // "effectively constexpr" for better compatibility. + // See https://github.com/llvm/llvm-project/issues/102293 for more info. if (isa<CXXDestructorDecl>(M)) { auto Check = [](QualType T, auto &&Check) -> bool { const CXXRecordDecl *RD = @@ -7071,9 +7072,9 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) { // function right away. // FIXME: We can defer doing this until the vtable is marked as used. if (CSM != CXXSpecialMemberKind::Invalid && !M->isDeleted() && - M->isDefaulted() && M->isConstexpr() && M->size_overridden_methods()) - if (EffectivelyConstexprDestructor) - DefineDefaultedFunction(*this, M, M->getLocation()); + M->isDefaulted() && M->isConstexpr() && M->size_overridden_methods() && + EffectivelyConstexprDestructor) + DefineDefaultedFunction(*this, M, M->getLocation()); if (!Incomplete) CheckCompletedMemberFunction(M); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits