diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/Parser.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/Parser.cpp | 439 |
1 files changed, 190 insertions, 249 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 457dd36..37ce157 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -12,9 +12,9 @@ //===----------------------------------------------------------------------===// #include "clang/Parse/Parser.h" -#include "ParsePragma.h" #include "RAIIObjectsForParser.h" #include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/DeclSpec.h" @@ -33,7 +33,7 @@ class ActionCommentHandler : public CommentHandler { public: explicit ActionCommentHandler(Sema &S) : S(S) { } - virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) { + bool HandleComment(Preprocessor &PP, SourceRange Comment) override { S.ActOnComment(Comment); return false; } @@ -56,58 +56,14 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies; Tok.startToken(); Tok.setKind(tok::eof); - Actions.CurScope = 0; + Actions.CurScope = nullptr; NumCachedScopes = 0; ParenCount = BracketCount = BraceCount = 0; - CurParsedObjCImpl = 0; + CurParsedObjCImpl = nullptr; // Add #pragma handlers. These are removed and destroyed in the // destructor. - AlignHandler.reset(new PragmaAlignHandler()); - PP.AddPragmaHandler(AlignHandler.get()); - - GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler()); - PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); - - OptionsHandler.reset(new PragmaOptionsHandler()); - PP.AddPragmaHandler(OptionsHandler.get()); - - PackHandler.reset(new PragmaPackHandler()); - PP.AddPragmaHandler(PackHandler.get()); - - MSStructHandler.reset(new PragmaMSStructHandler()); - PP.AddPragmaHandler(MSStructHandler.get()); - - UnusedHandler.reset(new PragmaUnusedHandler()); - PP.AddPragmaHandler(UnusedHandler.get()); - - WeakHandler.reset(new PragmaWeakHandler()); - PP.AddPragmaHandler(WeakHandler.get()); - - RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler()); - PP.AddPragmaHandler(RedefineExtnameHandler.get()); - - FPContractHandler.reset(new PragmaFPContractHandler()); - PP.AddPragmaHandler("STDC", FPContractHandler.get()); - - if (getLangOpts().OpenCL) { - OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler()); - PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); - - PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); - } - if (getLangOpts().OpenMP) - OpenMPHandler.reset(new PragmaOpenMPHandler()); - else - OpenMPHandler.reset(new PragmaNoOpenMPHandler()); - PP.AddPragmaHandler(OpenMPHandler.get()); - - if (getLangOpts().MicrosoftExt) { - MSCommentHandler.reset(new PragmaCommentHandler(actions)); - PP.AddPragmaHandler(MSCommentHandler.get()); - MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(actions)); - PP.AddPragmaHandler(MSDetectMismatchHandler.get()); - } + initializePragmaHandlers(); CommentSemaHandler.reset(new ActionCommentHandler(actions)); PP.addCommentHandler(CommentSemaHandler.get()); @@ -152,14 +108,8 @@ static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) { } } -/// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the -/// input. If so, it is consumed and false is returned. -/// -/// If the input is malformed, this emits the specified diagnostic. Next, if -/// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is -/// returned. bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, - const char *Msg, tok::TokenKind SkipToTok) { + StringRef Msg) { if (Tok.is(ExpectedTok) || Tok.is(tok::code_completion)) { ConsumeAnyToken(); return false; @@ -168,35 +118,48 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, // Detect common single-character typos and resume. if (IsCommonTypo(ExpectedTok, Tok)) { SourceLocation Loc = Tok.getLocation(); - Diag(Loc, DiagID) - << Msg - << FixItHint::CreateReplacement(SourceRange(Loc), - getTokenSimpleSpelling(ExpectedTok)); - ConsumeAnyToken(); + { + DiagnosticBuilder DB = Diag(Loc, DiagID); + DB << FixItHint::CreateReplacement( + SourceRange(Loc), tok::getPunctuatorSpelling(ExpectedTok)); + if (DiagID == diag::err_expected) + DB << ExpectedTok; + else if (DiagID == diag::err_expected_after) + DB << Msg << ExpectedTok; + else + DB << Msg; + } // Pretend there wasn't a problem. + ConsumeAnyToken(); return false; } - const char *Spelling = 0; SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); - if (EndLoc.isValid() && - (Spelling = tok::getTokenSimpleSpelling(ExpectedTok))) { - // Show what code to insert to fix this problem. - Diag(EndLoc, DiagID) - << Msg - << FixItHint::CreateInsertion(EndLoc, Spelling); - } else - Diag(Tok, DiagID) << Msg; + const char *Spelling = nullptr; + if (EndLoc.isValid()) + Spelling = tok::getPunctuatorSpelling(ExpectedTok); + + DiagnosticBuilder DB = + Spelling + ? Diag(EndLoc, DiagID) << FixItHint::CreateInsertion(EndLoc, Spelling) + : Diag(Tok, DiagID); + if (DiagID == diag::err_expected) + DB << ExpectedTok; + else if (DiagID == diag::err_expected_after) + DB << Msg << ExpectedTok; + else + DB << Msg; - if (SkipToTok != tok::unknown) - SkipUntil(SkipToTok, StopAtSemi); return true; } bool Parser::ExpectAndConsumeSemi(unsigned DiagID) { - if (Tok.is(tok::semi) || Tok.is(tok::code_completion)) { - ConsumeToken(); + if (TryConsumeToken(tok::semi)) + return false; + + if (Tok.is(tok::code_completion)) { + handleUnexpectedCodeCompletionToken(); return false; } @@ -241,7 +204,8 @@ void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) { if (Kind != AfterMemberFunctionDefinition || HadMultipleSemis) Diag(StartLoc, diag::ext_extra_semi) - << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST) + << Kind << DeclSpec::getSpecifierName((DeclSpec::TST)TST, + Actions.getASTContext().getPrintingPolicy()) << FixItHint::CreateRemoval(SourceRange(StartLoc, EndLoc)); else // A single semicolon is valid after a member function definition. @@ -288,7 +252,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) { if (Toks.size() == 1 && Toks[0] == tok::eof && !HasFlagsSet(Flags, StopAtSemi) && !HasFlagsSet(Flags, StopAtCodeCompletion)) { - while (Tok.getKind() != tok::eof) + while (Tok.isNot(tok::eof)) ConsumeAnyToken(); return true; } @@ -297,10 +261,20 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) { case tok::eof: // Ran out of tokens. return false; - + + case tok::annot_pragma_openmp_end: + // Stop before an OpenMP pragma boundary. + case tok::annot_module_begin: + case tok::annot_module_end: + case tok::annot_module_include: + // Stop before we change submodules. They generally indicate a "good" + // place to pick up parsing again (except in the special case where + // we're trying to skip to EOF). + return false; + case tok::code_completion: if (!HasFlagsSet(Flags, StopAtCodeCompletion)) - ConsumeToken(); + handleUnexpectedCodeCompletionToken(); return false; case tok::l_paren: @@ -391,8 +365,7 @@ void Parser::ExitScope() { // Inform the actions module that this scope is going away if there are any // decls in it. - if (!getCurScope()->decl_empty()) - Actions.ActOnPopScope(Tok.getLocation(), getCurScope()); + Actions.ActOnPopScope(Tok.getLocation(), getCurScope()); Scope *OldScope = getCurScope(); Actions.CurScope = OldScope->getParent(); @@ -407,7 +380,7 @@ void Parser::ExitScope() { /// this object does nothing. Parser::ParseScopeFlags::ParseScopeFlags(Parser *Self, unsigned ScopeFlags, bool ManageFlags) - : CurScope(ManageFlags ? Self->getCurScope() : 0) { + : CurScope(ManageFlags ? Self->getCurScope() : nullptr) { if (CurScope) { OldFlags = CurScope->getFlags(); CurScope->setFlags(ScopeFlags); @@ -429,47 +402,13 @@ Parser::ParseScopeFlags::~ParseScopeFlags() { Parser::~Parser() { // If we still have scopes active, delete the scope tree. delete getCurScope(); - Actions.CurScope = 0; - + Actions.CurScope = nullptr; + // Free the scope cache. for (unsigned i = 0, e = NumCachedScopes; i != e; ++i) delete ScopeCache[i]; - // Remove the pragma handlers we installed. - PP.RemovePragmaHandler(AlignHandler.get()); - AlignHandler.reset(); - PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get()); - GCCVisibilityHandler.reset(); - PP.RemovePragmaHandler(OptionsHandler.get()); - OptionsHandler.reset(); - PP.RemovePragmaHandler(PackHandler.get()); - PackHandler.reset(); - PP.RemovePragmaHandler(MSStructHandler.get()); - MSStructHandler.reset(); - PP.RemovePragmaHandler(UnusedHandler.get()); - UnusedHandler.reset(); - PP.RemovePragmaHandler(WeakHandler.get()); - WeakHandler.reset(); - PP.RemovePragmaHandler(RedefineExtnameHandler.get()); - RedefineExtnameHandler.reset(); - - if (getLangOpts().OpenCL) { - PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get()); - OpenCLExtensionHandler.reset(); - PP.RemovePragmaHandler("OPENCL", FPContractHandler.get()); - } - PP.RemovePragmaHandler(OpenMPHandler.get()); - OpenMPHandler.reset(); - - if (getLangOpts().MicrosoftExt) { - PP.RemovePragmaHandler(MSCommentHandler.get()); - MSCommentHandler.reset(); - PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); - MSDetectMismatchHandler.reset(); - } - - PP.RemovePragmaHandler("STDC", FPContractHandler.get()); - FPContractHandler.reset(); + resetPragmaHandlers(); PP.removeCommentHandler(CommentSemaHandler.get()); @@ -482,7 +421,7 @@ Parser::~Parser() { /// void Parser::Initialize() { // Create the translation unit scope. Install it as the current scope. - assert(getCurScope() == 0 && "A scope is already active?"); + assert(getCurScope() == nullptr && "A scope is already active?"); EnterScope(Scope::DeclScope); Actions.ActOnTranslationUnitScope(getCurScope()); @@ -497,10 +436,10 @@ void Parser::Initialize() { ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref"); } - Ident_instancetype = 0; - Ident_final = 0; - Ident_sealed = 0; - Ident_override = 0; + Ident_instancetype = nullptr; + Ident_final = nullptr; + Ident_sealed = nullptr; + Ident_override = nullptr; Ident_super = &PP.getIdentifierTable().get("super"); @@ -510,16 +449,18 @@ void Parser::Initialize() { Ident_bool = &PP.getIdentifierTable().get("bool"); } - Ident_introduced = 0; - Ident_deprecated = 0; - Ident_obsoleted = 0; - Ident_unavailable = 0; + Ident_introduced = nullptr; + Ident_deprecated = nullptr; + Ident_obsoleted = nullptr; + Ident_unavailable = nullptr; - Ident__except = 0; - - Ident__exception_code = Ident__exception_info = Ident__abnormal_termination = 0; - Ident___exception_code = Ident___exception_info = Ident___abnormal_termination = 0; - Ident_GetExceptionCode = Ident_GetExceptionInfo = Ident_AbnormalTermination = 0; + Ident__except = nullptr; + + Ident__exception_code = Ident__exception_info = nullptr; + Ident__abnormal_termination = Ident___exception_code = nullptr; + Ident___exception_info = Ident___abnormal_termination = nullptr; + Ident_GetExceptionCode = Ident_GetExceptionInfo = nullptr; + Ident_AbnormalTermination = nullptr; if(getLangOpts().Borland) { Ident__exception_info = PP.getIdentifierInfo("_exception_info"); @@ -574,7 +515,7 @@ namespace { bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { DestroyTemplateIdAnnotationsRAIIObj CleanupRAII(TemplateIds); - // Skip over the EOF token, flagging end of previous input for incremental + // Skip over the EOF token, flagging end of previous input for incremental // processing if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) ConsumeToken(); @@ -592,6 +533,12 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { ConsumeToken(); return false; + case tok::annot_module_begin: + case tok::annot_module_end: + // FIXME: Update visibility based on the submodule we're in. + ConsumeToken(); + return false; + case tok::eof: // Late template parsing can begin. if (getLangOpts().DelayedTemplateParsing) @@ -647,7 +594,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, return DeclGroupPtrTy(); } - Decl *SingleDecl = 0; + Decl *SingleDecl = nullptr; switch (Tok.getKind()) { case tok::annot_pragma_vis: HandlePragmaVisibility(); @@ -679,6 +626,15 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_openmp: ParseOpenMPDeclarativeDirective(); return DeclGroupPtrTy(); + case tok::annot_pragma_ms_pointers_to_members: + HandlePragmaMSPointersToMembers(); + return DeclGroupPtrTy(); + case tok::annot_pragma_ms_vtordisp: + HandlePragmaMSVtorDisp(); + return DeclGroupPtrTy(); + case tok::annot_pragma_ms_pragma: + HandlePragmaMSPragma(); + return DeclGroupPtrTy(); case tok::semi: // Either a C++11 empty-declaration or attribute-declaration. SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), @@ -706,7 +662,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, SourceLocation EndLoc; ExprResult Result(ParseSimpleAsm(&EndLoc)); - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, + ExpectAndConsume(tok::semi, diag::err_expected_after, "top-level asm block"); if (Result.isInvalid()) @@ -793,7 +749,6 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParseExplicitInstantiation(Declarator::FileContext, ExternLoc, TemplateLoc, DeclEnd)); } - // FIXME: Detect C++ linkage specifications here? goto dont_know; case tok::kw___if_exists: @@ -907,9 +862,10 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, DS.abort(); - const char *PrevSpec = 0; + const char *PrevSpec = nullptr; unsigned DiagID; - if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID)) + if (DS.SetTypeSpecType(DeclSpec::TST_unspecified, AtLoc, PrevSpec, DiagID, + Actions.getASTContext().getPrintingPolicy())) Diag(AtLoc, DiagID) << PrevSpec; if (Tok.isObjCAtKeyword(tok::objc_protocol)) @@ -922,7 +878,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, // If the declspec consisted only of 'extern' and we have a string // literal following it, this must be a C++ linkage specifier like // 'extern "C"'. - if (Tok.is(tok::string_literal) && getLangOpts().CPlusPlus && + if (getLangOpts().CPlusPlus && isTokenStringLiteral() && DS.getStorageClassSpec() == DeclSpec::SCS_extern && DS.getParsedSpecifiers() == DeclSpec::PQ_StorageClassSpecifier) { Decl *TheDecl = ParseLinkage(DS, Declarator::FileContext); @@ -949,26 +905,6 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributesWithRange &attrs, } } - -static inline bool isFunctionDeclaratorRequiringReturnTypeDeduction( - const Declarator &D) { - if (!D.isFunctionDeclarator() || !D.getDeclSpec().containsPlaceholderType()) - return false; - for (unsigned I = 0, E = D.getNumTypeObjects(); I != E; ++I) { - unsigned chunkIndex = E - I - 1; - const DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex); - if (DeclType.Kind == DeclaratorChunk::Function) { - const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun; - if (!FTI.hasTrailingReturnType()) - return true; - QualType TrailingRetType = FTI.getTrailingReturnType().get(); - return TrailingRetType->getCanonicalTypeInternal() - ->getContainedAutoType(); - } - } - return false; -} - /// ParseFunctionDefinition - We parsed and verified that the specified /// Declarator is well formed. If this is a K&R-style function, read the /// parameters declaration-list, then start the compound-statement. @@ -996,9 +932,11 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (getLangOpts().ImplicitInt && D.getDeclSpec().isEmpty()) { const char *PrevSpec; unsigned DiagID; + const PrintingPolicy &Policy = Actions.getASTContext().getPrintingPolicy(); D.getMutableDeclSpec().SetTypeSpecType(DeclSpec::TST_int, D.getIdentifierLoc(), - PrevSpec, DiagID); + PrevSpec, DiagID, + Policy); D.SetRangeBegin(D.getDeclSpec().getSourceRange().getBegin()); } @@ -1021,7 +959,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // If we didn't find the '{', bail out. if (Tok.isNot(tok::l_brace)) - return 0; + return nullptr; } // Check to make sure that any normal attributes are allowed to be on @@ -1029,10 +967,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (Tok.isNot(tok::equal)) { AttributeList *DtorAttrs = D.getAttributes(); while (DtorAttrs) { - if (!IsThreadSafetyAttribute(DtorAttrs->getName()->getName()) && + if (DtorAttrs->isKnownToGCC() && !DtorAttrs->isCXX11Attribute()) { Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition) - << DtorAttrs->getName()->getName(); + << DtorAttrs->getName(); } DtorAttrs = DtorAttrs->getNext(); } @@ -1042,8 +980,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // tokens and store them for late parsing at the end of the translation unit. if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) && TemplateInfo.Kind == ParsedTemplateInfo::Template && - !D.getDeclSpec().isConstexprSpecified() && - !isFunctionDeclaratorRequiringReturnTypeDeduction(D)) { + Actions.canDelayFunctionBody(D)) { MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams); ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); @@ -1059,12 +996,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, LexTemplateFunctionForLateParsing(Toks); if (DP) { - FunctionDecl *FnD = 0; - if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(DP)) - FnD = FunTmpl->getTemplatedDecl(); - else - FnD = cast<FunctionDecl>(DP); - + FunctionDecl *FnD = DP->getAsFunction(); Actions.CheckForFunctionRedefinition(FnD); Actions.MarkAsLateParsedTemplate(FnD, DP, Toks); } @@ -1077,7 +1009,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, Actions.CurContext->isTranslationUnit()) { ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); Scope *ParentScope = getCurScope()->getParent(); - + D.setFunctionDefinitionKind(FDK_Definition); Decl *FuncDecl = Actions.HandleDeclarator(ParentScope, D, MultiTemplateParamsArg()); @@ -1089,8 +1021,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, CurParsedObjCImpl->HasCFunction = true; return FuncDecl; } + // FIXME: Should we really fall through here? } - + // Enter a scope for the function body. ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); @@ -1108,28 +1041,22 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // safe because we're always the sole owner. D.getMutableDeclSpec().abort(); - if (Tok.is(tok::equal)) { + if (TryConsumeToken(tok::equal)) { assert(getLangOpts().CPlusPlus && "Only C++ function definitions have '='"); - ConsumeToken(); + Actions.ActOnFinishFunctionBody(Res, nullptr, false); - Actions.ActOnFinishFunctionBody(Res, 0, false); - bool Delete = false; SourceLocation KWLoc; - if (Tok.is(tok::kw_delete)) { - Diag(Tok, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_deleted_function : - diag::ext_deleted_function); - - KWLoc = ConsumeToken(); + if (TryConsumeToken(tok::kw_delete, KWLoc)) { + Diag(KWLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_deleted_function + : diag::ext_deleted_function); Actions.SetDeclDeleted(Res, KWLoc); Delete = true; - } else if (Tok.is(tok::kw_default)) { - Diag(Tok, getLangOpts().CPlusPlus11 ? - diag::warn_cxx98_compat_defaulted_function : - diag::ext_defaulted_function); - - KWLoc = ConsumeToken(); + } else if (TryConsumeToken(tok::kw_default, KWLoc)) { + Diag(KWLoc, getLangOpts().CPlusPlus11 + ? diag::warn_cxx98_compat_defaulted_function + : diag::ext_defaulted_function); Actions.SetDeclDefaulted(Res, KWLoc); } else { llvm_unreachable("function definition after = not 'delete' or 'default'"); @@ -1139,9 +1066,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, Diag(KWLoc, diag::err_default_delete_in_multiple_declaration) << Delete; SkipUntil(tok::semi); - } else { - ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - Delete ? "delete" : "default", tok::semi); + } else if (ExpectAndConsume(tok::semi, diag::err_expected_after, + Delete ? "delete" : "default")) { + SkipUntil(tok::semi); } return Res; @@ -1158,7 +1085,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Recover from error. if (!Tok.is(tok::l_brace)) { BodyScope.Exit(); - Actions.ActOnFinishFunctionBody(Res, 0); + Actions.ActOnFinishFunctionBody(Res, nullptr); return Res; } } else @@ -1195,9 +1122,8 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // NOTE: GCC just makes this an ext-warn. It's not clear what it does with // the declarations though. It's trivial to ignore them, really hard to do // anything else with them. - if (Tok.is(tok::semi)) { + if (TryConsumeToken(tok::semi)) { Diag(DSStart, diag::err_declaration_does_not_declare_param); - ConsumeToken(); continue; } @@ -1237,20 +1163,20 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { for (unsigned i = 0; ; ++i) { // C99 6.9.1p6: those declarators shall declare only identifiers from // the identifier list. - if (i == FTI.NumArgs) { + if (i == FTI.NumParams) { Diag(ParmDeclarator.getIdentifierLoc(), diag::err_no_matching_param) << ParmDeclarator.getIdentifier(); break; } - if (FTI.ArgInfo[i].Ident == ParmDeclarator.getIdentifier()) { + if (FTI.Params[i].Ident == ParmDeclarator.getIdentifier()) { // Reject redefinitions of parameters. - if (FTI.ArgInfo[i].Param) { + if (FTI.Params[i].Param) { Diag(ParmDeclarator.getIdentifierLoc(), diag::err_param_redefinition) << ParmDeclarator.getIdentifier(); } else { - FTI.ArgInfo[i].Param = Param; + FTI.Params[i].Param = Param; } break; } @@ -1271,12 +1197,14 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { ParseDeclarator(ParmDeclarator); } - if (ExpectAndConsumeSemi(diag::err_expected_semi_declaration)) { - // Skip to end of block or statement - SkipUntil(tok::semi); - if (Tok.is(tok::semi)) - ConsumeToken(); - } + // Consume ';' and continue parsing. + if (!ExpectAndConsumeSemi(diag::err_expected_semi_declaration)) + continue; + + // Otherwise recover by skipping to next semi or mandatory function body. + if (SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch)) + break; + TryConsumeToken(tok::semi); } // The actions module must verify that all arguments were declared. @@ -1340,16 +1268,15 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { ExprResult Result(ParseAsmStringLiteral()); - if (Result.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch); - if (EndLoc) - *EndLoc = Tok.getLocation(); - ConsumeAnyToken(); - } else { + if (!Result.isInvalid()) { // Close the paren and get the location of the end bracket T.consumeClose(); if (EndLoc) *EndLoc = T.getCloseLocation(); + } else if (SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch)) { + if (EndLoc) + *EndLoc = Tok.getLocation(); + ConsumeParen(); } return Result; @@ -1430,11 +1357,11 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, // Look up and classify the identifier. We don't perform any typo-correction // after a scope specifier, because in general we can't recover from typos - // there (eg, after correcting 'A::tempalte B<X>::C', we would need to jump - // back into scope specifier parsing). + // there (eg, after correcting 'A::tempalte B<X>::C' [sic], we would need to + // jump back into scope specifier parsing). Sema::NameClassification Classification = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next, - IsAddressOfOperand, SS.isEmpty() ? CCC : 0); + IsAddressOfOperand, SS.isEmpty() ? CCC : nullptr); switch (Classification.getKind()) { case Sema::NC_Error: @@ -1504,16 +1431,34 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, } bool Parser::TryKeywordIdentFallback(bool DisableKeyword) { - assert(Tok.isNot(tok::identifier)); + assert(!Tok.is(tok::identifier) && !Tok.isAnnotation()); Diag(Tok, diag::ext_keyword_as_ident) << PP.getSpelling(Tok) << DisableKeyword; - if (DisableKeyword) - Tok.getIdentifierInfo()->RevertTokenIDToIdentifier(); + if (DisableKeyword) { + IdentifierInfo *II = Tok.getIdentifierInfo(); + ContextualKeywords[II] = Tok.getKind(); + II->RevertTokenIDToIdentifier(); + } Tok.setKind(tok::identifier); return true; } +bool Parser::TryIdentKeywordUpgrade() { + assert(Tok.is(tok::identifier)); + const IdentifierInfo *II = Tok.getIdentifierInfo(); + assert(II->hasRevertedTokenIDToIdentifier()); + // If we find that this is in fact the name of a type trait, + // update the token kind in place and parse again to treat it as + // the appropriate kind of type trait. + llvm::SmallDenseMap<const IdentifierInfo *, tok::TokenKind>::iterator Known = + ContextualKeywords.find(II); + if (Known == ContextualKeywords.end()) + return false; + Tok.setKind(Known->second); + return true; +} + /// TryAnnotateTypeOrScopeToken - If the current token position is on a /// typename (possibly qualified in C++) or a C++ scope specifier not followed /// by a typename, TryAnnotateTypeOrScopeToken will replace one or more tokens @@ -1549,7 +1494,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { // We will consume the typedef token here and put it back after we have // parsed the first identifier, transforming it into something more like: // typename T_::D typedef D; - if (getLangOpts().MicrosoftMode && NextToken().is(tok::kw_typedef)) { + if (getLangOpts().MSVCCompat && NextToken().is(tok::kw_typedef)) { Token TypedefToken; PP.Lex(TypedefToken); bool Result = TryAnnotateTypeOrScopeToken(EnteringContext, NeedType); @@ -1570,7 +1515,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { CXXScopeSpec SS; if (ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/ParsedType(), /*EnteringContext=*/false, - 0, /*IsTypename*/true)) + nullptr, /*IsTypename*/ true)) return true; if (!SS.isSet()) { if (Tok.is(tok::identifier) || Tok.is(tok::annot_template_id) || @@ -1601,7 +1546,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { Tok.getLocation()); } else if (Tok.is(tok::annot_template_id)) { TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); - if (TemplateId->Kind == TNK_Function_template) { + if (TemplateId->Kind != TNK_Type_template && + TemplateId->Kind != TNK_Dependent_template_name) { Diag(Tok, diag::err_typename_refers_to_non_type_template) << Tok.getAnnotationRange(); return true; @@ -1652,7 +1598,7 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, CXXScopeSpec &SS, bool IsNewScope) { if (Tok.is(tok::identifier)) { - IdentifierInfo *CorrectedII = 0; + IdentifierInfo *CorrectedII = nullptr; // Determine whether the identifier is a type name. if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), @@ -1660,8 +1606,9 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, NextToken().is(tok::period), ParsedType(), /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo*/true, - NeedType ? &CorrectedII : NULL)) { + /*NonTrivialTypeSourceInfo*/ true, + NeedType ? &CorrectedII + : nullptr)) { // A FixIt was applied as a result of typo correction if (CorrectedII) Tok.setIdentifierInfo(CorrectedII); @@ -1725,8 +1672,7 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, // annotation token to a type annotation token now. AnnotateTemplateIdTokenAsType(); return false; - } else if (TemplateId->Kind == TNK_Var_template) - return false; + } } if (SS.isEmpty()) @@ -1780,8 +1726,8 @@ bool Parser::isTokenEqualOrEqualTypo() { case tok::pipeequal: // |= case tok::equalequal: // == Diag(Tok, diag::err_invalid_token_after_declarator_suggest_equal) - << getTokenSimpleSpelling(Kind) - << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "="); + << Kind + << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), "="); case tok::equal: return true; } @@ -1910,7 +1856,7 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { BalancedDelimiterTracker Braces(*this, tok::l_brace); if (Braces.consumeOpen()) { - Diag(Tok, diag::err_expected_lbrace); + Diag(Tok, diag::err_expected) << tok::l_brace; return; } @@ -1928,14 +1874,15 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { } // Parse the declarations. - while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof)) { + // FIXME: Support module import within __if_exists? + while (Tok.isNot(tok::r_brace) && !isEofOrEom()) { ParsedAttributesWithRange attrs(AttrFactory); MaybeParseCXX11Attributes(attrs); MaybeParseMicrosoftAttributes(attrs); DeclGroupPtrTy Result = ParseExternalDeclaration(attrs); if (Result && !getCurScope()->getParent()) Actions.getASTConsumer().HandleTopLevelDecl(Result.get()); - } + } Braces.consumeClose(); } @@ -1951,8 +1898,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) { if (!Tok.is(tok::identifier)) { if (Tok.is(tok::code_completion)) { Actions.CodeCompleteModuleImport(ImportLoc, Path); - ConsumeCodeCompletionToken(); - SkipUntil(tok::semi); + cutOffParsing(); return DeclGroupPtrTy(); } @@ -1991,17 +1937,20 @@ bool BalancedDelimiterTracker::diagnoseOverflow() { P.Diag(P.Tok, diag::err_bracket_depth_exceeded) << P.getLangOpts().BracketDepth; P.Diag(P.Tok, diag::note_bracket_depth); - P.SkipUntil(tok::eof); - return true; + P.cutOffParsing(); + return true; } bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID, - const char *Msg, - tok::TokenKind SkipToToc ) { + const char *Msg, + tok::TokenKind SkipToTok) { LOpen = P.Tok.getLocation(); - if (P.ExpectAndConsume(Kind, DiagID, Msg, SkipToToc)) + if (P.ExpectAndConsume(Kind, DiagID, Msg)) { + if (SkipToTok != tok::unknown) + P.SkipUntil(SkipToTok, Parser::StopAtSemi); return true; - + } + if (getDepth() < MaxDepth) return false; @@ -2010,17 +1959,9 @@ bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID, bool BalancedDelimiterTracker::diagnoseMissingClose() { assert(!P.Tok.is(Close) && "Should have consumed closing delimiter"); - - const char *LHSName = "unknown"; - diag::kind DID; - switch (Close) { - default: llvm_unreachable("Unexpected balanced token"); - case tok::r_paren : LHSName = "("; DID = diag::err_expected_rparen; break; - case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break; - case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break; - } - P.Diag(P.Tok, DID); - P.Diag(LOpen, diag::note_matching) << LHSName; + + 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 // token. |