summaryrefslogtreecommitdiff
path: root/lib/Parse/ParseDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r--lib/Parse/ParseDecl.cpp130
1 files changed, 92 insertions, 38 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 73b4f50fda460..b248d7582d847 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -86,8 +86,8 @@ static bool isAttributeLateParsed(const IdentifierInfo &II) {
}
/// Check if the a start and end source location expand to the same macro.
-bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc,
- SourceLocation EndLoc) {
+static bool FindLocsWithCommonFileID(Preprocessor &PP, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
if (!StartLoc.isMacroID() || !EndLoc.isMacroID())
return false;
@@ -335,6 +335,7 @@ unsigned Parser::ParseAttributeArgsCommon(
ConsumeParen();
bool ChangeKWThisToIdent = attributeTreatsKeywordThisAsIdentifier(*AttrName);
+ bool AttributeIsTypeArgAttr = attributeIsTypeArgAttr(*AttrName);
// Interpret "kw_this" as an identifier if the attributed requests it.
if (ChangeKWThisToIdent && Tok.is(tok::kw_this))
@@ -346,7 +347,7 @@ unsigned Parser::ParseAttributeArgsCommon(
bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName) ||
attributeHasVariadicIdentifierArg(*AttrName);
ParsedAttr::Kind AttrKind =
- ParsedAttr::getKind(AttrName, ScopeName, Syntax);
+ ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
// If we don't know how to parse this attribute, but this is the only
// token in this argument, assume it's meant to be an identifier.
@@ -360,6 +361,7 @@ unsigned Parser::ParseAttributeArgsCommon(
ArgExprs.push_back(ParseIdentifierLoc());
}
+ ParsedType TheParsedType;
if (!ArgExprs.empty() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren)) {
// Eat the comma.
if (!ArgExprs.empty())
@@ -372,8 +374,17 @@ unsigned Parser::ParseAttributeArgsCommon(
Tok.setKind(tok::identifier);
ExprResult ArgExpr;
- if (Tok.is(tok::identifier) &&
- attributeHasVariadicIdentifierArg(*AttrName)) {
+ if (AttributeIsTypeArgAttr) {
+ TypeResult T = ParseTypeName();
+ if (T.isInvalid()) {
+ SkipUntil(tok::r_paren, StopAtSemi);
+ return 0;
+ }
+ if (T.isUsable())
+ TheParsedType = T.get();
+ break; // FIXME: Multiple type arguments are not implemented.
+ } else if (Tok.is(tok::identifier) &&
+ attributeHasVariadicIdentifierArg(*AttrName)) {
ArgExprs.push_back(ParseIdentifierLoc());
} else {
bool Uneval = attributeParsedArgsUnevaluated(*AttrName);
@@ -397,14 +408,20 @@ unsigned Parser::ParseAttributeArgsCommon(
SourceLocation RParen = Tok.getLocation();
if (!ExpectAndConsume(tok::r_paren)) {
SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc;
- Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
- ArgExprs.data(), ArgExprs.size(), Syntax);
+
+ if (AttributeIsTypeArgAttr && !TheParsedType.get().isNull()) {
+ Attrs.addNewTypeAttr(AttrName, SourceRange(AttrNameLoc, RParen),
+ ScopeName, ScopeLoc, TheParsedType, Syntax);
+ } else {
+ Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc,
+ ArgExprs.data(), ArgExprs.size(), Syntax);
+ }
}
if (EndLoc)
*EndLoc = RParen;
- return static_cast<unsigned>(ArgExprs.size());
+ return static_cast<unsigned>(ArgExprs.size() + !TheParsedType.get().isNull());
}
/// Parse the arguments to a parameterized GNU attribute or
@@ -421,7 +438,7 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
ParsedAttr::Kind AttrKind =
- ParsedAttr::getKind(AttrName, ScopeName, Syntax);
+ ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
if (AttrKind == ParsedAttr::AT_Availability) {
ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName,
@@ -471,7 +488,7 @@ unsigned Parser::ParseClangAttributeArgs(
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
ParsedAttr::Kind AttrKind =
- ParsedAttr::getKind(AttrName, ScopeName, Syntax);
+ ParsedAttr::getParsedKind(AttrName, ScopeName, Syntax);
switch (AttrKind) {
default:
@@ -1672,9 +1689,9 @@ void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs,
if (!AL.isCXX11Attribute() && !AL.isC2xAttribute())
continue;
if (AL.getKind() == ParsedAttr::UnknownAttribute)
- Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName();
+ Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL;
else {
- Diag(AL.getLoc(), DiagID) << AL.getName();
+ Diag(AL.getLoc(), DiagID) << AL;
AL.setInvalid();
}
}
@@ -1724,9 +1741,10 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs,
/// [C++11/C11] static_assert-declaration
/// others... [FIXME]
///
-Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
- SourceLocation &DeclEnd,
- ParsedAttributesWithRange &attrs) {
+Parser::DeclGroupPtrTy
+Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &attrs,
+ SourceLocation *DeclSpecStart) {
ParenBraceBracketBalancer BalancerRAIIObj(*this);
// Must temporarily exit the objective-c container scope for
// parsing c none objective-c decls.
@@ -1746,8 +1764,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
SourceLocation InlineLoc = ConsumeToken();
return ParseNamespace(Context, DeclEnd, InlineLoc);
}
- return ParseSimpleDeclaration(Context, DeclEnd, attrs,
- true);
+ return ParseSimpleDeclaration(Context, DeclEnd, attrs, true, nullptr,
+ DeclSpecStart);
case tok::kw_namespace:
ProhibitAttributes(attrs);
return ParseNamespace(Context, DeclEnd);
@@ -1760,7 +1778,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
SingleDecl = ParseStaticAssertDeclaration(DeclEnd);
break;
default:
- return ParseSimpleDeclaration(Context, DeclEnd, attrs, true);
+ return ParseSimpleDeclaration(Context, DeclEnd, attrs, true, nullptr,
+ DeclSpecStart);
}
// This routine returns a DeclGroup, if the thing we parsed only contains a
@@ -1785,11 +1804,14 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context,
/// If FRI is non-null, we might be parsing a for-range-declaration instead
/// of a simple-declaration. If we find that we are, we also parse the
/// for-range-initializer, and place it here.
-Parser::DeclGroupPtrTy
-Parser::ParseSimpleDeclaration(DeclaratorContext Context,
- SourceLocation &DeclEnd,
- ParsedAttributesWithRange &Attrs,
- bool RequireSemi, ForRangeInit *FRI) {
+///
+/// DeclSpecStart is used when decl-specifiers are parsed before parsing
+/// the Declaration. The SourceLocation for this Decl is set to
+/// DeclSpecStart if DeclSpecStart is non-null.
+Parser::DeclGroupPtrTy Parser::ParseSimpleDeclaration(
+ DeclaratorContext Context, SourceLocation &DeclEnd,
+ ParsedAttributesWithRange &Attrs, bool RequireSemi, ForRangeInit *FRI,
+ SourceLocation *DeclSpecStart) {
// Parse the common declaration-specifiers piece.
ParsingDeclSpec DS(*this);
@@ -1819,6 +1841,9 @@ Parser::ParseSimpleDeclaration(DeclaratorContext Context,
return Actions.ConvertDeclToDeclGroup(TheDecl);
}
+ if (DeclSpecStart)
+ DS.SetRangeStart(*DeclSpecStart);
+
DS.takeAttributesFrom(Attrs);
return ParseDeclGroup(DS, Context, &DeclEnd, FRI);
}
@@ -2075,6 +2100,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
bool IsForRangeLoop = false;
if (TryConsumeToken(tok::colon, FRI->ColonLoc)) {
IsForRangeLoop = true;
+ if (getLangOpts().OpenMP)
+ Actions.startOpenMPCXXRangeFor();
if (Tok.is(tok::l_brace))
FRI->RangeExpr = ParseBraceInitializer();
else
@@ -2489,7 +2516,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS,
// Issue diagnostic and remove constexpr specifier if present.
if (DS.hasConstexprSpecifier() && DSC != DeclSpecContext::DSC_condition) {
Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr)
- << (DS.getConstexprSpecifier() == CSK_consteval);
+ << DS.getConstexprSpecifier();
DS.ClearConstexprSpec();
}
}
@@ -2902,28 +2929,29 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS,
IdentifierInfo *Name = AfterScope.getIdentifierInfo();
Sema::NameClassification Classification = Actions.ClassifyName(
getCurScope(), SS, Name, AfterScope.getLocation(), Next,
- /*IsAddressOfOperand=*/false, /*CCC=*/nullptr);
+ /*CCC=*/nullptr);
switch (Classification.getKind()) {
case Sema::NC_Error:
SkipMalformedDecl();
return true;
case Sema::NC_Keyword:
- case Sema::NC_NestedNameSpecifier:
- llvm_unreachable("typo correction and nested name specifiers not "
- "possible here");
+ llvm_unreachable("typo correction is not possible here");
case Sema::NC_Type:
case Sema::NC_TypeTemplate:
+ case Sema::NC_UndeclaredNonType:
+ case Sema::NC_UndeclaredTemplate:
// Not a previously-declared non-type entity.
MightBeDeclarator = false;
break;
case Sema::NC_Unknown:
- case Sema::NC_Expression:
+ case Sema::NC_NonType:
+ case Sema::NC_DependentNonType:
+ case Sema::NC_ContextIndependentExpr:
case Sema::NC_VarTemplate:
case Sema::NC_FunctionTemplate:
- case Sema::NC_UndeclaredTemplate:
// Might be a redeclaration of a prior entity.
break;
}
@@ -3549,6 +3577,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isStorageClass = true;
break;
case tok::kw__Thread_local:
+ if (!getLangOpts().C11)
+ Diag(Tok, diag::ext_c11_feature) << Tok.getName();
isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local,
Loc, PrevSpec, DiagID);
isStorageClass = true;
@@ -3599,14 +3629,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
}
case tok::kw__Noreturn:
if (!getLangOpts().C11)
- Diag(Loc, diag::ext_c11_noreturn);
+ Diag(Tok, diag::ext_c11_feature) << Tok.getName();
isInvalid = DS.setFunctionSpecNoreturn(Loc, PrevSpec, DiagID);
break;
// alignment-specifier
case tok::kw__Alignas:
if (!getLangOpts().C11)
- Diag(Tok, diag::ext_c11_alignment) << Tok.getName();
+ Diag(Tok, diag::ext_c11_feature) << Tok.getName();
ParseAlignmentSpecifier(DS.getAttributes());
continue;
@@ -3626,15 +3656,16 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
isInvalid = DS.setModulePrivateSpec(Loc, PrevSpec, DiagID);
break;
- // constexpr
+ // constexpr, consteval, constinit specifiers
case tok::kw_constexpr:
isInvalid = DS.SetConstexprSpec(CSK_constexpr, Loc, PrevSpec, DiagID);
break;
-
- // consteval
case tok::kw_consteval:
isInvalid = DS.SetConstexprSpec(CSK_consteval, Loc, PrevSpec, DiagID);
break;
+ case tok::kw_constinit:
+ isInvalid = DS.SetConstexprSpec(CSK_constinit, Loc, PrevSpec, DiagID);
+ break;
// type-specifier
case tok::kw_short:
@@ -3662,10 +3693,14 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
DiagID);
break;
case tok::kw__Complex:
+ if (!getLangOpts().C99)
+ Diag(Tok, diag::ext_c99_feature) << Tok.getName();
isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_complex, Loc, PrevSpec,
DiagID);
break;
case tok::kw__Imaginary:
+ if (!getLangOpts().C99)
+ Diag(Tok, diag::ext_c99_feature) << Tok.getName();
isInvalid = DS.SetTypeSpecComplex(DeclSpec::TSC_imaginary, Loc, PrevSpec,
DiagID);
break;
@@ -3746,6 +3781,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
break;
case tok::kw_bool:
case tok::kw__Bool:
+ if (Tok.is(tok::kw__Bool) && !getLangOpts().C99)
+ Diag(Tok, diag::ext_c99_feature) << Tok.getName();
+
if (Tok.is(tok::kw_bool) &&
DS.getTypeSpecType() != DeclSpec::TST_unspecified &&
DS.getStorageClassSpec() == DeclSpec::SCS_typedef) {
@@ -3889,6 +3927,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
// If the _Atomic keyword is immediately followed by a left parenthesis,
// it is interpreted as a type specifier (with a type name), not as a
// type qualifier.
+ if (!getLangOpts().C11)
+ Diag(Tok, diag::ext_c11_feature) << Tok.getName();
+
if (NextToken().is(tok::l_paren)) {
ParseAtomicSpecifier(DS);
continue;
@@ -4081,7 +4122,7 @@ void Parser::ParseStructDeclaration(
/// [OBC] '@' 'defs' '(' class-name ')'
///
void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
- unsigned TagType, Decl *TagDecl) {
+ DeclSpec::TST TagType, Decl *TagDecl) {
PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc,
"parsing struct/union body");
assert(!getLangOpts().CPlusPlus && "C++ declarations not supported");
@@ -4131,6 +4172,14 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
continue;
}
+ if (tok::isPragmaAnnotation(Tok.getKind())) {
+ Diag(Tok.getLocation(), diag::err_pragma_misplaced_in_decl)
+ << DeclSpec::getSpecifierName(
+ TagType, Actions.getASTContext().getPrintingPolicy());
+ ConsumeAnnotationToken();
+ continue;
+ }
+
if (!Tok.is(tok::at)) {
auto CFieldCallback = [&](ParsingFieldDeclarator &FD) {
// Install the declarator into the current TagDecl.
@@ -4632,8 +4681,10 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) {
ExprResult AssignedVal;
EnumAvailabilityDiags.emplace_back(*this);
+ EnterExpressionEvaluationContext ConstantEvaluated(
+ Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated);
if (TryConsumeToken(tok::equal, EqualLoc)) {
- AssignedVal = ParseConstantExpression();
+ AssignedVal = ParseConstantExpressionInExprEvalContext();
if (AssignedVal.isInvalid())
SkipUntil(tok::comma, tok::r_brace, StopBeforeMatch);
}
@@ -5038,8 +5089,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
case tok::annot_decltype:
case tok::kw_constexpr:
- // C++20 consteval.
+ // C++20 consteval and constinit.
case tok::kw_consteval:
+ case tok::kw_constinit:
// C11 _Atomic
case tok::kw__Atomic:
@@ -5286,6 +5338,8 @@ void Parser::ParseTypeQualifierListOpt(
case tok::kw__Atomic:
if (!AtomicAllowed)
goto DoneWithTypeQuals;
+ if (!getLangOpts().C11)
+ Diag(Tok, diag::ext_c11_feature) << Tok.getName();
isInvalid = DS.SetTypeQual(DeclSpec::TQ_atomic, Loc, PrevSpec, DiagID,
getLangOpts());
break;