@@ -7042,11 +7042,38 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
7042
7042
}
7043
7043
}
7044
7044
7045
+ bool EffectivelyConstexprDestructor = true;
7046
+ // Avoid triggering vtable instantiation due to a dtor that is not
7047
+ // "effectively constexpr" for better compatibility.
7048
+ // See https://github.com/llvm/llvm-project/issues/102293 for more info.
7049
+ if (isa<CXXDestructorDecl>(M)) {
7050
+ auto Check = [](QualType T, auto &&Check) -> bool {
7051
+ const CXXRecordDecl *RD =
7052
+ T->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
7053
+ if (!RD || !RD->isCompleteDefinition())
7054
+ return true;
7055
+
7056
+ if (!RD->hasConstexprDestructor())
7057
+ return false;
7058
+
7059
+ for (const CXXBaseSpecifier &B : RD->bases())
7060
+ if (!Check(B.getType(), Check))
7061
+ return false;
7062
+ for (const FieldDecl *FD : RD->fields())
7063
+ if (!Check(FD->getType(), Check))
7064
+ return false;
7065
+ return true;
7066
+ };
7067
+ EffectivelyConstexprDestructor =
7068
+ Check(QualType(Record->getTypeForDecl(), 0), Check);
7069
+ }
7070
+
7045
7071
// Define defaulted constexpr virtual functions that override a base class
7046
7072
// function right away.
7047
7073
// FIXME: We can defer doing this until the vtable is marked as used.
7048
7074
if (CSM != CXXSpecialMemberKind::Invalid && !M->isDeleted() &&
7049
- M->isDefaulted() && M->isConstexpr() && M->size_overridden_methods())
7075
+ M->isDefaulted() && M->isConstexpr() && M->size_overridden_methods() &&
7076
+ EffectivelyConstexprDestructor)
7050
7077
DefineDefaultedFunction(*this, M, M->getLocation());
7051
7078
7052
7079
if (!Incomplete)
0 commit comments