diff options
author | Ed Schouten <ed@FreeBSD.org> | 2009-06-02 17:58:47 +0000 |
---|---|---|
committer | Ed Schouten <ed@FreeBSD.org> | 2009-06-02 17:58:47 +0000 |
commit | ec2b103c267a06a66e926f62cd96767b280f5cf5 (patch) | |
tree | ce7d964cbb5e39695b71481698f10cb099c23d4a /include/clang/Parse/Parser.h | |
download | src-test2-ec2b103c267a06a66e926f62cd96767b280f5cf5.tar.gz src-test2-ec2b103c267a06a66e926f62cd96767b280f5cf5.zip |
Notes
Diffstat (limited to 'include/clang/Parse/Parser.h')
-rw-r--r-- | include/clang/Parse/Parser.h | 1208 |
1 files changed, 1208 insertions, 0 deletions
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h new file mode 100644 index 000000000000..26e37e2806a0 --- /dev/null +++ b/include/clang/Parse/Parser.h @@ -0,0 +1,1208 @@ +//===--- Parser.h - C Language Parser ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Parser interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_PARSER_H +#define LLVM_CLANG_PARSE_PARSER_H + +#include "clang/Lex/Preprocessor.h" +#include "clang/Parse/AccessSpecifier.h" +#include "clang/Parse/Action.h" +#include "clang/Parse/DeclSpec.h" +#include "llvm/ADT/OwningPtr.h" +#include <stack> +#include <list> + +namespace clang { + class AttributeList; + class PragmaHandler; + class Scope; + class DiagnosticBuilder; + class Parser; + class PragmaUnusedHandler; + +/// PrettyStackTraceParserEntry - If a crash happens while the parser is active, +/// an entry is printed for it. +class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { + const Parser &P; +public: + PrettyStackTraceParserEntry(const Parser &p) : P(p) {} + virtual void print(llvm::raw_ostream &OS) const; +}; + + +/// Parser - This implements a parser for the C family of languages. After +/// parsing units of the grammar, productions are invoked to handle whatever has +/// been read. +/// +class Parser { + friend class PragmaUnusedHandler; + PrettyStackTraceParserEntry CrashInfo; + + Preprocessor &PP; + + /// Tok - The current token we are peeking ahead. All parsing methods assume + /// that this is valid. + Token Tok; + + // 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; + + unsigned short ParenCount, BracketCount, BraceCount; + + /// Actions - These are the callbacks we invoke as we parse various constructs + /// in the file. This refers to the common base class between MinimalActions + /// and SemaActions for those uses that don't matter. + Action &Actions; + + Scope *CurScope; + Diagnostic &Diags; + + /// ScopeCache - Cache scopes to reduce malloc traffic. + enum { ScopeCacheSize = 16 }; + unsigned NumCachedScopes; + Scope *ScopeCache[ScopeCacheSize]; + + /// Ident_super - IdentifierInfo for "super", to support fast + /// comparison. + IdentifierInfo *Ident_super; + + llvm::OwningPtr<PragmaHandler> PackHandler; + llvm::OwningPtr<PragmaHandler> UnusedHandler; + + /// 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; + + /// \brief RAII object that makes '>' behave either as an operator + /// or as the closing angle bracket for a template argument list. + struct GreaterThanIsOperatorScope { + bool &GreaterThanIsOperator; + bool OldGreaterThanIsOperator; + + GreaterThanIsOperatorScope(bool >IO, bool Val) + : GreaterThanIsOperator(GTIO), OldGreaterThanIsOperator(GTIO) { + GreaterThanIsOperator = Val; + } + + ~GreaterThanIsOperatorScope() { + GreaterThanIsOperator = OldGreaterThanIsOperator; + } + }; + +public: + Parser(Preprocessor &PP, Action &Actions); + ~Parser(); + + const LangOptions &getLang() const { return PP.getLangOptions(); } + TargetInfo &getTargetInfo() const { return PP.getTargetInfo(); } + Preprocessor &getPreprocessor() const { return PP; } + Action &getActions() const { return Actions; } + + const Token &getCurToken() const { return Tok; } + + // Type forwarding. All of these are statically 'void*', but they may all be + // different actual classes based on the actions in place. + typedef Action::ExprTy ExprTy; + typedef Action::StmtTy StmtTy; + typedef Action::DeclPtrTy DeclPtrTy; + typedef Action::DeclGroupPtrTy DeclGroupPtrTy; + typedef Action::TypeTy TypeTy; + typedef Action::BaseTy BaseTy; + typedef Action::MemInitTy MemInitTy; + typedef Action::CXXScopeTy CXXScopeTy; + typedef Action::TemplateParamsTy TemplateParamsTy; + typedef Action::TemplateTy TemplateTy; + + typedef llvm::SmallVector<TemplateParamsTy *, 4> TemplateParameterLists; + + typedef Action::ExprResult ExprResult; + typedef Action::StmtResult StmtResult; + typedef Action::BaseResult BaseResult; + typedef Action::MemInitResult MemInitResult; + typedef Action::TypeResult TypeResult; + + typedef Action::OwningExprResult OwningExprResult; + typedef Action::OwningStmtResult OwningStmtResult; + + typedef Action::ExprArg ExprArg; + typedef Action::MultiStmtArg MultiStmtArg; + typedef Action::FullExprArg FullExprArg; + + /// Adorns a ExprResult with Actions to make it an OwningExprResult + OwningExprResult Owned(ExprResult res) { + return OwningExprResult(Actions, res); + } + /// Adorns a StmtResult with Actions to make it an OwningStmtResult + OwningStmtResult Owned(StmtResult res) { + return OwningStmtResult(Actions, res); + } + + OwningExprResult ExprError() { return OwningExprResult(Actions, true); } + OwningStmtResult StmtError() { return OwningStmtResult(Actions, true); } + + OwningExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); } + OwningStmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); } + + OwningExprResult ExprEmpty() { return OwningExprResult(Actions, false); } + + // Parsing methods. + + /// ParseTranslationUnit - All in one method that initializes parses, and + /// shuts down the parser. + void ParseTranslationUnit(); + + /// Initialize - Warm up the parser. + /// + void Initialize(); + + /// ParseTopLevelDecl - Parse one top-level declaration. Returns true if + /// the EOF was encountered. + bool ParseTopLevelDecl(DeclGroupPtrTy &Result); + +private: + //===--------------------------------------------------------------------===// + // Low-Level token peeking and consumption methods. + // + + /// isTokenParen - Return true if the cur token is '(' or ')'. + bool isTokenParen() const { + return Tok.getKind() == tok::l_paren || Tok.getKind() == tok::r_paren; + } + /// isTokenBracket - Return true if the cur token is '[' or ']'. + bool isTokenBracket() const { + return Tok.getKind() == tok::l_square || Tok.getKind() == tok::r_square; + } + /// isTokenBrace - Return true if the cur token is '{' or '}'. + bool isTokenBrace() const { + return Tok.getKind() == tok::l_brace || Tok.getKind() == tok::r_brace; + } + + /// isTokenStringLiteral - True if this token is a string-literal. + /// + bool isTokenStringLiteral() const { + return Tok.getKind() == tok::string_literal || + Tok.getKind() == tok::wide_string_literal; + } + + /// ConsumeToken - Consume the current 'peek token' and lex the next one. + /// This does not work with all kinds of tokens: strings and specific other + /// tokens must be consumed with custom methods below. This returns the + /// location of the consumed token. + SourceLocation ConsumeToken() { + assert(!isTokenStringLiteral() && !isTokenParen() && !isTokenBracket() && + !isTokenBrace() && + "Should consume special tokens with Consume*Token"); + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + /// 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() { + if (isTokenParen()) + return ConsumeParen(); + else if (isTokenBracket()) + return ConsumeBracket(); + else if (isTokenBrace()) + return ConsumeBrace(); + else if (isTokenStringLiteral()) + return ConsumeStringToken(); + else + return ConsumeToken(); + } + + /// ConsumeParen - This consume method keeps the paren count up-to-date. + /// + SourceLocation ConsumeParen() { + assert(isTokenParen() && "wrong consume method"); + if (Tok.getKind() == tok::l_paren) + ++ParenCount; + else if (ParenCount) + --ParenCount; // Don't let unbalanced )'s drive the count negative. + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + /// ConsumeBracket - This consume method keeps the bracket count up-to-date. + /// + SourceLocation ConsumeBracket() { + assert(isTokenBracket() && "wrong consume method"); + if (Tok.getKind() == tok::l_square) + ++BracketCount; + else if (BracketCount) + --BracketCount; // Don't let unbalanced ]'s drive the count negative. + + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + /// ConsumeBrace - This consume method keeps the brace count up-to-date. + /// + SourceLocation ConsumeBrace() { + assert(isTokenBrace() && "wrong consume method"); + if (Tok.getKind() == tok::l_brace) + ++BraceCount; + else if (BraceCount) + --BraceCount; // Don't let unbalanced }'s drive the count negative. + + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + /// ConsumeStringToken - Consume the current 'peek token', lexing a new one + /// and returning the token kind. This method is specific to strings, as it + /// handles string literal concatenation, as per C99 5.1.1.2, translation + /// phase #6. + SourceLocation ConsumeStringToken() { + assert(isTokenStringLiteral() && + "Should only consume string literals with this method"); + PrevTokLocation = Tok.getLocation(); + PP.Lex(Tok); + return PrevTokLocation; + } + + /// 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); + } + + /// NextToken - This peeks ahead one token and returns it without + /// consuming it. + const Token &NextToken() { + return PP.LookAhead(0); + } + + /// 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. + /// + /// This returns true if the token was annotated. + bool TryAnnotateTypeOrScopeToken(); + + /// TryAnnotateCXXScopeToken - Like TryAnnotateTypeOrScopeToken but only + /// annotates C++ scope specifiers. This returns true if the token was + /// annotated. + bool TryAnnotateCXXScopeToken(); + + /// TentativeParsingAction - An object that is used as a kind of "tentative + /// parsing transaction". It gets instantiated to mark the token position and + /// after the token consumption is done, Commit() or Revert() is called to + /// either "commit the consumed tokens" or revert to the previously marked + /// token position. Example: + /// + /// TentativeParsingAction TPA; + /// ConsumeToken(); + /// .... + /// TPA.Revert(); + /// + class TentativeParsingAction { + Parser &P; + Token PrevTok; + bool isActive; + + public: + explicit TentativeParsingAction(Parser& p) : P(p) { + PrevTok = P.Tok; + P.PP.EnableBacktrackAtThisPos(); + isActive = true; + } + void Commit() { + assert(isActive && "Parsing action was finished!"); + P.PP.CommitBacktrackedTokens(); + isActive = false; + } + void Revert() { + assert(isActive && "Parsing action was finished!"); + P.PP.Backtrack(); + P.Tok = PrevTok; + isActive = false; + } + ~TentativeParsingAction() { + assert(!isActive && "Forgot to call Commit or Revert!"); + } + }; + + + /// MatchRHSPunctuation - For punctuation with a LHS and RHS (e.g. '['/']'), + /// this helper function matches and consumes the specified RHS token if + /// present. If not present, it emits the specified diagnostic indicating + /// that the parser failed to match the RHS of the token at LHSLoc. LHSName + /// should be the name of the unmatched LHS token. This returns the location + /// of the consumed token. + SourceLocation MatchRHSPunctuation(tok::TokenKind RHSTok, + SourceLocation LHSLoc); + + /// ExpectAndConsume - The parser expects that 'ExpectedTok' is next in the + /// input. If so, it is consumed and false is returned. + /// + /// If the input is malformed, this emits the specified diagnostic. Next, if + /// SkipToTok is specified, it calls SkipUntil(SkipToTok). Finally, true is + /// returned. + bool ExpectAndConsume(tok::TokenKind ExpectedTok, unsigned Diag, + const char *DiagMsg = "", + tok::TokenKind SkipToTok = tok::unknown); + + //===--------------------------------------------------------------------===// + // Scope manipulation + + /// 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&); // do not implement + ParseScope& operator=(const ParseScope&); // do not implement + + 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 ManageScope is true (the default). If + // ManageScope is false, this object does nothing. + ParseScope(Parser *Self, unsigned ScopeFlags, bool ManageScope = true) + : Self(Self) { + if (ManageScope) + Self->EnterScope(ScopeFlags); + else + this->Self = 0; + } + + // Exit - Exit the scope associated with this object now, rather + // than waiting until the object is destroyed. + void Exit() { + if (Self) { + Self->ExitScope(); + Self = 0; + } + } + + ~ParseScope() { + Exit(); + } + }; + + /// EnterScope - Start a new scope. + void EnterScope(unsigned ScopeFlags); + + /// ExitScope - Pop a scope off the scope stack. + void ExitScope(); + + //===--------------------------------------------------------------------===// + // Diagnostic Emission and Error recovery. + + DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID); + DiagnosticBuilder Diag(const Token &Tok, unsigned DiagID); + + void SuggestParentheses(SourceLocation Loc, unsigned DK, + SourceRange ParenRange); + + /// SkipUntil - Read tokens until we get to the specified token, then consume + /// it (unless DontConsume is true). 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 SkipUntil(tok::TokenKind T, bool StopAtSemi = true, + bool DontConsume = false) { + return SkipUntil(&T, 1, StopAtSemi, DontConsume); + } + bool SkipUntil(tok::TokenKind T1, tok::TokenKind T2, bool StopAtSemi = true, + bool DontConsume = false) { + tok::TokenKind TokArray[] = {T1, T2}; + return SkipUntil(TokArray, 2, StopAtSemi, DontConsume); + } + bool SkipUntil(const tok::TokenKind *Toks, unsigned NumToks, + bool StopAtSemi = true, bool DontConsume = false); + + //===--------------------------------------------------------------------===// + // Lexing and parsing of C++ inline methods. + + struct LexedMethod { + Action::DeclPtrTy D; + CachedTokens Toks; + explicit LexedMethod(Action::DeclPtrTy MD) : D(MD) {} + }; + + /// LateParsedDefaultArgument - Keeps track of a parameter that may + /// have a default argument that cannot be parsed yet because it + /// occurs within a member function declaration inside the class + /// (C++ [class.mem]p2). + struct LateParsedDefaultArgument { + explicit LateParsedDefaultArgument(Action::DeclPtrTy P, + CachedTokens *Toks = 0) + : Param(P), Toks(Toks) { } + + /// Param - The parameter declaration for this parameter. + Action::DeclPtrTy Param; + + /// Toks - The sequence of tokens that comprises the default + /// argument expression, not including the '=' or the terminating + /// ')' or ','. This will be NULL for parameters that have no + /// default argument. + CachedTokens *Toks; + }; + + /// LateParsedMethodDeclaration - A method declaration inside a class that + /// contains at least one entity whose parsing needs to be delayed + /// until the class itself is completely-defined, such as a default + /// argument (C++ [class.mem]p2). + struct LateParsedMethodDeclaration { + explicit LateParsedMethodDeclaration(Action::DeclPtrTy M) : Method(M) { } + + /// Method - The method declaration. + Action::DeclPtrTy Method; + + /// DefaultArgs - Contains the parameters of the function and + /// their default arguments. At least one of the parameters will + /// have a default argument, but all of the parameters of the + /// method will be stored so that they can be reintroduced into + /// scope at the appropriate times. + llvm::SmallVector<LateParsedDefaultArgument, 8> DefaultArgs; + }; + + /// LateParsedMethodDecls - During parsing of a top (non-nested) C++ + /// class, its method declarations that contain parts that won't be + /// parsed until after the definiton is completed (C++ [class.mem]p2), + /// the method declarations will be stored here with the tokens that + /// will be parsed to create those entities. + typedef std::list<LateParsedMethodDeclaration> LateParsedMethodDecls; + + /// LexedMethodsForTopClass - During parsing of a top (non-nested) C++ class, + /// its inline method definitions and the inline method definitions of its + /// nested classes are lexed and stored here. + typedef std::list<LexedMethod> LexedMethodsForTopClass; + + /// \brief Representation of a class that has been parsed, including + /// any member function declarations or definitions that need to be + /// parsed after the corresponding top-level class is complete. + struct ParsingClass { + ParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass) + : TopLevelClass(TopLevelClass), TemplateScope(false), + TagOrTemplate(TagOrTemplate) { } + + /// \brief Whether this is a "top-level" class, meaning that it is + /// not nested within another class. + bool TopLevelClass : 1; + + /// \brief Whether this class had an associated template + /// scope. When true, TagOrTemplate is a template declaration; + /// othewise, it is a tag declaration. + bool TemplateScope : 1; + + /// \brief The class or class template whose definition we are parsing. + DeclPtrTy TagOrTemplate; + + /// MethodDecls - Method declarations that contain pieces whose + /// parsing will be delayed until the class is fully defined. + LateParsedMethodDecls MethodDecls; + + /// MethodDefs - Methods whose definitions will be parsed once the + /// class has been fully defined. + LexedMethodsForTopClass MethodDefs; + + /// \brief Nested classes inside this class. + llvm::SmallVector<ParsingClass*, 4> NestedClasses; + }; + + /// \brief The stack of classes that is currently being + /// parsed. Nested and local classes will be pushed onto this stack + /// when they are parsed, and removed afterward. + std::stack<ParsingClass *> ClassStack; + + ParsingClass &getCurrentClass() { + assert(!ClassStack.empty() && "No lexed method stacks!"); + return *ClassStack.top(); + } + + /// \brief RAII object used to + class ParsingClassDefinition { + Parser &P; + bool Popped; + + public: + ParsingClassDefinition(Parser &P, DeclPtrTy TagOrTemplate, bool TopLevelClass) + : P(P), Popped(false) { + P.PushParsingClass(TagOrTemplate, TopLevelClass); + } + + /// \brief Pop this class of the stack. + void Pop() { + assert(!Popped && "Nested class has already been popped"); + Popped = true; + P.PopParsingClass(); + } + + ~ParsingClassDefinition() { + if (!Popped) + P.PopParsingClass(); + } + }; + + void PushParsingClass(DeclPtrTy TagOrTemplate, bool TopLevelClass); + void DeallocateParsedClasses(ParsingClass *Class); + void PopParsingClass(); + + DeclPtrTy ParseCXXInlineMethodDef(AccessSpecifier AS, Declarator &D); + void ParseLexedMethodDeclarations(ParsingClass &Class); + void ParseLexedMethodDefs(ParsingClass &Class); + bool ConsumeAndStoreUntil(tok::TokenKind T1, tok::TokenKind T2, + CachedTokens &Toks, + tok::TokenKind EarlyAbortIf = tok::unknown, + bool ConsumeFinalToken = true); + + /// \brief Contains information about any template-specific + /// information that has been parsed prior to parsing declaration + /// specifiers. + struct ParsedTemplateInfo { + ParsedTemplateInfo() + : Kind(NonTemplate), TemplateParams(0), TemplateLoc() { } + + ParsedTemplateInfo(TemplateParameterLists *TemplateParams, + bool isSpecialization) + : Kind(isSpecialization? ExplicitSpecialization : Template), + TemplateParams(TemplateParams) { } + + explicit ParsedTemplateInfo(SourceLocation TemplateLoc) + : Kind(ExplicitInstantiation), TemplateParams(0), + TemplateLoc(TemplateLoc) { } + + /// \brief The kind of template we are parsing. + enum { + /// \brief We are not parsing a template at all. + NonTemplate = 0, + /// \brief We are parsing a template declaration. + Template, + /// \brief We are parsing an explicit specialization. + ExplicitSpecialization, + /// \brief We are parsing an explicit instantiation. + ExplicitInstantiation + } Kind; + + /// \brief The template parameter lists, for template declarations + /// and explicit specializations. + TemplateParameterLists *TemplateParams; + + /// \brief The location of the 'template' keyword, for an explicit + /// instantiation. + SourceLocation TemplateLoc; + }; + + //===--------------------------------------------------------------------===// + // C99 6.9: External Definitions. + DeclGroupPtrTy ParseExternalDeclaration(); + bool isDeclarationAfterDeclarator(); + bool isStartOfFunctionDefinition(); + DeclGroupPtrTy ParseDeclarationOrFunctionDefinition( + AccessSpecifier AS = AS_none); + + DeclPtrTy ParseFunctionDefinition(Declarator &D); + void ParseKNRParamDeclarations(Declarator &D); + // EndLoc, if non-NULL, is filled with the location of the last token of + // the simple-asm. + OwningExprResult ParseSimpleAsm(SourceLocation *EndLoc = 0); + OwningExprResult ParseAsmStringLiteral(); + + // Objective-C External Declarations + DeclPtrTy ParseObjCAtDirectives(); + DeclPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); + DeclPtrTy ParseObjCAtInterfaceDeclaration(SourceLocation atLoc, + AttributeList *prefixAttrs = 0); + void ParseObjCClassInstanceVariables(DeclPtrTy interfaceDecl, + SourceLocation atLoc); + bool ParseObjCProtocolReferences(llvm::SmallVectorImpl<Action::DeclPtrTy> &P, + bool WarnOnDeclarations, + SourceLocation &EndProtoLoc); + void ParseObjCInterfaceDeclList(DeclPtrTy interfaceDecl, + tok::ObjCKeywordKind contextKey); + DeclPtrTy ParseObjCAtProtocolDeclaration(SourceLocation atLoc, + AttributeList *prefixAttrs = 0); + + DeclPtrTy ObjCImpDecl; + + DeclPtrTy ParseObjCAtImplementationDeclaration(SourceLocation atLoc); + DeclPtrTy ParseObjCAtEndDeclaration(SourceLocation atLoc); + DeclPtrTy ParseObjCAtAliasDeclaration(SourceLocation atLoc); + DeclPtrTy ParseObjCPropertySynthesize(SourceLocation atLoc); + DeclPtrTy ParseObjCPropertyDynamic(SourceLocation atLoc); + + IdentifierInfo *ParseObjCSelectorPiece(SourceLocation &MethodLocation); + // Definitions for Objective-c context sensitive keywords recognition. + enum ObjCTypeQual { + objc_in=0, objc_out, objc_inout, objc_oneway, objc_bycopy, objc_byref, + objc_NumQuals + }; + IdentifierInfo *ObjCTypeQuals[objc_NumQuals]; + + bool isTokIdentifier_in() const; + + TypeTy *ParseObjCTypeName(ObjCDeclSpec &DS); + void ParseObjCMethodRequirement(); + DeclPtrTy ParseObjCMethodPrototype(DeclPtrTy classOrCat, + tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); + DeclPtrTy ParseObjCMethodDecl(SourceLocation mLoc, tok::TokenKind mType, + DeclPtrTy classDecl, + tok::ObjCKeywordKind MethodImplKind = tok::objc_not_keyword); + void ParseObjCPropertyAttribute(ObjCDeclSpec &DS); + + DeclPtrTy ParseObjCMethodDefinition(); + + //===--------------------------------------------------------------------===// + // C99 6.5: Expressions. + + OwningExprResult ParseExpression(); + OwningExprResult ParseConstantExpression(); + // Expr that doesn't include commas. + OwningExprResult ParseAssignmentExpression(); + + OwningExprResult ParseExpressionWithLeadingAt(SourceLocation AtLoc); + + OwningExprResult ParseExpressionWithLeadingExtension(SourceLocation ExtLoc); + + OwningExprResult ParseRHSOfBinaryExpression(OwningExprResult LHS, + unsigned MinPrec); + OwningExprResult ParseCastExpression(bool isUnaryExpression, + bool isAddressOfOperand, + bool &NotCastExpr); + OwningExprResult ParseCastExpression(bool isUnaryExpression, + bool isAddressOfOperand = false); + OwningExprResult ParsePostfixExpressionSuffix(OwningExprResult LHS); + OwningExprResult ParseSizeofAlignofExpression(); + OwningExprResult ParseBuiltinPrimaryExpression(); + + OwningExprResult ParseExprAfterTypeofSizeofAlignof(const Token &OpTok, + bool &isCastExpr, + TypeTy *&CastTy, + SourceRange &CastRange); + + static const unsigned ExprListSize = 12; + typedef llvm::SmallVector<ExprTy*, ExprListSize> ExprListTy; + typedef llvm::SmallVector<SourceLocation, ExprListSize> CommaLocsTy; + + /// ParseExpressionList - Used for C/C++ (argument-)expression-list. + bool ParseExpressionList(ExprListTy &Exprs, CommaLocsTy &CommaLocs); + + /// ParenParseOption - Control what ParseParenExpression will parse. + enum ParenParseOption { + SimpleExpr, // Only parse '(' expression ')' + CompoundStmt, // Also allow '(' compound-statement ')' + CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}' + CastExpr // Also allow '(' type-name ')' <anything> + }; + OwningExprResult ParseParenExpression(ParenParseOption &ExprType, + bool stopIfCastExpr, + TypeTy *&CastTy, + SourceLocation &RParenLoc); + + OwningExprResult ParseCXXAmbiguousParenExpression(ParenParseOption &ExprType, + TypeTy *&CastTy, + SourceLocation LParenLoc, + SourceLocation &RParenLoc); + + OwningExprResult ParseCompoundLiteralExpression(TypeTy *Ty, + SourceLocation LParenLoc, + SourceLocation RParenLoc); + + OwningExprResult ParseStringLiteralExpression(); + + //===--------------------------------------------------------------------===// + // C++ Expressions + OwningExprResult ParseCXXIdExpression(bool isAddressOfOperand = false); + + /// ParseOptionalCXXScopeSpecifier - Parse global scope or + /// nested-name-specifier if present. Returns true if a nested-name-specifier + /// was parsed from the token stream. Note that this routine will not parse + /// ::new or ::delete, it will just leave them in the token stream. + /// + bool ParseOptionalCXXScopeSpecifier(CXXScopeSpec &SS); + + //===--------------------------------------------------------------------===// + // C++ 5.2p1: C++ Casts + OwningExprResult ParseCXXCasts(); + + //===--------------------------------------------------------------------===// + // C++ 5.2p1: C++ Type Identification + OwningExprResult ParseCXXTypeid(); + + //===--------------------------------------------------------------------===// + // C++ 9.3.2: C++ 'this' pointer + OwningExprResult ParseCXXThis(); + + //===--------------------------------------------------------------------===// + // C++ 15: C++ Throw Expression + OwningExprResult ParseThrowExpression(); + // EndLoc is filled with the location of the last token of the specification. + bool ParseExceptionSpecification(SourceLocation &EndLoc, + llvm::SmallVector<TypeTy*, 2> &Exceptions, + llvm::SmallVector<SourceRange, 2> &Ranges, + bool &hasAnyExceptionSpec); + + //===--------------------------------------------------------------------===// + // C++ 2.13.5: C++ Boolean Literals + OwningExprResult ParseCXXBoolLiteral(); + + //===--------------------------------------------------------------------===// + // C++ 5.2.3: Explicit type conversion (functional notation) + OwningExprResult ParseCXXTypeConstructExpression(const DeclSpec &DS); + + /// ParseCXXSimpleTypeSpecifier - [C++ 7.1.5.2] Simple type specifiers. + /// This should only be called when the current token is known to be part of + /// simple-type-specifier. + void ParseCXXSimpleTypeSpecifier(DeclSpec &DS); + + bool ParseCXXTypeSpecifierSeq(DeclSpec &DS); + + //===--------------------------------------------------------------------===// + // C++ 5.3.4 and 5.3.5: C++ new and delete + bool ParseExpressionListOrTypeId(ExprListTy &Exprs, Declarator &D); + void ParseDirectNewDeclarator(Declarator &D); + OwningExprResult ParseCXXNewExpression(bool UseGlobal, SourceLocation Start); + OwningExprResult ParseCXXDeleteExpression(bool UseGlobal, + SourceLocation Start); + + //===--------------------------------------------------------------------===// + // C++ if/switch/while/for condition expression. + OwningExprResult ParseCXXCondition(); + + //===--------------------------------------------------------------------===// + // C++ types + + //===--------------------------------------------------------------------===// + // C99 6.7.8: Initialization. + + /// ParseInitializer + /// initializer: [C99 6.7.8] + /// assignment-expression + /// '{' ... + OwningExprResult ParseInitializer() { + if (Tok.isNot(tok::l_brace)) + return ParseAssignmentExpression(); + return ParseBraceInitializer(); + } + OwningExprResult ParseBraceInitializer(); + OwningExprResult ParseInitializerWithPotentialDesignator(); + + //===--------------------------------------------------------------------===// + // clang Expressions + + OwningExprResult ParseBlockLiteralExpression(); // ^{...} + + //===--------------------------------------------------------------------===// + // Objective-C Expressions + + bool isTokObjCMessageIdentifierReceiver() const { + if (!Tok.is(tok::identifier)) + return false; + + IdentifierInfo *II = Tok.getIdentifierInfo(); + if (Actions.getTypeName(*II, Tok.getLocation(), CurScope)) + return true; + + return II == Ident_super; + } + + OwningExprResult ParseObjCAtExpression(SourceLocation AtLocation); + OwningExprResult ParseObjCStringLiteral(SourceLocation AtLoc); + OwningExprResult ParseObjCEncodeExpression(SourceLocation AtLoc); + OwningExprResult ParseObjCSelectorExpression(SourceLocation AtLoc); + OwningExprResult ParseObjCProtocolExpression(SourceLocation AtLoc); + OwningExprResult ParseObjCMessageExpression(); + OwningExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc, + SourceLocation NameLoc, + IdentifierInfo *ReceiverName, + ExprArg ReceiverExpr); + OwningExprResult ParseAssignmentExprWithObjCMessageExprStart( + SourceLocation LBracloc, SourceLocation NameLoc, + IdentifierInfo *ReceiverName, ExprArg ReceiverExpr); + + //===--------------------------------------------------------------------===// + // C99 6.8: Statements and Blocks. + + OwningStmtResult ParseStatement() { + return ParseStatementOrDeclaration(true); + } + OwningStmtResult ParseStatementOrDeclaration(bool OnlyStatement = false); + OwningStmtResult ParseLabeledStatement(); + OwningStmtResult ParseCaseStatement(); + OwningStmtResult ParseDefaultStatement(); + OwningStmtResult ParseCompoundStatement(bool isStmtExpr = false); + OwningStmtResult ParseCompoundStatementBody(bool isStmtExpr = false); + bool ParseParenExprOrCondition(OwningExprResult &CondExp, + bool OnlyAllowCondition = false); + OwningStmtResult ParseIfStatement(); + OwningStmtResult ParseSwitchStatement(); + OwningStmtResult ParseWhileStatement(); + OwningStmtResult ParseDoStatement(); + OwningStmtResult ParseForStatement(); + OwningStmtResult ParseGotoStatement(); + OwningStmtResult ParseContinueStatement(); + OwningStmtResult ParseBreakStatement(); + OwningStmtResult ParseReturnStatement(); + OwningStmtResult ParseAsmStatement(bool &msAsm); + OwningStmtResult FuzzyParseMicrosoftAsmStatement(); + bool ParseAsmOperandsOpt(llvm::SmallVectorImpl<std::string> &Names, + llvm::SmallVectorImpl<ExprTy*> &Constraints, + llvm::SmallVectorImpl<ExprTy*> &Exprs); + + //===--------------------------------------------------------------------===// + // C++ 6: Statements and Blocks + + OwningStmtResult ParseCXXTryBlock(); + OwningStmtResult ParseCXXTryBlockCommon(SourceLocation TryLoc); + OwningStmtResult ParseCXXCatchBlock(); + + //===--------------------------------------------------------------------===// + // Objective-C Statements + + OwningStmtResult ParseObjCAtStatement(SourceLocation atLoc); + OwningStmtResult ParseObjCTryStmt(SourceLocation atLoc); + OwningStmtResult ParseObjCThrowStmt(SourceLocation atLoc); + OwningStmtResult ParseObjCSynchronizedStmt(SourceLocation atLoc); + + + //===--------------------------------------------------------------------===// + // C99 6.7: Declarations. + + DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd); + DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context, + SourceLocation &DeclEnd, + bool RequireSemi = true); + DeclPtrTy ParseDeclarationAfterDeclarator(Declarator &D); + DeclGroupPtrTy ParseInitDeclaratorListAfterFirstDeclarator(Declarator &D); + DeclPtrTy ParseFunctionStatementBody(DeclPtrTy Decl); + DeclPtrTy ParseFunctionTryBlock(DeclPtrTy Decl); + + bool ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, + const ParsedTemplateInfo &TemplateInfo, + AccessSpecifier AS); + void ParseDeclarationSpecifiers(DeclSpec &DS, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + AccessSpecifier AS = AS_none); + bool ParseOptionalTypeSpecifier(DeclSpec &DS, int &isInvalid, + const char *&PrevSpec, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo()); + + void ParseSpecifierQualifierList(DeclSpec &DS); + + void ParseObjCTypeQualifierList(ObjCDeclSpec &DS); + + void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, + AccessSpecifier AS = AS_none); + void ParseEnumBody(SourceLocation StartLoc, DeclPtrTy TagDecl); + void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, + DeclPtrTy TagDecl); + void ParseStructDeclaration(DeclSpec &DS, + llvm::SmallVectorImpl<FieldDeclarator> &Fields); + + bool isDeclarationSpecifier(); + bool isTypeSpecifierQualifier(); + bool isTypeQualifier() const; + + /// isDeclarationStatement - Disambiguates between a declaration or an + /// expression statement, when parsing function bodies. + /// Returns true for declaration, false for expression. + bool isDeclarationStatement() { + if (getLang().CPlusPlus) + return isCXXDeclarationStatement(); + return isDeclarationSpecifier(); + } + + /// isSimpleDeclaration - Disambiguates between a declaration or an + /// expression, mainly used for the C 'clause-1' or the C++ + // 'for-init-statement' part of a 'for' statement. + /// Returns true for declaration, false for expression. + bool isSimpleDeclaration() { + if (getLang().CPlusPlus) + return isCXXSimpleDeclaration(); + return isDeclarationSpecifier(); + } + + /// \brief Specifies the context in which type-id/expression + /// disambiguation will occur. + enum TentativeCXXTypeIdContext { + TypeIdInParens, + TypeIdAsTemplateArgument + }; + + + /// isTypeIdInParens - Assumes that a '(' was parsed and now we want to know + /// whether the parens contain an expression or a type-id. + /// Returns true for a type-id and false for an expression. + bool isTypeIdInParens(bool &isAmbiguous) { + if (getLang().CPlusPlus) + return isCXXTypeId(TypeIdInParens, isAmbiguous); + isAmbiguous = false; + return isTypeSpecifierQualifier(); + } + bool isTypeIdInParens() { + bool isAmbiguous; + return isTypeIdInParens(isAmbiguous); + } + + /// isCXXDeclarationStatement - C++-specialized function that disambiguates + /// between a declaration or an expression statement, when parsing function + /// bodies. Returns true for declaration, false for expression. + bool isCXXDeclarationStatement(); + + /// isCXXSimpleDeclaration - C++-specialized function that disambiguates + /// between a simple-declaration or an expression-statement. + /// If during the disambiguation process a parsing error is encountered, + /// the function returns true to let the declaration parsing code handle it. + /// Returns false if the statement is disambiguated as expression. + bool isCXXSimpleDeclaration(); + + /// isCXXFunctionDeclarator - Disambiguates between a function declarator or + /// a constructor-style initializer, when parsing declaration statements. + /// Returns true for function declarator and false for constructor-style + /// initializer. If 'warnIfAmbiguous' is true a warning will be emitted to + /// indicate that the parens were disambiguated as function declarator. + /// If during the disambiguation process a parsing error is encountered, + /// the function returns true to let the declaration parsing code handle it. + bool isCXXFunctionDeclarator(bool warnIfAmbiguous); + + /// isCXXConditionDeclaration - Disambiguates between a declaration or an + /// expression for a condition of a if/switch/while/for statement. + /// If during the disambiguation process a parsing error is encountered, + /// the function returns true to let the declaration parsing code handle it. + bool isCXXConditionDeclaration(); + + bool isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous); + bool isCXXTypeId(TentativeCXXTypeIdContext Context) { + bool isAmbiguous; + return isCXXTypeId(Context, isAmbiguous); + } + + /// TPResult - Used as the result value for functions whose purpose is to + /// disambiguate C++ constructs by "tentatively parsing" them. + /// This is a class instead of a simple enum because the implicit enum-to-bool + /// conversions may cause subtle bugs. + class TPResult { + enum Result { + TPR_true, + TPR_false, + TPR_ambiguous, + TPR_error + }; + Result Res; + TPResult(Result result) : Res(result) {} + public: + static TPResult True() { return TPR_true; } + static TPResult False() { return TPR_false; } + static TPResult Ambiguous() { return TPR_ambiguous; } + static TPResult Error() { return TPR_error; } + + bool operator==(const TPResult &RHS) const { return Res == RHS.Res; } + bool operator!=(const TPResult &RHS) const { return Res != RHS.Res; } + }; + + /// isCXXDeclarationSpecifier - Returns TPResult::True() if it is a + /// declaration specifier, TPResult::False() if it is not, + /// TPResult::Ambiguous() if it could be either a decl-specifier or a + /// function-style cast, and TPResult::Error() if a parsing error was + /// encountered. + /// Doesn't consume tokens. + TPResult isCXXDeclarationSpecifier(); + + // "Tentative parsing" functions, used for disambiguation. If a parsing error + // is encountered they will return TPResult::Error(). + // Returning TPResult::True()/False() indicates that the ambiguity was + // resolved and tentative parsing may stop. TPResult::Ambiguous() indicates + // that more tentative parsing is necessary for disambiguation. + // They all consume tokens, so backtracking should be used after calling them. + + TPResult TryParseDeclarationSpecifier(); + TPResult TryParseSimpleDeclaration(); + TPResult TryParseTypeofSpecifier(); + TPResult TryParseInitDeclaratorList(); + TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true); + TPResult TryParseParameterDeclarationClause(); + TPResult TryParseFunctionDeclarator(); + TPResult TryParseBracketDeclarator(); + + TypeResult ParseTypeName(SourceRange *Range = 0); + void ParseBlockId(); + // EndLoc, if non-NULL, is filled with the location of the last token of + // the attribute list. + AttributeList *ParseAttributes(SourceLocation *EndLoc = 0); + void FuzzyParseMicrosoftDeclSpec(); + void ParseTypeofSpecifier(DeclSpec &DS); + + /// DeclaratorScopeObj - RAII object used in Parser::ParseDirectDeclarator to + /// enter a new C++ declarator scope and exit it when the function is + /// finished. + class DeclaratorScopeObj { + Parser &P; + CXXScopeSpec &SS; + public: + DeclaratorScopeObj(Parser &p, CXXScopeSpec &ss) : P(p), SS(ss) {} + + void EnterDeclaratorScope() { + if (SS.isSet()) + P.Actions.ActOnCXXEnterDeclaratorScope(P.CurScope, SS); + } + + ~DeclaratorScopeObj() { + if (SS.isSet()) + P.Actions.ActOnCXXExitDeclaratorScope(P.CurScope, SS); + } + }; + + /// ParseDeclarator - Parse and verify a newly-initialized declarator. + void ParseDeclarator(Declarator &D); + /// A function that parses a variant of direct-declarator. + typedef void (Parser::*DirectDeclParseFunction)(Declarator&); + void ParseDeclaratorInternal(Declarator &D, + DirectDeclParseFunction DirectDeclParser); + void ParseTypeQualifierListOpt(DeclSpec &DS, bool AttributesAllowed = true); + void ParseDirectDeclarator(Declarator &D); + void ParseParenDeclarator(Declarator &D); + void ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, + AttributeList *AttrList = 0, + bool RequiresArg = false); + void ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc, + Declarator &D); + void ParseBracketDeclarator(Declarator &D); + + //===--------------------------------------------------------------------===// + // C++ 7: Declarations [dcl.dcl] + + DeclPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd); + DeclPtrTy ParseLinkage(unsigned Context); + DeclPtrTy ParseUsingDirectiveOrDeclaration(unsigned Context, + SourceLocation &DeclEnd); + DeclPtrTy ParseUsingDirective(unsigned Context, SourceLocation UsingLoc, + SourceLocation &DeclEnd); + DeclPtrTy ParseUsingDeclaration(unsigned Context, SourceLocation UsingLoc, + SourceLocation &DeclEnd); + DeclPtrTy ParseStaticAssertDeclaration(SourceLocation &DeclEnd); + DeclPtrTy ParseNamespaceAlias(SourceLocation NamespaceLoc, + SourceLocation AliasLoc, IdentifierInfo *Alias, + SourceLocation &DeclEnd); + + //===--------------------------------------------------------------------===// + // C++ 9: classes [class] and C structs/unions. + TypeResult ParseClassName(SourceLocation &EndLocation, + const CXXScopeSpec *SS = 0); + void ParseClassSpecifier(tok::TokenKind TagTokKind, SourceLocation TagLoc, + DeclSpec &DS, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + AccessSpecifier AS = AS_none); + void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType, + DeclPtrTy TagDecl); + void ParseCXXClassMemberDeclaration(AccessSpecifier AS); + void ParseConstructorInitializer(DeclPtrTy ConstructorDecl); + MemInitResult ParseMemInitializer(DeclPtrTy ConstructorDecl); + + //===--------------------------------------------------------------------===// + // C++ 10: Derived classes [class.derived] + void ParseBaseClause(DeclPtrTy ClassDecl); + BaseResult ParseBaseSpecifier(DeclPtrTy ClassDecl); + AccessSpecifier getAccessSpecifierIfPresent() const; + + //===--------------------------------------------------------------------===// + // C++ 13.5: Overloaded operators [over.oper] + // EndLoc, if non-NULL, is filled with the location of the last token of + // the ID. + OverloadedOperatorKind TryParseOperatorFunctionId(SourceLocation *EndLoc = 0); + TypeTy *ParseConversionFunctionId(SourceLocation *EndLoc = 0); + + //===--------------------------------------------------------------------===// + // C++ 14: Templates [temp] + typedef llvm::SmallVector<DeclPtrTy, 4> TemplateParameterList; + + // C++ 14.1: Template Parameters [temp.param] + DeclPtrTy ParseDeclarationStartingWithTemplate(unsigned Context, + SourceLocation &DeclEnd, + AccessSpecifier AS = AS_none); + DeclPtrTy ParseTemplateDeclarationOrSpecialization(unsigned Context, + SourceLocation &DeclEnd, + AccessSpecifier AS); + DeclPtrTy ParseSingleDeclarationAfterTemplate( + unsigned Context, + const ParsedTemplateInfo &TemplateInfo, + SourceLocation &DeclEnd, + AccessSpecifier AS=AS_none); + bool ParseTemplateParameters(unsigned Depth, + TemplateParameterList &TemplateParams, + SourceLocation &LAngleLoc, + SourceLocation &RAngleLoc); + bool ParseTemplateParameterList(unsigned Depth, + TemplateParameterList &TemplateParams); + DeclPtrTy ParseTemplateParameter(unsigned Depth, unsigned Position); + DeclPtrTy ParseTypeParameter(unsigned Depth, unsigned Position); + DeclPtrTy ParseTemplateTemplateParameter(unsigned Depth, unsigned Position); + DeclPtrTy ParseNonTypeTemplateParameter(unsigned Depth, unsigned Position); + // C++ 14.3: Template arguments [temp.arg] + typedef llvm::SmallVector<void *, 16> TemplateArgList; + typedef llvm::SmallVector<bool, 16> TemplateArgIsTypeList; + typedef llvm::SmallVector<SourceLocation, 16> TemplateArgLocationList; + + bool ParseTemplateIdAfterTemplateName(TemplateTy Template, + SourceLocation TemplateNameLoc, + const CXXScopeSpec *SS, + bool ConsumeLastToken, + SourceLocation &LAngleLoc, + TemplateArgList &TemplateArgs, + TemplateArgIsTypeList &TemplateArgIsType, + TemplateArgLocationList &TemplateArgLocations, + SourceLocation &RAngleLoc); + + void AnnotateTemplateIdToken(TemplateTy Template, TemplateNameKind TNK, + const CXXScopeSpec *SS, + SourceLocation TemplateKWLoc = SourceLocation(), + bool AllowTypeAnnotation = true); + void AnnotateTemplateIdTokenAsType(const CXXScopeSpec *SS = 0); + bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs, + TemplateArgIsTypeList &TemplateArgIsType, + TemplateArgLocationList &TemplateArgLocations); + void *ParseTemplateArgument(bool &ArgIsType); + DeclPtrTy ParseExplicitInstantiation(SourceLocation TemplateLoc, + SourceLocation &DeclEnd); + + //===--------------------------------------------------------------------===// + // GNU G++: Type Traits [Type-Traits.html in the GCC manual] + OwningExprResult ParseUnaryTypeTrait(); +}; + +} // end namespace clang + +#endif |