diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/Parse | |
parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) | |
download | src-486754660bb926339aefcf012a3f848592babb8b.tar.gz src-486754660bb926339aefcf012a3f848592babb8b.zip |
Vendor import of clang trunk r338150:vendor/clang/clang-trunk-r338150
Notes
Notes:
svn path=/vendor/clang/dist/; revision=336815
svn path=/vendor/clang/clang-trunk-r338150/; revision=336816; tag=vendor/clang/clang-trunk-r338150
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseAST.cpp | 18 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 24 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 738 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 283 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 208 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 348 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 197 | ||||
-rw-r--r-- | lib/Parse/ParseOpenMP.cpp | 319 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 208 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 74 | ||||
-rw-r--r-- | lib/Parse/ParseStmtAsm.cpp | 2 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 383 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 63 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 81 |
14 files changed, 1723 insertions, 1223 deletions
diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp index d018d4c08ed9..696506099e58 100644 --- a/lib/Parse/ParseAST.cpp +++ b/lib/Parse/ParseAST.cpp @@ -21,6 +21,7 @@ #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaConsumer.h" +#include "clang/Sema/TemplateInstCallback.h" #include "llvm/Support/CrashRecoveryContext.h" #include <cstdio> #include <memory> @@ -121,6 +122,10 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { bool OldCollectStats = PrintStats; std::swap(OldCollectStats, S.CollectStats); + // Initialize the template instantiation observer chain. + // FIXME: See note on "finalize" below. + initialize(S.TemplateInstCallbacks, S); + ASTConsumer *Consumer = &S.getASTConsumer(); std::unique_ptr<Parser> ParseOP( @@ -136,6 +141,12 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { CleanupParser(ParseOP.get()); S.getPreprocessor().EnterMainSourceFile(); + if (!S.getPreprocessor().getCurrentLexer()) { + // If a PCH through header is specified that does not have an include in + // the source, there won't be any tokens or a Lexer. + return; + } + P.Initialize(); Parser::DeclGroupPtrTy ADecl; @@ -158,6 +169,13 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { Consumer->HandleTranslationUnit(S.getASTContext()); + // Finalize the template instantiation observer chain. + // FIXME: This (and init.) should be done in the Sema class, but because + // Sema does not have a reliable "Finalize" function (it has a + // destructor, but it is not guaranteed to be called ("-disable-free")). + // So, do the initialization above and do the finalization here: + finalize(S.TemplateInstCallbacks, S); + std::swap(OldCollectStats, S.CollectStats); if (PrintStats) { llvm::errs() << "\nSTATISTICS:\n"; diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index 2b3d4ba85bd8..27d48be0e3eb 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -22,12 +22,10 @@ using namespace clang; /// ParseCXXInlineMethodDef - We parsed and verified that the specified /// Declarator is a well formed C++ inline method definition. Now lex its body /// and store its tokens for parsing after the C++ class is complete. -NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, - AttributeList *AccessAttrs, - ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS, - SourceLocation PureSpecLoc) { +NamedDecl *Parser::ParseCXXInlineMethodDef( + AccessSpecifier AS, ParsedAttributes &AccessAttrs, ParsingDeclarator &D, + const ParsedTemplateInfo &TemplateInfo, const VirtSpecifiers &VS, + SourceLocation PureSpecLoc) { assert(D.isFunctionDeclarator() && "This isn't a function declarator!"); assert(Tok.isOneOf(tok::l_brace, tok::colon, tok::kw_try, tok::equal) && "Current token not a '{', ':', '=', or 'try'!"); @@ -312,6 +310,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { Actions.ActOnDelayedCXXMethodParameter(getCurScope(), Param); std::unique_ptr<CachedTokens> Toks = std::move(LM.DefaultArgs[I].Toks); if (Toks) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Mark the end of the default argument so that we know when to stop when // we parse it later on. Token LastDefaultArgToken = Toks->back(); @@ -384,6 +384,8 @@ void Parser::ParseLexedMethodDeclaration(LateParsedMethodDeclaration &LM) { // Parse a delayed exception-specification, if there is one. if (CachedTokens *Toks = LM.ExceptionSpecTokens) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Add the 'stop' token. Token LastExceptionSpecToken = Toks->back(); Token ExceptionSpecEnd; @@ -489,6 +491,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) { ++CurTemplateDepthTracker; } + ParenBraceBracketBalancer BalancerRAIIObj(*this); + assert(!LM.Toks.empty() && "Empty body!"); Token LastBodyToken = LM.Toks.back(); Token BodyEnd; @@ -609,6 +613,8 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { if (!MI.Field || MI.Field->isInvalidDecl()) return; + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Append the current token at the end of the new token stream so that it // doesn't get lost. MI.Toks.push_back(Tok); @@ -733,7 +739,7 @@ bool Parser::ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, } } -/// \brief Consume tokens and store them in the passed token container until +/// Consume tokens and store them in the passed token container until /// we've passed the try keyword and constructor initializers and have consumed /// the opening brace of the function body. The opening brace will be consumed /// if and only if there was no error. @@ -937,7 +943,7 @@ bool Parser::ConsumeAndStoreFunctionPrologue(CachedTokens &Toks) { } } -/// \brief Consume and store tokens from the '?' to the ':' in a conditional +/// Consume and store tokens from the '?' to the ':' in a conditional /// expression. bool Parser::ConsumeAndStoreConditional(CachedTokens &Toks) { // Consume '?'. @@ -962,7 +968,7 @@ bool Parser::ConsumeAndStoreConditional(CachedTokens &Toks) { return true; } -/// \brief A tentative parsing action that can also revert token annotations. +/// A tentative parsing action that can also revert token annotations. class Parser::UnannotatedTentativeParsingAction : public TentativeParsingAction { public: explicit UnannotatedTentativeParsingAction(Parser &Self, 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. diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 44e7a3512098..7c4c83d032b6 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -14,6 +14,7 @@ #include "clang/Parse/Parser.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/CharInfo.h" #include "clang/Basic/OperatorKinds.h" @@ -22,7 +23,6 @@ #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" -#include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallString.h" @@ -55,7 +55,7 @@ using namespace clang; /// namespace-alias-definition: [C++ 7.3.2: namespace.alias] /// 'namespace' identifier '=' qualified-namespace-specifier ';' /// -Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context, +Parser::DeclGroupPtrTy Parser::ParseNamespace(DeclaratorContext Context, SourceLocation &DeclEnd, SourceLocation InlineLoc) { assert(Tok.is(tok::kw_namespace) && "Not a namespace!"); @@ -183,13 +183,12 @@ Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context, ParseScope NamespaceScope(this, Scope::DeclScope); UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; - Decl *NamespcDecl = - Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc, - IdentLoc, Ident, T.getOpenLocation(), - attrs.getList(), ImplicitUsingDirectiveDecl); + Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( + getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident, + T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl); - PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc, - "parsing namespace"); + PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl, + NamespaceLoc, "parsing namespace"); // Parse the contents of the namespace. This includes parsing recovery on // any improperly nested namespaces. @@ -233,11 +232,10 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc, // desugaring it here. ParseScope NamespaceScope(this, Scope::DeclScope); UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; - Decl *NamespcDecl = - Actions.ActOnStartNamespaceDef(getCurScope(), SourceLocation(), - NamespaceLoc[index], IdentLoc[index], - Ident[index], Tracker.getOpenLocation(), - attrs.getList(), ImplicitUsingDirectiveDecl); + Decl *NamespcDecl = Actions.ActOnStartNamespaceDef( + getCurScope(), SourceLocation(), NamespaceLoc[index], IdentLoc[index], + Ident[index], Tracker.getOpenLocation(), attrs, + ImplicitUsingDirectiveDecl); assert(!ImplicitUsingDirectiveDecl && "nested namespace definition cannot define anonymous namespace"); @@ -307,7 +305,7 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, /// 'extern' string-literal '{' declaration-seq[opt] '}' /// 'extern' string-literal declaration /// -Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, unsigned Context) { +Decl *Parser::ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context) { assert(isTokenStringLiteral() && "Not a string literal!"); ExprResult Lang = ParseStringLiteralExpression(false); @@ -434,7 +432,7 @@ Decl *Parser::ParseExportDeclaration() { /// ParseUsingDirectiveOrDeclaration - Parse C++ using using-declaration or /// using-directive. Assumes that current token is 'using'. Parser::DeclGroupPtrTy -Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, +Parser::ParseUsingDirectiveOrDeclaration(DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs) { @@ -482,7 +480,7 @@ Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, /// 'using' 'namespace' ::[opt] nested-name-specifier[opt] /// namespace-name attributes[opt] ; /// -Decl *Parser::ParseUsingDirective(unsigned Context, +Decl *Parser::ParseUsingDirective(DeclaratorContext Context, SourceLocation UsingLoc, SourceLocation &DeclEnd, ParsedAttributes &attrs) { @@ -543,7 +541,7 @@ Decl *Parser::ParseUsingDirective(unsigned Context, SkipUntil(tok::semi); return Actions.ActOnUsingDirective(getCurScope(), UsingLoc, NamespcLoc, SS, - IdentLoc, NamespcName, attrs.getList()); + IdentLoc, NamespcName, attrs); } /// Parse a using-declarator (or the identifier in a C++11 alias-declaration). @@ -551,7 +549,8 @@ Decl *Parser::ParseUsingDirective(unsigned Context, /// using-declarator: /// 'typename'[opt] nested-name-specifier unqualified-id /// -bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) { +bool Parser::ParseUsingDeclarator(DeclaratorContext Context, + UsingDeclarator &D) { D.clear(); // Ignore optional 'typename'. @@ -582,7 +581,8 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) { // or the simple-template-id's template-name in the last component of the // nested-name-specifier, the name is [...] considered to name the // constructor. - if (getLangOpts().CPlusPlus11 && Context == Declarator::MemberContext && + if (getLangOpts().CPlusPlus11 && + Context == DeclaratorContext::MemberContext && Tok.is(tok::identifier) && (NextToken().is(tok::semi) || NextToken().is(tok::comma) || NextToken().is(tok::ellipsis)) && @@ -600,7 +600,7 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) { /*AllowConstructorName=*/!(Tok.is(tok::identifier) && NextToken().is(tok::equal)), /*AllowDeductionGuide=*/false, - nullptr, D.TemplateKWLoc, D.Name)) + nullptr, nullptr, D.Name)) return true; } @@ -629,7 +629,7 @@ bool Parser::ParseUsingDeclarator(unsigned Context, UsingDeclarator &D) { /// 'using' identifier attribute-specifier-seq[opt] = type-id ; /// Parser::DeclGroupPtrTy -Parser::ParseUsingDeclaration(unsigned Context, +Parser::ParseUsingDeclaration(DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, SourceLocation &DeclEnd, AccessSpecifier AS) { @@ -699,7 +699,7 @@ Parser::ParseUsingDeclaration(unsigned Context, // "typename" keyword is allowed for identifiers only, // because it may be a type definition. if (D.TypenameLoc.isValid() && - D.Name.getKind() != UnqualifiedId::IK_Identifier) { + D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) { Diag(D.Name.getSourceRange().getBegin(), diag::err_typename_identifiers_only) << FixItHint::CreateRemoval(SourceRange(D.TypenameLoc)); @@ -709,7 +709,7 @@ Parser::ParseUsingDeclaration(unsigned Context, Decl *UD = Actions.ActOnUsingDeclaration(getCurScope(), AS, UsingLoc, D.TypenameLoc, D.SS, D.Name, - D.EllipsisLoc, Attrs.getList()); + D.EllipsisLoc, Attrs); if (UD) DeclsInGroup.push_back(UD); } @@ -753,7 +753,7 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( // Type alias templates cannot be specialized. int SpecKind = -1; if (TemplateInfo.Kind == ParsedTemplateInfo::Template && - D.Name.getKind() == UnqualifiedId::IK_TemplateId) + D.Name.getKind() == UnqualifiedIdKind::IK_TemplateId) SpecKind = 0; if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitSpecialization) SpecKind = 1; @@ -773,7 +773,7 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( } // Name must be an identifier. - if (D.Name.getKind() != UnqualifiedId::IK_Identifier) { + if (D.Name.getKind() != UnqualifiedIdKind::IK_Identifier) { Diag(D.Name.StartLocation, diag::err_alias_declaration_not_identifier); // No removal fixit: can't recover from this. SkipUntil(tok::semi); @@ -791,11 +791,11 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( << FixItHint::CreateRemoval(SourceRange(D.EllipsisLoc)); Decl *DeclFromDeclSpec = nullptr; - TypeResult TypeAlias = - ParseTypeName(nullptr, - TemplateInfo.Kind ? Declarator::AliasTemplateContext - : Declarator::AliasDeclContext, - AS, &DeclFromDeclSpec, &Attrs); + TypeResult TypeAlias = ParseTypeName( + nullptr, + TemplateInfo.Kind ? DeclaratorContext::AliasTemplateContext + : DeclaratorContext::AliasDeclContext, + AS, &DeclFromDeclSpec, &Attrs); if (OwnedType) *OwnedType = DeclFromDeclSpec; @@ -811,8 +811,8 @@ Decl *Parser::ParseAliasDeclarationAfterDeclarator( TemplateParams ? TemplateParams->data() : nullptr, TemplateParams ? TemplateParams->size() : 0); return Actions.ActOnAliasDeclaration(getCurScope(), AS, TemplateParamsArg, - UsingLoc, D.Name, Attrs.getList(), - TypeAlias, DeclFromDeclSpec); + UsingLoc, D.Name, Attrs, TypeAlias, + DeclFromDeclSpec); } /// ParseStaticAssertDeclaration - Parse C++0x or C11 static_assert-declaration. @@ -940,7 +940,7 @@ SourceLocation Parser::ParseDecltypeSpecifier(DeclSpec &DS) { // The operand of the decltype specifier is an unevaluated operand. EnterExpressionEvaluationContext Unevaluated( Actions, Sema::ExpressionEvaluationContext::Unevaluated, nullptr, - /*IsDecltype=*/true); + Sema::ExpressionEvaluationContextRecord::EK_Decltype); Result = Actions.CorrectDelayedTyposInExpr(ParseExpression(), [](Expr *E) { return E->hasPlaceholderType() ? ExprError() : E; @@ -1094,7 +1094,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, EndLocation = ParseDecltypeSpecifier(DS); - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext); return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } @@ -1195,7 +1195,7 @@ TypeResult Parser::ParseBaseTypeSpecifier(SourceLocation &BaseLoc, DS.SetTypeSpecType(TST_typename, IdLoc, PrevSpec, DiagID, Type, Actions.getASTContext().getPrintingPolicy()); - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext); return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } @@ -1206,7 +1206,7 @@ void Parser::ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs) { IdentifierInfo *AttrName = Tok.getIdentifierInfo(); SourceLocation AttrNameLoc = ConsumeToken(); attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_Keyword); + ParsedAttr::AS_Keyword); } } @@ -1612,14 +1612,15 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // new struct s; // or // &T::operator struct s; - // For these, DSC is DSC_type_specifier or DSC_alias_declaration. + // For these, DSC is DeclSpecContext::DSC_type_specifier or + // DeclSpecContext::DSC_alias_declaration. // If there are attributes after class name, parse them. MaybeParseCXX11Attributes(Attributes); const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); Sema::TagUseKind TUK; - if (DSC == DSC_trailing) + if (DSC == DeclSpecContext::DSC_trailing) TUK = Sema::TUK_Reference; else if (Tok.is(tok::l_brace) || (getLangOpts().CPlusPlus && Tok.is(tok::colon)) || @@ -1749,24 +1750,16 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // This is an explicit instantiation of a class template. ProhibitAttributes(attrs); - TagOrTempResult - = Actions.ActOnExplicitInstantiation(getCurScope(), - TemplateInfo.ExternLoc, - TemplateInfo.TemplateLoc, - TagType, - StartLoc, - SS, - TemplateId->Template, - TemplateId->TemplateNameLoc, - TemplateId->LAngleLoc, - TemplateArgsPtr, - TemplateId->RAngleLoc, - attrs.getList()); - - // Friend template-ids are treated as references unless - // they have template headers, in which case they're ill-formed - // (FIXME: "template <class T> friend class A<T>::B<int>;"). - // We diagnose this error in ActOnClassTemplateSpecialization. + TagOrTempResult = Actions.ActOnExplicitInstantiation( + getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, + TagType, StartLoc, SS, TemplateId->Template, + TemplateId->TemplateNameLoc, TemplateId->LAngleLoc, TemplateArgsPtr, + TemplateId->RAngleLoc, attrs); + + // Friend template-ids are treated as references unless + // they have template headers, in which case they're ill-formed + // (FIXME: "template <class T> friend class A<T>::B<int>;"). + // We diagnose this error in ActOnClassTemplateSpecialization. } else if (TUK == Sema::TUK_Reference || (TUK == Sema::TUK_Friend && TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate)) { @@ -1822,7 +1815,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // Build the class template specialization. TagOrTempResult = Actions.ActOnClassTemplateSpecialization( getCurScope(), TagType, TUK, StartLoc, DS.getModulePrivateSpecLoc(), - *TemplateId, attrs.getList(), + *TemplateId, attrs, MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, TemplateParams ? TemplateParams->size() : 0), @@ -1837,24 +1830,18 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // ProhibitAttributes(attrs); - TagOrTempResult - = Actions.ActOnExplicitInstantiation(getCurScope(), - TemplateInfo.ExternLoc, - TemplateInfo.TemplateLoc, - TagType, StartLoc, SS, Name, - NameLoc, attrs.getList()); + TagOrTempResult = Actions.ActOnExplicitInstantiation( + getCurScope(), TemplateInfo.ExternLoc, TemplateInfo.TemplateLoc, + TagType, StartLoc, SS, Name, NameLoc, attrs); } else if (TUK == Sema::TUK_Friend && TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate) { ProhibitAttributes(attrs); - TagOrTempResult = - Actions.ActOnTemplatedFriendTag(getCurScope(), DS.getFriendSpecLoc(), - TagType, StartLoc, SS, - Name, NameLoc, attrs.getList(), - MultiTemplateParamsArg( - TemplateParams? &(*TemplateParams)[0] - : nullptr, - TemplateParams? TemplateParams->size() : 0)); + TagOrTempResult = Actions.ActOnTemplatedFriendTag( + getCurScope(), DS.getFriendSpecLoc(), TagType, StartLoc, SS, Name, + NameLoc, attrs, + MultiTemplateParamsArg(TemplateParams ? &(*TemplateParams)[0] : nullptr, + TemplateParams ? TemplateParams->size() : 0)); } else { if (TUK != Sema::TUK_Declaration && TUK != Sema::TUK_Definition) ProhibitAttributes(attrs); @@ -1881,15 +1868,14 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, stripTypeAttributesOffDeclSpec(attrs, DS, TUK); // Declaration or definition of a class type - TagOrTempResult = Actions.ActOnTag(getCurScope(), TagType, TUK, StartLoc, - SS, Name, NameLoc, attrs.getList(), AS, - DS.getModulePrivateSpecLoc(), - TParams, Owned, IsDependent, - SourceLocation(), false, - clang::TypeResult(), - DSC == DSC_type_specifier, - DSC == DSC_template_param || - DSC == DSC_template_type_arg, &SkipBody); + TagOrTempResult = Actions.ActOnTag( + getCurScope(), TagType, TUK, StartLoc, SS, Name, NameLoc, attrs, AS, + DS.getModulePrivateSpecLoc(), TParams, Owned, IsDependent, + SourceLocation(), false, clang::TypeResult(), + DSC == DeclSpecContext::DSC_type_specifier, + DSC == DeclSpecContext::DSC_template_param || + DSC == DeclSpecContext::DSC_template_type_arg, + &SkipBody); // If ActOnTag said the type was dependent, try again with the // less common call. @@ -1927,7 +1913,7 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, if (!TagOrTempResult.isInvalid()) // Delayed processing of attributes. - Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs.getList()); + Actions.ProcessDeclAttributeDelayed(TagOrTempResult.get(), attrs); const char *PrevSpec = nullptr; unsigned DiagID; @@ -2107,7 +2093,7 @@ AccessSpecifier Parser::getAccessSpecifierIfPresent() const { } } -/// \brief If the given declarator has any parts for which parsing has to be +/// If the given declarator has any parts for which parsing has to be /// delayed, e.g., default arguments or an exception-specification, create a /// late-parsed method declaration record to handle the parsing at the end of /// the class definition. @@ -2247,7 +2233,7 @@ bool Parser::isCXX11FinalKeyword() const { Specifier == VirtSpecifiers::VS_Sealed; } -/// \brief Parse a C++ member-declarator up to, but not including, the optional +/// Parse a C++ member-declarator up to, but not including, the optional /// brace-or-equal-initializer or pure-specifier. bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( Declarator &DeclaratorInfo, VirtSpecifiers &VS, ExprResult &BitfieldSize, @@ -2298,12 +2284,10 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( if (!VS.isUnset()) { // If we saw any GNU-style attributes that are known to GCC followed by a // virt-specifier, issue a GCC-compat warning. - const AttributeList *Attr = DeclaratorInfo.getAttributes(); - while (Attr) { - if (Attr->isKnownToGCC() && !Attr->isCXX11Attribute()) - Diag(Attr->getLoc(), diag::warn_gcc_attribute_location); - Attr = Attr->getNext(); - } + for (const ParsedAttr &AL : DeclaratorInfo.getAttributes()) + if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) + Diag(AL.getLoc(), diag::warn_gcc_attribute_location); + MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(DeclaratorInfo, VS); } } @@ -2318,7 +2302,7 @@ bool Parser::ParseCXXMemberDeclaratorBeforeInitializer( return false; } -/// \brief Look for declaration specifiers possibly occurring after C++11 +/// Look for declaration specifiers possibly occurring after C++11 /// virt-specifier-seq and diagnose them. void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( Declarator &D, @@ -2422,7 +2406,7 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( /// Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, - AttributeList *AccessAttrs, + ParsedAttributes &AccessAttrs, const ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { if (Tok.is(tok::at)) { @@ -2474,7 +2458,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SourceLocation TemplateKWLoc; UnqualifiedId Name; if (ParseUnqualifiedId(SS, false, true, true, false, nullptr, - TemplateKWLoc, Name)) { + &TemplateKWLoc, Name)) { SkipUntil(tok::semi); return nullptr; } @@ -2486,10 +2470,12 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return nullptr; } + // FIXME: We should do something with the 'template' keyword here. return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration( getCurScope(), AS, /*UsingLoc*/ SourceLocation(), /*TypenameLoc*/ SourceLocation(), SS, Name, - /*EllipsisLoc*/ SourceLocation(), /*AttrList*/ nullptr))); + /*EllipsisLoc*/ SourceLocation(), + /*AttrList*/ ParsedAttributesView()))); } } @@ -2509,7 +2495,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SourceLocation DeclEnd; return DeclGroupPtrTy::make( DeclGroupRef(ParseTemplateDeclarationOrSpecialization( - Declarator::MemberContext, DeclEnd, AS, AccessAttrs))); + DeclaratorContext::MemberContext, DeclEnd, AccessAttrs, AS))); } // Handle: member-declaration ::= '__extension__' member-declaration @@ -2522,12 +2508,12 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } ParsedAttributesWithRange attrs(AttrFactory); - ParsedAttributesWithRange FnAttrs(AttrFactory); + ParsedAttributesViewWithRange FnAttrs; // Optional C++11 attribute-specifier MaybeParseCXX11Attributes(attrs); // We need to keep these attributes for future diagnostic // before they are taken over by declaration specifier. - FnAttrs.addAll(attrs.getList()); + FnAttrs.addAll(attrs.begin(), attrs.end()); FnAttrs.Range = attrs.Range; MaybeParseMicrosoftAttributes(attrs); @@ -2545,7 +2531,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } SourceLocation DeclEnd; // Otherwise, it must be a using-declaration or an alias-declaration. - return ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo, + return ParseUsingDeclaration(DeclaratorContext::MemberContext, TemplateInfo, UsingLoc, DeclEnd, AS); } @@ -2559,7 +2545,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (MalformedTypeSpec) DS.SetTypeSpecError(); - ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC_class, + ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DeclSpecContext::DSC_class, &CommonLateParsedAttrs); // Turn off colon protection that was set for declspec. @@ -2569,7 +2555,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // may get this far before the problem becomes obvious. if (DS.hasTagDefinition() && TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate && - DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_class, + DiagnoseMissingSemiAfterTagDefinition(DS, AS, DeclSpecContext::DSC_class, &CommonLateParsedAttrs)) return nullptr; @@ -2593,7 +2579,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, return Actions.ConvertDeclToDeclGroup(TheDecl); } - ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext); + ParsingDeclarator DeclaratorInfo(*this, DS, DeclaratorContext::MemberContext); VirtSpecifiers VS; // Hold late-parsed attributes so we can attach a Decl to them later. @@ -2774,7 +2760,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // initialize it. ThisDecl = VT->getTemplatedDecl(); - if (ThisDecl && AccessAttrs) + if (ThisDecl) Actions.ProcessDeclAttributeList(getCurScope(), ThisDecl, AccessAttrs); } @@ -2852,7 +2838,7 @@ Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, break; if (Tok.isAtStartOfLine() && - !MightBeDeclarator(Declarator::MemberContext)) { + !MightBeDeclarator(DeclaratorContext::MemberContext)) { // This comma was followed by a line-break and something which can't be // the start of a declarator. The comma was probably a typo for a // semicolon. @@ -3006,10 +2992,12 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs, DeclSpec::TST TagType, Decl *TagDecl) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + switch (Tok.getKind()) { case tok::kw___if_exists: case tok::kw___if_not_exists: - ParseMicrosoftIfExistsClassDeclaration(TagType, AS); + ParseMicrosoftIfExistsClassDeclaration(TagType, AccessAttrs, AS); return nullptr; case tok::semi: @@ -3075,8 +3063,7 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( Diag(ASLoc, diag::err_access_specifier_interface) << (AS == AS_protected); } - if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, - AccessAttrs.getList())) { + if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, AccessAttrs)) { // found another attribute than only annotations AccessAttrs.clear(); } @@ -3089,7 +3076,7 @@ Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( TagDecl); default: - return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList()); + return ParseCXXClassMemberDeclaration(AS, AccessAttrs); } } @@ -3108,7 +3095,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, TagType == DeclSpec::TST_union || TagType == DeclSpec::TST_class) && "Invalid TagType!"); - PrettyDeclStackTraceEntry CrashInfo(Actions, TagDecl, RecordLoc, + PrettyDeclStackTraceEntry CrashInfo(Actions.Context, TagDecl, RecordLoc, "parsing struct/union/class body"); // Determine whether this is a non-nested class. Note that local @@ -3277,9 +3264,8 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, if (TagDecl) Actions.ActOnFinishCXXMemberSpecification(getCurScope(), RecordLoc, TagDecl, - T.getOpenLocation(), - T.getCloseLocation(), - attrs.getList()); + T.getOpenLocation(), + T.getCloseLocation(), attrs); // C++11 [class.mem]p2: // Within the class member-specification, the class is regarded as complete @@ -3502,7 +3488,7 @@ MemInitResult Parser::ParseMemInitializer(Decl *ConstructorDecl) { return Diag(Tok, diag::err_expected) << tok::l_paren; } -/// \brief Parse a C++ exception-specification if present (C++0x [except.spec]). +/// Parse a C++ exception-specification if present (C++0x [except.spec]). /// /// exception-specification: /// dynamic-exception-specification @@ -3583,15 +3569,11 @@ Parser::tryParseExceptionSpecification(bool Delayed, // There is an argument. BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); - NoexceptType = EST_ComputedNoexcept; NoexceptExpr = ParseConstantExpression(); T.consumeClose(); - // The argument must be contextually convertible to bool. We use - // CheckBooleanCondition for this purpose. - // FIXME: Add a proper Sema entry point for this. if (!NoexceptExpr.isInvalid()) { - NoexceptExpr = - Actions.CheckBooleanCondition(KeywordLoc, NoexceptExpr.get()); + NoexceptExpr = Actions.ActOnNoexceptSpec(KeywordLoc, NoexceptExpr.get(), + NoexceptType); NoexceptRange = SourceRange(KeywordLoc, T.getCloseLocation()); } else { NoexceptType = EST_BasicNoexcept; @@ -3704,15 +3686,18 @@ ExceptionSpecificationType Parser::ParseDynamicExceptionSpecification( /// ParseTrailingReturnType - Parse a trailing return type on a new-style /// function declaration. -TypeResult Parser::ParseTrailingReturnType(SourceRange &Range) { +TypeResult Parser::ParseTrailingReturnType(SourceRange &Range, + bool MayBeFollowedByDirectInit) { assert(Tok.is(tok::arrow) && "expected arrow"); ConsumeToken(); - return ParseTypeName(&Range, Declarator::TrailingReturnContext); + return ParseTypeName(&Range, MayBeFollowedByDirectInit + ? DeclaratorContext::TrailingReturnVarContext + : DeclaratorContext::TrailingReturnContext); } -/// \brief We have just started parsing the definition of a new class, +/// We have just started parsing the definition of a new class, /// so push that class onto our stack of classes that is currently /// being parsed. Sema::ParsingClassState @@ -3724,7 +3709,7 @@ Parser::PushParsingClass(Decl *ClassDecl, bool NonNestedClass, return Actions.PushParsingClass(); } -/// \brief Deallocate the given parsed class and all of its nested +/// Deallocate the given parsed class and all of its nested /// classes. void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) { for (unsigned I = 0, N = Class->LateParsedDeclarations.size(); I != N; ++I) @@ -3732,7 +3717,7 @@ void Parser::DeallocateParsedClasses(Parser::ParsingClass *Class) { delete Class; } -/// \brief Pop the top class of the stack of classes that are +/// Pop the top class of the stack of classes that are /// currently being parsed. /// /// This routine should be called when we have finished parsing the @@ -3770,7 +3755,7 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) { Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope(); } -/// \brief Try to parse an 'identifier' which appears within an attribute-token. +/// Try to parse an 'identifier' which appears within an attribute-token. /// /// \return the parsed identifier on success, and 0 if the next token is not an /// attribute-token. @@ -3818,16 +3803,15 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) { static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, IdentifierInfo *ScopeName) { - switch (AttributeList::getKind(AttrName, ScopeName, - AttributeList::AS_CXX11)) { - case AttributeList::AT_CarriesDependency: - case AttributeList::AT_Deprecated: - case AttributeList::AT_FallThrough: - case AttributeList::AT_CXX11NoReturn: + switch (ParsedAttr::getKind(AttrName, ScopeName, ParsedAttr::AS_CXX11)) { + case ParsedAttr::AT_CarriesDependency: + case ParsedAttr::AT_Deprecated: + case ParsedAttr::AT_FallThrough: + case ParsedAttr::AT_CXX11NoReturn: return true; - case AttributeList::AT_WarnUnusedResult: + case ParsedAttr::AT_WarnUnusedResult: return !ScopeName && AttrName->getName().equals("nodiscard"); - case AttributeList::AT_Unused: + case ParsedAttr::AT_Unused: return !ScopeName && AttrName->getName().equals("maybe_unused"); default: return false; @@ -3857,8 +3841,8 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); SourceLocation LParenLoc = Tok.getLocation(); const LangOptions &LO = getLangOpts(); - AttributeList::Syntax Syntax = - LO.CPlusPlus ? AttributeList::AS_CXX11 : AttributeList::AS_C2x; + ParsedAttr::Syntax Syntax = + LO.CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C2x; // If the attribute isn't known, we will not attempt to parse any // arguments. @@ -3889,25 +3873,26 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, Syntax); - const AttributeList *Attr = Attrs.getList(); - if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { + if (!Attrs.empty() && + IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { + ParsedAttr &Attr = *Attrs.begin(); // If the attribute is a standard or built-in attribute and we are // parsing an argument list, we need to determine whether this attribute // was allowed to have an argument list (such as [[deprecated]]), and how // many arguments were parsed (so we can diagnose on [[deprecated()]]). - if (Attr->getMaxArgs() && !NumArgs) { + if (Attr.getMaxArgs() && !NumArgs) { // The attribute was allowed to have arguments, but none were provided // even though the attribute parsed successfully. This is an error. Diag(LParenLoc, diag::err_attribute_requires_arguments) << AttrName; - Attr->setInvalid(true); - } else if (!Attr->getMaxArgs()) { + Attr.setInvalid(true); + } else if (!Attr.getMaxArgs()) { // The attribute parsed successfully, but was not allowed to have any // arguments. It doesn't matter whether any were provided -- the // presence of the argument list (even if empty) is diagnosed. Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments) << AttrName << FixItHint::CreateRemoval(SourceRange(LParenLoc, *EndLoc)); - Attr->setInvalid(true); + Attr.setInvalid(true); } } return true; @@ -4026,12 +4011,11 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, AttrName, SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc, AttrLoc), ScopeName, ScopeLoc, nullptr, 0, - getLangOpts().CPlusPlus ? AttributeList::AS_CXX11 - : AttributeList::AS_C2x); + getLangOpts().CPlusPlus ? ParsedAttr::AS_CXX11 : ParsedAttr::AS_C2x); if (TryConsumeToken(tok::ellipsis)) Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis) - << AttrName->getName(); + << AttrName; } if (ExpectAndConsume(tok::r_square)) @@ -4179,7 +4163,7 @@ void Parser::ParseMicrosoftUuidAttributeArgs(ParsedAttributes &Attrs) { if (!T.consumeClose()) { Attrs.addNew(UuidIdent, SourceRange(UuidLoc, T.getCloseLocation()), nullptr, SourceLocation(), ArgExprs.data(), ArgExprs.size(), - AttributeList::AS_Microsoft); + ParsedAttr::AS_Microsoft); } } @@ -4217,8 +4201,9 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs, } while (Tok.is(tok::l_square)); } -void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, - AccessSpecifier& CurAS) { +void Parser::ParseMicrosoftIfExistsClassDeclaration( + DeclSpec::TST TagType, ParsedAttributes &AccessAttrs, + AccessSpecifier &CurAS) { IfExistsCondition Result; if (ParseMicrosoftIfExistsCondition(Result)) return; @@ -4248,7 +4233,8 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // __if_exists, __if_not_exists can nest. if (Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { - ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); + ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, + AccessAttrs, CurAS); continue; } @@ -4265,7 +4251,8 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, SourceLocation ASLoc = Tok.getLocation(); ConsumeToken(); if (Tok.is(tok::colon)) - Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation()); + Actions.ActOnAccessSpecifier(AS, ASLoc, Tok.getLocation(), + ParsedAttributesView{}); else Diag(Tok, diag::err_expected) << tok::colon; ConsumeToken(); @@ -4273,7 +4260,7 @@ void Parser::ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, } // Parse all the comma separated declarators. - ParseCXXClassMemberDeclaration(CurAS, nullptr); + ParseCXXClassMemberDeclaration(CurAS, AccessAttrs); } Braces.consumeClose(); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index bc587628c954..4a0e1c5e3413 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Provides the Expression parsing implementation. +/// Provides the Expression parsing implementation. /// /// Expressions in C99 basically consist of a bunch of binary operators with /// unary operators and other random stuff at the leaves. @@ -32,7 +32,7 @@ #include "llvm/ADT/SmallVector.h" using namespace clang; -/// \brief Simple precedence-based parser for binary/ternary operators. +/// Simple precedence-based parser for binary/ternary operators. /// /// Note: we diverge from the C99 grammar when parsing the assignment-expression /// production. C99 specifies that the LHS of an assignment operator should be @@ -156,7 +156,7 @@ Parser::ParseExpressionWithLeadingExtension(SourceLocation ExtLoc) { return ParseRHSOfBinaryExpression(LHS, prec::Comma); } -/// \brief Parse an expr that doesn't include (top-level) commas. +/// Parse an expr that doesn't include (top-level) commas. ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Expression); @@ -175,7 +175,7 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { return ParseRHSOfBinaryExpression(LHS, prec::Assignment); } -/// \brief Parse an assignment expression where part of an Objective-C message +/// Parse an assignment expression where part of an Objective-C message /// send has already been parsed. /// /// In this case \p LBracLoc indicates the location of the '[' of the message @@ -217,7 +217,15 @@ ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { return ParseConstantExpressionInExprEvalContext(isTypeCast); } -/// \brief Parse a constraint-expression. +ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) { + EnterExpressionEvaluationContext ConstantEvaluated( + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); + ExprResult Res(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); + return Actions.ActOnCaseExpr(CaseLoc, Res); +} + +/// Parse a constraint-expression. /// /// \verbatim /// constraint-expression: [Concepts TS temp.constr.decl p1] @@ -246,30 +254,6 @@ bool Parser::isNotExpressionStart() { return isKnownToBeDeclarationSpecifier(); } -/// We've parsed something that could plausibly be intended to be a template -/// name (\p LHS) followed by a '<' token, and the following code can't possibly -/// be an expression. Determine if this is likely to be a template-id and if so, -/// diagnose it. -bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) { - TentativeParsingAction TPA(*this); - // FIXME: We could look at the token sequence in a lot more detail here. - if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater, - StopAtSemi | StopBeforeMatch)) { - TPA.Commit(); - - SourceLocation Greater; - ParseGreaterThanInTemplateList(Greater, true, false); - Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS, - Less, Greater); - return true; - } - - // There's no matching '>' token, this probably isn't supposed to be - // interpreted as a template-id. Parse it as an (ill-formed) comparison. - TPA.Revert(); - return false; -} - bool Parser::isFoldOperator(prec::Level Level) const { return Level > prec::Unknown && Level != prec::Conditional && Level != prec::Spaceship; @@ -279,7 +263,7 @@ bool Parser::isFoldOperator(tok::TokenKind Kind) const { return isFoldOperator(getBinOpPrecedence(Kind, GreaterThanIsOperator, true)); } -/// \brief Parse a binary expression that starts with \p LHS and has a +/// Parse a binary expression that starts with \p LHS and has a /// precedence of at least \p MinPrec. ExprResult Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { @@ -302,6 +286,14 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { if (OpToken.is(tok::caretcaret)) { return ExprError(Diag(Tok, diag::err_opencl_logical_exclusive_or)); } + + // If we're potentially in a template-id, we may now be able to determine + // whether we're actually in one or not. + if (OpToken.isOneOf(tok::comma, tok::greater, tok::greatergreater, + tok::greatergreatergreater) && + checkPotentialAngleBracketDelimiter(OpToken)) + return ExprError(); + // Bail out when encountering a comma followed by a token which can't // possibly be the start of an expression. For instance: // int f() { return 1, } @@ -313,16 +305,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { return LHS; } - // If a '<' token is followed by a type that can be a template argument and - // cannot be an expression, then this is ill-formed, but might be intended - // to be a template-id. - if (OpToken.is(tok::less) && Actions.mightBeIntendedToBeTemplateName(LHS) && - (isKnownToBeDeclarationSpecifier() || - Tok.isOneOf(tok::greater, tok::greatergreater, - tok::greatergreatergreater)) && - diagnoseUnknownTemplateId(LHS, OpToken.getLocation())) - return ExprError(); - // If the next token is an ellipsis, then this is a fold-expression. Leave // it alone so we can handle it in the paren expression. if (isFoldOperator(NextTokPrec) && Tok.is(tok::ellipsis)) { @@ -336,7 +318,17 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { // Special case handling for the ternary operator. ExprResult TernaryMiddle(true); if (NextTokPrec == prec::Conditional) { - if (Tok.isNot(tok::colon)) { + if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { + // Parse a braced-init-list here for error recovery purposes. + SourceLocation BraceLoc = Tok.getLocation(); + TernaryMiddle = ParseBraceInitializer(); + if (!TernaryMiddle.isInvalid()) { + Diag(BraceLoc, diag::err_init_list_bin_op) + << /*RHS*/ 1 << PP.getSpelling(OpToken) + << Actions.getExprRange(TernaryMiddle.get()); + TernaryMiddle = ExprError(); + } + } else if (Tok.isNot(tok::colon)) { // Don't parse FOO:BAR as if it were a typo for FOO::BAR. ColonProtectionRAIIObject X(*this); @@ -345,11 +337,6 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { // In particular, the RHS of the '?' is 'expression', not // 'logical-OR-expression' as we might expect. TernaryMiddle = ParseExpression(); - if (TernaryMiddle.isInvalid()) { - Actions.CorrectDelayedTyposInExpr(LHS); - LHS = ExprError(); - TernaryMiddle = nullptr; - } } else { // Special case handling of "X ? Y : Z" where Y is empty: // logical-OR-expression '?' ':' conditional-expression [GNU] @@ -357,6 +344,12 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { Diag(Tok, diag::ext_gnu_conditional_expr); } + if (TernaryMiddle.isInvalid()) { + Actions.CorrectDelayedTyposInExpr(LHS); + LHS = ExprError(); + TernaryMiddle = nullptr; + } + if (!TryConsumeToken(tok::colon, ColonLoc)) { // Otherwise, we're missing a ':'. Assume that this was a typo that // the user forgot. If we're not in a macro expansion, we can suggest @@ -469,6 +462,11 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { if (ThisPrec == prec::Assignment) { Diag(OpToken, diag::warn_cxx98_compat_generalized_initializer_lists) << Actions.getExprRange(RHS.get()); + } else if (ColonLoc.isValid()) { + Diag(ColonLoc, diag::err_init_list_bin_op) + << /*RHS*/1 << ":" + << Actions.getExprRange(RHS.get()); + LHS = ExprError(); } else { Diag(OpToken, diag::err_init_list_bin_op) << /*RHS*/1 << PP.getSpelling(OpToken) @@ -513,7 +511,7 @@ Parser::ParseRHSOfBinaryExpression(ExprResult LHS, prec::Level MinPrec) { } } -/// \brief Parse a cast-expression, or, if \p isUnaryExpression is true, +/// Parse a cast-expression, or, if \p isUnaryExpression is true, /// parse a unary-expression. /// /// \p isAddressOfOperand exists because an id-expression that is the @@ -570,7 +568,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { }; } -/// \brief Parse a cast-expression, or, if \pisUnaryExpression is true, parse +/// Parse a cast-expression, or, if \pisUnaryExpression is true, parse /// a unary-expression. /// /// \p isAddressOfOperand exists because an id-expression that is the operand @@ -619,6 +617,8 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { /// [GNU] '__FUNCTION__' /// [MS] '__FUNCDNAME__' /// [MS] 'L__FUNCTION__' +/// [MS] '__FUNCSIG__' +/// [MS] 'L__FUNCSIG__' /// [GNU] '__PRETTY_FUNCTION__' /// [GNU] '(' compound-statement ')' /// [GNU] '__builtin_va_arg' '(' assignment-expression ',' type-name ')' @@ -820,6 +820,8 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, assert(Res.get() == nullptr && "Stray primary-expression annotation?"); Res = getExprAnnotation(Tok); ConsumeAnnotationToken(); + if (!Res.isInvalid() && Tok.is(tok::less)) + checkPotentialAngleBracket(Res); break; case tok::kw___super: @@ -1000,7 +1002,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, DS.SetTypeSpecType(TST_typename, ILoc, PrevSpec, DiagID, Typ, Actions.getASTContext().getPrintingPolicy()); - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext); TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); if (Ty.isInvalid()) @@ -1039,11 +1041,13 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, isAddressOfOperand, std::move(Validator), /*IsInlineAsmIdentifier=*/false, Tok.is(tok::r_paren) ? nullptr : &Replacement); - if (!Res.isInvalid() && !Res.get()) { + if (!Res.isInvalid() && Res.isUnset()) { UnconsumeToken(Replacement); return ParseCastExpression(isUnaryExpression, isAddressOfOperand, NotCastExpr, isTypeCast); } + if (!Res.isInvalid() && Tok.is(tok::less)) + checkPotentialAngleBracket(Res); break; } case tok::char_constant: // constant: character-constant @@ -1059,6 +1063,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::kw___FUNCDNAME__: // primary-expression: __FUNCDNAME__ [MS] case tok::kw___FUNCSIG__: // primary-expression: __FUNCSIG__ [MS] case tok::kw_L__FUNCTION__: // primary-expression: L__FUNCTION__ [MS] + case tok::kw_L__FUNCSIG__: // primary-expression: L__FUNCSIG__ [MS] case tok::kw___PRETTY_FUNCTION__: // primary-expression: __P..Y_F..N__ [GNU] Res = Actions.ActOnPredefinedExpr(Tok.getLocation(), SavedKind); ConsumeToken(); @@ -1209,7 +1214,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, PrevSpec, DiagID, Type, Actions.getASTContext().getPrintingPolicy()); - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext); TypeResult Ty = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); if (Ty.isInvalid()) break; @@ -1224,6 +1229,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, case tok::annot_decltype: 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_bool: @@ -1449,7 +1455,7 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return Res; } -/// \brief Once the leading part of a postfix-expression is parsed, this +/// Once the leading part of a postfix-expression is parsed, this /// method parses any suffixes that apply. /// /// \verbatim @@ -1686,8 +1692,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { CXXScopeSpec SS; ParsedType ObjectType; bool MayBePseudoDestructor = false; + Expr* OrigLHS = !LHS.isInvalid() ? LHS.get() : nullptr; + if (getLangOpts().CPlusPlus && !LHS.isInvalid()) { - Expr *Base = LHS.get(); + Expr *Base = OrigLHS; const Type* BaseType = Base->getType().getTypePtrOrNull(); if (BaseType && Tok.is(tok::l_paren) && (BaseType->isFunctionType() || @@ -1712,11 +1720,25 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } if (Tok.is(tok::code_completion)) { + tok::TokenKind CorrectedOpKind = + OpKind == tok::arrow ? tok::period : tok::arrow; + ExprResult CorrectedLHS(/*IsInvalid=*/true); + if (getLangOpts().CPlusPlus && OrigLHS) { + const bool DiagsAreSuppressed = Diags.getSuppressAllDiagnostics(); + Diags.setSuppressAllDiagnostics(true); + CorrectedLHS = Actions.ActOnStartCXXMemberReference( + getCurScope(), OrigLHS, OpLoc, CorrectedOpKind, ObjectType, + MayBePseudoDestructor); + Diags.setSuppressAllDiagnostics(DiagsAreSuppressed); + } + + Expr *Base = LHS.get(); + Expr *CorrectedBase = CorrectedLHS.get(); + // Code completion for a member access expression. - if (Expr *Base = LHS.get()) - Actions.CodeCompleteMemberReferenceExpr( - getCurScope(), Base, OpLoc, OpKind == tok::arrow, - ExprStatementTokLoc == Base->getLocStart()); + Actions.CodeCompleteMemberReferenceExpr( + getCurScope(), Base, CorrectedBase, OpLoc, OpKind == tok::arrow, + Base && ExprStatementTokLoc == Base->getLocStart()); cutOffParsing(); return ExprError(); @@ -1755,7 +1777,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /*AllowConstructorName=*/ getLangOpts().MicrosoftExt, /*AllowDeductionGuide=*/false, - ObjectType, TemplateKWLoc, Name)) { + ObjectType, &TemplateKWLoc, Name)) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); } @@ -1765,6 +1787,8 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { OpKind, SS, TemplateKWLoc, Name, CurParsedObjCImpl ? CurParsedObjCImpl->Dcl : nullptr); + if (!LHS.isInvalid() && Tok.is(tok::less)) + checkPotentialAngleBracket(LHS); break; } case tok::plusplus: // postfix-expression: postfix-expression '++' @@ -1824,7 +1848,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, if (isTypeIdUnambiguously()) { DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext); ParseDeclarator(DeclaratorInfo); SourceLocation LParenLoc = PP.getLocForEndOfToken(OpTok.getLocation()); @@ -1881,7 +1905,7 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, } -/// \brief Parse a sizeof or alignof expression. +/// Parse a sizeof or alignof expression. /// /// \verbatim /// unary-expression: [C99 6.5.3] @@ -2381,7 +2405,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, // Parse the type declarator. DeclSpec DS(AttrFactory); ParseSpecifierQualifierList(DS); - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext); ParseDeclarator(DeclaratorInfo); // If our type is followed by an identifier and either ':' or ']', then @@ -2694,7 +2718,7 @@ ExprResult Parser::ParseGenericSelectionExpression() { Types, Exprs); } -/// \brief Parse A C++1z fold-expression after the opening paren and optional +/// Parse A C++1z fold-expression after the opening paren and optional /// left-hand-side expression. /// /// \verbatim @@ -2802,7 +2826,10 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs, if (Tok.isNot(tok::comma)) break; // Move to the next argument, remember where the comma was. + Token Comma = Tok; CommaLocs.push_back(ConsumeToken()); + + checkPotentialAngleBracketDelimiter(Comma); } if (SawError) { // Ensure typos get diagnosed when errors were encountered while parsing the @@ -2837,7 +2864,10 @@ Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs, return false; // Move to the next argument, remember where the comma was. + Token Comma = Tok; CommaLocs.push_back(ConsumeToken()); + + checkPotentialAngleBracketDelimiter(Comma); } } @@ -2858,7 +2888,7 @@ void Parser::ParseBlockId(SourceLocation CaretLoc) { ParseSpecifierQualifierList(DS); // Parse the block-declarator. - Declarator DeclaratorInfo(DS, Declarator::BlockLiteralContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::BlockLiteralContext); DeclaratorInfo.setFunctionDefinitionKind(FDK_Definition); ParseDeclarator(DeclaratorInfo); @@ -2897,7 +2927,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { // Parse the return type if present. DeclSpec DS(AttrFactory); - Declarator ParamInfo(DS, Declarator::BlockLiteralContext); + Declarator ParamInfo(DS, DeclaratorContext::BlockLiteralContext); ParamInfo.setFunctionDefinitionKind(FDK_Definition); // FIXME: Since the return type isn't actually parsed, it can't be used to // fill ParamInfo with an initial valid range, so do it manually. @@ -2929,33 +2959,31 @@ ExprResult Parser::ParseBlockLiteralExpression() { ParseBlockId(CaretLoc); } else { // Otherwise, pretend we saw (void). - ParsedAttributes attrs(AttrFactory); SourceLocation NoLoc; - ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(/*HasProto=*/true, - /*IsAmbiguous=*/false, - /*RParenLoc=*/NoLoc, - /*ArgInfo=*/nullptr, - /*NumArgs=*/0, - /*EllipsisLoc=*/NoLoc, - /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, - /*RefQualifierIsLvalueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, - /*MutableLoc=*/NoLoc, - EST_None, - /*ESpecRange=*/SourceRange(), - /*Exceptions=*/nullptr, - /*ExceptionRanges=*/nullptr, - /*NumExceptions=*/0, - /*NoexceptExpr=*/nullptr, - /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - CaretLoc, CaretLoc, - ParamInfo), - attrs, CaretLoc); + ParamInfo.AddTypeInfo( + DeclaratorChunk::getFunction(/*HasProto=*/true, + /*IsAmbiguous=*/false, + /*RParenLoc=*/NoLoc, + /*ArgInfo=*/nullptr, + /*NumArgs=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLvalueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, + /*MutableLoc=*/NoLoc, EST_None, + /*ESpecRange=*/SourceRange(), + /*Exceptions=*/nullptr, + /*ExceptionRanges=*/nullptr, + /*NumExceptions=*/0, + /*NoexceptExpr=*/nullptr, + /*ExceptionSpecTokens=*/nullptr, + /*DeclsInPrototype=*/None, CaretLoc, + CaretLoc, ParamInfo), + CaretLoc); MaybeParseGNUAttributes(ParamInfo); diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index 959cb7a61d3a..26e75999518a 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -100,7 +100,7 @@ void Parser::CheckForTemplateAndDigraph(Token &Next, ParsedType ObjectType, /*AtDigraph*/false); } -/// \brief Parse global scope or nested-name-specifier if present. +/// Parse global scope or nested-name-specifier if present. /// /// Parses a C++ global scope specifier ('::') or nested-name-specifier (which /// may be preceded by '::'). Note that this routine will not parse ::new or @@ -292,8 +292,8 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, break; } - if (TemplateName.getKind() != UnqualifiedId::IK_OperatorFunctionId && - TemplateName.getKind() != UnqualifiedId::IK_LiteralOperatorId) { + if (TemplateName.getKind() != UnqualifiedIdKind::IK_OperatorFunctionId && + TemplateName.getKind() != UnqualifiedIdKind::IK_LiteralOperatorId) { Diag(TemplateName.getSourceRange().getBegin(), diag::err_id_after_template_in_nested_name_spec) << TemplateName.getSourceRange(); @@ -515,7 +515,7 @@ bool Parser::ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS, << FixItHint::CreateInsertion(Tok.getLocation(), "template "); if (TemplateNameKind TNK = Actions.ActOnDependentTemplateName( - getCurScope(), SS, SourceLocation(), TemplateName, ObjectType, + getCurScope(), SS, Tok.getLocation(), TemplateName, ObjectType, EnteringContext, Template, /*AllowInjectedClassName*/ true)) { // Consume the identifier. ConsumeToken(); @@ -553,7 +553,7 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOpe /*AllowDestructorName=*/false, /*AllowConstructorName=*/false, /*AllowDeductionGuide=*/false, - /*ObjectType=*/nullptr, TemplateKWLoc, Name)) + /*ObjectType=*/nullptr, &TemplateKWLoc, Name)) return ExprError(); // This is only the direct operand of an & operator if it is not @@ -561,10 +561,13 @@ ExprResult Parser::tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOpe if (isAddressOfOperand && isPostfixExpressionSuffixStart()) isAddressOfOperand = false; - return Actions.ActOnIdExpression(getCurScope(), SS, TemplateKWLoc, Name, - Tok.is(tok::l_paren), isAddressOfOperand, - nullptr, /*IsInlineAsmIdentifier=*/false, - &Replacement); + ExprResult E = Actions.ActOnIdExpression( + getCurScope(), SS, TemplateKWLoc, Name, Tok.is(tok::l_paren), + isAddressOfOperand, nullptr, /*IsInlineAsmIdentifier=*/false, + &Replacement); + if (!E.isInvalid() && !E.isUnset() && Tok.is(tok::less)) + checkPotentialAngleBracket(E); + return E; } /// ParseCXXIdExpression - Handle id-expression. @@ -730,7 +733,7 @@ ExprResult Parser::TryParseLambdaExpression() { return ParseLambdaExpressionAfterIntroducer(Intro); } -/// \brief Parse a lambda introducer. +/// Parse a lambda introducer. /// \param Intro A LambdaIntroducer filled in with information about the /// contents of the lambda-introducer. /// \param SkippedInits If non-null, we are disambiguating between an Obj-C @@ -805,6 +808,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, IdentifierInfo *Id = nullptr; SourceLocation EllipsisLoc; ExprResult Init; + SourceLocation LocStart = Tok.getLocation(); if (Tok.is(tok::star)) { Loc = ConsumeToken(); @@ -978,8 +982,11 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, Loc, Kind == LCK_ByRef, Id, InitKind, InitExpr); Init = InitExpr; } + + SourceLocation LocEnd = PrevTokLocation; + Intro.addCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init, - InitCaptureType); + InitCaptureType, SourceRange(LocStart, LocEnd)); } T.consumeClose(); @@ -1090,7 +1097,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // Parse lambda-declarator[opt]. DeclSpec DS(AttrFactory); - Declarator D(DS, Declarator::LambdaExprContext); + Declarator D(DS, DeclaratorContext::LambdaExprContext); TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth); Actions.PushLambdaScope(); @@ -1106,12 +1113,12 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // after '(...)'. nvcc doesn't accept this. auto WarnIfHasCUDATargetAttr = [&] { if (getLangOpts().CUDA) - for (auto *A = Attr.getList(); A != nullptr; A = A->getNext()) - if (A->getKind() == AttributeList::AT_CUDADevice || - A->getKind() == AttributeList::AT_CUDAHost || - A->getKind() == AttributeList::AT_CUDAGlobal) - Diag(A->getLoc(), diag::warn_cuda_attr_lambda_position) - << A->getName()->getName(); + for (const ParsedAttr &A : Attr) + if (A.getKind() == ParsedAttr::AT_CUDADevice || + A.getKind() == ParsedAttr::AT_CUDAHost || + A.getKind() == ParsedAttr::AT_CUDAGlobal) + Diag(A.getLoc(), diag::warn_cuda_attr_lambda_position) + << A.getName()->getName(); }; TypeResult TrailingReturnType; @@ -1183,7 +1190,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( if (Tok.is(tok::arrow)) { FunLocalRangeEnd = Tok.getLocation(); SourceRange Range; - TrailingReturnType = ParseTrailingReturnType(Range); + TrailingReturnType = + ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit*/ false); if (Range.getEnd().isValid()) DeclEndLoc = Range.getEnd(); } @@ -1193,29 +1201,23 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( WarnIfHasCUDATargetAttr(); SourceLocation NoLoc; - D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, - /*isAmbiguous=*/false, - LParenLoc, - ParamInfo.data(), ParamInfo.size(), - EllipsisLoc, RParenLoc, - DS.getTypeQualifiers(), - /*RefQualifierIsLValueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, - MutableLoc, - ESpecType, ESpecRange, - DynamicExceptions.data(), - DynamicExceptionRanges.data(), - DynamicExceptions.size(), - NoexceptExpr.isUsable() ? - NoexceptExpr.get() : nullptr, - /*ExceptionSpecTokens*/nullptr, - /*DeclsInPrototype=*/None, - LParenLoc, FunLocalRangeEnd, D, - TrailingReturnType), - Attr, DeclEndLoc); + D.AddTypeInfo(DeclaratorChunk::getFunction( + /*hasProto=*/true, + /*isAmbiguous=*/false, LParenLoc, ParamInfo.data(), + ParamInfo.size(), EllipsisLoc, RParenLoc, + DS.getTypeQualifiers(), + /*RefQualifierIsLValueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, MutableLoc, ESpecType, + ESpecRange, DynamicExceptions.data(), + DynamicExceptionRanges.data(), DynamicExceptions.size(), + NoexceptExpr.isUsable() ? NoexceptExpr.get() : nullptr, + /*ExceptionSpecTokens*/ nullptr, + /*DeclsInPrototype=*/None, LParenLoc, FunLocalRangeEnd, D, + TrailingReturnType), + std::move(Attr), DeclEndLoc); } else if (Tok.isOneOf(tok::kw_mutable, tok::arrow, tok::kw___attribute, tok::kw_constexpr) || (Tok.is(tok::l_square) && NextToken().is(tok::l_square))) { @@ -1253,7 +1255,8 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( // Parse the return type, if there is one. if (Tok.is(tok::arrow)) { SourceRange Range; - TrailingReturnType = ParseTrailingReturnType(Range); + TrailingReturnType = + ParseTrailingReturnType(Range, /*MayBeFollowedByDirectInit*/ false); if (Range.getEnd().isValid()) DeclEndLoc = Range.getEnd(); } @@ -1261,31 +1264,29 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( WarnIfHasCUDATargetAttr(); SourceLocation NoLoc; - D.AddTypeInfo(DeclaratorChunk::getFunction(/*hasProto=*/true, - /*isAmbiguous=*/false, - /*LParenLoc=*/NoLoc, - /*Params=*/nullptr, - /*NumParams=*/0, - /*EllipsisLoc=*/NoLoc, - /*RParenLoc=*/NoLoc, - /*TypeQuals=*/0, - /*RefQualifierIsLValueRef=*/true, - /*RefQualifierLoc=*/NoLoc, - /*ConstQualifierLoc=*/NoLoc, - /*VolatileQualifierLoc=*/NoLoc, - /*RestrictQualifierLoc=*/NoLoc, - MutableLoc, - EST_None, - /*ESpecRange=*/SourceRange(), - /*Exceptions=*/nullptr, - /*ExceptionRanges=*/nullptr, - /*NumExceptions=*/0, - /*NoexceptExpr=*/nullptr, - /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, - DeclLoc, DeclEndLoc, D, - TrailingReturnType), - Attr, DeclEndLoc); + D.AddTypeInfo(DeclaratorChunk::getFunction( + /*hasProto=*/true, + /*isAmbiguous=*/false, + /*LParenLoc=*/NoLoc, + /*Params=*/nullptr, + /*NumParams=*/0, + /*EllipsisLoc=*/NoLoc, + /*RParenLoc=*/NoLoc, + /*TypeQuals=*/0, + /*RefQualifierIsLValueRef=*/true, + /*RefQualifierLoc=*/NoLoc, + /*ConstQualifierLoc=*/NoLoc, + /*VolatileQualifierLoc=*/NoLoc, + /*RestrictQualifierLoc=*/NoLoc, MutableLoc, EST_None, + /*ESpecRange=*/SourceRange(), + /*Exceptions=*/nullptr, + /*ExceptionRanges=*/nullptr, + /*NumExceptions=*/0, + /*NoexceptExpr=*/nullptr, + /*ExceptionSpecTokens=*/nullptr, + /*DeclsInPrototype=*/None, DeclLoc, DeclEndLoc, D, + TrailingReturnType), + std::move(Attr), DeclEndLoc); } // FIXME: Rename BlockScope -> ClosureScope if we decide to continue using @@ -1353,7 +1354,7 @@ ExprResult Parser::ParseCXXCasts() { ParseSpecifierQualifierList(DS); // Parse the abstract-declarator, if present. - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext); ParseDeclarator(DeclaratorInfo); SourceLocation RAngleBracketLoc = Tok.getLocation(); @@ -1498,7 +1499,7 @@ ExprResult Parser::ParseCXXUuidof() { return Result; } -/// \brief Parse a C++ pseudo-destructor expression after the base, +/// Parse a C++ pseudo-destructor expression after the base, /// . or -> operator, and nested-name-specifier have already been /// parsed. /// @@ -1619,7 +1620,7 @@ ExprResult Parser::ParseThrowExpression() { } } -/// \brief Parse the C++ Coroutines co_yield expression. +/// Parse the C++ Coroutines co_yield expression. /// /// co_yield-expression: /// 'co_yield' assignment-expression[opt] @@ -1660,7 +1661,7 @@ ExprResult Parser::ParseCXXThis() { /// In C++1z onwards, the type specifier can also be a template-name. ExprResult Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { - Declarator DeclaratorInfo(DS, Declarator::FunctionalCastContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::FunctionalCastContext); ParsedType TypeRep = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo).get(); assert((Tok.is(tok::l_paren) || @@ -1672,9 +1673,9 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { if (Init.isInvalid()) return Init; Expr *InitList = Init.get(); - return Actions.ActOnCXXTypeConstructExpr(TypeRep, SourceLocation(), - MultiExprArg(&InitList, 1), - SourceLocation()); + return Actions.ActOnCXXTypeConstructExpr( + TypeRep, InitList->getLocStart(), MultiExprArg(&InitList, 1), + InitList->getLocEnd(), /*ListInitialization=*/true); } else { BalancedDelimiterTracker T(*this, tok::l_paren); T.consumeOpen(); @@ -1702,9 +1703,9 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { assert((Exprs.size() == 0 || Exprs.size()-1 == CommaLocs.size())&& "Unexpected number of commas!"); - return Actions.ActOnCXXTypeConstructExpr(TypeRep, T.getOpenLocation(), - Exprs, - T.getCloseLocation()); + return Actions.ActOnCXXTypeConstructExpr(TypeRep, T.getOpenLocation(), + Exprs, T.getCloseLocation(), + /*ListInitialization=*/false); } } @@ -1733,6 +1734,8 @@ Parser::ParseCXXTypeConstructExpression(const DeclSpec &DS) { Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, SourceLocation Loc, Sema::ConditionKind CK) { + ParenBraceBracketBalancer BalancerRAIIObj(*this); + if (Tok.is(tok::code_completion)) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Condition); cutOffParsing(); @@ -1742,17 +1745,34 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); + const auto WarnOnInit = [this, &CK] { + Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 + ? diag::warn_cxx14_compat_init_statement + : diag::ext_init_statement) + << (CK == Sema::ConditionKind::Switch); + }; + // Determine what kind of thing we have. switch (isCXXConditionDeclarationOrInitStatement(InitStmt)) { case ConditionOrInitStatement::Expression: { ProhibitAttributes(attrs); + // We can have an empty expression here. + // if (; true); + if (InitStmt && Tok.is(tok::semi)) { + WarnOnInit(); + SourceLocation SemiLoc = ConsumeToken(); + *InitStmt = Actions.ActOnNullStmt(SemiLoc); + return ParseCXXCondition(nullptr, Loc, CK); + } + // Parse the expression. ExprResult Expr = ParseExpression(); // expression if (Expr.isInvalid()) return Sema::ConditionError(); if (InitStmt && Tok.is(tok::semi)) { + WarnOnInit(); *InitStmt = Actions.ActOnExprStmt(Expr.get()); ConsumeToken(); return ParseCXXCondition(nullptr, Loc, CK); @@ -1762,13 +1782,11 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, } case ConditionOrInitStatement::InitStmtDecl: { - Diag(Tok.getLocation(), getLangOpts().CPlusPlus17 - ? diag::warn_cxx14_compat_init_statement - : diag::ext_init_statement) - << (CK == Sema::ConditionKind::Switch); + WarnOnInit(); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy DG = ParseSimpleDeclaration( - Declarator::InitStmtContext, DeclEnd, attrs, /*RequireSemi=*/true); + DeclGroupPtrTy DG = + ParseSimpleDeclaration(DeclaratorContext::InitStmtContext, DeclEnd, + attrs, /*RequireSemi=*/true); *InitStmt = Actions.ActOnDeclStmt(DG, DeclStart, DeclEnd); return ParseCXXCondition(nullptr, Loc, CK); } @@ -1781,10 +1799,10 @@ Sema::ConditionResult Parser::ParseCXXCondition(StmtResult *InitStmt, // type-specifier-seq DeclSpec DS(AttrFactory); DS.takeAttributesFrom(attrs); - ParseSpecifierQualifierList(DS, AS_none, DSC_condition); + ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_condition); // declarator - Declarator DeclaratorInfo(DS, Declarator::ConditionContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::ConditionContext); ParseDeclarator(DeclaratorInfo); // simple-asm-expr[opt] @@ -1945,6 +1963,9 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::kw_wchar_t: DS.SetTypeSpecType(DeclSpec::TST_wchar, Loc, PrevSpec, DiagID, Policy); break; + case tok::kw_char8_t: + DS.SetTypeSpecType(DeclSpec::TST_char8, Loc, PrevSpec, DiagID, Policy); + break; case tok::kw_char16_t: DS.SetTypeSpecType(DeclSpec::TST_char16, Loc, PrevSpec, DiagID, Policy); break; @@ -1982,12 +2003,12 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { /// type-specifier type-specifier-seq[opt] /// bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { - ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier); + ParseSpecifierQualifierList(DS, AS_none, DeclSpecContext::DSC_type_specifier); DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy()); return false; } -/// \brief Finish parsing a C++ unqualified-id that is a template-id of +/// Finish parsing a C++ unqualified-id that is a template-id of /// some form. /// /// This routine is invoked when a '<' is encountered after an identifier or @@ -2027,15 +2048,14 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, ParsedType ObjectType, UnqualifiedId &Id, bool AssumeTemplateId) { - assert((AssumeTemplateId || Tok.is(tok::less)) && - "Expected '<' to finish parsing a template-id"); - + assert(Tok.is(tok::less) && "Expected '<' to finish parsing a template-id"); + TemplateTy Template; TemplateNameKind TNK = TNK_Non_template; switch (Id.getKind()) { - case UnqualifiedId::IK_Identifier: - case UnqualifiedId::IK_OperatorFunctionId: - case UnqualifiedId::IK_LiteralOperatorId: + case UnqualifiedIdKind::IK_Identifier: + case UnqualifiedIdKind::IK_OperatorFunctionId: + case UnqualifiedIdKind::IK_LiteralOperatorId: if (AssumeTemplateId) { // We defer the injected-class-name checks until we've found whether // this template-id is used to form a nested-name-specifier or not. @@ -2058,11 +2078,11 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // parse correctly as a template, so suggest the keyword 'template' // before 'getAs' and treat this as a dependent template name. std::string Name; - if (Id.getKind() == UnqualifiedId::IK_Identifier) + if (Id.getKind() == UnqualifiedIdKind::IK_Identifier) Name = Id.Identifier->getName(); else { Name = "operator "; - if (Id.getKind() == UnqualifiedId::IK_OperatorFunctionId) + if (Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId) Name += getOperatorSpelling(Id.OperatorFunctionId.Operator); else Name += Id.Identifier->getName(); @@ -2079,7 +2099,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, } break; - case UnqualifiedId::IK_ConstructorName: { + case UnqualifiedIdKind::IK_ConstructorName: { UnqualifiedId TemplateName; bool MemberOfUnknownSpecialization; TemplateName.setIdentifier(Name, NameLoc); @@ -2090,7 +2110,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, break; } - case UnqualifiedId::IK_DestructorName: { + case UnqualifiedIdKind::IK_DestructorName: { UnqualifiedId TemplateName; bool MemberOfUnknownSpecialization; TemplateName.setIdentifier(Name, NameLoc); @@ -2125,22 +2145,24 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, // Parse the enclosed template argument list. SourceLocation LAngleLoc, RAngleLoc; TemplateArgList TemplateArgs; - if (Tok.is(tok::less) && ParseTemplateIdAfterTemplateName( - true, LAngleLoc, TemplateArgs, RAngleLoc)) + if (ParseTemplateIdAfterTemplateName(true, LAngleLoc, TemplateArgs, + RAngleLoc)) return true; - - if (Id.getKind() == UnqualifiedId::IK_Identifier || - Id.getKind() == UnqualifiedId::IK_OperatorFunctionId || - Id.getKind() == UnqualifiedId::IK_LiteralOperatorId) { + + if (Id.getKind() == UnqualifiedIdKind::IK_Identifier || + Id.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId || + Id.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) { // Form a parsed representation of the template-id to be stored in the // UnqualifiedId. // FIXME: Store name for literal operator too. IdentifierInfo *TemplateII = - Id.getKind() == UnqualifiedId::IK_Identifier ? Id.Identifier : nullptr; - OverloadedOperatorKind OpKind = Id.getKind() == UnqualifiedId::IK_Identifier - ? OO_None - : Id.OperatorFunctionId.Operator; + Id.getKind() == UnqualifiedIdKind::IK_Identifier ? Id.Identifier + : nullptr; + OverloadedOperatorKind OpKind = + Id.getKind() == UnqualifiedIdKind::IK_Identifier + ? OO_None + : Id.OperatorFunctionId.Operator; TemplateIdAnnotation *TemplateId = TemplateIdAnnotation::Create( SS, TemplateKWLoc, Id.StartLocation, TemplateII, OpKind, Template, TNK, @@ -2162,7 +2184,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, if (Type.isInvalid()) return true; - if (Id.getKind() == UnqualifiedId::IK_ConstructorName) + if (Id.getKind() == UnqualifiedIdKind::IK_ConstructorName) Id.setConstructorName(Type.get(), NameLoc, RAngleLoc); else Id.setDestructorName(Id.StartLocation, Type.get(), RAngleLoc); @@ -2170,7 +2192,7 @@ bool Parser::ParseUnqualifiedIdTemplateId(CXXScopeSpec &SS, return false; } -/// \brief Parse an operator-function-id or conversion-function-id as part +/// Parse an operator-function-id or conversion-function-id as part /// of a C++ unqualified-id. /// /// This routine is responsible only for parsing the operator-function-id or @@ -2395,7 +2417,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // Parse the conversion-declarator, which is merely a sequence of // ptr-operators. - Declarator D(DS, Declarator::ConversionIdContext); + Declarator D(DS, DeclaratorContext::ConversionIdContext); ParseDeclaratorInternal(D, /*DirectDeclParser=*/nullptr); // Finish up the type. @@ -2409,7 +2431,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, return false; } -/// \brief Parse a C++ unqualified-id (or a C identifier), which describes the +/// Parse a C++ unqualified-id (or a C identifier), which describes the /// name of an entity. /// /// \code @@ -2446,16 +2468,23 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, bool AllowConstructorName, bool AllowDeductionGuide, ParsedType ObjectType, - SourceLocation& TemplateKWLoc, + SourceLocation *TemplateKWLoc, UnqualifiedId &Result) { + if (TemplateKWLoc) + *TemplateKWLoc = SourceLocation(); // Handle 'A::template B'. This is for template-ids which have not // already been annotated by ParseOptionalCXXScopeSpecifier(). bool TemplateSpecified = false; - if (getLangOpts().CPlusPlus && Tok.is(tok::kw_template) && - (ObjectType || SS.isSet())) { - TemplateSpecified = true; - TemplateKWLoc = ConsumeToken(); + if (Tok.is(tok::kw_template)) { + if (TemplateKWLoc && (ObjectType || SS.isSet())) { + TemplateSpecified = true; + *TemplateKWLoc = ConsumeToken(); + } else { + SourceLocation TemplateLoc = ConsumeToken(); + Diag(TemplateLoc, diag::err_unexpected_template_in_unqualified_id) + << FixItHint::CreateRemoval(TemplateLoc); + } } // unqualified-id: @@ -2477,10 +2506,10 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, if (AllowConstructorName && Actions.isCurrentClassName(*Id, getCurScope(), &SS)) { // We have parsed a constructor name. - ParsedType Ty = Actions.getTypeName(*Id, IdLoc, getCurScope(), &SS, false, - false, nullptr, - /*IsCtorOrDtorName=*/true, - /*NonTrivialTypeSourceInfo=*/true); + ParsedType Ty = Actions.getConstructorName(*Id, IdLoc, getCurScope(), SS, + EnteringContext); + if (!Ty) + return true; Result.setConstructorName(Ty, IdLoc, IdLoc); } else if (getLangOpts().CPlusPlus17 && AllowDeductionGuide && SS.isEmpty() && @@ -2494,11 +2523,18 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, } // If the next token is a '<', we may have a template. - if (TemplateSpecified || Tok.is(tok::less)) - return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, Id, IdLoc, - EnteringContext, ObjectType, - Result, TemplateSpecified); - + TemplateTy Template; + if (Tok.is(tok::less)) + return ParseUnqualifiedIdTemplateId( + SS, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), Id, IdLoc, + EnteringContext, ObjectType, Result, TemplateSpecified); + else if (TemplateSpecified && + Actions.ActOnDependentTemplateName( + getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, + EnteringContext, Template, + /*AllowInjectedClassName*/ true) == TNK_Non_template) + return true; + return false; } @@ -2520,11 +2556,11 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, << TemplateId->Name << FixItHint::CreateRemoval( SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc)); - ParsedType Ty = - Actions.getTypeName(*TemplateId->Name, TemplateId->TemplateNameLoc, - getCurScope(), &SS, false, false, nullptr, - /*IsCtorOrDtorName=*/true, - /*NontrivialTypeSourceInfo=*/true); + ParsedType Ty = Actions.getConstructorName( + *TemplateId->Name, TemplateId->TemplateNameLoc, getCurScope(), SS, + EnteringContext); + if (!Ty) + return true; Result.setConstructorName(Ty, TemplateId->TemplateNameLoc, TemplateId->RAngleLoc); ConsumeAnnotationToken(); @@ -2539,7 +2575,14 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // We have already parsed a template-id; consume the annotation token as // our unqualified-id. Result.setTemplateId(TemplateId); - TemplateKWLoc = TemplateId->TemplateKWLoc; + SourceLocation TemplateLoc = TemplateId->TemplateKWLoc; + if (TemplateLoc.isValid()) { + if (TemplateKWLoc && (ObjectType || SS.isSet())) + *TemplateKWLoc = TemplateLoc; + else + Diag(TemplateLoc, diag::err_unexpected_template_in_unqualified_id) + << FixItHint::CreateRemoval(TemplateLoc); + } ConsumeAnnotationToken(); return false; } @@ -2556,13 +2599,20 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, // // template-id: // operator-function-id < template-argument-list[opt] > - if ((Result.getKind() == UnqualifiedId::IK_OperatorFunctionId || - Result.getKind() == UnqualifiedId::IK_LiteralOperatorId) && - (TemplateSpecified || Tok.is(tok::less))) - return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, - nullptr, SourceLocation(), - EnteringContext, ObjectType, - Result, TemplateSpecified); + TemplateTy Template; + if ((Result.getKind() == UnqualifiedIdKind::IK_OperatorFunctionId || + Result.getKind() == UnqualifiedIdKind::IK_LiteralOperatorId) && + Tok.is(tok::less)) + return ParseUnqualifiedIdTemplateId( + SS, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), nullptr, + SourceLocation(), EnteringContext, ObjectType, Result, + TemplateSpecified); + else if (TemplateSpecified && + Actions.ActOnDependentTemplateName( + getCurScope(), SS, *TemplateKWLoc, Result, ObjectType, + EnteringContext, Template, + /*AllowInjectedClassName*/ true) == TNK_Non_template) + return true; return false; } @@ -2630,12 +2680,11 @@ bool Parser::ParseUnqualifiedId(CXXScopeSpec &SS, bool EnteringContext, IdentifierInfo *ClassName = Tok.getIdentifierInfo(); SourceLocation ClassNameLoc = ConsumeToken(); - if (TemplateSpecified || Tok.is(tok::less)) { + if (Tok.is(tok::less)) { Result.setDestructorName(TildeLoc, nullptr, ClassNameLoc); - return ParseUnqualifiedIdTemplateId(SS, TemplateKWLoc, - ClassName, ClassNameLoc, - EnteringContext, ObjectType, - Result, TemplateSpecified); + return ParseUnqualifiedIdTemplateId( + SS, TemplateKWLoc ? *TemplateKWLoc : SourceLocation(), ClassName, + ClassNameLoc, EnteringContext, ObjectType, Result, TemplateSpecified); } // Note that this is a destructor name. @@ -2696,7 +2745,7 @@ Parser::ParseCXXNewExpression(bool UseGlobal, SourceLocation Start) { SourceRange TypeIdParens; DeclSpec DS(AttrFactory); - Declarator DeclaratorInfo(DS, Declarator::CXXNewContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::CXXNewContext); if (Tok.is(tok::l_paren)) { // If it turns out to be a placement, we change the type location. BalancedDelimiterTracker T(*this, tok::l_paren); @@ -2836,10 +2885,9 @@ void Parser::ParseDirectNewDeclarator(Declarator &D) { D.AddTypeInfo(DeclaratorChunk::getArray(0, /*static=*/false, /*star=*/false, - Size.get(), - T.getOpenLocation(), + Size.get(), T.getOpenLocation(), T.getCloseLocation()), - Attrs, T.getCloseLocation()); + std::move(Attrs), T.getCloseLocation()); if (T.getCloseLocation().isInvalid()) return; @@ -2954,7 +3002,7 @@ static unsigned TypeTraitArity(tok::TokenKind kind) { } } -/// \brief Parse the built-in type-trait pseudo-functions that allow +/// Parse the built-in type-trait pseudo-functions that allow /// implementation of the TR1/C++11 type traits templates. /// /// primary-expression: @@ -3172,7 +3220,7 @@ Parser::ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, if (ParseAs >= CompoundLiteral) { // Parse the type declarator. DeclSpec DS(AttrFactory); - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext); { ColonProtectionRAIIObject InnerColonProtection(*this); ParseSpecifierQualifierList(DS); diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index fb8624a324b9..5c5b3cdfcf33 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -13,11 +13,11 @@ #include "clang/Parse/Parser.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/CharInfo.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" -#include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" @@ -45,7 +45,8 @@ void Parser::MaybeSkipAttributes(tok::ObjCKeywordKind Kind) { /// [OBJC] objc-protocol-definition /// [OBJC] objc-method-definition /// [OBJC] '@' 'end' -Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { +Parser::DeclGroupPtrTy +Parser::ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs) { SourceLocation AtLoc = ConsumeToken(); // the "@" if (Tok.is(tok::code_completion)) { @@ -58,15 +59,11 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { switch (Tok.getObjCKeywordID()) { case tok::objc_class: return ParseObjCAtClassDeclaration(AtLoc); - case tok::objc_interface: { - ParsedAttributes attrs(AttrFactory); - SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, attrs); + case tok::objc_interface: + SingleDecl = ParseObjCAtInterfaceDeclaration(AtLoc, Attrs); break; - } - case tok::objc_protocol: { - ParsedAttributes attrs(AttrFactory); - return ParseObjCAtProtocolDeclaration(AtLoc, attrs); - } + case tok::objc_protocol: + return ParseObjCAtProtocolDeclaration(AtLoc, Attrs); case tok::objc_implementation: return ParseObjCAtImplementationDeclaration(AtLoc); case tok::objc_end: @@ -290,7 +287,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, Decl *CategoryType = Actions.ActOnStartCategoryInterface( AtLoc, nameId, nameLoc, typeParameterList, categoryId, categoryLoc, ProtocolRefs.data(), ProtocolRefs.size(), ProtocolLocs.data(), - EndProtoLoc, attrs.getList()); + EndProtoLoc, attrs); if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(CategoryType, tok::objc_private, AtLoc); @@ -356,17 +353,12 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, if (Tok.isNot(tok::less)) Actions.ActOnTypedefedProtocols(protocols, protocolLocs, superClassId, superClassLoc); - - Decl *ClsType = - Actions.ActOnStartClassInterface(getCurScope(), AtLoc, nameId, nameLoc, - typeParameterList, superClassId, - superClassLoc, - typeArgs, - SourceRange(typeArgsLAngleLoc, - typeArgsRAngleLoc), - protocols.data(), protocols.size(), - protocolLocs.data(), - EndProtoLoc, attrs.getList()); + + Decl *ClsType = Actions.ActOnStartClassInterface( + getCurScope(), AtLoc, nameId, nameLoc, typeParameterList, superClassId, + superClassLoc, typeArgs, + SourceRange(typeArgsLAngleLoc, typeArgsRAngleLoc), protocols.data(), + protocols.size(), protocolLocs.data(), EndProtoLoc, attrs); if (Tok.is(tok::l_brace)) ParseObjCClassInstanceVariables(ClsType, tok::objc_protected, AtLoc); @@ -384,25 +376,21 @@ static void addContextSensitiveTypeNullability(Parser &P, SourceLocation nullabilityLoc, bool &addedToDeclSpec) { // Create the attribute. - auto getNullabilityAttr = [&]() -> AttributeList * { - return D.getAttributePool().create( - P.getNullabilityKeyword(nullability), - SourceRange(nullabilityLoc), - nullptr, SourceLocation(), - nullptr, 0, - AttributeList::AS_ContextSensitiveKeyword); + auto getNullabilityAttr = [&](AttributePool &Pool) -> ParsedAttr * { + return Pool.create(P.getNullabilityKeyword(nullability), + SourceRange(nullabilityLoc), nullptr, SourceLocation(), + nullptr, 0, ParsedAttr::AS_ContextSensitiveKeyword); }; if (D.getNumTypeObjects() > 0) { // Add the attribute to the declarator chunk nearest the declarator. - auto nullabilityAttr = getNullabilityAttr(); - DeclaratorChunk &chunk = D.getTypeObject(0); - nullabilityAttr->setNext(chunk.getAttrListRef()); - chunk.getAttrListRef() = nullabilityAttr; + D.getTypeObject(0).getAttrs().addAtStart( + getNullabilityAttr(D.getAttributePool())); } else if (!addedToDeclSpec) { // Otherwise, just put it on the declaration specifiers (if one // isn't there already). - D.getMutableDeclSpec().addAttributes(getNullabilityAttr()); + D.getMutableDeclSpec().getAttributes().addAtStart( + getNullabilityAttr(D.getMutableDeclSpec().getAttributes().getPool())); addedToDeclSpec = true; } } @@ -1140,14 +1128,14 @@ bool Parser::isTokIdentifier_in() const { /// 'null_unspecified' /// void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, - Declarator::TheContext Context) { - assert(Context == Declarator::ObjCParameterContext || - Context == Declarator::ObjCResultContext); + DeclaratorContext Context) { + assert(Context == DeclaratorContext::ObjCParameterContext || + Context == DeclaratorContext::ObjCResultContext); while (1) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCPassingType(getCurScope(), DS, - Context == Declarator::ObjCParameterContext); + Context == DeclaratorContext::ObjCParameterContext); return cutOffParsing(); } @@ -1205,18 +1193,12 @@ void Parser::ParseObjCTypeQualifierList(ObjCDeclSpec &DS, /// Take all the decl attributes out of the given list and add /// them to the given attribute set. -static void takeDeclAttributes(ParsedAttributes &attrs, - AttributeList *list) { - while (list) { - AttributeList *cur = list; - list = cur->getNext(); - - if (!cur->isUsedAsTypeAttr()) { - // Clear out the next pointer. We're really completely - // destroying the internal invariants of the declarator here, - // but it doesn't matter because we're done with it. - cur->setNext(nullptr); - attrs.add(cur); +static void takeDeclAttributes(ParsedAttributesView &attrs, + ParsedAttributesView &from) { + for (auto &AL : llvm::reverse(from)) { + if (!AL.isUsedAsTypeAttr()) { + from.remove(&AL); + attrs.addAtStart(&AL); } } } @@ -1230,11 +1212,10 @@ static void takeDeclAttributes(ParsedAttributes &attrs, attrs.getPool().takeAllFrom(D.getDeclSpec().getAttributePool()); // Now actually move the attributes over. - takeDeclAttributes(attrs, D.getDeclSpec().getAttributes().getList()); + takeDeclAttributes(attrs, D.getMutableDeclSpec().getAttributes()); takeDeclAttributes(attrs, D.getAttributes()); for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) - takeDeclAttributes(attrs, - const_cast<AttributeList*>(D.getTypeObject(i).getAttrs())); + takeDeclAttributes(attrs, D.getTypeObject(i).getAttrs()); } /// objc-type-name: @@ -1242,12 +1223,12 @@ static void takeDeclAttributes(ParsedAttributes &attrs, /// '(' objc-type-qualifiers[opt] ')' /// ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, - Declarator::TheContext context, + DeclaratorContext context, ParsedAttributes *paramAttrs) { - assert(context == Declarator::ObjCParameterContext || - context == Declarator::ObjCResultContext); + assert(context == DeclaratorContext::ObjCParameterContext || + context == DeclaratorContext::ObjCResultContext); assert((paramAttrs != nullptr) == - (context == Declarator::ObjCParameterContext)); + (context == DeclaratorContext::ObjCParameterContext)); assert(Tok.is(tok::l_paren) && "expected ("); @@ -1265,9 +1246,9 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, // Parse an abstract declarator. DeclSpec declSpec(AttrFactory); declSpec.setObjCQualifiers(&DS); - DeclSpecContext dsContext = DSC_normal; - if (context == Declarator::ObjCResultContext) - dsContext = DSC_objc_method_result; + DeclSpecContext dsContext = DeclSpecContext::DSC_normal; + if (context == DeclaratorContext::ObjCResultContext) + dsContext = DeclSpecContext::DSC_objc_method_result; ParseSpecifierQualifierList(declSpec, AS_none, dsContext); Declarator declarator(declSpec, context); ParseDeclarator(declarator); @@ -1288,7 +1269,7 @@ ParsedType Parser::ParseObjCTypeName(ObjCDeclSpec &DS, // If we're parsing a parameter, steal all the decl attributes // and add them to the decl spec. - if (context == Declarator::ObjCParameterContext) + if (context == DeclaratorContext::ObjCParameterContext) takeDeclAttributes(*paramAttrs, declarator); } } @@ -1352,13 +1333,14 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ParsedType ReturnType; ObjCDeclSpec DSRet; if (Tok.is(tok::l_paren)) - ReturnType = ParseObjCTypeName(DSRet, Declarator::ObjCResultContext, + ReturnType = ParseObjCTypeName(DSRet, DeclaratorContext::ObjCResultContext, nullptr); // If attributes exist before the method, parse them. ParsedAttributes methodAttrs(AttrFactory); if (getLangOpts().ObjC2) MaybeParseGNUAttributes(methodAttrs); + MaybeParseCXX11Attributes(methodAttrs); if (Tok.is(tok::code_completion)) { Actions.CodeCompleteObjCMethodDecl(getCurScope(), mType == tok::minus, @@ -1385,15 +1367,13 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist after the method, parse them. if (getLangOpts().ObjC2) MaybeParseGNUAttributes(methodAttrs); + MaybeParseCXX11Attributes(methodAttrs); Selector Sel = PP.getSelectorTable().getNullarySelector(SelIdent); - Decl *Result - = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, DSRet, ReturnType, - selLoc, Sel, nullptr, - CParamInfo.data(), CParamInfo.size(), - methodAttrs.getList(), MethodImplKind, - false, MethodDefinition); + Decl *Result = Actions.ActOnMethodDeclaration( + getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, + selLoc, Sel, nullptr, CParamInfo.data(), CParamInfo.size(), methodAttrs, + MethodImplKind, false, MethodDefinition); PD.complete(Result); return Result; } @@ -1416,16 +1396,15 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, ArgInfo.Type = nullptr; if (Tok.is(tok::l_paren)) // Parse the argument type if present. ArgInfo.Type = ParseObjCTypeName(ArgInfo.DeclSpec, - Declarator::ObjCParameterContext, + DeclaratorContext::ObjCParameterContext, ¶mAttrs); // If attributes exist before the argument name, parse them. // Regardless, collect all the attributes we've parsed so far. - ArgInfo.ArgAttrs = nullptr; - if (getLangOpts().ObjC2) { + if (getLangOpts().ObjC2) MaybeParseGNUAttributes(paramAttrs); - ArgInfo.ArgAttrs = paramAttrs.getList(); - } + MaybeParseCXX11Attributes(paramAttrs); + ArgInfo.ArgAttrs = paramAttrs; // Code completion for the next piece of the selector. if (Tok.is(tok::code_completion)) { @@ -1494,7 +1473,7 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); // Parse the declarator. - Declarator ParmDecl(DS, Declarator::PrototypeContext); + Declarator ParmDecl(DS, DeclaratorContext::PrototypeContext); ParseDeclarator(ParmDecl); IdentifierInfo *ParmII = ParmDecl.getIdentifier(); Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl); @@ -1508,20 +1487,18 @@ Decl *Parser::ParseObjCMethodDecl(SourceLocation mLoc, // If attributes exist after the method, parse them. if (getLangOpts().ObjC2) MaybeParseGNUAttributes(methodAttrs); - + MaybeParseCXX11Attributes(methodAttrs); + if (KeyIdents.size() == 0) return nullptr; Selector Sel = PP.getSelectorTable().getSelector(KeyIdents.size(), &KeyIdents[0]); - Decl *Result - = Actions.ActOnMethodDeclaration(getCurScope(), mLoc, Tok.getLocation(), - mType, DSRet, ReturnType, - KeyLocs, Sel, &ArgInfos[0], - CParamInfo.data(), CParamInfo.size(), - methodAttrs.getList(), - MethodImplKind, isVariadic, MethodDefinition); - + Decl *Result = Actions.ActOnMethodDeclaration( + getCurScope(), mLoc, Tok.getLocation(), mType, DSRet, ReturnType, KeyLocs, + Sel, &ArgInfos[0], CParamInfo.data(), CParamInfo.size(), methodAttrs, + MethodImplKind, isVariadic, MethodDefinition); + PD.complete(Result); return Result; } @@ -1703,7 +1680,7 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers( typeArg, Actions.getASTContext().getPrintingPolicy()); // Form a declarator to turn this into a type. - Declarator D(DS, Declarator::TypeNameContext); + Declarator D(DS, DeclaratorContext::TypeNameContext); TypeResult fullTypeArg = Actions.ActOnTypeName(getCurScope(), D); if (fullTypeArg.isUsable()) { typeArgs.push_back(fullTypeArg.get()); @@ -1886,9 +1863,9 @@ void Parser::HelperActionsForIvarDeclarations(Decl *interfaceDecl, SourceLocatio Actions.ActOnObjCContainerFinishDefinition(); // Call ActOnFields() even if we don't have any decls. This is useful // for code rewriting tools that need to be aware of the empty list. - Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, - AllIvarDecls, - T.getOpenLocation(), T.getCloseLocation(), nullptr); + Actions.ActOnFields(getCurScope(), atLoc, interfaceDecl, AllIvarDecls, + T.getOpenLocation(), T.getCloseLocation(), + ParsedAttributesView()); } /// objc-class-instance-variables: @@ -2038,8 +2015,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol. IdentifierLocPair ProtoInfo(protocolName, nameLoc); - return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, - attrs.getList()); + return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, attrs); } CheckNestedObjCContexts(AtLoc); @@ -2066,8 +2042,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol")) return nullptr; - return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, - attrs.getList()); + return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, attrs); } // Last, and definitely not least, parse a protocol declaration. @@ -2081,12 +2056,9 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, /*consumeLastToken=*/true)) return nullptr; - Decl *ProtoType = - Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc, - ProtocolRefs.data(), - ProtocolRefs.size(), - ProtocolLocs.data(), - EndProtoLoc, attrs.getList()); + Decl *ProtoType = Actions.ActOnStartProtocolInterface( + AtLoc, protocolName, nameLoc, ProtocolRefs.data(), ProtocolRefs.size(), + ProtocolLocs.data(), EndProtoLoc, attrs); ParseObjCInterfaceDeclList(tok::objc_protocol, ProtoType); return Actions.ConvertDeclToDeclGroup(ProtoType); @@ -2273,7 +2245,7 @@ void Parser::ObjCImplParsingDataRAII::finish(SourceRange AtEnd) { P.ParseLexedObjCMethodDefs(*LateParsedObjCMethods[i], false/*c-functions*/); - /// \brief Clear and free the cached objc methods. + /// Clear and free the cached objc methods. for (LateParsedObjCMethodContainer::iterator I = LateParsedObjCMethods.begin(), E = LateParsedObjCMethods.end(); I != E; ++I) @@ -2543,7 +2515,7 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { if (Tok.isNot(tok::ellipsis)) { DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS); - Declarator ParmDecl(DS, Declarator::ObjCCatchContext); + Declarator ParmDecl(DS, DeclaratorContext::ObjCCatchContext); ParseDeclarator(ParmDecl); // Inform the actions module about the declarator, so it @@ -2586,13 +2558,26 @@ StmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) { ParseScope FinallyScope(this, Scope::DeclScope | Scope::CompoundStmtScope); + bool ShouldCapture = + getTargetInfo().getTriple().isWindowsMSVCEnvironment(); + if (ShouldCapture) + Actions.ActOnCapturedRegionStart(Tok.getLocation(), getCurScope(), + CR_ObjCAtFinally, 1); + StmtResult FinallyBody(true); if (Tok.is(tok::l_brace)) FinallyBody = ParseCompoundStatementBody(); else Diag(Tok, diag::err_expected) << tok::l_brace; - if (FinallyBody.isInvalid()) + + if (FinallyBody.isInvalid()) { FinallyBody = Actions.ActOnNullStmt(Tok.getLocation()); + if (ShouldCapture) + Actions.ActOnCapturedRegionError(); + } else if (ShouldCapture) { + FinallyBody = Actions.ActOnCapturedRegionEnd(FinallyBody.get()); + } + FinallyStmt = Actions.ActOnObjCAtFinallyStmt(AtCatchFinallyLoc, FinallyBody.get()); catch_or_finally_seen = true; @@ -2681,7 +2666,7 @@ void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) { Decl *Parser::ParseObjCMethodDefinition() { Decl *MDecl = ParseObjCMethodPrototype(); - PrettyDeclStackTraceEntry CrashInfo(Actions, MDecl, Tok.getLocation(), + PrettyDeclStackTraceEntry CrashInfo(Actions.Context, MDecl, Tok.getLocation(), "parsing Objective-C method"); // parse optional ';' @@ -2865,7 +2850,7 @@ ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) { } } -/// \brief Parse the receiver of an Objective-C++ message send. +/// Parse the receiver of an Objective-C++ message send. /// /// This routine parses the receiver of a message send in /// Objective-C++ either as a type or as an expression. Note that this @@ -2945,7 +2930,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { // We have a class message. Turn the simple-type-specifier or // typename-specifier we parsed into a type and parse the // remainder of the class message. - Declarator DeclaratorInfo(DS, Declarator::TypeNameContext); + Declarator DeclaratorInfo(DS, DeclaratorContext::TypeNameContext); TypeResult Type = Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); if (Type.isInvalid()) return true; @@ -2955,7 +2940,7 @@ bool Parser::ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr) { return false; } -/// \brief Determine whether the parser is currently referring to a an +/// Determine whether the parser is currently referring to a an /// Objective-C message send, using a simplified heuristic to avoid overhead. /// /// This routine will only return true for a subset of valid message-send @@ -3100,7 +3085,7 @@ ExprResult Parser::ParseObjCMessageExpression() { Res.get()); } -/// \brief Parse the remainder of an Objective-C message following the +/// Parse the remainder of an Objective-C message following the /// '[' objc-receiver. /// /// This routine handles sends to super, class messages (sent to a diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index a67a5bbe0dea..a413e96a91e7 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// /// \file -/// \brief This file implements parsing of all OpenMP directives and clauses. +/// This file implements parsing of all OpenMP directives and clauses. /// //===----------------------------------------------------------------------===// @@ -80,51 +80,56 @@ static unsigned getOpenMPDirectiveKindEx(StringRef S) { .Default(OMPD_unknown); } -static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { +static OpenMPDirectiveKind parseOpenMPDirectiveKind(Parser &P) { // Array of foldings: F[i][0] F[i][1] ===> F[i][2]. // E.g.: OMPD_for OMPD_simd ===> OMPD_for_simd // TODO: add other combined directives in topological order. static const unsigned F[][3] = { - { OMPD_cancellation, OMPD_point, OMPD_cancellation_point }, - { OMPD_declare, OMPD_reduction, OMPD_declare_reduction }, - { OMPD_declare, OMPD_simd, OMPD_declare_simd }, - { OMPD_declare, OMPD_target, OMPD_declare_target }, - { OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel }, - { OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for }, - { OMPD_distribute_parallel_for, OMPD_simd, - OMPD_distribute_parallel_for_simd }, - { OMPD_distribute, OMPD_simd, OMPD_distribute_simd }, - { OMPD_end, OMPD_declare, OMPD_end_declare }, - { OMPD_end_declare, OMPD_target, OMPD_end_declare_target }, - { OMPD_target, OMPD_data, OMPD_target_data }, - { OMPD_target, OMPD_enter, OMPD_target_enter }, - { OMPD_target, OMPD_exit, OMPD_target_exit }, - { OMPD_target, OMPD_update, OMPD_target_update }, - { OMPD_target_enter, OMPD_data, OMPD_target_enter_data }, - { OMPD_target_exit, OMPD_data, OMPD_target_exit_data }, - { OMPD_for, OMPD_simd, OMPD_for_simd }, - { OMPD_parallel, OMPD_for, OMPD_parallel_for }, - { OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd }, - { OMPD_parallel, OMPD_sections, OMPD_parallel_sections }, - { OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd }, - { OMPD_target, OMPD_parallel, OMPD_target_parallel }, - { OMPD_target, OMPD_simd, OMPD_target_simd }, - { OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for }, - { OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd }, - { OMPD_teams, OMPD_distribute, OMPD_teams_distribute }, - { OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd }, - { OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel }, - { OMPD_teams_distribute_parallel, OMPD_for, OMPD_teams_distribute_parallel_for }, - { OMPD_teams_distribute_parallel_for, OMPD_simd, OMPD_teams_distribute_parallel_for_simd }, - { OMPD_target, OMPD_teams, OMPD_target_teams }, - { OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute }, - { OMPD_target_teams_distribute, OMPD_parallel, OMPD_target_teams_distribute_parallel }, - { OMPD_target_teams_distribute, OMPD_simd, OMPD_target_teams_distribute_simd }, - { OMPD_target_teams_distribute_parallel, OMPD_for, OMPD_target_teams_distribute_parallel_for }, - { OMPD_target_teams_distribute_parallel_for, OMPD_simd, OMPD_target_teams_distribute_parallel_for_simd } - }; + {OMPD_cancellation, OMPD_point, OMPD_cancellation_point}, + {OMPD_declare, OMPD_reduction, OMPD_declare_reduction}, + {OMPD_declare, OMPD_simd, OMPD_declare_simd}, + {OMPD_declare, OMPD_target, OMPD_declare_target}, + {OMPD_distribute, OMPD_parallel, OMPD_distribute_parallel}, + {OMPD_distribute_parallel, OMPD_for, OMPD_distribute_parallel_for}, + {OMPD_distribute_parallel_for, OMPD_simd, + OMPD_distribute_parallel_for_simd}, + {OMPD_distribute, OMPD_simd, OMPD_distribute_simd}, + {OMPD_end, OMPD_declare, OMPD_end_declare}, + {OMPD_end_declare, OMPD_target, OMPD_end_declare_target}, + {OMPD_target, OMPD_data, OMPD_target_data}, + {OMPD_target, OMPD_enter, OMPD_target_enter}, + {OMPD_target, OMPD_exit, OMPD_target_exit}, + {OMPD_target, OMPD_update, OMPD_target_update}, + {OMPD_target_enter, OMPD_data, OMPD_target_enter_data}, + {OMPD_target_exit, OMPD_data, OMPD_target_exit_data}, + {OMPD_for, OMPD_simd, OMPD_for_simd}, + {OMPD_parallel, OMPD_for, OMPD_parallel_for}, + {OMPD_parallel_for, OMPD_simd, OMPD_parallel_for_simd}, + {OMPD_parallel, OMPD_sections, OMPD_parallel_sections}, + {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}, + {OMPD_target, OMPD_parallel, OMPD_target_parallel}, + {OMPD_target, OMPD_simd, OMPD_target_simd}, + {OMPD_target_parallel, OMPD_for, OMPD_target_parallel_for}, + {OMPD_target_parallel_for, OMPD_simd, OMPD_target_parallel_for_simd}, + {OMPD_teams, OMPD_distribute, OMPD_teams_distribute}, + {OMPD_teams_distribute, OMPD_simd, OMPD_teams_distribute_simd}, + {OMPD_teams_distribute, OMPD_parallel, OMPD_teams_distribute_parallel}, + {OMPD_teams_distribute_parallel, OMPD_for, + OMPD_teams_distribute_parallel_for}, + {OMPD_teams_distribute_parallel_for, OMPD_simd, + OMPD_teams_distribute_parallel_for_simd}, + {OMPD_target, OMPD_teams, OMPD_target_teams}, + {OMPD_target_teams, OMPD_distribute, OMPD_target_teams_distribute}, + {OMPD_target_teams_distribute, OMPD_parallel, + OMPD_target_teams_distribute_parallel}, + {OMPD_target_teams_distribute, OMPD_simd, + OMPD_target_teams_distribute_simd}, + {OMPD_target_teams_distribute_parallel, OMPD_for, + OMPD_target_teams_distribute_parallel_for}, + {OMPD_target_teams_distribute_parallel_for, OMPD_simd, + OMPD_target_teams_distribute_parallel_for_simd}}; enum { CancellationPoint = 0, DeclareReduction = 1, TargetData = 2 }; - auto Tok = P.getCurToken(); + Token Tok = P.getCurToken(); unsigned DKind = Tok.isAnnotation() ? static_cast<unsigned>(OMPD_unknown) @@ -132,8 +137,8 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { if (DKind == OMPD_unknown) return OMPD_unknown; - for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) { - if (DKind != F[i][0]) + for (unsigned I = 0; I < llvm::array_lengthof(F); ++I) { + if (DKind != F[I][0]) continue; Tok = P.getPreprocessor().LookAhead(0); @@ -144,9 +149,9 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { if (SDKind == OMPD_unknown) continue; - if (SDKind == F[i][1]) { + if (SDKind == F[I][1]) { P.ConsumeToken(); - DKind = F[i][2]; + DKind = F[I][2]; } } return DKind < OMPD_unknown ? static_cast<OpenMPDirectiveKind>(DKind) @@ -205,7 +210,7 @@ static DeclarationName parseOpenMPReductionId(Parser &P) { : DeclNames.getCXXOperatorName(OOK); } -/// \brief Parse 'omp declare reduction' construct. +/// Parse 'omp declare reduction' construct. /// /// declare-reduction-directive: /// annot_pragma_openmp 'declare' 'reduction' @@ -250,9 +255,10 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { do { ColonProtectionRAIIObject ColonRAII(*this); SourceRange Range; - TypeResult TR = ParseTypeName(&Range, Declarator::PrototypeContext, AS); + TypeResult TR = + ParseTypeName(&Range, DeclaratorContext::PrototypeContext, AS); if (TR.isUsable()) { - auto ReductionType = + QualType ReductionType = Actions.ActOnOpenMPDeclareReductionType(Range.getBegin(), TR); if (!ReductionType.isNull()) { ReductionTypes.push_back( @@ -299,7 +305,7 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { // Parse <combiner> expression and then parse initializer if any for each // correct type. unsigned I = 0, E = ReductionTypes.size(); - for (auto *D : DRD.get()) { + for (Decl *D : DRD.get()) { TentativeParsingAction TPA(*this); ParseScope OMPDRScope(this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope | @@ -322,9 +328,9 @@ Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) { if (Tok.isNot(tok::annot_pragma_openmp_end)) { // Parse <initializer> expression. if (Tok.is(tok::identifier) && - Tok.getIdentifierInfo()->isStr("initializer")) + Tok.getIdentifierInfo()->isStr("initializer")) { ConsumeToken(); - else { + } else { Diag(Tok.getLocation(), diag::err_expected) << "'initializer'"; TPA.Commit(); IsCorrect = false; @@ -418,13 +424,15 @@ void Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) { SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else { // Match the ')'. - T.consumeClose(); + SourceLocation RLoc = Tok.getLocation(); + if (!T.consumeClose()) + RLoc = T.getCloseLocation(); assert(!Exprs.empty() && Exprs.size() - 1 == CommaLocs.size() && "Unexpected number of commas!"); - ExprResult Initializer = Actions.ActOnParenListExpr( - T.getOpenLocation(), T.getCloseLocation(), Exprs); + ExprResult Initializer = + Actions.ActOnParenListExpr(T.getOpenLocation(), RLoc, Exprs); Actions.AddInitializerToDecl(OmpPrivParm, Initializer.get(), /*DirectInit=*/true); } @@ -550,7 +558,7 @@ static bool parseDeclareSimdClauses( if (CKind == OMPC_uniform || CKind == OMPC_aligned || CKind == OMPC_linear) { Parser::OpenMPVarListDataTy Data; - auto *Vars = &Uniforms; + SmallVectorImpl<Expr *> *Vars = &Uniforms; if (CKind == OMPC_aligned) Vars = &Aligneds; else if (CKind == OMPC_linear) @@ -560,9 +568,9 @@ static bool parseDeclareSimdClauses( if (P.ParseOpenMPVarList(OMPD_declare_simd, getOpenMPClauseKind(ClauseName), *Vars, Data)) IsError = true; - if (CKind == OMPC_aligned) + if (CKind == OMPC_aligned) { Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr); - else if (CKind == OMPC_linear) { + } else if (CKind == OMPC_linear) { if (P.getActions().CheckOpenMPLinearModifier(Data.LinKind, Data.DepLinMapLoc)) Data.LinKind = OMPC_LINEAR_val; @@ -612,15 +620,14 @@ Parser::ParseOMPDeclareSimdClauses(Parser::DeclGroupPtrTy Ptr, } // Skip the last annot_pragma_openmp_end. SourceLocation EndLoc = ConsumeAnnotationToken(); - if (!IsError) { - return Actions.ActOnOpenMPDeclareSimdDirective( - Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, - LinModifiers, Steps, SourceRange(Loc, EndLoc)); - } - return Ptr; + if (IsError) + return Ptr; + return Actions.ActOnOpenMPDeclareSimdDirective( + Ptr, BS, Simdlen.get(), Uniforms, Aligneds, Alignments, Linears, + LinModifiers, Steps, SourceRange(Loc, EndLoc)); } -/// \brief Parsing of declarative OpenMP directives. +/// Parsing of declarative OpenMP directives. /// /// threadprivate-directive: /// annot_pragma_openmp 'threadprivate' simple-variable-list @@ -642,7 +649,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( ParenBraceBracketBalancer BalancerRAIIObj(*this); SourceLocation Loc = ConsumeAnnotationToken(); - auto DKind = ParseOpenMPDirectiveKind(*this); + OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); switch (DKind) { case OMPD_threadprivate: { @@ -665,7 +672,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( } case OMPD_declare_reduction: ConsumeToken(); - if (auto Res = ParseOpenMPDeclareReductionDirective(AS)) { + if (DeclGroupPtrTy Res = ParseOpenMPDeclareReductionDirective(AS)) { // The last seen token is annot_pragma_openmp_end - need to check for // extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { @@ -694,9 +701,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( ConsumeAnyToken(); DeclGroupPtrTy Ptr; - if (Tok.is(tok::annot_pragma_openmp)) + if (Tok.is(tok::annot_pragma_openmp)) { Ptr = ParseOpenMPDeclarativeDirectiveWithExtDecl(AS, Attrs, TagType, Tag); - else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { + } else if (Tok.isNot(tok::r_brace) && !isEofOrEom()) { // Here we expect to see some function declaration. if (AS == AS_none) { assert(TagType == DeclSpec::TST_unspecified); @@ -718,7 +725,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( SourceLocation DTLoc = ConsumeAnyToken(); if (Tok.isNot(tok::annot_pragma_openmp_end)) { // OpenMP 4.5 syntax with list of entities. - llvm::SmallSetVector<const NamedDecl*, 16> SameDirectiveDecls; + Sema::NamedDeclSetType SameDirectiveDecls; while (Tok.isNot(tok::annot_pragma_openmp_end)) { OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To; @@ -734,12 +741,13 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( } ConsumeToken(); } - auto Callback = [this, MT, &SameDirectiveDecls]( - CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { + auto &&Callback = [this, MT, &SameDirectiveDecls]( + CXXScopeSpec &SS, DeclarationNameInfo NameInfo) { Actions.ActOnOpenMPDeclareTargetName(getCurScope(), SS, NameInfo, MT, SameDirectiveDecls); }; - if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, true)) + if (ParseOpenMPSimpleVarList(OMPD_declare_target, Callback, + /*AllowScopeSpecifier=*/true)) break; // Consume optional ','. @@ -748,7 +756,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( } SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); ConsumeAnyToken(); - return DeclGroupPtrTy(); + SmallVector<Decl *, 4> Decls(SameDirectiveDecls.begin(), + SameDirectiveDecls.end()); + if (Decls.empty()) + return DeclGroupPtrTy(); + return Actions.BuildDeclaratorGroup(Decls); } // Skip the last annot_pragma_openmp_end. @@ -757,7 +769,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( if (!Actions.ActOnStartOpenMPDeclareTargetDirective(DTLoc)) return DeclGroupPtrTy(); - DKind = ParseOpenMPDirectiveKind(*this); + llvm::SmallVector<Decl *, 4> Decls; + DKind = parseOpenMPDirectiveKind(*this); while (DKind != OMPD_end_declare_target && DKind != OMPD_declare_target && Tok.isNot(tok::eof) && Tok.isNot(tok::r_brace)) { DeclGroupPtrTy Ptr; @@ -771,10 +784,14 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( Ptr = ParseCXXClassMemberDeclarationWithPragmas(AS, Attrs, TagType, Tag); } + if (Ptr) { + DeclGroupRef Ref = Ptr.get(); + Decls.append(Ref.begin(), Ref.end()); + } if (Tok.isAnnotation() && Tok.is(tok::annot_pragma_openmp)) { TentativeParsingAction TPA(*this); ConsumeAnnotationToken(); - DKind = ParseOpenMPDirectiveKind(*this); + DKind = parseOpenMPDirectiveKind(*this); if (DKind != OMPD_end_declare_target) TPA.Revert(); else @@ -796,7 +813,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( Diag(DTLoc, diag::note_matching) << "'#pragma omp declare target'"; } Actions.ActOnFinishOpenMPDeclareTargetDirective(); - return DeclGroupPtrTy(); + return Actions.BuildDeclaratorGroup(Decls); } case OMPD_unknown: Diag(Tok, diag::err_omp_unknown_directive); @@ -850,7 +867,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( case OMPD_target_teams_distribute_parallel_for_simd: case OMPD_target_teams_distribute_simd: Diag(Tok, diag::err_omp_unexpected_directive) - << getOpenMPDirectiveName(DKind); + << 1 << getOpenMPDirectiveName(DKind); break; } while (Tok.isNot(tok::annot_pragma_openmp_end)) @@ -859,7 +876,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl( return nullptr; } -/// \brief Parsing of declarative or executable OpenMP directives. +/// Parsing of declarative or executable OpenMP directives. /// /// threadprivate-directive: /// annot_pragma_openmp 'threadprivate' simple-variable-list @@ -902,7 +919,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope; SourceLocation Loc = ConsumeAnnotationToken(), EndLoc; - auto DKind = ParseOpenMPDirectiveKind(*this); + OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this); OpenMPDirectiveKind CancelRegion = OMPD_unknown; // Name of critical directive. DeclarationNameInfo DirName; @@ -935,7 +952,8 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( } case OMPD_declare_reduction: ConsumeToken(); - if (auto Res = ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { + if (DeclGroupPtrTy Res = + ParseOpenMPDeclareReductionDirective(/*AS=*/AS_none)) { // The last seen token is annot_pragma_openmp_end - need to check for // extra tokens. if (Tok.isNot(tok::annot_pragma_openmp_end)) { @@ -946,8 +964,9 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( } ConsumeAnyToken(); Directive = Actions.ActOnDeclStmt(Res, Loc, Tok.getLocation()); - } else + } else { SkipUntil(tok::annot_pragma_openmp_end); + } break; case OMPD_flush: if (PP.LookAhead(0).is(tok::l_paren)) { @@ -1026,7 +1045,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( T.consumeClose(); } } else if (DKind == OMPD_cancellation_point || DKind == OMPD_cancel) { - CancelRegion = ParseOpenMPDirectiveKind(*this); + CancelRegion = parseOpenMPDirectiveKind(*this); if (Tok.isNot(tok::annot_pragma_openmp_end)) ConsumeToken(); } @@ -1079,21 +1098,18 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( StmtResult AssociatedStmt; if (HasAssociatedStatement) { // The body is a block scope like in Lambdas and Blocks. - Sema::CompoundScopeRAII CompoundScope(Actions); Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); - Actions.ActOnStartOfCompoundStmt(); - // Parse statement - AssociatedStmt = ParseStatement(); - Actions.ActOnFinishOfCompoundStmt(); + // FIXME: We create a bogus CompoundStmt scope to hold the contents of + // the captured region. Code elsewhere assumes that any FunctionScopeInfo + // should have at least one compound statement scope within it. + AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement()); AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); } else if (DKind == OMPD_target_update || DKind == OMPD_target_enter_data || DKind == OMPD_target_exit_data) { - Sema::CompoundScopeRAII CompoundScope(Actions); Actions.ActOnOpenMPRegionStart(DKind, getCurScope()); - Actions.ActOnStartOfCompoundStmt(); - AssociatedStmt = - Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, /*isStmtExpr=*/false); - Actions.ActOnFinishOfCompoundStmt(); + AssociatedStmt = (Sema::CompoundScopeRAII(Actions), + Actions.ActOnCompoundStmt(Loc, Loc, llvm::None, + /*isStmtExpr=*/false)); AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); } Directive = Actions.ActOnOpenMPExecutableDirective( @@ -1109,7 +1125,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( case OMPD_declare_target: case OMPD_end_declare_target: Diag(Tok, diag::err_omp_unexpected_directive) - << getOpenMPDirectiveName(DKind); + << 1 << getOpenMPDirectiveName(DKind); SkipUntil(tok::annot_pragma_openmp_end); break; case OMPD_unknown: @@ -1140,7 +1156,6 @@ bool Parser::ParseOpenMPSimpleVarList( // Read tokens while ')' or annot_pragma_openmp_end is not found. while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) { CXXScopeSpec SS; - SourceLocation TemplateKWLoc; UnqualifiedId Name; // Read var name. Token PrevTok = Tok; @@ -1152,7 +1167,7 @@ bool Parser::ParseOpenMPSimpleVarList( SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else if (ParseUnqualifiedId(SS, false, false, false, false, nullptr, - TemplateKWLoc, Name)) { + nullptr, Name)) { IsCorrect = false; SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); @@ -1184,7 +1199,7 @@ bool Parser::ParseOpenMPSimpleVarList( return !IsCorrect; } -/// \brief Parsing of OpenMP clauses. +/// Parsing of OpenMP clauses. /// /// clause: /// if-clause | final-clause | num_threads-clause | safelen-clause | @@ -1204,11 +1219,13 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { OMPClause *Clause = nullptr; bool ErrorFound = false; + bool WrongDirective = false; // Check if clause is allowed for the given directive. if (CKind != OMPC_unknown && !isAllowedClauseForDirective(DKind, CKind)) { Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); ErrorFound = true; + WrongDirective = true; } switch (CKind) { @@ -1252,9 +1269,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, } if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) - Clause = ParseOpenMPClause(CKind); + Clause = ParseOpenMPClause(CKind, WrongDirective); else - Clause = ParseOpenMPSingleExprClause(CKind); + Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective); break; case OMPC_default: case OMPC_proc_bind: @@ -1269,7 +1286,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, ErrorFound = true; } - Clause = ParseOpenMPSimpleClause(CKind); + Clause = ParseOpenMPSimpleClause(CKind, WrongDirective); break; case OMPC_schedule: case OMPC_dist_schedule: @@ -1286,7 +1303,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, LLVM_FALLTHROUGH; case OMPC_if: - Clause = ParseOpenMPSingleExprWithArgClause(CKind); + Clause = ParseOpenMPSingleExprWithArgClause(CKind, WrongDirective); break; case OMPC_nowait: case OMPC_untied: @@ -1309,7 +1326,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, ErrorFound = true; } - Clause = ParseOpenMPClause(CKind); + Clause = ParseOpenMPClause(CKind, WrongDirective); break; case OMPC_private: case OMPC_firstprivate: @@ -1329,7 +1346,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_from: case OMPC_use_device_ptr: case OMPC_is_device_ptr: - Clause = ParseOpenMPVarListClause(DKind, CKind); + Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective); break; case OMPC_unknown: Diag(Tok, diag::warn_omp_extra_tokens_at_eol) @@ -1338,8 +1355,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, break; case OMPC_threadprivate: case OMPC_uniform: - Diag(Tok, diag::err_omp_unexpected_clause) << getOpenMPClauseName(CKind) - << getOpenMPDirectiveName(DKind); + if (!WrongDirective) + Diag(Tok, diag::err_omp_unexpected_clause) + << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind); SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch); break; } @@ -1362,13 +1380,14 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); // Parse ')'. - T.consumeClose(); + RLoc = Tok.getLocation(); + if (!T.consumeClose()) + RLoc = T.getCloseLocation(); - RLoc = T.getCloseLocation(); return Val; } -/// \brief Parsing of OpenMP clauses with single expressions like 'final', +/// Parsing of OpenMP clauses with single expressions like 'final', /// 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams', /// 'thread_limit', 'simdlen', 'priority', 'grainsize', 'num_tasks' or 'hint'. /// @@ -1399,7 +1418,8 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName, /// hint-clause: /// 'hint' '(' expression ')' /// -OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { +OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, + bool ParseOnly) { SourceLocation Loc = ConsumeToken(); SourceLocation LLoc = Tok.getLocation(); SourceLocation RLoc; @@ -1409,10 +1429,12 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { if (Val.isInvalid()) return nullptr; + if (ParseOnly) + return nullptr; return Actions.ActOnOpenMPSingleExprClause(Kind, Val.get(), Loc, LLoc, RLoc); } -/// \brief Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. +/// Parsing of simple OpenMP clauses like 'default' or 'proc_bind'. /// /// default-clause: /// 'default' '(' 'none' | 'shared' ') @@ -1420,7 +1442,8 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { /// proc_bind-clause: /// 'proc_bind' '(' 'master' | 'close' | 'spread' ') /// -OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { +OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind, + bool ParseOnly) { SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); // Parse '('. @@ -1437,13 +1460,16 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { ConsumeAnyToken(); // Parse ')'. - T.consumeClose(); + SourceLocation RLoc = Tok.getLocation(); + if (!T.consumeClose()) + RLoc = T.getCloseLocation(); - return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, - Tok.getLocation()); + if (ParseOnly) + return nullptr; + return Actions.ActOnOpenMPSimpleClause(Kind, Type, TypeLoc, LOpen, Loc, RLoc); } -/// \brief Parsing of OpenMP clauses like 'ordered'. +/// Parsing of OpenMP clauses like 'ordered'. /// /// ordered-clause: /// 'ordered' @@ -1469,15 +1495,17 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { /// nogroup-clause: /// 'nogroup' /// -OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) { +OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly) { SourceLocation Loc = Tok.getLocation(); ConsumeAnyToken(); + if (ParseOnly) + return nullptr; return Actions.ActOnOpenMPClause(Kind, Loc, Tok.getLocation()); } -/// \brief Parsing of OpenMP clauses with single expressions and some additional +/// Parsing of OpenMP clauses with single expressions and some additional /// argument like 'schedule' or 'dist_schedule'. /// /// schedule-clause: @@ -1490,7 +1518,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) { /// defaultmap: /// 'defaultmap' '(' modifier ':' kind ')' /// -OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { +OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, + bool ParseOnly) { SourceLocation Loc = ConsumeToken(); SourceLocation DelimLoc; // Parse '('. @@ -1509,7 +1538,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; - auto KindModifier = getOpenMPSimpleClauseType( + unsigned KindModifier = getOpenMPSimpleClauseType( Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); if (KindModifier > OMPC_SCHEDULE_unknown) { // Parse 'modifier' @@ -1582,7 +1611,7 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { assert(Kind == OMPC_if); KLoc.push_back(Tok.getLocation()); TentativeParsingAction TPA(*this); - Arg.push_back(ParseOpenMPDirectiveKind(*this)); + Arg.push_back(parseOpenMPDirectiveKind(*this)); if (Arg.back() != OMPD_unknown) { ConsumeToken(); if (Tok.is(tok::colon) && getLangOpts().OpenMP > 40) { @@ -1592,8 +1621,9 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { TPA.Revert(); Arg.back() = OMPD_unknown; } - } else + } else { TPA.Revert(); + } } bool NeedAnExpression = (Kind == OMPC_schedule && DelimLoc.isValid()) || @@ -1607,19 +1637,21 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { } // Parse ')'. - T.consumeClose(); + SourceLocation RLoc = Tok.getLocation(); + if (!T.consumeClose()) + RLoc = T.getCloseLocation(); if (NeedAnExpression && Val.isInvalid()) return nullptr; + if (ParseOnly) + return nullptr; return Actions.ActOnOpenMPSingleExprWithArgClause( - Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, - T.getCloseLocation()); + Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, RLoc); } static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, UnqualifiedId &ReductionId) { - SourceLocation TemplateKWLoc; if (ReductionIdScopeSpec.isEmpty()) { auto OOK = OO_None; switch (P.getCurToken().getKind()) { @@ -1661,7 +1693,7 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, /*AllowDestructorName*/ false, /*AllowConstructorName*/ false, /*AllowDeductionGuide*/ false, - nullptr, TemplateKWLoc, ReductionId); + nullptr, nullptr, ReductionId); } /// Parses clauses with list. @@ -1723,9 +1755,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, return false; } } - if (Tok.is(tok::colon)) + if (Tok.is(tok::colon)) { Data.ColonLoc = ConsumeToken(); - else { + } else { Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren : diag::warn_pragma_expected_colon) << "dependency type"; @@ -1774,8 +1806,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, if (Data.MapTypeModifier != OMPC_MAP_always) { Diag(Tok, diag::err_omp_unknown_map_type_modifier); Data.MapTypeModifier = OMPC_MAP_unknown; - } else + } else { MapTypeModifierSpecified = true; + } ConsumeToken(); ConsumeToken(); @@ -1799,8 +1832,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, if (Data.MapTypeModifier != OMPC_MAP_always) { Diag(Tok, diag::err_omp_unknown_map_type_modifier); Data.MapTypeModifier = OMPC_MAP_unknown; - } else + } else { MapTypeModifierSpecified = true; + } ConsumeToken(); @@ -1847,9 +1881,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, // Parse variable ExprResult VarExpr = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); - if (VarExpr.isUsable()) + if (VarExpr.isUsable()) { Vars.push_back(VarExpr.get()); - else { + } else { SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } @@ -1885,16 +1919,16 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, } // Parse ')'. - T.consumeClose(); - if ((Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown && - Vars.empty()) || - (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || - (MustHaveTail && !Data.TailExpr) || InvalidReductionId) - return true; - return false; + Data.RLoc = Tok.getLocation(); + if (!T.consumeClose()) + Data.RLoc = T.getCloseLocation(); + return (Kind == OMPC_depend && Data.DepKind != OMPC_DEPEND_unknown && + Vars.empty()) || + (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) || + (MustHaveTail && !Data.TailExpr) || InvalidReductionId; } -/// \brief Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', +/// Parsing of OpenMP clause 'private', 'firstprivate', 'lastprivate', /// 'shared', 'copyin', 'copyprivate', 'flush', 'reduction', 'task_reduction' or /// 'in_reduction'. /// @@ -1939,7 +1973,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, /// modifier(list) /// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, - OpenMPClauseKind Kind) { + OpenMPClauseKind Kind, + bool ParseOnly) { SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); SmallVector<Expr *, 4> Vars; @@ -1948,8 +1983,10 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, if (ParseOpenMPVarList(DKind, Kind, Vars, Data)) return nullptr; + if (ParseOnly) + return nullptr; return Actions.ActOnOpenMPVarListClause( - Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Tok.getLocation(), + Kind, Vars, Data.TailExpr, Loc, LOpen, Data.ColonLoc, Data.RLoc, Data.ReductionIdScopeSpec, Data.ReductionId, Data.DepKind, Data.LinKind, Data.MapTypeModifier, Data.MapType, Data.IsMapTypeImplicit, Data.DepLinMapLoc); diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 198d5c6e9cb0..9a25f9c25c03 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -95,6 +95,44 @@ struct PragmaFPContractHandler : public PragmaHandler { Token &FirstToken) override; }; +// Pragma STDC implementations. + +/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...". +struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler { + PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + tok::OnOffSwitch OOS; + if (PP.LexOnOffSwitch(OOS)) + return; + if (OOS == tok::OOS_ON) + PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported); + } +}; + +/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...". +struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler { + PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {} + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &Tok) override { + tok::OnOffSwitch OOS; + PP.LexOnOffSwitch(OOS); + } +}; + +/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...". +struct PragmaSTDC_UnknownHandler : public PragmaHandler { + PragmaSTDC_UnknownHandler() = default; + + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &UnknownTok) override { + // C99 6.10.6p2, unknown forms are not allowed. + PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored); + } +}; + struct PragmaFPHandler : public PragmaHandler { PragmaFPHandler() : PragmaHandler("fp") {} void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, @@ -182,6 +220,12 @@ struct PragmaMSIntrinsicHandler : public PragmaHandler { Token &FirstToken) override; }; +struct PragmaMSOptimizeHandler : public PragmaHandler { + PragmaMSOptimizeHandler() : PragmaHandler("optimize") {} + void HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, + Token &FirstToken) override; +}; + struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler { PragmaForceCUDAHostDeviceHandler(Sema &Actions) : PragmaHandler("force_cuda_host_device"), Actions(Actions) {} @@ -233,6 +277,15 @@ void Parser::initializePragmaHandlers() { FPContractHandler.reset(new PragmaFPContractHandler()); PP.AddPragmaHandler("STDC", FPContractHandler.get()); + STDCFENVHandler.reset(new PragmaSTDC_FENV_ACCESSHandler()); + PP.AddPragmaHandler("STDC", STDCFENVHandler.get()); + + STDCCXLIMITHandler.reset(new PragmaSTDC_CX_LIMITED_RANGEHandler()); + PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get()); + + STDCUnknownHandler.reset(new PragmaSTDC_UnknownHandler()); + PP.AddPragmaHandler("STDC", STDCUnknownHandler.get()); + PCSectionHandler.reset(new PragmaClangSectionHandler(Actions)); PP.AddPragmaHandler("clang", PCSectionHandler.get()); @@ -248,7 +301,8 @@ void Parser::initializePragmaHandlers() { OpenMPHandler.reset(new PragmaNoOpenMPHandler()); PP.AddPragmaHandler(OpenMPHandler.get()); - if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) { + if (getLangOpts().MicrosoftExt || + getTargetInfo().getTriple().isOSBinFormatELF()) { MSCommentHandler.reset(new PragmaCommentHandler(Actions)); PP.AddPragmaHandler(MSCommentHandler.get()); } @@ -276,6 +330,8 @@ void Parser::initializePragmaHandlers() { PP.AddPragmaHandler(MSRuntimeChecks.get()); MSIntrinsic.reset(new PragmaMSIntrinsicHandler()); PP.AddPragmaHandler(MSIntrinsic.get()); + MSOptimize.reset(new PragmaMSOptimizeHandler()); + PP.AddPragmaHandler(MSOptimize.get()); } if (getLangOpts().CUDA) { @@ -330,7 +386,8 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler(OpenMPHandler.get()); OpenMPHandler.reset(); - if (getLangOpts().MicrosoftExt || getTargetInfo().getTriple().isPS4()) { + if (getLangOpts().MicrosoftExt || + getTargetInfo().getTriple().isOSBinFormatELF()) { PP.RemovePragmaHandler(MSCommentHandler.get()); MSCommentHandler.reset(); } @@ -361,6 +418,8 @@ void Parser::resetPragmaHandlers() { MSRuntimeChecks.reset(); PP.RemovePragmaHandler(MSIntrinsic.get()); MSIntrinsic.reset(); + PP.RemovePragmaHandler(MSOptimize.get()); + MSOptimize.reset(); } if (getLangOpts().CUDA) { @@ -371,6 +430,15 @@ void Parser::resetPragmaHandlers() { PP.RemovePragmaHandler("STDC", FPContractHandler.get()); FPContractHandler.reset(); + PP.RemovePragmaHandler("STDC", STDCFENVHandler.get()); + STDCFENVHandler.reset(); + + PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get()); + STDCCXLIMITHandler.reset(); + + PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get()); + STDCUnknownHandler.reset(); + PP.RemovePragmaHandler("clang", OptimizeHandler.get()); OptimizeHandler.reset(); @@ -390,7 +458,7 @@ void Parser::resetPragmaHandlers() { AttributePragmaHandler.reset(); } -/// \brief Handle the annotation token produced for #pragma unused(...) +/// Handle the annotation token produced for #pragma unused(...) /// /// Each annot_pragma_unused is followed by the argument token so e.g. /// "#pragma unused(x,y)" becomes: @@ -451,8 +519,10 @@ void Parser::HandlePragmaAlign() { Sema::PragmaOptionsAlignKind Kind = static_cast<Sema::PragmaOptionsAlignKind>( reinterpret_cast<uintptr_t>(Tok.getAnnotationValue())); - SourceLocation PragmaLoc = ConsumeAnnotationToken(); - Actions.ActOnPragmaOptionsAlign(Kind, PragmaLoc); + Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation()); + // Consume the token after processing the pragma to enable pragma-specific + // #include warnings. + ConsumeAnnotationToken(); } void Parser::HandlePragmaDump() { @@ -1175,7 +1245,7 @@ bool Parser::ParsePragmaAttributeSubjectMatchRuleSet( namespace { -/// Describes the stage at which attribute subject rule parsing was interruped. +/// Describes the stage at which attribute subject rule parsing was interrupted. enum class MissingAttributeSubjectRulesRecoveryPoint { Comma, ApplyTo, @@ -1201,7 +1271,7 @@ getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) { /// suggests the possible attribute subject rules in a fix-it together with /// any other missing tokens. DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic( - unsigned DiagID, AttributeList &Attribute, + unsigned DiagID, ParsedAttr &Attribute, MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) { SourceLocation Loc = PRef.getEndOfPreviousToken(); if (Loc.isInvalid()) @@ -1301,12 +1371,11 @@ void Parser::HandlePragmaAttribute() { if (Tok.isNot(tok::l_paren)) Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0, - AttributeList::AS_GNU); + ParsedAttr::AS_GNU); else ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr, /*ScopeName=*/nullptr, - /*ScopeLoc=*/SourceLocation(), - AttributeList::AS_GNU, + /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU, /*Declarator=*/nullptr); if (ExpectAndConsume(tok::r_paren)) @@ -1320,9 +1389,9 @@ void Parser::HandlePragmaAttribute() { if (Tok.getIdentifierInfo()) { // If we suspect that this is an attribute suggest the use of // '__attribute__'. - if (AttributeList::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, - AttributeList::AS_GNU) != - AttributeList::UnknownAttribute) { + if (ParsedAttr::getKind(Tok.getIdentifierInfo(), /*ScopeName=*/nullptr, + ParsedAttr::AS_GNU) != + ParsedAttr::UnknownAttribute) { SourceLocation InsertStartLoc = Tok.getLocation(); ConsumeToken(); if (Tok.is(tok::l_paren)) { @@ -1340,26 +1409,26 @@ void Parser::HandlePragmaAttribute() { return; } - if (!Attrs.getList() || Attrs.getList()->isInvalid()) { + if (Attrs.empty() || Attrs.begin()->isInvalid()) { SkipToEnd(); return; } // Ensure that we don't have more than one attribute. - if (Attrs.getList()->getNext()) { - SourceLocation Loc = Attrs.getList()->getNext()->getLoc(); + if (Attrs.size() > 1) { + SourceLocation Loc = Attrs[1].getLoc(); Diag(Loc, diag::err_pragma_attribute_multiple_attributes); SkipToEnd(); return; } - if (!Attrs.getList()->isSupportedByPragmaAttribute()) { + ParsedAttr &Attribute = *Attrs.begin(); + if (!Attribute.isSupportedByPragmaAttribute()) { Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute) - << Attrs.getList()->getName(); + << Attribute.getName(); SkipToEnd(); return; } - AttributeList &Attribute = *Attrs.getList(); // Parse the subject-list. if (!TryConsumeToken(tok::comma)) { @@ -2030,7 +2099,7 @@ PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP, StateLoc, State); } -/// \brief Handle '#pragma omp ...' when OpenMP is disabled. +/// Handle '#pragma omp ...' when OpenMP is disabled. /// void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, @@ -2045,7 +2114,7 @@ PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP, PP.DiscardUntilEndOfDirective(); } -/// \brief Handle '#pragma omp ...' when OpenMP is enabled. +/// Handle '#pragma omp ...' when OpenMP is enabled. /// void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, @@ -2057,9 +2126,21 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, Tok.setKind(tok::annot_pragma_openmp); Tok.setLocation(FirstTok.getLocation()); - while (Tok.isNot(tok::eod)) { + while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) { Pragma.push_back(Tok); PP.Lex(Tok); + if (Tok.is(tok::annot_pragma_openmp)) { + PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0; + unsigned InnerPragmaCnt = 1; + while (InnerPragmaCnt != 0) { + PP.Lex(Tok); + if (Tok.is(tok::annot_pragma_openmp)) + ++InnerPragmaCnt; + else if (Tok.is(tok::annot_pragma_openmp_end)) + --InnerPragmaCnt; + } + PP.Lex(Tok); + } } SourceLocation EodLoc = Tok.getLocation(); Tok.startToken(); @@ -2073,7 +2154,7 @@ PragmaOpenMPHandler::HandlePragma(Preprocessor &PP, /*DisableMacroExpansion=*/false); } -/// \brief Handle '#pragma pointers_to_members' +/// Handle '#pragma pointers_to_members' // The grammar for this pragma is as follows: // // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance' @@ -2171,7 +2252,7 @@ void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP, PP.EnterToken(AnnotTok); } -/// \brief Handle '#pragma vtordisp' +/// Handle '#pragma vtordisp' // The grammar for this pragma is as follows: // // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' ) @@ -2264,7 +2345,7 @@ void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP, PP.EnterToken(AnnotTok); } -/// \brief Handle all MS pragmas. Simply forwards the tokens after inserting +/// Handle all MS pragmas. Simply forwards the tokens after inserting /// an annotation token. void PragmaMSPragma::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, @@ -2282,7 +2363,7 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP, TokenVector.push_back(Tok); AnnotTok.setAnnotationEndLoc(Tok.getLocation()); } - // Add a sentinal EoF token to the end of the list. + // Add a sentinel EoF token to the end of the list. TokenVector.push_back(EoF); // We must allocate this array with new because EnterTokenStream is going to // delete it later. @@ -2295,7 +2376,7 @@ void PragmaMSPragma::HandlePragma(Preprocessor &PP, PP.EnterToken(AnnotTok); } -/// \brief Handle the Microsoft \#pragma detect_mismatch extension. +/// Handle the Microsoft \#pragma detect_mismatch extension. /// /// The syntax is: /// \code @@ -2352,7 +2433,7 @@ void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP, Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString); } -/// \brief Handle the microsoft \#pragma comment extension. +/// Handle the microsoft \#pragma comment extension. /// /// The syntax is: /// \code @@ -2393,6 +2474,12 @@ void PragmaCommentHandler::HandlePragma(Preprocessor &PP, return; } + if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored) + << II->getName(); + return; + } + // On PS4, issue a warning about any pragma comments other than // #pragma comment lib. if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) { @@ -2595,7 +2682,7 @@ void Parser::HandlePragmaFP() { ConsumeAnnotationToken(); } -/// \brief Parses loop or unroll pragma hint value and fills in Info. +/// Parses loop or unroll pragma hint value and fills in Info. static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, Token Option, bool ValueInParens, PragmaLoopHintInfo &Info) { @@ -2637,7 +2724,7 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, return false; } -/// \brief Handle the \#pragma clang loop directive. +/// Handle the \#pragma clang loop directive. /// #pragma clang 'loop' loop-hints /// /// loop-hints: @@ -2752,7 +2839,7 @@ void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, /*DisableMacroExpansion=*/false); } -/// \brief Handle the loop unroll optimization pragmas. +/// Handle the loop unroll optimization pragmas. /// #pragma unroll /// #pragma unroll unroll-hint-value /// #pragma unroll '(' unroll-hint-value ')' @@ -2822,7 +2909,7 @@ void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP, /*DisableMacroExpansion=*/false); } -/// \brief Handle the Microsoft \#pragma intrinsic extension. +/// Handle the Microsoft \#pragma intrinsic extension. /// /// The syntax is: /// \code @@ -2871,6 +2958,61 @@ void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP, PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "intrinsic"; } + +// #pragma optimize("gsty", on|off) +void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP, + PragmaIntroducerKind Introducer, + Token &Tok) { + SourceLocation StartLoc = Tok.getLocation(); + PP.Lex(Tok); + + if (Tok.isNot(tok::l_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize"; + return; + } + PP.Lex(Tok); + + if (Tok.isNot(tok::string_literal)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize"; + return; + } + // We could syntax check the string but it's probably not worth the effort. + PP.Lex(Tok); + + if (Tok.isNot(tok::comma)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize"; + return; + } + PP.Lex(Tok); + + if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument) + << "optimize" << /*Expected=*/true << "'on' or 'off'"; + return; + } + IdentifierInfo *II = Tok.getIdentifierInfo(); + if (!II || (!II->isStr("on") && !II->isStr("off"))) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument) + << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true + << "'on' or 'off'"; + return; + } + PP.Lex(Tok); + + if (Tok.isNot(tok::r_paren)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize"; + return; + } + PP.Lex(Tok); + + if (Tok.isNot(tok::eod)) { + PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) + << "optimize"; + return; + } + PP.Diag(StartLoc, diag::warn_pragma_optimize); +} + void PragmaForceCUDAHostDeviceHandler::HandlePragma( Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) { Token FirstTok = Tok; @@ -2895,7 +3037,7 @@ void PragmaForceCUDAHostDeviceHandler::HandlePragma( diag::warn_pragma_force_cuda_host_device_bad_arg); } -/// \brief Handle the #pragma clang attribute directive. +/// Handle the #pragma clang attribute directive. /// /// The syntax is: /// \code diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index 3f25610f4471..deb10af4b17b 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -12,13 +12,13 @@ // //===----------------------------------------------------------------------===// +#include "clang/AST/PrettyDeclStackTrace.h" #include "clang/Basic/Attributes.h" #include "clang/Basic/PrettyStackTrace.h" #include "clang/Parse/Parser.h" #include "clang/Parse/RAIIObjectsForParser.h" #include "clang/Sema/DeclSpec.h" #include "clang/Sema/LoopHint.h" -#include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" using namespace clang; @@ -27,7 +27,7 @@ using namespace clang; // C99 6.8: Statements and Blocks. //===----------------------------------------------------------------------===// -/// \brief Parse a standalone statement (for instance, as the body of an 'if', +/// Parse a standalone statement (for instance, as the body of an 'if', /// 'while', or 'for'). StmtResult Parser::ParseStatement(SourceLocation *TrailingElseLoc, bool AllowOpenMPStandalone) { @@ -116,7 +116,7 @@ Parser::ParseStatementOrDeclaration(StmtVector &Stmts, if (Attrs.empty() || Res.isInvalid()) return Res; - return Actions.ProcessStmtAttributes(Res.get(), Attrs.getList(), Attrs.Range); + return Actions.ProcessStmtAttributes(Res.get(), Attrs, Attrs.Range); } namespace { @@ -211,7 +211,7 @@ Retry: Allowed == ACK_Any) && isDeclarationStatement()) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy Decl = ParseDeclaration(Declarator::BlockContext, + DeclGroupPtrTy Decl = ParseDeclaration(DeclaratorContext::BlockContext, DeclEnd, Attrs); return Actions.ActOnDeclStmt(Decl, DeclStart, DeclEnd); } @@ -402,7 +402,7 @@ Retry: return Res; } -/// \brief Parse an expression statement. +/// Parse an expression statement. StmtResult Parser::ParseExprStatement() { // If a case keyword is missing, this is where it should be inserted. Token OldToken = Tok; @@ -610,8 +610,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) { Stmts, /*Allowed=*/ACK_StatementsOpenMPNonStandalone, nullptr, TempAttrs); if (!TempAttrs.empty() && !SubStmt.isInvalid()) - SubStmt = Actions.ProcessStmtAttributes( - SubStmt.get(), TempAttrs.getList(), TempAttrs.Range); + SubStmt = Actions.ProcessStmtAttributes(SubStmt.get(), TempAttrs, + TempAttrs.Range); } else { Diag(Tok, diag::err_expected_after) << "__attribute__" << tok::semi; } @@ -627,10 +627,8 @@ StmtResult Parser::ParseLabeledStatement(ParsedAttributesWithRange &attrs) { LabelDecl *LD = Actions.LookupOrCreateLabel(IdentTok.getIdentifierInfo(), IdentTok.getLocation()); - if (AttributeList *Attrs = attrs.getList()) { - Actions.ProcessDeclAttributeList(Actions.CurScope, LD, Attrs); - attrs.clear(); - } + Actions.ProcessDeclAttributeList(Actions.CurScope, LD, attrs); + attrs.clear(); return Actions.ActOnLabelStmt(IdentTok.getLocation(), LD, ColonLoc, SubStmt.get()); @@ -687,20 +685,12 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { ExprResult LHS; if (!MissingCase) { - LHS = ParseConstantExpression(); - if (!getLangOpts().CPlusPlus11) { - LHS = Actions.CorrectDelayedTyposInExpr(LHS, [this](class Expr *E) { - return Actions.VerifyIntegerConstantExpression(E); - }); - } + LHS = ParseCaseExpression(CaseLoc); if (LHS.isInvalid()) { // If constant-expression is parsed unsuccessfully, recover by skipping // current case statement (moving to the colon that ends it). - if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) { - TryConsumeToken(tok::colon, ColonLoc); - continue; - } - return StmtError(); + if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) + return StmtError(); } } else { LHS = Expr; @@ -712,13 +702,10 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { ExprResult RHS; if (TryConsumeToken(tok::ellipsis, DotDotDotLoc)) { Diag(DotDotDotLoc, diag::ext_gnu_case_range); - RHS = ParseConstantExpression(); + RHS = ParseCaseExpression(CaseLoc); if (RHS.isInvalid()) { - if (SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) { - TryConsumeToken(tok::colon, ColonLoc); - continue; - } - return StmtError(); + if (!SkipUntil(tok::colon, tok::r_brace, StopAtSemi | StopBeforeMatch)) + return StmtError(); } } @@ -740,8 +727,7 @@ StmtResult Parser::ParseCaseStatement(bool MissingCase, ExprResult Expr) { } StmtResult Case = - Actions.ActOnCaseStmt(CaseLoc, LHS.get(), DotDotDotLoc, - RHS.get(), ColonLoc); + Actions.ActOnCaseStmt(CaseLoc, LHS, DotDotDotLoc, RHS, ColonLoc); // If we had a sema error parsing this case, then just ignore it and // continue parsing the sub-stmt. @@ -954,7 +940,7 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { if (T.consumeOpen()) return StmtError(); - Sema::CompoundScopeRAII CompoundScope(Actions); + Sema::CompoundScopeRAII CompoundScope(Actions, isStmtExpr); // Parse any pragmas at the beginning of the compound statement. ParseCompoundStatementLeadingPragmas(); @@ -1021,8 +1007,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { ExtensionRAIIObject O(Diags); SourceLocation DeclStart = Tok.getLocation(), DeclEnd; - DeclGroupPtrTy Res = ParseDeclaration(Declarator::BlockContext, DeclEnd, - attrs); + DeclGroupPtrTy Res = + ParseDeclaration(DeclaratorContext::BlockContext, DeclEnd, attrs); R = Actions.ActOnDeclStmt(Res, DeclStart, DeclEnd); } else { // Otherwise this was a unary __extension__ marker. @@ -1196,7 +1182,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { { EnterExpressionEvaluationContext PotentiallyDiscarded( Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr, - false, + Sema::ExpressionEvaluationContextRecord::EK_Other, /*ShouldEnter=*/ConstexprCondition && !*ConstexprCondition); ThenStmt = ParseStatement(&InnerStatementTrailingElseLoc); } @@ -1230,7 +1216,7 @@ StmtResult Parser::ParseIfStatement(SourceLocation *TrailingElseLoc) { EnterExpressionEvaluationContext PotentiallyDiscarded( Actions, Sema::ExpressionEvaluationContext::DiscardedStatement, nullptr, - false, + Sema::ExpressionEvaluationContextRecord::EK_Other, /*ShouldEnter=*/ConstexprCondition && *ConstexprCondition); ElseStmt = ParseStatement(); @@ -1621,9 +1607,13 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { attrs, attrs.Range.getEnd()); ForRange = true; } else if (isForInitDeclaration()) { // for (int X = 4; + ParenBraceBracketBalancer BalancerRAIIObj(*this); + // Parse declaration, which eats the ';'. - if (!C99orCXXorObjC) // Use of C99-style for loops in C90 mode? + if (!C99orCXXorObjC) { // Use of C99-style for loops in C90 mode? Diag(Tok, diag::ext_c99_variable_decl_in_for_loop); + Diag(Tok, diag::warn_gcc_variable_decl_in_for_loop); + } // In C++0x, "for (T NS:a" might not be a typo for :: bool MightBeForRangeStmt = getLangOpts().CPlusPlus; @@ -1631,7 +1621,7 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { SourceLocation DeclStart = Tok.getLocation(), DeclEnd; DeclGroupPtrTy DG = ParseSimpleDeclaration( - Declarator::ForContext, DeclEnd, attrs, false, + DeclaratorContext::ForContext, DeclEnd, attrs, false, MightBeForRangeStmt ? &ForRangeInit : nullptr); FirstPart = Actions.ActOnDeclStmt(DG, DeclStart, Tok.getLocation()); if (ForRangeInit.ParsedForRangeDecl()) { @@ -1940,7 +1930,7 @@ StmtResult Parser::ParsePragmaLoopHint(StmtVector &Stmts, ArgsUnion(Hint.ValueExpr)}; TempAttrs.addNew(Hint.PragmaNameLoc->Ident, Hint.Range, nullptr, Hint.PragmaNameLoc->Loc, ArgHints, 4, - AttributeList::AS_Pragma); + ParsedAttr::AS_Pragma); } // Get the next statement. @@ -1957,7 +1947,7 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { assert(Tok.is(tok::l_brace)); SourceLocation LBraceLoc = Tok.getLocation(); - PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, + PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, LBraceLoc, "parsing function body"); // Save and reset current vtordisp stack if we have entered a C++ method body. @@ -1990,7 +1980,7 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { assert(Tok.is(tok::kw_try) && "Expected 'try'"); SourceLocation TryLoc = ConsumeToken(); - PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, TryLoc, + PrettyDeclStackTraceEntry CrashInfo(Actions.Context, Decl, TryLoc, "parsing function try block"); // Constructor initializer list? @@ -2181,7 +2171,7 @@ StmtResult Parser::ParseCXXCatchBlock(bool FnCatch) { if (ParseCXXTypeSpecifierSeq(DS)) return StmtError(); - Declarator ExDecl(DS, Declarator::CXXCatchContext); + Declarator ExDecl(DS, DeclaratorContext::CXXCatchContext); ParseDeclarator(ExDecl); ExceptionDecl = Actions.ActOnExceptionDeclarator(getCurScope(), ExDecl); } else @@ -2265,7 +2255,7 @@ bool Parser::ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) { if (Attrs.empty()) return true; - if (Attrs.getList()->getKind() != AttributeList::AT_OpenCLUnrollHint) + if (Attrs.begin()->getKind() != ParsedAttr::AT_OpenCLUnrollHint) return true; if (!(Tok.is(tok::kw_for) || Tok.is(tok::kw_while) || Tok.is(tok::kw_do))) { diff --git a/lib/Parse/ParseStmtAsm.cpp b/lib/Parse/ParseStmtAsm.cpp index d81029e27974..290723c29532 100644 --- a/lib/Parse/ParseStmtAsm.cpp +++ b/lib/Parse/ParseStmtAsm.cpp @@ -239,7 +239,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, /*AllowDestructorName=*/false, /*AllowConstructorName=*/false, /*AllowDeductionGuide=*/false, - /*ObjectType=*/nullptr, TemplateKWLoc, Id); + /*ObjectType=*/nullptr, &TemplateKWLoc, Id); // Perform the lookup. Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, IsUnevaluatedContext); diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 56a16b9e0271..f7a69c482e17 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -21,27 +21,22 @@ #include "clang/Sema/Scope.h" using namespace clang; -/// \brief Parse a template declaration, explicit instantiation, or +/// Parse a template declaration, explicit instantiation, or /// explicit specialization. -Decl * -Parser::ParseDeclarationStartingWithTemplate(unsigned Context, - SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs) { +Decl *Parser::ParseDeclarationStartingWithTemplate( + DeclaratorContext Context, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { ObjCDeclContextSwitch ObjCDC(*this); if (Tok.is(tok::kw_template) && NextToken().isNot(tok::less)) { - return ParseExplicitInstantiation(Context, - SourceLocation(), ConsumeToken(), - DeclEnd, AS); + return ParseExplicitInstantiation(Context, SourceLocation(), ConsumeToken(), + DeclEnd, AccessAttrs, AS); } - return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AS, - AccessAttrs); + return ParseTemplateDeclarationOrSpecialization(Context, DeclEnd, AccessAttrs, + AS); } - - -/// \brief Parse a template declaration or an explicit specialization. +/// Parse a template declaration or an explicit specialization. /// /// Template declarations include one or more template parameter lists /// and either the function or class template declaration. Explicit @@ -56,11 +51,9 @@ Parser::ParseDeclarationStartingWithTemplate(unsigned Context, /// /// explicit-specialization: [ C++ temp.expl.spec] /// 'template' '<' '>' declaration -Decl * -Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, - SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs) { +Decl *Parser::ParseTemplateDeclarationOrSpecialization( + DeclaratorContext Context, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { assert(Tok.isOneOf(tok::kw_export, tok::kw_template) && "Token does not start a template declaration."); @@ -149,15 +142,13 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, ParseScopeFlags TemplateScopeFlags(this, NewFlags, isSpecialization); // Parse the actual template declaration. - return ParseSingleDeclarationAfterTemplate(Context, - ParsedTemplateInfo(&ParamLists, - isSpecialization, - LastParamListWasEmpty), - ParsingTemplateParams, - DeclEnd, AS, AccessAttrs); + return ParseSingleDeclarationAfterTemplate( + Context, + ParsedTemplateInfo(&ParamLists, isSpecialization, LastParamListWasEmpty), + ParsingTemplateParams, DeclEnd, AccessAttrs, AS); } -/// \brief Parse a single declaration that declares a template, +/// Parse a single declaration that declares a template, /// template specialization, or explicit instantiation of a template. /// /// \param DeclEnd will receive the source location of the last token @@ -167,14 +158,10 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, /// declaration. Will be AS_none for namespace-scope declarations. /// /// \returns the new declaration. -Decl * -Parser::ParseSingleDeclarationAfterTemplate( - unsigned Context, - const ParsedTemplateInfo &TemplateInfo, - ParsingDeclRAIIObject &DiagsFromTParams, - SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs) { +Decl *Parser::ParseSingleDeclarationAfterTemplate( + DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, + ParsingDeclRAIIObject &DiagsFromTParams, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { assert(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate && "Template information required"); @@ -186,7 +173,7 @@ Parser::ParseSingleDeclarationAfterTemplate( return ParseStaticAssertDeclaration(DeclEnd); } - if (Context == Declarator::MemberContext) { + if (Context == DeclaratorContext::MemberContext) { // We are parsing a member template. ParseCXXClassMemberDeclaration(AS, AccessAttrs, TemplateInfo, &DiagsFromTParams); @@ -234,7 +221,7 @@ Parser::ParseSingleDeclarationAfterTemplate( DS.takeAttributesFrom(prefixAttrs); // Parse the declarator. - ParsingDeclarator DeclaratorInfo(*this, DS, (Declarator::TheContext)Context); + ParsingDeclarator DeclaratorInfo(*this, DS, (DeclaratorContext)Context); ParseDeclarator(DeclaratorInfo); // Error parsing the declarator? if (!DeclaratorInfo.hasName()) { @@ -255,7 +242,7 @@ Parser::ParseSingleDeclarationAfterTemplate( // 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) { Diag(Tok, diag::err_function_definition_not_allowed); SkipMalformedDecl(); return nullptr; @@ -271,7 +258,8 @@ Parser::ParseSingleDeclarationAfterTemplate( } if (TemplateInfo.Kind == ParsedTemplateInfo::ExplicitInstantiation) { - if (DeclaratorInfo.getName().getKind() != UnqualifiedId::IK_TemplateId) { + if (DeclaratorInfo.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) << 0; @@ -369,7 +357,7 @@ bool Parser::ParseTemplateParameters( /// template-parameter /// template-parameter-list ',' template-parameter bool -Parser::ParseTemplateParameterList(unsigned Depth, +Parser::ParseTemplateParameterList(const unsigned Depth, SmallVectorImpl<NamedDecl*> &TemplateParams) { while (1) { @@ -402,7 +390,7 @@ Parser::ParseTemplateParameterList(unsigned Depth, return true; } -/// \brief Determine whether the parser is at the start of a template +/// Determine whether the parser is at the start of a template /// type parameter. bool Parser::isStartOfTemplateTypeParameter() { if (Tok.is(tok::kw_class)) { @@ -487,6 +475,20 @@ NamedDecl *Parser::ParseTemplateParameter(unsigned Depth, unsigned Position) { if (Tok.is(tok::kw_template)) return ParseTemplateTemplateParameter(Depth, Position); + // Is there just a typo in the input code? ('typedef' instead of 'typename') + if (Tok.is(tok::kw_typedef)) { + Diag(Tok.getLocation(), diag::err_expected_template_parameter); + + Diag(Tok.getLocation(), diag::note_meant_to_use_typename) + << FixItHint::CreateReplacement(CharSourceRange::getCharRange( + Tok.getLocation(), Tok.getEndLoc()), + "typename"); + + Tok.setKind(tok::kw_typename); + + return ParseTypeParameter(Depth, Position); + } + // If it's none of the above, then it must be a parameter declaration. // NOTE: This will pick up errors in the closure of the template parameter // list (e.g., template < ; Check here to implement >> style closures. @@ -546,7 +548,7 @@ NamedDecl *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) { ParsedType DefaultArg; if (TryConsumeToken(tok::equal, EqualLoc)) DefaultArg = ParseTypeName(/*Range=*/nullptr, - Declarator::TemplateTypeArgContext).get(); + DeclaratorContext::TemplateTypeArgContext).get(); return Actions.ActOnTypeParameter(getCurScope(), TypenameKeyword, EllipsisLoc, KeyLoc, ParamName, NameLoc, Depth, Position, @@ -676,10 +678,10 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // declarators (parts of declarators?) are accepted for parameters. DeclSpec DS(AttrFactory); ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS_none, - DSC_template_param); + DeclSpecContext::DSC_template_param); // Parse this as a typename. - Declarator ParamDecl(DS, Declarator::TemplateParamContext); + Declarator ParamDecl(DS, DeclaratorContext::TemplateParamContext); ParseDeclarator(ParamDecl); if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) { Diag(Tok.getLocation(), diag::err_expected_template_parameter); @@ -739,7 +741,7 @@ void Parser::DiagnoseMisplacedEllipsisInDeclarator(SourceLocation EllipsisLoc, AlreadyHasEllipsis, D.hasName()); } -/// \brief Parses a '>' at the end of a template list. +/// Parses a '>' at the end of a template list. /// /// If this function encounters '>>', '>>>', '>=', or '>>=', it tries /// to determine if these tokens were supposed to be a '>' followed by @@ -760,6 +762,7 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, // What will be left once we've consumed the '>'. tok::TokenKind RemainingToken; const char *ReplacementStr = "> >"; + bool MergeWithNextToken = false; switch (Tok.getKind()) { default: @@ -785,6 +788,15 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, case tok::greaterequal: RemainingToken = tok::equal; ReplacementStr = "> ="; + + // Join two adjacent '=' tokens into one, for cases like: + // void (*p)() = f<int>; + // return f<int>==p; + if (NextToken().is(tok::equal) && + areTokensAdjacent(Tok, NextToken())) { + RemainingToken = tok::equalequal; + MergeWithNextToken = true; + } break; case tok::greatergreaterequal: @@ -792,22 +804,35 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, break; } - // This template-id is terminated by a token which starts with a '>'. Outside - // C++11, this is now error recovery, and in C++11, this is error recovery if - // the token isn't '>>' or '>>>'. - // '>>>' is for CUDA, where this sequence of characters is parsed into - // tok::greatergreatergreater, rather than two separate tokens. + // This template-id is terminated by a token that starts with a '>'. + // Outside C++11 and Objective-C, this is now error recovery. + // + // C++11 allows this when the token is '>>', and in CUDA + C++11 mode, we + // extend that treatment to also apply to the '>>>' token. // - // We always allow this for Objective-C type parameter and type argument - // lists. - RAngleLoc = Tok.getLocation(); + // Objective-C allows this in its type parameter / argument lists. + + SourceLocation TokBeforeGreaterLoc = PrevTokLocation; + SourceLocation TokLoc = Tok.getLocation(); Token Next = NextToken(); + + // Whether splitting the current token after the '>' would undesirably result + // in the remaining token pasting with the token after it. This excludes the + // MergeWithNextToken cases, which we've already handled. + bool PreventMergeWithNextToken = + (RemainingToken == tok::greater || + RemainingToken == tok::greatergreater) && + (Next.isOneOf(tok::greater, tok::greatergreater, + tok::greatergreatergreater, tok::equal, tok::greaterequal, + tok::greatergreaterequal, tok::equalequal)) && + areTokensAdjacent(Tok, Next); + + // Diagnose this situation as appropriate. if (!ObjCGenericList) { - // The source range of the '>>' or '>=' at the start of the token. - CharSourceRange ReplacementRange = - CharSourceRange::getCharRange(RAngleLoc, - Lexer::AdvanceToTokenCharacter(RAngleLoc, 2, PP.getSourceManager(), - getLangOpts())); + // The source range of the replaced token(s). + CharSourceRange ReplacementRange = CharSourceRange::getCharRange( + TokLoc, Lexer::AdvanceToTokenCharacter(TokLoc, 2, PP.getSourceManager(), + getLangOpts())); // A hint to put a space between the '>>'s. In order to make the hint as // clear as possible, we include the characters either side of the space in @@ -818,13 +843,7 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, // A hint to put another space after the token, if it would otherwise be // lexed differently. FixItHint Hint2; - if ((RemainingToken == tok::greater || - RemainingToken == tok::greatergreater) && - (Next.isOneOf(tok::greater, tok::greatergreater, - tok::greatergreatergreater, tok::equal, - tok::greaterequal, tok::greatergreaterequal, - tok::equalequal)) && - areTokensAdjacent(Tok, Next)) + if (PreventMergeWithNextToken) Hint2 = FixItHint::CreateInsertion(Next.getLocation(), " "); unsigned DiagId = diag::err_two_right_angle_brackets_need_space; @@ -833,55 +852,68 @@ bool Parser::ParseGreaterThanInTemplateList(SourceLocation &RAngleLoc, DiagId = diag::warn_cxx98_compat_two_right_angle_brackets; else if (Tok.is(tok::greaterequal)) DiagId = diag::err_right_angle_bracket_equal_needs_space; - Diag(Tok.getLocation(), DiagId) << Hint1 << Hint2; + Diag(TokLoc, DiagId) << Hint1 << Hint2; } + // Find the "length" of the resulting '>' token. This is not always 1, as it + // can contain escaped newlines. + unsigned GreaterLength = Lexer::getTokenPrefixLength( + TokLoc, 1, PP.getSourceManager(), getLangOpts()); + + // Annotate the source buffer to indicate that we split the token after the + // '>'. This allows us to properly find the end of, and extract the spelling + // of, the '>' token later. + RAngleLoc = PP.SplitToken(TokLoc, GreaterLength); + // Strip the initial '>' from the token. - Token PrevTok = Tok; - if (RemainingToken == tok::equal && Next.is(tok::equal) && - areTokensAdjacent(Tok, Next)) { - // Join two adjacent '=' tokens into one, for cases like: - // void (*p)() = f<int>; - // return f<int>==p; + bool CachingTokens = PP.IsPreviousCachedToken(Tok); + + Token Greater = Tok; + Greater.setLocation(RAngleLoc); + Greater.setKind(tok::greater); + Greater.setLength(GreaterLength); + + unsigned OldLength = Tok.getLength(); + if (MergeWithNextToken) { ConsumeToken(); - Tok.setKind(tok::equalequal); - Tok.setLength(Tok.getLength() + 1); - } else { - Tok.setKind(RemainingToken); - Tok.setLength(Tok.getLength() - 1); + OldLength += Tok.getLength(); } - Tok.setLocation(Lexer::AdvanceToTokenCharacter(RAngleLoc, 1, - PP.getSourceManager(), - getLangOpts())); - - // The advance from '>>' to '>' in a ObjectiveC template argument list needs - // to be properly reflected in the token cache to allow correct interaction - // between annotation and backtracking. - if (ObjCGenericList && PrevTok.getKind() == tok::greatergreater && - RemainingToken == tok::greater && PP.IsPreviousCachedToken(PrevTok)) { - PrevTok.setKind(RemainingToken); - PrevTok.setLength(1); - // Break tok::greatergreater into two tok::greater but only add the second - // one in case the client asks to consume the last token. + + Tok.setKind(RemainingToken); + Tok.setLength(OldLength - GreaterLength); + + // Split the second token if lexing it normally would lex a different token + // (eg, the fifth token in 'A<B>>>' should re-lex as '>', not '>>'). + SourceLocation AfterGreaterLoc = TokLoc.getLocWithOffset(GreaterLength); + if (PreventMergeWithNextToken) + AfterGreaterLoc = PP.SplitToken(AfterGreaterLoc, Tok.getLength()); + Tok.setLocation(AfterGreaterLoc); + + // Update the token cache to match what we just did if necessary. + if (CachingTokens) { + // If the previous cached token is being merged, delete it. + if (MergeWithNextToken) + PP.ReplacePreviousCachedToken({}); + if (ConsumeLastToken) - PP.ReplacePreviousCachedToken({PrevTok, Tok}); + PP.ReplacePreviousCachedToken({Greater, Tok}); else - PP.ReplacePreviousCachedToken({PrevTok}); + PP.ReplacePreviousCachedToken({Greater}); } - if (!ConsumeLastToken) { - // Since we're not supposed to consume the '>' token, we need to push - // this token and revert the current token back to the '>'. + if (ConsumeLastToken) { + PrevTokLocation = RAngleLoc; + } else { + PrevTokLocation = TokBeforeGreaterLoc; PP.EnterToken(Tok); - Tok.setKind(tok::greater); - Tok.setLength(1); - Tok.setLocation(RAngleLoc); + Tok = Greater; } + return false; } -/// \brief Parses a template-id that after the template name has +/// Parses a template-id that after the template name has /// already been parsed. /// /// This routine takes care of parsing the enclosed template argument @@ -923,7 +955,7 @@ Parser::ParseTemplateIdAfterTemplateName(bool ConsumeLastToken, /*ObjCGenericList=*/false); } -/// \brief Replace the tokens that form a simple-template-id with an +/// Replace the tokens that form a simple-template-id with an /// annotation token containing the complete template-id. /// /// The first token in the stream must be the name of a template that @@ -1015,12 +1047,12 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, Tok.setKind(tok::annot_template_id); IdentifierInfo *TemplateII = - TemplateName.getKind() == UnqualifiedId::IK_Identifier + TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier ? TemplateName.Identifier : nullptr; OverloadedOperatorKind OpKind = - TemplateName.getKind() == UnqualifiedId::IK_Identifier + TemplateName.getKind() == UnqualifiedIdKind::IK_Identifier ? OO_None : TemplateName.OperatorFunctionId.Operator; @@ -1044,7 +1076,7 @@ bool Parser::AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, return false; } -/// \brief Replaces a template-id annotation token with a type +/// Replaces a template-id annotation token with a type /// annotation token. /// /// If there was a failure when forming the type from the template-id, @@ -1089,12 +1121,12 @@ void Parser::AnnotateTemplateIdTokenAsType(bool IsClassName) { PP.AnnotateCachedTokens(Tok); } -/// \brief Determine whether the given token can end a template argument. +/// Determine whether the given token can end a template argument. static bool isEndOfTemplateArgument(Token Tok) { return Tok.isOneOf(tok::comma, tok::greater, tok::greatergreater); } -/// \brief Parse a C++ template template argument. +/// Parse a C++ template template argument. ParsedTemplateArgument Parser::ParseTemplateTemplateArgument() { if (!Tok.is(tok::identifier) && !Tok.is(tok::coloncolon) && !Tok.is(tok::annot_cxxscope)) @@ -1190,17 +1222,13 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { // argument before trying to disambiguate. EnterExpressionEvaluationContext EnterConstantEvaluated( - Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); + Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated, + /*LambdaContextDecl=*/nullptr, + /*ExprContext=*/Sema::ExpressionEvaluationContextRecord::EK_TemplateArgument); if (isCXXTypeId(TypeIdAsTemplateArgument)) { - SourceLocation Loc = Tok.getLocation(); - TypeResult TypeArg = ParseTypeName(/*Range=*/nullptr, - Declarator::TemplateTypeArgContext); - if (TypeArg.isInvalid()) - return ParsedTemplateArgument(); - - return ParsedTemplateArgument(ParsedTemplateArgument::Type, - TypeArg.get().getAsOpaquePtr(), - Loc); + TypeResult TypeArg = ParseTypeName( + /*Range=*/nullptr, DeclaratorContext::TemplateArgContext); + return Actions.ActOnTemplateTypeArgument(TypeArg); } // Try to parse a template template argument. @@ -1228,7 +1256,7 @@ ParsedTemplateArgument Parser::ParseTemplateArgument() { ExprArg.get(), Loc); } -/// \brief Determine whether the current tokens can only be parsed as a +/// Determine whether the current tokens can only be parsed as a /// template argument list (starting with the '<') and never as a '<' /// expression. bool Parser::IsTemplateArgumentList(unsigned Skip) { @@ -1290,27 +1318,26 @@ Parser::ParseTemplateArgumentList(TemplateArgList &TemplateArgs) { return false; } -/// \brief Parse a C++ explicit template instantiation +/// Parse a C++ explicit template instantiation /// (C++ [temp.explicit]). /// /// explicit-instantiation: /// 'extern' [opt] 'template' declaration /// /// Note that the 'extern' is a GNU extension and C++11 feature. -Decl *Parser::ParseExplicitInstantiation(unsigned Context, +Decl *Parser::ParseExplicitInstantiation(DeclaratorContext Context, SourceLocation ExternLoc, SourceLocation TemplateLoc, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS) { // This isn't really required here. ParsingDeclRAIIObject ParsingTemplateParams(*this, ParsingDeclRAIIObject::NoParent); - return ParseSingleDeclarationAfterTemplate(Context, - ParsedTemplateInfo(ExternLoc, - TemplateLoc), - ParsingTemplateParams, - DeclEnd, AS); + return ParseSingleDeclarationAfterTemplate( + Context, ParsedTemplateInfo(ExternLoc, TemplateLoc), + ParsingTemplateParams, DeclEnd, AccessAttrs, AS); } SourceRange Parser::ParsedTemplateInfo::getSourceRange() const { @@ -1328,7 +1355,7 @@ void Parser::LateTemplateParserCallback(void *P, LateParsedTemplate &LPT) { ((Parser *)P)->ParseLateTemplatedFuncDef(LPT); } -/// \brief Late parse a C++ function template in Microsoft mode. +/// Late parse a C++ function template in Microsoft mode. void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { if (!LPT.D) return; @@ -1419,7 +1446,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) { delete *I; } -/// \brief Lex a delayed template function for late parsing. +/// Lex a delayed template function for late parsing. void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) { tok::TokenKind kind = Tok.getKind(); if (!ConsumeAndStoreFunctionPrologue(Toks)) { @@ -1435,3 +1462,111 @@ void Parser::LexTemplateFunctionForLateParsing(CachedTokens &Toks) { } } } + +/// We've parsed something that could plausibly be intended to be a template +/// name (\p LHS) followed by a '<' token, and the following code can't possibly +/// be an expression. Determine if this is likely to be a template-id and if so, +/// diagnose it. +bool Parser::diagnoseUnknownTemplateId(ExprResult LHS, SourceLocation Less) { + TentativeParsingAction TPA(*this); + // FIXME: We could look at the token sequence in a lot more detail here. + if (SkipUntil(tok::greater, tok::greatergreater, tok::greatergreatergreater, + StopAtSemi | StopBeforeMatch)) { + TPA.Commit(); + + SourceLocation Greater; + ParseGreaterThanInTemplateList(Greater, true, false); + Actions.diagnoseExprIntendedAsTemplateName(getCurScope(), LHS, + Less, Greater); + return true; + } + + // There's no matching '>' token, this probably isn't supposed to be + // interpreted as a template-id. Parse it as an (ill-formed) comparison. + TPA.Revert(); + return false; +} + +void Parser::checkPotentialAngleBracket(ExprResult &PotentialTemplateName) { + assert(Tok.is(tok::less) && "not at a potential angle bracket"); + + bool DependentTemplateName = false; + if (!Actions.mightBeIntendedToBeTemplateName(PotentialTemplateName, + DependentTemplateName)) + return; + + // OK, this might be a name that the user intended to be parsed as a + // template-name, followed by a '<' token. Check for some easy cases. + + // If we have potential_template<>, then it's supposed to be a template-name. + if (NextToken().is(tok::greater) || + (getLangOpts().CPlusPlus11 && + NextToken().isOneOf(tok::greatergreater, tok::greatergreatergreater))) { + SourceLocation Less = ConsumeToken(); + SourceLocation Greater; + ParseGreaterThanInTemplateList(Greater, true, false); + Actions.diagnoseExprIntendedAsTemplateName( + getCurScope(), PotentialTemplateName, Less, Greater); + // FIXME: Perform error recovery. + PotentialTemplateName = ExprError(); + return; + } + + // If we have 'potential_template<type-id', assume it's supposed to be a + // template-name if there's a matching '>' later on. + { + // FIXME: Avoid the tentative parse when NextToken() can't begin a type. + TentativeParsingAction TPA(*this); + SourceLocation Less = ConsumeToken(); + if (isTypeIdUnambiguously() && + diagnoseUnknownTemplateId(PotentialTemplateName, Less)) { + TPA.Commit(); + // FIXME: Perform error recovery. + PotentialTemplateName = ExprError(); + return; + } + TPA.Revert(); + } + + // Otherwise, remember that we saw this in case we see a potentially-matching + // '>' token later on. + AngleBracketTracker::Priority Priority = + (DependentTemplateName ? AngleBracketTracker::DependentName + : AngleBracketTracker::PotentialTypo) | + (Tok.hasLeadingSpace() ? AngleBracketTracker::SpaceBeforeLess + : AngleBracketTracker::NoSpaceBeforeLess); + AngleBrackets.add(*this, PotentialTemplateName.get(), Tok.getLocation(), + Priority); +} + +bool Parser::checkPotentialAngleBracketDelimiter( + const AngleBracketTracker::Loc &LAngle, const Token &OpToken) { + // If a comma in an expression context is followed by a type that can be a + // template argument and cannot be an expression, then this is ill-formed, + // but might be intended to be part of a template-id. + if (OpToken.is(tok::comma) && isTypeIdUnambiguously() && + diagnoseUnknownTemplateId(LAngle.TemplateName, LAngle.LessLoc)) { + AngleBrackets.clear(*this); + return true; + } + + // If a context that looks like a template-id is followed by '()', then + // this is ill-formed, but might be intended to be a template-id + // followed by '()'. + if (OpToken.is(tok::greater) && Tok.is(tok::l_paren) && + NextToken().is(tok::r_paren)) { + Actions.diagnoseExprIntendedAsTemplateName( + getCurScope(), LAngle.TemplateName, LAngle.LessLoc, + OpToken.getLocation()); + AngleBrackets.clear(*this); + return true; + } + + // After a '>' (etc), we're no longer potentially in a construct that's + // intended to be treated as a template-id. + if (OpToken.is(tok::greater) || + (getLangOpts().CPlusPlus11 && + OpToken.isOneOf(tok::greatergreater, tok::greatergreatergreater))) + AngleBrackets.clear(*this); + return false; +} diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 5c206f4eab90..0603d8e75eea 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -401,7 +401,7 @@ struct Parser::ConditionDeclarationOrInitStatementState { } }; -/// \brief Disambiguates between a declaration in a condition, a +/// Disambiguates between a declaration in a condition, a /// simple-declaration in an init-statement, and an expression for /// a condition of a if/switch statement. /// @@ -472,7 +472,7 @@ Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement) { return ConditionOrInitStatement::Expression; } - /// \brief Determine whether the next set of tokens contains a type-id. + /// Determine whether the next set of tokens contains a type-id. /// /// The context parameter states what context we're parsing right /// now, which affects how this routine copes with the token @@ -553,7 +553,7 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) { return TPR == TPResult::True; } -/// \brief Returns true if this is a C++11 attribute-specifier. Per +/// Returns true if this is a C++11 attribute-specifier. Per /// C++11 [dcl.attr.grammar]p6, two consecutive left square bracket tokens /// always introduce an attribute. In Objective-C++11, this rule does not /// apply if either '[' begins a message-send. @@ -873,7 +873,8 @@ Parser::TPResult Parser::TryParseOperatorId() { /// template-id [TODO] /// Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, - bool mayHaveIdentifier) { + bool mayHaveIdentifier, + bool mayHaveDirectInit) { // declarator: // direct-declarator // ptr-operator declarator @@ -930,6 +931,9 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, return TPResult::False; } + if (mayHaveDirectInit) + return TPResult::Ambiguous; + while (1) { TPResult TPR(TPResult::Ambiguous); @@ -1015,6 +1019,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw___FUNCDNAME__: case tok::kw___FUNCSIG__: case tok::kw_L__FUNCTION__: + case tok::kw_L__FUNCSIG__: case tok::kw___PRETTY_FUNCTION__: case tok::kw___uuidof: #define TYPE_TRAIT(N,Spelling,K) \ @@ -1048,6 +1053,7 @@ Parser::isExpressionOrTypeSpecifierSimple(tok::TokenKind Kind) { case tok::kw_class: case tok::kw_typename: case tok::kw_wchar_t: + case tok::kw_char8_t: case tok::kw_char16_t: case tok::kw_char32_t: case tok::kw__Decimal32: @@ -1242,6 +1248,17 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case ANK_TentativeDecl: return TPResult::False; case ANK_TemplateName: + // In C++17, this could be a type template for class template argument + // deduction. Try to form a type annotation for it. If we're in a + // template template argument, we'll undo this when checking the + // validity of the argument. + if (getLangOpts().CPlusPlus17) { + if (TryAnnotateTypeOrScopeToken()) + return TPResult::Error; + if (Tok.isNot(tok::identifier)) + break; + } + // A bare type template-name which can't be a template template // argument is an error, and was probably intended to be a type. return GreaterThanIsOperator ? TPResult::True : TPResult::False; @@ -1341,6 +1358,11 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, // cv-qualifier case tok::kw_const: case tok::kw_volatile: + case tok::kw___private: + case tok::kw___local: + case tok::kw___global: + case tok::kw___constant: + case tok::kw___generic: // GNU case tok::kw_restrict: @@ -1420,8 +1442,6 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, *HasMissingTypename = true; return TPResult::Ambiguous; } - - // FIXME: Fails to either revert or commit the tentative parse! } else { // Try to resolve the name. If it doesn't exist, assume it was // intended to name a type and keep disambiguating. @@ -1431,19 +1451,33 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case ANK_TentativeDecl: return TPResult::False; case ANK_TemplateName: + // In C++17, this could be a type template for class template + // argument deduction. + if (getLangOpts().CPlusPlus17) { + if (TryAnnotateTypeOrScopeToken()) + return TPResult::Error; + if (Tok.isNot(tok::identifier)) + break; + } + // A bare type template-name which can't be a template template // argument is an error, and was probably intended to be a type. - return GreaterThanIsOperator ? TPResult::True : TPResult::False; + // In C++17, this could be class template argument deduction. + return (getLangOpts().CPlusPlus17 || GreaterThanIsOperator) + ? TPResult::True + : TPResult::False; case ANK_Unresolved: return HasMissingTypename ? TPResult::Ambiguous : TPResult::False; case ANK_Success: - // Annotated it, check again. - assert(Tok.isNot(tok::annot_cxxscope) || - NextToken().isNot(tok::identifier)); - return isCXXDeclarationSpecifier(BracedCastResult, - HasMissingTypename); + break; } + + // Annotated it, check again. + assert(Tok.isNot(tok::annot_cxxscope) || + NextToken().isNot(tok::identifier)); + return isCXXDeclarationSpecifier(BracedCastResult, + HasMissingTypename); } } return TPResult::False; @@ -1496,6 +1530,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, 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_bool: @@ -1587,6 +1622,7 @@ bool Parser::isCXXDeclarationSpecifierAType() { // simple-type-specifier 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_bool: @@ -1867,7 +1903,8 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() { return TPResult::Error; // cv-qualifier-seq - while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw_restrict)) + while (Tok.isOneOf(tok::kw_const, tok::kw_volatile, tok::kw___unaligned, + tok::kw_restrict)) ConsumeToken(); // ref-qualifier[opt] diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 8aa50a2c7f2a..7a0b29cbae86 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -20,11 +20,12 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "llvm/Support/Path.h" using namespace clang; namespace { -/// \brief A comment handler that passes comments found by the preprocessor +/// A comment handler that passes comments found by the preprocessor /// to the parser action. class ActionCommentHandler : public CommentHandler { Sema &S; @@ -77,7 +78,7 @@ DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) { return Diag(Tok.getLocation(), DiagID); } -/// \brief Emits a diagnostic suggesting parentheses surrounding a +/// Emits a diagnostic suggesting parentheses surrounding a /// given range. /// /// \param Loc The location where we'll emit the diagnostic. @@ -697,9 +698,8 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, return nullptr; case tok::semi: // Either a C++11 empty-declaration or attribute-declaration. - SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), - attrs.getList(), - Tok.getLocation()); + SingleDecl = + Actions.ActOnEmptyDeclaration(getCurScope(), attrs, Tok.getLocation()); ConsumeExtraSemi(OutsideFunction); break; case tok::r_brace: @@ -741,7 +741,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, break; } case tok::at: - return ParseObjCAtDirectives(); + return ParseObjCAtDirectives(attrs); case tok::minus: case tok::plus: if (!getLangOpts().ObjC1) { @@ -783,7 +783,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // A function definition cannot start with any of these keywords. { SourceLocation DeclEnd; - return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs); + return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs); } case tok::kw_static: @@ -793,7 +793,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 0; SourceLocation DeclEnd; - return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs); + return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs); } goto dont_know; @@ -804,7 +804,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // Inline namespaces. Allowed as an extension even in C++03. if (NextKind == tok::kw_namespace) { SourceLocation DeclEnd; - return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs); + return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs); } // Parse (then ignore) 'inline' prior to a template instantiation. This is @@ -813,7 +813,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 1; SourceLocation DeclEnd; - return ParseDeclaration(Declarator::FileContext, DeclEnd, attrs); + return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs); } } goto dont_know; @@ -828,8 +828,8 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc); SourceLocation DeclEnd; return Actions.ConvertDeclToDeclGroup( - ParseExplicitInstantiation(Declarator::FileContext, - ExternLoc, TemplateLoc, DeclEnd)); + ParseExplicitInstantiation(DeclaratorContext::FileContext, ExternLoc, + TemplateLoc, DeclEnd, attrs)); } goto dont_know; @@ -858,7 +858,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, return Actions.ConvertDeclToDeclGroup(SingleDecl); } -/// \brief Determine whether the current token, if it occurs after a +/// Determine whether the current token, if it occurs after a /// declarator, continues a declaration or declaration list. bool Parser::isDeclarationAfterDeclarator() { // Check for '= delete' or '= default' @@ -877,7 +877,7 @@ bool Parser::isDeclarationAfterDeclarator() { Tok.is(tok::l_paren)); // int X(0) -> not a function def [C++] } -/// \brief Determine whether the current token, if it occurs after a +/// Determine whether the current token, if it occurs after a /// declarator, indicates the start of a function definition. bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { assert(Declarator.isFunctionDeclarator() && "Isn't a function declarator"); @@ -919,12 +919,13 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, AccessSpecifier AS) { MaybeParseMicrosoftAttributes(DS.getAttributes()); // Parse the common declaration-specifiers piece. - ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level); + ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, + DeclSpecContext::DSC_top_level); // If we had a free-standing type definition with a missing semicolon, we // may get this far before the problem becomes obvious. - if (DS.hasTagDefinition() && - DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_top_level)) + if (DS.hasTagDefinition() && DiagnoseMissingSemiAfterTagDefinition( + DS, AS, DeclSpecContext::DSC_top_level)) return nullptr; // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" @@ -1004,11 +1005,11 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, if (getLangOpts().CPlusPlus && isTokenStringLiteral() && DS.getStorageClassSpec() == DeclSpec::SCS_extern && DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) { - Decl *TheDecl = ParseLinkage(DS, Declarator::FileContext); + Decl *TheDecl = ParseLinkage(DS, DeclaratorContext::FileContext); return Actions.ConvertDeclToDeclGroup(TheDecl); } - return ParseDeclGroup(DS, Declarator::FileContext); + return ParseDeclGroup(DS, DeclaratorContext::FileContext); } Parser::DeclGroupPtrTy @@ -1088,15 +1089,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Check to make sure that any normal attributes are allowed to be on // a definition. Late parsed attributes are checked at the end. if (Tok.isNot(tok::equal)) { - AttributeList *DtorAttrs = D.getAttributes(); - while (DtorAttrs) { - if (DtorAttrs->isKnownToGCC() && - !DtorAttrs->isCXX11Attribute()) { - Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition) - << DtorAttrs->getName(); - } - DtorAttrs = DtorAttrs->getNext(); - } + for (const ParsedAttr &AL : D.getAttributes()) + if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) + Diag(AL.getLoc(), diag::warn_attribute_on_function_definition) + << AL.getName(); } // In delayed template parsing mode, for function template we consume the @@ -1313,7 +1309,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { } // Parse the first declarator attached to this declspec. - Declarator ParmDeclarator(DS, Declarator::KNRTypeListContext); + Declarator ParmDeclarator(DS, DeclaratorContext::KNRTypeListContext); ParseDeclarator(ParmDeclarator); // Handle the full declarator list. @@ -1450,7 +1446,7 @@ ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { return Result; } -/// \brief Get the TemplateIdAnnotation from the token and put it in the +/// Get the TemplateIdAnnotation from the token and put it in the /// cleanup pool so that it gets destroyed when parsing the current top level /// declaration is finished. TemplateIdAnnotation *Parser::takeTemplateIdAnnotation(const Token &tok) { @@ -1478,7 +1474,7 @@ void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) { PP.AnnotateCachedTokens(Tok); } -/// \brief Attempt to classify the name at the current token position. This may +/// Attempt to classify the name at the current token position. This may /// form a type, scope or primary expression annotation, or replace the token /// with a typo-corrected keyword. This is only appropriate when the current /// name must refer to an entity which has already been declared. @@ -1763,7 +1759,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { return TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation); } -/// \brief Try to annotate a type or scope token, having already parsed an +/// Try to annotate a type or scope token, having already parsed an /// optional scope specifier. \p IsNewScope should be \c true unless the scope /// specifier was extracted from an existing tok::annot_cxxscope annotation. bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, @@ -1774,8 +1770,8 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS, false, NextToken().is(tok::period), nullptr, /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo*/ true, - /*IsClassTemplateDeductionContext*/GreaterThanIsOperator)) { + /*NonTrivialTypeSourceInfo*/true, + /*IsClassTemplateDeductionContext*/true)) { SourceLocation BeginLoc = Tok.getLocation(); if (SS.isNotEmpty()) // it was a C++ qualified type name. BeginLoc = SS.getBeginLoc(); @@ -2001,7 +1997,7 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) { if (ParseUnqualifiedId( Result.SS, /*EnteringContext*/false, /*AllowDestructorName*/true, /*AllowConstructorName*/true, /*AllowDeductionGuide*/false, nullptr, - TemplateKWLoc, Result.Name)) { + &TemplateKWLoc, Result.Name)) { T.skipToEnd(); return true; } @@ -2122,6 +2118,7 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc) { assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import) : Tok.isObjCAtKeyword(tok::objc_import)) && "Improper start to module import"); + bool IsObjCAtImport = Tok.isObjCAtKeyword(tok::objc_import); SourceLocation ImportLoc = ConsumeToken(); SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc; @@ -2145,6 +2142,16 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc) { if (Import.isInvalid()) return nullptr; + // Using '@import' in framework headers requires modules to be enabled so that + // the header is parseable. Emit a warning to make the user aware. + if (IsObjCAtImport && AtLoc.isValid()) { + auto &SrcMgr = PP.getSourceManager(); + auto *FE = SrcMgr.getFileEntryForID(SrcMgr.getFileID(AtLoc)); + if (FE && llvm::sys::path::parent_path(FE->getDir()->getName()) + .endswith(".framework")) + Diags.Report(AtLoc, diag::warn_atimport_in_framework_header); + } + return Import.get(); } @@ -2184,7 +2191,7 @@ bool Parser::ParseModuleName( } } -/// \brief Try recover parser when module annotation appears where it must not +/// Try recover parser when module annotation appears where it must not /// be found. /// \returns false if the recover was successful and parsing may be continued, or /// true if parser must bail out to top level and handle the token there. @@ -2249,7 +2256,7 @@ bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID, return true; } - if (getDepth() < MaxDepth) + if (getDepth() < P.getLangOpts().BracketDepth) return false; return diagnoseOverflow(); |