diff options
Diffstat (limited to 'lib/Parse/ParseDecl.cpp')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 738 |
1 files changed, 409 insertions, 329 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 2a999399fb50..4f6bb08bdc64 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -15,6 +15,7 @@ #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/CharInfo.h" @@ -22,14 +23,12 @@ #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/ParsedTemplate.h" -#include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" -#include "llvm/Support/ScopedPrinter.h" using namespace clang; @@ -43,18 +42,18 @@ using namespace clang; /// /// Called type-id in C++. TypeResult Parser::ParseTypeName(SourceRange *Range, - Declarator::TheContext Context, + DeclaratorContext Context, AccessSpecifier AS, Decl **OwnedType, ParsedAttributes *Attrs) { DeclSpecContext DSC = getDeclSpecContextFromDeclaratorContext(Context); - if (DSC == DSC_normal) - DSC = DSC_type_specifier; + if (DSC == DeclSpecContext::DSC_normal) + DSC = DeclSpecContext::DSC_type_specifier; // Parse the common declaration-specifiers piece. DeclSpec DS(AttrFactory); if (Attrs) - DS.addAttributes(Attrs->getList()); + DS.addAttributes(*Attrs); ParseSpecifierQualifierList(DS, AS, DSC); if (OwnedType) *OwnedType = DS.isTypeSpecOwned() ? DS.getRepAsDecl() : nullptr; @@ -71,7 +70,7 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } -/// \brief Normalizes an attribute name by dropping prefixed and suffixed __. +/// Normalizes an attribute name by dropping prefixed and suffixed __. static StringRef normalizeAttrName(StringRef Name) { if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__")) return Name.drop_front(2).drop_back(2); @@ -163,14 +162,14 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, if (Tok.isNot(tok::l_paren)) { attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_GNU); + ParsedAttr::AS_GNU); continue; } // Handle "parameterized" attributes if (!LateAttrs || !isAttributeLateParsed(*AttrName)) { ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc, nullptr, - SourceLocation(), AttributeList::AS_GNU, D); + SourceLocation(), ParsedAttr::AS_GNU, D); continue; } @@ -207,7 +206,7 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs, } } -/// \brief Determine whether the given attribute has an identifier argument. +/// Determine whether the given attribute has an identifier argument. static bool attributeHasIdentifierArg(const IdentifierInfo &II) { #define CLANG_ATTR_IDENTIFIER_ARG_LIST return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) @@ -216,7 +215,16 @@ static bool attributeHasIdentifierArg(const IdentifierInfo &II) { #undef CLANG_ATTR_IDENTIFIER_ARG_LIST } -/// \brief Determine whether the given attribute parses a type argument. +/// Determine whether the given attribute has a variadic identifier argument. +static bool attributeHasVariadicIdentifierArg(const IdentifierInfo &II) { +#define CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST + return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) +#include "clang/Parse/AttrParserStringSwitches.inc" + .Default(false); +#undef CLANG_ATTR_VARIADIC_IDENTIFIER_ARG_LIST +} + +/// Determine whether the given attribute parses a type argument. static bool attributeIsTypeArgAttr(const IdentifierInfo &II) { #define CLANG_ATTR_TYPE_ARG_LIST return llvm::StringSwitch<bool>(normalizeAttrName(II.getName())) @@ -225,7 +233,7 @@ static bool attributeIsTypeArgAttr(const IdentifierInfo &II) { #undef CLANG_ATTR_TYPE_ARG_LIST } -/// \brief Determine whether the given attribute requires parsing its arguments +/// Determine whether the given attribute requires parsing its arguments /// in an unevaluated context or not. static bool attributeParsedArgsUnevaluated(const IdentifierInfo &II) { #define CLANG_ATTR_ARG_CONTEXT_LIST @@ -250,7 +258,7 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax) { + ParsedAttr::Syntax Syntax) { BalancedDelimiterTracker Parens(*this, tok::l_paren); Parens.consumeOpen(); @@ -276,21 +284,22 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, unsigned Parser::ParseAttributeArgsCommon( IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { + SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { // Ignore the left paren location for now. ConsumeParen(); ArgsVector ArgExprs; if (Tok.is(tok::identifier)) { // If this attribute wants an 'identifier' argument, make it so. - bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName); - AttributeList::Kind AttrKind = - AttributeList::getKind(AttrName, ScopeName, Syntax); + bool IsIdentifierArg = attributeHasIdentifierArg(*AttrName) || + attributeHasVariadicIdentifierArg(*AttrName); + ParsedAttr::Kind AttrKind = + ParsedAttr::getKind(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. - if (AttrKind == AttributeList::UnknownAttribute || - AttrKind == AttributeList::IgnoredAttribute) { + if (AttrKind == ParsedAttr::UnknownAttribute || + AttrKind == ParsedAttr::IgnoredAttribute) { const Token &Next = NextToken(); IsIdentifierArg = Next.isOneOf(tok::r_paren, tok::comma); } @@ -306,21 +315,25 @@ unsigned Parser::ParseAttributeArgsCommon( // Parse the non-empty comma-separated list of expressions. do { - bool Uneval = attributeParsedArgsUnevaluated(*AttrName); - EnterExpressionEvaluationContext Unevaluated( - Actions, - Uneval ? Sema::ExpressionEvaluationContext::Unevaluated - : Sema::ExpressionEvaluationContext::ConstantEvaluated, - /*LambdaContextDecl=*/nullptr, - /*IsDecltype=*/false); - - ExprResult ArgExpr( - Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); - if (ArgExpr.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return 0; + ExprResult ArgExpr; + if (Tok.is(tok::identifier) && + attributeHasVariadicIdentifierArg(*AttrName)) { + ArgExprs.push_back(ParseIdentifierLoc()); + } else { + bool Uneval = attributeParsedArgsUnevaluated(*AttrName); + EnterExpressionEvaluationContext Unevaluated( + Actions, + Uneval ? Sema::ExpressionEvaluationContext::Unevaluated + : Sema::ExpressionEvaluationContext::ConstantEvaluated); + + ExprResult ArgExpr( + Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression())); + if (ArgExpr.isInvalid()) { + SkipUntil(tok::r_paren, StopAtSemi); + return 0; + } + ArgExprs.push_back(ArgExpr.get()); } - ArgExprs.push_back(ArgExpr.get()); // Eat the comma, move to the next argument } while (TryConsumeToken(tok::comma)); } @@ -346,27 +359,27 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax, + ParsedAttr::Syntax Syntax, Declarator *D) { assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); - AttributeList::Kind AttrKind = - AttributeList::getKind(AttrName, ScopeName, Syntax); + ParsedAttr::Kind AttrKind = + ParsedAttr::getKind(AttrName, ScopeName, Syntax); - if (AttrKind == AttributeList::AT_Availability) { + if (AttrKind == ParsedAttr::AT_Availability) { ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; - } else if (AttrKind == AttributeList::AT_ExternalSourceSymbol) { + } else if (AttrKind == ParsedAttr::AT_ExternalSourceSymbol) { ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; - } else if (AttrKind == AttributeList::AT_ObjCBridgeRelated) { + } else if (AttrKind == ParsedAttr::AT_ObjCBridgeRelated) { ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; - } else if (AttrKind == AttributeList::AT_TypeTagForDatatype) { + } else if (AttrKind == ParsedAttr::AT_TypeTagForDatatype) { ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); return; @@ -398,20 +411,34 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, unsigned Parser::ParseClangAttributeArgs( IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { + SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); - AttributeList::Kind AttrKind = - AttributeList::getKind(AttrName, ScopeName, Syntax); + ParsedAttr::Kind AttrKind = + ParsedAttr::getKind(AttrName, ScopeName, Syntax); - if (AttrKind == AttributeList::AT_ExternalSourceSymbol) { + switch (AttrKind) { + default: + return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, Syntax); + case ParsedAttr::AT_ExternalSourceSymbol: ParseExternalSourceSymbolAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); - return Attrs.getList() ? Attrs.getList()->getNumArgs() : 0; + break; + case ParsedAttr::AT_Availability: + ParseAvailabilityAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, + ScopeLoc, Syntax); + break; + case ParsedAttr::AT_ObjCBridgeRelated: + ParseObjCBridgeRelatedAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, Syntax); + break; + case ParsedAttr::AT_TypeTagForDatatype: + ParseTypeTagForDatatypeAttribute(*AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, Syntax); + break; } - - return ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, - ScopeName, ScopeLoc, Syntax); + return !Attrs.empty() ? Attrs.begin()->getNumArgs() : 0; } bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, @@ -538,19 +565,18 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, if (!HasInvalidAccessor) Attrs.addNewPropertyAttr(AttrName, AttrNameLoc, nullptr, SourceLocation(), AccessorNames[AK_Get], AccessorNames[AK_Put], - AttributeList::AS_Declspec); + ParsedAttr::AS_Declspec); T.skipToEnd(); return !HasInvalidAccessor; } unsigned NumArgs = ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr, - SourceLocation(), AttributeList::AS_Declspec); + SourceLocation(), ParsedAttr::AS_Declspec); // If this attribute's args were parsed, and it was expected to have // arguments but none were provided, emit a diagnostic. - const AttributeList *Attr = Attrs.getList(); - if (Attr && Attr->getMaxArgs() && !NumArgs) { + if (!Attrs.empty() && Attrs.begin()->getMaxArgs() && !NumArgs) { Diag(OpenParenLoc, diag::err_attribute_requires_arguments) << AttrName; return false; } @@ -621,7 +647,7 @@ void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs, if (!AttrHandled) Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Declspec); + ParsedAttr::AS_Declspec); } T.consumeClose(); if (End) @@ -647,7 +673,7 @@ void Parser::ParseMicrosoftTypeAttributes(ParsedAttributes &attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); break; } default: @@ -698,7 +724,7 @@ void Parser::ParseBorlandTypeAttributes(ParsedAttributes &attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); } } @@ -708,7 +734,7 @@ void Parser::ParseOpenCLKernelAttributes(ParsedAttributes &attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); } } @@ -716,7 +742,7 @@ void Parser::ParseOpenCLQualifiers(ParsedAttributes &Attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = Tok.getLocation(); Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); } void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) { @@ -732,7 +758,7 @@ void Parser::ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs) { Diag(AttrNameLoc, diag::ext_nullability) << AttrName; attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); break; } default: @@ -745,12 +771,14 @@ static bool VersionNumberSeparator(const char Separator) { return (Separator == '.' || Separator == '_'); } -/// \brief Parse a version number. +/// Parse a version number. /// /// version: /// simple-integer -/// simple-integer ',' simple-integer -/// simple-integer ',' simple-integer ',' simple-integer +/// simple-integer '.' simple-integer +/// simple-integer '_' simple-integer +/// simple-integer '.' simple-integer '.' simple-integer +/// simple-integer '_' simple-integer '_' simple-integer VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { Range = SourceRange(Tok.getLocation(), Tok.getEndLoc()); @@ -828,7 +856,7 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { return VersionTuple(); } - return VersionTuple(Major, Minor, (AfterMajorSeparator == '_')); + return VersionTuple(Major, Minor); } const char AfterMinorSeparator = ThisTokBegin[AfterMinor]; @@ -859,10 +887,10 @@ VersionTuple Parser::ParseVersionTuple(SourceRange &Range) { return VersionTuple(); } ConsumeToken(); - return VersionTuple(Major, Minor, Subminor, (AfterMajorSeparator == '_')); + return VersionTuple(Major, Minor, Subminor); } -/// \brief Parse the contents of the "availability" attribute. +/// Parse the contents of the "availability" attribute. /// /// availability-attribute: /// 'availability' '(' platform ',' opt-strict version-arg-list, @@ -893,7 +921,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, SourceLocation *endLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax) { + ParsedAttr::Syntax Syntax) { enum { Introduced, Deprecated, Obsoleted, Unknown }; AvailabilityChange Changes[Unknown]; ExprResult MessageExpr, ReplacementExpr; @@ -1094,7 +1122,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, Syntax, StrictLoc, ReplacementExpr.get()); } -/// \brief Parse the contents of the "external_source_symbol" attribute. +/// Parse the contents of the "external_source_symbol" attribute. /// /// external-source-symbol-attribute: /// 'external_source_symbol' '(' keyword-arg-list ')' @@ -1110,7 +1138,7 @@ void Parser::ParseAvailabilityAttribute(IdentifierInfo &Availability, void Parser::ParseExternalSourceSymbolAttribute( IdentifierInfo &ExternalSourceSymbol, SourceLocation Loc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { + SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax) { // Opening '('. BalancedDelimiterTracker T(*this, tok::l_paren); if (T.expectAndConsume()) @@ -1207,7 +1235,7 @@ void Parser::ParseExternalSourceSymbolAttribute( ScopeName, ScopeLoc, Args, llvm::array_lengthof(Args), Syntax); } -/// \brief Parse the contents of the "objc_bridge_related" attribute. +/// Parse the contents of the "objc_bridge_related" attribute. /// objc_bridge_related '(' related_class ',' opt-class_method ',' opt-instance_method ')' /// related_class: /// Identifier @@ -1224,7 +1252,7 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, SourceLocation *endLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax) { + ParsedAttr::Syntax Syntax) { // Opening '('. BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) { @@ -1244,7 +1272,9 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, return; } - // Parse optional class method name. + // Parse class method name. It's non-optional in the sense that a trailing + // comma is required, but it can be the empty string, and then we record a + // nullptr. IdentifierLoc *ClassMethod = nullptr; if (Tok.is(tok::identifier)) { ClassMethod = ParseIdentifierLoc(); @@ -1263,7 +1293,8 @@ void Parser::ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, return; } - // Parse optional instance method name. + // Parse instance method name. Also non-optional but empty string is + // permitted. IdentifierLoc *InstanceMethod = nullptr; if (Tok.is(tok::identifier)) InstanceMethod = ParseIdentifierLoc(); @@ -1335,7 +1366,7 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) { Class.TagOrTemplate); } -/// \brief Parse all attributes in LAs, and attach them to Decl D. +/// Parse all attributes in LAs, and attach them to Decl D. void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, bool EnterScope, bool OnDefinition) { assert(LAs.parseSoon() && @@ -1349,7 +1380,7 @@ void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, LAs.clear(); } -/// \brief Finish parsing an attribute for which parsing was delayed. +/// Finish parsing an attribute for which parsing was delayed. /// This will be called at the end of parsing a class declaration /// for each LateParsedAttribute. We consume the saved tokens and /// create an attribute with the arguments filled in. We add this @@ -1400,7 +1431,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, Actions.ActOnReenterFunctionContext(Actions.CurScope, D); ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, - nullptr, SourceLocation(), AttributeList::AS_GNU, + nullptr, SourceLocation(), ParsedAttr::AS_GNU, nullptr); if (HasFunScope) { @@ -1414,16 +1445,15 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA, // If there are multiple decls, then the decl cannot be within the // function scope. ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc, - nullptr, SourceLocation(), AttributeList::AS_GNU, + nullptr, SourceLocation(), ParsedAttr::AS_GNU, nullptr); } } else { Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName(); } - const AttributeList *AL = Attrs.getList(); - if (OnDefinition && AL && !AL->isCXX11Attribute() && - AL->isKnownToGCC()) + if (OnDefinition && !Attrs.empty() && !Attrs.begin()->isCXX11Attribute() && + Attrs.begin()->isKnownToGCC()) Diag(Tok, diag::warn_attribute_on_function_definition) << &LA.AttrName; @@ -1445,7 +1475,7 @@ void Parser::ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax) { + ParsedAttr::Syntax Syntax) { assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('"); BalancedDelimiterTracker T(*this, tok::l_paren); @@ -1535,7 +1565,7 @@ bool Parser::DiagnoseProhibitedCXX11Attribute() { llvm_unreachable("All cases handled above."); } -/// \brief We have found the opening square brackets of a C++11 +/// We have found the opening square brackets of a C++11 /// attribute-specifier in a location where an attribute is not permitted, but /// we know where the attributes ought to be written. Parse them anyway, and /// provide a fixit moving them to the right place. @@ -1554,29 +1584,27 @@ void Parser::DiagnoseMisplacedCXX11Attribute(ParsedAttributesWithRange &Attrs, << FixItHint::CreateRemoval(AttrRange); } -void Parser::DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs, - const SourceLocation CorrectLocation) { +void Parser::DiagnoseProhibitedAttributes( + const SourceRange &Range, const SourceLocation CorrectLocation) { if (CorrectLocation.isValid()) { - CharSourceRange AttrRange(attrs.Range, true); + CharSourceRange AttrRange(Range, true); Diag(CorrectLocation, diag::err_attributes_misplaced) << FixItHint::CreateInsertionFromRange(CorrectLocation, AttrRange) << FixItHint::CreateRemoval(AttrRange); } else - Diag(attrs.Range.getBegin(), diag::err_attributes_not_allowed) << attrs.Range; + Diag(Range.getBegin(), diag::err_attributes_not_allowed) << Range; } void Parser::ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, unsigned DiagID) { - for (AttributeList *Attr = Attrs.getList(); Attr; Attr = Attr->getNext()) { - if (!Attr->isCXX11Attribute() && !Attr->isC2xAttribute()) + for (const ParsedAttr &AL : Attrs) { + if (!AL.isCXX11Attribute() && !AL.isC2xAttribute()) continue; - if (Attr->getKind() == AttributeList::UnknownAttribute) - Diag(Attr->getLoc(), diag::warn_unknown_attribute_ignored) - << Attr->getName(); + if (AL.getKind() == ParsedAttr::UnknownAttribute) + Diag(AL.getLoc(), diag::warn_unknown_attribute_ignored) << AL.getName(); else { - Diag(Attr->getLoc(), DiagID) - << Attr->getName(); - Attr->setInvalid(); + Diag(AL.getLoc(), DiagID) << AL.getName(); + AL.setInvalid(); } } } @@ -1594,52 +1622,24 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, if (TUK == Sema::TUK_Reference) return; - ParsedAttributes &PA = DS.getAttributes(); - AttributeList *AL = PA.getList(); - AttributeList *Prev = nullptr; - AttributeList *TypeAttrHead = nullptr; - AttributeList *TypeAttrTail = nullptr; - while (AL) { - AttributeList *Next = AL->getNext(); - - if ((AL->getKind() == AttributeList::AT_Aligned && - AL->isDeclspecAttribute()) || - AL->isMicrosoftAttribute()) { - // Stitch the attribute into the tag's attribute list. - if (TypeAttrTail) - TypeAttrTail->setNext(AL); - else - TypeAttrHead = AL; - TypeAttrTail = AL; - TypeAttrTail->setNext(nullptr); - - // Remove the attribute from the variable's attribute list. - if (Prev) { - // Set the last variable attribute's next attribute to be the attribute - // after the current one. - Prev->setNext(Next); - } else { - // Removing the head of the list requires us to reset the head to the - // next attribute. - PA.set(Next); - } - } else { - Prev = AL; - } + llvm::SmallVector<ParsedAttr *, 1> ToBeMoved; - AL = Next; + for (ParsedAttr &AL : DS.getAttributes()) { + if ((AL.getKind() == ParsedAttr::AT_Aligned && + AL.isDeclspecAttribute()) || + AL.isMicrosoftAttribute()) + ToBeMoved.push_back(&AL); } - // Find end of type attributes Attrs and add NewTypeAttributes in the same - // order they were in originally. (Remember, in AttributeList things earlier - // in source order are later in the list, since new attributes are added to - // the front of the list.) - Attrs.addAllAtEnd(TypeAttrHead); + for (ParsedAttr *AL : ToBeMoved) { + DS.getAttributes().remove(AL); + Attrs.addAtEnd(AL); + } } /// ParseDeclaration - Parse a full 'declaration', which consists of /// declaration-specifiers, some number of declarators, and a semicolon. -/// 'Context' should be a Declarator::TheContext value. This returns the +/// 'Context' should be a DeclaratorContext value. This returns the /// location of the semicolon in DeclEnd. /// /// declaration: [C99 6.7] @@ -1653,7 +1653,7 @@ void Parser::stripTypeAttributesOffDeclSpec(ParsedAttributesWithRange &Attrs, /// [C++11/C11] static_assert-declaration /// others... [FIXME] /// -Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, +Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs) { ParenBraceBracketBalancer BalancerRAIIObj(*this); @@ -1666,7 +1666,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, case tok::kw_template: case tok::kw_export: ProhibitAttributes(attrs); - SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd); + SingleDecl = ParseDeclarationStartingWithTemplate(Context, DeclEnd, attrs); break; case tok::kw_inline: // Could be the start of an inline namespace. Allowed as an ext in C++03. @@ -1714,7 +1714,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, /// 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(unsigned Context, +Parser::ParseSimpleDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &Attrs, bool RequireSemi, ForRangeInit *FRI) { @@ -1753,7 +1753,7 @@ Parser::ParseSimpleDeclaration(unsigned Context, /// Returns true if this might be the start of a declarator, or a common typo /// for a declarator. -bool Parser::MightBeDeclarator(unsigned Context) { +bool Parser::MightBeDeclarator(DeclaratorContext Context) { switch (Tok.getKind()) { case tok::annot_cxxscope: case tok::annot_template_id: @@ -1772,11 +1772,12 @@ bool Parser::MightBeDeclarator(unsigned Context) { return getLangOpts().CPlusPlus; case tok::l_square: // Might be an attribute on an unnamed bit-field. - return Context == Declarator::MemberContext && getLangOpts().CPlusPlus11 && - NextToken().is(tok::l_square); + return Context == DeclaratorContext::MemberContext && + getLangOpts().CPlusPlus11 && NextToken().is(tok::l_square); case tok::colon: // Might be a typo for '::' or an unnamed bit-field. - return Context == Declarator::MemberContext || getLangOpts().CPlusPlus; + return Context == DeclaratorContext::MemberContext || + getLangOpts().CPlusPlus; case tok::identifier: switch (NextToken().getKind()) { @@ -1802,8 +1803,9 @@ bool Parser::MightBeDeclarator(unsigned Context) { // At namespace scope, 'identifier:' is probably a typo for 'identifier::' // and in block scope it's probably a label. Inside a class definition, // this is a bit-field. - return Context == Declarator::MemberContext || - (getLangOpts().CPlusPlus && Context == Declarator::FileContext); + return Context == DeclaratorContext::MemberContext || + (getLangOpts().CPlusPlus && + Context == DeclaratorContext::FileContext); case tok::identifier: // Possible virt-specifier. return getLangOpts().CPlusPlus11 && isCXX11VirtSpecifier(NextToken()); @@ -1902,11 +1904,11 @@ void Parser::SkipMalformedDecl() { /// definition or a group of object declarations, actually parse the /// result. Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, - unsigned Context, + DeclaratorContext Context, SourceLocation *DeclEnd, ForRangeInit *FRI) { // Parse the first declarator. - ParsingDeclarator D(*this, DS, static_cast<Declarator::TheContext>(Context)); + ParsingDeclarator D(*this, DS, Context); ParseDeclarator(D); // Bail out if the first declarator didn't seem well-formed. @@ -1953,7 +1955,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, // Function definitions are only allowed at file scope and in C++ classes. // The C++ inline method definition case is handled elsewhere, so we only // need to handle the file scope definition case. - if (Context == Declarator::FileContext) { + if (Context == DeclaratorContext::FileContext) { if (isStartOfFunctionDefinition(D)) { if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { Diag(Tok, diag::err_function_declared_typedef); @@ -2008,8 +2010,13 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, } Decl *ThisDecl = Actions.ActOnDeclarator(getCurScope(), D); - if (IsForRangeLoop) + if (IsForRangeLoop) { Actions.ActOnCXXForRangeDecl(ThisDecl); + } else { + // Obj-C for loop + if (auto *VD = dyn_cast_or_null<VarDecl>(ThisDecl)) + VD->setObjCForDecl(true); + } Actions.FinalizeDeclaration(ThisDecl); D.complete(ThisDecl); return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, ThisDecl); @@ -2024,7 +2031,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, if (FirstDecl) DeclsInGroup.push_back(FirstDecl); - bool ExpectSemi = Context != Declarator::ForContext; + bool ExpectSemi = Context != DeclaratorContext::ForContext; // If we don't have a comma, it is either the end of the list (a ';') or an // error, bail out. @@ -2070,7 +2077,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS, *DeclEnd = Tok.getLocation(); if (ExpectSemi && - ExpectAndConsumeSemi(Context == Declarator::FileContext + ExpectAndConsumeSemi(Context == DeclaratorContext::FileContext ? diag::err_invalid_token_after_toplevel_declarator : diag::err_expected_semi_declaration)) { // Okay, there was no semicolon and one was expected. If we see a @@ -2105,7 +2112,7 @@ bool Parser::ParseAsmAttributesAfterDeclarator(Declarator &D) { return false; } -/// \brief Parse 'declaration' after parsing 'declaration-specifiers +/// Parse 'declaration' after parsing 'declaration-specifiers /// declarator'. This method parses the remainder of the declaration /// (including any attributes or initializer, among other things) and /// finalizes the declaration. @@ -2199,7 +2206,7 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( // FIXME: This check should be for a variable template instantiation only. // Check that this is a valid instantiation - if (D.getName().getKind() != UnqualifiedId::IK_TemplateId) { + if (D.getName().getKind() != UnqualifiedIdKind::IK_TemplateId) { // If the declarator-id is not a template-id, issue a diagnostic and // recover by ignoring the 'template' keyword. Diag(Tok, diag::err_template_defn_explicit_instantiation) @@ -2273,8 +2280,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( if (Init.isInvalid()) { SmallVector<tok::TokenKind, 2> StopTokens; StopTokens.push_back(tok::comma); - if (D.getContext() == Declarator::ForContext || - D.getContext() == Declarator::InitStmtContext) + if (D.getContext() == DeclaratorContext::ForContext || + D.getContext() == DeclaratorContext::InitStmtContext) StopTokens.push_back(tok::r_paren); SkipUntil(StopTokens, StopAtSemi | StopBeforeMatch); Actions.ActOnInitializerError(ThisDecl); @@ -2397,7 +2404,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, } // Issue diagnostic and remove constexpr specfier if present. - if (DS.isConstexprSpecified() && DSC != DSC_condition) { + if (DS.isConstexprSpecified() && DSC != DeclSpecContext::DSC_condition) { Diag(DS.getConstexprSpecLoc(), diag::err_typename_invalid_constexpr); DS.ClearConstexprSpec(); } @@ -2444,7 +2451,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, SourceLocation Loc = Tok.getLocation(); // If we see an identifier that is not a type name, we normally would - // parse it as the identifer being declared. However, when a typename + // parse it as the identifier being declared. However, when a typename // is typo'd or the definition is not included, this will incorrectly // parse the typename as the identifier name and fall over misparsing // later parts of the diagnostic. @@ -2486,7 +2493,7 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // classes. if (ParsedType T = Actions.ActOnMSVCUnknownTypeName( *Tok.getIdentifierInfo(), Tok.getLocation(), - DSC == DSC_template_type_arg)) { + DSC == DeclSpecContext::DSC_template_type_arg)) { const char *PrevSpec; unsigned DiagID; DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, DiagID, T, @@ -2540,18 +2547,20 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // Parse this as a tag as if the missing tag were present. if (TagKind == tok::kw_enum) - ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, DSC_normal); + ParseEnumSpecifier(Loc, DS, TemplateInfo, AS, + DeclSpecContext::DSC_normal); else ParseClassSpecifier(TagKind, Loc, DS, TemplateInfo, AS, - /*EnteringContext*/ false, DSC_normal, Attrs); + /*EnteringContext*/ false, + DeclSpecContext::DSC_normal, Attrs); return true; } } // Determine whether this identifier could plausibly be the name of something // being declared (with a missing type). - if (!isTypeSpecifier(DSC) && - (!SS || DSC == DSC_top_level || DSC == DSC_class)) { + if (!isTypeSpecifier(DSC) && (!SS || DSC == DeclSpecContext::DSC_top_level || + DSC == DeclSpecContext::DSC_class)) { // Look ahead to the next token to try to figure out what this declaration // was supposed to be. switch (NextToken().getKind()) { @@ -2575,7 +2584,8 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, // If we're in a context where we could be declaring a constructor, // check whether this is a constructor declaration with a bogus name. - if (DSC == DSC_class || (DSC == DSC_top_level && SS)) { + if (DSC == DeclSpecContext::DSC_class || + (DSC == DeclSpecContext::DSC_top_level && SS)) { IdentifierInfo *II = Tok.getIdentifierInfo(); if (Actions.isCurrentClassNameTypo(II, SS)) { Diag(Loc, diag::err_constructor_bad_name) @@ -2651,27 +2661,29 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, return false; } -/// \brief Determine the declaration specifier context from the declarator +/// Determine the declaration specifier context from the declarator /// context. /// /// \param Context the declarator context, which is one of the -/// Declarator::TheContext enumerator values. +/// DeclaratorContext enumerator values. Parser::DeclSpecContext -Parser::getDeclSpecContextFromDeclaratorContext(unsigned Context) { - if (Context == Declarator::MemberContext) - return DSC_class; - if (Context == Declarator::FileContext) - return DSC_top_level; - if (Context == Declarator::TemplateParamContext) - return DSC_template_param; - if (Context == Declarator::TemplateTypeArgContext) - return DSC_template_type_arg; - if (Context == Declarator::TrailingReturnContext) - return DSC_trailing; - if (Context == Declarator::AliasDeclContext || - Context == Declarator::AliasTemplateContext) - return DSC_alias_declaration; - return DSC_normal; +Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) { + if (Context == DeclaratorContext::MemberContext) + return DeclSpecContext::DSC_class; + if (Context == DeclaratorContext::FileContext) + return DeclSpecContext::DSC_top_level; + if (Context == DeclaratorContext::TemplateParamContext) + return DeclSpecContext::DSC_template_param; + if (Context == DeclaratorContext::TemplateArgContext || + Context == DeclaratorContext::TemplateTypeArgContext) + return DeclSpecContext::DSC_template_type_arg; + if (Context == DeclaratorContext::TrailingReturnContext || + Context == DeclaratorContext::TrailingReturnVarContext) + return DeclSpecContext::DSC_trailing; + if (Context == DeclaratorContext::AliasDeclContext || + Context == DeclaratorContext::AliasTemplateContext) + return DeclSpecContext::DSC_alias_declaration; + return DeclSpecContext::DSC_normal; } /// ParseAlignArgument - Parse the argument to an alignment-specifier. @@ -2735,7 +2747,7 @@ void Parser::ParseAlignmentSpecifier(ParsedAttributes &Attrs, ArgsVector ArgExprs; ArgExprs.push_back(ArgExpr.get()); Attrs.addNew(KWName, KWLoc, nullptr, KWLoc, ArgExprs.data(), 1, - AttributeList::AS_Keyword, EllipsisLoc); + ParsedAttr::AS_Keyword, EllipsisLoc); } /// Determine whether we're looking at something that might be a declarator @@ -2751,7 +2763,8 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, LateParsedAttrList *LateAttrs) { assert(DS.hasTagDefinition() && "shouldn't call this"); - bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level); + bool EnteringContext = (DSContext == DeclSpecContext::DSC_class || + DSContext == DeclSpecContext::DSC_top_level); if (getLangOpts().CPlusPlus && Tok.isOneOf(tok::identifier, tok::coloncolon, tok::kw_decltype, @@ -2845,6 +2858,17 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, return false; } +// Choose the apprpriate diagnostic error for why fixed point types are +// disabled, set the previous specifier, and mark as invalid. +static void SetupFixedPointError(const LangOptions &LangOpts, + const char *&PrevSpec, unsigned &DiagID, + bool &isInvalid) { + assert(!LangOpts.FixedPoint); + DiagID = diag::err_fixed_point_not_enabled; + PrevSpec = ""; // Not used by diagnostic + isInvalid = true; +} + /// ParseDeclarationSpecifiers /// declaration-specifiers: [C99 6.7] /// storage-class-specifier declaration-specifiers[opt] @@ -2885,7 +2909,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, DS.SetRangeEnd(SourceLocation()); } - bool EnteringContext = (DSContext == DSC_class || DSContext == DSC_top_level); + bool EnteringContext = (DSContext == DeclSpecContext::DSC_class || + DSContext == DeclSpecContext::DSC_top_level); bool AttrsLastTime = false; ParsedAttributesWithRange attrs(AttrFactory); // We use Sema's policy to get bool macros right. @@ -2955,8 +2980,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, Scope::FunctionPrototypeScope | Scope::AtCatchScope)) == 0; bool AllowNestedNameSpecifiers - = DSContext == DSC_top_level || - (DSContext == DSC_class && DS.isFriendSpecified()); + = DSContext == DeclSpecContext::DSC_top_level || + (DSContext == DeclSpecContext::DSC_class && DS.isFriendSpecified()); Actions.CodeCompleteDeclSpec(getCurScope(), DS, AllowNonIdentifiers, @@ -2967,9 +2992,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (getCurScope()->getFnParent() || getCurScope()->getBlockParent()) CCC = Sema::PCC_LocalDeclarationSpecifiers; else if (TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) - CCC = DSContext == DSC_class? Sema::PCC_MemberTemplate - : Sema::PCC_Template; - else if (DSContext == DSC_class) + CCC = DSContext == DeclSpecContext::DSC_class ? Sema::PCC_MemberTemplate + : Sema::PCC_Template; + else if (DSContext == DeclSpecContext::DSC_class) CCC = Sema::PCC_Class; else if (CurParsedObjCImpl) CCC = Sema::PCC_ObjCImplementation; @@ -3013,10 +3038,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // To improve diagnostics for this case, parse the declaration as a // constructor (and reject the extra template arguments later). TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Next); - if ((DSContext == DSC_top_level || DSContext == DSC_class) && + if ((DSContext == DeclSpecContext::DSC_top_level || + DSContext == DeclSpecContext::DSC_class) && TemplateId->Name && Actions.isCurrentClassName(*TemplateId->Name, getCurScope(), &SS) && - isConstructorDeclarator(/*Unqualified*/false)) { + isConstructorDeclarator(/*Unqualified*/ false)) { // The user meant this to be an out-of-line constructor // definition, but template arguments are not allowed // there. Just allow this as a constructor; we'll @@ -3055,7 +3081,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Check whether this is a constructor declaration. If we're in a // context where the identifier could be a class name, and it has the // shape of a constructor declaration, process it as one. - if ((DSContext == DSC_top_level || DSContext == DSC_class) && + if ((DSContext == DeclSpecContext::DSC_top_level || + DSContext == DeclSpecContext::DSC_class) && Actions.isCurrentClassName(*Next.getIdentifierInfo(), getCurScope(), &SS) && isConstructorDeclarator(/*Unqualified*/ false)) @@ -3193,7 +3220,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, if (DS.isTypeAltiVecVector()) goto DoneWithDeclSpec; - if (DSContext == DSC_objc_method_result && isObjCInstancetype()) { + if (DSContext == DeclSpecContext::DSC_objc_method_result && + isObjCInstancetype()) { ParsedType TypeRep = Actions.ActOnObjCInstanceType(Loc); assert(TypeRep); isInvalid = DS.SetTypeSpecType(DeclSpec::TST_typename, Loc, PrevSpec, @@ -3206,6 +3234,13 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, continue; } + // If we're in a context where the identifier could be a class name, + // check whether this is a constructor declaration. + if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class && + Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) && + isConstructorDeclarator(/*Unqualified*/true)) + goto DoneWithDeclSpec; + ParsedType TypeRep = Actions.getTypeName( *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), nullptr, false, false, nullptr, false, false, @@ -3225,17 +3260,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, goto DoneWithDeclSpec; } - // If we're in a context where the identifier could be a class name, - // check whether this is a constructor declaration. - if (getLangOpts().CPlusPlus && DSContext == DSC_class && - Actions.isCurrentClassName(*Tok.getIdentifierInfo(), getCurScope()) && - isConstructorDeclarator(/*Unqualified*/true)) - goto DoneWithDeclSpec; - // Likewise, if this is a context where the identifier could be a template // name, check whether this is a deduction guide declaration. if (getLangOpts().CPlusPlus17 && - (DSContext == DSC_class || DSContext == DSC_top_level) && + (DSContext == DeclSpecContext::DSC_class || + DSContext == DeclSpecContext::DSC_top_level) && Actions.isDeductionGuideName(getCurScope(), *Tok.getIdentifierInfo(), Tok.getLocation()) && isConstructorDeclarator(/*Unqualified*/ true, @@ -3281,7 +3310,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // If we're in a context where the template-id could be a // constructor name or specialization, check whether this is a // constructor declaration. - if (getLangOpts().CPlusPlus && DSContext == DSC_class && + if (getLangOpts().CPlusPlus && DSContext == DeclSpecContext::DSC_class && Actions.isCurrentClassName(*TemplateId->Name, getCurScope()) && isConstructorDeclarator(TemplateId->SS.isEmpty())) goto DoneWithDeclSpec; @@ -3308,7 +3337,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = Tok.getLocation(); DS.getAttributes().addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, - nullptr, 0, AttributeList::AS_Keyword); + nullptr, 0, ParsedAttr::AS_Keyword); break; } @@ -3351,7 +3380,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // Objective-C 'kindof' types. case tok::kw___kindof: DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc, - nullptr, 0, AttributeList::AS_Keyword); + nullptr, 0, ParsedAttr::AS_Keyword); (void)ConsumeToken(); continue; @@ -3419,6 +3448,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw_thread_local: isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS_thread_local, Loc, PrevSpec, DiagID); + isStorageClass = true; break; case tok::kw__Thread_local: isInvalid = DS.SetStorageClassSpecThread(DeclSpec::TSCS__Thread_local, @@ -3431,7 +3461,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.setFunctionSpecInline(Loc, PrevSpec, DiagID); break; case tok::kw_virtual: - isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID); + // OpenCL C++ v1.0 s2.9: the virtual function qualifier is not supported. + if (getLangOpts().OpenCLCPlusPlus) { + DiagID = diag::err_openclcxx_virtual_function; + PrevSpec = Tok.getIdentifierInfo()->getNameStart(); + isInvalid = true; + } + else { + isInvalid = DS.setFunctionSpecVirtual(Loc, PrevSpec, DiagID); + } break; case tok::kw_explicit: isInvalid = DS.setFunctionSpecExplicit(Loc, PrevSpec, DiagID); @@ -3451,7 +3489,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // friend case tok::kw_friend: - if (DSContext == DSC_class) + if (DSContext == DeclSpecContext::DSC_class) isInvalid = DS.SetFriendSpec(Loc, PrevSpec, DiagID); else { PrevSpec = ""; // not actually used by the diagnostic @@ -3535,6 +3573,29 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float16, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw__Accum: + if (!getLangOpts().FixedPoint) { + SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid); + } else { + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_accum, Loc, PrevSpec, + DiagID, Policy); + } + break; + case tok::kw__Fract: + if (!getLangOpts().FixedPoint) { + SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid); + } else { + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_fract, Loc, PrevSpec, + DiagID, Policy); + } + break; + case tok::kw__Sat: + if (!getLangOpts().FixedPoint) { + SetupFixedPointError(getLangOpts(), PrevSpec, DiagID, isInvalid); + } else { + isInvalid = DS.SetTypeSpecSat(Loc, PrevSpec, DiagID); + } + break; case tok::kw___float128: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_float128, Loc, PrevSpec, DiagID, Policy); @@ -3543,6 +3604,10 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, isInvalid = DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw_char8_t: + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char8, Loc, PrevSpec, + DiagID, Policy); + break; case tok::kw_char16_t: isInvalid = DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID, Policy); @@ -3703,11 +3768,25 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, getLangOpts()); break; - // OpenCL qualifiers: + // OpenCL access qualifiers: + case tok::kw___read_only: + case tok::kw___write_only: + case tok::kw___read_write: + // OpenCL C++ 1.0 s2.2: access qualifiers are reserved keywords. + if (Actions.getLangOpts().OpenCLCPlusPlus) { + DiagID = diag::err_openclcxx_reserved; + PrevSpec = Tok.getIdentifierInfo()->getNameStart(); + isInvalid = true; + } + ParseOpenCLQualifiers(DS.getAttributes()); + break; + + // OpenCL address space qualifiers: case tok::kw___generic: // generic address space is introduced only in OpenCL v2.0 // see OpenCL C Spec v2.0 s6.5.5 - if (Actions.getLangOpts().OpenCLVersion < 200) { + if (Actions.getLangOpts().OpenCLVersion < 200 && + !Actions.getLangOpts().OpenCLCPlusPlus) { DiagID = diag::err_opencl_unknown_type_specifier; PrevSpec = Tok.getIdentifierInfo()->getNameStart(); isInvalid = true; @@ -3718,9 +3797,6 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, case tok::kw___global: case tok::kw___local: case tok::kw___constant: - case tok::kw___read_only: - case tok::kw___write_only: - case tok::kw___read_write: ParseOpenCLQualifiers(DS.getAttributes()); break; @@ -3758,18 +3834,17 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, Diag(Tok, DiagID) << PrevSpec << FixItHint::CreateRemoval(Tok.getLocation()); else if (DiagID == diag::err_opencl_unknown_type_specifier) { - const int OpenCLVer = getLangOpts().OpenCLVersion; - std::string VerSpec = llvm::to_string(OpenCLVer / 100) + - std::string (".") + - llvm::to_string((OpenCLVer % 100) / 10); - Diag(Tok, DiagID) << VerSpec << PrevSpec << isStorageClass; + Diag(Tok, DiagID) << getLangOpts().OpenCLCPlusPlus + << getLangOpts().getOpenCLVersionTuple().getAsString() + << PrevSpec << isStorageClass; } else Diag(Tok, DiagID) << PrevSpec; } DS.SetRangeEnd(Tok.getLocation()); if (DiagID != diag::err_bool_redeclaration) - ConsumeToken(); + // After an error the next token can be an annotation token. + ConsumeAnyToken(); AttrsLastTime = false; } @@ -3878,7 +3953,7 @@ void Parser::ParseStructDeclaration( /// void Parser::ParseStructUnionBody(SourceLocation RecordLoc, unsigned TagType, Decl *TagDecl) { - PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc, + PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc, "parsing struct/union body"); assert(!getLangOpts().CPlusPlus && "C++ declarations not supported"); @@ -3984,10 +4059,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, // If attributes exist after struct contents, parse them. MaybeParseGNUAttributes(attrs); - Actions.ActOnFields(getCurScope(), - RecordLoc, TagDecl, FieldDecls, - T.getOpenLocation(), T.getCloseLocation(), - attrs.getList()); + Actions.ActOnFields(getCurScope(), RecordLoc, TagDecl, FieldDecls, + T.getOpenLocation(), T.getCloseLocation(), attrs); StructScope.Exit(); Actions.ActOnTagFinishDefinition(getCurScope(), TagDecl, T.getRange()); } @@ -4070,7 +4143,7 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, SuppressAccessChecks diagsFromTag(*this, shouldDelayDiagsInTag); // Enum definitions should not be parsed in a trailing-return-type. - bool AllowDeclaration = DSC != DSC_trailing; + bool AllowDeclaration = DSC != DeclSpecContext::DSC_trailing; bool AllowFixedUnderlyingType = AllowDeclaration && (getLangOpts().CPlusPlus11 || getLangOpts().MicrosoftExt || @@ -4296,14 +4369,14 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, bool IsDependent = false; const char *PrevSpec = nullptr; unsigned DiagID; - Decl *TagDecl = Actions.ActOnTag(getCurScope(), DeclSpec::TST_enum, TUK, - StartLoc, SS, Name, NameLoc, attrs.getList(), - AS, DS.getModulePrivateSpecLoc(), TParams, - Owned, IsDependent, ScopedEnumKWLoc, - IsScopedUsingClassTag, BaseType, - DSC == DSC_type_specifier, - DSC == DSC_template_param || - DSC == DSC_template_type_arg, &SkipBody); + Decl *TagDecl = Actions.ActOnTag( + getCurScope(), DeclSpec::TST_enum, TUK, StartLoc, SS, Name, NameLoc, + attrs, AS, DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, + ScopedEnumKWLoc, IsScopedUsingClassTag, BaseType, + DSC == DeclSpecContext::DSC_type_specifier, + DSC == DeclSpecContext::DSC_template_param || + DSC == DeclSpecContext::DSC_template_type_arg, + &SkipBody); if (SkipBody.ShouldSkip) { assert(TUK == Sema::TUK_Definition && "can only skip a definition"); @@ -4440,8 +4513,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { // Install the enumerator constant into EnumDecl. Decl *EnumConstDecl = Actions.ActOnEnumConstant( - getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, - attrs.getList(), EqualLoc, AssignedVal.get()); + getCurScope(), EnumDecl, LastEnumConstDecl, IdentLoc, Ident, attrs, + EqualLoc, AssignedVal.get()); EnumAvailabilityDiags.back().done(); EnumConstantDecls.push_back(EnumConstDecl); @@ -4493,10 +4566,8 @@ void Parser::ParseEnumBody(SourceLocation StartLoc, Decl *EnumDecl) { ParsedAttributes attrs(AttrFactory); MaybeParseGNUAttributes(attrs); - Actions.ActOnEnumBody(StartLoc, T.getRange(), - EnumDecl, EnumConstantDecls, - getCurScope(), - attrs.getList()); + Actions.ActOnEnumBody(StartLoc, T.getRange(), EnumDecl, EnumConstantDecls, + getCurScope(), attrs); // Now handle enum constant availability diagnostics. assert(EnumConstantDecls.size() == EnumAvailabilityDiags.size()); @@ -4540,12 +4611,15 @@ bool Parser::isKnownToBeTypeSpecifier(const Token &Tok) const { case tok::kw_void: case tok::kw_char: case tok::kw_wchar_t: + case tok::kw_char8_t: case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw_int: case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Accum: + case tok::kw__Fract: case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: @@ -4616,12 +4690,15 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_void: case tok::kw_char: case tok::kw_wchar_t: + case tok::kw_char8_t: case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw_int: case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Accum: + case tok::kw__Fract: case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: @@ -4645,6 +4722,7 @@ bool Parser::isTypeSpecifierQualifier() { case tok::kw_const: case tok::kw_volatile: case tok::kw_restrict: + case tok::kw__Sat: // Debugger support. case tok::kw___unknown_anytype: @@ -4772,6 +4850,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_void: case tok::kw_char: case tok::kw_wchar_t: + case tok::kw_char8_t: case tok::kw_char16_t: case tok::kw_char32_t: @@ -4779,6 +4858,8 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_half: case tok::kw_float: case tok::kw_double: + case tok::kw__Accum: + case tok::kw__Fract: case tok::kw__Float16: case tok::kw___float128: case tok::kw_bool: @@ -4800,6 +4881,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw_const: case tok::kw_volatile: case tok::kw_restrict: + case tok::kw__Sat: // function-specifier case tok::kw_inline: @@ -5089,7 +5171,7 @@ void Parser::ParseTypeQualifierListOpt( getLangOpts()); break; case tok::kw___uptr: - // GNU libc headers in C mode use '__uptr' as an identifer which conflicts + // GNU libc headers in C mode use '__uptr' as an identifier which conflicts // with the MS modifier keyword. if ((AttrReqs & AR_DeclspecAttributesParsed) && !getLangOpts().CPlusPlus && IdentifierRequired && DS.isEmpty() && NextToken().is(tok::semi)) { @@ -5129,7 +5211,7 @@ void Parser::ParseTypeQualifierListOpt( // Objective-C 'kindof' types. case tok::kw___kindof: DS.getAttributes().addNew(Tok.getIdentifierInfo(), Loc, nullptr, Loc, - nullptr, 0, AttributeList::AS_Keyword); + nullptr, 0, ParsedAttr::AS_Keyword); (void)ConsumeToken(); continue; @@ -5175,7 +5257,7 @@ void Parser::ParseDeclarator(Declarator &D) { } static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, - unsigned TheContext) { + DeclaratorContext TheContext) { if (Kind == tok::star || Kind == tok::caret) return true; @@ -5194,8 +5276,9 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang, // (The same thing can in theory happen after a trailing-return-type, but // since those are a C++11 feature, there is no rejects-valid issue there.) if (Kind == tok::ampamp) - return Lang.CPlusPlus11 || (TheContext != Declarator::ConversionIdContext && - TheContext != Declarator::CXXNewContext); + return Lang.CPlusPlus11 || + (TheContext != DeclaratorContext::ConversionIdContext && + TheContext != DeclaratorContext::CXXNewContext); return false; } @@ -5249,8 +5332,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, (Tok.is(tok::identifier) && (NextToken().is(tok::coloncolon) || NextToken().is(tok::less))) || Tok.is(tok::annot_cxxscope))) { - bool EnteringContext = D.getContext() == Declarator::FileContext || - D.getContext() == Declarator::MemberContext; + bool EnteringContext = + D.getContext() == DeclaratorContext::FileContext || + D.getContext() == DeclaratorContext::MemberContext; CXXScopeSpec SS; ParseOptionalCXXScopeSpecifier(SS, nullptr, EnteringContext); @@ -5278,10 +5362,10 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Sema will have to catch (syntactically invalid) pointers into global // scope. It has to catch pointers into namespace scope anyway. - D.AddTypeInfo(DeclaratorChunk::getMemberPointer(SS,DS.getTypeQualifiers(), - DS.getLocEnd()), - DS.getAttributes(), - /* Don't replace range end. */SourceLocation()); + D.AddTypeInfo(DeclaratorChunk::getMemberPointer( + SS, DS.getTypeQualifiers(), DS.getLocEnd()), + std::move(DS.getAttributes()), + /* Don't replace range end. */ SourceLocation()); return; } } @@ -5294,7 +5378,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, D.AddTypeInfo( DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()), - DS.getAttributes(), SourceLocation()); + std::move(DS.getAttributes()), SourceLocation()); } // Not a pointer, C++ reference, or block. @@ -5316,9 +5400,9 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // GNU attributes are not allowed here in a new-type-id, but Declspec and // C++11 attributes are allowed. unsigned Reqs = AR_CXX11AttributesParsed | AR_DeclspecAttributesParsed | - ((D.getContext() != Declarator::CXXNewContext) - ? AR_GNUAttributesParsed - : AR_GNUAttributesParsedAndRejected); + ((D.getContext() != DeclaratorContext::CXXNewContext) + ? AR_GNUAttributesParsed + : AR_GNUAttributesParsedAndRejected); ParseTypeQualifierListOpt(DS, Reqs, true, !D.mayOmitIdentifier()); D.ExtendWithDeclSpec(DS); @@ -5326,20 +5410,16 @@ void Parser::ParseDeclaratorInternal(Declarator &D, ParseDeclaratorInternal(D, DirectDeclParser); if (Kind == tok::star) // Remember that we parsed a pointer type, and remember the type-quals. - D.AddTypeInfo(DeclaratorChunk::getPointer(DS.getTypeQualifiers(), Loc, - DS.getConstSpecLoc(), - DS.getVolatileSpecLoc(), - DS.getRestrictSpecLoc(), - DS.getAtomicSpecLoc(), - DS.getUnalignedSpecLoc()), - DS.getAttributes(), - SourceLocation()); + D.AddTypeInfo(DeclaratorChunk::getPointer( + DS.getTypeQualifiers(), Loc, DS.getConstSpecLoc(), + DS.getVolatileSpecLoc(), DS.getRestrictSpecLoc(), + DS.getAtomicSpecLoc(), DS.getUnalignedSpecLoc()), + std::move(DS.getAttributes()), SourceLocation()); else // Remember that we parsed a Block type, and remember the type-quals. - D.AddTypeInfo(DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), - Loc), - DS.getAttributes(), - SourceLocation()); + D.AddTypeInfo( + DeclaratorChunk::getBlockPointer(DS.getTypeQualifiers(), Loc), + std::move(DS.getAttributes()), SourceLocation()); } else { // Is a reference DeclSpec DS(AttrFactory); @@ -5394,8 +5474,7 @@ void Parser::ParseDeclaratorInternal(Declarator &D, // Remember that we parsed a reference type. D.AddTypeInfo(DeclaratorChunk::getReference(DS.getTypeQualifiers(), Loc, Kind == tok::amp), - DS.getAttributes(), - SourceLocation()); + std::move(DS.getAttributes()), SourceLocation()); } } @@ -5470,15 +5549,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // Don't parse FOO:BAR as if it were a typo for FOO::BAR inside a class, in // this context it is a bitfield. Also in range-based for statement colon // may delimit for-range-declaration. - ColonProtectionRAIIObject X(*this, - D.getContext() == Declarator::MemberContext || - (D.getContext() == Declarator::ForContext && - getLangOpts().CPlusPlus11)); + ColonProtectionRAIIObject X( + *this, D.getContext() == DeclaratorContext::MemberContext || + (D.getContext() == DeclaratorContext::ForContext && + getLangOpts().CPlusPlus11)); // ParseDeclaratorInternal might already have parsed the scope. if (D.getCXXScopeSpec().isEmpty()) { - bool EnteringContext = D.getContext() == Declarator::FileContext || - D.getContext() == Declarator::MemberContext; + bool EnteringContext = + D.getContext() == DeclaratorContext::FileContext || + D.getContext() == DeclaratorContext::MemberContext; ParseOptionalCXXScopeSpecifier(D.getCXXScopeSpec(), nullptr, EnteringContext); } @@ -5507,9 +5587,9 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // been expanded or contains auto; otherwise, it is parsed as part of the // parameter-declaration-clause. if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() && - !((D.getContext() == Declarator::PrototypeContext || - D.getContext() == Declarator::LambdaExprParameterContext || - D.getContext() == Declarator::BlockLiteralContext) && + !((D.getContext() == DeclaratorContext::PrototypeContext || + D.getContext() == DeclaratorContext::LambdaExprParameterContext || + D.getContext() == DeclaratorContext::BlockLiteralContext) && NextToken().is(tok::r_paren) && !D.hasGroupingParens() && !Actions.containsUnexpandedParameterPacks(D) && @@ -5541,22 +5621,22 @@ void Parser::ParseDirectDeclarator(Declarator &D) { AllowDeductionGuide = false; } else if (D.getCXXScopeSpec().isSet()) { AllowConstructorName = - (D.getContext() == Declarator::FileContext || - D.getContext() == Declarator::MemberContext); + (D.getContext() == DeclaratorContext::FileContext || + D.getContext() == DeclaratorContext::MemberContext); AllowDeductionGuide = false; } else { - AllowConstructorName = (D.getContext() == Declarator::MemberContext); + AllowConstructorName = + (D.getContext() == DeclaratorContext::MemberContext); AllowDeductionGuide = - (D.getContext() == Declarator::FileContext || - D.getContext() == Declarator::MemberContext); + (D.getContext() == DeclaratorContext::FileContext || + D.getContext() == DeclaratorContext::MemberContext); } - SourceLocation TemplateKWLoc; bool HadScope = D.getCXXScopeSpec().isValid(); if (ParseUnqualifiedId(D.getCXXScopeSpec(), /*EnteringContext=*/true, /*AllowDestructorName=*/true, AllowConstructorName, - AllowDeductionGuide, nullptr, TemplateKWLoc, + AllowDeductionGuide, nullptr, nullptr, D.getName()) || // Once we're past the identifier, if the scope was bad, mark the // whole declarator bad. @@ -5604,15 +5684,16 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // An identifier within parens is unlikely to be intended to be anything // other than a name being "declared". DiagnoseIdentifier = true; - else if (D.getContext() == Declarator::TemplateTypeArgContext) + else if (D.getContext() == DeclaratorContext::TemplateArgContext) // T<int N> is an accidental identifier; T<int N indicates a missing '>'. DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::greater, tok::greatergreater); - else if (D.getContext() == Declarator::AliasDeclContext || - D.getContext() == Declarator::AliasTemplateContext) + else if (D.getContext() == DeclaratorContext::AliasDeclContext || + D.getContext() == DeclaratorContext::AliasTemplateContext) // The most likely error is that the ';' was forgotten. DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi); - else if (D.getContext() == Declarator::TrailingReturnContext && + else if ((D.getContext() == DeclaratorContext::TrailingReturnContext || + D.getContext() == DeclaratorContext::TrailingReturnVarContext) && !isCXX11VirtSpecifier(Tok)) DiagnoseIdentifier = NextToken().isOneOf( tok::comma, tok::semi, tok::equal, tok::l_brace, tok::kw_try); @@ -5626,6 +5707,18 @@ void Parser::ParseDirectDeclarator(Declarator &D) { } if (Tok.is(tok::l_paren)) { + // If this might be an abstract-declarator followed by a direct-initializer, + // check whether this is a valid declarator chunk. If it can't be, assume + // that it's an initializer instead. + if (D.mayOmitIdentifier() && D.mayBeFollowedByCXXDirectInit()) { + RevertingTentativeParsingAction PA(*this); + if (TryParseDeclarator(true, D.mayHaveIdentifier(), true) == + TPResult::False) { + D.SetIdentifier(nullptr, Tok.getLocation()); + goto PastIdentifier; + } + } + // direct-declarator: '(' declarator ')' // direct-declarator: '(' attributes declarator ')' // Example: 'char (*X)' or 'int (*XX)(void)' @@ -5659,7 +5752,7 @@ void Parser::ParseDirectDeclarator(Declarator &D) { LLVM_BUILTIN_TRAP; if (Tok.is(tok::l_square)) return ParseMisplacedBracketDeclarator(D); - if (D.getContext() == Declarator::MemberContext) { + if (D.getContext() == DeclaratorContext::MemberContext) { // Objective-C++: Detect C++ keywords and try to prevent further errors by // treating these keyword as valid member names. if (getLangOpts().ObjC1 && getLangOpts().CPlusPlus && @@ -5889,9 +5982,9 @@ void Parser::ParseParenDeclarator(Declarator &D) { ParseDeclaratorInternal(D, &Parser::ParseDirectDeclarator); // Match the ')'. T.consumeClose(); - D.AddTypeInfo(DeclaratorChunk::getParen(T.getOpenLocation(), - T.getCloseLocation()), - attrs, T.getCloseLocation()); + D.AddTypeInfo( + DeclaratorChunk::getParen(T.getOpenLocation(), T.getCloseLocation()), + std::move(attrs), T.getCloseLocation()); D.setGroupingParens(hadGroupingParens); @@ -6042,9 +6135,9 @@ void Parser::ParseFunctionDeclarator(Declarator &D, bool IsCXX11MemberFunction = getLangOpts().CPlusPlus11 && D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && - (D.getContext() == Declarator::MemberContext + (D.getContext() == DeclaratorContext::MemberContext ? !D.getDeclSpec().isFriendSpecified() - : D.getContext() == Declarator::FileContext && + : D.getContext() == DeclaratorContext::FileContext && D.getCXXScopeSpec().isValid() && Actions.CurContext->isRecord()); Sema::CXXThisScopeRAII ThisScope(Actions, @@ -6096,7 +6189,8 @@ void Parser::ParseFunctionDeclarator(Declarator &D, StartLoc = D.getDeclSpec().getTypeSpecTypeLoc(); LocalEndLoc = Tok.getLocation(); SourceRange Range; - TrailingReturnType = ParseTrailingReturnType(Range); + TrailingReturnType = + ParseTrailingReturnType(Range, D.mayBeFollowedByCXXDirectInit()); EndLoc = Range.getEnd(); } } else if (standardAttributesAllowed()) { @@ -6120,28 +6214,19 @@ void Parser::ParseFunctionDeclarator(Declarator &D, } // Remember that we parsed a function type, and remember the attributes. - D.AddTypeInfo(DeclaratorChunk::getFunction(HasProto, - IsAmbiguous, - LParenLoc, - ParamInfo.data(), ParamInfo.size(), - EllipsisLoc, RParenLoc, - DS.getTypeQualifiers(), - RefQualifierIsLValueRef, - RefQualifierLoc, ConstQualifierLoc, - VolatileQualifierLoc, - RestrictQualifierLoc, - /*MutableLoc=*/SourceLocation(), - ESpecType, ESpecRange, - DynamicExceptions.data(), - DynamicExceptionRanges.data(), - DynamicExceptions.size(), - NoexceptExpr.isUsable() ? - NoexceptExpr.get() : nullptr, - ExceptionSpecTokens, - DeclsInPrototype, - StartLoc, LocalEndLoc, D, - TrailingReturnType), - FnAttrs, EndLoc); + D.AddTypeInfo(DeclaratorChunk::getFunction( + HasProto, IsAmbiguous, LParenLoc, ParamInfo.data(), + ParamInfo.size(), EllipsisLoc, RParenLoc, + DS.getTypeQualifiers(), RefQualifierIsLValueRef, + RefQualifierLoc, ConstQualifierLoc, VolatileQualifierLoc, + RestrictQualifierLoc, + /*MutableLoc=*/SourceLocation(), ESpecType, ESpecRange, + DynamicExceptions.data(), DynamicExceptionRanges.data(), + DynamicExceptions.size(), + NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, + ExceptionSpecTokens, DeclsInPrototype, StartLoc, + LocalEndLoc, D, TrailingReturnType), + std::move(FnAttrs), EndLoc); } /// ParseRefQualifier - Parses a member function ref-qualifier. Returns @@ -6309,10 +6394,10 @@ void Parser::ParseParameterDeclarationClause( // Parse the declarator. This is "PrototypeContext" or // "LambdaExprParameterContext", because we must accept either // 'declarator' or 'abstract-declarator' here. - Declarator ParmDeclarator(DS, - D.getContext() == Declarator::LambdaExprContext ? - Declarator::LambdaExprParameterContext : - Declarator::PrototypeContext); + Declarator ParmDeclarator( + DS, D.getContext() == DeclaratorContext::LambdaExprContext + ? DeclaratorContext::LambdaExprParameterContext + : DeclaratorContext::PrototypeContext); ParseDeclarator(ParmDeclarator); // Parse GNU attributes, if present. @@ -6355,7 +6440,7 @@ void Parser::ParseParameterDeclarationClause( SourceLocation EqualLoc = Tok.getLocation(); // Parse the default argument - if (D.getContext() == Declarator::MemberContext) { + if (D.getContext() == DeclaratorContext::MemberContext) { // If we're inside a class definition, cache the tokens // corresponding to the default argument. We'll actually parse // them when we see the end of the class definition. @@ -6463,7 +6548,7 @@ void Parser::ParseBracketDeclarator(Declarator &D) { D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, nullptr, T.getOpenLocation(), T.getCloseLocation()), - attrs, T.getCloseLocation()); + std::move(attrs), T.getCloseLocation()); return; } else if (Tok.getKind() == tok::numeric_constant && GetLookAheadToken(1).is(tok::r_square)) { @@ -6476,11 +6561,10 @@ void Parser::ParseBracketDeclarator(Declarator &D) { MaybeParseCXX11Attributes(attrs); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, - ExprRes.get(), + D.AddTypeInfo(DeclaratorChunk::getArray(0, false, false, ExprRes.get(), T.getOpenLocation(), T.getCloseLocation()), - attrs, T.getCloseLocation()); + std::move(attrs), T.getCloseLocation()); return; } else if (Tok.getKind() == tok::code_completion) { Actions.CodeCompleteBracketDeclarator(getCurScope()); @@ -6553,12 +6637,11 @@ void Parser::ParseBracketDeclarator(Declarator &D) { MaybeParseCXX11Attributes(DS.getAttributes()); // Remember that we parsed a array type, and remember its features. - D.AddTypeInfo(DeclaratorChunk::getArray(DS.getTypeQualifiers(), - StaticLoc.isValid(), isStar, - NumElements.get(), - T.getOpenLocation(), - T.getCloseLocation()), - DS.getAttributes(), T.getCloseLocation()); + D.AddTypeInfo( + DeclaratorChunk::getArray(DS.getTypeQualifiers(), StaticLoc.isValid(), + isStar, NumElements.get(), T.getOpenLocation(), + T.getCloseLocation()), + std::move(DS.getAttributes()), T.getCloseLocation()); } /// Diagnose brackets before an identifier. @@ -6610,18 +6693,15 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) { if (NeedParens) { // Create a DeclaratorChunk for the inserted parens. - ParsedAttributes attrs(AttrFactory); SourceLocation EndLoc = PP.getLocForEndOfToken(D.getLocEnd()); - D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), attrs, + D.AddTypeInfo(DeclaratorChunk::getParen(SuggestParenLoc, EndLoc), SourceLocation()); } // Adding back the bracket info to the end of the Declarator. for (unsigned i = 0, e = TempDeclarator.getNumTypeObjects(); i < e; ++i) { const DeclaratorChunk &Chunk = TempDeclarator.getTypeObject(i); - ParsedAttributes attrs(AttrFactory); - attrs.set(Chunk.Common.AttrList); - D.AddTypeInfo(Chunk, attrs, SourceLocation()); + D.AddTypeInfo(Chunk, SourceLocation()); } // The missing identifier would have been diagnosed in ParseDirectDeclarator. |