diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 22 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 116 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 46 |
4 files changed, 66 insertions, 133 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 52789c781c..3c73f689e7 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3991,8 +3991,15 @@ Sema::ActOnVariableDeclarator(Scope *S, Declarator &D, DeclContext *DC, TemplateParamLists.release()); } - if (D.getDeclSpec().isConstexprSpecified()) + if (D.getDeclSpec().isConstexprSpecified()) { NewVD->setConstexpr(true); + SourceLocation ConstexprLoc = D.getDeclSpec().getConstexprSpecLoc(); + if (!NewVD->isInvalidDecl() && !R->isDependentType() && + RequireLiteralType(NewVD->getLocation(), R, + PDiag(diag::err_constexpr_var_non_literal) + << SourceRange(ConstexprLoc))) + NewVD->setInvalidDecl(); + } } // Set the lexical context. If the declarator has a C++ scope specifier, the @@ -5347,10 +5354,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Previous.getResultKind() != LookupResult::FoundOverloaded) && "previous declaration set still overloaded"); - if (NewFD->isConstexpr() && !NewFD->isInvalidDecl() && - !CheckConstexprFunctionDecl(NewFD, CCK_Declaration)) - NewFD->setInvalidDecl(); - NamedDecl *PrincipalDecl = (FunctionTemplate ? cast<NamedDecl>(FunctionTemplate) : NewFD); @@ -6223,8 +6226,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, if (DclT->isDependentType()) { // Allow any 'static constexpr' members, whether or not they are of literal - // type. We separately check that the initializer is a constant expression, - // which implicitly requires the member to be of literal type. + // type. We separately check that every constexpr variable is of literal + // type. } else if (VDecl->isConstexpr()) { // Require constness. @@ -7350,8 +7353,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, ActivePolicy = &WP; } - if (FD && FD->isConstexpr() && !FD->isInvalidDecl() && - !CheckConstexprFunctionBody(FD, Body, IsInstantiation)) + if (!IsInstantiation && FD && FD->isConstexpr() && !FD->isInvalidDecl() && + (!CheckConstexprFunctionDecl(FD) || + !CheckConstexprFunctionBody(FD, Body))) FD->setInvalidDecl(); assert(ExprCleanupObjects.empty() && "Leftover temporaries in function"); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b8ea85bea9..66f045ea8e 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/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: diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 7449c62fee..fb771aa30b 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1034,7 +1034,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, D->getLocation(), D->getDeclName(), T, TInfo, D->getStorageClass(), D->getStorageClassAsWritten(), D->isInlineSpecified(), D->hasWrittenPrototype(), - /*isConstexpr*/ false); + D->isConstexpr()); if (QualifierLoc) Function->setQualifierInfo(QualifierLoc); @@ -1379,7 +1379,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, StartLoc, NameInfo, T, TInfo, Constructor->isExplicit(), Constructor->isInlineSpecified(), - false, /*isConstexpr*/ false); + false, Constructor->isConstexpr()); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, @@ -1390,7 +1390,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, StartLoc, NameInfo, T, TInfo, Conversion->isInlineSpecified(), Conversion->isExplicit(), - /*isConstexpr*/ false, + Conversion->isConstexpr(), Conversion->getLocEnd()); } else { Method = CXXMethodDecl::Create(SemaRef.Context, Record, @@ -1398,7 +1398,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, D->isStatic(), D->getStorageClassAsWritten(), D->isInlineSpecified(), - /*isConstexpr*/ false, D->getLocEnd()); + D->isConstexpr(), D->getLocEnd()); } if (QualifierLoc) @@ -2305,13 +2305,6 @@ TemplateDeclInstantiator::InitFunctionInstantiation(FunctionDecl *New, EPI)); } - // C++0x [dcl.constexpr]p6: If the instantiated template specialization of - // a constexpr function template satisfies the requirements for a constexpr - // function, then it is a constexpr function. - if (Tmpl->isConstexpr() && - SemaRef.CheckConstexprFunctionDecl(New, Sema::CCK_Instantiation)) - New->setConstexpr(true); - const FunctionDecl* Definition = Tmpl; // Get the definition. Leaves the variable unchanged if undefined. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 6cc4426e5e..a4b3d86d10 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -4243,19 +4243,14 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, /// @param PD The partial diagnostic that will be printed out if T is not a /// literal type. /// -/// @param AllowIncompleteType If true, an incomplete type will be considered -/// acceptable. -/// /// @returns @c true if @p T is not a literal type and a diagnostic was emitted, /// @c false otherwise. bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD, - bool AllowIncompleteType) { + const PartialDiagnostic &PD) { assert(!T->isDependentType() && "type should not be dependent"); - bool Incomplete = RequireCompleteType(Loc, T, 0); - if (T->isLiteralType() || - (AllowIncompleteType && Incomplete && !T->isVoidType())) + RequireCompleteType(Loc, T, 0); + if (T->isLiteralType()) return false; if (PD.getDiagID() == 0) @@ -4273,8 +4268,9 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); // If the class has virtual base classes, then it's not an aggregate, and - // cannot have any constexpr constructors, so is non-literal. This is better - // to diagnose than the resulting absence of constexpr constructors. + // cannot have any constexpr constructors or a trivial default constructor, + // so is non-literal. This is better to diagnose than the resulting absence + // of constexpr constructors. if (RD->getNumVBases()) { Diag(RD->getLocation(), diag::note_non_literal_virtual_base) << RD->isStruct() << RD->getNumVBases(); @@ -4282,29 +4278,9 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, E = RD->vbases_end(); I != E; ++I) Diag(I->getSourceRange().getBegin(), diag::note_constexpr_virtual_base_here) << I->getSourceRange(); - } else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor()) { + } else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() && + !RD->hasTrivialDefaultConstructor()) { Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD; - - switch (RD->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ExplicitSpecialization: - break; - - case TSK_ImplicitInstantiation: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - // If the base template had constexpr constructors which were - // instantiated as non-constexpr constructors, explain why. - for (CXXRecordDecl::ctor_iterator I = RD->ctor_begin(), - E = RD->ctor_end(); I != E; ++I) { - if ((*I)->isCopyConstructor() || (*I)->isMoveConstructor()) - continue; - - FunctionDecl *Base = (*I)->getInstantiatedFromMemberFunction(); - if (Base && Base->isConstexpr()) - CheckConstexprFunctionDecl(*I, CCK_NoteNonConstexprInstantiation); - } - } } else if (RD->hasNonLiteralTypeFieldsOrBases()) { for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { @@ -4317,9 +4293,11 @@ bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, } for (CXXRecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end(); I != E; ++I) { - if (!(*I)->getType()->isLiteralType()) { + if (!(*I)->getType()->isLiteralType() || + (*I)->getType().isVolatileQualified()) { Diag((*I)->getLocation(), diag::note_non_literal_field) - << RD << (*I) << (*I)->getType(); + << RD << (*I) << (*I)->getType() + << (*I)->getType().isVolatileQualified(); return true; } } |