//===--- Decl.h - Classes for representing declarations ---------*- 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 Decl subclasses. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_DECL_H #define LLVM_CLANG_AST_DECL_H #include "clang/AST/APValue.h" #include "clang/AST/DeclBase.h" #include "clang/AST/Redeclarable.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/ExternalASTSource.h" namespace clang { class CXXTemporary; class Expr; class FunctionTemplateDecl; class Stmt; class CompoundStmt; class StringLiteral; class TemplateArgumentList; class MemberSpecializationInfo; class FunctionTemplateSpecializationInfo; class TypeLoc; /// \brief A container of type source information. /// /// A client can read the relevant info using TypeLoc wrappers, e.g: /// @code /// TypeLoc TL = TypeSourceInfo->getTypeLoc(); /// if (PointerLoc *PL = dyn_cast(&TL)) /// PL->getStarLoc().print(OS, SrcMgr); /// @endcode /// class TypeSourceInfo { QualType Ty; // Contains a memory block after the class, used for type source information, // allocated by ASTContext. friend class ASTContext; TypeSourceInfo(QualType ty) : Ty(ty) { } public: /// \brief Return the type wrapped by this type source info. QualType getType() const { return Ty; } /// \brief Return the TypeLoc wrapper for the type source info. TypeLoc getTypeLoc() const; }; /// TranslationUnitDecl - The top declaration context. class TranslationUnitDecl : public Decl, public DeclContext { ASTContext &Ctx; /// The (most recently entered) anonymous namespace for this /// translation unit, if one has been created. NamespaceDecl *AnonymousNamespace; explicit TranslationUnitDecl(ASTContext &ctx) : Decl(TranslationUnit, 0, SourceLocation()), DeclContext(TranslationUnit), Ctx(ctx), AnonymousNamespace(0) {} public: ASTContext &getASTContext() const { return Ctx; } NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; } void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; } static TranslationUnitDecl *Create(ASTContext &C); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == TranslationUnit; } static bool classof(const TranslationUnitDecl *D) { return true; } static DeclContext *castToDeclContext(const TranslationUnitDecl *D) { return static_cast(const_cast(D)); } static TranslationUnitDecl *castFromDeclContext(const DeclContext *DC) { return static_cast(const_cast(DC)); } }; /// NamedDecl - This represents a decl with a name. Many decls have names such /// as ObjCMethodDecl, but not @class, etc. class NamedDecl : public Decl { /// Name - The name of this declaration, which is typically a normal /// identifier but may also be a special kind of name (C++ /// constructor, Objective-C selector, etc.) DeclarationName Name; protected: NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) : Decl(DK, DC, L), Name(N) { } public: /// getIdentifier - Get the identifier that names this declaration, /// if there is one. This will return NULL if this declaration has /// no name (e.g., for an unnamed class) or if the name is a special /// name (C++ constructor, Objective-C selector, etc.). IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); } /// getName - Get the name of identifier for this declaration as a StringRef. /// This requires that the declaration have a name and that it be a simple /// identifier. llvm::StringRef getName() const { assert(Name.isIdentifier() && "Name is not a simple identifier"); return getIdentifier() ? getIdentifier()->getName() : ""; } /// getNameAsCString - Get the name of identifier for this declaration as a /// C string (const char*). This requires that the declaration have a name /// and that it be a simple identifier. // // FIXME: Deprecated, move clients to getName(). const char *getNameAsCString() const { assert(Name.isIdentifier() && "Name is not a simple identifier"); return getIdentifier() ? getIdentifier()->getNameStart() : ""; } /// getNameAsString - Get a human-readable name for the declaration, even if /// it is one of the special kinds of names (C++ constructor, Objective-C /// selector, etc). Creating this name requires expensive string /// manipulation, so it should be called only when performance doesn't matter. /// For simple declarations, getNameAsCString() should suffice. // // FIXME: This function should be renamed to indicate that it is not just an // alternate form of getName(), and clients should move as appropriate. // // FIXME: Deprecated, move clients to getName(). std::string getNameAsString() const { return Name.getAsString(); } /// getDeclName - Get the actual, stored name of the declaration, /// which may be a special name. DeclarationName getDeclName() const { return Name; } /// \brief Set the name of this declaration. void setDeclName(DeclarationName N) { Name = N; } /// getQualifiedNameAsString - Returns human-readable qualified name for /// declaration, like A::B::i, for i being member of namespace A::B. /// If declaration is not member of context which can be named (record, /// namespace), it will return same result as getNameAsString(). /// Creating this name is expensive, so it should be called only when /// performance doesn't matter. std::string getQualifiedNameAsString() const; std::string getQualifiedNameAsString(const PrintingPolicy &Policy) const; /// getNameForDiagnostic - Appends a human-readable name for this /// declaration into the given string. /// /// This is the method invoked by Sema when displaying a NamedDecl /// in a diagnostic. It does not necessarily produce the same /// result as getNameAsString(); for example, class template /// specializations are printed with their template arguments. /// /// TODO: use an API that doesn't require so many temporary strings virtual void getNameForDiagnostic(std::string &S, const PrintingPolicy &Policy, bool Qualified) const { if (Qualified) S += getQualifiedNameAsString(Policy); else S += getNameAsString(); } /// declarationReplaces - Determine whether this declaration, if /// known to be well-formed within its context, will replace the /// declaration OldD if introduced into scope. A declaration will /// replace another declaration if, for example, it is a /// redeclaration of the same variable or function, but not if it is /// a declaration of a different kind (function vs. class) or an /// overloaded function. bool declarationReplaces(NamedDecl *OldD) const; /// \brief Determine whether this declaration has linkage. bool hasLinkage() const; /// \brief Determine whether this declaration is a C++ class member. bool isCXXClassMember() const { const DeclContext *DC = getDeclContext(); // C++0x [class.mem]p1: // The enumerators of an unscoped enumeration defined in // the class are members of the class. // FIXME: support C++0x scoped enumerations. if (isa(DC)) DC = DC->getParent(); return DC->isRecord(); } /// \brief Describes the different kinds of linkage /// (C++ [basic.link], C99 6.2.2) that an entity may have. enum Linkage { /// \brief No linkage, which means that the entity is unique and /// can only be referred to from within its scope. NoLinkage = 0, /// \brief Internal linkage, which indicates that the entity can /// be referred to from within the translation unit (but not other /// translation units). InternalLinkage, /// \brief External linkage, which indicates that the entity can /// be referred to from other translation units. ExternalLinkage }; /// \brief Determine what kind of linkage this entity has. Linkage getLinkage() const; /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. NamedDecl *getUnderlyingDecl(); const NamedDecl *getUnderlyingDecl() const { return const_cast(this)->getUnderlyingDecl(); } static bool classof(const Decl *D) { return D->getKind() >= NamedFirst && D->getKind() <= NamedLast; } static bool classof(const NamedDecl *D) { return true; } }; /// NamespaceDecl - Represent a C++ namespace. class NamespaceDecl : public NamedDecl, public DeclContext { SourceLocation LBracLoc, RBracLoc; // For extended namespace definitions: // // namespace A { int x; } // namespace A { int y; } // // there will be one NamespaceDecl for each declaration. // NextNamespace points to the next extended declaration. // OrigNamespace points to the original namespace declaration. // OrigNamespace of the first namespace decl points to itself. NamespaceDecl *OrigNamespace, *NextNamespace; // The (most recently entered) anonymous namespace inside this // namespace. NamespaceDecl *AnonymousNamespace; NamespaceDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : NamedDecl(Namespace, DC, L, Id), DeclContext(Namespace) { OrigNamespace = this; NextNamespace = 0; AnonymousNamespace = 0; } public: static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id); virtual void Destroy(ASTContext& C); // \brief Returns true if this is an anonymous namespace declaration. // // For example: // namespace { // ... // }; // q.v. C++ [namespace.unnamed] bool isAnonymousNamespace() const { return !getIdentifier(); } NamespaceDecl *getNextNamespace() { return NextNamespace; } const NamespaceDecl *getNextNamespace() const { return NextNamespace; } void setNextNamespace(NamespaceDecl *ND) { NextNamespace = ND; } NamespaceDecl *getOriginalNamespace() const { return OrigNamespace; } void setOriginalNamespace(NamespaceDecl *ND) { OrigNamespace = ND; } NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; } void setAnonymousNamespace(NamespaceDecl *D) { assert(D->isAnonymousNamespace()); assert(D->getParent() == this); AnonymousNamespace = D; } virtual NamespaceDecl *getCanonicalDecl() { return OrigNamespace; } const NamespaceDecl *getCanonicalDecl() const { return OrigNamespace; } virtual SourceRange getSourceRange() const { return SourceRange(getLocation(), RBracLoc); } SourceLocation getLBracLoc() const { return LBracLoc; } SourceLocation getRBracLoc() const { return RBracLoc; } void setLBracLoc(SourceLocation LBrace) { LBracLoc = LBrace; } void setRBracLoc(SourceLocation RBrace) { RBracLoc = RBrace; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == Namespace; } static bool classof(const NamespaceDecl *D) { return true; } static DeclContext *castToDeclContext(const NamespaceDecl *D) { return static_cast(const_cast(D)); } static NamespaceDecl *castFromDeclContext(const DeclContext *DC) { return static_cast(const_cast(DC)); } }; /// ValueDecl - Represent the declaration of a variable (in which case it is /// an lvalue) a function (in which case it is a function designator) or /// an enum constant. class ValueDecl : public NamedDecl { QualType DeclType; protected: ValueDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T) : NamedDecl(DK, DC, L, N), DeclType(T) {} public: QualType getType() const { return DeclType; } void setType(QualType newType) { DeclType = newType; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= ValueFirst && D->getKind() <= ValueLast; } static bool classof(const ValueDecl *D) { return true; } }; /// \brief Represents a ValueDecl that came out of a declarator. /// Contains type source information through TypeSourceInfo. class DeclaratorDecl : public ValueDecl { TypeSourceInfo *DeclInfo; protected: DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo) : ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo) {} public: TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; } void setTypeSourceInfo(TypeSourceInfo *TInfo) { DeclInfo = TInfo; } SourceLocation getTypeSpecStartLoc() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= DeclaratorFirst && D->getKind() <= DeclaratorLast; } static bool classof(const DeclaratorDecl *D) { return true; } }; /// \brief Structure used to store a statement, the constant value to /// which it was evaluated (if any), and whether or not the statement /// is an integral constant expression (if known). struct EvaluatedStmt { EvaluatedStmt() : WasEvaluated(false), IsEvaluating(false), CheckedICE(false), CheckingICE(false), IsICE(false) { } /// \brief Whether this statement was already evaluated. bool WasEvaluated : 1; /// \brief Whether this statement is being evaluated. bool IsEvaluating : 1; /// \brief Whether we already checked whether this statement was an /// integral constant expression. bool CheckedICE : 1; /// \brief Whether we are checking whether this statement is an /// integral constant expression. bool CheckingICE : 1; /// \brief Whether this statement is an integral constant /// expression. Only valid if CheckedICE is true. bool IsICE : 1; Stmt *Value; APValue Evaluated; }; // \brief Describes the kind of template specialization that a // particular template specialization declaration represents. enum TemplateSpecializationKind { /// This template specialization was formed from a template-id but /// has not yet been declared, defined, or instantiated. TSK_Undeclared = 0, /// This template specialization was implicitly instantiated from a /// template. (C++ [temp.inst]). TSK_ImplicitInstantiation, /// This template specialization was declared or defined by an /// explicit specialization (C++ [temp.expl.spec]) or partial /// specialization (C++ [temp.class.spec]). TSK_ExplicitSpecialization, /// This template specialization was instantiated from a template /// due to an explicit instantiation declaration request /// (C++0x [temp.explicit]). TSK_ExplicitInstantiationDeclaration, /// This template specialization was instantiated from a template /// due to an explicit instantiation definition request /// (C++ [temp.explicit]). TSK_ExplicitInstantiationDefinition }; /// VarDecl - An instance of this class is created to represent a variable /// declaration or definition. class VarDecl : public DeclaratorDecl, public Redeclarable { public: enum StorageClass { None, Auto, Register, Extern, Static, PrivateExtern }; /// getStorageClassSpecifierString - Return the string used to /// specify the storage class \arg SC. /// /// It is illegal to call this function with SC == None. static const char *getStorageClassSpecifierString(StorageClass SC); protected: /// \brief Placeholder type used in Init to denote an unparsed C++ default /// argument. struct UnparsedDefaultArgument; /// \brief Placeholder type used in Init to denote an uninstantiated C++ /// default argument. struct UninstantiatedDefaultArgument; typedef llvm::PointerUnion4 InitType; /// \brief The initializer for this variable or, for a ParmVarDecl, the /// C++ default argument. mutable InitType Init; private: // FIXME: This can be packed into the bitfields in Decl. unsigned SClass : 3; bool ThreadSpecified : 1; bool HasCXXDirectInit : 1; /// DeclaredInCondition - Whether this variable was declared in a /// condition, e.g., if (int x = foo()) { ... }. bool DeclaredInCondition : 1; friend class StmtIteratorBase; protected: VarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass SC) : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Init(), ThreadSpecified(false), HasCXXDirectInit(false), DeclaredInCondition(false) { SClass = SC; } typedef Redeclarable redeclarable_base; virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); } public: typedef redeclarable_base::redecl_iterator redecl_iterator; redecl_iterator redecls_begin() const { return redeclarable_base::redecls_begin(); } redecl_iterator redecls_end() const { return redeclarable_base::redecls_end(); } static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S); virtual ~VarDecl(); virtual void Destroy(ASTContext& C); StorageClass getStorageClass() const { return (StorageClass)SClass; } void setStorageClass(StorageClass SC) { SClass = SC; } virtual SourceRange getSourceRange() const; const Expr *getInit() const { if (Init.isNull()) return 0; const Stmt *S = Init.dyn_cast(); if (!S) { if (EvaluatedStmt *ES = Init.dyn_cast()) S = ES->Value; } return (const Expr*) S; } Expr *getInit() { if (Init.isNull()) return 0; Stmt *S = Init.dyn_cast(); if (!S) { if (EvaluatedStmt *ES = Init.dyn_cast()) S = ES->Value; } return (Expr*) S; } /// \brief Retrieve the address of the initializer expression. Stmt **getInitAddress() { if (EvaluatedStmt *ES = Init.dyn_cast()) return &ES->Value; // This union hack tip-toes around strict-aliasing rules. union { InitType *InitPtr; Stmt **StmtPtr; }; InitPtr = &Init; return StmtPtr; } void setInit(ASTContext &C, Expr *I); EvaluatedStmt *EnsureEvaluatedStmt() const { EvaluatedStmt *Eval = Init.dyn_cast(); if (!Eval) { Stmt *S = Init.get(); Eval = new (getASTContext()) EvaluatedStmt; Eval->Value = S; Init = Eval; } return Eval; } /// \brief Check whether we are in the process of checking whether the /// initializer can be evaluated. bool isEvaluatingValue() const { if (EvaluatedStmt *Eval = Init.dyn_cast()) return Eval->IsEvaluating; return false; } /// \brief Note that we now are checking whether the initializer can be /// evaluated. void setEvaluatingValue() const { EvaluatedStmt *Eval = EnsureEvaluatedStmt(); Eval->IsEvaluating = true; } /// \brief Note that constant evaluation has computed the given /// value for this variable's initializer. void setEvaluatedValue(const APValue &Value) const { EvaluatedStmt *Eval = EnsureEvaluatedStmt(); Eval->IsEvaluating = false; Eval->WasEvaluated = true; Eval->Evaluated = Value; } /// \brief Return the already-evaluated value of this variable's /// initializer, or NULL if the value is not yet known. Returns pointer /// to untyped APValue if the value could not be evaluated. APValue *getEvaluatedValue() const { if (EvaluatedStmt *Eval = Init.dyn_cast()) if (Eval->WasEvaluated) return &Eval->Evaluated; return 0; } /// \brief Determines whether it is already known whether the /// initializer is an integral constant expression or not. bool isInitKnownICE() const { if (EvaluatedStmt *Eval = Init.dyn_cast()) return Eval->CheckedICE; return false; } /// \brief Determines whether the initializer is an integral /// constant expression. /// /// \pre isInitKnownICE() bool isInitICE() const { assert(isInitKnownICE() && "Check whether we already know that the initializer is an ICE"); return Init.get()->IsICE; } /// \brief Check whether we are in the process of checking the initializer /// is an integral constant expression. bool isCheckingICE() const { if (EvaluatedStmt *Eval = Init.dyn_cast()) return Eval->CheckingICE; return false; } /// \brief Note that we now are checking whether the initializer is an /// integral constant expression. void setCheckingICE() const { EvaluatedStmt *Eval = EnsureEvaluatedStmt(); Eval->CheckingICE = true; } /// \brief Note that we now know whether the initializer is an /// integral constant expression. void setInitKnownICE(bool IsICE) const { EvaluatedStmt *Eval = EnsureEvaluatedStmt(); Eval->CheckingICE = false; Eval->CheckedICE = true; Eval->IsICE = IsICE; } /// \brief Retrieve the definition of this variable, which may come /// from a previous declaration. Def will be set to the VarDecl that /// contains the initializer, and the result will be that /// initializer. const Expr *getDefinition(const VarDecl *&Def) const; void setThreadSpecified(bool T) { ThreadSpecified = T; } bool isThreadSpecified() const { return ThreadSpecified; } void setCXXDirectInitializer(bool T) { HasCXXDirectInit = T; } /// hasCXXDirectInitializer - If true, the initializer was a direct /// initializer, e.g: "int x(1);". The Init expression will be the expression /// inside the parens or a "ClassType(a,b,c)" class constructor expression for /// class types. Clients can distinguish between "int x(1);" and "int x=1;" /// by checking hasCXXDirectInitializer. /// bool hasCXXDirectInitializer() const { return HasCXXDirectInit; } /// isDeclaredInCondition - Whether this variable was declared as /// part of a condition in an if/switch/while statement, e.g., /// @code /// if (int x = foo()) { ... } /// @endcode bool isDeclaredInCondition() const { return DeclaredInCondition; } void setDeclaredInCondition(bool InCondition) { DeclaredInCondition = InCondition; } virtual VarDecl *getCanonicalDecl(); const VarDecl *getCanonicalDecl() const { return const_cast(this)->getCanonicalDecl(); } /// hasLocalStorage - Returns true if a variable with function scope /// is a non-static local variable. bool hasLocalStorage() const { if (getStorageClass() == None) return !isFileVarDecl(); // Return true for: Auto, Register. // Return false for: Extern, Static, PrivateExtern. return getStorageClass() <= Register; } /// hasExternStorage - Returns true if a variable has extern or /// __private_extern__ storage. bool hasExternalStorage() const { return getStorageClass() == Extern || getStorageClass() == PrivateExtern; } /// hasGlobalStorage - Returns true for all variables that do not /// have local storage. This includs all global variables as well /// as static variables declared within a function. bool hasGlobalStorage() const { return !hasLocalStorage(); } /// isBlockVarDecl - Returns true for local variable declarations. Note that /// this includes static variables inside of functions. /// /// void foo() { int x; static int y; extern int z; } /// bool isBlockVarDecl() const { if (getKind() != Decl::Var) return false; if (const DeclContext *DC = getDeclContext()) return DC->getLookupContext()->isFunctionOrMethod(); return false; } /// \brief Determines whether this is a static data member. /// /// This will only be true in C++, and applies to, e.g., the /// variable 'x' in: /// \code /// struct S { /// static int x; /// }; /// \endcode bool isStaticDataMember() const { return getDeclContext()->isRecord(); } /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a static data member. bool isOutOfLine() const; /// \brief If this is a static data member, find its out-of-line definition. VarDecl *getOutOfLineDefinition(); /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member /// from which it was instantiated. VarDecl *getInstantiatedFromStaticDataMember() const; /// \brief If this variable is a static data member, determine what kind of /// template specialization or instantiation this is. TemplateSpecializationKind getTemplateSpecializationKind() const; /// \brief If this variable is an instantiation of a static data member of a /// class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const; /// \brief For a static data member that was instantiated from a static /// data member of a class template, set the template specialiation kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation = SourceLocation()); /// isFileVarDecl - Returns true for file scoped variable declaration. bool isFileVarDecl() const { if (getKind() != Decl::Var) return false; if (const DeclContext *Ctx = getDeclContext()) { Ctx = Ctx->getLookupContext(); if (isa(Ctx) || isa(Ctx) ) return true; } if (isStaticDataMember()) return true; return false; } /// \brief Determine whether this is a tentative definition of a /// variable in C. bool isTentativeDefinition(ASTContext &Context) const; /// \brief Determines whether this variable is a variable with /// external, C linkage. bool isExternC() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= VarFirst && D->getKind() <= VarLast; } static bool classof(const VarDecl *D) { return true; } }; class ImplicitParamDecl : public VarDecl { protected: ImplicitParamDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType Tw) : VarDecl(DK, DC, L, Id, Tw, /*TInfo=*/0, VarDecl::None) {} public: static ImplicitParamDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T); // Implement isa/cast/dyncast/etc. static bool classof(const ImplicitParamDecl *D) { return true; } static bool classof(const Decl *D) { return D->getKind() == ImplicitParam; } }; /// ParmVarDecl - Represent a parameter to a function. class ParmVarDecl : public VarDecl { // NOTE: VC++ treats enums as signed, avoid using the ObjCDeclQualifier enum /// FIXME: Also can be paced into the bitfields in Decl. /// in, inout, etc. unsigned objcDeclQualifier : 6; protected: ParmVarDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg) : VarDecl(DK, DC, L, Id, T, TInfo, S), objcDeclQualifier(OBJC_TQ_None) { setDefaultArg(DefArg); } public: static ParmVarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L,IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg); ObjCDeclQualifier getObjCDeclQualifier() const { return ObjCDeclQualifier(objcDeclQualifier); } void setObjCDeclQualifier(ObjCDeclQualifier QTVal) { objcDeclQualifier = QTVal; } Expr *getDefaultArg(); const Expr *getDefaultArg() const { return const_cast(this)->getDefaultArg(); } void setDefaultArg(Expr *defarg) { Init = reinterpret_cast(defarg); } unsigned getNumDefaultArgTemporaries() const; CXXTemporary *getDefaultArgTemporary(unsigned i); const CXXTemporary *getDefaultArgTemporary(unsigned i) const { return const_cast(this)->getDefaultArgTemporary(i); } /// \brief Retrieve the source range that covers the entire default /// argument. SourceRange getDefaultArgRange() const; void setUninstantiatedDefaultArg(Expr *arg) { Init = reinterpret_cast(arg); } Expr *getUninstantiatedDefaultArg() { return (Expr *)Init.get(); } const Expr *getUninstantiatedDefaultArg() const { return (const Expr *)Init.get(); } /// hasDefaultArg - Determines whether this parameter has a default argument, /// either parsed or not. bool hasDefaultArg() const { return getInit() || hasUnparsedDefaultArg() || hasUninstantiatedDefaultArg(); } /// hasUnparsedDefaultArg - Determines whether this parameter has a /// default argument that has not yet been parsed. This will occur /// during the processing of a C++ class whose member functions have /// default arguments, e.g., /// @code /// class X { /// public: /// void f(int x = 17); // x has an unparsed default argument now /// }; // x has a regular default argument now /// @endcode bool hasUnparsedDefaultArg() const { return Init.is(); } bool hasUninstantiatedDefaultArg() const { return Init.is(); } /// setUnparsedDefaultArg - Specify that this parameter has an /// unparsed default argument. The argument will be replaced with a /// real default argument via setDefaultArg when the class /// definition enclosing the function declaration that owns this /// default argument is completed. void setUnparsedDefaultArg() { Init = (UnparsedDefaultArgument *)0; } QualType getOriginalType() const { if (getTypeSourceInfo()) return getTypeSourceInfo()->getType(); return getType(); } /// setOwningFunction - Sets the function declaration that owns this /// ParmVarDecl. Since ParmVarDecls are often created before the /// FunctionDecls that own them, this routine is required to update /// the DeclContext appropriately. void setOwningFunction(DeclContext *FD) { setDeclContext(FD); } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return (D->getKind() == ParmVar); } static bool classof(const ParmVarDecl *D) { return true; } }; /// FunctionDecl - An instance of this class is created to represent a /// function declaration or definition. /// /// Since a given function can be declared several times in a program, /// there may be several FunctionDecls that correspond to that /// function. Only one of those FunctionDecls will be found when /// traversing the list of declarations in the context of the /// FunctionDecl (e.g., the translation unit); this FunctionDecl /// contains all of the information known about the function. Other, /// previous declarations of the function are available via the /// getPreviousDeclaration() chain. class FunctionDecl : public DeclaratorDecl, public DeclContext, public Redeclarable { public: enum StorageClass { None, Extern, Static, PrivateExtern }; private: /// ParamInfo - new[]'d array of pointers to VarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. ParmVarDecl **ParamInfo; LazyDeclStmtPtr Body; // FIXME: This can be packed into the bitfields in Decl. // NOTE: VC++ treats enums as signed, avoid using the StorageClass enum unsigned SClass : 2; bool IsInline : 1; bool IsVirtualAsWritten : 1; bool IsPure : 1; bool HasInheritedPrototype : 1; bool HasWrittenPrototype : 1; bool IsDeleted : 1; bool IsTrivial : 1; // sunk from CXXMethodDecl bool IsCopyAssignment : 1; // sunk from CXXMethodDecl bool HasImplicitReturnZero : 1; /// \brief End part of this FunctionDecl's source range. /// /// We could compute the full range in getSourceRange(). However, when we're /// dealing with a function definition deserialized from a PCH/AST file, /// we can only compute the full range once the function body has been /// de-serialized, so it's far better to have the (sometimes-redundant) /// EndRangeLoc. SourceLocation EndRangeLoc; /// \brief The template or declaration that this declaration /// describes or was instantiated from, respectively. /// /// For non-templates, this value will be NULL. For function /// declarations that describe a function template, this will be a /// pointer to a FunctionTemplateDecl. For member functions /// of class template specializations, this will be a MemberSpecializationInfo /// pointer containing information about the specialization. /// For function template specializations, this will be a /// FunctionTemplateSpecializationInfo, which contains information about /// the template being specialized and the template arguments involved in /// that specialization. llvm::PointerUnion3 TemplateOrSpecialization; protected: FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass S, bool isInline) : DeclaratorDecl(DK, DC, L, N, T, TInfo), DeclContext(DK), ParamInfo(0), Body(), SClass(S), IsInline(isInline), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), IsDeleted(false), IsTrivial(false), IsCopyAssignment(false), HasImplicitReturnZero(false), EndRangeLoc(L), TemplateOrSpecialization() {} virtual ~FunctionDecl() {} virtual void Destroy(ASTContext& C); typedef Redeclarable redeclarable_base; virtual FunctionDecl *getNextRedeclaration() { return RedeclLink.getNext(); } public: typedef redeclarable_base::redecl_iterator redecl_iterator; redecl_iterator redecls_begin() const { return redeclarable_base::redecls_begin(); } redecl_iterator redecls_end() const { return redeclarable_base::redecls_end(); } static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, TypeSourceInfo *TInfo, StorageClass S = None, bool isInline = false, bool hasWrittenPrototype = true); virtual void getNameForDiagnostic(std::string &S, const PrintingPolicy &Policy, bool Qualified) const; virtual SourceRange getSourceRange() const { return SourceRange(getLocation(), EndRangeLoc); } void setLocEnd(SourceLocation E) { EndRangeLoc = E; } /// getBody - Retrieve the body (definition) of the function. The /// function body might be in any of the (re-)declarations of this /// function. The variant that accepts a FunctionDecl pointer will /// set that function declaration to the actual declaration /// containing the body (if there is one). Stmt *getBody(const FunctionDecl *&Definition) const; virtual Stmt *getBody() const { const FunctionDecl* Definition; return getBody(Definition); } /// isThisDeclarationADefinition - Returns whether this specific /// declaration of the function is also a definition. This does not /// determine whether the function has been defined (e.g., in a /// previous definition); for that information, use getBody. /// FIXME: Should return true if function is deleted or defaulted. However, /// CodeGenModule.cpp uses it, and I don't know if this would break it. bool isThisDeclarationADefinition() const { return Body; } void setBody(Stmt *B); void setLazyBody(uint64_t Offset) { Body = Offset; } /// Whether this function is marked as virtual explicitly. bool isVirtualAsWritten() const { return IsVirtualAsWritten; } void setVirtualAsWritten(bool V) { IsVirtualAsWritten = V; } /// Whether this virtual function is pure, i.e. makes the containing class /// abstract. bool isPure() const { return IsPure; } void setPure(bool P = true) { IsPure = P; } /// Whether this function is "trivial" in some specialized C++ senses. /// Can only be true for default constructors, copy constructors, /// copy assignment operators, and destructors. Not meaningful until /// the class has been fully built by Sema. bool isTrivial() const { return IsTrivial; } void setTrivial(bool IT) { IsTrivial = IT; } bool isCopyAssignment() const { return IsCopyAssignment; } void setCopyAssignment(bool CA) { IsCopyAssignment = CA; } /// Whether falling off this function implicitly returns null/zero. /// If a more specific implicit return value is required, front-ends /// should synthesize the appropriate return statements. bool hasImplicitReturnZero() const { return HasImplicitReturnZero; } void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; } /// \brief Whether this function has a prototype, either because one /// was explicitly written or because it was "inherited" by merging /// a declaration without a prototype with a declaration that has a /// prototype. bool hasPrototype() const { return HasWrittenPrototype || HasInheritedPrototype; } bool hasWrittenPrototype() const { return HasWrittenPrototype; } void setHasWrittenPrototype(bool P) { HasWrittenPrototype = P; } /// \brief Whether this function inherited its prototype from a /// previous declaration. bool hasInheritedPrototype() const { return HasInheritedPrototype; } void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; } /// \brief Whether this function has been deleted. /// /// A function that is "deleted" (via the C++0x "= delete" syntax) /// acts like a normal function, except that it cannot actually be /// called or have its address taken. Deleted functions are /// typically used in C++ overload resolution to attract arguments /// whose type or lvalue/rvalue-ness would permit the use of a /// different overload that would behave incorrectly. For example, /// one might use deleted functions to ban implicit conversion from /// a floating-point number to an Integer type: /// /// @code /// struct Integer { /// Integer(long); // construct from a long /// Integer(double) = delete; // no construction from float or double /// Integer(long double) = delete; // no construction from long double /// }; /// @endcode bool isDeleted() const { return IsDeleted; } void setDeleted(bool D = true) { IsDeleted = D; } /// \brief Determines whether this is a function "main", which is /// the entry point into an executable program. bool isMain() const; /// \brief Determines whether this function is a function with /// external, C linkage. bool isExternC() const; /// \brief Determines whether this is a global function. bool isGlobal() const; void setPreviousDeclaration(FunctionDecl * PrevDecl); virtual const FunctionDecl *getCanonicalDecl() const; virtual FunctionDecl *getCanonicalDecl(); unsigned getBuiltinID() const; unsigned getNumParmVarDeclsFromType() const; // Iterator access to formal parameters. unsigned param_size() const { return getNumParams(); } typedef ParmVarDecl **param_iterator; typedef ParmVarDecl * const *param_const_iterator; param_iterator param_begin() { return ParamInfo; } param_iterator param_end() { return ParamInfo+param_size(); } param_const_iterator param_begin() const { return ParamInfo; } param_const_iterator param_end() const { return ParamInfo+param_size(); } /// getNumParams - Return the number of parameters this function must have /// based on its functiontype. This is the length of the PararmInfo array /// after it has been created. unsigned getNumParams() const; const ParmVarDecl *getParamDecl(unsigned i) const { assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } ParmVarDecl *getParamDecl(unsigned i) { assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams); /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default /// arguments (in C++). unsigned getMinRequiredArguments() const; QualType getResultType() const { return getType()->getAs()->getResultType(); } StorageClass getStorageClass() const { return StorageClass(SClass); } void setStorageClass(StorageClass SC) { SClass = SC; } /// \brief Determine whether the "inline" keyword was specified for this /// function. bool isInlineSpecified() const { return IsInline; } /// Set whether the "inline" keyword was specified for this function. void setInlineSpecified(bool I) { IsInline = I; } /// \brief Determine whether this function should be inlined, because it is /// either marked "inline" or is a member function of a C++ class that /// was defined in the class body. bool isInlined() const; bool isInlineDefinitionExternallyVisible() const; /// isOverloadedOperator - Whether this function declaration /// represents an C++ overloaded operator, e.g., "operator+". bool isOverloadedOperator() const { return getOverloadedOperator() != OO_None; } OverloadedOperatorKind getOverloadedOperator() const; const IdentifierInfo *getLiteralIdentifier() const; /// \brief If this function is an instantiation of a member function /// of a class template specialization, retrieves the function from /// which it was instantiated. /// /// This routine will return non-NULL for (non-templated) member /// functions of class templates and for instantiations of function /// templates. For example, given: /// /// \code /// template /// struct X { /// void f(T); /// }; /// \endcode /// /// The declaration for X::f is a (non-templated) FunctionDecl /// whose parent is the class template specialization X. For /// this declaration, getInstantiatedFromFunction() will return /// the FunctionDecl X::A. When a complete definition of /// X::A is required, it will be instantiated from the /// declaration returned by getInstantiatedFromMemberFunction(). FunctionDecl *getInstantiatedFromMemberFunction() const; /// \brief If this function is an instantiation of a member function of a /// class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const; /// \brief Specify that this record is an instantiation of the /// member function FD. void setInstantiationOfMemberFunction(FunctionDecl *FD, TemplateSpecializationKind TSK); /// \brief Retrieves the function template that is described by this /// function declaration. /// /// Every function template is represented as a FunctionTemplateDecl /// and a FunctionDecl (or something derived from FunctionDecl). The /// former contains template properties (such as the template /// parameter lists) while the latter contains the actual /// description of the template's /// contents. FunctionTemplateDecl::getTemplatedDecl() retrieves the /// FunctionDecl that describes the function template, /// getDescribedFunctionTemplate() retrieves the /// FunctionTemplateDecl from a FunctionDecl. FunctionTemplateDecl *getDescribedFunctionTemplate() const { return TemplateOrSpecialization.dyn_cast(); } void setDescribedFunctionTemplate(FunctionTemplateDecl *Template) { TemplateOrSpecialization = Template; } /// \brief Determine whether this function is a function template /// specialization. bool isFunctionTemplateSpecialization() const { return getPrimaryTemplate() != 0; } /// \brief If this function is actually a function template specialization, /// retrieve information about this function template specialization. /// Otherwise, returns NULL. FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const { return TemplateOrSpecialization. dyn_cast(); } /// \brief Determines whether this function is a function template /// specialization or a member of a class template specialization that can /// be implicitly instantiated. bool isImplicitlyInstantiable() const; /// \brief Retrieve the function declaration from which this function could /// be instantiated, if it is an instantiation (rather than a non-template /// or a specialization, for example). FunctionDecl *getTemplateInstantiationPattern() const; /// \brief Retrieve the primary template that this function template /// specialization either specializes or was instantiated from. /// /// If this function declaration is not a function template specialization, /// returns NULL. FunctionTemplateDecl *getPrimaryTemplate() const; /// \brief Retrieve the template arguments used to produce this function /// template specialization from the primary template. /// /// If this function declaration is not a function template specialization, /// returns NULL. const TemplateArgumentList *getTemplateSpecializationArgs() const; /// \brief Specify that this function declaration is actually a function /// template specialization. /// /// \param Context the AST context in which this function resides. /// /// \param Template the function template that this function template /// specialization specializes. /// /// \param TemplateArgs the template arguments that produced this /// function template specialization from the template. /// /// \param InsertPos If non-NULL, the position in the function template /// specialization set where the function template specialization data will /// be inserted. /// /// \param TSK the kind of template specialization this is. void setFunctionTemplateSpecialization(ASTContext &Context, FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, TemplateSpecializationKind TSK = TSK_ImplicitInstantiation); /// \brief Determine what kind of template instantiation this function /// represents. TemplateSpecializationKind getTemplateSpecializationKind() const; /// \brief Determine what kind of template instantiation this function /// represents. void setTemplateSpecializationKind(TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation = SourceLocation()); /// \brief Retrieve the (first) point of instantiation of a function template /// specialization or a member of a class template specialization. /// /// \returns the first point of instantiation, if this function was /// instantiated from a template; otherwie, returns an invalid source /// location. SourceLocation getPointOfInstantiation() const; /// \brief Determine whether this is or was instantiated from an out-of-line /// definition of a member function. bool isOutOfLine() const; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast; } static bool classof(const FunctionDecl *D) { return true; } static DeclContext *castToDeclContext(const FunctionDecl *D) { return static_cast(const_cast(D)); } static FunctionDecl *castFromDeclContext(const DeclContext *DC) { return static_cast(const_cast(DC)); } }; /// FieldDecl - An instance of this class is created by Sema::ActOnField to /// represent a member of a struct/union/class. class FieldDecl : public DeclaratorDecl { // FIXME: This can be packed into the bitfields in Decl. bool Mutable : 1; Expr *BitWidth; protected: FieldDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable) : DeclaratorDecl(DK, DC, L, Id, T, TInfo), Mutable(Mutable), BitWidth(BW) { } public: static FieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable); /// isMutable - Determines whether this field is mutable (C++ only). bool isMutable() const { return Mutable; } /// \brief Set whether this field is mutable (C++ only). void setMutable(bool M) { Mutable = M; } /// isBitfield - Determines whether this field is a bitfield. bool isBitField() const { return BitWidth != NULL; } /// @brief Determines whether this is an unnamed bitfield. bool isUnnamedBitfield() const { return BitWidth != NULL && !getDeclName(); } /// isAnonymousStructOrUnion - Determines whether this field is a /// representative for an anonymous struct or union. Such fields are /// unnamed and are implicitly generated by the implementation to /// store the data for the anonymous union or struct. bool isAnonymousStructOrUnion() const; Expr *getBitWidth() const { return BitWidth; } void setBitWidth(Expr *BW) { BitWidth = BW; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= FieldFirst && D->getKind() <= FieldLast; } static bool classof(const FieldDecl *D) { return true; } }; /// EnumConstantDecl - An instance of this object exists for each enum constant /// that is defined. For example, in "enum X {a,b}", each of a/b are /// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a /// TagType for the X EnumDecl. class EnumConstantDecl : public ValueDecl { Stmt *Init; // an integer constant expression llvm::APSInt Val; // The value. protected: EnumConstantDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, const llvm::APSInt &V) : ValueDecl(EnumConstant, DC, L, Id, T), Init((Stmt*)E), Val(V) {} virtual ~EnumConstantDecl() {} public: static EnumConstantDecl *Create(ASTContext &C, EnumDecl *DC, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, const llvm::APSInt &V); virtual void Destroy(ASTContext& C); const Expr *getInitExpr() const { return (const Expr*) Init; } Expr *getInitExpr() { return (Expr*) Init; } const llvm::APSInt &getInitVal() const { return Val; } void setInitExpr(Expr *E) { Init = (Stmt*) E; } void setInitVal(const llvm::APSInt &V) { Val = V; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == EnumConstant; } static bool classof(const EnumConstantDecl *D) { return true; } friend class StmtIteratorBase; }; /// TypeDecl - Represents a declaration of a type. /// class TypeDecl : public NamedDecl { /// TypeForDecl - This indicates the Type object that represents /// this TypeDecl. It is a cache maintained by /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl. mutable Type *TypeForDecl; friend class ASTContext; friend class DeclContext; friend class TagDecl; friend class TemplateTypeParmDecl; friend class ClassTemplateSpecializationDecl; friend class TagType; protected: TypeDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id) : NamedDecl(DK, DC, L, Id), TypeForDecl(0) {} public: // Low-level accessor Type *getTypeForDecl() const { return TypeForDecl; } void setTypeForDecl(Type *TD) { TypeForDecl = TD; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= TypeFirst && D->getKind() <= TypeLast; } static bool classof(const TypeDecl *D) { return true; } }; class TypedefDecl : public TypeDecl, public Redeclarable { /// UnderlyingType - This is the type the typedef is set to. TypeSourceInfo *TInfo; TypedefDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, TypeSourceInfo *TInfo) : TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {} virtual ~TypedefDecl(); public: static TypedefDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, TypeSourceInfo *TInfo); TypeSourceInfo *getTypeSourceInfo() const { return TInfo; } /// Retrieves the canonical declaration of this typedef. TypedefDecl *getCanonicalDecl() { return getFirstDeclaration(); } const TypedefDecl *getCanonicalDecl() const { return getFirstDeclaration(); } QualType getUnderlyingType() const { return TInfo->getType(); } void setTypeSourceInfo(TypeSourceInfo *newType) { TInfo = newType; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == Typedef; } static bool classof(const TypedefDecl *D) { return true; } }; class TypedefDecl; /// TagDecl - Represents the declaration of a struct/union/class/enum. class TagDecl : public TypeDecl, public DeclContext, public Redeclarable { public: // This is really ugly. typedef ElaboratedType::TagKind TagKind; static const TagKind TK_struct = ElaboratedType::TK_struct; static const TagKind TK_union = ElaboratedType::TK_union; static const TagKind TK_class = ElaboratedType::TK_class; static const TagKind TK_enum = ElaboratedType::TK_enum; private: // FIXME: This can be packed into the bitfields in Decl. /// TagDeclKind - The TagKind enum. unsigned TagDeclKind : 2; /// IsDefinition - True if this is a definition ("struct foo {};"), false if /// it is a declaration ("struct foo;"). bool IsDefinition : 1; /// TypedefForAnonDecl - If a TagDecl is anonymous and part of a typedef, /// this points to the TypedefDecl. Used for mangling. TypedefDecl *TypedefForAnonDecl; SourceLocation TagKeywordLoc; SourceLocation RBraceLoc; protected: TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl, SourceLocation TKL = SourceLocation()) : TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0), TagKeywordLoc(TKL) { assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum"); TagDeclKind = TK; IsDefinition = false; setPreviousDeclaration(PrevDecl); } typedef Redeclarable redeclarable_base; virtual TagDecl *getNextRedeclaration() { return RedeclLink.getNext(); } public: typedef redeclarable_base::redecl_iterator redecl_iterator; redecl_iterator redecls_begin() const { return redeclarable_base::redecls_begin(); } redecl_iterator redecls_end() const { return redeclarable_base::redecls_end(); } SourceLocation getRBraceLoc() const { return RBraceLoc; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } SourceLocation getTagKeywordLoc() const { return TagKeywordLoc; } void setTagKeywordLoc(SourceLocation TKL) { TagKeywordLoc = TKL; } virtual SourceRange getSourceRange() const; virtual TagDecl* getCanonicalDecl(); const TagDecl* getCanonicalDecl() const { return const_cast(this)->getCanonicalDecl(); } /// isDefinition - Return true if this decl has its body specified. bool isDefinition() const { return IsDefinition; } /// \brief Whether this declaration declares a type that is /// dependent, i.e., a type that somehow depends on template /// parameters. bool isDependentType() const { return isDependentContext(); } /// @brief Starts the definition of this tag declaration. /// /// This method should be invoked at the beginning of the definition /// of this tag declaration. It will set the tag type into a state /// where it is in the process of being defined. void startDefinition(); /// @brief Completes the definition of this tag declaration. void completeDefinition(); /// getDefinition - Returns the TagDecl that actually defines this /// struct/union/class/enum. When determining whether or not a /// struct/union/class/enum is completely defined, one should use this method /// as opposed to 'isDefinition'. 'isDefinition' indicates whether or not a /// specific TagDecl is defining declaration, not whether or not the /// struct/union/class/enum type is defined. This method returns NULL if /// there is no TagDecl that defines the struct/union/class/enum. TagDecl* getDefinition(ASTContext& C) const; const char *getKindName() const { return ElaboratedType::getNameForTagKind(getTagKind()); } /// getTagKindForTypeSpec - Converts a type specifier (DeclSpec::TST) /// into a tag kind. It is an error to provide a type specifier /// which *isn't* a tag kind here. static TagKind getTagKindForTypeSpec(unsigned TypeSpec); TagKind getTagKind() const { return TagKind(TagDeclKind); } void setTagKind(TagKind TK) { TagDeclKind = TK; } bool isStruct() const { return getTagKind() == TK_struct; } bool isClass() const { return getTagKind() == TK_class; } bool isUnion() const { return getTagKind() == TK_union; } bool isEnum() const { return getTagKind() == TK_enum; } TypedefDecl *getTypedefForAnonDecl() const { return TypedefForAnonDecl; } void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefForAnonDecl = TDD; } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= TagFirst && D->getKind() <= TagLast; } static bool classof(const TagDecl *D) { return true; } static DeclContext *castToDeclContext(const TagDecl *D) { return static_cast(const_cast(D)); } static TagDecl *castFromDeclContext(const DeclContext *DC) { return static_cast(const_cast(DC)); } void setDefinition(bool V) { IsDefinition = V; } }; /// EnumDecl - Represents an enum. As an extension, we allow forward-declared /// enums. class EnumDecl : public TagDecl { /// IntegerType - This represent the integer type that the enum corresponds /// to for code generation purposes. Note that the enumerator constants may /// have a different type than this does. QualType IntegerType; /// PromotionType - The integer type that values of this type should /// promote to. In C, enumerators are generally of an integer type /// directly, but gcc-style large enumerators (and all enumerators /// in C++) are of the enum type instead. QualType PromotionType; /// \brief If the enumeration was instantiated from an enumeration /// within a class or function template, this pointer refers to the /// enumeration declared within the template. EnumDecl *InstantiatedFrom; EnumDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, EnumDecl *PrevDecl, SourceLocation TKL) : TagDecl(Enum, TK_enum, DC, L, Id, PrevDecl, TKL), InstantiatedFrom(0) { IntegerType = QualType(); } public: EnumDecl *getCanonicalDecl() { return cast(TagDecl::getCanonicalDecl()); } const EnumDecl *getCanonicalDecl() const { return cast(TagDecl::getCanonicalDecl()); } static EnumDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL, EnumDecl *PrevDecl); virtual void Destroy(ASTContext& C); /// completeDefinition - When created, the EnumDecl corresponds to a /// forward-declared enum. This method is used to mark the /// declaration as being defined; it's enumerators have already been /// added (via DeclContext::addDecl). NewType is the new underlying /// type of the enumeration type. void completeDefinition(ASTContext &C, QualType NewType, QualType PromotionType); // enumerator_iterator - Iterates through the enumerators of this // enumeration. typedef specific_decl_iterator enumerator_iterator; enumerator_iterator enumerator_begin() const { return enumerator_iterator(this->decls_begin()); } enumerator_iterator enumerator_end() const { return enumerator_iterator(this->decls_end()); } /// getPromotionType - Return the integer type that enumerators /// should promote to. QualType getPromotionType() const { return PromotionType; } /// \brief Set the promotion type. void setPromotionType(QualType T) { PromotionType = T; } /// getIntegerType - Return the integer type this enum decl corresponds to. /// This returns a null qualtype for an enum forward definition. QualType getIntegerType() const { return IntegerType; } /// \brief Set the underlying integer type. void setIntegerType(QualType T) { IntegerType = T; } /// \brief Returns the enumeration (declared within the template) /// from which this enumeration type was instantiated, or NULL if /// this enumeration was not instantiated from any template. EnumDecl *getInstantiatedFromMemberEnum() const { return InstantiatedFrom; } void setInstantiationOfMemberEnum(EnumDecl *IF) { InstantiatedFrom = IF; } static bool classof(const Decl *D) { return D->getKind() == Enum; } static bool classof(const EnumDecl *D) { return true; } }; /// RecordDecl - Represents a struct/union/class. For example: /// struct X; // Forward declaration, no "body". /// union Y { int A, B; }; // Has body with members A and B (FieldDecls). /// This decl will be marked invalid if *any* members are invalid. /// class RecordDecl : public TagDecl { // FIXME: This can be packed into the bitfields in Decl. /// HasFlexibleArrayMember - This is true if this struct ends with a flexible /// array member (e.g. int X[]) or if this union contains a struct that does. /// If so, this cannot be contained in arrays or other structs as a member. bool HasFlexibleArrayMember : 1; /// AnonymousStructOrUnion - Whether this is the type of an /// anonymous struct or union. bool AnonymousStructOrUnion : 1; /// HasObjectMember - This is true if this struct has at least one /// member containing an object bool HasObjectMember : 1; protected: RecordDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, RecordDecl *PrevDecl, SourceLocation TKL); virtual ~RecordDecl(); public: static RecordDecl *Create(ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, SourceLocation TKL = SourceLocation(), RecordDecl* PrevDecl = 0); virtual void Destroy(ASTContext& C); bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; } /// isAnonymousStructOrUnion - Whether this is an anonymous struct /// or union. To be an anonymous struct or union, it must have been /// declared without a name and there must be no objects of this /// type declared, e.g., /// @code /// union { int i; float f; }; /// @endcode /// is an anonymous union but neither of the following are: /// @code /// union X { int i; float f; }; /// union { int i; float f; } obj; /// @endcode bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; } void setAnonymousStructOrUnion(bool Anon) { AnonymousStructOrUnion = Anon; } bool hasObjectMember() const { return HasObjectMember; } void setHasObjectMember (bool val) { HasObjectMember = val; } /// \brief Determines whether this declaration represents the /// injected class name. /// /// The injected class name in C++ is the name of the class that /// appears inside the class itself. For example: /// /// \code /// struct C { /// // C is implicitly declared here as a synonym for the class name. /// }; /// /// C::C c; // same as "C c;" /// \endcode bool isInjectedClassName() const; /// getDefinition - Returns the RecordDecl that actually defines this /// struct/union/class. When determining whether or not a struct/union/class /// is completely defined, one should use this method as opposed to /// 'isDefinition'. 'isDefinition' indicates whether or not a specific /// RecordDecl is defining declaration, not whether or not the record /// type is defined. This method returns NULL if there is no RecordDecl /// that defines the struct/union/tag. RecordDecl* getDefinition(ASTContext& C) const { return cast_or_null(TagDecl::getDefinition(C)); } // Iterator access to field members. The field iterator only visits // the non-static data members of this class, ignoring any static // data members, functions, constructors, destructors, etc. typedef specific_decl_iterator field_iterator; field_iterator field_begin() const { return field_iterator(decls_begin()); } field_iterator field_end() const { return field_iterator(decls_end()); } // field_empty - Whether there are any fields (non-static data // members) in this record. bool field_empty() const { return field_begin() == field_end(); } /// completeDefinition - Notes that the definition of this type is /// now complete. void completeDefinition(ASTContext& C); static bool classof(const Decl *D) { return D->getKind() >= RecordFirst && D->getKind() <= RecordLast; } static bool classof(const RecordDecl *D) { return true; } }; class FileScopeAsmDecl : public Decl { StringLiteral *AsmString; FileScopeAsmDecl(DeclContext *DC, SourceLocation L, StringLiteral *asmstring) : Decl(FileScopeAsm, DC, L), AsmString(asmstring) {} public: static FileScopeAsmDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, StringLiteral *Str); const StringLiteral *getAsmString() const { return AsmString; } StringLiteral *getAsmString() { return AsmString; } void setAsmString(StringLiteral *Asm) { AsmString = Asm; } static bool classof(const Decl *D) { return D->getKind() == FileScopeAsm; } static bool classof(const FileScopeAsmDecl *D) { return true; } }; /// BlockDecl - This represents a block literal declaration, which is like an /// unnamed FunctionDecl. For example: /// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } /// class BlockDecl : public Decl, public DeclContext { // FIXME: This can be packed into the bitfields in Decl. bool isVariadic : 1; /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. ParmVarDecl **ParamInfo; unsigned NumParams; Stmt *Body; protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) : Decl(Block, DC, CaretLoc), DeclContext(Block), isVariadic(false), ParamInfo(0), NumParams(0), Body(0) {} virtual ~BlockDecl(); virtual void Destroy(ASTContext& C); public: static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); SourceLocation getCaretLocation() const { return getLocation(); } bool IsVariadic() const { return isVariadic; } void setIsVariadic(bool value) { isVariadic = value; } CompoundStmt *getCompoundBody() const { return (CompoundStmt*) Body; } Stmt *getBody() const { return (Stmt*) Body; } void setBody(CompoundStmt *B) { Body = (Stmt*) B; } // Iterator access to formal parameters. unsigned param_size() const { return getNumParams(); } typedef ParmVarDecl **param_iterator; typedef ParmVarDecl * const *param_const_iterator; bool param_empty() const { return NumParams == 0; } param_iterator param_begin() { return ParamInfo; } param_iterator param_end() { return ParamInfo+param_size(); } param_const_iterator param_begin() const { return ParamInfo; } param_const_iterator param_end() const { return ParamInfo+param_size(); } unsigned getNumParams() const; const ParmVarDecl *getParamDecl(unsigned i) const { assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } ParmVarDecl *getParamDecl(unsigned i) { assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } void setParams(ASTContext& C, ParmVarDecl **NewParamInfo, unsigned NumParams); // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() == Block; } static bool classof(const BlockDecl *D) { return true; } static DeclContext *castToDeclContext(const BlockDecl *D) { return static_cast(const_cast(D)); } static BlockDecl *castFromDeclContext(const DeclContext *DC) { return static_cast(const_cast(DC)); } }; /// Insertion operator for diagnostics. This allows sending NamedDecl's /// into a diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, NamedDecl* ND) { DB.AddTaggedVal(reinterpret_cast(ND), Diagnostic::ak_nameddecl); return DB; } } // end namespace clang #endif