[c++20] P1064R0: Allow virtual function calls in constant expression
evaluation.
This reinstates r360559, reverted in r360580, with a fix to avoid
crashing if evaluation-for-overflow mode encounters a virtual call on an
object of a class with a virtual base class, and to generally not try to
resolve virtual function calls to objects whose (notional) vptrs are not
readable. (The standard rules are unclear here, but this seems like a
reasonable approach.)
llvm-svn: 360635
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index edc281c..55d1d94 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2082,6 +2082,7 @@
LateInstantiatedAttrVec LateAttrs;
Instantiator.enableLateAttributeInstantiation(&LateAttrs);
+ bool MightHaveConstexprVirtualFunctions = false;
for (auto *Member : Pattern->decls()) {
// Don't instantiate members not belonging in this semantic context.
// e.g. for:
@@ -2128,6 +2129,10 @@
Instantiation->setInvalidDecl();
break;
}
+ } else if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewMember)) {
+ if (MD->isConstexpr() && !MD->getFriendObjectKind() &&
+ (MD->isVirtualAsWritten() || Instantiation->getNumBases()))
+ MightHaveConstexprVirtualFunctions = true;
}
if (NewMember->isInvalidDecl())
@@ -2220,9 +2225,14 @@
Consumer.HandleTagDeclDefinition(Instantiation);
// Always emit the vtable for an explicit instantiation definition
- // of a polymorphic class template specialization.
+ // of a polymorphic class template specialization. Otherwise, eagerly
+ // instantiate only constexpr virtual functions in preparation for their use
+ // in constant evaluation.
if (TSK == TSK_ExplicitInstantiationDefinition)
MarkVTableUsed(PointOfInstantiation, Instantiation, true);
+ else if (MightHaveConstexprVirtualFunctions)
+ MarkVirtualMembersReferenced(PointOfInstantiation, Instantiation,
+ /*ConstexprOnly*/ true);
}
return Instantiation->isInvalidDecl();