diff options
Diffstat (limited to 'gnu/llvm/tools/clang/lib/Parse/Parser.cpp')
| -rw-r--r-- | gnu/llvm/tools/clang/lib/Parse/Parser.cpp | 128 |
1 files changed, 67 insertions, 61 deletions
diff --git a/gnu/llvm/tools/clang/lib/Parse/Parser.cpp b/gnu/llvm/tools/clang/lib/Parse/Parser.cpp index a6f966eda1b..c3085654f52 100644 --- a/gnu/llvm/tools/clang/lib/Parse/Parser.cpp +++ b/gnu/llvm/tools/clang/lib/Parse/Parser.cpp @@ -20,11 +20,12 @@ #include "clang/Sema/DeclSpec.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/Scope.h" +#include "llvm/Support/Path.h" using namespace clang; namespace { -/// \brief A comment handler that passes comments found by the preprocessor +/// A comment handler that passes comments found by the preprocessor /// to the parser action. class ActionCommentHandler : public CommentHandler { Sema &S; @@ -40,7 +41,7 @@ public: } // end anonymous namespace IdentifierInfo *Parser::getSEHExceptKeyword() { - // __except is accepted as a (contextual) keyword + // __except is accepted as a (contextual) keyword if (!Ident__except && (getLangOpts().MicrosoftExt || getLangOpts().Borland)) Ident__except = PP.getIdentifierInfo("__except"); @@ -49,7 +50,7 @@ IdentifierInfo *Parser::getSEHExceptKeyword() { Parser::Parser(Preprocessor &pp, Sema &actions, bool skipFunctionBodies) : PP(pp), Actions(actions), Diags(PP.getDiagnostics()), - GreaterThanIsOperator(true), ColonIsSacred(false), + GreaterThanIsOperator(true), ColonIsSacred(false), InMessageExpression(false), TemplateParameterDepth(0), ParsingInObjCContainer(false) { SkipFunctionBodies = pp.isCodeCompletionEnabled() || skipFunctionBodies; @@ -77,7 +78,7 @@ DiagnosticBuilder Parser::Diag(const Token &Tok, unsigned DiagID) { return Diag(Tok.getLocation(), DiagID); } -/// \brief Emits a diagnostic suggesting parentheses surrounding a +/// Emits a diagnostic suggesting parentheses surrounding a /// given range. /// /// \param Loc The location where we'll emit the diagnostic. @@ -160,8 +161,8 @@ bool Parser::ExpectAndConsumeSemi(unsigned DiagID) { handleUnexpectedCodeCompletionToken(); return false; } - - if ((Tok.is(tok::r_paren) || Tok.is(tok::r_square)) && + + 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) @@ -170,7 +171,7 @@ bool Parser::ExpectAndConsumeSemi(unsigned DiagID) { ConsumeToken(); // The ';'. return false; } - + return ExpectAndConsume(tok::semi, DiagID); } @@ -290,7 +291,7 @@ bool Parser::SkipUntil(ArrayRef<tok::TokenKind> Toks, SkipUntilFlags Flags) { if (!HasFlagsSet(Flags, StopAtCodeCompletion)) handleUnexpectedCodeCompletionToken(); return false; - + case tok::l_paren: // Recursively skip properly-nested parens. ConsumeParen(); @@ -697,9 +698,8 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, return nullptr; case tok::semi: // Either a C++11 empty-declaration or attribute-declaration. - SingleDecl = Actions.ActOnEmptyDeclaration(getCurScope(), - attrs.getList(), - Tok.getLocation()); + SingleDecl = + Actions.ActOnEmptyDeclaration(getCurScope(), attrs, Tok.getLocation()); ConsumeExtraSemi(OutsideFunction); break; case tok::r_brace: @@ -741,7 +741,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, break; } case tok::at: - return ParseObjCAtDirectives(); + return ParseObjCAtDirectives(attrs); case tok::minus: case tok::plus: if (!getLangOpts().ObjC1) { @@ -796,17 +796,17 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, return ParseDeclaration(DeclaratorContext::FileContext, DeclEnd, attrs); } goto dont_know; - + case tok::kw_inline: if (getLangOpts().CPlusPlus) { tok::TokenKind NextKind = NextToken().getKind(); - + // Inline namespaces. Allowed as an extension even in C++03. if (NextKind == tok::kw_namespace) { SourceLocation DeclEnd; return ParseDeclaration(DeclaratorContext::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) { @@ -828,8 +828,8 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, diag::ext_extern_template) << SourceRange(ExternLoc, TemplateLoc); SourceLocation DeclEnd; return Actions.ConvertDeclToDeclGroup( - ParseExplicitInstantiation(DeclaratorContext::FileContext, - ExternLoc, TemplateLoc, DeclEnd)); + ParseExplicitInstantiation(DeclaratorContext::FileContext, ExternLoc, + TemplateLoc, DeclEnd, attrs)); } goto dont_know; @@ -858,7 +858,7 @@ Parser::ParseExternalDeclaration(ParsedAttributesWithRange &attrs, return Actions.ConvertDeclToDeclGroup(SingleDecl); } -/// \brief Determine whether the current token, if it occurs after a +/// Determine whether the current token, if it occurs after a /// declarator, continues a declaration or declaration list. bool Parser::isDeclarationAfterDeclarator() { // Check for '= delete' or '= default' @@ -867,7 +867,7 @@ bool Parser::isDeclarationAfterDeclarator() { if (KW.is(tok::kw_default) || KW.is(tok::kw_delete)) return false; } - + return Tok.is(tok::equal) || // int X()= -> not a function def Tok.is(tok::comma) || // int X(), -> not a function def Tok.is(tok::semi) || // int X(); -> not a function def @@ -877,23 +877,23 @@ bool Parser::isDeclarationAfterDeclarator() { Tok.is(tok::l_paren)); // int X(0) -> not a function def [C++] } -/// \brief Determine whether the current token, if it occurs after a +/// 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.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 (!getLangOpts().CPlusPlus && - Declarator.getFunctionTypeInfo().isKNRPrototype()) + Declarator.getFunctionTypeInfo().isKNRPrototype()) return isDeclarationSpecifier(); if (getLangOpts().CPlusPlus && Tok.is(tok::equal)) { const Token &KW = NextToken(); return KW.is(tok::kw_default) || KW.is(tok::kw_delete); } - + return Tok.is(tok::colon) || // X() : Base() {} (used for ctors) Tok.is(tok::kw_try); // X() try { ... } } @@ -947,7 +947,7 @@ Parser::ParseDeclOrFunctionDefInternal(ParsedAttributesWithRange &attrs, default: llvm_unreachable("we only expect to get the length of the class/struct/union/enum"); } - + }; // Suggest correct location to fix '[[attrib]] struct' to 'struct [[attrib]]' SourceLocation CorrectLocationForAttributes = @@ -1072,7 +1072,7 @@ 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) && + if (Tok.isNot(tok::l_brace) && (!getLangOpts().CPlusPlus || (Tok.isNot(tok::colon) && Tok.isNot(tok::kw_try) && Tok.isNot(tok::equal)))) { @@ -1089,15 +1089,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Check to make sure that any normal attributes are allowed to be on // a definition. Late parsed attributes are checked at the end. if (Tok.isNot(tok::equal)) { - AttributeList *DtorAttrs = D.getAttributes(); - while (DtorAttrs) { - if (DtorAttrs->isKnownToGCC() && - !DtorAttrs->isCXX11Attribute()) { - Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition) - << DtorAttrs->getName(); - } - DtorAttrs = DtorAttrs->getNext(); - } + for (const ParsedAttr &AL : D.getAttributes()) + if (AL.isKnownToGCC() && !AL.isCXX11Attribute()) + Diag(AL.getLoc(), diag::warn_attribute_on_function_definition) + << AL.getName(); } // In delayed template parsing mode, for function template we consume the @@ -1133,10 +1128,10 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, } return DP; } - else if (CurParsedObjCImpl && + else if (CurParsedObjCImpl && !TemplateInfo.TemplateParams && (Tok.is(tok::l_brace) || Tok.is(tok::kw_try) || - Tok.is(tok::colon)) && + Tok.is(tok::colon)) && Actions.CurContext->isTranslationUnit()) { ParseScope BodyScope(this, Scope::FnScope | Scope::DeclScope | Scope::CompoundStmtScope); @@ -1176,7 +1171,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D, // Break out of the ParsingDeclarator context before we parse the body. D.complete(Res); - + // Break out of the ParsingDeclSpec context, too. This const_cast is // safe because we're always the sole owner. D.getMutableDeclSpec().abort(); @@ -1451,7 +1446,7 @@ ExprResult Parser::ParseSimpleAsm(SourceLocation *EndLoc) { return Result; } -/// \brief Get the TemplateIdAnnotation from the token and put it in the +/// Get the TemplateIdAnnotation from the token and put it in the /// cleanup pool so that it gets destroyed when parsing the current top level /// declaration is finished. TemplateIdAnnotation *Parser::takeTemplateIdAnnotation(const Token &tok) { @@ -1479,7 +1474,7 @@ void Parser::AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation) { PP.AnnotateCachedTokens(Tok); } -/// \brief Attempt to classify the name at the current token position. This may +/// 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. @@ -1715,7 +1710,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { TypeResult Ty; if (Tok.is(tok::identifier)) { // FIXME: check whether the next token is '<', first! - Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, + Ty = Actions.ActOnTypenameType(getCurScope(), TypenameLoc, SS, *Tok.getIdentifierInfo(), Tok.getLocation()); } else if (Tok.is(tok::annot_template_id)) { @@ -1764,7 +1759,7 @@ bool Parser::TryAnnotateTypeOrScopeToken() { return TryAnnotateTypeOrScopeTokenAfterScopeSpec(SS, !WasScopeAnnotation); } -/// \brief Try to annotate a type or scope token, having already parsed an +/// 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(CXXScopeSpec &SS, @@ -1775,8 +1770,8 @@ bool Parser::TryAnnotateTypeOrScopeTokenAfterScopeSpec(CXXScopeSpec &SS, *Tok.getIdentifierInfo(), Tok.getLocation(), getCurScope(), &SS, false, NextToken().is(tok::period), nullptr, /*IsCtorOrDtorName=*/false, - /*NonTrivialTypeSourceInfo*/ true, - /*IsClassTemplateDeductionContext*/GreaterThanIsOperator)) { + /*NonTrivialTypeSourceInfo*/true, + /*IsClassTemplateDeductionContext*/true)) { SourceLocation BeginLoc = Tok.getLocation(); if (SS.isNotEmpty()) // it was a C++ qualified type name. BeginLoc = SS.getBeginLoc(); @@ -1931,14 +1926,14 @@ SourceLocation Parser::handleUnexpectedCodeCompletionToken() { cutOffParsing(); return PrevTokLocation; } - + if (S->getFlags() & Scope::ClassScope) { Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Class); cutOffParsing(); return PrevTokLocation; } } - + Actions.CodeCompleteOrdinaryName(getCurScope(), Sema::PCC_Namespace); cutOffParsing(); return PrevTokLocation; @@ -1958,7 +1953,7 @@ void Parser::CodeCompleteMacroName(bool IsDefinition) { Actions.CodeCompletePreprocessorMacroName(IsDefinition); } -void Parser::CodeCompletePreprocessorExpression() { +void Parser::CodeCompletePreprocessorExpression() { Actions.CodeCompletePreprocessorExpression(); } @@ -1981,11 +1976,11 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) { BalancedDelimiterTracker T(*this, tok::l_paren); if (T.consumeOpen()) { - Diag(Tok, diag::err_expected_lparen_after) + Diag(Tok, diag::err_expected_lparen_after) << (Result.IsIfExists? "__if_exists" : "__if_not_exists"); return true; } - + // Parse nested-name-specifier. if (getLangOpts().CPlusPlus) ParseOptionalCXXScopeSpecifier(Result.SS, nullptr, @@ -2002,14 +1997,14 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) { if (ParseUnqualifiedId( Result.SS, /*EnteringContext*/false, /*AllowDestructorName*/true, /*AllowConstructorName*/true, /*AllowDeductionGuide*/false, nullptr, - TemplateKWLoc, Result.Name)) { + &TemplateKWLoc, Result.Name)) { T.skipToEnd(); return true; } if (T.consumeClose()) return true; - + // Check if the symbol exists. switch (Actions.CheckMicrosoftIfExistsSymbol(getCurScope(), Result.KeywordLoc, Result.IsIfExists, Result.SS, @@ -2025,7 +2020,7 @@ bool Parser::ParseMicrosoftIfExistsCondition(IfExistsCondition& Result) { case Sema::IER_Dependent: Result.Behavior = IEB_Dependent; break; - + case Sema::IER_Error: return true; } @@ -2037,7 +2032,7 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { IfExistsCondition Result; if (ParseMicrosoftIfExistsCondition(Result)) return; - + BalancedDelimiterTracker Braces(*this, tok::l_brace); if (Braces.consumeOpen()) { Diag(Tok, diag::err_expected) << tok::l_brace; @@ -2048,10 +2043,10 @@ void Parser::ParseMicrosoftIfExistsExternalDeclaration() { case IEB_Parse: // Parse declarations below. break; - + case IEB_Dependent: llvm_unreachable("Cannot have a dependent external declaration"); - + case IEB_Skip: Braces.skipToEnd(); return; @@ -2114,7 +2109,7 @@ Parser::DeclGroupPtrTy Parser::ParseModuleDecl() { /// Parse a module import declaration. This is essentially the same for /// Objective-C and the C++ Modules TS, except for the leading '@' (in ObjC) /// and the trailing optional attributes (in C++). -/// +/// /// [ObjC] @import declaration: /// '@' 'import' module-name ';' /// [ModTS] module-import-declaration: @@ -2123,9 +2118,10 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc) { assert((AtLoc.isInvalid() ? Tok.is(tok::kw_import) : Tok.isObjCAtKeyword(tok::objc_import)) && "Improper start to module import"); + bool IsObjCAtImport = Tok.isObjCAtKeyword(tok::objc_import); SourceLocation ImportLoc = ConsumeToken(); SourceLocation StartLoc = AtLoc.isInvalid() ? ImportLoc : AtLoc; - + SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> Path; if (ParseModuleName(ImportLoc, Path, /*IsImport*/true)) return nullptr; @@ -2146,6 +2142,16 @@ Decl *Parser::ParseModuleImport(SourceLocation AtLoc) { if (Import.isInvalid()) return nullptr; + // Using '@import' in framework headers requires modules to be enabled so that + // the header is parseable. Emit a warning to make the user aware. + if (IsObjCAtImport && AtLoc.isValid()) { + auto &SrcMgr = PP.getSourceManager(); + auto *FE = SrcMgr.getFileEntryForID(SrcMgr.getFileID(AtLoc)); + if (FE && llvm::sys::path::parent_path(FE->getDir()->getName()) + .endswith(".framework")) + Diags.Report(AtLoc, diag::warn_atimport_in_framework_header); + } + return Import.get(); } @@ -2168,12 +2174,12 @@ bool Parser::ParseModuleName( cutOffParsing(); return true; } - + Diag(Tok, diag::err_module_expected_ident) << IsImport; SkipUntil(tok::semi); return true; } - + // Record this part of the module path. Path.push_back(std::make_pair(Tok.getIdentifierInfo(), Tok.getLocation())); ConsumeToken(); @@ -2185,7 +2191,7 @@ bool Parser::ParseModuleName( } } -/// \brief Try recover parser when module annotation appears where it must not +/// 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. @@ -2250,9 +2256,9 @@ bool BalancedDelimiterTracker::expectAndConsume(unsigned DiagID, return true; } - if (getDepth() < MaxDepth) + if (getDepth() < P.getLangOpts().BracketDepth) return false; - + return diagnoseOverflow(); } |
