diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-13 03:54:03 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-13 03:54:03 +0000 |
commit | 3607ffee5ccaab26be4e99f9beabb4a6c84f2700 (patch) | |
tree | 7ebec671a00bf2a92cee0b1b80f1ec6302ef416b /clang/lib/Sema/SemaDeclCXX.cpp | |
parent | 779579b332f55e2a5852c65b4085e4705af9f42c (diff) | |
download | bcm5719-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.cpp | 116 |
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: |