diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-13 23:35:21 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2019-05-13 23:35:21 +0000 |
commit | 921f132a0f609154fa3a2c419b0119f7bf32ba96 (patch) | |
tree | e4cd3ab26a41cb96125814ef4123d5cfa31abcfd /clang/lib/Sema/SemaDeclCXX.cpp | |
parent | 91792f1b93e91ee011c6bde87d263f0e8f859790 (diff) | |
download | bcm5719-llvm-921f132a0f609154fa3a2c419b0119f7bf32ba96.tar.gz bcm5719-llvm-921f132a0f609154fa3a2c419b0119f7bf32ba96.zip |
[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
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 38 |
1 files changed, 23 insertions, 15 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index afd50f1438e..1da2ca8ca5f 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1596,6 +1596,9 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { // The definition of a constexpr constructor shall satisfy the following // constraints: // - the class shall not have any virtual base classes; + // + // FIXME: This only applies to constructors, not arbitrary member + // functions. const CXXRecordDecl *RD = MD->getParent(); if (RD->getNumVBases()) { Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base) @@ -1612,21 +1615,25 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following // constraints: - // - it shall not be virtual; + // - it shall not be virtual; (removed in C++20) const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD); if (Method && Method->isVirtual()) { - Method = Method->getCanonicalDecl(); - Diag(Method->getLocation(), diag::err_constexpr_virtual); - - // If it's not obvious why this function is virtual, find an overridden - // function which uses the 'virtual' keyword. - const CXXMethodDecl *WrittenVirtual = Method; - while (!WrittenVirtual->isVirtualAsWritten()) - WrittenVirtual = *WrittenVirtual->begin_overridden_methods(); - if (WrittenVirtual != Method) - Diag(WrittenVirtual->getLocation(), - diag::note_overridden_virtual_function); - return false; + if (getLangOpts().CPlusPlus2a) { + Diag(Method->getLocation(), diag::warn_cxx17_compat_constexpr_virtual); + } else { + Method = Method->getCanonicalDecl(); + Diag(Method->getLocation(), diag::err_constexpr_virtual); + + // If it's not obvious why this function is virtual, find an overridden + // function which uses the 'virtual' keyword. + const CXXMethodDecl *WrittenVirtual = Method; + while (!WrittenVirtual->isVirtualAsWritten()) + WrittenVirtual = *WrittenVirtual->begin_overridden_methods(); + if (WrittenVirtual != Method) + Diag(WrittenVirtual->getLocation(), + diag::note_overridden_virtual_function); + return false; + } } // - its return type shall be a literal type; @@ -15197,7 +15204,8 @@ void Sema::MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc, } void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, - const CXXRecordDecl *RD) { + const CXXRecordDecl *RD, + bool ConstexprOnly) { // Mark all functions which will appear in RD's vtable as used. CXXFinalOverriderMap FinalOverriders; RD->getFinalOverriders(FinalOverriders); @@ -15212,7 +15220,7 @@ void Sema::MarkVirtualMembersReferenced(SourceLocation Loc, // C++ [basic.def.odr]p2: // [...] A virtual member function is used if it is not pure. [...] - if (!Overrider->isPure()) + if (!Overrider->isPure() && (!ConstexprOnly || Overrider->isConstexpr())) MarkFunctionReferenced(Loc, Overrider); } } |