summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-02-13 03:54:03 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-02-13 03:54:03 +0000
commit3607ffee5ccaab26be4e99f9beabb4a6c84f2700 (patch)
tree7ebec671a00bf2a92cee0b1b80f1ec6302ef416b /clang/lib/Sema/SemaDeclCXX.cpp
parent779579b332f55e2a5852c65b4085e4705af9f42c (diff)
downloadbcm5719-llvm-3607ffee5ccaab26be4e99f9beabb4a6c84f2700.tar.gz
bcm5719-llvm-3607ffee5ccaab26be4e99f9beabb4a6c84f2700.zip
Update constexpr implementation to match CWG's chosen approach for core issues
1358, 1360, 1452 and 1453. - Instantiations of constexpr functions are always constexpr. This removes the need for separate declaration/definition checking, which is now gone. - This makes it possible for a constexpr function to be virtual, if they are only dependently virtual. Virtual calls to such functions are not constant expressions. - Likewise, it's now possible for a literal type to have virtual base classes. A constexpr constructor for such a type cannot actually produce a constant expression, though, so add a special-case diagnostic for a constructor call to such a type rather than trying to evaluate it. - Classes with trivial default constructors (for which value initialization can produce a fully-initialized value) are considered literal types. - Classes with volatile members are not literal types. - constexpr constructors can be members of non-literal types. We do not yet use static initialization for global objects constructed in this way. llvm-svn: 150359
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp116
1 files changed, 37 insertions, 79 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index b8ea85bea96..66f045ea8e2 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -632,9 +632,9 @@ void Sema::CheckCXXDefaultArguments(FunctionDecl *FD) {
// CheckConstexprParameterTypes - Check whether a function's parameter types
// are all literal types. If so, return true. If not, produce a suitable
-// diagnostic depending on @p CCK and return false.
-static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD,
- Sema::CheckConstexprKind CCK) {
+// diagnostic and return false.
+static bool CheckConstexprParameterTypes(Sema &SemaRef,
+ const FunctionDecl *FD) {
unsigned ArgIndex = 0;
const FunctionProtoType *FT = FD->getType()->getAs<FunctionProtoType>();
for (FunctionProtoType::arg_type_iterator i = FT->arg_type_begin(),
@@ -642,63 +642,37 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, const FunctionDecl *FD,
const ParmVarDecl *PD = FD->getParamDecl(ArgIndex);
SourceLocation ParamLoc = PD->getLocation();
if (!(*i)->isDependentType() &&
- SemaRef.RequireLiteralType(ParamLoc, *i, CCK == Sema::CCK_Declaration ?
+ SemaRef.RequireLiteralType(ParamLoc, *i,
SemaRef.PDiag(diag::err_constexpr_non_literal_param)
<< ArgIndex+1 << PD->getSourceRange()
- << isa<CXXConstructorDecl>(FD) :
- SemaRef.PDiag(),
- /*AllowIncompleteType*/ true)) {
- if (CCK == Sema::CCK_NoteNonConstexprInstantiation)
- SemaRef.Diag(ParamLoc, diag::note_constexpr_tmpl_non_literal_param)
- << ArgIndex+1 << PD->getSourceRange()
- << isa<CXXConstructorDecl>(FD) << *i;
+ << isa<CXXConstructorDecl>(FD)))
return false;
- }
}
return true;
}
// CheckConstexprFunctionDecl - Check whether a function declaration satisfies
-// the requirements of a constexpr function declaration or a constexpr
-// constructor declaration. Return true if it does, false if not.
-//
-// This implements C++11 [dcl.constexpr]p3,4, as amended by N3308.
+// the requirements of a constexpr function definition or a constexpr
+// constructor definition. If so, return true. If not, produce appropriate
+// diagnostics and return false.
//
-// \param CCK Specifies whether to produce diagnostics if the function does not
-// satisfy the requirements.
-bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD,
- CheckConstexprKind CCK) {
- assert((CCK != CCK_NoteNonConstexprInstantiation ||
- (NewFD->getTemplateInstantiationPattern() &&
- NewFD->getTemplateInstantiationPattern()->isConstexpr())) &&
- "only constexpr templates can be instantiated non-constexpr");
-
+// This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360.
+bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) {
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:
+ // C++11 [dcl.constexpr]p4:
+ // The definition of a constexpr constructor shall satisfy the following
+ // constraints:
// - the class shall not have any virtual base classes;
- //
- // 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
- // constructor. We also reject cases where the body is = delete, as
- // required by N3308.
- if (CCK != CCK_Instantiation) {
- Diag(NewFD->getLocation(),
- CCK == CCK_Declaration ? diag::err_constexpr_virtual_base
- : diag::note_constexpr_tmpl_virtual_base)
- << 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(),
- diag::note_constexpr_virtual_base_here) << I->getSourceRange();
- }
+ Diag(NewFD->getLocation(), diag::err_constexpr_virtual_base)
+ << 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(),
+ diag::note_constexpr_virtual_base_here) << I->getSourceRange();
return false;
}
}
@@ -710,39 +684,29 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD,
// - it shall not be virtual;
const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(NewFD);
if (Method && Method->isVirtual()) {
- if (CCK != CCK_Instantiation) {
- Diag(NewFD->getLocation(),
- CCK == CCK_Declaration ? diag::err_constexpr_virtual
- : diag::note_constexpr_tmpl_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);
- }
+ Diag(NewFD->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;
QualType RT = NewFD->getResultType();
if (!RT->isDependentType() &&
- RequireLiteralType(NewFD->getLocation(), RT, CCK == CCK_Declaration ?
- PDiag(diag::err_constexpr_non_literal_return) :
- PDiag(),
- /*AllowIncompleteType*/ true)) {
- if (CCK == CCK_NoteNonConstexprInstantiation)
- Diag(NewFD->getLocation(),
- diag::note_constexpr_tmpl_non_literal_return) << RT;
+ RequireLiteralType(NewFD->getLocation(), RT,
+ PDiag(diag::err_constexpr_non_literal_return)))
return false;
- }
}
// - each of its parameter types shall be a literal type;
- if (!CheckConstexprParameterTypes(*this, NewFD, CCK))
+ if (!CheckConstexprParameterTypes(*this, NewFD))
return false;
return true;
@@ -854,8 +818,7 @@ static void CheckConstexprCtorInitializer(Sema &SemaRef,
/// the permitted types of statement. C++11 [dcl.constexpr]p3,p4.
///
/// \return true if the body is OK, false if we have diagnosed a problem.
-bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body,
- bool IsInstantiation) {
+bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) {
if (isa<CXXTryStmt>(Body)) {
// C++11 [dcl.constexpr]p3:
// The definition of a constexpr function shall satisfy the following
@@ -1005,7 +968,7 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body,
// - every constructor involved in initializing non-static data members and
// base class sub-objects shall be a constexpr constructor.
llvm::SmallVector<PartialDiagnosticAt, 8> Diags;
- if (!IsInstantiation && !Expr::isPotentialConstantExpr(Dcl, Diags)) {
+ if (!Expr::isPotentialConstantExpr(Dcl, Diags)) {
Diag(Dcl->getLocation(), diag::err_constexpr_function_never_constant_expr)
<< isa<CXXConstructorDecl>(Dcl);
for (size_t I = 0, N = Diags.size(); I != N; ++I)
@@ -3755,9 +3718,6 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
// const. [...] The class of which that function is a member shall be
// a literal type.
//
- // It's fine to diagnose constructors here too: such constructors cannot
- // produce a constant expression, so are ill-formed (no diagnostic required).
- //
// If the class has virtual bases, any constexpr members will already have
// been diagnosed by the checks performed on the member declaration, so
// suppress this (less useful) diagnostic.
@@ -3766,16 +3726,14 @@ void Sema::CheckCompletedCXXClass(CXXRecordDecl *Record) {
for (CXXRecordDecl::method_iterator M = Record->method_begin(),
MEnd = Record->method_end();
M != MEnd; ++M) {
- if (M->isConstexpr() && M->isInstance()) {
+ if (M->isConstexpr() && M->isInstance() && !isa<CXXConstructorDecl>(*M)) {
switch (Record->getTemplateSpecializationKind()) {
case TSK_ImplicitInstantiation:
case TSK_ExplicitInstantiationDeclaration:
case TSK_ExplicitInstantiationDefinition:
// If a template instantiates to a non-literal type, but its members
// instantiate to constexpr functions, the template is technically
- // ill-formed, but we allow it for sanity. Such members are treated as
- // non-constexpr.
- (*M)->setConstexpr(false);
+ // ill-formed, but we allow it for sanity.
continue;
case TSK_Undeclared:
OpenPOWER on IntegriCloud