diff options
21 files changed, 211 insertions, 278 deletions
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 6c3b418ee8..46136c3bab 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -469,7 +469,8 @@ class CXXRecordDecl : public RecordDecl { bool HasTrivialDestructor : 1; /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least - /// one non-static data member or base class of non literal type. + /// one non-static data member or base class of non-literal or volatile + /// type. bool HasNonLiteralTypeFieldsOrBases : 1; /// ComputedVisibleConversions - True when visible conversion functions are @@ -1095,8 +1096,8 @@ public: // (C++ [class.dtor]p3) bool hasTrivialDestructor() const { return data().HasTrivialDestructor; } - // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal type - // non-static data member or base class. + // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal or + // volatile type non-static data member or base class. bool hasNonLiteralTypeFieldsOrBases() const { return data().HasNonLiteralTypeFieldsOrBases; } @@ -1116,20 +1117,23 @@ public: // isLiteral - Whether this class is a literal type. // - // C++0x [basic.types]p10 + // C++11 [basic.types]p10 // A class type that has all the following properties: - // -- a trivial destructor + // -- it has a trivial destructor // -- every constructor call and full-expression in the // brace-or-equal-intializers for non-static data members (if any) is // a constant expression. // -- it is an aggregate type or has at least one constexpr constructor or // constructor template that is not a copy or move constructor, and - // -- all non-static data members and base classes of literal types + // -- all of its non-static data members and base classes are of literal + // types // - // We resolve DR1361 by ignoring the second bullet. + // We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by + // treating types with trivial default constructors as literal types. bool isLiteral() const { return hasTrivialDestructor() && - (isAggregate() || hasConstexprNonCopyMoveConstructor()) && + (isAggregate() || hasConstexprNonCopyMoveConstructor() || + hasTrivialDefaultConstructor()) && !hasNonLiteralTypeFieldsOrBases(); } diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index fb6e73090e..0f1a05d16f 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -28,6 +28,11 @@ def note_constexpr_lshift_discards : Note<"signed left shift discards bits">; def note_constexpr_invalid_function : Note< "%select{non-constexpr|undefined}0 %select{function|constructor}1 %2 cannot " "be used in a constant expression">; +def note_constexpr_virtual_call : Note< + "cannot evaluate virtual function call in a constant expression">; +def note_constexpr_virtual_base : Note< + "cannot construct object of type %0 with virtual base class " + "in a constant expression">; def note_constexpr_nonliteral : Note< "non-literal type %0 cannot be used in a constant expression">; def note_constexpr_non_global : Note< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index dbc8aa2eca..3e6c190343 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -1361,6 +1361,8 @@ def err_invalid_constexpr_var_decl : Error< "constexpr variable declaration must be a definition">; def err_constexpr_static_mem_var_requires_init : Error< "declaration of constexpr static data member %0 requires an initializer">; +def err_constexpr_var_non_literal : Error< + "constexpr variable cannot have non-literal type %0">; def err_constexpr_var_requires_const_init : Error< "constexpr variable %0 must be initialized by a constant expression">; def err_constexpr_redecl_mismatch : Error< @@ -1369,29 +1371,17 @@ def err_constexpr_redecl_mismatch : Error< def note_constexpr_redecl_mismatch : Note< "previous declaration was %select{not |}0marked constexpr">; 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 %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">; def err_constexpr_non_literal_return : Error< "constexpr function's return type %0 is not a literal type">; -def note_constexpr_tmpl_non_literal_return : Note< - "function template instantiation is not constexpr because return type %0 is " - "not a literal type">; def err_constexpr_non_literal_param : Error< "constexpr %select{function|constructor}1's %ordinal0 parameter type %2 is " "not a literal type">; -def note_constexpr_tmpl_non_literal_param : Note< - "%select{function|constructor}1 template instantiation is not constexpr " - "because %ordinal0 parameter type %2 is not a literal type">; def err_constexpr_body_invalid_stmt : Error< "statement not allowed in constexpr %select{function|constructor}0">; def err_constexpr_type_definition : Error< @@ -1426,7 +1416,8 @@ def note_non_literal_no_constexpr_ctors : Note< def note_non_literal_base_class : Note< "%0 is not literal because it has base class %1 of non-literal type">; def note_non_literal_field : Note< - "%0 is not literal because it has data member %1 of non-literal type %2">; + "%0 is not literal because it has data member %1 of " + "%select{non-literal|volatile}3 type %2">; def note_non_literal_user_provided_dtor : Note< "%0 is not literal because it has a user-provided destructor">; def note_non_literal_nontrivial_dtor : Note< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 3333e56e71..2e5f8750db 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -835,8 +835,7 @@ public: PartialDiagnostic> Note); bool RequireLiteralType(SourceLocation Loc, QualType T, - const PartialDiagnostic &PD, - bool AllowIncompleteType = false); + const PartialDiagnostic &PD); QualType getElaboratedType(ElaboratedTypeKeyword Keyword, const CXXScopeSpec &SS, QualType T); @@ -1004,23 +1003,8 @@ public: bool &AddToScope); bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); - /// \brief The kind of constexpr declaration checking we are performing. - /// - /// The kind affects which diagnostics (if any) are emitted if the function - /// does not satisfy the requirements of a constexpr function declaration. - enum CheckConstexprKind { - /// \brief Check a constexpr function declaration, and produce errors if it - /// does not satisfy the requirements. - CCK_Declaration, - /// \brief Check a constexpr function template instantiation. - CCK_Instantiation, - /// \brief Produce notes explaining why an instantiation was not constexpr. - CCK_NoteNonConstexprInstantiation - }; - bool CheckConstexprFunctionDecl(const FunctionDecl *FD, - CheckConstexprKind CCK); - bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body, - bool IsInstantiation); + bool CheckConstexprFunctionDecl(const FunctionDecl *FD); + bool CheckConstexprFunctionBody(const FunctionDecl *FD, Stmt *Body); void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD); // Returns true if the function declaration is a redeclaration diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index 22a9eadaad..f9d95b121a 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -799,8 +799,8 @@ NotASpecialMember:; data().IsStandardLayout = false; } - // Record if this field is the first non-literal field or base. - if (!hasNonLiteralTypeFieldsOrBases() && !T->isLiteralType()) + // Record if this field is the first non-literal or volatile field or base. + if (!T->isLiteralType() || T.isVolatileQualified()) data().HasNonLiteralTypeFieldsOrBases = true; if (Field->hasInClassInitializer()) { diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp index 998bb705f9..520e3cbbaf 100644 --- a/lib/AST/ExprConstant.cpp +++ b/lib/AST/ExprConstant.cpp @@ -2033,6 +2033,12 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, if (!Info.CheckCallLimit(CallLoc)) return false; + const CXXRecordDecl *RD = Definition->getParent(); + if (RD->getNumVBases()) { + Info.Diag(CallLoc, diag::note_constexpr_virtual_base) << RD; + return false; + } + CallStackFrame Frame(Info, CallLoc, Definition, &This, ArgValues.data()); // If it's a delegating constructor, just delegate. @@ -2044,7 +2050,6 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, // For a trivial copy or move constructor, perform an APValue copy. This is // essential for unions, where the operations performed by the constructor // cannot be represented by ctor-initializers. - const CXXRecordDecl *RD = Definition->getParent(); if (Definition->isDefaulted() && ((Definition->isCopyConstructor() && RD->hasTrivialCopyConstructor()) || (Definition->isMoveConstructor() && RD->hasTrivialMoveConstructor()))) { @@ -2083,7 +2088,7 @@ static bool HandleConstructorCall(SourceLocation CallLoc, const LValue &This, QualType BaseType((*I)->getBaseClass(), 0); #ifndef NDEBUG // Non-virtual base classes are initialized in the order in the class - // definition. We cannot have a virtual base class for a literal type. + // definition. We have already checked for virtual base classes. assert(!BaseIt->isVirtual() && "virtual base for literal type"); assert(Info.Ctx.hasSameType(BaseIt->getType(), BaseType) && "base class initializers not in expected order"); @@ -2414,6 +2419,7 @@ public: const FunctionDecl *FD = 0; LValue *This = 0, ThisVal; llvm::ArrayRef<const Expr*> Args(E->getArgs(), E->getNumArgs()); + bool HasQualifier = false; // Extract function decl and 'this' pointer from the callee. if (CalleeType->isSpecificBuiltinType(BuiltinType::BoundMember)) { @@ -2424,6 +2430,7 @@ public: return false; Member = ME->getMemberDecl(); This = &ThisVal; + HasQualifier = ME->hasQualifier(); } else if (const BinaryOperator *BE = dyn_cast<BinaryOperator>(Callee)) { // Indirect bound member calls ('.*' or '->*'). Member = HandleMemberPointerAccess(Info, BE, ThisVal, false); @@ -2472,6 +2479,12 @@ public: if (This && !This->checkSubobject(Info, E, CSK_This)) return false; + // DR1358 allows virtual constexpr functions in some cases. Don't allow + // calls to such functions in constant expressions. + if (This && !HasQualifier && + isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isVirtual()) + return Error(E, diag::note_constexpr_virtual_call); + const FunctionDecl *Definition = 0; Stmt *Body = FD->getBody(Definition); APValue Result; 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; } } diff --git a/test/CXX/basic/basic.types/p10.cpp b/test/CXX/basic/basic.types/p10.cpp index def4dc95bb..7641e09f61 100644 --- a/test/CXX/basic/basic.types/p10.cpp +++ b/test/CXX/basic/basic.types/p10.cpp @@ -5,22 +5,23 @@ struct NonLiteral { NonLiteral(); }; // A type is a literal type if it is: // - a scalar type -constexpr int f1(double); +constexpr int f1(double) { return 0; } // - a reference type struct S { S(); }; |