diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Parse/Parser.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Parse/Parser.cpp | 208 |
1 files changed, 156 insertions, 52 deletions
diff --git a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp index 44bd0fb..a50763a 100644 --- a/contrib/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/contrib/llvm/tools/clang/lib/Parse/Parser.cpp @@ -23,8 +23,8 @@ using namespace clang; Parser::Parser(Preprocessor &pp, Sema &actions) : CrashInfo(*this), PP(pp), Actions(actions), Diags(PP.getDiagnostics()), - GreaterThanIsOperator(true), ColonIsSacred(false), - TemplateParameterDepth(0) { + GreaterThanIsOperator(true), ColonIsSacred(false), + InMessageExpression(false), TemplateParameterDepth(0) { Tok.setKind(tok::eof); Actions.CurScope = 0; NumCachedScopes = 0; @@ -50,6 +50,17 @@ Parser::Parser(Preprocessor &pp, Sema &actions) WeakHandler.reset(new PragmaWeakHandler(actions)); PP.AddPragmaHandler(WeakHandler.get()); + + FPContractHandler.reset(new PragmaFPContractHandler(actions, *this)); + PP.AddPragmaHandler("STDC", FPContractHandler.get()); + + if (getLang().OpenCL) { + OpenCLExtensionHandler.reset( + new PragmaOpenCLExtensionHandler(actions, *this)); + PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get()); + + PP.AddPragmaHandler("OPENCL", FPContractHandler.get()); + } PP.setCodeCompletionHandler(*this); } @@ -78,7 +89,7 @@ void PrettyStackTraceParserEntry::print(llvm::raw_ostream &OS) const { DiagnosticBuilder Parser::Diag(SourceLocation Loc, unsigned DiagID) { - return Diags.Report(FullSourceLoc(Loc, PP.getSourceManager()), DiagID); + return Diags.Report(Loc, DiagID); } DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) { @@ -126,6 +137,8 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok, case tok::r_brace : LHSName = "{"; DID = diag::err_expected_rbrace; break; case tok::r_square: LHSName = "["; DID = diag::err_expected_rsquare; break; case tok::greater: LHSName = "<"; DID = diag::err_expected_greater; break; + case tok::greatergreatergreater: + LHSName = "<<<"; DID = diag::err_expected_ggg; break; } Diag(Tok, DID); Diag(LHSLoc, diag::note_matching) << LHSName; @@ -133,6 +146,13 @@ SourceLocation Parser::MatchRHSPunctuation(tok::TokenKind RHSTok, return R; } +static bool IsCommonTypo(tok::TokenKind ExpectedTok, const Token &Tok) { + switch (ExpectedTok) { + case tok::semi: return Tok.is(tok::colon); // : for ; + default: return false; + } +} + /// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the /// input. If so, it is consumed and false is returned. /// @@ -146,6 +166,19 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, return false; } + // 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(); + + // Pretend there wasn't a problem. + return false; + } + const char *Spelling = 0; SourceLocation EndLoc = PP.getLocForEndOfToken(PrevTokLocation); if (EndLoc.isValid() && @@ -162,6 +195,25 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, return true; } +bool Parser::ExpectAndConsumeSemi(unsigned DiagID) { + if (Tok.is(tok::semi) || Tok.is(tok::code_completion)) { + ConsumeAnyToken(); + return false; + } + + if ((Tok.is(tok::r_paren) || Tok.is(tok::r_square)) && + NextToken().is(tok::semi)) { + Diag(Tok, diag::err_extraneous_token_before_semi) + << PP.getSpelling(Tok) + << FixItHint::CreateRemoval(Tok.getLocation()); + ConsumeAnyToken(); // The ')' or ']'. + ConsumeToken(); // The ';'. + return false; + } + + return ExpectAndConsume(tok::semi, DiagID); +} + //===----------------------------------------------------------------------===// // Error recovery. //===----------------------------------------------------------------------===// @@ -175,7 +227,8 @@ bool Parser::ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned DiagID, /// If SkipUntil finds the specified token, it returns true, otherwise it /// returns false. bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks, - bool StopAtSemi, bool DontConsume) { + bool StopAtSemi, bool DontConsume, + bool StopAtCodeCompletion) { // 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; @@ -198,23 +251,24 @@ bool Parser::SkipUntil(const tok::TokenKind *Toks, unsigned NumToks, return false; case tok::code_completion: - ConsumeToken(); + if (!StopAtCodeCompletion) + ConsumeToken(); return false; case tok::l_paren: // Recursively skip properly-nested parens. ConsumeParen(); - SkipUntil(tok::r_paren, false); + SkipUntil(tok::r_paren, false, false, StopAtCodeCompletion); break; case tok::l_square: // Recursively skip properly-nested square brackets. ConsumeBracket(); - SkipUntil(tok::r_square, false); + SkipUntil(tok::r_square, false, false, StopAtCodeCompletion); break; case tok::l_brace: // Recursively skip properly-nested braces. ConsumeBrace(); - SkipUntil(tok::r_brace, false); + SkipUntil(tok::r_brace, false, false, StopAtCodeCompletion); break; // Okay, we found a ']' or '}' or ')', which we think should be balanced. @@ -266,9 +320,8 @@ void Parser::EnterScope(unsigned ScopeFlags) { N->Init(getCurScope(), ScopeFlags); Actions.CurScope = N; } else { - Actions.CurScope = new Scope(getCurScope(), ScopeFlags); + Actions.CurScope = new Scope(getCurScope(), ScopeFlags, Diags); } - getCurScope()->setNumErrorsAtStart(Diags.getNumErrors()); } /// ExitScope - Pop a scope off the scope stack. @@ -318,6 +371,15 @@ Parser::~Parser() { UnusedHandler.reset(); PP.RemovePragmaHandler(WeakHandler.get()); WeakHandler.reset(); + + if (getLang().OpenCL) { + PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get()); + OpenCLExtensionHandler.reset(); + PP.RemovePragmaHandler("OPENCL", FPContractHandler.get()); + } + + PP.RemovePragmaHandler("STDC", FPContractHandler.get()); + FPContractHandler.reset(); PP.clearCodeCompletionHandler(); } @@ -347,6 +409,9 @@ void Parser::Initialize() { ObjCTypeQuals[objc_byref] = &PP.getIdentifierTable().get("byref"); } + Ident_final = 0; + Ident_override = 0; + Ident_super = &PP.getIdentifierTable().get("super"); if (getLang().AltiVec) { @@ -358,16 +423,21 @@ void Parser::Initialize() { /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the /// action tells us to. This returns true if the EOF was encountered. bool Parser::ParseTopLevelDecl(DeclGroupPtrTy &Result) { + + while (Tok.is(tok::annot_pragma_unused)) + HandlePragmaUnused(); + Result = DeclGroupPtrTy(); if (Tok.is(tok::eof)) { Actions.ActOnEndOfTranslationUnit(); return true; } - CXX0XAttributeList Attr; - if (getLang().CPlusPlus0x && isCXX0XAttributeSpecifier()) - Attr = ParseCXX0XAttributes(); - Result = ParseExternalDeclaration(Attr); + ParsedAttributesWithRange attrs; + MaybeParseCXX0XAttributes(attrs); + MaybeParseMicrosoftAttributes(attrs); + + Result = ParseExternalDeclaration(attrs); return false; } @@ -408,8 +478,9 @@ void Parser::ParseTranslationUnit() { /// ';' /// /// [C++0x/GNU] 'extern' 'template' declaration -Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, - ParsingDeclSpec *DS) { +Parser::DeclGroupPtrTy +Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, + ParsingDeclSpec *DS) { ParenBraceBracketBalancer BalancerRAIIObj(*this); Decl *SingleDecl = 0; @@ -433,12 +504,10 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, // __extension__ silences extension warnings in the subexpression. ExtensionRAIIObject O(Diags); // Use RAII to do this. ConsumeToken(); - return ParseExternalDeclaration(Attr); + return ParseExternalDeclaration(attrs); } case tok::kw_asm: { - if (Attr.HasAttr) - Diag(Attr.Range.getBegin(), diag::err_attributes_not_allowed) - << Attr.Range; + ProhibitAttributes(attrs); ExprResult Result(ParseSimpleAsm()); @@ -470,7 +539,7 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, ObjCImpDecl? Sema::PCC_ObjCImplementation : Sema::PCC_Namespace); ConsumeCodeCompletionToken(); - return ParseExternalDeclaration(Attr); + return ParseExternalDeclaration(attrs); case tok::kw_using: case tok::kw_namespace: case tok::kw_typedef: @@ -480,14 +549,42 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, // A function definition cannot start with a these keywords. { SourceLocation DeclEnd; - return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr); + StmtVector Stmts(Actions); + return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); } + case tok::kw_static: + // Parse (then ignore) 'static' prior to a template instantiation. This is + // a GCC extension that we intentionally do not support. + if (getLang().CPlusPlus && NextToken().is(tok::kw_template)) { + Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) + << 0; + SourceLocation DeclEnd; + StmtVector Stmts(Actions); + return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); + } + goto dont_know; + case tok::kw_inline: - if (getLang().CPlusPlus && NextToken().is(tok::kw_namespace)) { + if (getLang().CPlusPlus) { + tok::TokenKind NextKind = NextToken().getKind(); + // Inline namespaces. Allowed as an extension even in C++03. - SourceLocation DeclEnd; - return ParseDeclaration(Declarator::FileContext, DeclEnd, Attr); + if (NextKind == tok::kw_namespace) { + SourceLocation DeclEnd; + StmtVector Stmts(Actions); + return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); + } + + // Parse (then ignore) 'inline' prior to a template instantiation. This is + // a GCC extension that we intentionally do not support. + if (NextKind == tok::kw_template) { + Diag(ConsumeToken(), diag::warn_static_inline_explicit_inst_ignored) + << 1; + SourceLocation DeclEnd; + StmtVector Stmts(Actions); + return ParseDeclaration(Stmts, Declarator::FileContext, DeclEnd, attrs); + } } goto dont_know; @@ -506,10 +603,12 @@ Parser::DeclGroupPtrTy Parser::ParseExternalDeclaration(CXX0XAttributeList Attr, default: dont_know: // We can't tell whether this is a function-definition or declaration yet. - if (DS) - return ParseDeclarationOrFunctionDefinition(*DS, Attr.AttrList); - else - return ParseDeclarationOrFunctionDefinition(Attr.AttrList); + if (DS) { + DS->takeAttributesFrom(attrs); + return ParseDeclarationOrFunctionDefinition(*DS); + } else { + return ParseDeclarationOrFunctionDefinition(attrs); + } } // This routine returns a DeclGroup, if the thing we parsed only contains a @@ -532,14 +631,13 @@ bool Parser::isDeclarationAfterDeclarator() const { /// \brief Determine whether the current token, if it occurs after a /// declarator, indicates the start of a function definition. bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { - assert(Declarator.getTypeObject(0).Kind == DeclaratorChunk::Function && - "Isn't a function declarator"); + assert(Declarator.isFunctionDeclarator() && "Isn't a function declarator"); if (Tok.is(tok::l_brace)) // int X() {} return true; // Handle K&R C argument lists: int X(f) int f; {} if (!getLang().CPlusPlus && - Declarator.getTypeObject(0).Fun.isKNRPrototype()) + Declarator.getFunctionTypeInfo().isKNRPrototype()) return isDeclarationSpecifier(); return Tok.is(tok::colon) || // X() : Base() {} (used for ctors) @@ -564,12 +662,8 @@ bool Parser::isStartOfFunctionDefinition(const ParsingDeclarator &Declarator) { /// Parser::DeclGroupPtrTy Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS, - AttributeList *Attr, AccessSpecifier AS) { // Parse the common declaration-specifiers piece. - if (Attr) - DS.AddAttributes(Attr); - ParseDeclarationSpecifiers(DS, ParsedTemplateInfo(), AS, DSC_top_level); // C99 6.7.2.3p6: Handle "struct-or-union identifier;", "enum { X };" @@ -622,10 +716,11 @@ Parser::ParseDeclarationOrFunctionDefinition(ParsingDeclSpec &DS, } Parser::DeclGroupPtrTy -Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr, +Parser::ParseDeclarationOrFunctionDefinition(ParsedAttributes &attrs, AccessSpecifier AS) { ParsingDeclSpec DS(*this); - return ParseDeclarationOrFunctionDefinition(DS, Attr, AS); + DS.takeAttributesFrom(attrs); + return ParseDeclarationOrFunctionDefinition(DS, AS); } /// ParseFunctionDefinition - We parsed and verified that the specified @@ -643,11 +738,8 @@ Parser::ParseDeclarationOrFunctionDefinition(AttributeList *Attr, /// decl-specifier-seq[opt] declarator function-try-block /// Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo) { - const DeclaratorChunk &FnTypeInfo = D.getTypeObject(0); - assert(FnTypeInfo.Kind == DeclaratorChunk::Function && - "This isn't a function declarator!"); - const DeclaratorChunk::FunctionTypeInfo &FTI = FnTypeInfo.Fun; + const ParsedTemplateInfo &TemplateInfo) { + const DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // If this is C90 and the declspecs were completely missing, fudge in an // implicit int. We do this here because this is the only place where @@ -669,8 +761,9 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // We should have either an opening brace or, in a C++ constructor, // we may have a colon. - if (Tok.isNot(tok::l_brace) && Tok.isNot(tok::colon) && - Tok.isNot(tok::kw_try)) { + if (Tok.isNot(tok::l_brace) && + (!getLang().CPlusPlus || + (Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try)))) { Diag(Tok, diag::err_expected_fn_body); // Skip over garbage, until we get to '{'. Don't eat the '{'. @@ -724,7 +817,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, /// types for a function with a K&R-style identifier list for arguments. void Parser::ParseKNRParamDeclarations(Declarator &D) { // We know that the top-level of this declarator is a function. - DeclaratorChunk::FunctionTypeInfo &FTI = D.getTypeObject(0).Fun; + DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo(); // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. @@ -770,11 +863,7 @@ void Parser::ParseKNRParamDeclarations(Declarator &D) { // Handle the full declarator list. while (1) { // If attributes are present, parse them. - if (Tok.is(tok::kw___attribute)) { - SourceLocation Loc; - AttributeList *AttrList = ParseGNUAttributes(&Loc); - ParmDeclarator.AddAttributes(AttrList, Loc); - } + MaybeParseGNUAttributes(ParmDeclarator); // Ask the actions module to compute the type for this declarator. Decl *Param = @@ -994,7 +1083,8 @@ bool Parser::TryAnnotateTypeOrScopeToken(bool EnteringContext) { // Determine whether the identifier is a type name. if (ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), - &SS)) { + &SS, false, + NextToken().is(tok::period))) { // This is a typename. Replace the current token in-place with an // annotation type token. Tok.setKind(tok::annot_typename); @@ -1115,6 +1205,20 @@ bool Parser::TryAnnotateCXXScopeToken(bool EnteringContext) { return false; } +bool Parser::isTokenEqualOrMistypedEqualEqual(unsigned DiagID) { + if (Tok.is(tok::equalequal)) { + // We have '==' in a context that we would expect a '='. + // The user probably made a typo, intending to type '='. Emit diagnostic, + // fixit hint to turn '==' -> '=' and continue as if the user typed '='. + Diag(Tok, DiagID) + << FixItHint::CreateReplacement(SourceRange(Tok.getLocation()), + getTokenSimpleSpelling(tok::equal)); + return true; + } + + return Tok.is(tok::equal); +} + void Parser::CodeCompletionRecovery() { for (Scope *S = getCurScope(); S; S = S->getParent()) { if (S->getFlags() & Scope::FnScope) { |