diff options
author | Gauthier Harnisch <tyker1@outlook.com> | 2019-06-14 08:56:20 +0000 |
---|---|---|
committer | Gauthier Harnisch <tyker1@outlook.com> | 2019-06-14 08:56:20 +0000 |
commit | 17feca48a8331dd511992e3ef0876486e774deec (patch) | |
tree | d546e1c31de0d15580261c72cafd1d9fa7aaf424 /lib/Sema | |
parent | 4a58b8483cde0d2ea84c2ad9741c83b45ede8f55 (diff) | |
download | clang-17feca48a8331dd511992e3ef0876486e774deec.tar.gz |
[C++20] add Basic consteval specifier
Summary:
this revision adds Lexing, Parsing and Basic Semantic for the consteval specifier as specified by http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1073r3.html
with this patch, the consteval specifier is treated as constexpr but can only be applied to function declaration.
Changes:
- add the consteval keyword.
- add parsing of consteval specifier for normal declarations and lambdas expressions.
- add the whether a declaration is constexpr is now represented by and enum everywhere except for variable because they can't be consteval.
- adapt diagnostic about constexpr to print constexpr or consteval depending on the case.
- add tests for basic semantic.
Reviewers: rsmith, martong, shafik
Reviewed By: rsmith
Subscribers: eraman, efriedma, rnkovacs, cfe-commits
Tags: #clang
Differential Revision: https://reviews.llvm.org/D61790
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@363362 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/DeclSpec.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaCoroutine.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 60 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 10 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 68 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 37 | ||||
-rw-r--r-- | lib/Sema/SemaStmt.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 8 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 2 |
12 files changed, 133 insertions, 103 deletions
diff --git a/lib/Sema/DeclSpec.cpp b/lib/Sema/DeclSpec.cpp index 08c3b0ff32..21d7f6bd42 100644 --- a/lib/Sema/DeclSpec.cpp +++ b/lib/Sema/DeclSpec.cpp @@ -564,6 +564,15 @@ const char *DeclSpec::getSpecifierName(DeclSpec::TST T, llvm_unreachable("Unknown typespec!"); } +const char *DeclSpec::getSpecifierName(ConstexprSpecKind C) { + switch (C) { + case CSK_unspecified: return "unspecified"; + case CSK_constexpr: return "constexpr"; + case CSK_consteval: return "consteval"; + } + llvm_unreachable("Unknown ConstexprSpecKind"); +} + const char *DeclSpec::getSpecifierName(TQ T) { switch (T) { case DeclSpec::TQ_unspecified: return "unspecified"; @@ -1025,16 +1034,17 @@ bool DeclSpec::setModulePrivateSpec(SourceLocation Loc, const char *&PrevSpec, return false; } -bool DeclSpec::SetConstexprSpec(SourceLocation Loc, const char *&PrevSpec, +bool DeclSpec::SetConstexprSpec(ConstexprSpecKind ConstexprKind, + SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID) { - // 'constexpr constexpr' is ok, but warn as this is likely not what the user - // intended. - if (Constexpr_specified) { + if (ConstexprSpecifier != CSK_unspecified) { + if (ConstexprSpecifier == CSK_consteval || ConstexprKind == CSK_consteval) + return BadSpecifier(ConstexprKind, ConstexprSpecifier, PrevSpec, DiagID); DiagID = diag::warn_duplicate_declspec; PrevSpec = "constexpr"; return true; } - Constexpr_specified = true; + ConstexprSpecifier = ConstexprKind; ConstexprLoc = Loc; return false; } @@ -1280,9 +1290,10 @@ void DeclSpec::Finish(Sema &S, const PrintingPolicy &Policy) { else if (TypeSpecType == TST_char16 || TypeSpecType == TST_char32) S.Diag(TSTLoc, diag::warn_cxx98_compat_unicode_type) << (TypeSpecType == TST_char16 ? "char16_t" : "char32_t"); - if (Constexpr_specified) + if (getConstexprSpecifier() == CSK_constexpr) S.Diag(ConstexprLoc, diag::warn_cxx98_compat_constexpr); - + if (getConstexprSpecifier() == CSK_consteval) + S.Diag(ConstexprLoc, diag::warn_cxx20_compat_consteval); // C++ [class.friend]p6: // No storage-class-specifier shall appear in the decl-specifier-seq // of a friend declaration. diff --git a/lib/Sema/SemaCoroutine.cpp b/lib/Sema/SemaCoroutine.cpp index dc259fe03f..fc6470617c 100644 --- a/lib/Sema/SemaCoroutine.cpp +++ b/lib/Sema/SemaCoroutine.cpp @@ -210,6 +210,7 @@ static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, DiagConstexpr, DiagAutoRet, DiagVarargs, + DiagConsteval, }; bool Diagnosed = false; auto DiagInvalid = [&](InvalidFuncDiag ID) { @@ -244,7 +245,7 @@ static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, // evaluation of e [...] would evaluate one of the following expressions: // [...] an await-expression [...] a yield-expression." if (FD->isConstexpr()) - DiagInvalid(DiagConstexpr); + DiagInvalid(FD->isConsteval() ? DiagConsteval : DiagConstexpr); // [dcl.spec.auto]p15: "A function declared with a return type that uses a // placeholder type shall not be a coroutine." if (FD->getReturnType()->isUndeducedType()) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 10837f6894..ce6fd41236 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4292,14 +4292,18 @@ Sema::ParsedFreeStandingDeclSpec(Scope *S, AccessSpecifier AS, DeclSpec &DS, Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function) << getLangOpts().CPlusPlus17; - if (DS.isConstexprSpecified()) { + if (DS.hasConstexprSpecifier()) { // C++0x [dcl.constexpr]p1: constexpr can only be applied to declarations // and definitions of functions and variables. + // C++2a [dcl.constexpr]p1: The consteval specifier shall be applied only to + // the declaration of a function or function template + bool IsConsteval = DS.getConstexprSpecifier() == CSK_consteval; if (Tag) Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_tag) - << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()); + << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << IsConsteval; else - Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_no_declarators); + Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_wrong_decl_kind) + << IsConsteval; // Don't emit warnings after this error. return TagD; } @@ -5752,9 +5756,9 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, if (D.getDeclSpec().isInlineSpecified()) Diag(D.getDeclSpec().getInlineSpecLoc(), diag::err_inline_non_function) << getLangOpts().CPlusPlus17; - if (D.getDeclSpec().isConstexprSpecified()) + if (D.getDeclSpec().hasConstexprSpecifier()) Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_invalid_constexpr) - << 1; + << 1 << (D.getDeclSpec().getConstexprSpecifier() == CSK_consteval); if (D.getName().Kind != UnqualifiedIdKind::IK_Identifier) { if (D.getName().Kind == UnqualifiedIdKind::IK_DeductionGuideName) @@ -6648,13 +6652,17 @@ NamedDecl *Sema::ActOnVariableDeclarator( NewVD->setTemplateParameterListsInfo( Context, TemplateParamLists.drop_back(VDTemplateParamLists)); - if (D.getDeclSpec().isConstexprSpecified()) { + if (D.getDeclSpec().hasConstexprSpecifier()) { NewVD->setConstexpr(true); // C++1z [dcl.spec.constexpr]p1: // A static data member declared with the constexpr specifier is // implicitly an inline variable. if (NewVD->isStaticDataMember() && getLangOpts().CPlusPlus17) NewVD->setImplicitlyInline(); + if (D.getDeclSpec().getConstexprSpecifier() == CSK_consteval) + Diag(D.getDeclSpec().getConstexprSpecLoc(), + diag::err_constexpr_wrong_decl_kind) + << /*consteval*/ 1; } } @@ -7982,7 +7990,8 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, (!R->getAsAdjusted<FunctionType>() && R->isFunctionProtoType()); NewFD = FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo, - R, TInfo, SC, isInline, HasPrototype, false); + R, TInfo, SC, isInline, HasPrototype, + CSK_unspecified); if (D.isInvalidType()) NewFD->setInvalidDecl(); @@ -7990,8 +7999,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, } ExplicitSpecifier ExplicitSpecifier = D.getDeclSpec().getExplicitSpecifier(); - bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); - + ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier(); // Check that the return type is not an abstract class type. // For record types, this is done by the AbstractClassUsageDiagnoser once // the class has been completely parsed. @@ -8010,7 +8018,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, return CXXConstructorDecl::Create( SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, TInfo, ExplicitSpecifier, isInline, - /*isImplicitlyDeclared=*/false, isConstexpr); + /*isImplicitlyDeclared=*/false, ConstexprKind); } else if (Name.getNameKind() == DeclarationName::CXXDestructorName) { // This is a C++ destructor declaration. @@ -8040,7 +8048,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), D.getIdentifierLoc(), Name, R, TInfo, SC, isInline, - /*hasPrototype=*/true, isConstexpr); + /*hasPrototype=*/true, ConstexprKind); } } else if (Name.getNameKind() == DeclarationName::CXXConversionFunctionName) { @@ -8054,7 +8062,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, IsVirtualOkay = true; return CXXConversionDecl::Create( SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, - TInfo, isInline, ExplicitSpecifier, isConstexpr, SourceLocation()); + TInfo, isInline, ExplicitSpecifier, ConstexprKind, SourceLocation()); } else if (Name.getNameKind() == DeclarationName::CXXDeductionGuideName) { SemaRef.CheckDeductionGuideDeclarator(D, R, SC); @@ -8078,7 +8086,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // This is a C++ method declaration. CXXMethodDecl *Ret = CXXMethodDecl::Create( SemaRef.Context, cast<CXXRecordDecl>(DC), D.getBeginLoc(), NameInfo, R, - TInfo, SC, isInline, isConstexpr, SourceLocation()); + TInfo, SC, isInline, ConstexprKind, SourceLocation()); IsVirtualOkay = !Ret->isStatic(); return Ret; } else { @@ -8092,7 +8100,7 @@ static FunctionDecl* CreateNewFunctionDecl(Sema &SemaRef, Declarator &D, // - we're in C++ (where every function has a prototype), return FunctionDecl::Create(SemaRef.Context, DC, D.getBeginLoc(), NameInfo, R, TInfo, SC, isInline, true /*HasPrototype*/, - isConstexpr); + ConstexprKind); } } @@ -8422,7 +8430,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, bool isInline = D.getDeclSpec().isInlineSpecified(); bool isVirtual = D.getDeclSpec().isVirtualSpecified(); bool hasExplicit = D.getDeclSpec().hasExplicitSpecifier(); - bool isConstexpr = D.getDeclSpec().isConstexprSpecified(); + ConstexprSpecKind ConstexprKind = D.getDeclSpec().getConstexprSpecifier(); isFriend = D.getDeclSpec().isFriendSpecified(); if (isFriend && !isInline && D.isFunctionDefinition()) { // C++ [class.friend]p5 @@ -8621,7 +8629,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } } - if (isConstexpr) { + if (ConstexprKind != CSK_unspecified) { // C++11 [dcl.constexpr]p2: constexpr functions and constexpr constructors // are implicitly inline. NewFD->setImplicitlyInline(); @@ -8630,7 +8638,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, // be either constructors or to return a literal type. Therefore, // destructors cannot be declared constexpr. if (isa<CXXDestructorDecl>(NewFD)) - Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor); + Diag(D.getDeclSpec().getConstexprSpecLoc(), diag::err_constexpr_dtor) + << (ConstexprKind == CSK_consteval); } // If __module_private__ was specified, mark the function accordingly. @@ -9527,6 +9536,7 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, DeletedFuncs = 5, DefaultedFuncs = 6, ConstexprFuncs = 7, + ConstevalFuncs = 8, }; enum Different { CallingConv = 0, @@ -9602,7 +9612,8 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, if (NewFD->isConstexpr() && (MVType == MultiVersionKind::CPUDispatch || MVType == MultiVersionKind::CPUSpecific)) return S.Diag(NewFD->getLocation(), diag::err_multiversion_doesnt_support) - << IsCPUSpecificCPUDispatchMVType << ConstexprFuncs; + << IsCPUSpecificCPUDispatchMVType + << (NewFD->isConsteval() ? ConstevalFuncs : ConstexprFuncs); QualType NewQType = S.getASTContext().getCanonicalType(NewFD->getType()); const auto *NewType = cast<FunctionType>(NewQType); @@ -9633,7 +9644,7 @@ static bool CheckMultiVersionAdditionalRules(Sema &S, const FunctionDecl *OldFD, return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff) << ReturnType; - if (OldFD->isConstexpr() != NewFD->isConstexpr()) + if (OldFD->getConstexprKind() != NewFD->getConstexprKind()) return S.Diag(NewFD->getLocation(), diag::err_multiversion_diff) << ConstexprSpec; @@ -10383,8 +10394,9 @@ void Sema::CheckMain(FunctionDecl* FD, const DeclSpec& DS) { } if (FD->isConstexpr()) { Diag(DS.getConstexprSpecLoc(), diag::err_constexpr_main) - << FixItHint::CreateRemoval(DS.getConstexprSpecLoc()); - FD->setConstexpr(false); + << FD->isConsteval() + << FixItHint::CreateRemoval(DS.getConstexprSpecLoc()); + FD->setConstexprKind(CSK_unspecified); } if (getLangOpts().OpenCL) { @@ -12475,9 +12487,9 @@ Decl *Sema::ActOnParamDeclarator(Scope *S, Declarator &D) { if (DS.isInlineSpecified()) Diag(DS.getInlineSpecLoc(), diag::err_inline_non_function) << getLangOpts().CPlusPlus17; - if (DS.isConstexprSpecified()) + if (DS.hasConstexprSpecifier()) Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr) - << 0; + << 0 << (D.getDeclSpec().getConstexprSpecifier() == CSK_consteval); DiagnoseFunctionSpecifiers(DS); @@ -13128,7 +13140,7 @@ void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { bool Sema::canDelayFunctionBody(const Declarator &D) { // We can't delay parsing the body of a constexpr function template (yet). - if (D.getDeclSpec().isConstexprSpecified()) + if (D.getDeclSpec().hasConstexprSpecifier()) return false; // We can't delay parsing the body of a function template with a deduced diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 932cb18a93..c32653c5d2 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -7460,12 +7460,10 @@ NamedDecl * Sema::DeclClonePragmaWeak(NamedDecl *ND, IdentifierInfo *II, // FIXME: Mangling? // FIXME: Is the qualifier info correct? // FIXME: Is the DeclContext correct? - NewFD = FunctionDecl::Create(FD->getASTContext(), FD->getDeclContext(), - Loc, Loc, DeclarationName(II), - FD->getType(), FD->getTypeSourceInfo(), - SC_None, false/*isInlineSpecified*/, - FD->hasPrototype(), - false/*isConstexprSpecified*/); + NewFD = FunctionDecl::Create( + FD->getASTContext(), FD->getDeclContext(), Loc, Loc, + DeclarationName(II), FD->getType(), FD->getTypeSourceInfo(), SC_None, + false /*isInlineSpecified*/, FD->hasPrototype(), CSK_unspecified); NewD = NewFD; if (FD->getQualifier()) diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 354316a3cc..6686b855c3 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -638,9 +638,9 @@ bool Sema::MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old, // C++11 [dcl.constexpr]p1: If any declaration of a function or function // template has a constexpr specifier then all its declarations shall // contain the constexpr specifier. - if (New->isConstexpr() != Old->isConstexpr()) { + if (New->getConstexprKind() != Old->getConstexprKind()) { Diag(New->getLocation(), diag::err_constexpr_redecl_mismatch) - << New << New->isConstexpr(); + << New << New->getConstexprKind() << Old->getConstexprKind(); Diag(Old->getLocation(), diag::note_previous_declaration); Invalid = true; } else if (!Old->getMostRecentDecl()->isInlined() && New->isInlined() && @@ -741,8 +741,9 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, CPlusPlus20Specifiers.push_back(DeclSpec::getSpecifierName(TSCS)); CPlusPlus20SpecifierLocs.push_back(DS.getThreadStorageClassSpecLoc()); } - if (DS.isConstexprSpecified()) { - BadSpecifiers.push_back("constexpr"); + if (DS.hasConstexprSpecifier()) { + BadSpecifiers.push_back( + DeclSpec::getSpecifierName(DS.getConstexprSpecifier())); BadSpecifierLocs.push_back(DS.getConstexprSpecLoc()); } if (DS.isInlineSpecified()) { @@ -1581,10 +1582,10 @@ static bool CheckConstexprParameterTypes(Sema &SemaRef, const ParmVarDecl *PD = FD->getParamDecl(ArgIndex); SourceLocation ParamLoc = PD->getLocation(); if (!(*i)->isDependentType() && - SemaRef.RequireLiteralType(ParamLoc, *i, - diag::err_constexpr_non_literal_param, - ArgIndex+1, PD->getSourceRange(), - isa<CXXConstructorDecl>(FD))) + SemaRef.RequireLiteralType( + ParamLoc, *i, diag::err_constexpr_non_literal_param, ArgIndex + 1, + PD->getSourceRange(), isa<CXXConstructorDecl>(FD), + FD->isConsteval())) return false; } return true; @@ -1661,7 +1662,8 @@ bool Sema::CheckConstexprFunctionDecl(const FunctionDecl *NewFD) { QualType RT = NewFD->getReturnType(); if (!RT->isDependentType() && RequireLiteralType(NewFD->getLocation(), RT, - diag::err_constexpr_non_literal_return)) + diag::err_constexpr_non_literal_return, + NewFD->isConsteval())) return false; } @@ -1775,7 +1777,7 @@ static bool CheckConstexprDeclStmt(Sema &SemaRef, const FunctionDecl *Dcl, default: SemaRef.Diag(DS->getBeginLoc(), diag::err_constexpr_body_invalid_stmt) - << isa<CXXConstructorDecl>(Dcl); + << isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval(); return false; } } @@ -1960,7 +1962,7 @@ CheckConstexprFunctionStmt(Sema &SemaRef, const FunctionDecl *Dcl, Stmt *S, } SemaRef.Diag(S->getBeginLoc(), diag::err_constexpr_body_invalid_stmt) - << isa<CXXConstructorDecl>(Dcl); + << isa<CXXConstructorDecl>(Dcl) << Dcl->isConsteval(); return false; } @@ -2082,7 +2084,8 @@ bool Sema::CheckConstexprFunctionBody(const FunctionDecl *Dcl, Stmt *Body) { Dcl->getReturnType()->isDependentType()); Diag(Dcl->getLocation(), OK ? diag::warn_cxx11_compat_constexpr_body_no_return - : diag::err_constexpr_body_no_return); + : diag::err_constexpr_body_no_return) + << Dcl->isConsteval(); if (!OK) return false; } else if (ReturnStmts.size() > 1) { @@ -3052,7 +3055,7 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, DS.getStorageClassSpec() == DeclSpec::SCS_mutable) && !isFunc); - if (DS.isConstexprSpecified() && isInstField) { + if (DS.hasConstexprSpecifier() && isInstField) { SemaDiagnosticBuilder B = Diag(DS.getConstexprSpecLoc(), diag::err_invalid_constexpr_member); SourceLocation ConstexprLoc = DS.getConstexprSpecLoc(); @@ -6688,7 +6691,10 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { : isa<CXXConstructorDecl>(MD)) && MD->isConstexpr() && !Constexpr && MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) { - Diag(MD->getBeginLoc(), diag::err_incorrect_defaulted_constexpr) << CSM; + Diag(MD->getBeginLoc(), MD->isConsteval() + ? diag::err_incorrect_defaulted_consteval + : diag::err_incorrect_defaulted_constexpr) + << CSM; // FIXME: Explain why the special member can't be constexpr. HadError = true; } @@ -6698,7 +6704,7 @@ void Sema::CheckExplicitlyDefaultedSpecialMember(CXXMethodDecl *MD) { // If a function is explicitly defaulted on its first declaration, it is // implicitly considered to be constexpr if the implicit declaration // would be. - MD->setConstexpr(Constexpr); + MD->setConstexprKind(Constexpr ? CSK_constexpr : CSK_unspecified); if (!Type->hasExceptionSpec()) { // C++2a [except.spec]p3: @@ -8744,7 +8750,7 @@ void Sema::CheckDeductionGuideDeclarator(Declarator &D, QualType &R, // We leave 'friend' and 'virtual' to be rejected in the normal way. if (DS.hasTypeSpecifier() || DS.getTypeQualifiers() || DS.getStorageClassSpecLoc().isValid() || DS.isInlineSpecified() || - DS.isNoreturnSpecified() || DS.isConstexprSpecified()) { + DS.isNoreturnSpecified() || DS.hasConstexprSpecifier()) { BadSpecifierDiagnoser Diagnoser( *this, D.getIdentifierLoc(), diag::err_deduction_guide_invalid_specifier); @@ -11035,7 +11041,8 @@ CXXConstructorDecl *Sema::DeclareImplicitDefaultConstructor( CXXConstructorDecl *DefaultCon = CXXConstructorDecl::Create( Context, ClassDecl, ClassLoc, NameInfo, /*Type*/ QualType(), /*TInfo=*/nullptr, ExplicitSpecifier(), - /*isInline=*/true, /*isImplicitlyDeclared=*/true, Constexpr); + /*isInline=*/true, /*isImplicitlyDeclared=*/true, + Constexpr ? CSK_constexpr : CSK_unspecified); DefaultCon->setAccess(AS_public); DefaultCon->setDefaulted(); @@ -11155,7 +11162,8 @@ Sema::findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *DerivedCtor = CXXConstructorDecl::Create( Context, Derived, UsingLoc, NameInfo, TInfo->getType(), TInfo, BaseCtor->getExplicitSpecifier(), /*Inline=*/true, - /*ImplicitlyDeclared=*/true, Constexpr, + /*ImplicitlyDeclared=*/true, + Constexpr ? BaseCtor->getConstexprKind() : CSK_unspecified, InheritedConstructor(Shadow, BaseCtor)); if (Shadow->isInvalidDecl()) DerivedCtor->setInvalidDecl(); @@ -11904,10 +11912,11 @@ CXXMethodDecl *Sema::DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl) { DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); - CXXMethodDecl *CopyAssignment = - CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), - /*TInfo=*/nullptr, /*StorageClass=*/SC_None, - /*isInline=*/true, Constexpr, SourceLocation()); + CXXMethodDecl *CopyAssignment = CXXMethodDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, QualType(), + /*TInfo=*/nullptr, /*StorageClass=*/SC_None, + /*isInline=*/true, Constexpr ? CSK_constexpr : CSK_unspecified, + SourceLocation()); CopyAssignment->setAccess(AS_public); CopyAssignment->setDefaulted(); CopyAssignment->setImplicit(); @@ -12224,10 +12233,11 @@ CXXMethodDecl *Sema::DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl) { DeclarationName Name = Context.DeclarationNames.getCXXOperatorName(OO_Equal); SourceLocation ClassLoc = ClassDecl->getLocation(); DeclarationNameInfo NameInfo(Name, ClassLoc); - CXXMethodDecl *MoveAssignment = - CXXMethodDecl::Create(Context, ClassDecl, ClassLoc, NameInfo, QualType(), - /*TInfo=*/nullptr, /*StorageClass=*/SC_None, - /*isInline=*/true, Constexpr, SourceLocation()); + CXXMethodDecl *MoveAssignment = CXXMethodDecl::Create( + Context, ClassDecl, ClassLoc, NameInfo, QualType(), + /*TInfo=*/nullptr, /*StorageClass=*/SC_None, + /*isInline=*/true, Constexpr ? CSK_constexpr : CSK_unspecified, + SourceLocation()); MoveAssignment->setAccess(AS_public); MoveAssignment->setDefaulted(); MoveAssignment->setImplicit(); @@ -12608,7 +12618,8 @@ CXXConstructorDecl *Sema::DeclareImplicitCopyConstructor( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, ExplicitSpecifier(), /*isInline=*/true, - /*isImplicitlyDeclared=*/true, Constexpr); + /*isImplicitlyDeclared=*/true, + Constexpr ? CSK_constexpr : CSK_unspecified); CopyConstructor->setAccess(AS_public); CopyConstructor->setDefaulted(); @@ -12739,7 +12750,8 @@ CXXConstructorDecl *Sema::DeclareImplicitMoveConstructor( Context, ClassDecl, ClassLoc, NameInfo, QualType(), /*TInfo=*/nullptr, ExplicitSpecifier(), /*isInline=*/true, - /*isImplicitlyDeclared=*/true, Constexpr); + /*isImplicitlyDeclared=*/true, + Constexpr ? CSK_constexpr : CSK_unspecified); MoveConstructor->setAccess(AS_public); MoveConstructor->setDefaulted(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index d444a35be8..a8f3ec0ba5 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -17125,13 +17125,11 @@ ExprResult RebuildUnknownAnyExpr::resolveDecl(Expr *E, ValueDecl *VD) { DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); if (DRE && Proto && Proto->getParamTypes().empty() && Proto->isVariadic()) { SourceLocation Loc = FD->getLocation(); - FunctionDecl *NewFD = FunctionDecl::Create(S.Context, - FD->getDeclContext(), - Loc, Loc, FD->getNameInfo().getName(), - DestType, FD->getTypeSourceInfo(), - SC_None, false/*isInlineSpecified*/, - FD->hasPrototype(), - false/*isConstexprSpecified*/); + FunctionDecl *NewFD = FunctionDecl::Create( + S.Context, FD->getDeclContext(), Loc, Loc, + FD->getNameInfo().getName(), DestType, FD->getTypeSourceInfo(), + SC_None, false /*isInlineSpecified*/, FD->hasPrototype(), + /*ConstexprKind*/ CSK_unspecified); if (FD->getQualifier()) NewFD->setQualifierInfo(FD->getQualifierLoc()); diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index ccc8f6f42a..268e15c20e 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -370,7 +370,7 @@ Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext( CXXMethodDecl *Sema::startLambdaDefinition( CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodTypeInfo, SourceLocation EndLoc, - ArrayRef<ParmVarDecl *> Params, const bool IsConstexprSpecified, + ArrayRef<ParmVarDecl *> Params, ConstexprSpecKind ConstexprKind, Optional<std::pair<unsigned, Decl *>> Mangling) { QualType MethodType = MethodTypeInfo->getType(); TemplateParameterList *TemplateParams = @@ -400,16 +400,12 @@ CXXMethodDecl *Sema::startLambdaDefinition( = IntroducerRange.getBegin().getRawEncoding(); MethodNameLoc.CXXOperatorName.EndOpNameLoc = IntroducerRange.getEnd().getRawEncoding(); - CXXMethodDecl *Method - = CXXMethodDecl::Create(Context, Class, EndLoc, - DeclarationNameInfo(MethodName, - IntroducerRange.getBegin(), - MethodNameLoc), - MethodType, MethodTypeInfo, - SC_None, - /*isInline=*/true, - IsConstexprSpecified, - EndLoc); + CXXMethodDecl *Method = CXXMethodDecl::Create( + Context, Class, EndLoc, + DeclarationNameInfo(MethodName, IntroducerRange.getBegin(), + MethodNameLoc), + MethodType, MethodTypeInfo, SC_None, + /*isInline=*/true, ConstexprKind, EndLoc); Method->setAccess(AS_public); // Temporarily set the lexical declaration context to the current @@ -940,7 +936,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params, - ParamInfo.getDeclSpec().isConstexprSpecified()); + ParamInfo.getDeclSpec().getConstexprSpecifier()); if (ExplicitParams) CheckCXXDefaultArguments(Method); @@ -1341,7 +1337,7 @@ static void addFunctionPointerConversion(Sema &S, S.Context, Class, Loc, DeclarationNameInfo(ConversionName, Loc, ConvNameLoc), ConvTy, ConvTSI, /*isInline=*/true, ExplicitSpecifier(), - /*isConstexpr=*/S.getLangOpts().CPlusPlus17, + S.getLangOpts().CPlusPlus17 ? CSK_constexpr : CSK_unspecified, CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); @@ -1380,8 +1376,7 @@ static void addFunctionPointerConversion(Sema &S, CXXMethodDecl *Invoke = CXXMethodDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(InvokerName, Loc), InvokerFunctionTy, CallOperator->getTypeSourceInfo(), SC_Static, - /*IsInline=*/true, - /*IsConstexpr=*/false, CallOperator->getBody()->getEndLoc()); + /*IsInline=*/true, CSK_unspecified, CallOperator->getBody()->getEndLoc()); for (unsigned I = 0, N = CallOperator->getNumParams(); I != N; ++I) InvokerParams[I]->setOwningFunction(Invoke); Invoke->setParams(InvokerParams); @@ -1427,8 +1422,8 @@ static void addBlockPointerConversion(Sema &S, CXXConversionDecl *Conversion = CXXConversionDecl::Create( S.Context, Class, Loc, DeclarationNameInfo(Name, Loc, NameLoc), ConvTy, S.Context.getTrivialTypeSourceInfo(ConvTy, Loc), - /*isInline=*/true, ExplicitSpecifier(), - /*isConstexpr=*/false, CallOperator->getBody()->getEndLoc()); + /*isInline=*/true, ExplicitSpecifier(), CSK_unspecified, + CallOperator->getBody()->getEndLoc()); Conversion->setAccess(AS_public); Conversion->setImplicit(true); Class->addDecl(Conversion); @@ -1782,9 +1777,11 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, !isa<CoroutineBodyStmt>(CallOperator->getBody()) && !Class->getDeclContext()->isDependentContext()) { TentativeAnalysisScope DiagnosticScopeGuard(*this); - CallOperator->setConstexpr( - CheckConstexprFunctionDecl(CallOperator) && - CheckConstexprFunctionBody(CallOperator, CallOperator->getBody())); + CallOperator->setConstexprKind( + (CheckConstexprFunctionDecl(CallOperator) && + CheckConstexprFunctionBody(CallOperator, CallOperator->getBody())) + ? CSK_constexpr + : CSK_unspecified); } // Emit delayed shadowing warnings now that the full capture list is known. diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp index bc1e8f2709..3b149e6fdb 100644 --- a/lib/Sema/SemaStmt.cpp +++ b/lib/Sema/SemaStmt.cpp @@ -3693,7 +3693,8 @@ StmtResult Sema::BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp) { } if (FD) - Diag(ReturnLoc, DiagID) << FD->getIdentifier() << 0/*fn*/; + Diag(ReturnLoc, DiagID) + << FD->getIdentifier() << 0 /*fn*/ << FD->isConsteval(); else Diag(ReturnLoc, DiagID) << getCurMethodDecl()->getDeclName() << 1/*meth*/; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index f7f3ccc3e2..03240655ee 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1147,7 +1147,7 @@ NamedDecl *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, // variable or variable template or the declaration of a function or // function template. - if (DS.isConstexprSpecified()) + if (DS.hasConstexprSpecifier()) EmitDiag(DS.getConstexprSpecLoc()); // [dcl.fct.spec]p1: @@ -8371,7 +8371,7 @@ bool Sema::CheckFunctionTemplateSpecialization( // FIXME: We need an update record for this AST mutation. // FIXME: What if there are multiple such prior declarations (for instance, // from different modules)? - Specialization->setConstexpr(FD->isConstexpr()); + Specialization->setConstexprKind(FD->getConstexprKind()); } // FIXME: Check if the prior specialization has a point of instantiation. @@ -9260,7 +9260,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S, diag::err_explicit_instantiation_inline : diag::warn_explicit_instantiation_inline_0x) << FixItHint::CreateRemoval(D.getDeclSpec().getInlineSpecLoc()); - if (D.getDeclSpec().isConstexprSpecified() && R->isFunctionType()) + if (D.getDeclSpec().hasConstexprSpecifier() && R->isFunctionType()) // FIXME: Add a fix-it to remove the 'constexpr' and add a 'const' if one is // not already specified. Diag(D.getDeclSpec().getConstexprSpecLoc(), diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index d0ff0994ed..cbfb0fed23 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1779,7 +1779,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Function = FunctionDecl::Create( SemaRef.Context, DC, D->getInnerLocStart(), NameInfo, T, TInfo, D->getCanonicalDecl()->getStorageClass(), D->isInlineSpecified(), - D->hasWrittenPrototype(), D->isConstexpr()); + D->hasWrittenPrototype(), D->getConstexprKind()); Function->setRangeEnd(D->getSourceRange().getEnd()); } @@ -2087,7 +2087,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( Method = CXXConstructorDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, InstantiatedExplicitSpecifier, Constructor->isInlineSpecified(), false, - Constructor->isConstexpr()); + Constructor->getConstexprKind()); Method->setRangeEnd(Constructor->getEndLoc()); } else if (CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(D)) { Method = CXXDestructorDecl::Create(SemaRef.Context, Record, @@ -2099,12 +2099,12 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl( Method = CXXConversionDecl::Create( SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, Conversion->isInlineSpecified(), InstantiatedExplicitSpecifier, - Conversion->isConstexpr(), Conversion->getEndLoc()); + Conversion->getConstexprKind(), Conversion->getEndLoc()); } else { StorageClass SC = D->isStatic() ? SC_Static : SC_None; Method = CXXMethodDecl::Create(SemaRef.Context, Record, StartLoc, NameInfo, T, TInfo, SC, D->isInlineSpecified(), - D->isConstexpr(), D->getEndLoc()); + D->getConstexprKind(), D->getEndLoc()); } if (D->isInlined()) diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 47de398d4f..88b544068a 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -5146,7 +5146,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // C++0x [dcl.constexpr]p9: // A constexpr specifier used in an object declaration declares the object // as const. - if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) { + if (D.getDeclSpec().hasConstexprSpecifier() && T->isObjectType()) { T.addConst(); } diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 6e033cb579..65f8678d94 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -11337,7 +11337,7 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { Class, E->getIntroducerRange(), NewCallOpTSI, E->getCallOperator()->getEndLoc(), NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(), - E->getCallOperator()->isConstexpr(), Mangling); + E->getCallOperator()->getConstexprKind(), Mangling); LSI->CallOperator = NewCallOperator; |