diff options
Diffstat (limited to 'include/clang/Parse')
-rw-r--r-- | include/clang/Parse/AccessSpecifier.h | 30 | ||||
-rw-r--r-- | include/clang/Parse/Action.h | 1839 | ||||
-rw-r--r-- | include/clang/Parse/AttributeList.h | 173 | ||||
-rw-r--r-- | include/clang/Parse/DeclSpec.h | 1086 | ||||
-rw-r--r-- | include/clang/Parse/Designator.h | 239 | ||||
-rw-r--r-- | include/clang/Parse/Ownership.h | 830 | ||||
-rw-r--r-- | include/clang/Parse/ParseDiagnostic.h | 27 | ||||
-rw-r--r-- | include/clang/Parse/Parser.h | 1208 | ||||
-rw-r--r-- | include/clang/Parse/Scope.h | 310 |
9 files changed, 5742 insertions, 0 deletions
diff --git a/include/clang/Parse/AccessSpecifier.h b/include/clang/Parse/AccessSpecifier.h new file mode 100644 index 0000000..8d2cee8 --- /dev/null +++ b/include/clang/Parse/AccessSpecifier.h @@ -0,0 +1,30 @@ +//===--- AccessSpecifier.h - C++ Access Specifiers -*- 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 interfaces used for C++ access specifiers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_ACCESS_SPECIFIER_H +#define LLVM_CLANG_PARSE_ACCESS_SPECIFIER_H + +namespace clang { + +/// AccessSpecifier - A C++ access specifier (none, public, private, +/// protected). +enum AccessSpecifier { + AS_none, + AS_public, + AS_protected, + AS_private +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h new file mode 100644 index 0000000..5c23f9a --- /dev/null +++ b/include/clang/Parse/Action.h @@ -0,0 +1,1839 @@ +//===--- Action.h - Parser Action Interface ---------------------*- 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 Action and EmptyAction interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_ACTION_H +#define LLVM_CLANG_PARSE_ACTION_H + +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/TemplateKinds.h" +#include "clang/Basic/TypeTraits.h" +#include "clang/Parse/AccessSpecifier.h" +#include "clang/Parse/DeclSpec.h" +#include "clang/Parse/Ownership.h" +#include "llvm/Support/PrettyStackTrace.h" + +namespace clang { + // Semantic. + class DeclSpec; + class ObjCDeclSpec; + class CXXScopeSpec; + class Declarator; + class AttributeList; + struct FieldDeclarator; + // Parse. + class Scope; + class Action; + class Selector; + class Designation; + class InitListDesignations; + // Lex. + class Preprocessor; + class Token; + + // We can re-use the low bit of expression, statement, base, and + // member-initializer pointers for the "invalid" flag of + // ActionResult. + template<> struct IsResultPtrLowBitFree<0> { static const bool value = true;}; + template<> struct IsResultPtrLowBitFree<1> { static const bool value = true;}; + template<> struct IsResultPtrLowBitFree<3> { static const bool value = true;}; + template<> struct IsResultPtrLowBitFree<4> { static const bool value = true;}; + template<> struct IsResultPtrLowBitFree<5> { static const bool value = true;}; + +/// Action - As the parser reads the input file and recognizes the productions +/// of the grammar, it invokes methods on this class to turn the parsed input +/// into something useful: e.g. a parse tree. +/// +/// The callback methods that this class provides are phrased as actions that +/// the parser has just done or is about to do when the method is called. They +/// are not requests that the actions module do the specified action. +/// +/// All of the methods here are optional except getTypeName() and +/// isCurrentClassName(), which must be specified in order for the +/// parse to complete accurately. The MinimalAction class does this +/// bare-minimum of tracking to implement this functionality. +class Action : public ActionBase { +public: + /// Out-of-line virtual destructor to provide home for this class. + virtual ~Action(); + + // Types - Though these don't actually enforce strong typing, they document + // what types are required to be identical for the actions. + typedef ActionBase::ExprTy ExprTy; + typedef ActionBase::StmtTy StmtTy; + + /// Expr/Stmt/Type/BaseResult - Provide a unique type to wrap + /// ExprTy/StmtTy/TypeTy/BaseTy, providing strong typing and + /// allowing for failure. + typedef ActionResult<0> ExprResult; + typedef ActionResult<1> StmtResult; + typedef ActionResult<2> TypeResult; + typedef ActionResult<3> BaseResult; + typedef ActionResult<4> MemInitResult; + typedef ActionResult<5, DeclPtrTy> DeclResult; + + /// Same, but with ownership. + typedef ASTOwningResult<&ActionBase::DeleteExpr> OwningExprResult; + typedef ASTOwningResult<&ActionBase::DeleteStmt> OwningStmtResult; + // Note that these will replace ExprResult and StmtResult when the transition + // is complete. + + /// Single expressions or statements as arguments. +#if !defined(DISABLE_SMART_POINTERS) + typedef ASTOwningResult<&ActionBase::DeleteExpr> ExprArg; + typedef ASTOwningResult<&ActionBase::DeleteStmt> StmtArg; +#else + typedef ASTOwningPtr<&ActionBase::DeleteExpr> ExprArg; + typedef ASTOwningPtr<&ActionBase::DeleteStmt> StmtArg; +#endif + + /// Multiple expressions or statements as arguments. + typedef ASTMultiPtr<&ActionBase::DeleteExpr> MultiExprArg; + typedef ASTMultiPtr<&ActionBase::DeleteStmt> MultiStmtArg; + typedef ASTMultiPtr<&ActionBase::DeleteTemplateParams> MultiTemplateParamsArg; + + class FullExprArg { + public: + // FIXME: The const_cast here is ugly. RValue references would make this + // much nicer (or we could duplicate a bunch of the move semantics + // emulation code from Ownership.h). + FullExprArg(const FullExprArg& Other) + : Expr(move(const_cast<FullExprArg&>(Other).Expr)) {} + + OwningExprResult release() { + return move(Expr); + } + + ExprArg* operator->() { + return &Expr; + } + + private: + // FIXME: No need to make the entire Action class a friend when it's just + // Action::FullExpr that needs access to the constructor below. + friend class Action; + + explicit FullExprArg(ExprArg expr) + : Expr(move(expr)) {} + + ExprArg Expr; + }; + + template<typename T> + FullExprArg FullExpr(T &Arg) { + return FullExprArg(ActOnFinishFullExpr(move(Arg))); + } + + // Utilities for Action implementations to return smart results. + + OwningExprResult ExprError() { return OwningExprResult(*this, true); } + OwningStmtResult StmtError() { return OwningStmtResult(*this, true); } + + OwningExprResult ExprError(const DiagnosticBuilder&) { return ExprError(); } + OwningStmtResult StmtError(const DiagnosticBuilder&) { return StmtError(); } + + OwningExprResult ExprEmpty() { return OwningExprResult(*this, false); } + OwningStmtResult StmtEmpty() { return OwningStmtResult(*this, false); } + + /// Statistics. + virtual void PrintStats() const {} + + /// getDeclName - Return a pretty name for the specified decl if possible, or + /// an empty string if not. This is used for pretty crash reporting. + virtual std::string getDeclName(DeclPtrTy D) { return ""; } + + //===--------------------------------------------------------------------===// + // Declaration Tracking Callbacks. + //===--------------------------------------------------------------------===// + + /// ConvertDeclToDeclGroup - If the parser has one decl in a context where it + /// needs a decl group, it calls this to convert between the two + /// representations. + virtual DeclGroupPtrTy ConvertDeclToDeclGroup(DeclPtrTy Ptr) { + return DeclGroupPtrTy(); + } + + /// getTypeName - Return non-null if the specified identifier is a type name + /// in the current scope. + /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or + /// namespace) that the identifier must be a member of. + /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::". + virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, const CXXScopeSpec *SS = 0) = 0; + + /// isTagName() - This method is called *for error recovery purposes only* + /// to determine if the specified name is a valid tag name ("struct foo"). If + /// so, this returns the TST for the tag corresponding to it (TST_enum, + /// TST_union, TST_struct, TST_class). This is used to diagnose cases in C + /// where the user forgot to specify the tag. + virtual DeclSpec::TST isTagName(IdentifierInfo &II, Scope *S) { + return DeclSpec::TST_unspecified; + } + + /// isCurrentClassName - Return true if the specified name is the + /// name of the innermost C++ class type currently being defined. + virtual bool isCurrentClassName(const IdentifierInfo &II, Scope *S, + const CXXScopeSpec *SS = 0) = 0; + + /// \brief Determines whether the identifier II is a template name + /// in the current scope. If so, the kind of template name is + /// returned, and \p TemplateDecl receives the declaration. An + /// optional CXXScope can be passed to indicate the C++ scope in + /// which the identifier will be found. + virtual TemplateNameKind isTemplateName(const IdentifierInfo &II, Scope *S, + TemplateTy &Template, + const CXXScopeSpec *SS = 0) = 0; + + /// ActOnCXXGlobalScopeSpecifier - Return the object that represents the + /// global scope ('::'). + virtual CXXScopeTy *ActOnCXXGlobalScopeSpecifier(Scope *S, + SourceLocation CCLoc) { + return 0; + } + + /// ActOnCXXNestedNameSpecifier - Called during parsing of a + /// nested-name-specifier. e.g. for "foo::bar::" we parsed "foo::" and now + /// we want to resolve "bar::". 'SS' is empty or the previously parsed + /// nested-name part ("foo::"), 'IdLoc' is the source location of 'bar', + /// 'CCLoc' is the location of '::' and 'II' is the identifier for 'bar'. + /// Returns a CXXScopeTy* object representing the C++ scope. + virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, + const CXXScopeSpec &SS, + SourceLocation IdLoc, + SourceLocation CCLoc, + IdentifierInfo &II) { + return 0; + } + + /// ActOnCXXNestedNameSpecifier - Called during parsing of a + /// nested-name-specifier that involves a template-id, e.g., + /// "foo::bar<int, float>::", and now we need to build a scope + /// specifier. \p SS is empty or the previously parsed nested-name + /// part ("foo::"), \p Type is the already-parsed class template + /// specialization (or other template-id that names a type), \p + /// TypeRange is the source range where the type is located, and \p + /// CCLoc is the location of the trailing '::'. + virtual CXXScopeTy *ActOnCXXNestedNameSpecifier(Scope *S, + const CXXScopeSpec &SS, + TypeTy *Type, + SourceRange TypeRange, + SourceLocation CCLoc) { + return 0; + } + + /// ActOnCXXEnterDeclaratorScope - Called when a C++ scope specifier (global + /// scope or nested-name-specifier) is parsed, part of a declarator-id. + /// After this method is called, according to [C++ 3.4.3p3], names should be + /// looked up in the declarator-id's scope, until the declarator is parsed and + /// ActOnCXXExitDeclaratorScope is called. + /// The 'SS' should be a non-empty valid CXXScopeSpec. + virtual void ActOnCXXEnterDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { + } + + /// ActOnCXXExitDeclaratorScope - Called when a declarator that previously + /// invoked ActOnCXXEnterDeclaratorScope(), is finished. 'SS' is the same + /// CXXScopeSpec that was passed to ActOnCXXEnterDeclaratorScope as well. + /// Used to indicate that names should revert to being looked up in the + /// defining scope. + virtual void ActOnCXXExitDeclaratorScope(Scope *S, const CXXScopeSpec &SS) { + } + + /// ActOnDeclarator - This callback is invoked when a declarator is parsed and + /// 'Init' specifies the initializer if any. This is for things like: + /// "int X = 4" or "typedef int foo". + /// + virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D) { + return DeclPtrTy(); + } + + /// ActOnParamDeclarator - This callback is invoked when a parameter + /// declarator is parsed. This callback only occurs for functions + /// with prototypes. S is the function prototype scope for the + /// parameters (C++ [basic.scope.proto]). + virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D) { + return DeclPtrTy(); + } + + /// AddInitializerToDecl - This action is called immediately after + /// ActOnDeclarator (when an initializer is present). The code is factored + /// this way to make sure we are able to handle the following: + /// void func() { int xx = xx; } + /// This allows ActOnDeclarator to register "xx" prior to parsing the + /// initializer. The declaration above should still result in a warning, + /// since the reference to "xx" is uninitialized. + virtual void AddInitializerToDecl(DeclPtrTy Dcl, FullExprArg Init) { + return; + } + + /// SetDeclDeleted - This action is called immediately after ActOnDeclarator + /// if =delete is parsed. C++0x [dcl.fct.def]p10 + /// Note that this can be called even for variable declarations. It's the + /// action's job to reject it. + virtual void SetDeclDeleted(DeclPtrTy Dcl, SourceLocation DelLoc) { + return; + } + + /// ActOnUninitializedDecl - This action is called immediately after + /// ActOnDeclarator (when an initializer is *not* present). + virtual void ActOnUninitializedDecl(DeclPtrTy Dcl) { + return; + } + + /// FinalizeDeclaratorGroup - After a sequence of declarators are parsed, this + /// gives the actions implementation a chance to process the group as a whole. + virtual DeclGroupPtrTy FinalizeDeclaratorGroup(Scope *S, const DeclSpec& DS, + DeclPtrTy *Group, + unsigned NumDecls) { + return DeclGroupPtrTy(); + } + + + /// @brief Indicates that all K&R-style parameter declarations have + /// been parsed prior to a function definition. + /// @param S The function prototype scope. + /// @param D The function declarator. + virtual void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D, + SourceLocation LocAfterDecls) { + } + + /// ActOnStartOfFunctionDef - This is called at the start of a function + /// definition, instead of calling ActOnDeclarator. The Declarator includes + /// information about formal arguments that are part of this function. + virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) { + // Default to ActOnDeclarator. + return ActOnStartOfFunctionDef(FnBodyScope, + ActOnDeclarator(FnBodyScope, D)); + } + + /// ActOnStartOfFunctionDef - This is called at the start of a function + /// definition, after the FunctionDecl has already been created. + virtual DeclPtrTy ActOnStartOfFunctionDef(Scope *FnBodyScope, DeclPtrTy D) { + return D; + } + + virtual void ActOnStartOfObjCMethodDef(Scope *FnBodyScope, DeclPtrTy D) { + return; + } + + /// ActOnFinishFunctionBody - This is called when a function body has + /// completed parsing. Decl is returned by ParseStartOfFunctionDef. + virtual DeclPtrTy ActOnFinishFunctionBody(DeclPtrTy Decl, StmtArg Body) { + return Decl; + } + + virtual DeclPtrTy ActOnFileScopeAsmDecl(SourceLocation Loc, + ExprArg AsmString) { + return DeclPtrTy(); + } + + /// ActOnPopScope - This callback is called immediately before the specified + /// scope is popped and deleted. + virtual void ActOnPopScope(SourceLocation Loc, Scope *S) {} + + /// ActOnTranslationUnitScope - This callback is called once, immediately + /// after creating the translation unit scope (in Parser::Initialize). + virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S) {} + + /// ParsedFreeStandingDeclSpec - This method is invoked when a declspec with + /// no declarator (e.g. "struct foo;") is parsed. + virtual DeclPtrTy ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) { + return DeclPtrTy(); + } + + /// ActOnStartLinkageSpecification - Parsed the beginning of a C++ + /// linkage specification, including the language and (if present) + /// the '{'. ExternLoc is the location of the 'extern', LangLoc is + /// the location of the language string literal, which is provided + /// by Lang/StrSize. LBraceLoc, if valid, provides the location of + /// the '{' brace. Otherwise, this linkage specification does not + /// have any braces. + virtual DeclPtrTy ActOnStartLinkageSpecification(Scope *S, + SourceLocation ExternLoc, + SourceLocation LangLoc, + const char *Lang, + unsigned StrSize, + SourceLocation LBraceLoc) { + return DeclPtrTy(); + } + + /// ActOnFinishLinkageSpecification - Completely the definition of + /// the C++ linkage specification LinkageSpec. If RBraceLoc is + /// valid, it's the position of the closing '}' brace in a linkage + /// specification that uses braces. + virtual DeclPtrTy ActOnFinishLinkageSpecification(Scope *S, + DeclPtrTy LinkageSpec, + SourceLocation RBraceLoc) { + return LinkageSpec; + } + + /// ActOnEndOfTranslationUnit - This is called at the very end of the + /// translation unit when EOF is reached and all but the top-level scope is + /// popped. + virtual void ActOnEndOfTranslationUnit() {} + + //===--------------------------------------------------------------------===// + // Type Parsing Callbacks. + //===--------------------------------------------------------------------===// + + /// ActOnTypeName - A type-name (type-id in C++) was parsed. + virtual TypeResult ActOnTypeName(Scope *S, Declarator &D) { + return TypeResult(); + } + + enum TagKind { + TK_Reference, // Reference to a tag: 'struct foo *X;' + TK_Declaration, // Fwd decl of a tag: 'struct foo;' + TK_Definition // Definition of a tag: 'struct foo { int X; } Y;' + }; + virtual DeclPtrTy ActOnTag(Scope *S, unsigned TagSpec, TagKind TK, + SourceLocation KWLoc, const CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr, AccessSpecifier AS, + bool &OwnedDecl) { + // TagType is an instance of DeclSpec::TST, indicating what kind of tag this + // is (struct/union/enum/class). + return DeclPtrTy(); + } + + /// Act on @defs() element found when parsing a structure. ClassName is the + /// name of the referenced class. + virtual void ActOnDefs(Scope *S, DeclPtrTy TagD, SourceLocation DeclStart, + IdentifierInfo *ClassName, + llvm::SmallVectorImpl<DeclPtrTy> &Decls) {} + virtual DeclPtrTy ActOnField(Scope *S, DeclPtrTy TagD, + SourceLocation DeclStart, + Declarator &D, ExprTy *BitfieldWidth) { + return DeclPtrTy(); + } + + virtual DeclPtrTy ActOnIvar(Scope *S, SourceLocation DeclStart, + Declarator &D, ExprTy *BitfieldWidth, + tok::ObjCKeywordKind visibility) { + return DeclPtrTy(); + } + + virtual void ActOnFields(Scope* S, SourceLocation RecLoc, DeclPtrTy TagDecl, + DeclPtrTy *Fields, unsigned NumFields, + SourceLocation LBrac, SourceLocation RBrac, + AttributeList *AttrList) {} + + /// ActOnTagStartDefinition - Invoked when we have entered the + /// scope of a tag's definition (e.g., for an enumeration, class, + /// struct, or union). + virtual void ActOnTagStartDefinition(Scope *S, DeclPtrTy TagDecl) { } + + /// ActOnTagFinishDefinition - Invoked once we have finished parsing + /// the definition of a tag (enumeration, class, struct, or union). + virtual void ActOnTagFinishDefinition(Scope *S, DeclPtrTy TagDecl) { } + + virtual DeclPtrTy ActOnEnumConstant(Scope *S, DeclPtrTy EnumDecl, + DeclPtrTy LastEnumConstant, + SourceLocation IdLoc, IdentifierInfo *Id, + SourceLocation EqualLoc, ExprTy *Val) { + return DeclPtrTy(); + } + virtual void ActOnEnumBody(SourceLocation EnumLoc, SourceLocation LBraceLoc, + SourceLocation RBraceLoc, DeclPtrTy EnumDecl, + DeclPtrTy *Elements, unsigned NumElements) {} + + //===--------------------------------------------------------------------===// + // Statement Parsing Callbacks. + //===--------------------------------------------------------------------===// + + virtual OwningStmtResult ActOnNullStmt(SourceLocation SemiLoc) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, + MultiStmtArg Elts, + bool isStmtExpr) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, + SourceLocation StartLoc, + SourceLocation EndLoc) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnExprStmt(FullExprArg Expr) { + return OwningStmtResult(*this, Expr->release()); + } + + /// ActOnCaseStmt - Note that this handles the GNU 'case 1 ... 4' extension, + /// which can specify an RHS value. The sub-statement of the case is + /// specified in a separate action. + virtual OwningStmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprArg LHSVal, + SourceLocation DotDotDotLoc, + ExprArg RHSVal, + SourceLocation ColonLoc) { + return StmtEmpty(); + } + + /// ActOnCaseStmtBody - This installs a statement as the body of a case. + virtual void ActOnCaseStmtBody(StmtTy *CaseStmt, StmtArg SubStmt) {} + + virtual OwningStmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, + SourceLocation ColonLoc, + StmtArg SubStmt, Scope *CurScope){ + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnLabelStmt(SourceLocation IdentLoc, + IdentifierInfo *II, + SourceLocation ColonLoc, + StmtArg SubStmt) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnIfStmt(SourceLocation IfLoc, + FullExprArg CondVal, StmtArg ThenVal, + SourceLocation ElseLoc, + StmtArg ElseVal) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnStartOfSwitchStmt(ExprArg Cond) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnFinishSwitchStmt(SourceLocation SwitchLoc, + StmtArg Switch, StmtArg Body) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnWhileStmt(SourceLocation WhileLoc, + FullExprArg Cond, StmtArg Body) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnDoStmt(SourceLocation DoLoc, StmtArg Body, + SourceLocation WhileLoc, ExprArg Cond) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnForStmt(SourceLocation ForLoc, + SourceLocation LParenLoc, + StmtArg First, ExprArg Second, + ExprArg Third, SourceLocation RParenLoc, + StmtArg Body) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnObjCForCollectionStmt(SourceLocation ForColLoc, + SourceLocation LParenLoc, + StmtArg First, ExprArg Second, + SourceLocation RParenLoc, StmtArg Body) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnGotoStmt(SourceLocation GotoLoc, + SourceLocation LabelLoc, + IdentifierInfo *LabelII) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnIndirectGotoStmt(SourceLocation GotoLoc, + SourceLocation StarLoc, + ExprArg DestExp) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnContinueStmt(SourceLocation ContinueLoc, + Scope *CurScope) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnBreakStmt(SourceLocation GotoLoc, + Scope *CurScope) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnReturnStmt(SourceLocation ReturnLoc, + FullExprArg RetValExp) { + return StmtEmpty(); + } + virtual OwningStmtResult ActOnAsmStmt(SourceLocation AsmLoc, + bool IsSimple, + bool IsVolatile, + unsigned NumOutputs, + unsigned NumInputs, + std::string *Names, + MultiExprArg Constraints, + MultiExprArg Exprs, + ExprArg AsmString, + MultiExprArg Clobbers, + SourceLocation RParenLoc) { + return StmtEmpty(); + } + + // Objective-c statements + virtual OwningStmtResult ActOnObjCAtCatchStmt(SourceLocation AtLoc, + SourceLocation RParen, + DeclPtrTy Parm, StmtArg Body, + StmtArg CatchList) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnObjCAtFinallyStmt(SourceLocation AtLoc, + StmtArg Body) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnObjCAtTryStmt(SourceLocation AtLoc, + StmtArg Try, StmtArg Catch, + StmtArg Finally) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnObjCAtThrowStmt(SourceLocation AtLoc, + ExprArg Throw, + Scope *CurScope) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnObjCAtSynchronizedStmt(SourceLocation AtLoc, + ExprArg SynchExpr, + StmtArg SynchBody) { + return StmtEmpty(); + } + + // C++ Statements + virtual DeclPtrTy ActOnExceptionDeclarator(Scope *S, Declarator &D) { + return DeclPtrTy(); + } + + virtual OwningStmtResult ActOnCXXCatchBlock(SourceLocation CatchLoc, + DeclPtrTy ExceptionDecl, + StmtArg HandlerBlock) { + return StmtEmpty(); + } + + virtual OwningStmtResult ActOnCXXTryBlock(SourceLocation TryLoc, + StmtArg TryBlock, + MultiStmtArg Handlers) { + return StmtEmpty(); + } + + //===--------------------------------------------------------------------===// + // Expression Parsing Callbacks. + //===--------------------------------------------------------------------===// + + // Primary Expressions. + + /// \brief Retrieve the source range that corresponds to the given + /// expression. + virtual SourceRange getExprRange(ExprTy *E) const { + return SourceRange(); + } + + /// ActOnIdentifierExpr - Parse an identifier in expression context. + /// 'HasTrailingLParen' indicates whether or not the identifier has a '(' + /// token immediately after it. + /// An optional CXXScopeSpec can be passed to indicate the C++ scope (class or + /// namespace) that the identifier must be a member of. + /// i.e. for "foo::bar", 'II' will be "bar" and 'SS' will be "foo::". + virtual OwningExprResult ActOnIdentifierExpr(Scope *S, SourceLocation Loc, + IdentifierInfo &II, + bool HasTrailingLParen, + const CXXScopeSpec *SS = 0, + bool isAddressOfOperand = false){ + return ExprEmpty(); + } + + /// ActOnOperatorFunctionIdExpr - Parse a C++ overloaded operator + /// name (e.g., @c operator+ ) as an expression. This is very + /// similar to ActOnIdentifierExpr, except that instead of providing + /// an identifier the parser provides the kind of overloaded + /// operator that was parsed. + virtual OwningExprResult ActOnCXXOperatorFunctionIdExpr( + Scope *S, SourceLocation OperatorLoc, + OverloadedOperatorKind Op, + bool HasTrailingLParen, const CXXScopeSpec &SS, + bool isAddressOfOperand = false) { + return ExprEmpty(); + } + + /// ActOnCXXConversionFunctionExpr - Parse a C++ conversion function + /// name (e.g., @c operator void const *) as an expression. This is + /// very similar to ActOnIdentifierExpr, except that instead of + /// providing an identifier the parser provides the type of the + /// conversion function. + virtual OwningExprResult ActOnCXXConversionFunctionExpr( + Scope *S, SourceLocation OperatorLoc, + TypeTy *Type, bool HasTrailingLParen, + const CXXScopeSpec &SS, + bool isAddressOfOperand = false) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnPredefinedExpr(SourceLocation Loc, + tok::TokenKind Kind) { + return ExprEmpty(); + } + virtual OwningExprResult ActOnCharacterConstant(const Token &) { + return ExprEmpty(); + } + virtual OwningExprResult ActOnNumericConstant(const Token &) { + return ExprEmpty(); + } + + /// ActOnStringLiteral - The specified tokens were lexed as pasted string + /// fragments (e.g. "foo" "bar" L"baz"). + virtual OwningExprResult ActOnStringLiteral(const Token *Toks, + unsigned NumToks) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnParenExpr(SourceLocation L, SourceLocation R, + ExprArg Val) { + return move(Val); // Default impl returns operand. + } + + // Postfix Expressions. + virtual OwningExprResult ActOnPostfixUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Kind, + ExprArg Input) { + return ExprEmpty(); + } + virtual OwningExprResult ActOnArraySubscriptExpr(Scope *S, ExprArg Base, + SourceLocation LLoc, + ExprArg Idx, + SourceLocation RLoc) { + return ExprEmpty(); + } + virtual OwningExprResult ActOnMemberReferenceExpr(Scope *S, ExprArg Base, + SourceLocation OpLoc, + tok::TokenKind OpKind, + SourceLocation MemberLoc, + IdentifierInfo &Member, + DeclPtrTy ObjCImpDecl) { + return ExprEmpty(); + } + + /// ActOnCallExpr - Handle a call to Fn with the specified array of arguments. + /// This provides the location of the left/right parens and a list of comma + /// locations. There are guaranteed to be one fewer commas than arguments, + /// unless there are zero arguments. + virtual OwningExprResult ActOnCallExpr(Scope *S, ExprArg Fn, + SourceLocation LParenLoc, + MultiExprArg Args, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + + // Unary Operators. 'Tok' is the token for the operator. + virtual OwningExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, + tok::TokenKind Op, ExprArg Input) { + return ExprEmpty(); + } + virtual OwningExprResult + ActOnSizeOfAlignOfExpr(SourceLocation OpLoc, bool isSizeof, bool isType, + void *TyOrEx, const SourceRange &ArgRange) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnCompoundLiteral(SourceLocation LParen, + TypeTy *Ty, + SourceLocation RParen, + ExprArg Op) { + return ExprEmpty(); + } + virtual OwningExprResult ActOnInitList(SourceLocation LParenLoc, + MultiExprArg InitList, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + /// @brief Parsed a C99 designated initializer. + /// + /// @param Desig Contains the designation with one or more designators. + /// + /// @param Loc The location of the '=' or ':' prior to the + /// initialization expression. + /// + /// @param GNUSyntax If true, then this designated initializer used + /// the deprecated GNU syntax @c fieldname:foo or @c [expr]foo rather + /// than the C99 syntax @c .fieldname=foo or @c [expr]=foo. + /// + /// @param Init The value that the entity (or entities) described by + /// the designation will be initialized with. + virtual OwningExprResult ActOnDesignatedInitializer(Designation &Desig, + SourceLocation Loc, + bool GNUSyntax, + OwningExprResult Init) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnCastExpr(SourceLocation LParenLoc, TypeTy *Ty, + SourceLocation RParenLoc, ExprArg Op) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, + tok::TokenKind Kind, + ExprArg LHS, ExprArg RHS) { + return ExprEmpty(); + } + + /// ActOnConditionalOp - Parse a ?: operation. Note that 'LHS' may be null + /// in the case of a the GNU conditional expr extension. + virtual OwningExprResult ActOnConditionalOp(SourceLocation QuestionLoc, + SourceLocation ColonLoc, + ExprArg Cond, ExprArg LHS, + ExprArg RHS) { + return ExprEmpty(); + } + + //===---------------------- GNU Extension Expressions -------------------===// + + virtual OwningExprResult ActOnAddrLabel(SourceLocation OpLoc, + SourceLocation LabLoc, + IdentifierInfo *LabelII) { // "&&foo" + return ExprEmpty(); + } + + virtual OwningExprResult ActOnStmtExpr(SourceLocation LPLoc, StmtArg SubStmt, + SourceLocation RPLoc) { // "({..})" + return ExprEmpty(); + } + + // __builtin_offsetof(type, identifier(.identifier|[expr])*) + struct OffsetOfComponent { + SourceLocation LocStart, LocEnd; + bool isBrackets; // true if [expr], false if .ident + union { + IdentifierInfo *IdentInfo; + ExprTy *E; + } U; + }; + + virtual OwningExprResult ActOnBuiltinOffsetOf(Scope *S, + SourceLocation BuiltinLoc, + SourceLocation TypeLoc, + TypeTy *Arg1, + OffsetOfComponent *CompPtr, + unsigned NumComponents, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + + // __builtin_types_compatible_p(type1, type2) + virtual OwningExprResult ActOnTypesCompatibleExpr(SourceLocation BuiltinLoc, + TypeTy *arg1, TypeTy *arg2, + SourceLocation RPLoc) { + return ExprEmpty(); + } + // __builtin_choose_expr(constExpr, expr1, expr2) + virtual OwningExprResult ActOnChooseExpr(SourceLocation BuiltinLoc, + ExprArg cond, ExprArg expr1, + ExprArg expr2, SourceLocation RPLoc){ + return ExprEmpty(); + } + + // __builtin_va_arg(expr, type) + virtual OwningExprResult ActOnVAArg(SourceLocation BuiltinLoc, + ExprArg expr, TypeTy *type, + SourceLocation RPLoc) { + return ExprEmpty(); + } + + /// ActOnGNUNullExpr - Parsed the GNU __null expression, the token + /// for which is at position TokenLoc. + virtual OwningExprResult ActOnGNUNullExpr(SourceLocation TokenLoc) { + return ExprEmpty(); + } + + //===------------------------- "Block" Extension ------------------------===// + + /// ActOnBlockStart - This callback is invoked when a block literal is + /// started. The result pointer is passed into the block finalizers. + virtual void ActOnBlockStart(SourceLocation CaretLoc, Scope *CurScope) {} + + /// ActOnBlockArguments - This callback allows processing of block arguments. + /// If there are no arguments, this is still invoked. + virtual void ActOnBlockArguments(Declarator &ParamInfo, Scope *CurScope) {} + + /// ActOnBlockError - If there is an error parsing a block, this callback + /// is invoked to pop the information about the block from the action impl. + virtual void ActOnBlockError(SourceLocation CaretLoc, Scope *CurScope) {} + + /// ActOnBlockStmtExpr - This is called when the body of a block statement + /// literal was successfully completed. ^(int x){...} + virtual OwningExprResult ActOnBlockStmtExpr(SourceLocation CaretLoc, + StmtArg Body, + Scope *CurScope) { + return ExprEmpty(); + } + + //===------------------------- C++ Declarations -------------------------===// + + /// ActOnStartNamespaceDef - This is called at the start of a namespace + /// definition. + virtual DeclPtrTy ActOnStartNamespaceDef(Scope *S, SourceLocation IdentLoc, + IdentifierInfo *Ident, + SourceLocation LBrace) { + return DeclPtrTy(); + } + + /// ActOnFinishNamespaceDef - This callback is called after a namespace is + /// exited. Decl is returned by ActOnStartNamespaceDef. + virtual void ActOnFinishNamespaceDef(DeclPtrTy Dcl, SourceLocation RBrace) { + return; + } + + /// ActOnUsingDirective - This is called when using-directive is parsed. + virtual DeclPtrTy ActOnUsingDirective(Scope *CurScope, + SourceLocation UsingLoc, + SourceLocation NamespcLoc, + const CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *NamespcName, + AttributeList *AttrList); + + /// ActOnNamespaceAliasDef - This is called when a namespace alias definition + /// is parsed. + virtual DeclPtrTy ActOnNamespaceAliasDef(Scope *CurScope, + SourceLocation NamespaceLoc, + SourceLocation AliasLoc, + IdentifierInfo *Alias, + const CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *Ident) { + return DeclPtrTy(); + } + + /// ActOnParamDefaultArgument - Parse default argument for function parameter + virtual void ActOnParamDefaultArgument(DeclPtrTy param, + SourceLocation EqualLoc, + ExprArg defarg) { + } + + /// ActOnParamUnparsedDefaultArgument - We've seen a default + /// argument for a function parameter, but we can't parse it yet + /// because we're inside a class definition. Note that this default + /// argument will be parsed later. + virtual void ActOnParamUnparsedDefaultArgument(DeclPtrTy param, + SourceLocation EqualLoc) { } + + /// ActOnParamDefaultArgumentError - Parsing or semantic analysis of + /// the default argument for the parameter param failed. + virtual void ActOnParamDefaultArgumentError(DeclPtrTy param) { } + + /// AddCXXDirectInitializerToDecl - This action is called immediately after + /// ActOnDeclarator, when a C++ direct initializer is present. + /// e.g: "int x(1);" + virtual void AddCXXDirectInitializerToDecl(DeclPtrTy Dcl, + SourceLocation LParenLoc, + MultiExprArg Exprs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { + return; + } + + /// \brief Called when we re-enter a template parameter scope. + /// + /// This action occurs when we are going to parse an member + /// function's default arguments or inline definition after the + /// outermost class definition has been completed, and when one or + /// more of the class definitions enclosing the member function is a + /// template. The "entity" in the given scope will be set as it was + /// when we entered the scope of the template initially, and should + /// be used to, e.g., reintroduce the names of template parameters + /// into the current scope so that they can be found by name lookup. + /// + /// \param S The (new) template parameter scope. + /// + /// \param Template the class template declaration whose template + /// parameters should be reintroduced into the current scope. + virtual void ActOnReenterTemplateScope(Scope *S, DeclPtrTy Template) { + } + + /// ActOnStartDelayedCXXMethodDeclaration - We have completed + /// parsing a top-level (non-nested) C++ class, and we are now + /// parsing those parts of the given Method declaration that could + /// not be parsed earlier (C++ [class.mem]p2), such as default + /// arguments. This action should enter the scope of the given + /// Method declaration as if we had just parsed the qualified method + /// name. However, it should not bring the parameters into scope; + /// that will be performed by ActOnDelayedCXXMethodParameter. + virtual void ActOnStartDelayedCXXMethodDeclaration(Scope *S, + DeclPtrTy Method) { + } + + /// ActOnDelayedCXXMethodParameter - We've already started a delayed + /// C++ method declaration. We're (re-)introducing the given + /// function parameter into scope for use in parsing later parts of + /// the method declaration. For example, we could see an + /// ActOnParamDefaultArgument event for this parameter. + virtual void ActOnDelayedCXXMethodParameter(Scope *S, DeclPtrTy Param) { + } + + /// ActOnFinishDelayedCXXMethodDeclaration - We have finished + /// processing the delayed method declaration for Method. The method + /// declaration is now considered finished. There may be a separate + /// ActOnStartOfFunctionDef action later (not necessarily + /// immediately!) for this method, if it was also defined inside the + /// class body. + virtual void ActOnFinishDelayedCXXMethodDeclaration(Scope *S, + DeclPtrTy Method) { + } + + /// ActOnStaticAssertDeclaration - Parse a C++0x static_assert declaration. + virtual DeclPtrTy ActOnStaticAssertDeclaration(SourceLocation AssertLoc, + ExprArg AssertExpr, + ExprArg AssertMessageExpr) { + return DeclPtrTy(); + } + + /// ActOnFriendDecl - This action is called when a friend declaration is + /// encountered. Returns false on success. + virtual bool ActOnFriendDecl(Scope *S, SourceLocation FriendLoc, + DeclPtrTy Dcl) { + return false; + } + + + //===------------------------- C++ Expressions --------------------------===// + + /// ActOnCXXNamedCast - Parse {dynamic,static,reinterpret,const}_cast's. + virtual OwningExprResult ActOnCXXNamedCast(SourceLocation OpLoc, + tok::TokenKind Kind, + SourceLocation LAngleBracketLoc, + TypeTy *Ty, + SourceLocation RAngleBracketLoc, + SourceLocation LParenLoc, + ExprArg Op, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + + /// ActOnCXXTypeidOfType - Parse typeid( type-id ). + virtual OwningExprResult ActOnCXXTypeid(SourceLocation OpLoc, + SourceLocation LParenLoc, bool isType, + void *TyOrExpr, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + + /// ActOnCXXThis - Parse the C++ 'this' pointer. + virtual OwningExprResult ActOnCXXThis(SourceLocation ThisLoc) { + return ExprEmpty(); + } + + /// ActOnCXXBoolLiteral - Parse {true,false} literals. + virtual OwningExprResult ActOnCXXBoolLiteral(SourceLocation OpLoc, + tok::TokenKind Kind) { + return ExprEmpty(); + } + + /// ActOnCXXNullPtrLiteral - Parse 'nullptr'. + virtual OwningExprResult ActOnCXXNullPtrLiteral(SourceLocation Loc) { + return ExprEmpty(); + } + + /// ActOnCXXThrow - Parse throw expressions. + virtual OwningExprResult ActOnCXXThrow(SourceLocation OpLoc, ExprArg Op) { + return ExprEmpty(); + } + + /// ActOnCXXTypeConstructExpr - Parse construction of a specified type. + /// Can be interpreted either as function-style casting ("int(x)") + /// or class type construction ("ClassType(x,y,z)") + /// or creation of a value-initialized type ("int()"). + virtual OwningExprResult ActOnCXXTypeConstructExpr(SourceRange TypeRange, + TypeTy *TypeRep, + SourceLocation LParenLoc, + MultiExprArg Exprs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { + return ExprEmpty(); + } + + /// ActOnCXXConditionDeclarationExpr - Parsed a condition declaration of a + /// C++ if/switch/while/for statement. + /// e.g: "if (int x = f()) {...}" + virtual OwningExprResult ActOnCXXConditionDeclarationExpr(Scope *S, + SourceLocation StartLoc, + Declarator &D, + SourceLocation EqualLoc, + ExprArg AssignExprVal) { + return ExprEmpty(); + } + + /// ActOnCXXNew - Parsed a C++ 'new' expression. UseGlobal is true if the + /// new was qualified (::new). In a full new like + /// @code new (p1, p2) type(c1, c2) @endcode + /// the p1 and p2 expressions will be in PlacementArgs and the c1 and c2 + /// expressions in ConstructorArgs. The type is passed as a declarator. + virtual OwningExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, + SourceLocation PlacementLParen, + MultiExprArg PlacementArgs, + SourceLocation PlacementRParen, + bool ParenTypeId, Declarator &D, + SourceLocation ConstructorLParen, + MultiExprArg ConstructorArgs, + SourceLocation ConstructorRParen) { + return ExprEmpty(); + } + + /// ActOnCXXDelete - Parsed a C++ 'delete' expression. UseGlobal is true if + /// the delete was qualified (::delete). ArrayForm is true if the array form + /// was used (delete[]). + virtual OwningExprResult ActOnCXXDelete(SourceLocation StartLoc, + bool UseGlobal, bool ArrayForm, + ExprArg Operand) { + return ExprEmpty(); + } + + virtual OwningExprResult ActOnUnaryTypeTrait(UnaryTypeTrait OTT, + SourceLocation KWLoc, + SourceLocation LParen, + TypeTy *Ty, + SourceLocation RParen) { + return ExprEmpty(); + } + + + /// ActOnFinishFullExpr - Called whenever a full expression has been parsed. + /// (C++ [intro.execution]p12). + virtual OwningExprResult ActOnFinishFullExpr(ExprArg Expr) { + return move(Expr); + } + + //===---------------------------- C++ Classes ---------------------------===// + /// ActOnBaseSpecifier - Parsed a base specifier + virtual BaseResult ActOnBaseSpecifier(DeclPtrTy classdecl, + SourceRange SpecifierRange, + bool Virtual, AccessSpecifier Access, + TypeTy *basetype, + SourceLocation BaseLoc) { + return BaseResult(); + } + + virtual void ActOnBaseSpecifiers(DeclPtrTy ClassDecl, BaseTy **Bases, + unsigned NumBases) { + } + + /// ActOnCXXMemberDeclarator - This is invoked when a C++ class member + /// declarator is parsed. 'AS' is the access specifier, 'BitfieldWidth' + /// specifies the bitfield width if there is one and 'Init' specifies the + /// initializer if any. 'Deleted' is true if there's a =delete + /// specifier on the function. + virtual DeclPtrTy ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, + Declarator &D, + ExprTy *BitfieldWidth, + ExprTy *Init, + bool Deleted = false) { + return DeclPtrTy(); + } + + virtual MemInitResult ActOnMemInitializer(DeclPtrTy ConstructorDecl, + Scope *S, + IdentifierInfo *MemberOrBase, + SourceLocation IdLoc, + SourceLocation LParenLoc, + ExprTy **Args, unsigned NumArgs, + SourceLocation *CommaLocs, + SourceLocation RParenLoc) { + return true; + } + + /// ActOnMemInitializers - This is invoked when all of the member + /// initializers of a constructor have been parsed. ConstructorDecl + /// is the function declaration (which will be a C++ constructor in + /// a well-formed program), ColonLoc is the location of the ':' that + /// starts the constructor initializer, and MemInit/NumMemInits + /// contains the individual member (and base) initializers. + virtual void ActOnMemInitializers(DeclPtrTy ConstructorDecl, + SourceLocation ColonLoc, + MemInitTy **MemInits, unsigned NumMemInits){ + } + + /// ActOnFinishCXXMemberSpecification - Invoked after all member declarators + /// are parsed but *before* parsing of inline method definitions. + virtual void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, + DeclPtrTy TagDecl, + SourceLocation LBrac, + SourceLocation RBrac) { + } + + //===---------------------------C++ Templates----------------------------===// + + /// ActOnTypeParameter - Called when a C++ template type parameter + /// (e.g., "typename T") has been parsed. Typename specifies whether + /// the keyword "typename" was used to declare the type parameter + /// (otherwise, "class" was used), and KeyLoc is the location of the + /// "class" or "typename" keyword. ParamName is the name of the + /// parameter (NULL indicates an unnamed template parameter) and + /// ParamNameLoc is the location of the parameter name (if any). + /// If the type parameter has a default argument, it will be added + /// later via ActOnTypeParameterDefault. Depth and Position provide + /// the number of enclosing templates (see + /// ActOnTemplateParameterList) and the number of previous + /// parameters within this template parameter list. + virtual DeclPtrTy ActOnTypeParameter(Scope *S, bool Typename, + SourceLocation KeyLoc, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, unsigned Position) { + return DeclPtrTy(); + } + + /// ActOnTypeParameterDefault - Adds a default argument (the type + /// Default) to the given template type parameter (TypeParam). + virtual void ActOnTypeParameterDefault(DeclPtrTy TypeParam, + SourceLocation EqualLoc, + SourceLocation DefaultLoc, + TypeTy *Default) { + } + + /// ActOnNonTypeTemplateParameter - Called when a C++ non-type + /// template parameter (e.g., "int Size" in "template<int Size> + /// class Array") has been parsed. S is the current scope and D is + /// the parsed declarator. Depth and Position provide the number of + /// enclosing templates (see + /// ActOnTemplateParameterList) and the number of previous + /// parameters within this template parameter list. + virtual DeclPtrTy ActOnNonTypeTemplateParameter(Scope *S, Declarator &D, + unsigned Depth, + unsigned Position) { + return DeclPtrTy(); + } + + /// \brief Adds a default argument to the given non-type template + /// parameter. + virtual void ActOnNonTypeTemplateParameterDefault(DeclPtrTy TemplateParam, + SourceLocation EqualLoc, + ExprArg Default) { + } + + /// ActOnTemplateTemplateParameter - Called when a C++ template template + /// parameter (e.g., "int T" in "template<template <typename> class T> class + /// Array") has been parsed. TmpLoc is the location of the "template" keyword, + /// TemplateParams is the sequence of parameters required by the template, + /// ParamName is the name of the parameter (null if unnamed), and ParamNameLoc + /// is the source location of the identifier (if given). + virtual DeclPtrTy ActOnTemplateTemplateParameter(Scope *S, + SourceLocation TmpLoc, + TemplateParamsTy *Params, + IdentifierInfo *ParamName, + SourceLocation ParamNameLoc, + unsigned Depth, + unsigned Position) { + return DeclPtrTy(); + } + + /// \brief Adds a default argument to the given template template + /// parameter. + virtual void ActOnTemplateTemplateParameterDefault(DeclPtrTy TemplateParam, + SourceLocation EqualLoc, + ExprArg Default) { + } + + /// ActOnTemplateParameterList - Called when a complete template + /// parameter list has been parsed, e.g., + /// + /// @code + /// export template<typename T, T Size> + /// @endcode + /// + /// Depth is the number of enclosing template parameter lists. This + /// value does not include templates from outer scopes. For example: + /// + /// @code + /// template<typename T> // depth = 0 + /// class A { + /// template<typename U> // depth = 0 + /// class B; + /// }; + /// + /// template<typename T> // depth = 0 + /// template<typename U> // depth = 1 + /// class A<T>::B { ... }; + /// @endcode + /// + /// ExportLoc, if valid, is the position of the "export" + /// keyword. Otherwise, "export" was not specified. + /// TemplateLoc is the position of the template keyword, LAngleLoc + /// is the position of the left angle bracket, and RAngleLoc is the + /// position of the corresponding right angle bracket. + /// Params/NumParams provides the template parameters that were + /// parsed as part of the template-parameter-list. + virtual TemplateParamsTy * + ActOnTemplateParameterList(unsigned Depth, + SourceLocation ExportLoc, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + DeclPtrTy *Params, unsigned NumParams, + SourceLocation RAngleLoc) { + return 0; + } + + /// \brief Process the declaration or definition of a class template + /// with the given template parameter lists. + virtual DeclResult + ActOnClassTemplate(Scope *S, unsigned TagSpec, TagKind TK, + SourceLocation KWLoc, const CXXScopeSpec &SS, + IdentifierInfo *Name, SourceLocation NameLoc, + AttributeList *Attr, + MultiTemplateParamsArg TemplateParameterLists, + AccessSpecifier AS) { + return DeclResult(); + } + + /// \brief Form a type from a template and a list of template + /// arguments. + /// + /// This action merely forms the type for the template-id, possibly + /// checking well-formedness of the template arguments. It does not + /// imply the declaration of any entity. + /// + /// \param Template A template whose specialization results in a + /// type, e.g., a class template or template template parameter. + /// + /// \param IsSpecialization true when we are naming the class + /// template specialization as part of an explicit class + /// specialization or class template partial specialization. + virtual TypeResult ActOnTemplateIdType(TemplateTy Template, + SourceLocation TemplateLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc) { + return TypeResult(); + }; + + /// \brief Form a dependent template name. + /// + /// This action forms a dependent template name given the template + /// name and its (presumably dependent) scope specifier. For + /// example, given "MetaFun::template apply", the scope specifier \p + /// SS will be "MetaFun::", \p TemplateKWLoc contains the location + /// of the "template" keyword, and "apply" is the \p Name. + virtual TemplateTy ActOnDependentTemplateName(SourceLocation TemplateKWLoc, + const IdentifierInfo &Name, + SourceLocation NameLoc, + const CXXScopeSpec &SS) { + return TemplateTy(); + } + + /// \brief Process the declaration or definition of an explicit + /// class template specialization or a class template partial + /// specialization. + /// + /// This routine is invoked when an explicit class template + /// specialization or a class template partial specialization is + /// declared or defined, to introduce the (partial) specialization + /// and produce a declaration for it. In the following example, + /// ActOnClassTemplateSpecialization will be invoked for the + /// declarations at both A and B: + /// + /// \code + /// template<typename T> class X; + /// template<> class X<int> { }; // A: explicit specialization + /// template<typename T> class X<T*> { }; // B: partial specialization + /// \endcode + /// + /// Note that it is the job of semantic analysis to determine which + /// of the two cases actually occurred in the source code, since + /// they are parsed through the same path. The formulation of the + /// template parameter lists describes which case we are in. + /// + /// \param S the current scope + /// + /// \param TagSpec whether this declares a class, struct, or union + /// (template) + /// + /// \param TK whether this is a declaration or a definition + /// + /// \param KWLoc the location of the 'class', 'struct', or 'union' + /// keyword. + /// + /// \param SS the scope specifier preceding the template-id + /// + /// \param Template the declaration of the class template that we + /// are specializing. + /// + /// \param Attr attributes on the specialization + /// + /// \param TemplateParameterLists the set of template parameter + /// lists that apply to this declaration. In a well-formed program, + /// the number of template parameter lists will be one more than the + /// number of template-ids in the scope specifier. However, it is + /// common for users to provide the wrong number of template + /// parameter lists (such as a missing \c template<> prior to a + /// specialization); the parser does not check this condition. + virtual DeclResult + ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagKind TK, + SourceLocation KWLoc, + const CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc, + AttributeList *Attr, + MultiTemplateParamsArg TemplateParameterLists) { + return DeclResult(); + } + + /// \brief Process the explicit instantiation of a class template + /// specialization. + /// + /// This routine is invoked when an explicit instantiation of a + /// class template specialization is encountered. In the following + /// example, ActOnExplicitInstantiation will be invoked to force the + /// instantiation of X<int>: + /// + /// \code + /// template<typename T> class X { /* ... */ }; + /// template class X<int>; // explicit instantiation + /// \endcode + /// + /// \param S the current scope + /// + /// \param TemplateLoc the location of the 'template' keyword that + /// specifies that this is an explicit instantiation. + /// + /// \param TagSpec whether this declares a class, struct, or union + /// (template). + /// + /// \param KWLoc the location of the 'class', 'struct', or 'union' + /// keyword. + /// + /// \param SS the scope specifier preceding the template-id. + /// + /// \param Template the declaration of the class template that we + /// are instantiation. + /// + /// \param LAngleLoc the location of the '<' token in the template-id. + /// + /// \param TemplateArgs the template arguments used to form the + /// template-id. + /// + /// \param TemplateArgLocs the locations of the template arguments. + /// + /// \param RAngleLoc the location of the '>' token in the template-id. + /// + /// \param Attr attributes that apply to this instantiation. + virtual DeclResult + ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, + unsigned TagSpec, + SourceLocation KWLoc, + const CXXScopeSpec &SS, + TemplateTy Template, + SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, + ASTTemplateArgsPtr TemplateArgs, + SourceLocation *TemplateArgLocs, + SourceLocation RAngleLoc, + AttributeList *Attr) { + return DeclResult(); + } + + /// \brief Process the explicit instantiation of a member class of a + /// class template specialization. + /// + /// This routine is invoked when an explicit instantiation of a + /// member class of a class template specialization is + /// encountered. In the following example, + /// ActOnExplicitInstantiation will be invoked to force the + /// instantiation of X<int>::Inner: + /// + /// \code + /// template<typename T> class X { class Inner { /* ... */}; }; + /// template class X<int>::Inner; // explicit instantiation + /// \endcode + /// + /// \param S the current scope + /// + /// \param TemplateLoc the location of the 'template' keyword that + /// specifies that this is an explicit instantiation. + /// + /// \param TagSpec whether this declares a class, struct, or union + /// (template). + /// + /// \param KWLoc the location of the 'class', 'struct', or 'union' + /// keyword. + /// + /// \param SS the scope specifier preceding the template-id. + /// + /// \param Template the declaration of the class template that we + /// are instantiation. + /// + /// \param LAngleLoc the location of the '<' token in the template-id. + /// + /// \param TemplateArgs the template arguments used to form the + /// template-id. + /// + /// \param TemplateArgLocs the locations of the template arguments. + /// + /// \param RAngleLoc the location of the '>' token in the template-id. + /// + /// \param Attr attributes that apply to this instantiation. + virtual DeclResult + ActOnExplicitInstantiation(Scope *S, SourceLocation TemplateLoc, + unsigned TagSpec, + SourceLocation KWLoc, + const CXXScopeSpec &SS, + IdentifierInfo *Name, + SourceLocation NameLoc, + AttributeList *Attr) { + return DeclResult(); + } + + /// \brief Called when the parser has parsed a C++ typename + /// specifier that ends in an identifier, e.g., "typename T::type". + /// + /// \param TypenameLoc the location of the 'typename' keyword + /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). + /// \param II the identifier we're retrieving (e.g., 'type' in the example). + /// \param IdLoc the location of the identifier. + virtual TypeResult + ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, + const IdentifierInfo &II, SourceLocation IdLoc) { + return TypeResult(); + } + + /// \brief Called when the parser has parsed a C++ typename + /// specifier that ends in a template-id, e.g., + /// "typename MetaFun::template apply<T1, T2>". + /// + /// \param TypenameLoc the location of the 'typename' keyword + /// \param SS the nested-name-specifier following the typename (e.g., 'T::'). + /// \param TemplateLoc the location of the 'template' keyword, if any. + /// \param Ty the type that the typename specifier refers to. + virtual TypeResult + ActOnTypenameType(SourceLocation TypenameLoc, const CXXScopeSpec &SS, + SourceLocation TemplateLoc, TypeTy *Ty) { + return TypeResult(); + } + + //===----------------------- Obj-C Declarations -------------------------===// + + // ActOnStartClassInterface - this action is called immediately after parsing + // the prologue for a class interface (before parsing the instance + // variables). Instance variables are processed by ActOnFields(). + virtual DeclPtrTy ActOnStartClassInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *SuperName, + SourceLocation SuperLoc, + const DeclPtrTy *ProtoRefs, + unsigned NumProtoRefs, + SourceLocation EndProtoLoc, + AttributeList *AttrList) { + return DeclPtrTy(); + } + + /// ActOnCompatiblityAlias - this action is called after complete parsing of + /// @compaatibility_alias declaration. It sets up the alias relationships. + virtual DeclPtrTy ActOnCompatiblityAlias( + SourceLocation AtCompatibilityAliasLoc, + IdentifierInfo *AliasName, SourceLocation AliasLocation, + IdentifierInfo *ClassName, SourceLocation ClassLocation) { + return DeclPtrTy(); + } + + // ActOnStartProtocolInterface - this action is called immdiately after + // parsing the prologue for a protocol interface. + virtual DeclPtrTy ActOnStartProtocolInterface(SourceLocation AtProtoLoc, + IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, + const DeclPtrTy *ProtoRefs, + unsigned NumProtoRefs, + SourceLocation EndProtoLoc, + AttributeList *AttrList) { + return DeclPtrTy(); + } + // ActOnStartCategoryInterface - this action is called immdiately after + // parsing the prologue for a category interface. + virtual DeclPtrTy ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *CategoryName, + SourceLocation CategoryLoc, + const DeclPtrTy *ProtoRefs, + unsigned NumProtoRefs, + SourceLocation EndProtoLoc) { + return DeclPtrTy(); + } + // ActOnStartClassImplementation - this action is called immdiately after + // parsing the prologue for a class implementation. Instance variables are + // processed by ActOnFields(). + virtual DeclPtrTy ActOnStartClassImplementation( + SourceLocation AtClassImplLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *SuperClassname, + SourceLocation SuperClassLoc) { + return DeclPtrTy(); + } + // ActOnStartCategoryImplementation - this action is called immdiately after + // parsing the prologue for a category implementation. + virtual DeclPtrTy ActOnStartCategoryImplementation( + SourceLocation AtCatImplLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *CatName, + SourceLocation CatLoc) { + return DeclPtrTy(); + } + // ActOnPropertyImplDecl - called for every property implementation + virtual DeclPtrTy ActOnPropertyImplDecl( + SourceLocation AtLoc, // location of the @synthesize/@dynamic + SourceLocation PropertyNameLoc, // location for the property name + bool ImplKind, // true for @synthesize, false for + // @dynamic + DeclPtrTy ClassImplDecl, // class or category implementation + IdentifierInfo *propertyId, // name of property + IdentifierInfo *propertyIvar) { // name of the ivar + return DeclPtrTy(); + } + + struct ObjCArgInfo { + IdentifierInfo *Name; + SourceLocation NameLoc; + // The Type is null if no type was specified, and the DeclSpec is invalid + // in this case. + TypeTy *Type; + ObjCDeclSpec DeclSpec; + + /// ArgAttrs - Attribute list for this argument. + AttributeList *ArgAttrs; + }; + + // ActOnMethodDeclaration - called for all method declarations. + virtual DeclPtrTy ActOnMethodDeclaration( + SourceLocation BeginLoc, // location of the + or -. + SourceLocation EndLoc, // location of the ; or {. + tok::TokenKind MethodType, // tok::minus for instance, tok::plus for class. + DeclPtrTy ClassDecl, // class this methods belongs to. + ObjCDeclSpec &ReturnQT, // for return type's in inout etc. + TypeTy *ReturnType, // the method return type. + Selector Sel, // a unique name for the method. + ObjCArgInfo *ArgInfo, // ArgInfo: Has 'Sel.getNumArgs()' entries. + llvm::SmallVectorImpl<Declarator> &Cdecls, // c-style args + AttributeList *MethodAttrList, // optional + // tok::objc_not_keyword, tok::objc_optional, tok::objc_required + tok::ObjCKeywordKind impKind, + bool isVariadic = false) { + return DeclPtrTy(); + } + // ActOnAtEnd - called to mark the @end. For declarations (interfaces, + // protocols, categories), the parser passes all methods/properties. + // For class implementations, these values default to 0. For implementations, + // methods are processed incrementally (by ActOnMethodDeclaration above). + virtual void ActOnAtEnd(SourceLocation AtEndLoc, + DeclPtrTy classDecl, + DeclPtrTy *allMethods = 0, + unsigned allNum = 0, + DeclPtrTy *allProperties = 0, + unsigned pNum = 0, + DeclGroupPtrTy *allTUVars = 0, + unsigned tuvNum = 0) { + } + // ActOnProperty - called to build one property AST + virtual DeclPtrTy ActOnProperty(Scope *S, SourceLocation AtLoc, + FieldDeclarator &FD, ObjCDeclSpec &ODS, + Selector GetterSel, Selector SetterSel, + DeclPtrTy ClassCategory, + bool *OverridingProperty, + tok::ObjCKeywordKind MethodImplKind) { + return DeclPtrTy(); + } + + virtual OwningExprResult ActOnClassPropertyRefExpr( + IdentifierInfo &receiverName, + IdentifierInfo &propertyName, + SourceLocation &receiverNameLoc, + SourceLocation &propertyNameLoc) { + return ExprEmpty(); + } + + // ActOnClassMessage - used for both unary and keyword messages. + // ArgExprs is optional - if it is present, the number of expressions + // is obtained from NumArgs. + virtual ExprResult ActOnClassMessage( + Scope *S, + IdentifierInfo *receivingClassName, + Selector Sel, + SourceLocation lbrac, SourceLocation receiverLoc, + SourceLocation selectorLoc, + SourceLocation rbrac, + ExprTy **ArgExprs, unsigned NumArgs) { + return ExprResult(); + } + // ActOnInstanceMessage - used for both unary and keyword messages. + // ArgExprs is optional - if it is present, the number of expressions + // is obtained from NumArgs. + virtual ExprResult ActOnInstanceMessage( + ExprTy *receiver, Selector Sel, + SourceLocation lbrac, SourceLocation selectorLoc, SourceLocation rbrac, + ExprTy **ArgExprs, unsigned NumArgs) { + return ExprResult(); + } + virtual DeclPtrTy ActOnForwardClassDeclaration( + SourceLocation AtClassLoc, + IdentifierInfo **IdentList, + unsigned NumElts) { + return DeclPtrTy(); + } + virtual DeclPtrTy ActOnForwardProtocolDeclaration( + SourceLocation AtProtocolLoc, + const IdentifierLocPair*IdentList, + unsigned NumElts, + AttributeList *AttrList) { + return DeclPtrTy(); + } + + /// FindProtocolDeclaration - This routine looks up protocols and + /// issues error if they are not declared. It returns list of valid + /// protocols found. + virtual void FindProtocolDeclaration(bool WarnOnDeclarations, + const IdentifierLocPair *ProtocolId, + unsigned NumProtocols, + llvm::SmallVectorImpl<DeclPtrTy> &ResProtos) { + } + + //===----------------------- Obj-C Expressions --------------------------===// + + virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, + ExprTy **Strings, + unsigned NumStrings) { + return ExprResult(); + } + + virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc, + SourceLocation EncLoc, + SourceLocation LParenLoc, + TypeTy *Ty, + SourceLocation RParenLoc) { + return ExprResult(); + } + + virtual ExprResult ParseObjCSelectorExpression(Selector Sel, + SourceLocation AtLoc, + SourceLocation SelLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return ExprResult(); + } + + virtual ExprResult ParseObjCProtocolExpression(IdentifierInfo *ProtocolId, + SourceLocation AtLoc, + SourceLocation ProtoLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return ExprResult(); + } + + //===---------------------------- Pragmas -------------------------------===// + + enum PragmaPackKind { + PPK_Default, // #pragma pack([n]) + PPK_Show, // #pragma pack(show), only supported by MSVC. + PPK_Push, // #pragma pack(push, [identifier], [n]) + PPK_Pop // #pragma pack(pop, [identifier], [n]) + }; + + /// ActOnPragmaPack - Called on well formed #pragma pack(...). + virtual void ActOnPragmaPack(PragmaPackKind Kind, + IdentifierInfo *Name, + ExprTy *Alignment, + SourceLocation PragmaLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return; + } + + /// ActOnPragmaPack - Called on well formed #pragma pack(...). + virtual void ActOnPragmaUnused(ExprTy **Exprs, unsigned NumExprs, + SourceLocation PragmaLoc, + SourceLocation LParenLoc, + SourceLocation RParenLoc) { + return; + } +}; + +/// MinimalAction - Minimal actions are used by light-weight clients of the +/// parser that do not need name resolution or significant semantic analysis to +/// be performed. The actions implemented here are in the form of unresolved +/// identifiers. By using a simpler interface than the SemanticAction class, +/// the parser doesn't have to build complex data structures and thus runs more +/// quickly. +class MinimalAction : public Action { + /// Translation Unit Scope - useful to Objective-C actions that need + /// to lookup file scope declarations in the "ordinary" C decl namespace. + /// For example, user-defined classes, built-in "id" type, etc. + Scope *TUScope; + IdentifierTable &Idents; + Preprocessor &PP; + void *TypeNameInfoTablePtr; +public: + MinimalAction(Preprocessor &pp); + ~MinimalAction(); + + /// getTypeName - This looks at the IdentifierInfo::FETokenInfo field to + /// determine whether the name is a typedef or not in this scope. + virtual TypeTy *getTypeName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, const CXXScopeSpec *SS); + + /// isCurrentClassName - Always returns false, because MinimalAction + /// does not support C++ classes with constructors. + virtual bool isCurrentClassName(const IdentifierInfo& II, Scope *S, + const CXXScopeSpec *SS); + + virtual TemplateNameKind isTemplateName(const IdentifierInfo &II, Scope *S, + TemplateTy &Template, + const CXXScopeSpec *SS = 0); + + /// ActOnDeclarator - If this is a typedef declarator, we modify the + /// IdentifierInfo::FETokenInfo field to keep track of this fact, until S is + /// popped. + virtual DeclPtrTy ActOnDeclarator(Scope *S, Declarator &D); + + /// ActOnPopScope - When a scope is popped, if any typedefs are now + /// out-of-scope, they are removed from the IdentifierInfo::FETokenInfo field. + virtual void ActOnPopScope(SourceLocation Loc, Scope *S); + virtual void ActOnTranslationUnitScope(SourceLocation Loc, Scope *S); + + virtual DeclPtrTy ActOnForwardClassDeclaration(SourceLocation AtClassLoc, + IdentifierInfo **IdentList, + unsigned NumElts); + + virtual DeclPtrTy ActOnStartClassInterface(SourceLocation interLoc, + IdentifierInfo *ClassName, + SourceLocation ClassLoc, + IdentifierInfo *SuperName, + SourceLocation SuperLoc, + const DeclPtrTy *ProtoRefs, + unsigned NumProtoRefs, + SourceLocation EndProtoLoc, + AttributeList *AttrList); +}; + +/// PrettyStackTraceActionsDecl - If a crash occurs in the parser while parsing +/// something related to a virtualized decl, include that virtualized decl in +/// the stack trace. +class PrettyStackTraceActionsDecl : public llvm::PrettyStackTraceEntry { + Action::DeclPtrTy TheDecl; + SourceLocation Loc; + Action &Actions; + SourceManager &SM; + const char *Message; +public: + PrettyStackTraceActionsDecl(Action::DeclPtrTy Decl, SourceLocation L, + Action &actions, SourceManager &sm, + const char *Msg) + : TheDecl(Decl), Loc(L), Actions(actions), SM(sm), Message(Msg) {} + + virtual void print(llvm::raw_ostream &OS) const; +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h new file mode 100644 index 0000000..8225c9d --- /dev/null +++ b/include/clang/Parse/AttributeList.h @@ -0,0 +1,173 @@ +//===--- AttributeList.h ----------------------------------------*- 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 AttributeList class interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ATTRLIST_H +#define LLVM_CLANG_ATTRLIST_H + +#include "clang/Parse/Ownership.h" +#include "clang/Basic/SourceLocation.h" +#include <cassert> + +namespace clang { + class IdentifierInfo; + class Action; + +/// AttributeList - Represents GCC's __attribute__ declaration. There are +/// 4 forms of this construct...they are: +/// +/// 1: __attribute__(( const )). ParmName/Args/NumArgs will all be unused. +/// 2: __attribute__(( mode(byte) )). ParmName used, Args/NumArgs unused. +/// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. +/// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. +/// +class AttributeList { + IdentifierInfo *AttrName; + SourceLocation AttrLoc; + IdentifierInfo *ParmName; + SourceLocation ParmLoc; + ActionBase::ExprTy **Args; + unsigned NumArgs; + AttributeList *Next; + AttributeList(const AttributeList &); // DO NOT IMPLEMENT + void operator=(const AttributeList &); // DO NOT IMPLEMENT +public: + AttributeList(IdentifierInfo *AttrName, SourceLocation AttrLoc, + IdentifierInfo *ParmName, SourceLocation ParmLoc, + ActionBase::ExprTy **args, unsigned numargs, + AttributeList *Next); + ~AttributeList(); + + enum Kind { // Please keep this list alphabetized. + AT_IBOutlet, // Clang-specific. + AT_address_space, + AT_alias, + AT_aligned, + AT_always_inline, + AT_analyzer_noreturn, + AT_annotate, + AT_blocks, + AT_cleanup, + AT_const, + AT_constructor, + AT_deprecated, + AT_destructor, + AT_dllexport, + AT_dllimport, + AT_ext_vector_type, + AT_fastcall, + AT_format, + AT_format_arg, + AT_gnu_inline, + AT_mode, + AT_nodebug, + AT_noinline, + AT_no_instrument_function, + AT_nonnull, + AT_noreturn, + AT_nothrow, + AT_nsobject, + AT_objc_exception, + AT_cf_returns_retained, // Clang-specific. + AT_ns_returns_retained, // Clang-specific. + AT_objc_gc, + AT_overloadable, // Clang-specific. + AT_packed, + AT_pure, + AT_regparm, + AT_section, + AT_sentinel, + AT_stdcall, + AT_transparent_union, + AT_unavailable, + AT_unused, + AT_used, + AT_vector_size, + AT_visibility, + AT_warn_unused_result, + AT_weak, + AT_weak_import, + IgnoredAttribute, + UnknownAttribute + }; + + IdentifierInfo *getName() const { return AttrName; } + SourceLocation getLoc() const { return AttrLoc; } + IdentifierInfo *getParameterName() const { return ParmName; } + + Kind getKind() const { return getKind(getName()); } + static Kind getKind(const IdentifierInfo *Name); + + AttributeList *getNext() const { return Next; } + void setNext(AttributeList *N) { Next = N; } + + void addAttributeList(AttributeList *alist) { + assert((alist != 0) && "addAttributeList(): alist is null"); + AttributeList *next = this, *prev; + do { + prev = next; + next = next->getNext(); + } while (next); + prev->setNext(alist); + } + + /// getNumArgs - Return the number of actual arguments to this attribute. + unsigned getNumArgs() const { return NumArgs; } + + /// getArg - Return the specified argument. + ActionBase::ExprTy *getArg(unsigned Arg) const { + assert(Arg < NumArgs && "Arg access out of range!"); + return Args[Arg]; + } + + class arg_iterator { + ActionBase::ExprTy** X; + unsigned Idx; + public: + arg_iterator(ActionBase::ExprTy** x, unsigned idx) : X(x), Idx(idx) {} + + arg_iterator& operator++() { + ++Idx; + return *this; + } + + bool operator==(const arg_iterator& I) const { + assert (X == I.X && + "compared arg_iterators are for different argument lists"); + return Idx == I.Idx; + } + + bool operator!=(const arg_iterator& I) const { + return !operator==(I); + } + + ActionBase::ExprTy* operator*() const { + return X[Idx]; + } + + unsigned getArgNum() const { + return Idx+1; + } + }; + + arg_iterator arg_begin() const { + return arg_iterator(Args, 0); + } + + arg_iterator arg_end() const { + return arg_iterator(Args, NumArgs); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Parse/DeclSpec.h b/include/clang/Parse/DeclSpec.h new file mode 100644 index 0000000..a0b9b1e --- /dev/null +++ b/include/clang/Parse/DeclSpec.h @@ -0,0 +1,1086 @@ +//===--- SemaDeclSpec.h - Declaration Specifier Semantic Analys -*- 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 interfaces used for Declaration Specifiers and Declarators. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_DECLSPEC_H +#define LLVM_CLANG_PARSE_DECLSPEC_H + +#include "clang/Parse/AttributeList.h" +#include "clang/Lex/Token.h" +#include "clang/Basic/OperatorKinds.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { + class LangOptions; + class Diagnostic; + class IdentifierInfo; + class Preprocessor; + class Declarator; + +/// DeclSpec - This class captures information about "declaration specifiers", +/// which encompasses storage-class-specifiers, type-specifiers, +/// type-qualifiers, and function-specifiers. +class DeclSpec { +public: + // storage-class-specifier + enum SCS { + SCS_unspecified, + SCS_typedef, + SCS_extern, + SCS_static, + SCS_auto, + SCS_register, + SCS_private_extern, + SCS_mutable + }; + + // type-specifier + enum TSW { + TSW_unspecified, + TSW_short, + TSW_long, + TSW_longlong + }; + + enum TSC { + TSC_unspecified, + TSC_imaginary, + TSC_complex + }; + + enum TSS { + TSS_unspecified, + TSS_signed, + TSS_unsigned + }; + + enum TST { + TST_unspecified, + TST_void, + TST_char, + TST_wchar, // C++ wchar_t + TST_int, + TST_float, + TST_double, + TST_bool, // _Bool + TST_decimal32, // _Decimal32 + TST_decimal64, // _Decimal64 + TST_decimal128, // _Decimal128 + TST_enum, + TST_union, + TST_struct, + TST_class, // C++ class type + TST_typename, // Typedef, C++ class-name or enum name, etc. + TST_typeofType, + TST_typeofExpr, + TST_error // erroneous type + }; + + // type-qualifiers + enum TQ { // NOTE: These flags must be kept in sync with QualType::TQ. + TQ_unspecified = 0, + TQ_const = 1, + TQ_restrict = 2, + TQ_volatile = 4 + }; + + /// ParsedSpecifiers - Flags to query which specifiers were applied. This is + /// returned by getParsedSpecifiers. + enum ParsedSpecifiers { + PQ_None = 0, + PQ_StorageClassSpecifier = 1, + PQ_TypeSpecifier = 2, + PQ_TypeQualifier = 4, + PQ_FunctionSpecifier = 8 + }; + +private: + + // storage-class-specifier + /*SCS*/unsigned StorageClassSpec : 3; + bool SCS_thread_specified : 1; + + // type-specifier + /*TSW*/unsigned TypeSpecWidth : 2; + /*TSC*/unsigned TypeSpecComplex : 2; + /*TSS*/unsigned TypeSpecSign : 2; + /*TST*/unsigned TypeSpecType : 5; + bool TypeSpecOwned : 1; + + // type-qualifiers + unsigned TypeQualifiers : 3; // Bitwise OR of TQ. + + // function-specifier + bool FS_inline_specified : 1; + bool FS_virtual_specified : 1; + bool FS_explicit_specified : 1; + + // friend-specifier + bool Friend_specified : 1; + + /// TypeRep - This contains action-specific information about a specific TST. + /// For example, for a typedef or struct, it might contain the declaration for + /// these. + void *TypeRep; + + // attributes. + AttributeList *AttrList; + + // List of protocol qualifiers for objective-c classes. Used for + // protocol-qualified interfaces "NString<foo>" and protocol-qualified id + // "id<foo>". + const ActionBase::DeclPtrTy *ProtocolQualifiers; + unsigned NumProtocolQualifiers; + + // SourceLocation info. These are null if the item wasn't specified or if + // the setting was synthesized. + SourceRange Range; + + SourceLocation StorageClassSpecLoc, SCS_threadLoc; + SourceLocation TSWLoc, TSCLoc, TSSLoc, TSTLoc; + SourceLocation TQ_constLoc, TQ_restrictLoc, TQ_volatileLoc; + SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc; + SourceLocation FriendLoc; + + bool BadSpecifier(TST T, const char *&PrevSpec); + bool BadSpecifier(TQ T, const char *&PrevSpec); + bool BadSpecifier(TSS T, const char *&PrevSpec); + bool BadSpecifier(TSC T, const char *&PrevSpec); + bool BadSpecifier(TSW T, const char *&PrevSpec); + bool BadSpecifier(SCS T, const char *&PrevSpec); + + DeclSpec(const DeclSpec&); // DO NOT IMPLEMENT + void operator=(const DeclSpec&); // DO NOT IMPLEMENT +public: + + DeclSpec() + : StorageClassSpec(SCS_unspecified), + SCS_thread_specified(false), + TypeSpecWidth(TSW_unspecified), + TypeSpecComplex(TSC_unspecified), + TypeSpecSign(TSS_unspecified), + TypeSpecType(TST_unspecified), + TypeSpecOwned(false), + TypeQualifiers(TSS_unspecified), + FS_inline_specified(false), + FS_virtual_specified(false), + FS_explicit_specified(false), + Friend_specified(false), + TypeRep(0), + AttrList(0), + ProtocolQualifiers(0), + NumProtocolQualifiers(0) { + } + ~DeclSpec() { + delete AttrList; + delete [] ProtocolQualifiers; + } + // storage-class-specifier + SCS getStorageClassSpec() const { return (SCS)StorageClassSpec; } + bool isThreadSpecified() const { return SCS_thread_specified; } + + SourceLocation getStorageClassSpecLoc() const { return StorageClassSpecLoc; } + SourceLocation getThreadSpecLoc() const { return SCS_threadLoc; } + + void ClearStorageClassSpecs() { + StorageClassSpec = DeclSpec::SCS_unspecified; + SCS_thread_specified = false; + StorageClassSpecLoc = SourceLocation(); + SCS_threadLoc = SourceLocation(); + } + + // type-specifier + TSW getTypeSpecWidth() const { return (TSW)TypeSpecWidth; } + TSC getTypeSpecComplex() const { return (TSC)TypeSpecComplex; } + TSS getTypeSpecSign() const { return (TSS)TypeSpecSign; } + TST getTypeSpecType() const { return (TST)TypeSpecType; } + bool isTypeSpecOwned() const { return TypeSpecOwned; } + void *getTypeRep() const { return TypeRep; } + + const SourceRange &getSourceRange() const { return Range; } + SourceLocation getTypeSpecWidthLoc() const { return TSWLoc; } + SourceLocation getTypeSpecComplexLoc() const { return TSCLoc; } + SourceLocation getTypeSpecSignLoc() const { return TSSLoc; } + SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } + + /// getSpecifierName - Turn a type-specifier-type into a string like "_Bool" + /// or "union". + static const char *getSpecifierName(DeclSpec::TST T); + static const char *getSpecifierName(DeclSpec::SCS S); + + // type-qualifiers + + /// getTypeQualifiers - Return a set of TQs. + unsigned getTypeQualifiers() const { return TypeQualifiers; } + SourceLocation getConstSpecLoc() const { return TQ_constLoc; } + SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; } + SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; } + + // function-specifier + bool isInlineSpecified() const { return FS_inline_specified; } + SourceLocation getInlineSpecLoc() const { return FS_inlineLoc; } + + bool isVirtualSpecified() const { return FS_virtual_specified; } + SourceLocation getVirtualSpecLoc() const { return FS_virtualLoc; } + + bool isExplicitSpecified() const { return FS_explicit_specified; } + SourceLocation getExplicitSpecLoc() const { return FS_explicitLoc; } + + void ClearFunctionSpecs() { + FS_inline_specified = false; + FS_inlineLoc = SourceLocation(); + FS_virtual_specified = false; + FS_virtualLoc = SourceLocation(); + FS_explicit_specified = false; + FS_explicitLoc = SourceLocation(); + } + + /// hasTypeSpecifier - Return true if any type-specifier has been found. + bool hasTypeSpecifier() const { + return getTypeSpecType() != DeclSpec::TST_unspecified || + getTypeSpecWidth() != DeclSpec::TSW_unspecified || + getTypeSpecComplex() != DeclSpec::TSC_unspecified || + getTypeSpecSign() != DeclSpec::TSS_unspecified; + } + + /// getParsedSpecifiers - Return a bitmask of which flavors of specifiers this + /// DeclSpec includes. + /// + unsigned getParsedSpecifiers() const; + + /// isEmpty - Return true if this declaration specifier is completely empty: + /// no tokens were parsed in the production of it. + bool isEmpty() const { + return getParsedSpecifiers() == DeclSpec::PQ_None; + } + + void SetRangeStart(SourceLocation Loc) { Range.setBegin(Loc); } + void SetRangeEnd(SourceLocation Loc) { Range.setEnd(Loc); } + + /// These methods set the specified attribute of the DeclSpec, but return true + /// and ignore the request if invalid (e.g. "extern" then "auto" is + /// specified). The name of the previous specifier is returned in prevspec. + bool SetStorageClassSpec(SCS S, SourceLocation Loc, const char *&PrevSpec); + bool SetStorageClassSpecThread(SourceLocation Loc, const char *&PrevSpec); + bool SetTypeSpecWidth(TSW W, SourceLocation Loc, const char *&PrevSpec); + bool SetTypeSpecComplex(TSC C, SourceLocation Loc, const char *&PrevSpec); + bool SetTypeSpecSign(TSS S, SourceLocation Loc, const char *&PrevSpec); + bool SetTypeSpecType(TST T, SourceLocation Loc, const char *&PrevSpec, + void *Rep = 0, bool Owned = false); + bool SetTypeSpecError(); + + bool SetTypeQual(TQ T, SourceLocation Loc, const char *&PrevSpec, + const LangOptions &Lang); + + bool SetFunctionSpecInline(SourceLocation Loc, const char *&PrevSpec); + bool SetFunctionSpecVirtual(SourceLocation Loc, const char *&PrevSpec); + bool SetFunctionSpecExplicit(SourceLocation Loc, const char *&PrevSpec); + + bool SetFriendSpec(SourceLocation Loc, const char *&PrevSpec); + bool isFriendSpecified() const { return Friend_specified; } + SourceLocation getFriendSpecLoc() const { return FriendLoc; } + + /// AddAttributes - contatenates two attribute lists. + /// The GCC attribute syntax allows for the following: + /// + /// short __attribute__(( unused, deprecated )) + /// int __attribute__(( may_alias, aligned(16) )) var; + /// + /// This declares 4 attributes using 2 lists. The following syntax is + /// also allowed and equivalent to the previous declaration. + /// + /// short __attribute__((unused)) __attribute__((deprecated)) + /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; + /// + void AddAttributes(AttributeList *alist) { + if (!alist) + return; // we parsed __attribute__(()) or had a syntax error + + if (AttrList) + alist->addAttributeList(AttrList); + AttrList = alist; + } + void SetAttributes(AttributeList *AL) { AttrList = AL; } + const AttributeList *getAttributes() const { return AttrList; } + AttributeList *getAttributes() { return AttrList; } + + /// TakeAttributes - Return the current attribute list and remove them from + /// the DeclSpec so that it doesn't own them. + AttributeList *TakeAttributes() { + AttributeList *AL = AttrList; + AttrList = 0; + return AL; + } + + typedef const ActionBase::DeclPtrTy *ProtocolQualifierListTy; + ProtocolQualifierListTy getProtocolQualifiers() const { + return ProtocolQualifiers; + } + unsigned getNumProtocolQualifiers() const { + return NumProtocolQualifiers; + } + void setProtocolQualifiers(const ActionBase::DeclPtrTy *Protos, unsigned NP) { + if (NP == 0) return; + ProtocolQualifiers = new ActionBase::DeclPtrTy[NP]; + memcpy((void*)ProtocolQualifiers, Protos, sizeof(ActionBase::DeclPtrTy)*NP); + NumProtocolQualifiers = NP; + } + + /// Finish - This does final analysis of the declspec, issuing diagnostics for + /// things like "_Imaginary" (lacking an FP type). After calling this method, + /// DeclSpec is guaranteed self-consistent, even if an error occurred. + void Finish(Diagnostic &D, Preprocessor &PP); + + /// isMissingDeclaratorOk - This checks if this DeclSpec can stand alone, + /// without a Declarator. Only tag declspecs can stand alone. + bool isMissingDeclaratorOk(); +}; + +/// ObjCDeclSpec - This class captures information about +/// "declaration specifiers" specific to objective-c +class ObjCDeclSpec { +public: + /// ObjCDeclQualifier - Qualifier used on types in method declarations + enum ObjCDeclQualifier { + DQ_None = 0x0, + DQ_In = 0x1, + DQ_Inout = 0x2, + DQ_Out = 0x4, + DQ_Bycopy = 0x8, + DQ_Byref = 0x10, + DQ_Oneway = 0x20 + }; + + /// PropertyAttributeKind - list of property attributes. + enum ObjCPropertyAttributeKind { DQ_PR_noattr = 0x0, + DQ_PR_readonly = 0x01, + DQ_PR_getter = 0x02, + DQ_PR_assign = 0x04, + DQ_PR_readwrite = 0x08, + DQ_PR_retain = 0x10, + DQ_PR_copy = 0x20, + DQ_PR_nonatomic = 0x40, + DQ_PR_setter = 0x80 + }; + + + ObjCDeclSpec() : objcDeclQualifier(DQ_None), PropertyAttributes(DQ_PR_noattr), + GetterName(0), SetterName(0) + {} + ObjCDeclQualifier getObjCDeclQualifier() const { return objcDeclQualifier; } + void setObjCDeclQualifier(ObjCDeclQualifier DQVal) + { objcDeclQualifier = (ObjCDeclQualifier) (objcDeclQualifier | DQVal); } + + ObjCPropertyAttributeKind getPropertyAttributes() const + { return ObjCPropertyAttributeKind(PropertyAttributes); } + void setPropertyAttributes(ObjCPropertyAttributeKind PRVal) { + PropertyAttributes = + (ObjCPropertyAttributeKind) (PropertyAttributes | PRVal); + } + + const IdentifierInfo *getGetterName() const { return GetterName; } + IdentifierInfo *getGetterName() { return GetterName; } + void setGetterName(IdentifierInfo *name) { GetterName = name; } + + const IdentifierInfo *getSetterName() const { return SetterName; } + IdentifierInfo *getSetterName() { return SetterName; } + void setSetterName(IdentifierInfo *name) { SetterName = name; } +private: + // FIXME: These two are unrelated and mutially exclusive. So perhaps + // we can put them in a union to reflect their mutual exclusiveness + // (space saving is negligible). + ObjCDeclQualifier objcDeclQualifier : 6; + + // NOTE: VC++ treats enums as signed, avoid using ObjCPropertyAttributeKind + unsigned PropertyAttributes : 8; + IdentifierInfo *GetterName; // getter name of NULL if no getter + IdentifierInfo *SetterName; // setter name of NULL if no setter +}; + +/// CXXScopeSpec - Represents a C++ nested-name-specifier or a global scope +/// specifier. +class CXXScopeSpec { + SourceRange Range; + void *ScopeRep; + +public: + CXXScopeSpec() : Range(), ScopeRep() { } + + const SourceRange &getRange() const { return Range; } + void setRange(const SourceRange &R) { Range = R; } + void setBeginLoc(SourceLocation Loc) { Range.setBegin(Loc); } + void setEndLoc(SourceLocation Loc) { Range.setEnd(Loc); } + SourceLocation getBeginLoc() const { return Range.getBegin(); } + SourceLocation getEndLoc() const { return Range.getEnd(); } + + ActionBase::CXXScopeTy *getScopeRep() const { return ScopeRep; } + void setScopeRep(ActionBase::CXXScopeTy *S) { ScopeRep = S; } + + bool isEmpty() const { return !Range.isValid(); } + bool isNotEmpty() const { return !isEmpty(); } + + /// isInvalid - An error occured during parsing of the scope specifier. + bool isInvalid() const { return isNotEmpty() && ScopeRep == 0; } + + /// isSet - A scope specifier was resolved to a valid C++ scope. + bool isSet() const { return ScopeRep != 0; } + + void clear() { + Range = SourceRange(); + ScopeRep = 0; + } +}; + +/// CachedTokens - A set of tokens that has been cached for later +/// parsing. +typedef llvm::SmallVector<Token, 4> CachedTokens; + +/// DeclaratorChunk - One instance of this struct is used for each type in a +/// declarator that is parsed. +/// +/// This is intended to be a small value object. +struct DeclaratorChunk { + enum { + Pointer, Reference, Array, Function, BlockPointer, MemberPointer + } Kind; + + /// Loc - The place where this type was defined. + SourceLocation Loc; + + struct PointerTypeInfo { + /// The type qualifiers: const/volatile/restrict. + unsigned TypeQuals : 3; + AttributeList *AttrList; + void destroy() { + delete AttrList; + } + }; + + struct ReferenceTypeInfo { + /// The type qualifier: restrict. [GNU] C++ extension + bool HasRestrict : 1; + /// True if this is an lvalue reference, false if it's an rvalue reference. + bool LValueRef : 1; + AttributeList *AttrList; + void destroy() { + delete AttrList; + } + }; + + struct ArrayTypeInfo { + /// The type qualifiers for the array: const/volatile/restrict. + unsigned TypeQuals : 3; + + /// True if this dimension included the 'static' keyword. + bool hasStatic : 1; + + /// True if this dimension was [*]. In this case, NumElts is null. + bool isStar : 1; + + /// This is the size of the array, or null if [] or [*] was specified. + /// Since the parser is multi-purpose, and we don't want to impose a root + /// expression class on all clients, NumElts is untyped. + ActionBase::ExprTy *NumElts; + void destroy() {} + }; + + /// ParamInfo - An array of paraminfo objects is allocated whenever a function + /// declarator is parsed. There are two interesting styles of arguments here: + /// K&R-style identifier lists and parameter type lists. K&R-style identifier + /// lists will have information about the identifier, but no type information. + /// Parameter type lists will have type info (if the actions module provides + /// it), but may have null identifier info: e.g. for 'void foo(int X, int)'. + struct ParamInfo { + IdentifierInfo *Ident; + SourceLocation IdentLoc; + ActionBase::DeclPtrTy Param; + + /// DefaultArgTokens - When the parameter's default argument + /// cannot be parsed immediately (because it occurs within the + /// declaration of a member function), it will be stored here as a + /// sequence of tokens to be parsed once the class definition is + /// complete. Non-NULL indicates that there is a default argument. + CachedTokens *DefaultArgTokens; + + ParamInfo() {} + ParamInfo(IdentifierInfo *ident, SourceLocation iloc, + ActionBase::DeclPtrTy param, + CachedTokens *DefArgTokens = 0) + : Ident(ident), IdentLoc(iloc), Param(param), + DefaultArgTokens(DefArgTokens) {} + }; + + struct TypeAndRange { + ActionBase::TypeTy *Ty; + SourceRange Range; + }; + + struct FunctionTypeInfo { + /// hasPrototype - This is true if the function had at least one typed + /// argument. If the function is () or (a,b,c), then it has no prototype, + /// and is treated as a K&R-style function. + bool hasPrototype : 1; + + /// isVariadic - If this function has a prototype, and if that + /// proto ends with ',...)', this is true. When true, EllipsisLoc + /// contains the location of the ellipsis. + bool isVariadic : 1; + + /// The type qualifiers: const/volatile/restrict. + /// The qualifier bitmask values are the same as in QualType. + unsigned TypeQuals : 3; + + /// hasExceptionSpec - True if the function has an exception specification. + bool hasExceptionSpec : 1; + + /// hasAnyExceptionSpec - True if the function has a throw(...) specifier. + bool hasAnyExceptionSpec : 1; + + /// DeleteArgInfo - If this is true, we need to delete[] ArgInfo. + bool DeleteArgInfo : 1; + + /// When isVariadic is true, the location of the ellipsis in the source. + unsigned EllipsisLoc; + + /// NumArgs - This is the number of formal arguments provided for the + /// declarator. + unsigned NumArgs; + + /// NumExceptions - This is the number of types in the exception-decl, if + /// the function has one. + unsigned NumExceptions; + + /// ThrowLoc - When hasExceptionSpec is true, the location of the throw + /// keyword introducing the spec. + unsigned ThrowLoc; + + /// ArgInfo - This is a pointer to a new[]'d array of ParamInfo objects that + /// describe the arguments for this function declarator. This is null if + /// there are no arguments specified. + ParamInfo *ArgInfo; + + /// Exceptions - This is a pointer to a new[]'d array of TypeAndRange + /// objects that contain the types in the function's exception + /// specification and their locations. + TypeAndRange *Exceptions; + + /// freeArgs - reset the argument list to having zero arguments. This is + /// used in various places for error recovery. + void freeArgs() { + if (DeleteArgInfo) { + delete[] ArgInfo; + DeleteArgInfo = false; + } + NumArgs = 0; + } + + void destroy() { + if (DeleteArgInfo) + delete[] ArgInfo; + delete[] Exceptions; + } + + SourceLocation getEllipsisLoc() const { + return SourceLocation::getFromRawEncoding(EllipsisLoc); + } + SourceLocation getThrowLoc() const { + return SourceLocation::getFromRawEncoding(ThrowLoc); + } + }; + + struct BlockPointerTypeInfo { + /// For now, sema will catch these as invalid. + /// The type qualifiers: const/volatile/restrict. + unsigned TypeQuals : 3; + AttributeList *AttrList; + void destroy() { + delete AttrList; + } + }; + + struct MemberPointerTypeInfo { + /// The type qualifiers: const/volatile/restrict. + unsigned TypeQuals : 3; + AttributeList *AttrList; + // CXXScopeSpec has a constructor, so it can't be a direct member. + // So we need some pointer-aligned storage and a bit of trickery. + union { + void *Aligner; + char Mem[sizeof(CXXScopeSpec)]; + } ScopeMem; + CXXScopeSpec &Scope() { + return *reinterpret_cast<CXXScopeSpec*>(ScopeMem.Mem); + } + const CXXScopeSpec &Scope() const { + return *reinterpret_cast<const CXXScopeSpec*>(ScopeMem.Mem); + } + void destroy() { + delete AttrList; + Scope().~CXXScopeSpec(); + } + }; + + union { + PointerTypeInfo Ptr; + ReferenceTypeInfo Ref; + ArrayTypeInfo Arr; + FunctionTypeInfo Fun; + BlockPointerTypeInfo Cls; + MemberPointerTypeInfo Mem; + }; + + void destroy() { + switch (Kind) { + default: assert(0 && "Unknown decl type!"); + case DeclaratorChunk::Function: return Fun.destroy(); + case DeclaratorChunk::Pointer: return Ptr.destroy(); + case DeclaratorChunk::BlockPointer: return Cls.destroy(); + case DeclaratorChunk::Reference: return Ref.destroy(); + case DeclaratorChunk::Array: return Arr.destroy(); + case DeclaratorChunk::MemberPointer: return Mem.destroy(); + } + } + + /// getAttrs - If there are attributes applied to this declaratorchunk, return + /// them. + const AttributeList *getAttrs() const { + switch (Kind) { + default: assert(0 && "Unknown declarator kind!"); + case Pointer: return Ptr.AttrList; + case Reference: return Ref.AttrList; + case MemberPointer: return Mem.AttrList; + case Array: return 0; + case Function: return 0; + case BlockPointer: return Cls.AttrList; + } + } + + + /// getPointer - Return a DeclaratorChunk for a pointer. + /// + static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, + AttributeList *AL) { + DeclaratorChunk I; + I.Kind = Pointer; + I.Loc = Loc; + I.Ptr.TypeQuals = TypeQuals; + I.Ptr.AttrList = AL; + return I; + } + + /// getReference - Return a DeclaratorChunk for a reference. + /// + static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc, + AttributeList *AL, bool lvalue) { + DeclaratorChunk I; + I.Kind = Reference; + I.Loc = Loc; + I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; + I.Ref.LValueRef = lvalue; + I.Ref.AttrList = AL; + return I; + } + + /// getArray - Return a DeclaratorChunk for an array. + /// + static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic, + bool isStar, void *NumElts, + SourceLocation Loc) { + DeclaratorChunk I; + I.Kind = Array; + I.Loc = Loc; + I.Arr.TypeQuals = TypeQuals; + I.Arr.hasStatic = isStatic; + I.Arr.isStar = isStar; + I.Arr.NumElts = NumElts; + return I; + } + + /// DeclaratorChunk::getFunction - Return a DeclaratorChunk for a function. + /// "TheDeclarator" is the declarator that this will be added to. + static DeclaratorChunk getFunction(bool hasProto, bool isVariadic, + SourceLocation EllipsisLoc, + ParamInfo *ArgInfo, unsigned NumArgs, + unsigned TypeQuals, bool hasExceptionSpec, + SourceLocation ThrowLoc, + bool hasAnyExceptionSpec, + ActionBase::TypeTy **Exceptions, + SourceRange *ExceptionRanges, + unsigned NumExceptions, SourceLocation Loc, + Declarator &TheDeclarator); + + /// getBlockPointer - Return a DeclaratorChunk for a block. + /// + static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc, + AttributeList *AL) { + DeclaratorChunk I; + I.Kind = BlockPointer; + I.Loc = Loc; + I.Cls.TypeQuals = TypeQuals; + I.Cls.AttrList = AL; + return I; + } + + static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS, + unsigned TypeQuals, + SourceLocation Loc, + AttributeList *AL) { + DeclaratorChunk I; + I.Kind = MemberPointer; + I.Loc = Loc; + I.Mem.TypeQuals = TypeQuals; + I.Mem.AttrList = AL; + new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS); + return I; + } +}; + +/// Declarator - Information about one declarator, including the parsed type +/// information and the identifier. When the declarator is fully formed, this +/// is turned into the appropriate Decl object. +/// +/// Declarators come in two types: normal declarators and abstract declarators. +/// Abstract declarators are used when parsing types, and don't have an +/// identifier. Normal declarators do have ID's. +/// +/// Instances of this class should be a transient object that lives on the +/// stack, not objects that are allocated in large quantities on the heap. +class Declarator { +public: + enum TheContext { + FileContext, // File scope declaration. + PrototypeContext, // Within a function prototype. + KNRTypeListContext, // K&R type definition list for formals. + TypeNameContext, // Abstract declarator for types. + MemberContext, // Struct/Union field. + BlockContext, // Declaration within a block in a function. + ForContext, // Declaration within first part of a for loop. + ConditionContext, // Condition declaration in a C++ if/switch/while/for. + TemplateParamContext,// Within a template parameter list. + CXXCatchContext, // C++ catch exception-declaration + BlockLiteralContext // Block literal declarator. + }; + + /// DeclaratorKind - The kind of declarator this represents. + enum DeclaratorKind { + DK_Abstract, // An abstract declarator (has no identifier) + DK_Normal, // A normal declarator (has an identifier). + DK_Constructor, // A C++ constructor (identifier is the class name) + DK_Destructor, // A C++ destructor (identifier is ~class name) + DK_Operator, // A C++ overloaded operator name + DK_Conversion // A C++ conversion function (identifier is + // "operator " then the type name) + }; + +private: + const DeclSpec &DS; + CXXScopeSpec SS; + IdentifierInfo *Identifier; + SourceLocation IdentifierLoc; + SourceRange Range; + + /// Context - Where we are parsing this declarator. + /// + TheContext Context; + + /// Kind - What kind of declarator this is. + DeclaratorKind Kind; + + /// DeclTypeInfo - This holds each type that the declarator includes as it is + /// parsed. This is pushed from the identifier out, which means that element + /// #0 will be the most closely bound to the identifier, and + /// DeclTypeInfo.back() will be the least closely bound. + llvm::SmallVector<DeclaratorChunk, 8> DeclTypeInfo; + + /// InvalidType - Set by Sema::GetTypeForDeclarator(). + bool InvalidType : 1; + + /// GroupingParens - Set by Parser::ParseParenDeclarator(). + bool GroupingParens : 1; + + /// AttrList - Attributes. + AttributeList *AttrList; + + /// AsmLabel - The asm label, if specified. + ActionBase::ExprTy *AsmLabel; + + union { + // When Kind is DK_Constructor, DK_Destructor, or DK_Conversion, the + // type associated with the constructor, destructor, or conversion + // operator. + ActionBase::TypeTy *Type; + + /// When Kind is DK_Operator, this is the actual overloaded + /// operator that this declarator names. + OverloadedOperatorKind OperatorKind; + }; + + /// InlineParams - This is a local array used for the first function decl + /// chunk to avoid going to the heap for the common case when we have one + /// function chunk in the declarator. + DeclaratorChunk::ParamInfo InlineParams[16]; + bool InlineParamsUsed; + + friend struct DeclaratorChunk; + +public: + Declarator(const DeclSpec &ds, TheContext C) + : DS(ds), Identifier(0), Range(ds.getSourceRange()), Context(C), + Kind(DK_Abstract), + InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), + GroupingParens(false), AttrList(0), AsmLabel(0), Type(0), + InlineParamsUsed(false) { + } + + ~Declarator() { + clear(); + } + + /// getDeclSpec - Return the declaration-specifier that this declarator was + /// declared with. + const DeclSpec &getDeclSpec() const { return DS; } + + /// getMutableDeclSpec - Return a non-const version of the DeclSpec. This + /// should be used with extreme care: declspecs can often be shared between + /// multiple declarators, so mutating the DeclSpec affects all of the + /// Declarators. This should only be done when the declspec is known to not + /// be shared or when in error recovery etc. + DeclSpec &getMutableDeclSpec() { return const_cast<DeclSpec &>(DS); } + + /// getCXXScopeSpec - Return the C++ scope specifier (global scope or + /// nested-name-specifier) that is part of the declarator-id. + const CXXScopeSpec &getCXXScopeSpec() const { return SS; } + CXXScopeSpec &getCXXScopeSpec() { return SS; } + + TheContext getContext() const { return Context; } + DeclaratorKind getKind() const { return Kind; } + + /// getSourceRange - Get the source range that spans this declarator. + const SourceRange &getSourceRange() const { return Range; } + + void SetSourceRange(SourceRange R) { Range = R; } + /// SetRangeBegin - Set the start of the source range to Loc, unless it's + /// invalid. + void SetRangeBegin(SourceLocation Loc) { + if (!Loc.isInvalid()) + Range.setBegin(Loc); + } + /// SetRangeEnd - Set the end of the source range to Loc, unless it's invalid. + void SetRangeEnd(SourceLocation Loc) { + if (!Loc.isInvalid()) + Range.setEnd(Loc); + } + /// ExtendWithDeclSpec - Extend the declarator source range to include the + /// given declspec, unless its location is invalid. Adopts the range start if + /// the current range start is invalid. + void ExtendWithDeclSpec(const DeclSpec &DS) { + const SourceRange &SR = DS.getSourceRange(); + if (Range.getBegin().isInvalid()) + Range.setBegin(SR.getBegin()); + if (!SR.getEnd().isInvalid()) + Range.setEnd(SR.getEnd()); + } + + /// clear - Reset the contents of this Declarator. + void clear() { + SS.clear(); + Identifier = 0; + IdentifierLoc = SourceLocation(); + Range = DS.getSourceRange(); + Kind = DK_Abstract; + + for (unsigned i = 0, e = DeclTypeInfo.size(); i != e; ++i) + DeclTypeInfo[i].destroy(); + DeclTypeInfo.clear(); + delete AttrList; + AttrList = 0; + AsmLabel = 0; + Type = 0; + InlineParamsUsed = false; + } + + /// mayOmitIdentifier - Return true if the identifier is either optional or + /// not allowed. This is true for typenames, prototypes, and template + /// parameter lists. + bool mayOmitIdentifier() const { + return Context == TypeNameContext || Context == PrototypeContext || + Context == TemplateParamContext || Context == CXXCatchContext || + Context == BlockLiteralContext; + } + + /// mayHaveIdentifier - Return true if the identifier is either optional or + /// required. This is true for normal declarators and prototypes, but not + /// typenames. + bool mayHaveIdentifier() const { + return Context != TypeNameContext && Context != BlockLiteralContext; + } + + /// mayBeFollowedByCXXDirectInit - Return true if the declarator can be + /// followed by a C++ direct initializer, e.g. "int x(1);". + bool mayBeFollowedByCXXDirectInit() const { + return !hasGroupingParens() && + (Context == FileContext || + Context == BlockContext || + Context == ForContext); + } + + /// isPastIdentifier - Return true if we have parsed beyond the point where + /// the + bool isPastIdentifier() const { return IdentifierLoc.isValid(); } + + /// hasName - Whether this declarator has a name, which might be an + /// identifier (accessible via getIdentifier()) or some kind of + /// special C++ name (constructor, destructor, etc.). + bool hasName() const { return getKind() != DK_Abstract; } + + IdentifierInfo *getIdentifier() const { return Identifier; } + SourceLocation getIdentifierLoc() const { return IdentifierLoc; } + + void SetIdentifier(IdentifierInfo *ID, SourceLocation Loc) { + Identifier = ID; + IdentifierLoc = Loc; + if (ID) + Kind = DK_Normal; + else + Kind = DK_Abstract; + SetRangeEnd(Loc); + } + + /// setConstructor - Set this declarator to be a C++ constructor + /// declarator. Also extends the range. + void setConstructor(ActionBase::TypeTy *Ty, SourceLocation Loc) { + IdentifierLoc = Loc; + Kind = DK_Constructor; + Type = Ty; + SetRangeEnd(Loc); + } + + /// setDestructor - Set this declarator to be a C++ destructor + /// declarator. Also extends the range to End, which should be the identifier + /// token. + void setDestructor(ActionBase::TypeTy *Ty, SourceLocation Loc, + SourceLocation EndLoc) { + IdentifierLoc = Loc; + Kind = DK_Destructor; + Type = Ty; + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); + } + + /// setConversionFunction - Set this declarator to be a C++ + /// conversion function declarator (e.g., @c operator int const *). + /// Also extends the range to EndLoc, which should be the last token of the + /// type name. + void setConversionFunction(ActionBase::TypeTy *Ty, SourceLocation Loc, + SourceLocation EndLoc) { + Identifier = 0; + IdentifierLoc = Loc; + Kind = DK_Conversion; + Type = Ty; + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); + } + + /// setOverloadedOperator - Set this declaration to be a C++ + /// overloaded operator declarator (e.g., @c operator+). + /// Also extends the range to EndLoc, which should be the last token of the + /// operator. + void setOverloadedOperator(OverloadedOperatorKind Op, SourceLocation Loc, + SourceLocation EndLoc) { + IdentifierLoc = Loc; + Kind = DK_Operator; + OperatorKind = Op; + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); + } + + /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to + /// EndLoc, which should be the last token of the chunk. + void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) { + DeclTypeInfo.push_back(TI); + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); + } + + /// getNumTypeObjects() - Return the number of types applied to this + /// declarator. + unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); } + + /// Return the specified TypeInfo from this declarator. TypeInfo #0 is + /// closest to the identifier. + const DeclaratorChunk &getTypeObject(unsigned i) const { + assert(i < DeclTypeInfo.size() && "Invalid type chunk"); + return DeclTypeInfo[i]; + } + DeclaratorChunk &getTypeObject(unsigned i) { + assert(i < DeclTypeInfo.size() && "Invalid type chunk"); + return DeclTypeInfo[i]; + } + + /// isFunctionDeclarator - Once this declarator is fully parsed and formed, + /// this method returns true if the identifier is a function declarator. + bool isFunctionDeclarator() const { + return !DeclTypeInfo.empty() && + DeclTypeInfo[0].Kind == DeclaratorChunk::Function; + } + + /// AddAttributes - simply adds the attribute list to the Declarator. + /// These examples both add 3 attributes to "var": + /// short int var __attribute__((aligned(16),common,deprecated)); + /// short int x, __attribute__((aligned(16)) var + /// __attribute__((common,deprecated)); + /// + /// Also extends the range of the declarator. + void AddAttributes(AttributeList *alist, SourceLocation LastLoc) { + if (!alist) + return; // we parsed __attribute__(()) or had a syntax error + + if (AttrList) + alist->addAttributeList(AttrList); + AttrList = alist; + + if (!LastLoc.isInvalid()) + SetRangeEnd(LastLoc); + } + + const AttributeList *getAttributes() const { return AttrList; } + AttributeList *getAttributes() { return AttrList; } + + void setAsmLabel(ActionBase::ExprTy *E) { AsmLabel = E; } + ActionBase::ExprTy *getAsmLabel() const { return AsmLabel; } + + ActionBase::TypeTy *getDeclaratorIdType() const { return Type; } + + OverloadedOperatorKind getOverloadedOperator() const { return OperatorKind; } + + void setInvalidType(bool Val = true) { InvalidType = Val; } + bool isInvalidType() const { + return InvalidType || DS.getTypeSpecType() == DeclSpec::TST_error; + } + + void setGroupingParens(bool flag) { GroupingParens = flag; } + bool hasGroupingParens() const { return GroupingParens; } +}; + +/// FieldDeclarator - This little struct is used to capture information about +/// structure field declarators, which is basically just a bitfield size. +struct FieldDeclarator { + Declarator D; + ActionBase::ExprTy *BitfieldSize; + explicit FieldDeclarator(DeclSpec &DS) : D(DS, Declarator::MemberContext) { + BitfieldSize = 0; + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Parse/Designator.h b/include/clang/Parse/Designator.h new file mode 100644 index 0000000..026286d --- /dev/null +++ b/include/clang/Parse/Designator.h @@ -0,0 +1,239 @@ +//===--- Designator.h - Initialization Designator ---------------*- 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 interfaces used to represent Designators in the parser and +// is the input to Actions module. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_DESIGNATOR_H +#define LLVM_CLANG_PARSE_DESIGNATOR_H + +#include "clang/Parse/Action.h" + +namespace clang { + +/// Designator - This class is a discriminated union which holds the various +/// different sorts of designators possible. A Designation is an array of +/// these. An example of a designator are things like this: +/// [8] .field [47] // C99 designation: 3 designators +/// [8 ... 47] field: // GNU extensions: 2 designators +/// These occur in initializers, e.g.: +/// int a[10] = {2, 4, [8]=9, 10}; +/// +class Designator { +public: + enum DesignatorKind { + FieldDesignator, ArrayDesignator, ArrayRangeDesignator + }; +private: + DesignatorKind Kind; + + struct FieldDesignatorInfo { + const IdentifierInfo *II; + unsigned DotLoc; + unsigned NameLoc; + }; + struct ArrayDesignatorInfo { + ActionBase::ExprTy *Index; + unsigned LBracketLoc; + mutable unsigned RBracketLoc; + }; + struct ArrayRangeDesignatorInfo { + ActionBase::ExprTy *Start, *End; + unsigned LBracketLoc, EllipsisLoc; + mutable unsigned RBracketLoc; + }; + + union { + FieldDesignatorInfo FieldInfo; + ArrayDesignatorInfo ArrayInfo; + ArrayRangeDesignatorInfo ArrayRangeInfo; + }; + +public: + + DesignatorKind getKind() const { return Kind; } + bool isFieldDesignator() const { return Kind == FieldDesignator; } + bool isArrayDesignator() const { return Kind == ArrayDesignator; } + bool isArrayRangeDesignator() const { return Kind == ArrayRangeDesignator; } + + const IdentifierInfo *getField() const { + assert(isFieldDesignator() && "Invalid accessor"); + return FieldInfo.II; + } + + SourceLocation getDotLoc() const { + assert(isFieldDesignator() && "Invalid accessor"); + return SourceLocation::getFromRawEncoding(FieldInfo.DotLoc); + } + + SourceLocation getFieldLoc() const { + assert(isFieldDesignator() && "Invalid accessor"); + return SourceLocation::getFromRawEncoding(FieldInfo.NameLoc); + } + + ActionBase::ExprTy *getArrayIndex() const { + assert(isArrayDesignator() && "Invalid accessor"); + return ArrayInfo.Index; + } + + ActionBase::ExprTy *getArrayRangeStart() const { + assert(isArrayRangeDesignator() && "Invalid accessor"); + return ArrayRangeInfo.Start; + } + ActionBase::ExprTy *getArrayRangeEnd() const { + assert(isArrayRangeDesignator() && "Invalid accessor"); + return ArrayRangeInfo.End; + } + + SourceLocation getLBracketLoc() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && + "Invalid accessor"); + if (isArrayDesignator()) + return SourceLocation::getFromRawEncoding(ArrayInfo.LBracketLoc); + else + return SourceLocation::getFromRawEncoding(ArrayRangeInfo.LBracketLoc); + } + + SourceLocation getRBracketLoc() const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && + "Invalid accessor"); + if (isArrayDesignator()) + return SourceLocation::getFromRawEncoding(ArrayInfo.RBracketLoc); + else + return SourceLocation::getFromRawEncoding(ArrayRangeInfo.RBracketLoc); + } + + SourceLocation getEllipsisLoc() const { + assert(isArrayRangeDesignator() && "Invalid accessor"); + return SourceLocation::getFromRawEncoding(ArrayRangeInfo.EllipsisLoc); + } + + static Designator getField(const IdentifierInfo *II, SourceLocation DotLoc, + SourceLocation NameLoc) { + Designator D; + D.Kind = FieldDesignator; + D.FieldInfo.II = II; + D.FieldInfo.DotLoc = DotLoc.getRawEncoding(); + D.FieldInfo.NameLoc = NameLoc.getRawEncoding(); + return D; + } + + static Designator getArray(ActionBase::ExprTy *Index, + SourceLocation LBracketLoc) { + Designator D; + D.Kind = ArrayDesignator; + D.ArrayInfo.Index = Index; + D.ArrayInfo.LBracketLoc = LBracketLoc.getRawEncoding(); + D.ArrayInfo.RBracketLoc = 0; + return D; + } + + static Designator getArrayRange(ActionBase::ExprTy *Start, + ActionBase::ExprTy *End, + SourceLocation LBracketLoc, + SourceLocation EllipsisLoc) { + Designator D; + D.Kind = ArrayRangeDesignator; + D.ArrayRangeInfo.Start = Start; + D.ArrayRangeInfo.End = End; + D.ArrayRangeInfo.LBracketLoc = LBracketLoc.getRawEncoding(); + D.ArrayRangeInfo.EllipsisLoc = EllipsisLoc.getRawEncoding(); + D.ArrayRangeInfo.RBracketLoc = 0; + return D; + } + + void setRBracketLoc(SourceLocation RBracketLoc) const { + assert((isArrayDesignator() || isArrayRangeDesignator()) && + "Invalid accessor"); + if (isArrayDesignator()) + ArrayInfo.RBracketLoc = RBracketLoc.getRawEncoding(); + else + ArrayRangeInfo.RBracketLoc = RBracketLoc.getRawEncoding(); + } + + /// ClearExprs - Null out any expression references, which prevents them from + /// being 'delete'd later. + void ClearExprs(Action &Actions) { + switch (Kind) { + case FieldDesignator: return; + case ArrayDesignator: + ArrayInfo.Index = 0; + return; + case ArrayRangeDesignator: + ArrayRangeInfo.Start = 0; + ArrayRangeInfo.End = 0; + return; + } + } + + /// FreeExprs - Release any unclaimed memory for the expressions in this + /// designator. + void FreeExprs(Action &Actions) { + switch (Kind) { + case FieldDesignator: return; // nothing to free. + case ArrayDesignator: + Actions.DeleteExpr(getArrayIndex()); + return; + case ArrayRangeDesignator: + Actions.DeleteExpr(getArrayRangeStart()); + Actions.DeleteExpr(getArrayRangeEnd()); + return; + } + } +}; + + +/// Designation - Represent a full designation, which is a sequence of +/// designators. This class is mostly a helper for InitListDesignations. +class Designation { + /// InitIndex - The index of the initializer expression this is for. For + /// example, if the initializer were "{ A, .foo=B, C }" a Designation would + /// exist with InitIndex=1, because element #1 has a designation. + unsigned InitIndex; + + /// Designators - The actual designators for this initializer. + llvm::SmallVector<Designator, 2> Designators; + + Designation(unsigned Idx) : InitIndex(Idx) {} +public: + Designation() : InitIndex(4000) {} + + /// AddDesignator - Add a designator to the end of this list. + void AddDesignator(Designator D) { + Designators.push_back(D); + } + + bool empty() const { return Designators.empty(); } + + unsigned getNumDesignators() const { return Designators.size(); } + const Designator &getDesignator(unsigned Idx) const { + assert(Idx < Designators.size()); + return Designators[Idx]; + } + + /// ClearExprs - Null out any expression references, which prevents them from + /// being 'delete'd later. + void ClearExprs(Action &Actions) { + for (unsigned i = 0, e = Designators.size(); i != e; ++i) + Designators[i].ClearExprs(Actions); + } + + /// FreeExprs - Release any unclaimed memory for the expressions in this + /// designation. + void FreeExprs(Action &Actions) { + for (unsigned i = 0, e = Designators.size(); i != e; ++i) + Designators[i].FreeExprs(Actions); + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Parse/Ownership.h b/include/clang/Parse/Ownership.h new file mode 100644 index 0000000..5951793 --- /dev/null +++ b/include/clang/Parse/Ownership.h @@ -0,0 +1,830 @@ +//===--- Ownership.h - Parser Ownership Helpers -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains classes for managing ownership of Stmt and Expr nodes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_OWNERSHIP_H +#define LLVM_CLANG_PARSE_OWNERSHIP_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/PointerIntPair.h" + +//===----------------------------------------------------------------------===// +// OpaquePtr +//===----------------------------------------------------------------------===// + +namespace clang { + class ActionBase; + + /// OpaquePtr - This is a very simple POD type that wraps a pointer that the + /// Parser doesn't know about but that Sema or another client does. The UID + /// template argument is used to make sure that "Decl" pointers are not + /// compatible with "Type" pointers for example. + template<int UID> + class OpaquePtr { + void *Ptr; + public: + OpaquePtr() : Ptr(0) {} + + template <typename T> + T* getAs() const { + return llvm::PointerLikeTypeTraits<T*>::getFromVoidPointer(Ptr); + } + + template <typename T> + T getAsVal() const { + return llvm::PointerLikeTypeTraits<T>::getFromVoidPointer(Ptr); + } + + void *get() const { return Ptr; } + + template<typename T> + static OpaquePtr make(T P) { + OpaquePtr R; R.set(P); return R; + } + + template<typename T> + void set(T P) { + Ptr = llvm::PointerLikeTypeTraits<T>::getAsVoidPointer(P); + } + + operator bool() const { return Ptr != 0; } + }; +} + +namespace llvm { + template <int UID> + class PointerLikeTypeTraits<clang::OpaquePtr<UID> > { + public: + static inline void *getAsVoidPointer(clang::OpaquePtr<UID> P) { + // FIXME: Doesn't work? return P.getAs< void >(); + return P.get(); + } + static inline clang::OpaquePtr<UID> getFromVoidPointer(void *P) { + return clang::OpaquePtr<UID>::make(P); + } + enum { NumLowBitsAvailable = 3 }; + }; +} + + + +// -------------------------- About Move Emulation -------------------------- // +// The smart pointer classes in this file attempt to emulate move semantics +// as they appear in C++0x with rvalue references. Since C++03 doesn't have +// rvalue references, some tricks are needed to get similar results. +// Move semantics in C++0x have the following properties: +// 1) "Moving" means transferring the value of an object to another object, +// similar to copying, but without caring what happens to the old object. +// In particular, this means that the new object can steal the old object's +// resources instead of creating a copy. +// 2) Since moving can modify the source object, it must either be explicitly +// requested by the user, or the modifications must be unnoticeable. +// 3) As such, C++0x moving is only allowed in three contexts: +// * By explicitly using std::move() to request it. +// * From a temporary object, since that object cannot be accessed +// afterwards anyway, thus making the state unobservable. +// * On function return, since the object is not observable afterwards. +// +// To sum up: moving from a named object should only be possible with an +// explicit std::move(), or on function return. Moving from a temporary should +// be implicitly done. Moving from a const object is forbidden. +// +// The emulation is not perfect, and has the following shortcomings: +// * move() is not in namespace std. +// * move() is required on function return. +// * There are difficulties with implicit conversions. +// * Microsoft's compiler must be given the /Za switch to successfully compile. +// +// -------------------------- Implementation -------------------------------- // +// The move emulation relies on the peculiar reference binding semantics of +// C++03: as a rule, a non-const reference may not bind to a temporary object, +// except for the implicit object parameter in a member function call, which +// can refer to a temporary even when not being const. +// The moveable object has five important functions to facilitate moving: +// * A private, unimplemented constructor taking a non-const reference to its +// own class. This constructor serves a two-fold purpose. +// - It prevents the creation of a copy constructor that takes a const +// reference. Temporaries would be able to bind to the argument of such a +// constructor, and that would be bad. +// - Named objects will bind to the non-const reference, but since it's +// private, this will fail to compile. This prevents implicit moving from +// named objects. +// There's also a copy assignment operator for the same purpose. +// * An implicit, non-const conversion operator to a special mover type. This +// type represents the rvalue reference of C++0x. Being a non-const member, +// its implicit this parameter can bind to temporaries. +// * A constructor that takes an object of this mover type. This constructor +// performs the actual move operation. There is an equivalent assignment +// operator. +// There is also a free move() function that takes a non-const reference to +// an object and returns a temporary. Internally, this function uses explicit +// constructor calls to move the value from the referenced object to the return +// value. +// +// There are now three possible scenarios of use. +// * Copying from a const object. Constructor overload resolution will find the +// non-const copy constructor, and the move constructor. The first is not +// viable because the const object cannot be bound to the non-const reference. +// The second fails because the conversion to the mover object is non-const. +// Moving from a const object fails as intended. +// * Copying from a named object. Constructor overload resolution will select +// the non-const copy constructor, but fail as intended, because this +// constructor is private. +// * Copying from a temporary. Constructor overload resolution cannot select +// the non-const copy constructor, because the temporary cannot be bound to +// the non-const reference. It thus selects the move constructor. The +// temporary can be bound to the implicit this parameter of the conversion +// operator, because of the special binding rule. Construction succeeds. +// Note that the Microsoft compiler, as an extension, allows binding +// temporaries against non-const references. The compiler thus selects the +// non-const copy constructor and fails, because the constructor is private. +// Passing /Za (disable extensions) disables this behaviour. +// The free move() function is used to move from a named object. +// +// Note that when passing an object of a different type (the classes below +// have OwningResult and OwningPtr, which should be mixable), you get a problem. +// Argument passing and function return use copy initialization rules. The +// effect of this is that, when the source object is not already of the target +// type, the compiler will first seek a way to convert the source object to the +// target type, and only then attempt to copy the resulting object. This means +// that when passing an OwningResult where an OwningPtr is expected, the +// compiler will first seek a conversion from OwningResult to OwningPtr, then +// copy the OwningPtr. The resulting conversion sequence is: +// OwningResult object -> ResultMover -> OwningResult argument to +// OwningPtr(OwningResult) -> OwningPtr -> PtrMover -> final OwningPtr +// This conversion sequence is too complex to be allowed. Thus the special +// move_* functions, which help the compiler out with some explicit +// conversions. + +// Flip this switch to measure performance impact of the smart pointers. +//#define DISABLE_SMART_POINTERS + +namespace llvm { + template<> + class PointerLikeTypeTraits<clang::ActionBase*> { + typedef clang::ActionBase* PT; + public: + static inline void *getAsVoidPointer(PT P) { return P; } + static inline PT getFromVoidPointer(void *P) { + return static_cast<PT>(P); + } + enum { NumLowBitsAvailable = 2 }; + }; +} + +namespace clang { + // Basic + class DiagnosticBuilder; + + // Determines whether the low bit of the result pointer for the + // given UID is always zero. If so, ActionResult will use that bit + // for it's "invalid" flag. + template<unsigned UID> + struct IsResultPtrLowBitFree { + static const bool value = false; + }; + + /// ActionBase - A small part split from Action because of the horrible + /// definition order dependencies between Action and the smart pointers. + class ActionBase { + public: + /// Out-of-line virtual destructor to provide home for this class. + virtual ~ActionBase(); + + // Types - Though these don't actually enforce strong typing, they document + // what types are required to be identical for the actions. + typedef OpaquePtr<0> DeclPtrTy; + typedef OpaquePtr<1> DeclGroupPtrTy; + typedef OpaquePtr<2> TemplateTy; + typedef void AttrTy; + typedef void BaseTy; + typedef void MemInitTy; + typedef void ExprTy; + typedef void StmtTy; + typedef void TemplateParamsTy; + typedef void CXXScopeTy; + typedef void TypeTy; // FIXME: Change TypeTy to use OpaquePtr<N>. + + /// ActionResult - This structure is used while parsing/acting on + /// expressions, stmts, etc. It encapsulates both the object returned by + /// the action, plus a sense of whether or not it is valid. + /// When CompressInvalid is true, the "invalid" flag will be + /// stored in the low bit of the Val pointer. + template<unsigned UID, + typename PtrTy = void*, + bool CompressInvalid = IsResultPtrLowBitFree<UID>::value> + class ActionResult { + PtrTy Val; + bool Invalid; + + public: + ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {} + template<typename ActualExprTy> + ActionResult(ActualExprTy val) : Val(val), Invalid(false) {} + ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {} + + PtrTy get() const { return Val; } + void set(PtrTy V) { Val = V; } + bool isInvalid() const { return Invalid; } + + const ActionResult &operator=(PtrTy RHS) { + Val = RHS; + Invalid = false; + return *this; + } + }; + + // This ActionResult partial specialization places the "invalid" + // flag into the low bit of the pointer. + template<unsigned UID, typename PtrTy> + class ActionResult<UID, PtrTy, true> { + // A pointer whose low bit is 1 if this result is invalid, 0 + // otherwise. + uintptr_t PtrWithInvalid; + typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits; + public: + ActionResult(bool Invalid = false) + : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { } + + template<typename ActualExprTy> + ActionResult(ActualExprTy *val) { + PtrTy V(val); + void *VP = PtrTraits::getAsVoidPointer(V); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + } + + ActionResult(PtrTy V) { + void *VP = PtrTraits::getAsVoidPointer(V); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + } + + ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { } + + PtrTy get() const { + void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01); + return PtrTraits::getFromVoidPointer(VP); + } + + void set(PtrTy V) { + void *VP = PtrTraits::getAsVoidPointer(V); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + } + + bool isInvalid() const { return PtrWithInvalid & 0x01; } + + const ActionResult &operator=(PtrTy RHS) { + void *VP = PtrTraits::getAsVoidPointer(RHS); + PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); + assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); + return *this; + } + }; + + /// Deletion callbacks - Since the parser doesn't know the concrete types of + /// the AST nodes being generated, it must do callbacks to delete objects + /// when recovering from errors. These are in ActionBase because the smart + /// pointers need access to them. + virtual void DeleteExpr(ExprTy *E) {} + virtual void DeleteStmt(StmtTy *S) {} + virtual void DeleteTemplateParams(TemplateParamsTy *P) {} + }; + + /// ASTDestroyer - The type of an AST node destruction function pointer. + typedef void (ActionBase::*ASTDestroyer)(void *); + + /// For the transition phase: translate from an ASTDestroyer to its + /// ActionResult UID. + template <ASTDestroyer Destroyer> struct DestroyerToUID; + template <> struct DestroyerToUID<&ActionBase::DeleteExpr> { + static const unsigned UID = 0; + }; + template <> struct DestroyerToUID<&ActionBase::DeleteStmt> { + static const unsigned UID = 1; + }; + /// ASTOwningResult - A moveable smart pointer for AST nodes that also + /// has an extra flag to indicate an additional success status. + template <ASTDestroyer Destroyer> class ASTOwningResult; + + /// ASTMultiPtr - A moveable smart pointer to multiple AST nodes. Only owns + /// the individual pointers, not the array holding them. + template <ASTDestroyer Destroyer> class ASTMultiPtr; + +#if !defined(DISABLE_SMART_POINTERS) + namespace moving { + /// Move emulation helper for ASTOwningResult. NEVER EVER use this class + /// directly if you don't know what you're doing. + template <ASTDestroyer Destroyer> + class ASTResultMover + { + ASTOwningResult<Destroyer> &Moved; + + public: + ASTResultMover(ASTOwningResult<Destroyer> &moved) : Moved(moved) {} + + ASTOwningResult<Destroyer> * operator ->() { return &Moved; } + }; + + /// Move emulation helper for ASTMultiPtr. NEVER EVER use this class + /// directly if you don't know what you're doing. + template <ASTDestroyer Destroyer> + class ASTMultiMover + { + ASTMultiPtr<Destroyer> &Moved; + + public: + ASTMultiMover(ASTMultiPtr<Destroyer> &moved) : Moved(moved) {} + + ASTMultiPtr<Destroyer> * operator ->() { return &Moved; } + + /// Reset the moved object's internal structures. + void release(); + }; + } +#else + + /// Kept only as a type-safe wrapper for a void pointer, when smart pointers + /// are disabled. When they are enabled, ASTOwningResult takes over. + template <ASTDestroyer Destroyer> + class ASTOwningPtr + { + void *Node; + + public: + explicit ASTOwningPtr(ActionBase &) : Node(0) {} + ASTOwningPtr(ActionBase &, void *node) : Node(node) {} + // Normal copying operators are defined implicitly. + ASTOwningPtr(const ASTOwningResult<Destroyer> &o); + + ASTOwningPtr & operator =(void *raw) { + Node = raw; + return *this; + } + + /// Access to the raw pointer. + void * get() const { return Node; } + + /// Release the raw pointer. + void * take() { + return Node; + } + + /// Take outside ownership of the raw pointer and cast it down. + template<typename T> + T *takeAs() { + return static_cast<T*>(Node); + } + + /// Alias for interface familiarity with unique_ptr. + void * release() { + return take(); + } + }; +#endif + + // Important: There are two different implementations of + // ASTOwningResult below, depending on whether + // DISABLE_SMART_POINTERS is defined. If you make changes that + // affect the interface, be sure to compile and test both ways! + +#if !defined(DISABLE_SMART_POINTERS) + template <ASTDestroyer Destroyer> + class ASTOwningResult + { + llvm::PointerIntPair<ActionBase*, 1, bool> ActionInv; + void *Ptr; + + friend class moving::ASTResultMover<Destroyer>; + + ASTOwningResult(ASTOwningResult&); // DO NOT IMPLEMENT + ASTOwningResult& operator =(ASTOwningResult&); // DO NOT IMPLEMENT + + void destroy() { + if (Ptr) { + assert(ActionInv.getPointer() && + "Smart pointer has node but no action."); + (ActionInv.getPointer()->*Destroyer)(Ptr); + Ptr = 0; + } + } + + public: + typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult; + + explicit ASTOwningResult(ActionBase &actions, bool invalid = false) + : ActionInv(&actions, invalid), Ptr(0) {} + ASTOwningResult(ActionBase &actions, void *node) + : ActionInv(&actions, false), Ptr(node) {} + ASTOwningResult(ActionBase &actions, const DumbResult &res) + : ActionInv(&actions, res.isInvalid()), Ptr(res.get()) {} + /// Move from another owning result + ASTOwningResult(moving::ASTResultMover<Destroyer> mover) + : ActionInv(mover->ActionInv), + Ptr(mover->Ptr) { + mover->Ptr = 0; + } + + ~ASTOwningResult() { + destroy(); + } + + /// Move assignment from another owning result + ASTOwningResult &operator=(moving::ASTResultMover<Destroyer> mover) { + destroy(); + ActionInv = mover->ActionInv; + Ptr = mover->Ptr; + mover->Ptr = 0; + return *this; + } + + /// Assignment from a raw pointer. Takes ownership - beware! + ASTOwningResult &operator=(void *raw) { + destroy(); + Ptr = raw; + ActionInv.setInt(false); + return *this; + } + + /// Assignment from an ActionResult. Takes ownership - beware! + ASTOwningResult &operator=(const DumbResult &res) { + destroy(); + Ptr = res.get(); + ActionInv.setInt(res.isInvalid()); + return *this; + } + + /// Access to the raw pointer. + void *get() const { return Ptr; } + + bool isInvalid() const { return ActionInv.getInt(); } + + /// Does this point to a usable AST node? To be usable, the node must be + /// valid and non-null. + bool isUsable() const { return !isInvalid() && get(); } + + /// Take outside ownership of the raw pointer. + void *take() { + if (isInvalid()) + return 0; + void *tmp = Ptr; + Ptr = 0; + return tmp; + } + + /// Take outside ownership of the raw pointer and cast it down. + template<typename T> + T *takeAs() { + return static_cast<T*>(take()); + } + + /// Alias for interface familiarity with unique_ptr. + void *release() { return take(); } + + /// Pass ownership to a classical ActionResult. + DumbResult result() { + if (isInvalid()) + return true; + return take(); + } + + /// Move hook + operator moving::ASTResultMover<Destroyer>() { + return moving::ASTResultMover<Destroyer>(*this); + } + }; +#else + template <ASTDestroyer Destroyer> + class ASTOwningResult + { + public: + typedef ActionBase::ActionResult<DestroyerToUID<Destroyer>::UID> DumbResult; + + private: + DumbResult Result; + + public: + explicit ASTOwningResult(ActionBase &actions, bool invalid = false) + : Result(invalid) { } + ASTOwningResult(ActionBase &actions, void *node) : Result(node) { } + ASTOwningResult(ActionBase &actions, const DumbResult &res) : Result(res) { } + // Normal copying semantics are defined implicitly. + ASTOwningResult(const ASTOwningPtr<Destroyer> &o) : Result(o.get()) { } + + /// Assignment from a raw pointer. Takes ownership - beware! + ASTOwningResult & operator =(void *raw) + { + Result = raw; + return *this; + } + + /// Assignment from an ActionResult. Takes ownership - beware! + ASTOwningResult & operator =(const DumbResult &res) { + Result = res; + return *this; + } + + /// Access to the raw pointer. + void * get() const { return Result.get(); } + + bool isInvalid() const { return Result.isInvalid(); } + + /// Does this point to a usable AST node? To be usable, the node must be + /// valid and non-null. + bool isUsable() const { return !Result.isInvalid() && get(); } + + /// Take outside ownership of the raw pointer. + void * take() { + return Result.get(); + } + + /// Take outside ownership of the raw pointer and cast it down. + template<typename T> + T *takeAs() { + return static_cast<T*>(take()); + } + + /// Alias for interface familiarity with unique_ptr. + void * release() { return take(); } + + /// Pass ownership to a classical ActionResult. + DumbResult result() { return Result; } + }; +#endif + + template <ASTDestroyer Destroyer> + class ASTMultiPtr + { +#if !defined(DISABLE_SMART_POINTERS) + ActionBase &Actions; +#endif + void **Nodes; + unsigned Count; + +#if !defined(DISABLE_SMART_POINTERS) + friend class moving::ASTMultiMover<Destroyer>; + + ASTMultiPtr(ASTMultiPtr&); // DO NOT IMPLEMENT + // Reference member prevents copy assignment. + + void destroy() { + assert((Count == 0 || Nodes) && "No nodes when count is not zero."); + for (unsigned i = 0; i < Count; ++i) { + if (Nodes[i]) + (Actions.*Destroyer)(Nodes[i]); + } + } +#endif + + public: +#if !defined(DISABLE_SMART_POINTERS) + explicit ASTMultiPtr(ActionBase &actions) + : Actions(actions), Nodes(0), Count(0) {} + ASTMultiPtr(ActionBase &actions, void **nodes, unsigned count) + : Actions(actions), Nodes(nodes), Count(count) {} + /// Move constructor + ASTMultiPtr(moving::ASTMultiMover<Destroyer> mover) + : Actions(mover->Actions), Nodes(mover->Nodes), Count(mover->Count) { + mover.release(); + } +#else + // Normal copying implicitly defined + explicit ASTMultiPtr(ActionBase &) : Nodes(0), Count(0) {} + ASTMultiPtr(ActionBase &, void **nodes, unsigned count) + : Nodes(nodes), Count(count) {} + // Fake mover in Parse/AstGuard.h needs this: + ASTMultiPtr(void **nodes, unsigned count) : Nodes(nodes), Count(count) {} +#endif + +#if !defined(DISABLE_SMART_POINTERS) + /// Move assignment + ASTMultiPtr & operator =(moving::ASTMultiMover<Destroyer> mover) { + destroy(); + Nodes = mover->Nodes; + Count = mover->Count; + mover.release(); + return *this; + } +#endif + + /// Access to the raw pointers. + void ** get() const { return Nodes; } + + /// Access to the count. + unsigned size() const { return Count; } + + void ** release() { +#if !defined(DISABLE_SMART_POINTERS) + void **tmp = Nodes; + Nodes = 0; + Count = 0; + return tmp; +#else + return Nodes; +#endif + } + +#if !defined(DISABLE_SMART_POINTERS) + /// Move hook + operator moving::ASTMultiMover<Destroyer>() { + return moving::ASTMultiMover<Destroyer>(*this); + } +#endif + }; + + class ASTTemplateArgsPtr { +#if !defined(DISABLE_SMART_POINTERS) + ActionBase &Actions; +#endif + void **Args; + bool *ArgIsType; + mutable unsigned Count; + +#if !defined(DISABLE_SMART_POINTERS) + void destroy() { + if (!Count) + return; + + for (unsigned i = 0; i != Count; ++i) + if (Args[i] && !ArgIsType[i]) + Actions.DeleteExpr((ActionBase::ExprTy *)Args[i]); + + Count = 0; + } +#endif + + public: + ASTTemplateArgsPtr(ActionBase &actions, void **args, bool *argIsType, + unsigned count) : +#if !defined(DISABLE_SMART_POINTERS) + Actions(actions), +#endif + Args(args), ArgIsType(argIsType), Count(count) { } + + // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. + ASTTemplateArgsPtr(ASTTemplateArgsPtr &Other) : +#if !defined(DISABLE_SMART_POINTERS) + Actions(Other.Actions), +#endif + Args(Other.Args), ArgIsType(Other.ArgIsType), Count(Other.Count) { +#if !defined(DISABLE_SMART_POINTERS) + Other.Count = 0; +#endif + } + + // FIXME: Lame, not-fully-type-safe emulation of 'move semantics'. + ASTTemplateArgsPtr& operator=(ASTTemplateArgsPtr &Other) { +#if !defined(DISABLE_SMART_POINTERS) + Actions = Other.Actions; +#endif + Args = Other.Args; + ArgIsType = Other.ArgIsType; + Count = Other.Count; +#if !defined(DISABLE_SMART_POINTERS) + Other.Count = 0; +#endif + return *this; + } + +#if !defined(DISABLE_SMART_POINTERS) + ~ASTTemplateArgsPtr() { destroy(); } +#endif + + void **getArgs() const { return Args; } + bool *getArgIsType() const {return ArgIsType; } + unsigned size() const { return Count; } + + void reset(void **args, bool *argIsType, unsigned count) { +#if !defined(DISABLE_SMART_POINTERS) + destroy(); +#endif + Args = args; + ArgIsType = argIsType; + Count = count; + } + + void *operator[](unsigned Arg) const { return Args[Arg]; } + + void **release() const { +#if !defined(DISABLE_SMART_POINTERS) + Count = 0; +#endif + return Args; + } + }; + + /// \brief A small vector that owns a set of AST nodes. + template <ASTDestroyer Destroyer, unsigned N = 8> + class ASTOwningVector : public llvm::SmallVector<void *, N> { +#if !defined(DISABLE_SMART_POINTERS) + ActionBase &Actions; + bool Owned; +#endif + + ASTOwningVector(ASTOwningVector &); // do not implement + ASTOwningVector &operator=(ASTOwningVector &); // do not implement + + public: + explicit ASTOwningVector(ActionBase &Actions) +#if !defined(DISABLE_SMART_POINTERS) + : Actions(Actions), Owned(true) +#endif + { } + +#if !defined(DISABLE_SMART_POINTERS) + ~ASTOwningVector() { + if (!Owned) + return; + + for (unsigned I = 0, Last = this->size(); I != Last; ++I) + (Actions.*Destroyer)((*this)[I]); + } +#endif + + void **take() { +#if !defined(DISABLE_SMART_POINTERS) + Owned = false; +#endif + return &this->front(); + } + + template<typename T> T **takeAs() { return (T**)take(); } + +#if !defined(DISABLE_SMART_POINTERS) + ActionBase &getActions() const { return Actions; } +#endif + }; + + /// A SmallVector of statements, with stack size 32 (as that is the only one + /// used.) + typedef ASTOwningVector<&ActionBase::DeleteStmt, 32> StmtVector; + /// A SmallVector of expressions, with stack size 12 (the maximum used.) + typedef ASTOwningVector<&ActionBase::DeleteExpr, 12> ExprVector; + + template <ASTDestroyer Destroyer, unsigned N> inline + ASTMultiPtr<Destroyer> move_arg(ASTOwningVector<Destroyer, N> &vec) { +#if !defined(DISABLE_SMART_POINTERS) + return ASTMultiPtr<Destroyer>(vec.getActions(), vec.take(), vec.size()); +#else + return ASTMultiPtr<Destroyer>(vec.take(), vec.size()); +#endif + } + +#if !defined(DISABLE_SMART_POINTERS) + + // Out-of-line implementations due to definition dependencies + + template <ASTDestroyer Destroyer> inline + void moving::ASTMultiMover<Destroyer>::release() { + Moved.Nodes = 0; + Moved.Count = 0; + } + + // Move overloads. + + template <ASTDestroyer Destroyer> inline + ASTOwningResult<Destroyer> move(ASTOwningResult<Destroyer> &ptr) { + return ASTOwningResult<Destroyer>(moving::ASTResultMover<Destroyer>(ptr)); + } + + template <ASTDestroyer Destroyer> inline + ASTMultiPtr<Destroyer> move(ASTMultiPtr<Destroyer> &ptr) { + return ASTMultiPtr<Destroyer>(moving::ASTMultiMover<Destroyer>(ptr)); + } + +#else + + template <ASTDestroyer Destroyer> inline + ASTOwningPtr<Destroyer>::ASTOwningPtr(const ASTOwningResult<Destroyer> &o) + : Node(o.get()) + {} + + // These versions are hopefully no-ops. + template <ASTDestroyer Destroyer> inline + ASTOwningResult<Destroyer>& move(ASTOwningResult<Destroyer> &ptr) { + return ptr; + } + + template <ASTDestroyer Destroyer> inline + ASTOwningPtr<Destroyer>& move(ASTOwningPtr<Destroyer> &ptr) { + return ptr; + } + + template <ASTDestroyer Destroyer> inline + ASTMultiPtr<Destroyer>& move(ASTMultiPtr<Destroyer> &ptr) { + return ptr; + } +#endif +} + +#endif diff --git a/include/clang/Parse/ParseDiagnostic.h b/include/clang/Parse/ParseDiagnostic.h new file mode 100644 index 0000000..a85c6ad --- /dev/null +++ b/include/clang/Parse/ParseDiagnostic.h @@ -0,0 +1,27 @@ +//===--- DiagnosticParse.h - Diagnostics for libparse -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_DIAGNOSTICPARSE_H +#define LLVM_CLANG_DIAGNOSTICPARSE_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { + namespace diag { + enum { +#define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP) ENUM, +#define PARSESTART +#include "clang/Basic/DiagnosticParseKinds.inc" +#undef DIAG + NUM_BUILTIN_PARSE_DIAGNOSTICS + }; + } // end namespace diag +} // end namespace clang + +#endif diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h new file mode 100644 index 0000000..26e37e2 --- /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 diff --git a/include/clang/Parse/Scope.h b/include/clang/Parse/Scope.h new file mode 100644 index 0000000..84cc5d5 --- /dev/null +++ b/include/clang/Parse/Scope.h @@ -0,0 +1,310 @@ +//===--- Scope.h - Scope interface ------------------------------*- 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 Scope interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PARSE_SCOPE_H +#define LLVM_CLANG_PARSE_SCOPE_H + +#include "clang/Parse/Action.h" +#include "llvm/ADT/SmallPtrSet.h" + +namespace clang { + +/// Scope - A scope is a transient data structure that is used while parsing the +/// program. It assists with resolving identifiers to the appropriate +/// declaration. +/// +class Scope { +public: + /// ScopeFlags - These are bitfields that are or'd together when creating a + /// scope, which defines the sorts of things the scope contains. + enum ScopeFlags { + /// FnScope - This indicates that the scope corresponds to a function, which + /// means that labels are set here. + FnScope = 0x01, + + /// BreakScope - This is a while,do,switch,for, etc that can have break + /// stmts embedded into it. + BreakScope = 0x02, + + /// ContinueScope - This is a while,do,for, which can have continue + /// stmt embedded into it. + ContinueScope = 0x04, + + /// DeclScope - This is a scope that can contain a declaration. Some scopes + /// just contain loop constructs but don't contain decls. + DeclScope = 0x08, + + /// ControlScope - The controlling scope in a if/switch/while/for statement. + ControlScope = 0x10, + + /// ClassScope - The scope of a struct/union/class definition. + ClassScope = 0x20, + + /// BlockScope - This is a scope that corresponds to a block object. + /// Blocks serve as top-level scopes for some objects like labels, they + /// also prevent things like break and continue. BlockScopes have the + /// other flags set as well. + BlockScope = 0x40, + + /// TemplateParamScope - This is a scope that corresponds to the + /// template parameters of a C++ template. Template parameter + /// scope starts at the 'template' keyword and ends when the + /// template declaration ends. + TemplateParamScope = 0x80, + + /// FunctionPrototypeScope - This is a scope that corresponds to the + /// parameters within a function prototype. + FunctionPrototypeScope = 0x100, + + /// AtCatchScope - This is a scope that corresponds to the Objective-C + /// @catch statement. + AtCatchScope = 0x200 + }; +private: + /// The parent scope for this scope. This is null for the translation-unit + /// scope. + Scope *AnyParent; + + /// Depth - This is the depth of this scope. The translation-unit scope has + /// depth 0. + unsigned Depth : 16; + + /// Flags - This contains a set of ScopeFlags, which indicates how the scope + /// interrelates with other control flow statements. + unsigned Flags : 10; + + /// WithinElse - Whether this scope is part of the "else" branch in + /// its parent ControlScope. + bool WithinElse : 1; + + /// FnParent - If this scope has a parent scope that is a function body, this + /// pointer is non-null and points to it. This is used for label processing. + Scope *FnParent; + + /// BreakParent/ContinueParent - This is a direct link to the immediately + /// preceeding BreakParent/ContinueParent if this scope is not one, or null if + /// there is no containing break/continue scope. + Scope *BreakParent, *ContinueParent; + + /// ControlParent - This is a direct link to the immediately + /// preceeding ControlParent if this scope is not one, or null if + /// there is no containing control scope. + Scope *ControlParent; + + /// BlockParent - This is a direct link to the immediately containing + /// BlockScope if this scope is not one, or null if there is none. + Scope *BlockParent; + + /// TemplateParamParent - This is a direct link to the + /// immediately containing template parameter scope. In the + /// case of nested templates, template parameter scopes can have + /// other template parameter scopes as parents. + Scope *TemplateParamParent; + + /// DeclsInScope - This keeps track of all declarations in this scope. When + /// the declaration is added to the scope, it is set as the current + /// declaration for the identifier in the IdentifierTable. When the scope is + /// popped, these declarations are removed from the IdentifierTable's notion + /// of current declaration. It is up to the current Action implementation to + /// implement these semantics. + typedef llvm::SmallPtrSet<Action::DeclPtrTy, 32> DeclSetTy; + DeclSetTy DeclsInScope; + + /// Entity - The entity with which this scope is associated. For + /// example, the entity of a class scope is the class itself, the + /// entity of a function scope is a function, etc. This field is + /// maintained by the Action implementation. + void *Entity; + + typedef llvm::SmallVector<Action::DeclPtrTy, 2> UsingDirectivesTy; + UsingDirectivesTy UsingDirectives; + +public: + Scope(Scope *Parent, unsigned ScopeFlags) { + Init(Parent, ScopeFlags); + } + + /// getFlags - Return the flags for this scope. + /// + unsigned getFlags() const { return Flags; } + + /// isBlockScope - Return true if this scope does not correspond to a + /// closure. + bool isBlockScope() const { return Flags & BlockScope; } + + /// getParent - Return the scope that this is nested in. + /// + const Scope *getParent() const { return AnyParent; } + Scope *getParent() { return AnyParent; } + + /// getFnParent - Return the closest scope that is a function body. + /// + const Scope *getFnParent() const { return FnParent; } + Scope *getFnParent() { return FnParent; } + + /// getContinueParent - Return the closest scope that a continue statement + /// would be affected by. If the closest scope is a closure scope, we know + /// that there is no loop *inside* the closure. + Scope *getContinueParent() { + if (ContinueParent && !ContinueParent->isBlockScope()) + return ContinueParent; + return 0; + } + + const Scope *getContinueParent() const { + return const_cast<Scope*>(this)->getContinueParent(); + } + + /// getBreakParent - Return the closest scope that a break statement + /// would be affected by. If the closest scope is a block scope, we know + /// that there is no loop *inside* the block. + Scope *getBreakParent() { + if (BreakParent && !BreakParent->isBlockScope()) + return BreakParent; + return 0; + } + const Scope *getBreakParent() const { + return const_cast<Scope*>(this)->getBreakParent(); + } + + Scope *getControlParent() { return ControlParent; } + const Scope *getControlParent() const { return ControlParent; } + + Scope *getBlockParent() { return BlockParent; } + const Scope *getBlockParent() const { return BlockParent; } + + Scope *getTemplateParamParent() { return TemplateParamParent; } + const Scope *getTemplateParamParent() const { return TemplateParamParent; } + + typedef DeclSetTy::iterator decl_iterator; + decl_iterator decl_begin() const { return DeclsInScope.begin(); } + decl_iterator decl_end() const { return DeclsInScope.end(); } + bool decl_empty() const { return DeclsInScope.empty(); } + + void AddDecl(Action::DeclPtrTy D) { + DeclsInScope.insert(D); + } + + void RemoveDecl(Action::DeclPtrTy D) { + DeclsInScope.erase(D); + } + + /// isDeclScope - Return true if this is the scope that the specified decl is + /// declared in. + bool isDeclScope(Action::DeclPtrTy D) { + return DeclsInScope.count(D) != 0; + } + + void* getEntity() const { return Entity; } + void setEntity(void *E) { Entity = E; } + + /// isClassScope - Return true if this scope is a class/struct/union scope. + bool isClassScope() const { + return (getFlags() & Scope::ClassScope); + } + + /// isInCXXInlineMethodScope - Return true if this scope is a C++ inline + /// method scope or is inside one. + bool isInCXXInlineMethodScope() const { + if (const Scope *FnS = getFnParent()) { + assert(FnS->getParent() && "TUScope not created?"); + return FnS->getParent()->isClassScope(); + } + return false; + } + + /// isTemplateParamScope - Return true if this scope is a C++ + /// template parameter scope. + bool isTemplateParamScope() const { + return getFlags() & Scope::TemplateParamScope; + } + + /// isFunctionPrototypeScope - Return true if this scope is a + /// function prototype scope. + bool isFunctionPrototypeScope() const { + return getFlags() & Scope::FunctionPrototypeScope; + } + + /// isAtCatchScope - Return true if this scope is @catch. + bool isAtCatchScope() const { + return getFlags() & Scope::AtCatchScope; + } + + /// isWithinElse - Whether we are within the "else" of the + /// ControlParent (if any). + bool isWithinElse() const { return WithinElse; } + + void setWithinElse(bool WE) { WithinElse = WE; } + + typedef UsingDirectivesTy::iterator udir_iterator; + typedef UsingDirectivesTy::const_iterator const_udir_iterator; + + void PushUsingDirective(Action::DeclPtrTy UDir) { + UsingDirectives.push_back(UDir); + } + + udir_iterator using_directives_begin() { + return UsingDirectives.begin(); + } + + udir_iterator using_directives_end() { + return UsingDirectives.end(); + } + + const_udir_iterator using_directives_begin() const { + return UsingDirectives.begin(); + } + + const_udir_iterator using_directives_end() const { + return UsingDirectives.end(); + } + + /// Init - This is used by the parser to implement scope caching. + /// + void Init(Scope *Parent, unsigned ScopeFlags) { + AnyParent = Parent; + Depth = AnyParent ? AnyParent->Depth+1 : 0; + Flags = ScopeFlags; + + if (AnyParent) { + FnParent = AnyParent->FnParent; + BreakParent = AnyParent->BreakParent; + ContinueParent = AnyParent->ContinueParent; + ControlParent = AnyParent->ControlParent; + BlockParent = AnyParent->BlockParent; + TemplateParamParent = AnyParent->TemplateParamParent; + WithinElse = AnyParent->WithinElse; + + } else { + FnParent = BreakParent = ContinueParent = BlockParent = 0; + ControlParent = 0; + TemplateParamParent = 0; + WithinElse = false; + } + + // If this scope is a function or contains breaks/continues, remember it. + if (Flags & FnScope) FnParent = this; + if (Flags & BreakScope) BreakParent = this; + if (Flags & ContinueScope) ContinueParent = this; + if (Flags & ControlScope) ControlParent = this; + if (Flags & BlockScope) BlockParent = this; + if (Flags & TemplateParamScope) TemplateParamParent = this; + DeclsInScope.clear(); + UsingDirectives.clear(); + Entity = 0; + } +}; + +} // end namespace clang + +#endif |