llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Vlad Serebrennikov (Endilll) <details> <summary>Changes</summary> Following the steps of #<!-- -->82217, this patch reorganizes declarations in `Parse.h`. Highlights are: 1) Declarations are grouped in the same fashion as in `Sema.h`. Table of contents is provided at the beginning of `Parser` class. `public` declaration go first, then `private` ones, but unlike `Sema`, most of the stuff in `Parser` is private. 2) Documentation has been moved from `.cpp` files to the header. Grammar was consistently put in `\verbatim` blocks to render nicely in Doxygen. 3) File has been formatted with clang-format, except for the grammar, because clang-format butchers it. --- Patch is 731.75 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138511.diff 16 Files Affected: - (modified) clang/include/clang/Parse/Parser.h (+7898-3021) - (modified) clang/lib/Parse/ParseCXXInlineMethods.cpp (-52) - (modified) clang/lib/Parse/ParseDecl.cpp (-566) - (modified) clang/lib/Parse/ParseDeclCXX.cpp (-419) - (modified) clang/lib/Parse/ParseExpr.cpp (-543) - (modified) clang/lib/Parse/ParseExprCXX.cpp (-526) - (modified) clang/lib/Parse/ParseInit.cpp (-61) - (modified) clang/lib/Parse/ParseObjc.cpp (-376) - (modified) clang/lib/Parse/ParseOpenACC.cpp (-57) - (modified) clang/lib/Parse/ParseOpenMP.cpp (-348) - (modified) clang/lib/Parse/ParsePragma.cpp (-10) - (modified) clang/lib/Parse/ParseStmt.cpp (-240) - (modified) clang/lib/Parse/ParseStmtAsm.cpp (-58) - (modified) clang/lib/Parse/ParseTemplate.cpp (-233) - (modified) clang/lib/Parse/ParseTentative.cpp (+1-395) - (modified) clang/lib/Parse/Parser.cpp (+2-203) ``````````diff diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index 00e4b980bf44a..ab6927130bc2b 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -29,28 +29,28 @@ #include <stack> namespace clang { - class PragmaHandler; - class Scope; - class BalancedDelimiterTracker; - class CorrectionCandidateCallback; - class DeclGroupRef; - class DiagnosticBuilder; - struct LoopHint; - class Parser; - class ParsingDeclRAIIObject; - class ParsingDeclSpec; - class ParsingDeclarator; - class ParsingFieldDeclarator; - class ColonProtectionRAIIObject; - class InMessageExpressionRAIIObject; - class PoisonSEHIdentifiersRAIIObject; - class OMPClause; - class OpenACCClause; - class ObjCTypeParamList; - struct OMPTraitProperty; - struct OMPTraitSelector; - struct OMPTraitSet; - class OMPTraitInfo; +class PragmaHandler; +class Scope; +class BalancedDelimiterTracker; +class CorrectionCandidateCallback; +class DeclGroupRef; +class DiagnosticBuilder; +struct LoopHint; +class Parser; +class ParsingDeclRAIIObject; +class ParsingDeclSpec; +class ParsingDeclarator; +class ParsingFieldDeclarator; +class ColonProtectionRAIIObject; +class InMessageExpressionRAIIObject; +class PoisonSEHIdentifiersRAIIObject; +class OMPClause; +class OpenACCClause; +class ObjCTypeParamList; +struct OMPTraitProperty; +struct OMPTraitSelector; +struct OMPTraitSet; +class OMPTraitInfo; enum class AnnotatedNameKind { /// Annotation has failed and emitted an error. @@ -153,571 +153,438 @@ enum class CXX11AttributeKind { /// parsing units of the grammar, productions are invoked to handle whatever has /// been read. /// +/// \nosubgrouping class Parser : public CodeCompletionHandler { + // Table of Contents + // ----------------- + // 1. Parsing (Parser.cpp) + // 2. C++ Class Inline Methods (ParseCXXInlineMethods.cpp) + // 3. Declarations (ParseDecl.cpp) + // 4. C++ Declarations (ParseDeclCXX.cpp) + // 5. Expressions (ParseExpr.cpp) + // 6. C++ Expressions (ParseExprCXX.cpp) + // 7. HLSL Constructs (ParseHLSL.cpp) + // 8. Initializers (ParseInit.cpp) + // 9. Objective-C Constructs (ParseObjc.cpp) + // 10. OpenACC Constructs (ParseOpenACC.cpp) + // 11. OpenMP Constructs (ParseOpenMP.cpp) + // 12. Pragmas (ParsePragma.cpp) + // 13. Statements (ParseStmt.cpp) + // 14. `inline asm` Statement (ParseStmtAsm.cpp) + // 15. C++ Templates (ParseTemplate.cpp) + // 16. Tentative Parsing (ParseTentative.cpp) + + /// \name Parsing + /// Implementations are in Parser.cpp + ///@{ + +public: friend class ColonProtectionRAIIObject; - friend class ParsingOpenMPDirectiveRAII; - friend class ParsingOpenACCDirectiveRAII; - friend class InMessageExpressionRAIIObject; - friend class OffsetOfStateRAIIObject; friend class PoisonSEHIdentifiersRAIIObject; - friend class ObjCDeclContextSwitch; friend class ParenBraceBracketBalancer; friend class BalancedDelimiterTracker; - Preprocessor &PP; + Parser(Preprocessor &PP, Sema &Actions, bool SkipFunctionBodies); + ~Parser() override; - /// Tok - The current token we are peeking ahead. All parsing methods assume - /// that this is valid. - Token Tok; + const LangOptions &getLangOpts() const { return PP.getLangOpts(); } + const TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); } + Preprocessor &getPreprocessor() const { return PP; } + Sema &getActions() const { return Actions; } + AttributeFactory &getAttrFactory() { return AttrFactory; } - // PrevTokLocation - The location of the token we previously - // consumed. This token is used for diagnostics where we expected to - // see a token following another token (e.g., the ';' at the end of - // a statement). - SourceLocation PrevTokLocation; + const Token &getCurToken() const { return Tok; } + Scope *getCurScope() const { return Actions.getCurScope(); } - /// Tracks an expected type for the current token when parsing an expression. - /// Used by code completion for ranking. - PreferredTypeBuilder PreferredType; + void incrementMSManglingNumber() const { + return Actions.incrementMSManglingNumber(); + } - unsigned short ParenCount = 0, BracketCount = 0, BraceCount = 0; - unsigned short MisplacedModuleBeginCount = 0; + // Type forwarding. All of these are statically 'void*', but they may all be + // different actual classes based on the actions in place. + typedef OpaquePtr<DeclGroupRef> DeclGroupPtrTy; + typedef OpaquePtr<TemplateName> TemplateTy; - /// Actions - These are the callbacks we invoke as we parse various constructs - /// in the file. - Sema &Actions; + /// Initialize - Warm up the parser. + /// + void Initialize(); - DiagnosticsEngine &Diags; + /// Parse the first top-level declaration in a translation unit. + /// + /// \verbatim + /// translation-unit: + /// [C] external-declaration + /// [C] translation-unit external-declaration + /// [C++] top-level-declaration-seq[opt] + /// [C++20] global-module-fragment[opt] module-declaration + /// top-level-declaration-seq[opt] private-module-fragment[opt] + /// \endverbatim + /// + /// Note that in C, it is an error if there is no first declaration. + bool ParseFirstTopLevelDecl(DeclGroupPtrTy &Result, + Sema::ModuleImportState &ImportState); - StackExhaustionHandler StackHandler; + /// ParseTopLevelDecl - Parse one top-level declaration, return whatever the + /// action tells us to. This returns true if the EOF was encountered. + /// + /// \verbatim + /// top-level-declaration: + /// declaration + /// [C++20] module-import-declaration + /// \endverbatim + bool ParseTopLevelDecl(DeclGroupPtrTy &Result, + Sema::ModuleImportState &ImportState); + bool ParseTopLevelDecl() { + DeclGroupPtrTy Result; + Sema::ModuleImportState IS = Sema::ModuleImportState::NotACXX20Module; + return ParseTopLevelDecl(Result, IS); + } - /// ScopeCache - Cache scopes to reduce malloc traffic. - static constexpr int ScopeCacheSize = 16; - unsigned NumCachedScopes; - Scope *ScopeCache[ScopeCacheSize]; + /// ConsumeToken - Consume the current 'peek token' and lex the next one. + /// This does not work with special tokens: string literals, code completion, + /// annotation tokens and balanced tokens must be handled using the specific + /// consume methods. + /// Returns the location of the consumed token. + SourceLocation ConsumeToken() { + assert(!isTokenSpecial() && + "Should consume special tokens with Consume*Token"); + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } - /// Identifiers used for SEH handling in Borland. These are only - /// allowed in particular circumstances - // __except block - IdentifierInfo *Ident__exception_code, - *Ident___exception_code, - *Ident_GetExceptionCode; - // __except filter expression - IdentifierInfo *Ident__exception_info, - *Ident___exception_info, - *Ident_GetExceptionInfo; - // __finally - IdentifierInfo *Ident__abnormal_termination, - *Ident___abnormal_termination, - *Ident_AbnormalTermination; + bool TryConsumeToken(tok::TokenKind Expected) { + if (Tok.isNot(Expected)) + return false; + assert(!isTokenSpecial() && + "Should consume special tokens with Consume*Token"); + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return true; + } - /// Contextual keywords for Microsoft extensions. - IdentifierInfo *Ident__except; - mutable IdentifierInfo *Ident_sealed; - mutable IdentifierInfo *Ident_abstract; + bool TryConsumeToken(tok::TokenKind Expected, SourceLocation &Loc) { + if (!TryConsumeToken(Expected)) + return false; + Loc = PrevTokLocation; + return true; + } - /// Ident_super - IdentifierInfo for "super", to support fast - /// comparison. - IdentifierInfo *Ident_super; - /// Ident_vector, Ident_bool, Ident_Bool - cached IdentifierInfos for "vector" - /// and "bool" fast comparison. Only present if AltiVec or ZVector are - /// enabled. - IdentifierInfo *Ident_vector; - IdentifierInfo *Ident_bool; - IdentifierInfo *Ident_Bool; - /// Ident_pixel - cached IdentifierInfos for "pixel" fast comparison. - /// Only present if AltiVec enabled. - IdentifierInfo *Ident_pixel; + /// ConsumeAnyToken - Dispatch to the right Consume* method based on the + /// current token type. This should only be used in cases where the type of + /// the token really isn't known, e.g. in error recovery. + SourceLocation ConsumeAnyToken(bool ConsumeCodeCompletionTok = false) { + if (isTokenParen()) + return ConsumeParen(); + if (isTokenBracket()) + return ConsumeBracket(); + if (isTokenBrace()) + return ConsumeBrace(); + if (isTokenStringLiteral()) + return ConsumeStringToken(); + if (Tok.is(tok::code_completion)) + return ConsumeCodeCompletionTok ? ConsumeCodeCompletionToken() + : handleUnexpectedCodeCompletionToken(); + if (Tok.isAnnotation()) + return ConsumeAnnotationToken(); + return ConsumeToken(); + } - /// Objective-C contextual keywords. - IdentifierInfo *Ident_instancetype; + SourceLocation getEndOfPreviousToken() { + return PP.getLocForEndOfToken(PrevTokLocation); + } - /// Identifier for "introduced". - IdentifierInfo *Ident_introduced; + /// GetLookAheadToken - This peeks ahead N tokens and returns that token + /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) + /// returns the token after Tok, etc. + /// + /// Note that this differs from the Preprocessor's LookAhead method, because + /// the Parser always has one token lexed that the preprocessor doesn't. + /// + const Token &GetLookAheadToken(unsigned N) { + if (N == 0 || Tok.is(tok::eof)) + return Tok; + return PP.LookAhead(N - 1); + } - /// Identifier for "deprecated". - IdentifierInfo *Ident_deprecated; + /// NextToken - This peeks ahead one token and returns it without + /// consuming it. + const Token &NextToken() { return PP.LookAhead(0); } - /// Identifier for "obsoleted". - IdentifierInfo *Ident_obsoleted; + /// getTypeAnnotation - Read a parsed type out of an annotation token. + static TypeResult getTypeAnnotation(const Token &Tok) { + if (!Tok.getAnnotationValue()) + return TypeError(); + return ParsedType::getFromOpaquePtr(Tok.getAnnotationValue()); + } - /// Identifier for "unavailable". - IdentifierInfo *Ident_unavailable; + /// 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 + /// with a single annotation token representing the typename or C++ scope + /// respectively. + /// This simplifies handling of C++ scope specifiers and allows efficient + /// backtracking without the need to re-parse and resolve nested-names and + /// typenames. + /// It will mainly be called when we expect to treat identifiers as typenames + /// (if they are typenames). For example, in C we do not expect identifiers + /// inside expressions to be treated as typenames so it will not be called + /// for expressions in C. + /// The benefit for C/ObjC is that a typename will be annotated and + /// Actions.getTypeName will not be needed to be called again (e.g. + /// getTypeName will not be called twice, once to check whether we have a + /// declaration specifier, and another one to get the actual type inside + /// ParseDeclarationSpecifiers). + /// + /// This returns true if an error occurred. + /// + /// Note that this routine emits an error if you call it with ::new or + /// ::delete as the current tokens, so only call it in contexts where these + /// are invalid. + bool + TryAnnotateTypeOrScopeToken(ImplicitTypenameContext AllowImplicitTypename = + ImplicitTypenameContext::No); - /// Identifier for "message". - IdentifierInfo *Ident_message; + /// 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 TryAnnotateTypeOrScopeTokenAfterScopeSpec( + CXXScopeSpec &SS, bool IsNewScope, + ImplicitTypenameContext AllowImplicitTypename); - /// Identifier for "strict". - IdentifierInfo *Ident_strict; + /// TryAnnotateScopeToken - Like TryAnnotateTypeOrScopeToken but only + /// annotates C++ scope specifiers and template-ids. This returns + /// true if there was an error that could not be recovered from. + /// + /// Note that this routine emits an error if you call it with ::new or + /// ::delete as the current tokens, so only call it in contexts where these + /// are invalid. + bool TryAnnotateCXXScopeToken(bool EnteringContext = false); - /// Identifier for "replacement". - IdentifierInfo *Ident_replacement; + bool MightBeCXXScopeToken() { + return getLangOpts().CPlusPlus && + (Tok.is(tok::identifier) || Tok.is(tok::coloncolon) || + (Tok.is(tok::annot_template_id) && + NextToken().is(tok::coloncolon)) || + Tok.is(tok::kw_decltype) || Tok.is(tok::kw___super)); + } + bool TryAnnotateOptionalCXXScopeToken(bool EnteringContext = false) { + return MightBeCXXScopeToken() && TryAnnotateCXXScopeToken(EnteringContext); + } - /// Identifier for "environment". - IdentifierInfo *Ident_environment; + //===--------------------------------------------------------------------===// + // Scope manipulation - /// Identifiers used by the 'external_source_symbol' attribute. - IdentifierInfo *Ident_language, *Ident_defined_in, - *Ident_generated_declaration, *Ident_USR; + /// ParseScope - Introduces a new scope for parsing. The kind of + /// scope is determined by ScopeFlags. Objects of this type should + /// be created on the stack to coincide with the position where the + /// parser enters the new scope, and this object's constructor will + /// create that new scope. Similarly, once the object is destroyed + /// the parser will exit the scope. + class ParseScope { + Parser *Self; + ParseScope(const ParseScope &) = delete; + void operator=(const ParseScope &) = delete; - /// C++11 contextual keywords. - mutable IdentifierInfo *Ident_final; - mutable IdentifierInfo *Ident_GNU_final; - mutable IdentifierInfo *Ident_override; + public: + // ParseScope - Construct a new object to manage a scope in the + // parser Self where the new Scope is created with the flags + // ScopeFlags, but only when we aren't about to enter a compound statement. + ParseScope(Parser *Self, unsigned ScopeFlags, bool EnteredScope = true, + bool BeforeCompoundStmt = false) + : Self(Self) { + if (EnteredScope && !BeforeCompoundStmt) + Self->EnterScope(ScopeFlags); + else { + if (BeforeCompoundStmt) + Self->incrementMSManglingNumber(); - // C++2a contextual keywords. - mutable IdentifierInfo *Ident_import; - mutable IdentifierInfo *Ident_module; + this->Self = nullptr; + } + } - // C++ type trait keywords that can be reverted to identifiers and still be - // used as type traits. - llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind> RevertibleTypeTraits; + // Exit - Exit the scope associated with this object now, rather + // than waiting until the object is destroyed. + void Exit() { + if (Self) { + Self->ExitScope(); + Self = nullptr; + } + } - std::unique_ptr<PragmaHandler> AlignHandler; - std::unique_ptr<PragmaHandler> GCCVisibilityHandler; - std::unique_ptr<PragmaHandler> OptionsHandler; - std::unique_ptr<PragmaHandler> PackHandler; - std::unique_ptr<PragmaHandler> MSStructHandler; - std::unique_ptr<PragmaHandler> UnusedHandler; - std::unique_ptr<PragmaHandler> WeakHandler; - std::unique_ptr<PragmaHandler> RedefineExtnameHandler; - std::unique_ptr<PragmaHandler> FPContractHandler; - std::unique_ptr<PragmaHandler> OpenCLExtensionHandler; - std::unique_ptr<PragmaHandler> OpenMPHandler; - std::unique_ptr<PragmaHandler> OpenACCHandler; - std::unique_ptr<PragmaHandler> PCSectionHandler; - std::unique_ptr<PragmaHandler> MSCommentHandler; - std::unique_ptr<PragmaHandler> MSDetectMismatchHandler; - std::unique_ptr<PragmaHandler> FPEvalMethodHandler; - std::unique_ptr<PragmaHandler> FloatControlHandler; - std::unique_ptr<PragmaHandler> MSPointersToMembers; - std::unique_ptr<PragmaHandler> MSVtorDisp; - std::unique_ptr<PragmaHandler> MSInitSeg; - std::unique_ptr<PragmaHandler> MSDataSeg; - std::unique_ptr<PragmaHandler> MSBSSSeg; - std::unique_ptr<PragmaHandler> MSConstSeg; - std::unique_ptr<PragmaHandler> MSCodeSeg; - std::unique_ptr<PragmaHandler> MSSection; - std::unique_ptr<PragmaHandler> MSStrictGuardStackCheck; - std::unique_ptr<PragmaHandler> MSRuntimeChecks; - std::unique_ptr<PragmaHandler> MSIntrinsic; - std::unique_ptr<PragmaHandler> MSFunction; - std::unique_ptr<PragmaHandler> MSOptimize; - std::unique_ptr<PragmaHandler> MSFenvAccess; - std::unique_ptr<PragmaHandler> MSAllocText; - std::unique_ptr<PragmaHandler> CUDAForceHostDeviceHandler; - std::unique_ptr<PragmaHandler> OptimizeHandler; - std::unique_ptr<PragmaHandler> LoopHintHandler; - std::unique_ptr<PragmaHandler> UnrollHintHandler; - std::unique_ptr<PragmaHandler> NoUnrollHintHandler; - std::unique_ptr<PragmaHandler> UnrollAndJamHintHandler; - std::unique_ptr<PragmaHandler> NoUnrollAndJamHintHandler; - std::unique_ptr<PragmaHandler> FPHandler; - std::unique_ptr<PragmaHandler> STDCFenvAccessHandler; - std::unique_ptr<PragmaHandler> STDCFenvRoundHandler; - std::unique_ptr<PragmaHandler> STDCCXLIMITHandler; - std::unique_ptr<PragmaHandler> STDCUnknownHandler; - std::unique_ptr<PragmaHandler> AttributePragmaHandler; - std::unique_ptr<PragmaHandler> MaxTokensHerePragmaHandler; - std::unique_ptr<PragmaHandler> MaxTokensTotalPragmaHandler; - std::unique_ptr<PragmaHandler> RISCVPragmaHandler; + ~ParseScope() { Exit(); } + }; - std::unique_ptr<CommentHandler> CommentSemaHandler; + /// Introduces zero or more scopes for parsing. The scopes will all be exited + /// when the object is destroyed. + class MultiParseScope { + Parser &Self; + unsigned NumScopes = 0; - /// Whether the '>' token acts as an operator or not. This will be - /// true except when we are parsing an expression within a C++ - /// template argument list, where the '>' closes the template - /// argument list. - bool GreaterThanIsOperator; + MultiParseScope(const MultiParseScope &) = delete; - /// ColonIsSacred - When this is false, we aggressively try to recover from - /// code like "foo : bar" as if it were a typo for "foo :: bar". This is not - /// safe in case statements and a few other things. This is managed by the - /// ColonProtectionRAIIObject RAII object. - bool ColonIsSacred; + public: + MultiParseScope(Parser &Self) : Self(Self) {} + void Enter(unsigned ScopeFlags) { + Self.EnterScope(ScopeFlags); + ++NumScopes; + } + void Exit() { + while (NumScopes) { + Self.ExitScope(); + --NumScopes; + } + } + ~MultiParseScope() { Exit(); } + }; - /// Parsing OpenMP directive mode. - bool OpenMPDirectiveParsing = false; + /// EnterScope - Start a new scope. + void EnterScope(unsigned ScopeFlags); - /// Parsing OpenACC directive mode. - bool OpenACCDirectiveParsing = false; + /// ExitScope - Pop a scope off the scope stack. + void ExitScope(); - /// Currently parsing a situation where an OpenACC array section could be - /// legal, such as a 'var-list'. - bool AllowOpenACCArraySections = false; + //===--------------------------------------------------------------------===// + // Diagnostic Emission and Error recovery. - /// RAII object to set reset OpenACC parsing a context where Array Sections - /// are allowed. - class OpenACCArraySectionRAII { - Parser &P; + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); + DiagnosticBuilder Diag(const Token... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/138511 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits