diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-01-13 04:54:00 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-01-13 04:54:00 +0000 |
commit | 3534050c491454e4a5c7bcd0f8e6054cd89012cd (patch) | |
tree | dc3cb11ede4083e6e182a6e6e9454a87fdfe7e04 | |
parent | 89e6e85f1a6c4972ece0b68950673735daec970a (diff) |
PR11754: Reject non-static constexpr member functions in classes with virtual
base classes.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148094 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 12 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 36 | ||||
-rw-r--r-- | test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp | 4 |
3 files changed, 30 insertions, 22 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index dbe19dffca..a114dd35bc 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1308,11 +1308,13 @@ def note_constexpr_redecl_mismatch : Note< def err_constexpr_virtual : Error<"virtual function cannot be constexpr">; def note_constexpr_tmpl_virtual : Note<"function template instantiation is not " "constexpr because it is virtual">; -def err_constexpr_virtual_base : Error<"constexpr constructor not allowed in " - "%select{class|struct}0 with virtual base %plural{1:class|:classes}1">; -def note_constexpr_tmpl_virtual_base : Note<"constructor template instantiation is " - "not constexpr because %select{class|struct}0 has virtual base " - "%plural{1:class|:classes}1">; +def err_constexpr_virtual_base : Error< + "constexpr %select{member function|constructor}0 not allowed in " + "%select{class|struct}1 with virtual base %plural{1:class|:classes}2">; +def note_constexpr_tmpl_virtual_base : Note< + "%select{function|constructor}0 template instantiation is " + "not constexpr because %select{class|struct}1 has virtual base " + "%plural{1:class|:classes}2">; def note_non_literal_virtual_base : Note<"%select{class|struct}0 with virtual " "base %plural{1:class|:classes}1 is not a literal type">; def note_constexpr_virtual_base_here : Note<"virtual base class declared here">; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 9bb2639877..0b89e1b2a5 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -648,7 +648,7 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD, // the requirements of a constexpr function declaration or a constexpr // constructor declaration. Return true if it does, false if not. // -// This implements C++0x [dcl.constexpr]p3,4, as amended by N3308. +// This implements C++11 [dcl.constexpr]p3,4, as amended by N3308. // // \param CCK Specifies whether to produce diagnostics if the function does not // satisfy the requirements. @@ -659,17 +659,16 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD, NewFD->getTemplateInstantiationPattern()->isConstexpr())) && "only constexpr templates can be instantiated non-constexpr"); - if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(NewFD)) { - // C++0x [dcl.constexpr]p4: - // In the definition of a constexpr constructor, each of the parameter - // types shall be a literal type. - if (!CheckConstexprParameterTypes(*this, NewFD, CCK)) - return false; - + const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(NewFD); + if (MD && MD->isInstance()) { + // C++11 [dcl.constexpr]p4: In the definition of a constexpr constructor... // In addition, either its function-body shall be = delete or = default or // it shall satisfy the following constraints: // - the class shall not have any virtual base classes; - const CXXRecordDecl *RD = CD->getParent(); + // + // We apply this to constexpr member functions too: the class cannot be a + // literal type, so the members are not permitted to be constexpr. + const CXXRecordDecl *RD = MD->getParent(); if (RD->getNumVBases()) { // Note, this is still illegal if the body is = default, since the // implicit body does not satisfy the requirements of a constexpr @@ -679,7 +678,8 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD, Diag(NewFD->getLocation(), CCK == CCK_Declaration ? diag::err_constexpr_virtual_base : diag::note_constexpr_tmpl_virtual_base) - << RD->isStruct() << RD->getNumVBases(); + << isa<CXXConstructorDecl>(NewFD) << RD->isStruct() + << RD->getNumVBases(); for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(), E = RD->vbases_end(); I != E; ++I) Diag(I->getSourceRange().getBegin(), @@ -687,8 +687,10 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD, } return false; } - } else { - // C++0x [dcl.constexpr]p3: + } + + if (!isa<CXXConstructorDecl>(NewFD)) { + // C++11 [dcl.constexpr]p3: // The definition of a constexpr function shall satisfy the following // constraints: // - it shall not be virtual; @@ -705,7 +707,7 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD, while (!WrittenVirtual->isVirtualAsWritten()) WrittenVirtual = *WrittenVirtual->begin_overridden_methods(); if (WrittenVirtual != Method) - Diag(WrittenVirtual->getLocation(), + Diag(WrittenVirtual->getLocation(), diag::note_overridden_virtual_function); } return false; @@ -723,12 +725,12 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD, diag::note_constexpr_tmpl_non_literal_return) << RT; return false; } - - // - each of its parameter types shall be a literal type; - if (!CheckConstexprParameterTypes(*this, NewFD, CCK)) - return false; } + // - each of its parameter types shall be a literal type; + if (!CheckConstexprParameterTypes(*this, NewFD, CCK)) + return false; + return true; } diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp index 1b31d21f36..aa75ac863e 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp @@ -63,6 +63,10 @@ struct U { constexpr int SelfParam(U); }; +struct V : virtual U { // expected-note {{here}} + constexpr int F(); // expected-error {{constexpr member function not allowed in struct with virtual base class}} +}; + // or a compound-statememt that contains only constexpr int AllowedStmts() { // - null statements |