summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r--clang/lib/Sema/SemaDecl.cpp60
1 files changed, 36 insertions, 24 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 10837f68943..ce6fd412361 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/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
OpenPOWER on IntegriCloud