aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-01-13 04:54:00 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-01-13 04:54:00 +0000
commit3534050c491454e4a5c7bcd0f8e6054cd89012cd (patch)
treedc3cb11ede4083e6e182a6e6e9454a87fdfe7e04
parent89e6e85f1a6c4972ece0b68950673735daec970a (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.td12
-rw-r--r--lib/Sema/SemaDeclCXX.cpp36
-rw-r--r--test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p3.cpp4
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