diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp | 535 |
1 files changed, 300 insertions, 235 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp b/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp index 127e18439b8e..4f6bb08bdc64 100644 --- a/contrib/llvm/tools/clang/lib/Parse/ParseDecl.cpp +++ b/contrib/llvm/tools/clang/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; @@ -54,7 +53,7 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, // 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,47 +1622,19 @@ 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 @@ -1666,7 +1666,7 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(DeclaratorContext 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. @@ -2010,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); @@ -2107,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. @@ -2446,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. @@ -2656,7 +2661,7 @@ 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 @@ -2669,9 +2674,11 @@ Parser::getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context) { return DeclSpecContext::DSC_top_level; if (Context == DeclaratorContext::TemplateParamContext) return DeclSpecContext::DSC_template_param; - if (Context == DeclaratorContext::TemplateTypeArgContext) + if (Context == DeclaratorContext::TemplateArgContext || + Context == DeclaratorContext::TemplateTypeArgContext) return DeclSpecContext::DSC_template_type_arg; - if (Context == DeclaratorContext::TrailingReturnContext) + if (Context == DeclaratorContext::TrailingReturnContext || + Context == DeclaratorContext::TrailingReturnVarContext) return DeclSpecContext::DSC_trailing; if (Context == DeclaratorContext::AliasDeclContext || Context == DeclaratorContext::AliasTemplateContext) @@ -2740,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 @@ -2851,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] @@ -3216,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, @@ -3235,13 +3260,6 @@ 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 == DeclSpecContext::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 && @@ -3319,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; } @@ -3362,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; @@ -3430,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, @@ -3442,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); @@ -3546,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); @@ -3554,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); @@ -3714,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; @@ -3729,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; @@ -3769,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; } @@ -3889,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"); @@ -3995,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()); } @@ -4309,8 +4371,8 @@ void Parser::ParseEnumSpecifier(SourceLocation StartLoc, DeclSpec &DS, 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, + 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, @@ -4451,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); @@ -4504,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()); @@ -4551,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: @@ -4627,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: @@ -4656,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: @@ -4783,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: @@ -4790,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: @@ -4811,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: @@ -5100,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)) { @@ -5140,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; @@ -5291,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; } } @@ -5307,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. @@ -5339,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); @@ -5407,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()); } } @@ -5566,12 +5632,11 @@ void Parser::ParseDirectDeclarator(Declarator &D) { 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. @@ -5619,7 +5684,7 @@ 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() == DeclaratorContext::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); @@ -5627,7 +5692,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) { D.getContext() == DeclaratorContext::AliasTemplateContext) // The most likely error is that the ';' was forgotten. DiagnoseIdentifier = NextToken().isOneOf(tok::comma, tok::semi); - else if (D.getContext() == DeclaratorContext::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); @@ -5641,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)' @@ -5904,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); @@ -6111,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()) { @@ -6135,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 @@ -6478,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)) { @@ -6491,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()); @@ -6568,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. @@ -6625,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. |