diff options
Diffstat (limited to 'lib/Parse')
-rw-r--r-- | lib/Parse/ParseAST.cpp | 17 | ||||
-rw-r--r-- | lib/Parse/ParseCXXInlineMethods.cpp | 10 | ||||
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 77 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 365 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 44 | ||||
-rw-r--r-- | lib/Parse/ParseExprCXX.cpp | 55 | ||||
-rw-r--r-- | lib/Parse/ParseObjc.cpp | 102 | ||||
-rw-r--r-- | lib/Parse/ParseOpenMP.cpp | 377 | ||||
-rw-r--r-- | lib/Parse/ParsePragma.cpp | 47 | ||||
-rw-r--r-- | lib/Parse/ParseStmt.cpp | 63 | ||||
-rw-r--r-- | lib/Parse/ParseStmtAsm.cpp | 40 | ||||
-rw-r--r-- | lib/Parse/ParseTemplate.cpp | 13 | ||||
-rw-r--r-- | lib/Parse/ParseTentative.cpp | 3 | ||||
-rw-r--r-- | lib/Parse/Parser.cpp | 86 |
14 files changed, 915 insertions, 384 deletions
diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp index 6727afc..ccf9479 100644 --- a/lib/Parse/ParseAST.cpp +++ b/lib/Parse/ParseAST.cpp @@ -30,6 +30,21 @@ using namespace clang; namespace { +/// Resets LLVM's pretty stack state so that stack traces are printed correctly +/// when there are nested CrashRecoveryContexts and the inner one recovers from +/// a crash. +class ResetStackCleanup + : public llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, + const void> { +public: + ResetStackCleanup(llvm::CrashRecoveryContext *Context, const void *Top) + : llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, const void>( + Context, Top) {} + void recoverResources() override { + llvm::RestorePrettyStackState(resource); + } +}; + /// If a crash happens while the parser is active, an entry is printed for it. class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { const Parser &P; @@ -113,6 +128,8 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); Parser &P = *ParseOP.get(); + llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup> + CleanupPrettyStack(llvm::SavePrettyStackState()); PrettyStackTraceParserEntry CrashInfo(P); // Recover resources if we crash before exiting this method. diff --git a/lib/Parse/ParseCXXInlineMethods.cpp b/lib/Parse/ParseCXXInlineMethods.cpp index ab1f97d..e536644 100644 --- a/lib/Parse/ParseCXXInlineMethods.cpp +++ b/lib/Parse/ParseCXXInlineMethods.cpp @@ -67,8 +67,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, SourceLocation KWEndLoc = Tok.getEndLoc().getLocWithOffset(-1); if (TryConsumeToken(tok::kw_delete, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 - ? diag::warn_cxx98_compat_deleted_function - : diag::ext_deleted_function); + ? diag::warn_cxx98_compat_defaulted_deleted_function + : diag::ext_defaulted_deleted_function) + << 1 /* deleted */; Actions.SetDeclDeleted(FnD, KWLoc); Delete = true; if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) { @@ -76,8 +77,9 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS, } } else if (TryConsumeToken(tok::kw_default, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 - ? diag::warn_cxx98_compat_defaulted_function - : diag::ext_defaulted_function); + ? diag::warn_cxx98_compat_defaulted_deleted_function + : diag::ext_defaulted_deleted_function) + << 0 /* defaulted */; Actions.SetDeclDefaulted(FnD, KWLoc); if (auto *DeclAsFunction = dyn_cast<FunctionDecl>(FnD)) { DeclAsFunction->setRangeEnd(KWEndLoc); diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 45878b9..e69bb27 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -1,4 +1,4 @@ -//===--- ParseDecl.cpp - Declaration Parsing ------------------------------===// +//===--- ParseDecl.cpp - Declaration Parsing --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -24,9 +24,11 @@ #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/PrettyDeclStackTrace.h" #include "clang/Sema/Scope.h" +#include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringSwitch.h" + using namespace clang; //===----------------------------------------------------------------------===// @@ -67,7 +69,6 @@ TypeResult Parser::ParseTypeName(SourceRange *Range, return Actions.ActOnTypeName(getCurScope(), DeclaratorInfo); } - /// isAttributeLateParsed - Return true if the attribute has arguments that /// require late parsing. static bool isAttributeLateParsed(const IdentifierInfo &II) { @@ -387,7 +388,7 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, // If the attribute isn't known, we will not attempt to parse any // arguments. if (!hasAttribute(AttrSyntax::Declspec, nullptr, AttrName, - getTargetInfo().getTriple(), getLangOpts())) { + getTargetInfo(), getLangOpts())) { // Eat the left paren, then skip to the ending right paren. ConsumeParen(); SkipUntil(tok::r_paren); @@ -532,9 +533,7 @@ bool Parser::ParseMicrosoftDeclSpecArgs(IdentifierInfo *AttrName, /// extended-decl-modifier extended-decl-modifier-seq void Parser::ParseMicrosoftDeclSpecs(ParsedAttributes &Attrs, SourceLocation *End) { - assert((getLangOpts().MicrosoftExt || getLangOpts().Borland || - getLangOpts().CUDA) && - "Incorrect language options for parsing __declspec"); + assert(getLangOpts().DeclSpecKeyword && "__declspec keyword is not enabled"); assert(Tok.is(tok::kw___declspec) && "Not a declspec!"); while (Tok.is(tok::kw___declspec)) { @@ -1155,7 +1154,6 @@ void Parser::ParseLexedAttributes(ParsingClass &Class) { Class.TagOrTemplate); } - /// \brief Parse all attributes in LAs, and attach them to Decl D. void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, bool EnterScope, bool OnDefinition) { @@ -1170,7 +1168,6 @@ void Parser::ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, LAs.clear(); } - /// \brief 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 @@ -1468,15 +1465,13 @@ Parser::DeclGroupPtrTy Parser::ParseDeclaration(unsigned Context, if (getLangOpts().CPlusPlus && NextToken().is(tok::kw_namespace)) { ProhibitAttributes(attrs); SourceLocation InlineLoc = ConsumeToken(); - SingleDecl = ParseNamespace(Context, DeclEnd, InlineLoc); - break; + return ParseNamespace(Context, DeclEnd, InlineLoc); } return ParseSimpleDeclaration(Context, DeclEnd, attrs, true); case tok::kw_namespace: ProhibitAttributes(attrs); - SingleDecl = ParseNamespace(Context, DeclEnd); - break; + return ParseNamespace(Context, DeclEnd); case tok::kw_using: SingleDecl = ParseUsingDirectiveOrDeclaration(Context, ParsedTemplateInfo(), DeclEnd, attrs, &OwnedType); @@ -1979,8 +1974,8 @@ Decl *Parser::ParseDeclarationAfterDeclaratorAndAttributes( // Recover as if it were an explicit specialization. TemplateParameterLists FakedParamLists; FakedParamLists.push_back(Actions.ActOnTemplateParameterList( - 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr, - 0, LAngleLoc)); + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None, + LAngleLoc)); ThisDecl = Actions.ActOnTemplateDeclarator(getCurScope(), FakedParamLists, D); @@ -2161,7 +2156,7 @@ void Parser::ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS, DS.ClearStorageClassSpecs(); } - // Issue diagnostic and remove function specfier if present. + // Issue diagnostic and remove function specifier if present. if (Specs & DeclSpec::PQ_FunctionSpecifier) { if (DS.isInlineSpecified()) Diag(DS.getInlineSpecLoc(), diag::err_typename_invalid_functionspec); @@ -2203,7 +2198,6 @@ static bool isValidAfterIdentifierInDeclarator(const Token &T) { tok::colon); } - /// ParseImplicitInt - This method is called when we have an non-typename /// identifier in a declspec (which normally terminates the decl spec) when /// the declspec has no type specifier. In this case, the declspec is either @@ -2621,8 +2615,6 @@ Parser::DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, /// [OpenCL] '__kernel' /// 'friend': [C++ dcl.friend] /// 'constexpr': [C++0x dcl.constexpr] - -/// void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, @@ -2647,6 +2639,18 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, const char *PrevSpec = nullptr; unsigned DiagID = 0; + // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL + // implementation for VS2013 uses _Atomic as an identifier for one of the + // classes in <atomic>. + // + // A typedef declaration containing _Atomic<...> is among the places where + // the class is used. If we are currently parsing such a declaration, treat + // the token as an identifier. + if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) && + DS.getStorageClassSpec() == clang::DeclSpec::SCS_typedef && + !DS.hasTypeSpecifier() && GetLookAheadToken(1).is(tok::less)) + Tok.setKind(tok::identifier); + SourceLocation Loc = Tok.getLocation(); switch (Tok.getKind()) { @@ -2665,7 +2669,7 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // If this is not a declaration specifier token, we're done reading decl // specifiers. First verify that DeclSpec's are consistent. - DS.Finish(Diags, PP, Policy); + DS.Finish(Actions, Policy); return; case tok::l_square: @@ -2780,8 +2784,8 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // arguments. Complain, then parse it as a type as the user // intended. Diag(TemplateId->TemplateNameLoc, - diag::err_out_of_line_template_id_names_constructor) - << TemplateId->Name; + diag::err_out_of_line_template_id_type_names_constructor) + << TemplateId->Name << 0 /* template name */; } DS.getTypeSpecScope() = SS; @@ -2826,8 +2830,9 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, // looked at the declarator, and the user probably meant this // to be a type. Complain that it isn't supposed to be treated // as a type, then proceed to parse it as a type. - Diag(Next.getLocation(), diag::err_out_of_line_type_names_constructor) - << Next.getIdentifierInfo(); + Diag(Next.getLocation(), + diag::err_out_of_line_template_id_type_names_constructor) + << Next.getIdentifierInfo() << 1 /* type */; } ParsedType TypeRep = Actions.getTypeName(*Next.getIdentifierInfo(), @@ -3133,6 +3138,11 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS, PrevSpec, DiagID, Policy); isStorageClass = true; break; + case tok::kw___auto_type: + Diag(Tok, diag::ext_auto_type); + isInvalid = DS.SetTypeSpecType(DeclSpec::TST_auto_type, Loc, PrevSpec, + DiagID, Policy); + break; case tok::kw_register: isInvalid = DS.SetStorageClassSpec(Actions, DeclSpec::SCS_register, Loc, PrevSpec, DiagID, Policy); @@ -3577,7 +3587,8 @@ void Parser::ParseStructUnionBody(SourceLocation RecordLoc, SmallVector<Decl *, 32> FieldDecls; // While we still have something to read, read the declarations in the struct. - while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { + while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && + Tok.isNot(tok::eof)) { // Each iteration of this loop reads one struct-declaration. // Check for extraneous top-level semicolon. @@ -4434,6 +4445,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) { case tok::kw___private_extern__: case tok::kw_static: case tok::kw_auto: + case tok::kw___auto_type: case tok::kw_register: case tok::kw___thread: case tok::kw_thread_local: @@ -4807,7 +4819,7 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, DoneWithTypeQuals: // If this is not a type-qualifier token, we're done reading type // qualifiers. First verify that DeclSpec's are consistent. - DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy()); + DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy()); if (EndLoc.isValid()) DS.SetRangeEnd(EndLoc); return; @@ -4822,7 +4834,6 @@ void Parser::ParseTypeQualifierListOpt(DeclSpec &DS, unsigned AttrReqs, } } - /// ParseDeclarator - Parse and verify a newly-initialized declarator. /// void Parser::ParseDeclarator(Declarator &D) { @@ -5187,6 +5198,15 @@ void Parser::ParseDirectDeclarator(Declarator &D) { } goto PastIdentifier; } + + if (D.getCXXScopeSpec().isNotEmpty()) { + // We have a scope specifier but no following unqualified-id. + Diag(PP.getLocForEndOfToken(D.getCXXScopeSpec().getEndLoc()), + diag::err_expected_unqualified_id) + << /*C++*/1; + D.SetIdentifier(nullptr, Tok.getLocation()); + goto PastIdentifier; + } } else if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) { assert(!getLangOpts().CPlusPlus && "There's a C++-specific check for tok::identifier above"); @@ -5470,7 +5490,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, SmallVector<ParsedType, 2> DynamicExceptions; SmallVector<SourceRange, 2> DynamicExceptionRanges; ExprResult NoexceptExpr; - CachedTokens *ExceptionSpecTokens = 0; + CachedTokens *ExceptionSpecTokens = nullptr; ParsedAttributes FnAttrs(AttrFactory); TypeResult TrailingReturnType; @@ -5608,7 +5628,7 @@ void Parser::ParseFunctionDeclarator(Declarator &D, VolatileQualifierLoc, RestrictQualifierLoc, /*MutableLoc=*/SourceLocation(), - ESpecType, ESpecRange.getBegin(), + ESpecType, ESpecRange, DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), @@ -6227,7 +6247,6 @@ void Parser::ParseAtomicSpecifier(DeclSpec &DS) { Diag(StartLoc, DiagID) << PrevSpec; } - /// TryAltiVecVectorTokenOutOfLine - Out of line body that should only be called /// from TryAltiVecVectorToken. bool Parser::TryAltiVecVectorTokenOutOfLine() { diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index e347d4e..a4de975 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -1,4 +1,4 @@ -//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -----------------------===// +//===--- ParseDeclCXX.cpp - C++ Declaration Parsing -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -26,6 +26,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/ADT/SmallString.h" + using namespace clang; /// ParseNamespace - We know that the current token is a namespace keyword. This @@ -54,9 +55,9 @@ using namespace clang; /// namespace-alias-definition: [C++ 7.3.2: namespace.alias] /// 'namespace' identifier '=' qualified-namespace-specifier ';' /// -Decl *Parser::ParseNamespace(unsigned Context, - SourceLocation &DeclEnd, - SourceLocation InlineLoc) { +Parser::DeclGroupPtrTy Parser::ParseNamespace(unsigned Context, + SourceLocation &DeclEnd, + SourceLocation InlineLoc) { assert(Tok.is(tok::kw_namespace) && "Not a namespace!"); SourceLocation NamespaceLoc = ConsumeToken(); // eat the 'namespace'. ObjCDeclContextSwitch ObjCDC(*this); @@ -64,7 +65,7 @@ Decl *Parser::ParseNamespace(unsigned Context, if (Tok.is(tok::code_completion)) { Actions.CodeCompleteNamespaceDecl(getCurScope()); cutOffParsing(); - return nullptr; + return DeclGroupPtrTy(); } SourceLocation IdentLoc; @@ -108,16 +109,16 @@ Decl *Parser::ParseNamespace(unsigned Context, Diag(Tok, diag::err_expected) << tok::identifier; // Skip to end of the definition and eat the ';'. SkipUntil(tok::semi); - return nullptr; + return DeclGroupPtrTy(); } if (attrLoc.isValid()) Diag(attrLoc, diag::err_unexpected_namespace_attributes_alias); if (InlineLoc.isValid()) Diag(InlineLoc, diag::err_inline_namespace_alias) << FixItHint::CreateRemoval(InlineLoc); - return ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd); - } - + Decl *NSAlias = ParseNamespaceAlias(NamespaceLoc, IdentLoc, Ident, DeclEnd); + return Actions.ConvertDeclToDeclGroup(NSAlias); +} BalancedDelimiterTracker T(*this, tok::l_brace); if (T.consumeOpen()) { @@ -125,7 +126,7 @@ Decl *Parser::ParseNamespace(unsigned Context, Diag(Tok, diag::err_expected) << tok::l_brace; else Diag(Tok, diag::err_expected_either) << tok::identifier << tok::l_brace; - return nullptr; + return DeclGroupPtrTy(); } if (getCurScope()->isClassScope() || getCurScope()->isTemplateParamScope() || @@ -133,7 +134,7 @@ Decl *Parser::ParseNamespace(unsigned Context, getCurScope()->getFnParent()) { Diag(T.getOpenLocation(), diag::err_namespace_nonnamespace_scope); SkipUntil(tok::r_brace); - return nullptr; + return DeclGroupPtrTy(); } if (ExtraIdent.empty()) { @@ -180,10 +181,11 @@ Decl *Parser::ParseNamespace(unsigned Context, // Enter a scope for the namespace. ParseScope NamespaceScope(this, Scope::DeclScope); + UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr; Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident, T.getOpenLocation(), - attrs.getList()); + attrs.getList(), ImplicitUsingDirectiveDecl); PrettyDeclStackTraceEntry CrashInfo(Actions, NamespcDecl, NamespaceLoc, "parsing namespace"); @@ -198,8 +200,9 @@ Decl *Parser::ParseNamespace(unsigned Context, DeclEnd = T.getCloseLocation(); Actions.ActOnFinishNamespaceDef(NamespcDecl, DeclEnd); - - return NamespcDecl; + + return Actions.ConvertDeclToDeclGroup(NamespcDecl, + ImplicitUsingDirectiveDecl); } /// ParseInnerNamespace - Parse the contents of a namespace. @@ -210,7 +213,8 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc, ParsedAttributes &attrs, BalancedDelimiterTracker &Tracker) { if (index == Ident.size()) { - while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { + while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && + Tok.isNot(tok::eof)) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); @@ -228,17 +232,19 @@ void Parser::ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc, // FIXME: Preserve the source information through to the AST rather than // 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()); + attrs.getList(), ImplicitUsingDirectiveDecl); + assert(!ImplicitUsingDirectiveDecl && + "nested namespace definition cannot define anonymous namespace"); ParseInnerNamespace(IdentLoc, Ident, NamespaceLoc, ++index, InlineLoc, attrs, Tracker); NamespaceScope.Exit(); - Actions.ActOnFinishNamespaceDef(NamespcDecl, Tracker.getCloseLocation()); } @@ -279,8 +285,8 @@ Decl *Parser::ParseNamespaceAlias(SourceLocation NamespaceLoc, if (ExpectAndConsume(tok::semi, diag::err_expected_semi_after_namespace_name)) SkipUntil(tok::semi); - return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc, Alias, - SS, IdentLoc, Ident); + return Actions.ActOnNamespaceAliasDef(getCurScope(), NamespaceLoc, AliasLoc, + Alias, SS, IdentLoc, Ident); } /// ParseLinkage - We know that the current token is a string_literal @@ -393,8 +399,8 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, // Template parameters are always an error here. if (TemplateInfo.Kind) { SourceRange R = TemplateInfo.getSourceRange(); - Diag(UsingLoc, diag::err_templated_using_directive) - << R << FixItHint::CreateRemoval(R); + Diag(UsingLoc, diag::err_templated_using_directive_declaration) + << 0 /* directive */ << R << FixItHint::CreateRemoval(R); } return ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs); @@ -546,7 +552,8 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, } else if (ParseUnqualifiedId( SS, /*EnteringContext=*/false, /*AllowDestructorName=*/true, - /*AllowConstructorName=*/NextToken().isNot(tok::equal), + /*AllowConstructorName=*/!(Tok.is(tok::identifier) && + NextToken().is(tok::equal)), ParsedType(), TemplateKWLoc, Name)) { SkipUntil(tok::semi); return nullptr; @@ -643,8 +650,8 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, // template <...> using id = type; if (TemplateInfo.Kind && !IsAliasDecl) { SourceRange R = TemplateInfo.getSourceRange(); - Diag(UsingLoc, diag::err_templated_using_declaration) - << R << FixItHint::CreateRemoval(R); + Diag(UsingLoc, diag::err_templated_using_directive_declaration) + << 1 /* declaration */ << R << FixItHint::CreateRemoval(R); // Unfortunately, we have to bail out instead of recovering by // ignoring the parameters, just in case the nested name specifier @@ -1307,6 +1314,35 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // allow libstdc++ 4.2 and libc++ to work properly. TryKeywordIdentFallback(true); + struct PreserveAtomicIdentifierInfoRAII { + PreserveAtomicIdentifierInfoRAII(Token &Tok, bool Enabled) + : AtomicII(nullptr) { + if (!Enabled) + return; + assert(Tok.is(tok::kw__Atomic)); + AtomicII = Tok.getIdentifierInfo(); + AtomicII->revertTokenIDToIdentifier(); + Tok.setKind(tok::identifier); + } + ~PreserveAtomicIdentifierInfoRAII() { + if (!AtomicII) + return; + AtomicII->revertIdentifierToTokenID(tok::kw__Atomic); + } + IdentifierInfo *AtomicII; + }; + + // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL + // implementation for VS2013 uses _Atomic as an identifier for one of the + // classes in <atomic>. When we are parsing 'struct _Atomic', don't consider + // '_Atomic' to be a keyword. We are careful to undo this so that clang can + // use '_Atomic' in its own header files. + bool ShouldChangeAtomicToIdentifier = getLangOpts().MSVCCompat && + Tok.is(tok::kw__Atomic) && + TagType == DeclSpec::TST_struct; + PreserveAtomicIdentifierInfoRAII AtomicTokenGuard( + Tok, ShouldChangeAtomicToIdentifier); + // Parse the (optional) nested-name-specifier. CXXScopeSpec &SS = DS.getTypeSpecScope(); if (getLangOpts().CPlusPlus) { @@ -1626,8 +1662,8 @@ void Parser::ParseClassSpecifier(tok::TokenKind TagTokKind, // "template<>", so that we treat this construct as a class // template specialization. FakedParamLists.push_back(Actions.ActOnTemplateParameterList( - 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr, - 0, LAngleLoc)); + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None, + LAngleLoc)); TemplateParams = &FakedParamLists; } } @@ -1808,7 +1844,7 @@ void Parser::ParseBaseClause(Decl *ClassDecl) { } // Attach the base specifiers - Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo.data(), BaseInfo.size()); + Actions.ActOnBaseSpecifiers(ClassDecl, BaseInfo); } /// ParseBaseSpecifier - Parse a C++ base-specifier. A base-specifier is @@ -1858,6 +1894,15 @@ BaseResult Parser::ParseBaseSpecifier(Decl *ClassDecl) { CheckMisplacedCXX11Attribute(Attributes, StartLoc); // Parse the class-name. + + // HACK: MSVC doesn't consider _Atomic to be a keyword and its STL + // implementation for VS2013 uses _Atomic as an identifier for one of the + // classes in <atomic>. Treat '_Atomic' to be an identifier when we are + // parsing the class-name for a base specifier. + if (getLangOpts().MSVCCompat && Tok.is(tok::kw__Atomic) && + NextToken().is(tok::less)) + Tok.setKind(tok::identifier); + SourceLocation EndLocation; SourceLocation BaseLoc; TypeResult BaseType = ParseBaseTypeSpecifier(BaseLoc, EndLocation); @@ -1928,7 +1973,7 @@ void Parser::HandleMemberFunctionDeclDelays(Declarator& DeclaratorInfo, // Stash the exception-specification tokens in the late-pased method. LateMethod->ExceptionSpecTokens = FTI.ExceptionSpecTokens; - FTI.ExceptionSpecTokens = 0; + FTI.ExceptionSpecTokens = nullptr; // Push tokens for each parameter. Those that do not have // defaults will be NULL. @@ -2195,8 +2240,9 @@ void Parser::MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq( /// constant-initializer: /// '=' constant-expression /// -void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, - AttributeList *AccessAttrs, +Parser::DeclGroupPtrTy +Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, + AttributeList *AccessAttrs, const ParsedTemplateInfo &TemplateInfo, ParsingDeclRAIIObject *TemplateDiags) { if (Tok.is(tok::at)) { @@ -2207,7 +2253,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, ConsumeToken(); SkipUntil(tok::r_brace, StopAtSemi); - return; + return DeclGroupPtrTy(); } // Turn on colon protection early, while parsing declspec, although there is @@ -2241,7 +2287,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (SS.isInvalid()) { SkipUntil(tok::semi); - return; + return DeclGroupPtrTy(); } // Try to parse an unqualified-id. @@ -2250,24 +2296,21 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (ParseUnqualifiedId(SS, false, true, true, ParsedType(), TemplateKWLoc, Name)) { SkipUntil(tok::semi); - return; + return DeclGroupPtrTy(); } // TODO: recover from mistakenly-qualified operator declarations. if (ExpectAndConsume(tok::semi, diag::err_expected_after, "access declaration")) { SkipUntil(tok::semi); - return; + return DeclGroupPtrTy(); } - Actions.ActOnUsingDeclaration(getCurScope(), AS, - /* HasUsingKeyword */ false, - SourceLocation(), - SS, Name, - /* AttrList */ nullptr, - /* HasTypenameKeyword */ false, - SourceLocation()); - return; + return DeclGroupPtrTy::make(DeclGroupRef(Actions.ActOnUsingDeclaration( + getCurScope(), AS, + /* HasUsingKeyword */ false, SourceLocation(), SS, Name, + /* AttrList */ nullptr, + /* HasTypenameKeyword */ false, SourceLocation()))); } } @@ -2276,17 +2319,17 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (!TemplateInfo.Kind && Tok.isOneOf(tok::kw_static_assert, tok::kw__Static_assert)) { SourceLocation DeclEnd; - ParseStaticAssertDeclaration(DeclEnd); - return; + return DeclGroupPtrTy::make( + DeclGroupRef(ParseStaticAssertDeclaration(DeclEnd))); } if (Tok.is(tok::kw_template)) { assert(!TemplateInfo.TemplateParams && "Nested template improperly parsed?"); SourceLocation DeclEnd; - ParseDeclarationStartingWithTemplate(Declarator::MemberContext, DeclEnd, - AS, AccessAttrs); - return; + return DeclGroupPtrTy::make( + DeclGroupRef(ParseDeclarationStartingWithTemplate( + Declarator::MemberContext, DeclEnd, AS, AccessAttrs))); } // Handle: member-declaration ::= '__extension__' member-declaration @@ -2318,13 +2361,12 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::kw_namespace)) { Diag(UsingLoc, diag::err_using_namespace_in_class); SkipUntil(tok::semi, StopBeforeMatch); - } else { - SourceLocation DeclEnd; - // Otherwise, it must be a using-declaration or an alias-declaration. - ParseUsingDeclaration(Declarator::MemberContext, TemplateInfo, - UsingLoc, DeclEnd, AS); + return DeclGroupPtrTy(); } - return; + SourceLocation DeclEnd; + // Otherwise, it must be a using-declaration or an alias-declaration. + return DeclGroupPtrTy::make(DeclGroupRef(ParseUsingDeclaration( + Declarator::MemberContext, TemplateInfo, UsingLoc, DeclEnd, AS))); } // Hold late-parsed attributes so we can attach a Decl to them later. @@ -2349,7 +2391,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, TemplateInfo.Kind == ParsedTemplateInfo::NonTemplate && DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_class, &CommonLateParsedAttrs)) - return; + return DeclGroupPtrTy(); MultiTemplateParamsArg TemplateParams( TemplateInfo.TemplateParams? TemplateInfo.TemplateParams->data() @@ -2363,7 +2405,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, Decl *TheDecl = Actions.ParsedFreeStandingDeclSpec(getCurScope(), AS, DS, TemplateParams); DS.complete(TheDecl); - return; + return DeclGroupPtrTy::make(DeclGroupRef(TheDecl)); } ParsingDeclarator DeclaratorInfo(*this, DS, Declarator::MemberContext); @@ -2404,7 +2446,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (ParseCXXMemberDeclaratorBeforeInitializer( DeclaratorInfo, VS, BitfieldSize, LateParsedAttrs)) { TryConsumeToken(tok::semi); - return; + return DeclGroupPtrTy(); } // Check for a member function definition. @@ -2453,7 +2495,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, // Consume the optional ';' TryConsumeToken(tok::semi); - return; + return DeclGroupPtrTy(); } if (DS.getStorageClassSpec() == DeclSpec::SCS_typedef) { @@ -2482,7 +2524,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, if (Tok.is(tok::semi)) ConsumeExtraSemi(AfterMemberFunctionDefinition); - return; + return DeclGroupPtrTy::make(DeclGroupRef(FunDecl)); } } @@ -2656,10 +2698,10 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, SkipUntil(tok::r_brace, StopAtSemi | StopBeforeMatch); // If we stopped at a ';', eat it. TryConsumeToken(tok::semi); - return; + return DeclGroupPtrTy(); } - Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); + return Actions.FinalizeDeclaratorGroup(getCurScope(), DS, DeclsInGroup); } /// ParseCXXMemberInitializer - Parse the brace-or-equal-initializer. @@ -2777,6 +2819,100 @@ void Parser::SkipCXXMemberSpecification(SourceLocation RecordLoc, MaybeParseGNUAttributes(Attrs); } +Parser::DeclGroupPtrTy Parser::ParseCXXClassMemberDeclarationWithPragmas( + AccessSpecifier &AS, ParsedAttributesWithRange &AccessAttrs, + DeclSpec::TST TagType, Decl *TagDecl) { + if (getLangOpts().MicrosoftExt && + Tok.isOneOf(tok::kw___if_exists, tok::kw___if_not_exists)) { + ParseMicrosoftIfExistsClassDeclaration(TagType, AS); + return DeclGroupPtrTy(); + } + + // Check for extraneous top-level semicolon. + if (Tok.is(tok::semi)) { + ConsumeExtraSemi(InsideStruct, TagType); + return DeclGroupPtrTy(); + } + + if (Tok.is(tok::annot_pragma_vis)) { + HandlePragmaVisibility(); + return DeclGroupPtrTy(); + } + + if (Tok.is(tok::annot_pragma_pack)) { + HandlePragmaPack(); + return DeclGroupPtrTy(); + } + + if (Tok.is(tok::annot_pragma_align)) { + HandlePragmaAlign(); + return DeclGroupPtrTy(); + } + + if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) { + HandlePragmaMSPointersToMembers(); + return DeclGroupPtrTy(); + } + + if (Tok.is(tok::annot_pragma_ms_pragma)) { + HandlePragmaMSPragma(); + return DeclGroupPtrTy(); + } + + if (Tok.is(tok::annot_pragma_ms_vtordisp)) { + HandlePragmaMSVtorDisp(); + return DeclGroupPtrTy(); + } + + // If we see a namespace here, a close brace was missing somewhere. + if (Tok.is(tok::kw_namespace)) { + DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl)); + return DeclGroupPtrTy(); + } + + AccessSpecifier NewAS = getAccessSpecifierIfPresent(); + if (NewAS != AS_none) { + // Current token is a C++ access specifier. + AS = NewAS; + SourceLocation ASLoc = Tok.getLocation(); + unsigned TokLength = Tok.getLength(); + ConsumeToken(); + AccessAttrs.clear(); + MaybeParseGNUAttributes(AccessAttrs); + + SourceLocation EndLoc; + if (TryConsumeToken(tok::colon, EndLoc)) { + } else if (TryConsumeToken(tok::semi, EndLoc)) { + Diag(EndLoc, diag::err_expected) + << tok::colon << FixItHint::CreateReplacement(EndLoc, ":"); + } else { + EndLoc = ASLoc.getLocWithOffset(TokLength); + Diag(EndLoc, diag::err_expected) + << tok::colon << FixItHint::CreateInsertion(EndLoc, ":"); + } + + // The Microsoft extension __interface does not permit non-public + // access specifiers. + if (TagType == DeclSpec::TST_interface && AS != AS_public) { + Diag(ASLoc, diag::err_access_specifier_interface) << (AS == AS_protected); + } + + if (Actions.ActOnAccessSpecifier(NewAS, ASLoc, EndLoc, + AccessAttrs.getList())) { + // found another attribute than only annotations + AccessAttrs.clear(); + } + + return DeclGroupPtrTy(); + } + + if (Tok.is(tok::annot_pragma_openmp)) + return ParseOpenMPDeclarativeDirective(); + + // Parse all the comma separated declarators. + return ParseCXXClassMemberDeclaration(AS, AccessAttrs.getList()); +} + /// ParseCXXMemberSpecification - Parse the class definition. /// /// member-specification: @@ -2934,102 +3070,16 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, CurAS = AS_private; else CurAS = AS_public; - ParsedAttributes AccessAttrs(AttrFactory); + ParsedAttributesWithRange AccessAttrs(AttrFactory); if (TagDecl) { // While we still have something to read, read the member-declarations. - while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { + while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && + Tok.isNot(tok::eof)) { // Each iteration of this loop reads one member-declaration. - - if (getLangOpts().MicrosoftExt && Tok.isOneOf(tok::kw___if_exists, - tok::kw___if_not_exists)) { - ParseMicrosoftIfExistsClassDeclaration((DeclSpec::TST)TagType, CurAS); - continue; - } - - // Check for extraneous top-level semicolon. - if (Tok.is(tok::semi)) { - ConsumeExtraSemi(InsideStruct, TagType); - continue; - } - - if (Tok.is(tok::annot_pragma_vis)) { - HandlePragmaVisibility(); - continue; - } - - if (Tok.is(tok::annot_pragma_pack)) { - HandlePragmaPack(); - continue; - } - - if (Tok.is(tok::annot_pragma_align)) { - HandlePragmaAlign(); - continue; - } - - if (Tok.is(tok::annot_pragma_openmp)) { - ParseOpenMPDeclarativeDirective(); - continue; - } - - if (Tok.is(tok::annot_pragma_ms_pointers_to_members)) { - HandlePragmaMSPointersToMembers(); - continue; - } - - if (Tok.is(tok::annot_pragma_ms_pragma)) { - HandlePragmaMSPragma(); - continue; - } - - // If we see a namespace here, a close brace was missing somewhere. - if (Tok.is(tok::kw_namespace)) { - DiagnoseUnexpectedNamespace(cast<NamedDecl>(TagDecl)); - break; - } - - AccessSpecifier AS = getAccessSpecifierIfPresent(); - if (AS != AS_none) { - // Current token is a C++ access specifier. - CurAS = AS; - SourceLocation ASLoc = Tok.getLocation(); - unsigned TokLength = Tok.getLength(); - ConsumeToken(); - AccessAttrs.clear(); - MaybeParseGNUAttributes(AccessAttrs); - - SourceLocation EndLoc; - if (TryConsumeToken(tok::colon, EndLoc)) { - } else if (TryConsumeToken(tok::semi, EndLoc)) { - Diag(EndLoc, diag::err_expected) - << tok::colon << FixItHint::CreateReplacement(EndLoc, ":"); - } else { - EndLoc = ASLoc.getLocWithOffset(TokLength); - Diag(EndLoc, diag::err_expected) - << tok::colon << FixItHint::CreateInsertion(EndLoc, ":"); - } - - // The Microsoft extension __interface does not permit non-public - // access specifiers. - if (TagType == DeclSpec::TST_interface && CurAS != AS_public) { - Diag(ASLoc, diag::err_access_specifier_interface) - << (CurAS == AS_protected); - } - - if (Actions.ActOnAccessSpecifier(AS, ASLoc, EndLoc, - AccessAttrs.getList())) { - // found another attribute than only annotations - AccessAttrs.clear(); - } - - continue; - } - - // Parse all the comma separated declarators. - ParseCXXClassMemberDeclaration(CurAS, AccessAttrs.getList()); + ParseCXXClassMemberDeclarationWithPragmas( + CurAS, AccessAttrs, static_cast<DeclSpec::TST>(TagType), TagDecl); } - T.consumeClose(); } else { SkipUntil(tok::r_brace); @@ -3068,7 +3118,7 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc, // We've finished parsing everything, including default argument // initializers. - Actions.ActOnFinishCXXMemberDefaultArgs(TagDecl); + Actions.ActOnFinishCXXNonNestedClass(TagDecl); } if (TagDecl) @@ -3279,7 +3329,7 @@ Parser::tryParseExceptionSpecification(bool Delayed, ExprResult &NoexceptExpr, CachedTokens *&ExceptionSpecTokens) { ExceptionSpecificationType Result = EST_None; - ExceptionSpecTokens = 0; + ExceptionSpecTokens = nullptr; // Handle delayed parsing of exception-specifications. if (Delayed) { @@ -3296,7 +3346,7 @@ Parser::tryParseExceptionSpecification(bool Delayed, // If this is a bare 'noexcept', we're done. if (IsNoexcept) { Diag(Tok, diag::warn_cxx98_compat_noexcept_decl); - NoexceptExpr = 0; + NoexceptExpr = nullptr; return EST_BasicNoexcept; } @@ -3379,7 +3429,7 @@ Parser::tryParseExceptionSpecification(bool Delayed, } static void diagnoseDynamicExceptionSpecification( - Parser &P, const SourceRange &Range, bool IsNoexcept) { + Parser &P, SourceRange Range, bool IsNoexcept) { if (P.getLangOpts().CPlusPlus11) { const char *Replacement = IsNoexcept ? "noexcept" : "noexcept(false)"; P.Diag(Range.getBegin(), diag::warn_exception_spec_deprecated) << Range; @@ -3577,9 +3627,8 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, case AttributeList::AT_CarriesDependency: case AttributeList::AT_Deprecated: case AttributeList::AT_FallThrough: - case AttributeList::AT_CXX11NoReturn: { + case AttributeList::AT_CXX11NoReturn: return true; - } default: return false; @@ -3612,7 +3661,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, // If the attribute isn't known, we will not attempt to parse any // arguments. if (!hasAttribute(AttrSyntax::CXX, ScopeName, AttrName, - getTargetInfo().getTriple(), getLangOpts())) { + getTargetInfo(), getLangOpts())) { // Eat the left paren, then skip to the ending right paren. ConsumeParen(); SkipUntil(tok::r_paren); diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index b866798..490bd5a 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -163,6 +163,8 @@ ExprResult Parser::ParseAssignmentExpression(TypeCastState isTypeCast) { if (Tok.is(tok::kw_throw)) return ParseThrowExpression(); + if (Tok.is(tok::kw_co_yield)) + return ParseCoyieldExpression(); ExprResult LHS = ParseCastExpression(/*isUnaryExpression=*/false, /*isAddressOfOperand=*/false, @@ -522,6 +524,7 @@ class CastExpressionIdValidator : public CorrectionCandidateCallback { /// postfix-expression /// '++' unary-expression /// '--' unary-expression +/// [Coro] 'co_await' cast-expression /// unary-operator cast-expression /// 'sizeof' unary-expression /// 'sizeof' '(' type-name ')' @@ -1041,6 +1044,14 @@ ExprResult Parser::ParseCastExpression(bool isUnaryExpression, return Res; } + case tok::kw_co_await: { // unary-expression: 'co_await' cast-expression + SourceLocation CoawaitLoc = ConsumeToken(); + Res = ParseCastExpression(false); + if (!Res.isInvalid()) + Res = Actions.ActOnCoawaitExpr(getCurScope(), CoawaitLoc, Res.get()); + return Res; + } + case tok::kw___extension__:{//unary-expression:'__extension__' cast-expr [GNU] // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. @@ -1396,21 +1407,42 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); Loc = T.getOpenLocation(); - ExprResult Idx; + ExprResult Idx, Length; + SourceLocation ColonLoc; if (getLangOpts().CPlusPlus11 && Tok.is(tok::l_brace)) { Diag(Tok, diag::warn_cxx98_compat_generalized_initializer_lists); Idx = ParseBraceInitializer(); + } else if (getLangOpts().OpenMP) { + ColonProtectionRAIIObject RAII(*this); + // Parse [: or [ expr or [ expr : + if (!Tok.is(tok::colon)) { + // [ expr + Idx = ParseExpression(); + } + if (Tok.is(tok::colon)) { + // Consume ':' + ColonLoc = ConsumeToken(); + if (Tok.isNot(tok::r_square)) + Length = ParseExpression(); + } } else Idx = ParseExpression(); SourceLocation RLoc = Tok.getLocation(); - if (!LHS.isInvalid() && !Idx.isInvalid() && Tok.is(tok::r_square)) { - LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc, - Idx.get(), RLoc); + if (!LHS.isInvalid() && !Idx.isInvalid() && !Length.isInvalid() && + Tok.is(tok::r_square)) { + if (ColonLoc.isValid()) { + LHS = Actions.ActOnOMPArraySectionExpr(LHS.get(), Loc, Idx.get(), + ColonLoc, Length.get(), RLoc); + } else { + LHS = Actions.ActOnArraySubscriptExpr(getCurScope(), LHS.get(), Loc, + Idx.get(), RLoc); + } } else { (void)Actions.CorrectDelayedTyposInExpr(LHS); (void)Actions.CorrectDelayedTyposInExpr(Idx); + (void)Actions.CorrectDelayedTyposInExpr(Length); LHS = ExprError(); Idx = ExprError(); } @@ -1965,7 +1997,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { } else { PT.consumeClose(); Res = Actions.ActOnBuiltinOffsetOf(getCurScope(), StartLoc, TypeLoc, - Ty.get(), &Comps[0], Comps.size(), + Ty.get(), Comps, PT.getCloseLocation()); } break; @@ -2747,7 +2779,7 @@ ExprResult Parser::ParseBlockLiteralExpression() { /*RestrictQualifierLoc=*/NoLoc, /*MutableLoc=*/NoLoc, EST_None, - /*ESpecLoc=*/NoLoc, + /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, diff --git a/lib/Parse/ParseExprCXX.cpp b/lib/Parse/ParseExprCXX.cpp index c1dafe9..f8938ba 100644 --- a/lib/Parse/ParseExprCXX.cpp +++ b/lib/Parse/ParseExprCXX.cpp @@ -841,6 +841,7 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // Parse capture. LambdaCaptureKind Kind = LCK_ByCopy; + LambdaCaptureInitKind InitKind = LambdaCaptureInitKind::NoInit; SourceLocation Loc; IdentifierInfo *Id = nullptr; SourceLocation EllipsisLoc; @@ -878,6 +879,8 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, BalancedDelimiterTracker Parens(*this, tok::l_paren); Parens.consumeOpen(); + InitKind = LambdaCaptureInitKind::DirectInit; + ExprVector Exprs; CommaLocsTy Commas; if (SkippedInits) { @@ -898,14 +901,13 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // to save the necessary state, and restore it later. EnterExpressionEvaluationContext EC(Actions, Sema::PotentiallyEvaluated); - bool HadEquals = TryConsumeToken(tok::equal); + + if (TryConsumeToken(tok::equal)) + InitKind = LambdaCaptureInitKind::CopyInit; + else + InitKind = LambdaCaptureInitKind::ListInit; if (!SkippedInits) { - // Warn on constructs that will change meaning when we implement N3922 - if (!HadEquals && Tok.is(tok::l_brace)) { - Diag(Tok, diag::warn_init_capture_direct_list_init) - << FixItHint::CreateInsertion(Tok.getLocation(), "="); - } Init = ParseInitializer(); } else if (Tok.is(tok::l_brace)) { BalancedDelimiterTracker Braces(*this, tok::l_brace); @@ -993,19 +995,19 @@ Optional<unsigned> Parser::ParseLambdaIntroducer(LambdaIntroducer &Intro, // If x was not const, the second use would require 'L' to capture, and // that would be an error. - ParsedType InitCaptureParsedType; + ParsedType InitCaptureType; if (Init.isUsable()) { // Get the pointer and store it in an lvalue, so we can use it as an // out argument. Expr *InitExpr = Init.get(); // This performs any lvalue-to-rvalue conversions if necessary, which // can affect what gets captured in the containing decl-context. - QualType InitCaptureType = Actions.performLambdaInitCaptureInitialization( - Loc, Kind == LCK_ByRef, Id, InitExpr); + InitCaptureType = Actions.actOnLambdaInitCaptureInitialization( + Loc, Kind == LCK_ByRef, Id, InitKind, InitExpr); Init = InitExpr; - InitCaptureParsedType.set(InitCaptureType); } - Intro.addCapture(Kind, Loc, Id, EllipsisLoc, Init, InitCaptureParsedType); + Intro.addCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init, + InitCaptureType); } T.consumeClose(); @@ -1149,7 +1151,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*VolatileQualifierLoc=*/NoLoc, /*RestrictQualifierLoc=*/NoLoc, MutableLoc, - ESpecType, ESpecRange.getBegin(), + ESpecType, ESpecRange, DynamicExceptions.data(), DynamicExceptionRanges.data(), DynamicExceptions.size(), @@ -1217,7 +1219,7 @@ ExprResult Parser::ParseLambdaExpressionAfterIntroducer( /*RestrictQualifierLoc=*/NoLoc, MutableLoc, EST_None, - /*ESpecLoc=*/NoLoc, + /*ESpecRange=*/SourceRange(), /*Exceptions=*/nullptr, /*ExceptionRanges=*/nullptr, /*NumExceptions=*/0, @@ -1558,6 +1560,21 @@ ExprResult Parser::ParseThrowExpression() { } } +/// \brief Parse the C++ Coroutines co_yield expression. +/// +/// co_yield-expression: +/// 'co_yield' assignment-expression[opt] +ExprResult Parser::ParseCoyieldExpression() { + assert(Tok.is(tok::kw_co_yield) && "Not co_yield!"); + + SourceLocation Loc = ConsumeToken(); + ExprResult Expr = Tok.is(tok::l_brace) ? ParseBraceInitializer() + : ParseAssignmentExpression(); + if (!Expr.isInvalid()) + Expr = Actions.ActOnCoyieldExpr(getCurScope(), Loc, Expr.get()); + return Expr; +} + /// ParseCXXThis - This handles the C++ 'this' pointer. /// /// C++ 9.3.2: In the body of a non-static member function, the keyword this is @@ -1805,7 +1822,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { DS.SetRangeEnd(Tok.getAnnotationEndLoc()); ConsumeToken(); - DS.Finish(Diags, PP, Policy); + DS.Finish(Actions, Policy); return; } @@ -1861,12 +1878,12 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { case tok::annot_decltype: case tok::kw_decltype: DS.SetRangeEnd(ParseDecltypeSpecifier(DS)); - return DS.Finish(Diags, PP, Policy); + return DS.Finish(Actions, Policy); // GNU typeof support. case tok::kw_typeof: ParseTypeofSpecifier(DS); - DS.Finish(Diags, PP, Policy); + DS.Finish(Actions, Policy); return; } if (Tok.is(tok::annot_typename)) @@ -1874,7 +1891,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { else DS.SetRangeEnd(Tok.getLocation()); ConsumeToken(); - DS.Finish(Diags, PP, Policy); + DS.Finish(Actions, Policy); } /// ParseCXXTypeSpecifierSeq - Parse a C++ type-specifier-seq (C++ @@ -1890,7 +1907,7 @@ void Parser::ParseCXXSimpleTypeSpecifier(DeclSpec &DS) { /// bool Parser::ParseCXXTypeSpecifierSeq(DeclSpec &DS) { ParseSpecifierQualifierList(DS, AS_none, DSC_type_specifier); - DS.Finish(Diags, PP, Actions.getASTContext().getPrintingPolicy()); + DS.Finish(Actions, Actions.getASTContext().getPrintingPolicy()); return false; } @@ -2289,7 +2306,7 @@ bool Parser::ParseUnqualifiedIdOperator(CXXScopeSpec &SS, bool EnteringContext, // This isn't a valid literal-operator-id, but we think we know // what the user meant. Tell them what they should have written. SmallString<32> Str; - Str += "\"\" "; + Str += "\"\""; Str += II->getName(); Diag(DiagLoc, DiagId) << FixItHint::CreateReplacement( SourceRange(TokLocs.front(), TokLocs.back()), Str); diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index ed60904..e72a1f6 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -94,6 +94,28 @@ Parser::DeclGroupPtrTy Parser::ParseObjCAtDirectives() { return Actions.ConvertDeclToDeclGroup(SingleDecl); } +/// Class to handle popping type parameters when leaving the scope. +class Parser::ObjCTypeParamListScope { + Sema &Actions; + Scope *S; + ObjCTypeParamList *Params; +public: + ObjCTypeParamListScope(Sema &Actions, Scope *S) + : Actions(Actions), S(S), Params(nullptr) {} + ~ObjCTypeParamListScope() { + leave(); + } + void enter(ObjCTypeParamList *P) { + assert(!Params); + Params = P; + } + void leave() { + if (Params) + Actions.popObjCTypeParamList(S, Params); + Params = nullptr; + } +}; + /// /// objc-class-declaration: /// '@' 'class' objc-class-forward-decl (',' objc-class-forward-decl)* ';' @@ -121,11 +143,8 @@ Parser::ParseObjCAtClassDeclaration(SourceLocation atLoc) { // Parse the optional objc-type-parameter-list. ObjCTypeParamList *TypeParams = nullptr; - if (Tok.is(tok::less)) { + if (Tok.is(tok::less)) TypeParams = parseObjCTypeParamList(); - if (TypeParams) - Actions.popObjCTypeParamList(getCurScope(), TypeParams); - } ClassTypeParams.push_back(TypeParams); if (!TryConsumeToken(tok::comma)) break; @@ -221,11 +240,10 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, SourceLocation LAngleLoc, EndProtoLoc; SmallVector<IdentifierLocPair, 8> ProtocolIdents; ObjCTypeParamList *typeParameterList = nullptr; - if (Tok.is(tok::less)) { - typeParameterList = parseObjCTypeParamListOrProtocolRefs(LAngleLoc, - ProtocolIdents, - EndProtoLoc); - } + ObjCTypeParamListScope typeParamScope(Actions, getCurScope()); + if (Tok.is(tok::less)) + typeParameterList = parseObjCTypeParamListOrProtocolRefs( + typeParamScope, LAngleLoc, ProtocolIdents, EndProtoLoc); if (Tok.is(tok::l_paren) && !isKnownToBeTypeSpecifier(GetLookAheadToken(1))) { // we have a category. @@ -286,9 +304,6 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParseObjCInterfaceDeclList(tok::objc_not_keyword, CategoryType); - if (typeParameterList) - Actions.popObjCTypeParamList(getCurScope(), typeParameterList); - return CategoryType; } // Parse a class interface. @@ -342,8 +357,7 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, } Actions.FindProtocolDeclaration(/*WarnOnDeclarations=*/true, /*ForObjCContainer=*/true, - &ProtocolIdents[0], ProtocolIdents.size(), - protocols); + ProtocolIdents, protocols); } } else if (protocols.empty() && Tok.is(tok::less) && ParseObjCProtocolReferences(protocols, protocolLocs, true, true, @@ -371,9 +385,6 @@ Decl *Parser::ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParseObjCInterfaceDeclList(tok::objc_interface, ClsType); - if (typeParameterList) - Actions.popObjCTypeParamList(getCurScope(), typeParameterList); - return ClsType; } @@ -433,10 +444,9 @@ static void addContextSensitiveTypeNullability(Parser &P, /// /// \param rAngleLoc The location of the ending '>'. ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( - SourceLocation &lAngleLoc, - SmallVectorImpl<IdentifierLocPair> &protocolIdents, - SourceLocation &rAngleLoc, - bool mayBeProtocolList) { + ObjCTypeParamListScope &Scope, SourceLocation &lAngleLoc, + SmallVectorImpl<IdentifierLocPair> &protocolIdents, + SourceLocation &rAngleLoc, bool mayBeProtocolList) { assert(Tok.is(tok::less) && "Not at the beginning of a type parameter list"); // Within the type parameter list, don't treat '>' as an operator. @@ -493,8 +503,7 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( if (Tok.is(tok::code_completion)) { // FIXME: If these aren't protocol references, we'll need different // completions. - Actions.CodeCompleteObjCProtocolReferences(protocolIdents.data(), - protocolIdents.size()); + Actions.CodeCompleteObjCProtocolReferences(protocolIdents); cutOffParsing(); // FIXME: Better recovery here?. @@ -581,18 +590,19 @@ ObjCTypeParamList *Parser::parseObjCTypeParamListOrProtocolRefs( makeProtocolIdentsIntoTypeParameters(); } - // Form the type parameter list. + // Form the type parameter list and enter its scope. ObjCTypeParamList *list = Actions.actOnObjCTypeParamList( getCurScope(), lAngleLoc, typeParams, rAngleLoc); + Scope.enter(list); // Clear out the angle locations; they're used by the caller to indicate // whether there are any protocol references. lAngleLoc = SourceLocation(); rAngleLoc = SourceLocation(); - return list; + return invalid ? nullptr : list; } /// Parse an objc-type-parameter-list. @@ -600,8 +610,10 @@ ObjCTypeParamList *Parser::parseObjCTypeParamList() { SourceLocation lAngleLoc; SmallVector<IdentifierLocPair, 1> protocolIdents; SourceLocation rAngleLoc; - return parseObjCTypeParamListOrProtocolRefs(lAngleLoc, protocolIdents, - rAngleLoc, + + ObjCTypeParamListScope Scope(Actions, getCurScope()); + return parseObjCTypeParamListOrProtocolRefs(Scope, lAngleLoc, protocolIdents, + rAngleLoc, /*mayBeProtocolList=*/false); } @@ -620,7 +632,6 @@ ObjCTypeParamList *Parser::parseObjCTypeParamList() { void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, Decl *CDecl) { SmallVector<Decl *, 32> allMethods; - SmallVector<Decl *, 16> allProperties; SmallVector<DeclGroupPtrTy, 8> allTUVariables; tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword; @@ -776,12 +787,9 @@ void Parser::ParseObjCInterfaceDeclList(tok::ObjCKeywordKind contextKey, SetterSel = SelectorTable::constructSetterSelector( PP.getIdentifierTable(), PP.getSelectorTable(), FD.D.getIdentifier()); - bool isOverridingProperty = false; Decl *Property = Actions.ActOnProperty( getCurScope(), AtLoc, LParenLoc, FD, OCDS, GetterSel, SetterSel, - &isOverridingProperty, MethodImplKind); - if (!isOverridingProperty) - allProperties.push_back(Property); + MethodImplKind); FD.complete(Property); }; @@ -903,7 +911,7 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { // getter/setter require extra treatment. unsigned DiagID = IsSetter ? diag::err_objc_expected_equal_for_setter : - diag::err_objc_expected_equal_for_getter; + diag::err_objc_expected_equal_for_getter; if (ExpectAndConsume(tok::equal, DiagID)) { SkipUntil(tok::r_paren, StopAtSemi); @@ -918,7 +926,6 @@ void Parser::ParseObjCPropertyAttribute(ObjCDeclSpec &DS) { return cutOffParsing(); } - SourceLocation SelLoc; IdentifierInfo *SelIdent = ParseObjCSelectorPiece(SelLoc); @@ -1114,6 +1121,7 @@ IdentifierInfo *Parser::ParseObjCSelectorPiece(SourceLocation &SelectorLoc) { case tok::kw__Bool: case tok::kw__Complex: case tok::kw___alignof: + case tok::kw___auto_type: IdentifierInfo *II = Tok.getIdentifierInfo(); SelectorLoc = ConsumeToken(); return II; @@ -1557,8 +1565,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, while (1) { if (Tok.is(tok::code_completion)) { - Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents.data(), - ProtocolIdents.size()); + Actions.CodeCompleteObjCProtocolReferences(ProtocolIdents); cutOffParsing(); return true; } @@ -1584,8 +1591,7 @@ ParseObjCProtocolReferences(SmallVectorImpl<Decl *> &Protocols, // Convert the list of protocols identifiers into a list of protocol decls. Actions.FindProtocolDeclaration(WarnOnDeclarations, ForObjCContainer, - &ProtocolIdents[0], ProtocolIdents.size(), - Protocols); + ProtocolIdents, Protocols); return false; } @@ -1662,8 +1668,7 @@ void Parser::parseObjCTypeArgsOrProtocolQualifiers( if (!BaseT.isNull() && BaseT->acceptsObjCTypeParams()) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Type); } else { - Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs.data(), - identifierLocPairs.size()); + Actions.CodeCompleteObjCProtocolReferences(identifierLocPairs); } cutOffParsing(); return; @@ -2015,7 +2020,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (TryConsumeToken(tok::semi)) { // forward declaration of one protocol. IdentifierLocPair ProtoInfo(protocolName, nameLoc); - return Actions.ActOnForwardProtocolDeclaration(AtLoc, &ProtoInfo, 1, + return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtoInfo, attrs.getList()); } @@ -2044,9 +2049,7 @@ Parser::ParseObjCAtProtocolDeclaration(SourceLocation AtLoc, if (ExpectAndConsume(tok::semi, diag::err_expected_after, "@protocol")) return DeclGroupPtrTy(); - return Actions.ActOnForwardProtocolDeclaration(AtLoc, - &ProtocolRefs[0], - ProtocolRefs.size(), + return Actions.ActOnForwardProtocolDeclaration(AtLoc, ProtocolRefs, attrs.getList()); } @@ -2114,8 +2117,9 @@ Parser::ParseObjCAtImplementationDeclaration(SourceLocation AtLoc) { SourceLocation lAngleLoc, rAngleLoc; SmallVector<IdentifierLocPair, 8> protocolIdents; SourceLocation diagLoc = Tok.getLocation(); - if (parseObjCTypeParamListOrProtocolRefs(lAngleLoc, protocolIdents, - rAngleLoc)) { + ObjCTypeParamListScope typeParamScope(Actions, getCurScope()); + if (parseObjCTypeParamListOrProtocolRefs(typeParamScope, lAngleLoc, + protocolIdents, rAngleLoc)) { Diag(diagLoc, diag::err_objc_parameterized_implementation) << SourceRange(diagLoc, PrevTokLocation); } else if (lAngleLoc.isValid()) { @@ -2614,6 +2618,7 @@ void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) { } else if (Tok.is(tok::colon)) { ConsumeToken(); + // FIXME: This is wrong, due to C++11 braced initialization. while (Tok.isNot(tok::l_brace)) { ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false); ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false); @@ -3279,8 +3284,7 @@ ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) { AtStrings.push_back(Lit.get()); } - return Actions.ParseObjCStringLiteral(&AtLocs[0], AtStrings.data(), - AtStrings.size()); + return Actions.ParseObjCStringLiteral(AtLocs.data(), AtStrings); } /// ParseObjCBooleanLiteral - @@ -3431,7 +3435,7 @@ ExprResult Parser::ParseObjCDictionaryLiteral(SourceLocation AtLoc) { // Create the ObjCDictionaryLiteral. return Actions.BuildObjCDictionaryLiteral(SourceRange(AtLoc, EndLoc), - Elements.data(), Elements.size()); + Elements); } /// objc-encode-expression: diff --git a/lib/Parse/ParseOpenMP.cpp b/lib/Parse/ParseOpenMP.cpp index 0113a31..078f4c3 100644 --- a/lib/Parse/ParseOpenMP.cpp +++ b/lib/Parse/ParseOpenMP.cpp @@ -19,6 +19,7 @@ #include "clang/Parse/Parser.h" #include "clang/Sema/Scope.h" #include "llvm/ADT/PointerIntPair.h" + using namespace clang; //===----------------------------------------------------------------------===// @@ -32,15 +33,18 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { const OpenMPDirectiveKind F[][3] = { {OMPD_unknown /*cancellation*/, OMPD_unknown /*point*/, OMPD_cancellation_point}, + {OMPD_target, OMPD_unknown /*data*/, OMPD_target_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_parallel, OMPD_sections, OMPD_parallel_sections}, + {OMPD_taskloop, OMPD_simd, OMPD_taskloop_simd}}; auto Tok = P.getCurToken(); auto DKind = Tok.isAnnotation() ? OMPD_unknown : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); + bool TokenMatched = false; for (unsigned i = 0; i < llvm::array_lengthof(F); ++i) { if (!Tok.isAnnotation() && DKind == OMPD_unknown) { @@ -50,18 +54,24 @@ static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { } else { TokenMatched = DKind == F[i][0] && DKind != OMPD_unknown; } + if (TokenMatched) { Tok = P.getPreprocessor().LookAhead(0); + auto TokenIsAnnotation = Tok.isAnnotation(); auto SDKind = - Tok.isAnnotation() + TokenIsAnnotation ? OMPD_unknown : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); - if (!Tok.isAnnotation() && DKind == OMPD_unknown) { + + if (!TokenIsAnnotation && SDKind == OMPD_unknown) { TokenMatched = - (i == 0) && !P.getPreprocessor().getSpelling(Tok).compare("point"); + ((i == 0) && + !P.getPreprocessor().getSpelling(Tok).compare("point")) || + ((i == 1) && !P.getPreprocessor().getSpelling(Tok).compare("data")); } else { TokenMatched = SDKind == F[i][1] && SDKind != OMPD_unknown; } + if (TokenMatched) { P.ConsumeToken(); DKind = F[i][2]; @@ -127,6 +137,10 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_teams: case OMPD_cancellation_point: case OMPD_cancel: + case OMPD_target_data: + case OMPD_taskloop: + case OMPD_taskloop_simd: + case OMPD_distribute: Diag(Tok, diag::err_omp_unexpected_directive) << getOpenMPDirectiveName(DKind); break; @@ -146,8 +160,9 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// 'section' | 'single' | 'master' | 'critical' [ '(' <name> ')' ] | /// 'parallel for' | 'parallel sections' | 'task' | 'taskyield' | /// 'barrier' | 'taskwait' | 'flush' | 'ordered' | 'atomic' | -/// 'for simd' | 'parallel for simd' | 'target' | 'teams' | 'taskgroup' -/// {clause} +/// 'for simd' | 'parallel for simd' | 'target' | 'target data' | +/// 'taskgroup' | 'teams' | 'taskloop' | 'taskloop simd' {clause} | +/// 'distribute' /// annot_pragma_openmp_end /// StmtResult @@ -200,7 +215,7 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_cancel: if (!StandAloneAllowed) { Diag(Tok, diag::err_omp_immediate_directive) - << getOpenMPDirectiveName(DKind); + << getOpenMPDirectiveName(DKind) << 0; } HasAssociatedStatement = false; // Fall through for further analysis. @@ -221,7 +236,11 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { case OMPD_atomic: case OMPD_target: case OMPD_teams: - case OMPD_taskgroup: { + case OMPD_taskgroup: + case OMPD_target_data: + case OMPD_taskloop: + case OMPD_taskloop_simd: + case OMPD_distribute: { ConsumeToken(); // Parse directive name of the 'critical' directive if any. if (DKind == OMPD_critical) { @@ -276,8 +295,19 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { // Consume final annot_pragma_openmp_end. ConsumeToken(); + // OpenMP [2.13.8, ordered Construct, Syntax] + // If the depend clause is specified, the ordered construct is a stand-alone + // directive. + if (DKind == OMPD_ordered && FirstClauses[OMPC_depend].getInt()) { + if (!StandAloneAllowed) { + Diag(Loc, diag::err_omp_immediate_directive) + << getOpenMPDirectiveName(DKind) << 1 + << getOpenMPClauseName(OMPC_depend); + } + HasAssociatedStatement = false; + } + StmtResult AssociatedStmt; - bool CreateDirective = true; if (HasAssociatedStatement) { // The body is a block scope like in Lambdas and Blocks. Sema::CompoundScopeRAII CompoundScope(Actions); @@ -287,12 +317,10 @@ Parser::ParseOpenMPDeclarativeOrExecutableDirective(bool StandAloneAllowed) { AssociatedStmt = ParseStatement(); Actions.ActOnFinishOfCompoundStmt(); AssociatedStmt = Actions.ActOnOpenMPRegionEnd(AssociatedStmt, Clauses); - CreateDirective = AssociatedStmt.isUsable(); } - if (CreateDirective) - Directive = Actions.ActOnOpenMPExecutableDirective( - DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, - EndLoc); + Directive = Actions.ActOnOpenMPExecutableDirective( + DKind, DirName, CancelRegion, Clauses, AssociatedStmt.get(), Loc, + EndLoc); // Exit scope. Actions.EndOpenMPDSABlock(Directive.get()); @@ -385,7 +413,10 @@ bool Parser::ParseOpenMPSimpleVarList(OpenMPDirectiveKind Kind, /// lastprivate-clause | reduction-clause | proc_bind-clause | /// schedule-clause | copyin-clause | copyprivate-clause | untied-clause | /// mergeable-clause | flush-clause | read-clause | write-clause | -/// update-clause | capture-clause | seq_cst-clause +/// update-clause | capture-clause | seq_cst-clause | device-clause | +/// simdlen-clause | threads-clause | simd-clause | num_teams-clause | +/// thread_limit-clause | priority-clause | grainsize-clause | +/// nogroup-clause | num_tasks-clause | hint-clause /// OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause) { @@ -399,27 +430,49 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, } switch (CKind) { - case OMPC_if: case OMPC_final: case OMPC_num_threads: case OMPC_safelen: + case OMPC_simdlen: case OMPC_collapse: + case OMPC_ordered: + case OMPC_device: + case OMPC_num_teams: + case OMPC_thread_limit: + case OMPC_priority: + case OMPC_grainsize: + case OMPC_num_tasks: + case OMPC_hint: // OpenMP [2.5, Restrictions] - // At most one if clause can appear on the directive. // At most one num_threads clause can appear on the directive. // OpenMP [2.8.1, simd construct, Restrictions] // Only one safelen clause can appear on a simd directive. + // Only one simdlen clause can appear on a simd directive. // Only one collapse clause can appear on a simd directive. + // OpenMP [2.9.1, target data construct, Restrictions] + // At most one device clause can appear on the directive. // OpenMP [2.11.1, task Construct, Restrictions] // At most one if clause can appear on the directive. // At most one final clause can appear on the directive. + // OpenMP [teams Construct, Restrictions] + // At most one num_teams clause can appear on the directive. + // At most one thread_limit clause can appear on the directive. + // OpenMP [2.9.1, task Construct, Restrictions] + // At most one priority clause can appear on the directive. + // OpenMP [2.9.2, taskloop Construct, Restrictions] + // At most one grainsize clause can appear on the directive. + // OpenMP [2.9.2, taskloop Construct, Restrictions] + // At most one num_tasks clause can appear on the directive. if (!FirstClause) { - Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) - << getOpenMPClauseName(CKind); + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } - Clause = ParseOpenMPSingleExprClause(CKind); + if (CKind == OMPC_ordered && PP.LookAhead(/*N=*/0).isNot(tok::l_paren)) + Clause = ParseOpenMPClause(CKind); + else + Clause = ParseOpenMPSingleExprClause(CKind); break; case OMPC_default: case OMPC_proc_bind: @@ -429,8 +482,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, // OpenMP [2.5, parallel Construct, Restrictions] // At most one proc_bind clause can appear on the directive. if (!FirstClause) { - Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) - << getOpenMPClauseName(CKind); + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } @@ -440,14 +493,14 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, // OpenMP [2.7.1, Restrictions, p. 3] // Only one schedule clause can appear on a loop directive. if (!FirstClause) { - Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) - << getOpenMPClauseName(CKind); + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } + case OMPC_if: Clause = ParseOpenMPSingleExprWithArgClause(CKind); break; - case OMPC_ordered: case OMPC_nowait: case OMPC_untied: case OMPC_mergeable: @@ -456,13 +509,16 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_update: case OMPC_capture: case OMPC_seq_cst: + case OMPC_threads: + case OMPC_simd: + case OMPC_nogroup: // OpenMP [2.7.1, Restrictions, p. 9] // Only one ordered clause can appear on a loop directive. // OpenMP [2.7.1, Restrictions, C/C++, p. 4] // Only one nowait clause can appear on a for directive. if (!FirstClause) { - Diag(Tok, diag::err_omp_more_one_clause) << getOpenMPDirectiveName(DKind) - << getOpenMPClauseName(CKind); + Diag(Tok, diag::err_omp_more_one_clause) + << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0; ErrorFound = true; } @@ -479,7 +535,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, case OMPC_copyprivate: case OMPC_flush: case OMPC_depend: - Clause = ParseOpenMPVarListClause(CKind); + case OMPC_map: + Clause = ParseOpenMPVarListClause(DKind, CKind); break; case OMPC_unknown: Diag(Tok, diag::warn_omp_extra_tokens_at_eol) @@ -495,12 +552,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, return ErrorFound ? nullptr : Clause; } -/// \brief Parsing of OpenMP clauses with single expressions like 'if', -/// 'final', 'collapse', 'safelen', 'num_threads', 'simdlen', 'num_teams' or -/// 'thread_limit'. -/// -/// if-clause: -/// 'if' '(' expression ')' +/// \brief 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'. /// /// final-clause: /// 'final' '(' expression ')' @@ -511,9 +565,24 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind, /// safelen-clause: /// 'safelen' '(' expression ')' /// +/// simdlen-clause: +/// 'simdlen' '(' expression ')' +/// /// collapse-clause: /// 'collapse' '(' expression ')' /// +/// priority-clause: +/// 'priority' '(' expression ')' +/// +/// grainsize-clause: +/// 'grainsize' '(' expression ')' +/// +/// num_tasks-clause: +/// 'num_tasks' '(' expression ')' +/// +/// hint-clause: +/// 'hint' '(' expression ')' +/// OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { SourceLocation Loc = ConsumeToken(); @@ -522,8 +591,10 @@ OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind) { getOpenMPClauseName(Kind))) return nullptr; + SourceLocation ELoc = Tok.getLocation(); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); ExprResult Val(ParseRHSOfBinaryExpression(LHS, prec::Conditional)); + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); // Parse ')'. T.consumeClose(); @@ -583,6 +654,15 @@ OMPClause *Parser::ParseOpenMPSimpleClause(OpenMPClauseKind Kind) { /// read-clause: /// 'read' /// +/// threads-clause: +/// 'threads' +/// +/// simd-clause: +/// 'simd' +/// +/// nogroup-clause: +/// 'nogroup' +/// OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); ConsumeAnyToken(); @@ -595,11 +675,15 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPClauseKind Kind) { /// argument like 'schedule' or 'dist_schedule'. /// /// schedule-clause: -/// 'schedule' '(' kind [',' expression ] ')' +/// 'schedule' '(' [ modifier [ ',' modifier ] ':' ] kind [',' expression ] +/// ')' +/// +/// if-clause: +/// 'if' '(' [ directive-name-modifier ':' ] expression ')' /// OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { SourceLocation Loc = ConsumeToken(); - SourceLocation CommaLoc; + SourceLocation DelimLoc; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); if (T.expectAndConsume(diag::err_expected_lparen_after, @@ -607,29 +691,86 @@ OMPClause *Parser::ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind) { return nullptr; ExprResult Val; - unsigned Type = getOpenMPSimpleClauseType( - Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); - SourceLocation KLoc = Tok.getLocation(); - if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && - Tok.isNot(tok::annot_pragma_openmp_end)) - ConsumeAnyToken(); + SmallVector<unsigned, 4> Arg; + SmallVector<SourceLocation, 4> KLoc; + if (Kind == OMPC_schedule) { + enum { Modifier1, Modifier2, ScheduleKind, NumberOfElements }; + Arg.resize(NumberOfElements); + KLoc.resize(NumberOfElements); + Arg[Modifier1] = OMPC_SCHEDULE_MODIFIER_unknown; + Arg[Modifier2] = OMPC_SCHEDULE_MODIFIER_unknown; + Arg[ScheduleKind] = OMPC_SCHEDULE_unknown; + auto KindModifier = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); + if (KindModifier > OMPC_SCHEDULE_unknown) { + // Parse 'modifier' + Arg[Modifier1] = KindModifier; + KLoc[Modifier1] = Tok.getLocation(); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + if (Tok.is(tok::comma)) { + // Parse ',' 'modifier' + ConsumeAnyToken(); + KindModifier = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); + Arg[Modifier2] = KindModifier > OMPC_SCHEDULE_unknown + ? KindModifier + : (unsigned)OMPC_SCHEDULE_unknown; + KLoc[Modifier2] = Tok.getLocation(); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + } + // Parse ':' + if (Tok.is(tok::colon)) + ConsumeAnyToken(); + else + Diag(Tok, diag::warn_pragma_expected_colon) << "schedule modifier"; + KindModifier = getOpenMPSimpleClauseType( + Kind, Tok.isAnnotation() ? "" : PP.getSpelling(Tok)); + } + Arg[ScheduleKind] = KindModifier; + KLoc[ScheduleKind] = Tok.getLocation(); + if (Tok.isNot(tok::r_paren) && Tok.isNot(tok::comma) && + Tok.isNot(tok::annot_pragma_openmp_end)) + ConsumeAnyToken(); + if ((Arg[ScheduleKind] == OMPC_SCHEDULE_static || + Arg[ScheduleKind] == OMPC_SCHEDULE_dynamic || + Arg[ScheduleKind] == OMPC_SCHEDULE_guided) && + Tok.is(tok::comma)) + DelimLoc = ConsumeAnyToken(); + } else { + assert(Kind == OMPC_if); + KLoc.push_back(Tok.getLocation()); + Arg.push_back(ParseOpenMPDirectiveKind(*this)); + if (Arg.back() != OMPD_unknown) { + ConsumeToken(); + if (Tok.is(tok::colon)) + DelimLoc = ConsumeToken(); + else + Diag(Tok, diag::warn_pragma_expected_colon) + << "directive name modifier"; + } + } - if (Kind == OMPC_schedule && - (Type == OMPC_SCHEDULE_static || Type == OMPC_SCHEDULE_dynamic || - Type == OMPC_SCHEDULE_guided) && - Tok.is(tok::comma)) { - CommaLoc = ConsumeAnyToken(); + bool NeedAnExpression = + (Kind == OMPC_schedule && DelimLoc.isValid()) || Kind == OMPC_if; + if (NeedAnExpression) { + SourceLocation ELoc = Tok.getLocation(); ExprResult LHS(ParseCastExpression(false, false, NotTypeCast)); Val = ParseRHSOfBinaryExpression(LHS, prec::Conditional); - if (Val.isInvalid()) - return nullptr; + Val = Actions.ActOnFinishFullExpr(Val.get(), ELoc); } // Parse ')'. T.consumeClose(); + if (NeedAnExpression && Val.isInvalid()) + return nullptr; + return Actions.ActOnOpenMPSingleExprWithArgClause( - Kind, Type, Val.get(), Loc, T.getOpenLocation(), KLoc, CommaLoc, + Kind, Arg, Val.get(), Loc, T.getOpenLocation(), KLoc, DelimLoc, T.getCloseLocation()); } @@ -691,7 +832,7 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, /// shared-clause: /// 'shared' '(' list ')' /// linear-clause: -/// 'linear' '(' list [ ':' linear-step ] ')' +/// 'linear' '(' linear-list [ ':' linear-step ] ')' /// aligned-clause: /// 'aligned' '(' list [ ':' alignment ] ')' /// reduction-clause: @@ -701,9 +842,17 @@ static bool ParseReductionId(Parser &P, CXXScopeSpec &ReductionIdScopeSpec, /// flush-clause: /// 'flush' '(' list ')' /// depend-clause: -/// 'depend' '(' in | out | inout : list ')' +/// 'depend' '(' in | out | inout : list | source ')' +/// map-clause: +/// 'map' '(' [ [ always , ] +/// to | from | tofrom | alloc | release | delete ':' ] list ')'; /// -OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { +/// For 'linear' clause linear-list may have the following forms: +/// list +/// modifier(list) +/// where modifier is 'val' (C) or 'ref', 'val' or 'uval'(C++). +OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, + OpenMPClauseKind Kind) { SourceLocation Loc = Tok.getLocation(); SourceLocation LOpen = ConsumeToken(); SourceLocation ColonLoc = SourceLocation(); @@ -712,7 +861,14 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { UnqualifiedId ReductionId; bool InvalidReductionId = false; OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; - SourceLocation DepLoc; + // OpenMP 4.1 [2.15.3.7, linear Clause] + // If no modifier is specified it is assumed to be val. + OpenMPLinearClauseKind LinearModifier = OMPC_LINEAR_val; + OpenMPMapClauseKind MapType = OMPC_MAP_unknown; + OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; + bool MapTypeModifierSpecified = false; + bool UnexpectedId = false; + SourceLocation DepLinMapLoc; // Parse '('. BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end); @@ -720,6 +876,9 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { getOpenMPClauseName(Kind))) return nullptr; + bool NeedRParenForLinear = false; + BalancedDelimiterTracker LinearT(*this, tok::l_paren, + tok::annot_pragma_openmp_end); // Handle reduction-identifier for reduction clause. if (Kind == OMPC_reduction) { ColonProtectionRAIIObject ColonRAII(*this); @@ -742,25 +901,109 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { ColonProtectionRAIIObject ColonRAII(*this); DepKind = static_cast<OpenMPDependClauseKind>(getOpenMPSimpleClauseType( Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); - DepLoc = Tok.getLocation(); + DepLinMapLoc = Tok.getLocation(); if (DepKind == OMPC_DEPEND_unknown) { SkipUntil(tok::colon, tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); } else { ConsumeToken(); + // Special processing for depend(source) clause. + if (DKind == OMPD_ordered && DepKind == OMPC_DEPEND_source) { + // Parse ')'. + T.consumeClose(); + return Actions.ActOnOpenMPVarListClause( + Kind, llvm::None, /*TailExpr=*/nullptr, Loc, LOpen, + /*ColonLoc=*/SourceLocation(), Tok.getLocation(), + ReductionIdScopeSpec, DeclarationNameInfo(), DepKind, + LinearModifier, MapTypeModifier, MapType, DepLinMapLoc); + } } if (Tok.is(tok::colon)) { ColonLoc = ConsumeToken(); } else { - Diag(Tok, diag::warn_pragma_expected_colon) << "dependency type"; + Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren + : diag::warn_pragma_expected_colon) + << "dependency type"; + } + } else if (Kind == OMPC_linear) { + // Try to parse modifier if any. + if (Tok.is(tok::identifier) && PP.LookAhead(0).is(tok::l_paren)) { + LinearModifier = static_cast<OpenMPLinearClauseKind>( + getOpenMPSimpleClauseType(Kind, PP.getSpelling(Tok))); + DepLinMapLoc = ConsumeToken(); + LinearT.consumeOpen(); + NeedRParenForLinear = true; + } + } else if (Kind == OMPC_map) { + // Handle map type for map clause. + ColonProtectionRAIIObject ColonRAII(*this); + + // the first identifier may be a list item, a map-type or + // a map-type-modifier + MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); + DepLinMapLoc = Tok.getLocation(); + bool ColonExpected = false; + + if (Tok.is(tok::identifier)) { + if (PP.LookAhead(0).is(tok::colon)) { + MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); + if (MapType == OMPC_MAP_unknown) { + Diag(Tok, diag::err_omp_unknown_map_type); + } else if (MapType == OMPC_MAP_always) { + Diag(Tok, diag::err_omp_map_type_missing); + } + ConsumeToken(); + } else if (PP.LookAhead(0).is(tok::comma)) { + if (PP.LookAhead(1).is(tok::identifier) && + PP.LookAhead(2).is(tok::colon)) { + MapTypeModifier = + static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); + if (MapTypeModifier != OMPC_MAP_always) { + Diag(Tok, diag::err_omp_unknown_map_type_modifier); + MapTypeModifier = OMPC_MAP_unknown; + } else { + MapTypeModifierSpecified = true; + } + + ConsumeToken(); + ConsumeToken(); + + MapType = static_cast<OpenMPMapClauseKind>(getOpenMPSimpleClauseType( + Kind, Tok.is(tok::identifier) ? PP.getSpelling(Tok) : "")); + if (MapType == OMPC_MAP_unknown || MapType == OMPC_MAP_always) { + Diag(Tok, diag::err_omp_unknown_map_type); + } + ConsumeToken(); + } else { + MapType = OMPC_MAP_tofrom; + } + } else { + MapType = OMPC_MAP_tofrom; + } + } else { + UnexpectedId = true; + } + + if (Tok.is(tok::colon)) { + ColonLoc = ConsumeToken(); + } else if (ColonExpected) { + Diag(Tok, diag::warn_pragma_expected_colon) << "map type"; } } SmallVector<Expr *, 5> Vars; - bool IsComma = ((Kind != OMPC_reduction) && (Kind != OMPC_depend)) || - ((Kind == OMPC_reduction) && !InvalidReductionId) || - ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown); + bool IsComma = + ((Kind != OMPC_reduction) && (Kind != OMPC_depend) && + (Kind != OMPC_map)) || + ((Kind == OMPC_reduction) && !InvalidReductionId) || + ((Kind == OMPC_map) && (UnexpectedId || MapType != OMPC_MAP_unknown) && + (!MapTypeModifierSpecified || + (MapTypeModifierSpecified && MapTypeModifier == OMPC_MAP_always))) || + ((Kind == OMPC_depend) && DepKind != OMPC_DEPEND_unknown); const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned); while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) && Tok.isNot(tok::annot_pragma_openmp_end))) { @@ -787,14 +1030,18 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { << (Kind == OMPC_flush); } + // Parse ')' for linear clause with modifier. + if (NeedRParenForLinear) + LinearT.consumeClose(); + // Parse ':' linear-step (or ':' alignment). Expr *TailExpr = nullptr; const bool MustHaveTail = MayHaveTail && Tok.is(tok::colon); if (MustHaveTail) { ColonLoc = Tok.getLocation(); - ConsumeToken(); - ExprResult Tail = - Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); + SourceLocation ELoc = ConsumeToken(); + ExprResult Tail = ParseAssignmentExpression(); + Tail = Actions.ActOnFinishFullExpr(Tail.get(), ELoc); if (Tail.isUsable()) TailExpr = Tail.get(); else @@ -806,14 +1053,16 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPClauseKind Kind) { T.consumeClose(); if ((Kind == OMPC_depend && DepKind != OMPC_DEPEND_unknown && Vars.empty()) || (Kind != OMPC_depend && Vars.empty()) || (MustHaveTail && !TailExpr) || - InvalidReductionId) + (Kind == OMPC_map && MapType == OMPC_MAP_unknown) || + InvalidReductionId) { return nullptr; + } return Actions.ActOnOpenMPVarListClause( Kind, Vars, TailExpr, Loc, LOpen, ColonLoc, Tok.getLocation(), ReductionIdScopeSpec, ReductionId.isValid() ? Actions.GetNameFromUnqualifiedId(ReductionId) : DeclarationNameInfo(), - DepKind, DepLoc); + DepKind, LinearModifier, MapTypeModifier, MapType, DepLinMapLoc); } diff --git a/lib/Parse/ParsePragma.cpp b/lib/Parse/ParsePragma.cpp index 892d3c6..4430eb8 100644 --- a/lib/Parse/ParsePragma.cpp +++ b/lib/Parse/ParsePragma.cpp @@ -156,6 +156,10 @@ struct PragmaUnrollHintHandler : public PragmaHandler { Token &FirstToken) override; }; +struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler { + PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {} +}; + } // end namespace void Parser::initializePragmaHandlers() { @@ -222,6 +226,8 @@ void Parser::initializePragmaHandlers() { PP.AddPragmaHandler(MSCodeSeg.get()); MSSection.reset(new PragmaMSPragma("section")); PP.AddPragmaHandler(MSSection.get()); + MSRuntimeChecks.reset(new PragmaMSRuntimeChecksHandler()); + PP.AddPragmaHandler(MSRuntimeChecks.get()); } OptimizeHandler.reset(new PragmaOptimizeHandler(Actions)); @@ -288,6 +294,8 @@ void Parser::resetPragmaHandlers() { MSCodeSeg.reset(); PP.RemovePragmaHandler(MSSection.get()); MSSection.reset(); + PP.RemovePragmaHandler(MSRuntimeChecks.get()); + MSRuntimeChecks.reset(); } PP.RemovePragmaHandler("STDC", FPContractHandler.get()); @@ -326,6 +334,7 @@ void Parser::HandlePragmaVisibility() { Actions.ActOnPragmaVisibility(VisType, VisLoc); } +namespace { struct PragmaPackInfo { Sema::PragmaPackKind Kind; IdentifierInfo *Name; @@ -333,6 +342,7 @@ struct PragmaPackInfo { SourceLocation LParenLoc; SourceLocation RParenLoc; }; +} // end anonymous namespace void Parser::HandlePragmaPack() { assert(Tok.is(tok::annot_pragma_pack)); @@ -742,13 +752,13 @@ bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName, return true; } +namespace { struct PragmaLoopHintInfo { Token PragmaName; Token Option; - Token *Toks; - size_t TokSize; - PragmaLoopHintInfo() : Toks(nullptr), TokSize(0) {} + ArrayRef<Token> Toks; }; +} // end anonymous namespace static std::string PragmaLoopHintString(Token PragmaName, Token Option) { std::string PragmaString; @@ -780,8 +790,8 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { Hint.OptionLoc = IdentifierLoc::create( Actions.Context, Info->Option.getLocation(), OptionInfo); - Token *Toks = Info->Toks; - size_t TokSize = Info->TokSize; + const Token *Toks = Info->Toks.data(); + size_t TokSize = Info->Toks.size(); // Return a valid hint if pragma unroll or nounroll were specified // without an argument. @@ -824,10 +834,9 @@ bool Parser::HandlePragmaLoopHint(LoopHint &Hint) { SourceLocation StateLoc = Toks[0].getLocation(); IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo(); if (!StateInfo || - ((OptionUnroll ? !StateInfo->isStr("full") - : !StateInfo->isStr("enable") && - !StateInfo->isStr("assume_safety")) && - !StateInfo->isStr("disable"))) { + (!StateInfo->isStr("enable") && !StateInfo->isStr("disable") && + ((OptionUnroll && !StateInfo->isStr("full")) || + (!OptionUnroll && !StateInfo->isStr("assume_safety"))))) { Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword) << /*FullKeyword=*/OptionUnroll; return false; @@ -1928,11 +1937,7 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, EOFTok.setLocation(Tok.getLocation()); ValueList.push_back(EOFTok); // Terminates expression for parsing. - Token *TokenArray = (Token *)PP.getPreprocessorAllocator().Allocate( - ValueList.size() * sizeof(Token), llvm::alignOf<Token>()); - std::copy(ValueList.begin(), ValueList.end(), TokenArray); - Info.Toks = TokenArray; - Info.TokSize = ValueList.size(); + Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator()); Info.PragmaName = PragmaName; Info.Option = Option; @@ -1959,8 +1964,9 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, /// 'assume_safety' /// /// unroll-hint-keyword: -/// 'full' +/// 'enable' /// 'disable' +/// 'full' /// /// loop-hint-value: /// constant-expression @@ -1976,10 +1982,13 @@ static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName, /// only works on inner loops. /// /// The unroll and unroll_count directives control the concatenation -/// unroller. Specifying unroll(full) instructs llvm to try to -/// unroll the loop completely, and unroll(disable) disables unrolling -/// for the loop. Specifying unroll_count(_value_) instructs llvm to -/// try to unroll the loop the number of times indicated by the value. +/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop +/// completely if the trip count is known at compile time and unroll partially +/// if the trip count is not known. Specifying unroll(full) is similar to +/// unroll(enable) but will unroll the loop only if the trip count is known at +/// compile time. Specifying unroll(disable) disables unrolling for the +/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the +/// loop the number of times indicated by the value. void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP, PragmaIntroducerKind Introducer, Token &Tok) { diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index b658cef..717bcff 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -259,6 +259,10 @@ Retry: Res = ParseReturnStatement(); SemiError = "return"; break; + case tok::kw_co_return: // C++ Coroutines: co_return statement + Res = ParseReturnStatement(); + SemiError = "co_return"; + break; case tok::kw_asm: { ProhibitAttributes(Attrs); @@ -354,6 +358,11 @@ Retry: HandlePragmaMSPragma(); return StmtEmpty(); + case tok::annot_pragma_ms_vtordisp: + ProhibitAttributes(Attrs); + HandlePragmaMSVtorDisp(); + return StmtEmpty(); + case tok::annot_pragma_loop_hint: ProhibitAttributes(Attrs); return ParsePragmaLoopHint(Stmts, OnlyStatement, TrailingElseLoc, Attrs); @@ -881,6 +890,9 @@ void Parser::ParseCompoundStatementLeadingPragmas() { case tok::annot_pragma_ms_pragma: HandlePragmaMSPragma(); break; + case tok::annot_pragma_ms_vtordisp: + HandlePragmaMSVtorDisp(); + break; default: checkForPragmas = false; break; @@ -944,7 +956,8 @@ StmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { Stmts.push_back(R.get()); } - while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { + while (!tryParseMisplacedModuleImport() && Tok.isNot(tok::r_brace) && + Tok.isNot(tok::eof)) { if (Tok.is(tok::annot_pragma_unused)) { HandlePragmaUnused(); continue; @@ -1442,7 +1455,10 @@ bool Parser::isForRangeIdentifier() { /// 'for' '(' declaration expr[opt] ';' expr[opt] ')' statement /// [C++] 'for' '(' for-init-statement condition[opt] ';' expression[opt] ')' /// [C++] statement -/// [C++0x] 'for' '(' for-range-declaration : for-range-initializer ) statement +/// [C++0x] 'for' +/// 'co_await'[opt] [Coroutines] +/// '(' for-range-declaration ':' for-range-initializer ')' +/// statement /// [OBJC2] 'for' '(' declaration 'in' expr ')' statement /// [OBJC2] 'for' '(' expr 'in' expr ')' statement /// @@ -1459,6 +1475,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { assert(Tok.is(tok::kw_for) && "Not a for stmt!"); SourceLocation ForLoc = ConsumeToken(); // eat the 'for'. + SourceLocation CoawaitLoc; + if (Tok.is(tok::kw_co_await)) + CoawaitLoc = ConsumeToken(); + if (Tok.isNot(tok::l_paren)) { Diag(Tok, diag::err_expected_lparen_after) << "for"; SkipUntil(tok::semi); @@ -1665,6 +1685,13 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { // Match the ')'. T.consumeClose(); + // C++ Coroutines [stmt.iter]: + // 'co_await' can only be used for a range-based for statement. + if (CoawaitLoc.isValid() && !ForRange) { + Diag(CoawaitLoc, diag::err_for_co_await_not_range_for); + CoawaitLoc = SourceLocation(); + } + // We need to perform most of the semantic analysis for a C++0x for-range // statememt before parsing the body, in order to be able to deduce the type // of an auto-typed loop variable. @@ -1672,12 +1699,10 @@ StmtResult Parser::ParseForStatement(SourceLocation *TrailingElseLoc) { StmtResult ForEachStmt; if (ForRange) { - ForRangeStmt = Actions.ActOnCXXForRangeStmt(ForLoc, FirstPart.get(), - ForRangeInit.ColonLoc, - ForRangeInit.RangeExpr.get(), - T.getCloseLocation(), - Sema::BFRK_Build); - + ForRangeStmt = Actions.ActOnCXXForRangeStmt( + getCurScope(), ForLoc, CoawaitLoc, FirstPart.get(), + ForRangeInit.ColonLoc, ForRangeInit.RangeExpr.get(), + T.getCloseLocation(), Sema::BFRK_Build); // Similarly, we need to do the semantic analysis for a for-range // statement immediately in order to close over temporaries correctly. @@ -1799,13 +1824,19 @@ StmtResult Parser::ParseBreakStatement() { /// ParseReturnStatement /// jump-statement: /// 'return' expression[opt] ';' +/// 'return' braced-init-list ';' +/// 'co_return' expression[opt] ';' +/// 'co_return' braced-init-list ';' StmtResult Parser::ParseReturnStatement() { - assert(Tok.is(tok::kw_return) && "Not a return stmt!"); + assert((Tok.is(tok::kw_return) || Tok.is(tok::kw_co_return)) && + "Not a return stmt!"); + bool IsCoreturn = Tok.is(tok::kw_co_return); SourceLocation ReturnLoc = ConsumeToken(); // eat the 'return'. ExprResult R; if (Tok.isNot(tok::semi)) { - if (Tok.is(tok::code_completion)) { + // FIXME: Code completion for co_return. + if (Tok.is(tok::code_completion) && !IsCoreturn) { Actions.CodeCompleteReturn(getCurScope()); cutOffParsing(); return StmtError(); @@ -1825,6 +1856,8 @@ StmtResult Parser::ParseReturnStatement() { return StmtError(); } } + if (IsCoreturn) + return Actions.ActOnCoreturnStmt(ReturnLoc, R.get()); return Actions.ActOnReturnStmt(ReturnLoc, R.get(), getCurScope()); } @@ -1870,6 +1903,11 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope) { PrettyDeclStackTraceEntry CrashInfo(Actions, Decl, LBraceLoc, "parsing function body"); + // Save and reset current vtordisp stack if we have entered a C++ method body. + bool IsCXXMethod = + getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl); + Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod); + // Do not enter a scope for the brace, as the arguments are in the same scope // (the function body) as the body itself. Instead, just read the statement // list and put it into a CompoundStmt for safe keeping. @@ -1909,6 +1947,11 @@ Decl *Parser::ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope) { return Actions.ActOnSkippedFunctionBody(Decl); } + // Save and reset current vtordisp stack if we have entered a C++ method body. + bool IsCXXMethod = + getLangOpts().CPlusPlus && Decl && isa<CXXMethodDecl>(Decl); + Sema::VtorDispStackRAII SavedVtorDispStack(Actions, IsCXXMethod); + SourceLocation LBraceLoc = Tok.getLocation(); StmtResult FnBody(ParseCXXTryBlockCommon(TryLoc, /*FnTry*/true)); // If we failed to parse the try-catch, we just give the function an empty diff --git a/lib/Parse/ParseStmtAsm.cpp b/lib/Parse/ParseStmtAsm.cpp index 8cdae6a..f469a064 100644 --- a/lib/Parse/ParseStmtAsm.cpp +++ b/lib/Parse/ParseStmtAsm.cpp @@ -215,12 +215,36 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, // Require an identifier here. SourceLocation TemplateKWLoc; UnqualifiedId Id; - bool Invalid = - ParseUnqualifiedId(SS, - /*EnteringContext=*/false, - /*AllowDestructorName=*/false, - /*AllowConstructorName=*/false, - /*ObjectType=*/ParsedType(), TemplateKWLoc, Id); + bool Invalid = true; + ExprResult Result; + if (Tok.is(tok::kw_this)) { + Result = ParseCXXThis(); + Invalid = false; + } else { + Invalid = + ParseUnqualifiedId(SS, + /*EnteringContext=*/false, + /*AllowDestructorName=*/false, + /*AllowConstructorName=*/false, + /*ObjectType=*/ParsedType(), TemplateKWLoc, Id); + // Perform the lookup. + Result = Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, + IsUnevaluatedContext); + } + // While the next two tokens are 'period' 'identifier', repeatedly parse it as + // a field access. We have to avoid consuming assembler directives that look + // like '.' 'else'. + while (Result.isUsable() && Tok.is(tok::period)) { + Token IdTok = PP.LookAhead(0); + if (IdTok.isNot(tok::identifier)) + break; + ConsumeToken(); // Consume the period. + IdentifierInfo *Id = Tok.getIdentifierInfo(); + ConsumeToken(); // Consume the identifier. + unsigned OffsetUnused; + Result = Actions.LookupInlineAsmVarDeclField( + Result.get(), Id->getName(), OffsetUnused, Info, Tok.getLocation()); + } // Figure out how many tokens we are into LineToks. unsigned LineIndex = 0; @@ -254,9 +278,7 @@ ExprResult Parser::ParseMSAsmIdentifier(llvm::SmallVectorImpl<Token> &LineToks, LineToks.pop_back(); LineToks.pop_back(); - // Perform the lookup. - return Actions.LookupInlineAsmIdentifier(SS, TemplateKWLoc, Id, Info, - IsUnevaluatedContext); + return Result; } /// Turn a sequence of our tokens back into a string that we can hand diff --git a/lib/Parse/ParseTemplate.cpp b/lib/Parse/ParseTemplate.cpp index 3a964dd..a4dcdb1 100644 --- a/lib/Parse/ParseTemplate.cpp +++ b/lib/Parse/ParseTemplate.cpp @@ -126,8 +126,7 @@ Parser::ParseTemplateDeclarationOrSpecialization(unsigned Context, Actions.ActOnTemplateParameterList(CurTemplateDepthTracker.getDepth(), ExportLoc, TemplateLoc, LAngleLoc, - TemplateParams.data(), - TemplateParams.size(), RAngleLoc)); + TemplateParams, RAngleLoc)); if (!TemplateParams.empty()) { isSpecialization = false; @@ -280,8 +279,8 @@ Parser::ParseSingleDeclarationAfterTemplate( // Recover as if it were an explicit specialization. TemplateParameterLists FakedParamLists; FakedParamLists.push_back(Actions.ActOnTemplateParameterList( - 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, nullptr, - 0, LAngleLoc)); + 0, SourceLocation(), TemplateInfo.TemplateLoc, LAngleLoc, None, + LAngleLoc)); return ParseFunctionDefinition( DeclaratorInfo, ParsedTemplateInfo(&FakedParamLists, @@ -631,8 +630,7 @@ Parser::ParseTemplateTemplateParameter(unsigned Depth, unsigned Position) { TemplateParameterList *ParamList = Actions.ActOnTemplateParameterList(Depth, SourceLocation(), TemplateLoc, LAngleLoc, - TemplateParams.data(), - TemplateParams.size(), + TemplateParams, RAngleLoc); // Grab a default argument (if available). @@ -695,7 +693,8 @@ Parser::ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position) { // end of the template-parameter-list rather than a greater-than // operator. GreaterThanIsOperatorScope G(GreaterThanIsOperator, false); - EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated); + EnterExpressionEvaluationContext ConstantEvaluated(Actions, + Sema::ConstantEvaluated); DefaultArg = Actions.CorrectDelayedTyposInExpr(ParseAssignmentExpression()); if (DefaultArg.isInvalid()) diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 9d2a2b9..6fbcfd9 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -1089,6 +1089,7 @@ public: /// [GNU] typeof-specifier /// [GNU] '_Complex' /// [C++11] 'auto' +/// [GNU] '__auto_type' /// [C++11] 'decltype' ( expression ) /// [C++1y] 'decltype' ( 'auto' ) /// @@ -1262,6 +1263,7 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult, case tok::kw_restrict: case tok::kw__Complex: case tok::kw___attribute: + case tok::kw___auto_type: return TPResult::True; // Microsoft @@ -1515,6 +1517,7 @@ bool Parser::isCXXDeclarationSpecifierAType() { case tok::kw_double: case tok::kw_void: case tok::kw___unknown_anytype: + case tok::kw___auto_type: return true; case tok::kw_auto: diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 0574a63..b3eeb9d 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -282,6 +282,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) { // Ran out of tokens. return false; + case tok::annot_pragma_openmp: case tok::annot_pragma_openmp_end: // Stop before an OpenMP pragma boundary. case tok::annot_module_begin: @@ -1067,10 +1068,17 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Tell the actions module that we have entered a function definition with the // specified Declarator for the function. - Decl *Res = TemplateInfo.TemplateParams? - Actions.ActOnStartOfFunctionTemplateDef(getCurScope(), - *TemplateInfo.TemplateParams, D) - : Actions.ActOnStartOfFunctionDef(getCurScope(), D); + Sema::SkipBodyInfo SkipBody; + Decl *Res = Actions.ActOnStartOfFunctionDef(getCurScope(), D, + TemplateInfo.TemplateParams + ? *TemplateInfo.TemplateParams + : MultiTemplateParamsArg(), + &SkipBody); + + if (SkipBody.ShouldSkip) { + SkipFunctionBody(); + return Res; + } // Break out of the ParsingDeclarator context before we parse the body. D.complete(Res); @@ -1086,14 +1094,16 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, SourceLocation KWLoc; if (TryConsumeToken(tok::kw_delete, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 - ? diag::warn_cxx98_compat_deleted_function - : diag::ext_deleted_function); + ? diag::warn_cxx98_compat_defaulted_deleted_function + : diag::ext_defaulted_deleted_function) + << 1 /* deleted */; Actions.SetDeclDeleted(Res, KWLoc); Delete = true; } else if (TryConsumeToken(tok::kw_default, KWLoc)) { Diag(KWLoc, getLangOpts().CPlusPlus11 - ? diag::warn_cxx98_compat_defaulted_function - : diag::ext_defaulted_function); + ? diag::warn_cxx98_compat_defaulted_deleted_function + : diag::ext_defaulted_deleted_function) + << 0 /* defaulted */; Actions.SetDeclDefaulted(Res, KWLoc); } else { llvm_unreachable("function definition after = not 'delete' or 'default'"); @@ -1137,6 +1147,28 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, return ParseFunctionStatementBody(Res, BodyScope); } +void Parser::SkipFunctionBody() { + if (Tok.is(tok::equal)) { + SkipUntil(tok::semi); + return; + } + + bool IsFunctionTryBlock = Tok.is(tok::kw_try); + if (IsFunctionTryBlock) + ConsumeToken(); + + CachedTokens Skipped; + if (ConsumeAndStoreFunctionPrologue(Skipped)) + SkipMalformedDecl(); + else { + SkipUntil(tok::r_brace); + while (IsFunctionTryBlock && Tok.is(tok::kw_catch)) { + SkipUntil(tok::l_brace); + SkipUntil(tok::r_brace); + } + } +} + /// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides /// types for a function with a K&R-style identifier list for arguments. void Parser::ParseKNRParamDeclarations(Declarator &D) { @@ -1493,7 +1525,7 @@ bool Parser::TryKeywordIdentFallback(bool DisableKeyword) { << PP.getSpelling(Tok) << DisableKeyword; if (DisableKeyword) - Tok.getIdentifierInfo()->RevertTokenIDToIdentifier(); + Tok.getIdentifierInfo()->revertTokenIDToIdentifier(); Tok.setKind(tok::identifier); return true; } @@ -1989,6 +2021,37 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) { return Actions.ConvertDeclToDeclGroup(Import.get()); } +/// \brief 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. +bool Parser::parseMisplacedModuleImport() { + while (true) { + switch (Tok.getKind()) { + case tok::annot_module_end: + // Inform caller that recovery failed, the error must be handled at upper + // level. + return true; + case tok::annot_module_begin: + Actions.diagnoseMisplacedModuleImport(reinterpret_cast<Module *>( + Tok.getAnnotationValue()), Tok.getLocation()); + return true; + case tok::annot_module_include: + // Module import found where it should not be, for instance, inside a + // namespace. Recover by importing the module. + Actions.ActOnModuleInclude(Tok.getLocation(), + reinterpret_cast<Module *>( + Tok.getAnnotationValue())); + ConsumeToken(); + // If there is another module import, process it. + continue; + default: + return false; + } + } + return false; +} + bool BalancedDelimiterTracker::diagnoseOverflow() { P.Diag(P.Tok, diag::err_bracket_depth_exceeded) << P.getLangOpts().BracketDepth; @@ -2016,7 +2079,10 @@ bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID, bool BalancedDelimiterTracker::diagnoseMissingClose() { assert(!P.Tok.is(Close) && "Should have consumed closing delimiter"); - P.Diag(P.Tok, diag::err_expected) << Close; + if (P.Tok.is(tok::annot_module_end)) + P.Diag(P.Tok, diag::err_missing_before_module_end) << Close; + else + P.Diag(P.Tok, diag::err_expected) << Close; P.Diag(LOpen, diag::note_matching) << Kind; // If we're not already at some kind of closing bracket, skip to our closing |