diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/Parser.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/Parser.cpp | 184 |
1 files changed, 143 insertions, 41 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 455139b..457dd36 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -103,8 +103,10 @@ Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) PP.AddPragmaHandler(OpenMPHandler.get()); if (getLangOpts().MicrosoftExt) { - MSCommentHandler.reset(new PragmaCommentHandler()); + MSCommentHandler.reset(new PragmaCommentHandler(actions)); PP.AddPragmaHandler(MSCommentHandler.get()); + MSDetectMismatchHandler.reset(new PragmaDetectMismatchHandler(actions)); + PP.AddPragmaHandler(MSDetectMismatchHandler.get()); } CommentSemaHandler.reset(new ActionCommentHandler(actions)); @@ -188,7 +190,7 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, Diag(Tok, DiagID) << Msg; if (SkipToTok != tok::unknown) - SkipUntil(SkipToTok); + SkipUntil(SkipToTok, StopAtSemi); return true; } @@ -251,16 +253,19 @@ void Parser::ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST) { // Error recovery. //===----------------------------------------------------------------------===// +static bool HasFlagsSet(Parser::SkipUntilFlags L, Parser::SkipUntilFlags R) { + return (static_cast<unsigned>(L) & static_cast<unsigned>(R)) != 0; +} + /// SkipUntil - Read tokens until we get to the specified token, then consume -/// it (unless DontConsume is true). Because we cannot guarantee that the +/// it (unless no flag StopBeforeMatch). Because we cannot guarantee that the /// token will ever occur, this skips to the next token, or to some likely /// good stopping point. If StopAtSemi is true, skipping will stop at a ';' /// character. /// /// If SkipUntil finds the specified token, it returns true, otherwise it /// returns false. -bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, bool StopAtSemi, - bool DontConsume, bool StopAtCodeCompletion) { +bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) { // We always want this function to skip at least one token if the first token // isn't T and if not at EOF. bool isFirstTokenSkipped = true; @@ -268,7 +273,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, bool StopAtSemi, // If we found one of the tokens, stop and return true. for (unsigned i = 0, NumToks = Toks.size(); i != NumToks; ++i) { if (Tok.is(Toks[i])) { - if (DontConsume) { + if (HasFlagsSet(Flags, StopBeforeMatch)) { // Noop, don't consume the token. } else { ConsumeAnyToken(); @@ -277,30 +282,50 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, bool StopAtSemi, } } + // Important special case: The caller has given up and just wants us to + // skip the rest of the file. Do this without recursing, since we can + // get here precisely because the caller detected too much recursion. + if (Toks.size() == 1 && Toks[0] == tok::eof && + !HasFlagsSet(Flags, StopAtSemi) && + !HasFlagsSet(Flags, StopAtCodeCompletion)) { + while (Tok.getKind() != tok::eof) + ConsumeAnyToken(); + return true; + } + switch (Tok.getKind()) { case tok::eof: // Ran out of tokens. return false; case tok::code_completion: - if (!StopAtCodeCompletion) + if (!HasFlagsSet(Flags, StopAtCodeCompletion)) ConsumeToken(); return false; case tok::l_paren: // Recursively skip properly-nested parens. ConsumeParen(); - SkipUntil(tok::r_paren, false, false, StopAtCodeCompletion); + if (HasFlagsSet(Flags, StopAtCodeCompletion)) + SkipUntil(tok::r_paren, StopAtCodeCompletion); + else + SkipUntil(tok::r_paren); break; case tok::l_square: // Recursively skip properly-nested square brackets. ConsumeBracket(); - SkipUntil(tok::r_square, false, false, StopAtCodeCompletion); + if (HasFlagsSet(Flags, StopAtCodeCompletion)) + SkipUntil(tok::r_square, StopAtCodeCompletion); + else + SkipUntil(tok::r_square); break; case tok::l_brace: // Recursively skip properly-nested braces. ConsumeBrace(); - SkipUntil(tok::r_brace, false, false, StopAtCodeCompletion); + if (HasFlagsSet(Flags, StopAtCodeCompletion)) + SkipUntil(tok::r_brace, StopAtCodeCompletion); + else + SkipUntil(tok::r_brace); break; // Okay, we found a ']' or '}' or ')', which we think should be balanced. @@ -333,7 +358,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, bool StopAtSemi, break; case tok::semi: - if (StopAtSemi) + if (HasFlagsSet(Flags, StopAtSemi)) return false; // FALL THROUGH. default: @@ -410,11 +435,6 @@ Parser::~Parser() { for (unsigned i = 0, e = NumCachedScopes; i != e; ++i) delete ScopeCache[i]; - // Free LateParsedTemplatedFunction nodes. - for (LateParsedTemplateMapT::iterator it = LateParsedTemplateMap.begin(); - it != LateParsedTemplateMap.end(); ++it) - delete it->second; - // Remove the pragma handlers we installed. PP.RemovePragmaHandler(AlignHandler.get()); AlignHandler.reset(); @@ -444,6 +464,8 @@ Parser::~Parser() { if (getLangOpts().MicrosoftExt) { PP.RemovePragmaHandler(MSCommentHandler.get()); MSCommentHandler.reset(); + PP.RemovePragmaHandler(MSDetectMismatchHandler.get()); + MSDetectMismatchHandler.reset(); } PP.RemovePragmaHandler("STDC", FPContractHandler.get()); @@ -477,6 +499,7 @@ void Parser::Initialize() { Ident_instancetype = 0; Ident_final = 0; + Ident_sealed = 0; Ident_override = 0; Ident_super = &PP.getIdentifierTable().get("super"); @@ -484,6 +507,7 @@ void Parser::Initialize() { if (getLangOpts().AltiVec) { Ident_vector = &PP.getIdentifierTable().get("vector"); Ident_pixel = &PP.getIdentifierTable().get("pixel"); + Ident_bool = &PP.getIdentifierTable().get("bool"); } Ident_introduced = 0; @@ -555,19 +579,30 @@ bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { if (PP.isIncrementalProcessingEnabled() && Tok.is(tok::eof)) ConsumeToken(); - while (Tok.is(tok::annot_pragma_unused)) + Result = DeclGroupPtrTy(); + switch (Tok.getKind()) { + case tok::annot_pragma_unused: HandlePragmaUnused(); + return false; - Result = DeclGroupPtrTy(); - if (Tok.is(tok::eof)) { + case tok::annot_module_include: + Actions.ActOnModuleInclude(Tok.getLocation(), + reinterpret_cast<Module *>( + Tok.getAnnotationValue())); + ConsumeToken(); + return false; + + case tok::eof: // Late template parsing can begin. if (getLangOpts().DelayedTemplateParsing) Actions.SetLateTemplateParser(LateTemplateParserCallback, this); if (!PP.isIncrementalProcessingEnabled()) Actions.ActOnEndOfTranslationUnit(); //else don't tell Sema that we ended parsing: more input might come. - return true; + + default: + break; } ParsedAttributesWithRange attrs(AttrFactory); @@ -840,6 +875,12 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, // Parse the common declaration-specifiers piece. ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level); + // If we had a free-standing type definition with a missing semicolon, we + // may get this far before the problem becomes obvious. + if (DS.hasTagDefinition() && + DiagnoseMissingSemiAfterTagDefinition(DS, AS, DSC_top_level)) + return DeclGroupPtrTy(); + // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" // declaration-specifiers init-declarator-list[opt] ';' if (Tok.is(tok::semi)) { @@ -908,6 +949,26 @@ 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. @@ -956,7 +1017,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, Diag(Tok, diag::err_expected_fn_body); // Skip over garbage, until we get to '{'. Don't eat the '{'. - SkipUntil(tok::l_brace, true, true); + SkipUntil(tok::l_brace, StopAtSemi | StopBeforeMatch); // If we didn't find the '{', bail out. if (Tok.isNot(tok::l_brace)) @@ -979,9 +1040,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // In delayed template parsing mode, for function template we consume the // 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) { + if (getLangOpts().DelayedTemplateParsing && Tok.isNot(tok::equal) && + TemplateInfo.Kind == ParsedTemplateInfo::Template && + !D.getDeclSpec().isConstexprSpecified() && + !isFunctionDeclaratorRequiringReturnTypeDeduction(D)) { MultiTemplateParamsArg TemplateParameterLists(*TemplateInfo.TemplateParams); ParseScope BodyScope(this, Scope::FnScope|Scope::DeclScope); @@ -993,22 +1055,18 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, D.complete(DP); D.getMutableDeclSpec().abort(); - if (DP) { - LateParsedTemplatedFunction *LPT = new LateParsedTemplatedFunction(DP); + CachedTokens Toks; + LexTemplateFunctionForLateParsing(Toks); + if (DP) { FunctionDecl *FnD = 0; if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(DP)) FnD = FunTmpl->getTemplatedDecl(); else FnD = cast<FunctionDecl>(DP); - Actions.CheckForFunctionRedefinition(FnD); - LateParsedTemplateMap[FnD] = LPT; - Actions.MarkAsLateParsedTemplate(FnD); - LexTemplateFunctionForLateParsing(LPT->Toks); - } else { - CachedTokens Toks; - LexTemplateFunctionForLateParsing(Toks); + Actions.CheckForFunctionRedefinition(FnD); + Actions.MarkAsLateParsedTemplate(FnD, DP, Toks); } return DP; } @@ -1215,7 +1273,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { if (ExpectAndConsumeSemi(diag::err_expected_semi_declaration)) { // Skip to end of block or statement - SkipUntil(tok::semi, true); + SkipUntil(tok::semi); if (Tok.is(tok::semi)) ConsumeToken(); } @@ -1283,7 +1341,7 @@ Parser::ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { ExprResult Result(ParseAsmStringLiteral()); if (Result.isInvalid()) { - SkipUntil(tok::r_paren, true, true); + SkipUntil(tok::r_paren, StopAtSemi | StopBeforeMatch); if (EndLoc) *EndLoc = Tok.getLocation(); ConsumeAnyToken(); @@ -1422,8 +1480,9 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, return ANK_TemplateName; } // Fall through. + case Sema::NC_VarTemplate: case Sema::NC_FunctionTemplate: { - // We have a type or function template followed by '<'. + // We have a type, variable or function template followed by '<'. ConsumeToken(); UnqualifiedId Id; Id.setIdentifier(Name, NameLoc); @@ -1444,6 +1503,17 @@ Parser::TryAnnotateName(bool IsAddressOfOperand, return ANK_Unresolved; } +bool Parser::TryKeywordIdentFallback(bool DisableKeyword) { + assert(Tok.isNot(tok::identifier)); + Diag(Tok, diag::ext_keyword_as_ident) + << PP.getSpelling(Tok) + << DisableKeyword; + if (DisableKeyword) + Tok.getIdentifierInfo()->RevertTokenIDToIdentifier(); + Tok.setKind(tok::identifier); + 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 @@ -1473,6 +1543,23 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { && "Cannot be a type or scope token!"); if (Tok.is(tok::kw_typename)) { + // MSVC lets you do stuff like: + // typename typedef T_::D D; + // + // 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)) { + Token TypedefToken; + PP.Lex(TypedefToken); + bool Result = TryAnnotateTypeOrScopeToken(EnteringContext, NeedType); + PP.EnterToken(Tok); + Tok = TypedefToken; + if (!Result) + Diag(Tok.getLocation(), diag::warn_expected_qualified_after_typename); + return Result; + } + // Parse a C++ typename-specifier, e.g., "typename T::type". // // typename-specifier: @@ -1491,7 +1578,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext, bool NeedType) { // Attempt to recover by skipping the invalid 'typename' if (Tok.is(tok::annot_decltype) || (!TryAnnotateTypeOrScopeToken(EnteringContext, NeedType) && - Tok.isAnnotation())) { + Tok.isAnnotation())) { unsigned DiagID = diag::err_expected_qualified_after_typename; // MS compatibility: MSVC permits using known types with typename. // e.g. "typedef typename T* pointer_type" @@ -1638,7 +1725,8 @@ 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()) @@ -1884,7 +1972,13 @@ Parser::DeclGroupPtrTy Parser::ParseModuleImport(SourceLocation AtLoc) { break; } while (true); - + + if (PP.hadModuleLoaderFatalFailure()) { + // With a fatal failure in the module loader, we abort parsing. + cutOffParsing(); + return DeclGroupPtrTy(); + } + DeclResult Import = Actions.ActOnModuleImport(AtLoc, ImportLoc, Path); ExpectAndConsumeSemi(diag::err_module_expected_semi); if (Import.isInvalid()) @@ -1927,11 +2021,19 @@ bool BalancedDelimiterTracker::diagnoseMissingClose() { } P.Diag(P.Tok, DID); P.Diag(LOpen, diag::note_matching) << LHSName; - if (P.SkipUntil(Close, /*StopAtSemi*/ true, /*DontConsume*/ true)) + + // If we're not already at some kind of closing bracket, skip to our closing + // token. + if (P.Tok.isNot(tok::r_paren) && P.Tok.isNot(tok::r_brace) && + P.Tok.isNot(tok::r_square) && + P.SkipUntil(Close, FinalToken, + Parser::StopAtSemi | Parser::StopBeforeMatch) && + P.Tok.is(Close)) LClose = P.ConsumeAnyToken(); return true; } void BalancedDelimiterTracker::skipToEnd() { - P.SkipUntil(Close, false); + P.SkipUntil(Close, Parser::StopBeforeMatch); + consumeClose(); } |