[clang] d469794 - [clang] Avoid triggering vtable instantiation for C++23 constexpr dtor (#102605)

via cfe-commits cfe-commits at lists.llvm.org
Mon Aug 12 00:08:50 PDT 2024


Author: Mariya Podchishchaeva
Date: 2024-08-12T09:08:46+02:00
New Revision: d469794d0cdfd2fea50a6ce0c0e33abb242d744c

URL: https://github.com/llvm/llvm-project/commit/d469794d0cdfd2fea50a6ce0c0e33abb242d744c
DIFF: https://github.com/llvm/llvm-project/commit/d469794d0cdfd2fea50a6ce0c0e33abb242d744c.diff

LOG: [clang] Avoid triggering vtable instantiation for C++23 constexpr dtor (#102605)

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

Added: 
    clang/test/SemaCXX/gh102293.cpp

Modified: 
    clang/lib/Sema/SemaDeclCXX.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index b07e555afcaccf..c87edf41f35cee 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7042,11 +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.
+    // 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 =
+            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())
+        M->isDefaulted() && M->isConstexpr() && M->size_overridden_methods() &&
+        EffectivelyConstexprDestructor)
       DefineDefaultedFunction(*this, M, M->getLocation());
 
     if (!Incomplete)

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;
+};
+


        


More information about the cfe-commits mailing list