diff options
Diffstat (limited to 'lib/Parse/Parser.cpp')
-rw-r--r-- | lib/Parse/Parser.cpp | 272 |
1 files changed, 207 insertions, 65 deletions
diff --git a/lib/Parse/Parser.cpp b/lib/Parse/Parser.cpp index 3725e2b..f4cdd61 100644 --- a/lib/Parse/Parser.cpp +++ b/lib/Parse/Parser.cpp @@ -23,6 +23,7 @@ #include "clang/AST/ASTConsumer.h" using namespace clang; + namespace { /// \brief A comment handler that passes comments found by the preprocessor /// to the parser action. @@ -47,11 +48,13 @@ IdentifierInfo *Parser::getSEHExceptKeyword() { return Ident__except; } -Parser::Parser(Preprocessor &pp, Sema &actions, bool SkipFunctionBodies) +Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) : PP(pp), Actions(actions), Diags(PP.getDiagnostics()), GreaterThanIsOperator(true), ColonIsSacred(false), InMessageExpression(false), TemplateParameterDepth(0), - ParsingInObjCContainer(false), SkipFunctionBodies(SkipFunctionBodies) { + ParsingInObjCContainer(false) { + SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies; + Tok.startToken(); Tok.setKind(tok::eof); Actions.CurScope = 0; NumCachedScopes = 0; @@ -60,35 +63,35 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool SkipFunctionBodies) // Add #pragma handlers. These are removed and destroyed in the // destructor. - AlignHandler.reset(new PragmaAlignHandler(actions)); + AlignHandler.reset(new PragmaAlignHandler()); PP.AddPragmaHandler(AlignHandler.get()); - GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler(actions)); + GCCVisibilityHandler.reset(new PragmaGCCVisibilityHandler()); PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get()); - OptionsHandler.reset(new PragmaOptionsHandler(actions)); + OptionsHandler.reset(new PragmaOptionsHandler()); PP.AddPragmaHandler(OptionsHandler.get()); - PackHandler.reset(new PragmaPackHandler(actions)); + PackHandler.reset(new PragmaPackHandler()); PP.AddPragmaHandler(PackHandler.get()); - MSStructHandler.reset(new PragmaMSStructHandler(actions)); + MSStructHandler.reset(new PragmaMSStructHandler()); PP.AddPragmaHandler(MSStructHandler.get()); - UnusedHandler.reset(new PragmaUnusedHandler(actions)); + UnusedHandler.reset(new PragmaUnusedHandler()); PP.AddPragmaHandler(UnusedHandler.get()); - WeakHandler.reset(new PragmaWeakHandler(actions)); + WeakHandler.reset(new PragmaWeakHandler()); PP.AddPragmaHandler(WeakHandler.get()); - RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler(actions)); + RedefineExtnameHandler.reset(new PragmaRedefineExtnameHandler()); PP.AddPragmaHandler(RedefineExtnameHandler.get()); - FPContractHandler.reset(new PragmaFPContractHandler(actions)); + FPContractHandler.reset(new PragmaFPContractHandler()); PP.AddPragmaHandler("STDC", FPContractHandler.get()); if (getLangOpts().OpenCL) { - OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler(actions)); + OpenCLExtensionHandler.reset(new PragmaOpenCLExtensionHandler()); PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); @@ -135,7 +138,7 @@ DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) { /// given range. /// /// \param Loc The location where we'll emit the diagnostic. -/// \param Loc The kind of diagnostic to emit. +/// \param DK The kind of diagnostic to emit. /// \param ParenRange Source range enclosing code that should be parenthesized. void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK, SourceRange ParenRange) { @@ -154,7 +157,8 @@ void Parser::SuggestParentheses(SourceLocation Loc, unsigned DK, static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) { switch (ExpectedTok) { - case tok::semi: return Tok.is(tok::colon); // : for ; + case tok::semi: + return Tok.is(tok::colon) || Tok.is(tok::comma); // : or , for ; default: return false; } } @@ -466,9 +470,6 @@ void Parser::Initialize() { EnterScope(Scope::DeclScope); Actions.ActOnTranslationUnitScope(getCurScope()); - // Prime the lexer look-ahead. - ConsumeToken(); - // Initialization for Objective-C context sensitive keywords recognition. // Referenced in Parser::ParseObjCTypeQualifierList. if (getLangOpts().ObjC1) { @@ -523,6 +524,11 @@ void Parser::Initialize() { PP.SetPoisonReason(Ident___abnormal_termination,diag::err_seh___finally_block); PP.SetPoisonReason(Ident_AbnormalTermination,diag::err_seh___finally_block); } + + Actions.Initialize(); + + // Prime the lexer look-ahead. + ConsumeToken(); } namespace { @@ -634,6 +640,27 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, case tok::annot_pragma_pack: HandlePragmaPack(); return DeclGroupPtrTy(); + case tok::annot_pragma_msstruct: + HandlePragmaMSStruct(); + return DeclGroupPtrTy(); + case tok::annot_pragma_align: + HandlePragmaAlign(); + return DeclGroupPtrTy(); + case tok::annot_pragma_weak: + HandlePragmaWeak(); + return DeclGroupPtrTy(); + case tok::annot_pragma_weakalias: + HandlePragmaWeakAlias(); + return DeclGroupPtrTy(); + case tok::annot_pragma_redefine_extname: + HandlePragmaRedefineExtname(); + return DeclGroupPtrTy(); + case tok::annot_pragma_fp_contract: + HandlePragmaFPContract(); + return DeclGroupPtrTy(); + case tok::annot_pragma_opencl_extension: + HandlePragmaOpenCLExtension(); + return DeclGroupPtrTy(); case tok::semi: ConsumeExtraSemi(OutsideFunction); // TODO: Invoke action for top-level semicolon. @@ -693,7 +720,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // A function definition cannot start with any of these keywords. { SourceLocation DeclEnd; - StmtVector Stmts(Actions); + StmtVector Stmts; return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } @@ -704,7 +731,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 0; SourceLocation DeclEnd; - StmtVector Stmts(Actions); + StmtVector Stmts; return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } goto dont_know; @@ -716,7 +743,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, // Inline namespaces. Allowed as an extension even in C++03. if (NextKind == tok::kw_namespace) { SourceLocation DeclEnd; - StmtVector Stmts(Actions); + StmtVector Stmts; return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } @@ -726,7 +753,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) << 1; SourceLocation DeclEnd; - StmtVector Stmts(Actions); + StmtVector Stmts; return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } } @@ -972,16 +999,14 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) && TemplateInfo.Kind == ParsedTemplateInfo::Template) { - MultiTemplateParamsArg TemplateParameterLists(Actions, - TemplateInfo.TemplateParams->data(), - TemplateInfo.TemplateParams->size()); + MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams); ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); Scope *ParentScope = getCurScope()->getParent(); D.setFunctionDefinitionKind(FDK_Definition); Decl *DP = Actions.HandleDeclarator(ParentScope, D, - move(TemplateParameterLists)); + TemplateParameterLists); D.complete(DP); D.getMutableDeclSpec().abort(); @@ -1009,13 +1034,12 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, (Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || Tok.is(tok::colon)) && Actions.CurContext->isTranslationUnit()) { - MultiTemplateParamsArg TemplateParameterLists(Actions, 0, 0); ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); Scope *ParentScope = getCurScope()->getParent(); D.setFunctionDefinitionKind(FDK_Definition); Decl *FuncDecl = Actions.HandleDeclarator(ParentScope, D, - move(TemplateParameterLists)); + MultiTemplateParamsArg()); D.complete(FuncDecl); D.getMutableDeclSpec().abort(); if (FuncDecl) { @@ -1033,10 +1057,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // specified Declarator for the function. Decl *Res = TemplateInfo.TemplateParams? Actions.ActOnStartOfFunctionTemplateDef(getCurScope(), - MultiTemplateParamsArg(Actions, - TemplateInfo.TemplateParams->data(), - TemplateInfo.TemplateParams->size()), - D) + *TemplateInfo.TemplateParams, D) : Actions.ActOnStartOfFunctionDef(getCurScope(), D); // Break out of the ParsingDeclarator context before we parse the body. @@ -1288,7 +1309,7 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { *EndLoc = T.getCloseLocation(); } - return move(Result); + return Result; } /// \brief Get the TemplateIdAnnotation from the token and put it in the @@ -1301,6 +1322,143 @@ TemplateIdAnnotation *Parser::takeTemplateIdAnnotation(const Token &tok) { return Id; } +void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) { + // Push the current token back into the token stream (or revert it if it is + // cached) and use an annotation scope token for current token. + if (PP.isBacktrackEnabled()) + PP.RevertCachedTokens(1); + else + PP.EnterToken(Tok); + Tok.setKind(tok::annot_cxxscope); + Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS)); + Tok.setAnnotationRange(SS.getRange()); + + // In case the tokens were cached, have Preprocessor replace them + // with the annotation token. We don't need to do this if we've + // just reverted back to a prior state. + if (IsNewAnnotation) + PP.AnnotateCachedTokens(Tok); +} + +/// \brief Attempt to classify the name at the current token position. This may +/// form a type, scope or primary expression annotation, or replace the token +/// with a typo-corrected keyword. This is only appropriate when the current +/// name must refer to an entity which has already been declared. +/// +/// \param IsAddressOfOperand Must be \c true if the name is preceded by an '&' +/// and might possibly have a dependent nested name specifier. +/// \param CCC Indicates how to perform typo-correction for this name. If NULL, +/// no typo correction will be performed. +Parser::AnnotatedNameKind +Parser::TryAnnotateName(bool IsAddressOfOperand, + CorrectionCandidateCallback *CCC) { + assert(Tok.is(tok::identifier) || Tok.is(tok::annot_cxxscope)); + + const bool EnteringContext = false; + const bool WasScopeAnnotation = Tok.is(tok::annot_cxxscope); + + CXXScopeSpec SS; + if (getLangOpts().CPlusPlus && + ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext)) + return ANK_Error; + + if (Tok.isNot(tok::identifier) || SS.isInvalid()) { + if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, false, SS, + !WasScopeAnnotation)) + return ANK_Error; + return ANK_Unresolved; + } + + IdentifierInfo *Name = Tok.getIdentifierInfo(); + SourceLocation NameLoc = Tok.getLocation(); + + // FIXME: Move the tentative declaration logic into ClassifyName so we can + // typo-correct to tentatively-declared identifiers. + if (isTentativelyDeclared(Name)) { + // Identifier has been tentatively declared, and thus cannot be resolved as + // an expression. Fall back to annotating it as a type. + if (TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, false, SS, + !WasScopeAnnotation)) + return ANK_Error; + return Tok.is(tok::annot_typename) ? ANK_Success : ANK_TentativeDecl; + } + + Token Next = NextToken(); + + // 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). + Sema::NameClassification Classification + = Actions.ClassifyName(getCurScope(), SS, Name, NameLoc, Next, + IsAddressOfOperand, SS.isEmpty() ? CCC : 0); + + switch (Classification.getKind()) { + case Sema::NC_Error: + return ANK_Error; + + case Sema::NC_Keyword: + // The identifier was typo-corrected to a keyword. + Tok.setIdentifierInfo(Name); + Tok.setKind(Name->getTokenID()); + PP.TypoCorrectToken(Tok); + if (SS.isNotEmpty()) + AnnotateScopeToken(SS, !WasScopeAnnotation); + // We've "annotated" this as a keyword. + return ANK_Success; + + case Sema::NC_Unknown: + // It's not something we know about. Leave it unannotated. + break; + + case Sema::NC_Type: + Tok.setKind(tok::annot_typename); + setTypeAnnotation(Tok, Classification.getType()); + Tok.setAnnotationEndLoc(NameLoc); + if (SS.isNotEmpty()) + Tok.setLocation(SS.getBeginLoc()); + PP.AnnotateCachedTokens(Tok); + return ANK_Success; + + case Sema::NC_Expression: + Tok.setKind(tok::annot_primary_expr); + setExprAnnotation(Tok, Classification.getExpression()); + Tok.setAnnotationEndLoc(NameLoc); + if (SS.isNotEmpty()) + Tok.setLocation(SS.getBeginLoc()); + PP.AnnotateCachedTokens(Tok); + return ANK_Success; + + case Sema::NC_TypeTemplate: + if (Next.isNot(tok::less)) { + // This may be a type template being used as a template template argument. + if (SS.isNotEmpty()) + AnnotateScopeToken(SS, !WasScopeAnnotation); + return ANK_TemplateName; + } + // Fall through. + case Sema::NC_FunctionTemplate: { + // We have a type or function template followed by '<'. + ConsumeToken(); + UnqualifiedId Id; + Id.setIdentifier(Name, NameLoc); + if (AnnotateTemplateIdToken( + TemplateTy::make(Classification.getTemplateName()), + Classification.getTemplateNameKind(), SS, SourceLocation(), Id)) + return ANK_Error; + return ANK_Success; + } + + case Sema::NC_NestedNameSpecifier: + llvm_unreachable("already parsed nested name specifier"); + } + + // Unable to classify the name, but maybe we can annotate a scope specifier. + if (SS.isNotEmpty()) + AnnotateScopeToken(SS, !WasScopeAnnotation); + return ANK_Unresolved; +} + /// 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 @@ -1377,8 +1535,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { return true; } - ASTTemplateArgsPtr TemplateArgsPtr(Actions, - TemplateId->getTemplateArgs(), + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), TemplateId->NumArgs); Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, @@ -1404,13 +1561,24 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { } // Remembers whether the token was originally a scope annotation. - bool wasScopeAnnotation = Tok.is(tok::annot_cxxscope); + bool WasScopeAnnotation = Tok.is(tok::annot_cxxscope); CXXScopeSpec SS; if (getLangOpts().CPlusPlus) if (ParseOptionalCXXScopeSpecifier(SS, ParsedType(), EnteringContext)) return true; + return TryAnnotateTypeOrScopeTokenAfterScopeSpec(EnteringContext, NeedType, + SS, !WasScopeAnnotation); +} + +/// \brief Try to annotate a type or scope token, having already parsed an +/// optional scope specifier. \p IsNewScope should be \c true unless the scope +/// specifier was extracted from an existing tok::annot_cxxscope annotation. +bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(bool EnteringContext, + bool NeedType, + CXXScopeSpec &SS, + bool IsNewScope) { if (Tok.is(tok::identifier)) { IdentifierInfo *CorrectedII = 0; // Determine whether the identifier is a type name. @@ -1492,21 +1660,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { return false; // A C++ scope specifier that isn't followed by a typename. - // Push the current token back into the token stream (or revert it if it is - // cached) and use an annotation scope token for current token. - if (PP.isBacktrackEnabled()) - PP.RevertCachedTokens(1); - else - PP.EnterToken(Tok); - Tok.setKind(tok::annot_cxxscope); - Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS)); - Tok.setAnnotationRange(SS.getRange()); - - // In case the tokens were cached, have Preprocessor replace them - // with the annotation token. We don't need to do this if we've - // just reverted back to the state we were in before being called. - if (!wasScopeAnnotation) - PP.AnnotateCachedTokens(Tok); + AnnotateScopeToken(SS, IsNewScope); return false; } @@ -1529,19 +1683,7 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { if (SS.isEmpty()) return false; - // Push the current token back into the token stream (or revert it if it is - // cached) and use an annotation scope token for current token. - if (PP.isBacktrackEnabled()) - PP.RevertCachedTokens(1); - else - PP.EnterToken(Tok); - Tok.setKind(tok::annot_cxxscope); - Tok.setAnnotationValue(Actions.SaveNestedNameSpecifierAnnotation(SS)); - Tok.setAnnotationRange(SS.getRange()); - - // In case the tokens were cached, have Preprocessor replace them with the - // annotation token. - PP.AnnotateCachedTokens(Tok); + AnnotateScopeToken(SS, true); return false; } @@ -1798,8 +1940,8 @@ bool BalancedDelimiterTracker::diagnoseMissingClose() { } P.Diag(P.Tok, DID); P.Diag(LOpen, diag::note_matching) << LHSName; - if (P.SkipUntil(Close)) - LClose = P.Tok.getLocation(); + if (P.SkipUntil(Close, /*StopAtSemi*/ true, /*DontConsume*/ true)) + LClose = P.ConsumeAnyToken(); return true; } |