diff options
Diffstat (limited to 'include/clang/AST/Decl.h')
-rw-r--r-- | include/clang/AST/Decl.h | 442 |
1 files changed, 442 insertions, 0 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h new file mode 100644 index 0000000000..2d3b01d3ce --- /dev/null +++ b/include/clang/AST/Decl.h @@ -0,0 +1,442 @@ +//===--- Decl.h - Classes for representing declarations ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the Decl interface and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_DECL_H +#define LLVM_CLANG_AST_DECL_H + +#include "clang/Basic/SourceLocation.h" +#include "clang/AST/Type.h" +#include "llvm/ADT/APSInt.h" + +namespace clang { +class IdentifierInfo; +class Expr; +class Stmt; +class FunctionDecl; + + +/// Decl - This represents one declaration (or definition), e.g. a variable, +/// typedef, function, struct, etc. +/// +class Decl { +public: + enum Kind { + // Concrete sub-classes of ValueDecl + Function, BlockVariable, FileVariable, ParmVariable, EnumConstant, + // Concrete sub-classes of TypeDecl + Typedef, Struct, Union, Class, Enum, + // Concrete sub-class of Decl + Field + }; + + /// IdentifierNamespace - According to C99 6.2.3, there are four namespaces, + /// labels, tags, members and ordinary identifiers. + enum IdentifierNamespace { + IDNS_Label, + IDNS_Tag, + IDNS_Member, + IDNS_Ordinary + }; +private: + /// DeclKind - This indicates which class this is. + Kind DeclKind; + + /// Loc - The location that this decl. + SourceLocation Loc; + + /// Identifier - The identifier for this declaration (e.g. the name for the + /// variable, the tag for a struct). + IdentifierInfo *Identifier; + + /// When this decl is in scope while parsing, the Next field contains a + /// pointer to the shadowed decl of the same name. When the scope is popped, + /// Decls are relinked onto a containing decl object. + /// + Decl *Next; + + /// NextDeclarator - If this decl was part of a multi-declarator declaration, + /// such as "int X, Y, *Z;" this indicates Decl for the next declarator. + Decl *NextDeclarator; + +protected: + Decl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *NextDecl) + : DeclKind(DK), Loc(L), Identifier(Id), Next(0), NextDeclarator(NextDecl) { + if (Decl::CollectingStats()) addDeclKind(DK); + } + virtual ~Decl(); + +public: + IdentifierInfo *getIdentifier() const { return Identifier; } + SourceLocation getLocation() const { return Loc; } + void setLocation(SourceLocation L) { Loc = L; } + const char *getName() const; + + Kind getKind() const { return DeclKind; } + Decl *getNext() const { return Next; } + void setNext(Decl *N) { Next = N; } + + /// getNextDeclarator - If this decl was part of a multi-declarator + /// declaration, such as "int X, Y, *Z;" this returns the decl for the next + /// declarator. Otherwise it returns null. + Decl *getNextDeclarator() { return NextDeclarator; } + const Decl *getNextDeclarator() const { return NextDeclarator; } + void setNextDeclarator(Decl *N) { NextDeclarator = N; } + + IdentifierNamespace getIdentifierNamespace() const { + switch (DeclKind) { + default: assert(0 && "Unknown decl kind!"); + case Typedef: + case Function: + case BlockVariable: + case FileVariable: + case ParmVariable: + case EnumConstant: + return IDNS_Ordinary; + case Struct: + case Union: + case Class: + case Enum: + return IDNS_Tag; + } + } + // global temp stats (until we have a per-module visitor) + static void addDeclKind(const Kind k); + static bool CollectingStats(bool enable=false); + static void PrintStats(); + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *) { return true; } +}; + +/// 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 Decl { + QualType DeclType; +protected: + ValueDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T, + Decl *PrevDecl) : Decl(DK, L, Id, PrevDecl), DeclType(T) {} +public: + QualType getType() const { return DeclType; } + void setType(QualType newType) { DeclType = newType; } + QualType getCanonicalType() const { return DeclType.getCanonicalType(); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= Function && D->getKind() <= EnumConstant; + } + static bool classof(const ValueDecl *D) { return true; } +}; + +/// VarDecl - An instance of this class is created to represent a variable +/// declaration or definition. +class VarDecl : public ValueDecl { +public: + enum StorageClass { + None, Extern, Static, Auto, Register + }; + StorageClass getStorageClass() const { return SClass; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= BlockVariable && D->getKind() <= ParmVariable; + } + static bool classof(const VarDecl *D) { return true; } +protected: + VarDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T, + StorageClass SC, Decl *PrevDecl) + : ValueDecl(DK, L, Id, T, PrevDecl) { SClass = SC; } +private: + StorageClass SClass; + // TODO: Initializer. +}; + +/// BlockVarDecl - Represent a local variable declaration. +class BlockVarDecl : public VarDecl { +public: + BlockVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S, + Decl *PrevDecl) + : VarDecl(BlockVariable, L, Id, T, S, PrevDecl) {} + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return D->getKind() == BlockVariable; } + static bool classof(const BlockVarDecl *D) { return true; } +}; + +/// FileVarDecl - Represent a file scoped variable declaration. This +/// will allow us to reason about external variable declarations and tentative +/// definitions (C99 6.9.2p2) using our type system (without storing a +/// pointer to the decl's scope, which is transient). +class FileVarDecl : public VarDecl { +public: + FileVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S, + Decl *PrevDecl) + : VarDecl(FileVariable, L, Id, T, S, PrevDecl) {} + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return D->getKind() == FileVariable; } + static bool classof(const FileVarDecl *D) { return true; } +}; + +/// ParmVarDecl - Represent a parameter to a function. +class ParmVarDecl : public VarDecl { +public: + ParmVarDecl(SourceLocation L, IdentifierInfo *Id, QualType T, StorageClass S, + Decl *PrevDecl) + : VarDecl(ParmVariable, L, Id, T, S, PrevDecl) {} + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return D->getKind() == ParmVariable; } + static bool classof(const ParmVarDecl *D) { return true; } +}; + +/// FunctionDecl - An instance of this class is created to represent a function +/// declaration or definition. +class FunctionDecl : public ValueDecl { +public: + enum StorageClass { + None, Extern, Static + }; + FunctionDecl(SourceLocation L, IdentifierInfo *Id, QualType T, + StorageClass S = None, Decl *PrevDecl) + : ValueDecl(Function, L, Id, T, PrevDecl), + ParamInfo(0), Body(0), DeclChain(0), SClass(S) {} + virtual ~FunctionDecl(); + + Stmt *getBody() const { return Body; } + void setBody(Stmt *B) { Body = B; } + + Decl *getDeclChain() const { return DeclChain; } + void setDeclChain(Decl *D) { DeclChain = D; } + + 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(ParmVarDecl **NewParamInfo, unsigned NumParams); + + QualType getResultType() const { + return cast<FunctionType>(getType())->getResultType(); + } + StorageClass getStorageClass() const { return SClass; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return D->getKind() == Function; } + static bool classof(const FunctionDecl *D) { return true; } +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. TODO: we could allocate this space immediately after the + /// FunctionDecl object to save an allocation like FunctionType does. + ParmVarDecl **ParamInfo; + + Stmt *Body; // Null if a prototype. + + /// DeclChain - Linked list of declarations that are defined inside this + /// function. + Decl *DeclChain; + + StorageClass SClass; +}; + + +/// FieldDecl - An instance of this class is created by Sema::ParseField to +/// represent a member of a struct/union/class. +class FieldDecl : public Decl { + QualType DeclType; +public: + FieldDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Decl *PrevDecl) + : Decl(Field, L, Id, PrevDecl), DeclType(T) {} + + QualType getType() const { return DeclType; } + QualType getCanonicalType() const { return DeclType.getCanonicalType(); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == Field; + } + 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 { + Expr *Init; // an integer constant expression + llvm::APSInt Val; // The value. +public: + EnumConstantDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, + const llvm::APSInt &V, Decl *PrevDecl) + : ValueDecl(EnumConstant, L, Id, T, PrevDecl), Init(E), Val(V) {} + + const Expr *getInitExpr() const { return Init; } + Expr *getInitExpr() { return Init; } + const llvm::APSInt &getInitVal() const { return Val; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == EnumConstant; + } + static bool classof(const EnumConstantDecl *D) { return true; } +}; + + +/// TypeDecl - Represents a declaration of a type. +/// +class TypeDecl : public Decl { + /// TypeForDecl - This indicates the Type object that represents this + /// TypeDecl. It is a cache maintained by ASTContext::getTypedefType and + /// ASTContext::getTagDeclType. + Type *TypeForDecl; + friend class ASTContext; +protected: + TypeDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl) + : Decl(DK, L, Id, PrevDecl), TypeForDecl(0) {} +public: + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() >= Typedef && D->getKind() <= Enum; + } + static bool classof(const TypeDecl *D) { return true; } +}; + + +class TypedefDecl : public TypeDecl { + /// UnderlyingType - This is the type the typedef is set to. + QualType UnderlyingType; +public: + TypedefDecl(SourceLocation L, IdentifierInfo *Id, QualType T, Decl *PrevDecl) + : TypeDecl(Typedef, L, Id, PrevDecl), UnderlyingType(T) {} + + QualType getUnderlyingType() const { return UnderlyingType; } + void setUnderlyingType(QualType newType) { UnderlyingType = newType; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return D->getKind() == Typedef; } + static bool classof(const TypedefDecl *D) { return true; } +}; + + +/// TagDecl - Represents the declaration of a struct/union/class/enum. +class TagDecl : public TypeDecl { + /// IsDefinition - True if this is a definition ("struct foo {};"), false if + /// it is a declaration ("struct foo;"). + bool IsDefinition : 1; +protected: + TagDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl) + : TypeDecl(DK, L, Id, PrevDecl) { + IsDefinition = false; + } +public: + + /// isDefinition - Return true if this decl has its body specified. + bool isDefinition() const { + return IsDefinition; + } + + const char *getKindName() const { + switch (getKind()) { + default: assert(0 && "Unknown TagDecl!"); + case Struct: return "struct"; + case Union: return "union"; + case Class: return "class"; + case Enum: return "enum"; + } + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { + return D->getKind() == Struct || D->getKind() == Union || + D->getKind() == Class || D->getKind() == Enum; + } + static bool classof(const TagDecl *D) { return true; } +protected: + void setDefinition(bool V) { IsDefinition = V; } +}; + +/// EnumDecl - Represents an enum. As an extension, we allow forward-declared +/// enums. +class EnumDecl : public TagDecl { + /// ElementList - this is a linked list of EnumConstantDecl's which are linked + /// together through their getNextDeclarator pointers. + EnumConstantDecl *ElementList; +public: + EnumDecl(SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl) + : TagDecl(Enum, L, Id, PrevDecl) { + ElementList = 0; + } + + /// defineElements - When created, EnumDecl correspond to a forward declared + /// enum. This method is used to mark the decl as being defined, with the + /// specified list of enums. + void defineElements(EnumConstantDecl *ListHead) { + assert(!isDefinition() && "Cannot redefine enums!"); + ElementList = ListHead; + setDefinition(true); + } + + static bool classof(const Decl *D) { + return D->getKind() == Enum; + } + static bool classof(const EnumDecl *D) { return true; } +}; + + +/// RecordDecl - Represents a struct/union/class. +class RecordDecl : public TagDecl { + /// 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; + + /// Members/NumMembers - This is a new[]'d array of pointers to Decls. + FieldDecl **Members; // Null if not defined. + int NumMembers; // -1 if not defined. +public: + RecordDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl) + : TagDecl(DK, L, Id, PrevDecl) { + HasFlexibleArrayMember = false; + assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!"); + Members = 0; + NumMembers = -1; + } + + bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } + void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; } + + /// defineBody - When created, RecordDecl's correspond to a forward declared + /// record. This method is used to mark the decl as being defined, with the + /// specified contents. + void defineBody(FieldDecl **Members, unsigned numMembers); + + /// getMember - If the member doesn't exist, or there are no members, this + /// function will return 0; + FieldDecl *getMember(IdentifierInfo *name); + + static bool classof(const Decl *D) { + return D->getKind() == Struct || D->getKind() == Union || + D->getKind() == Class; + } + static bool classof(const RecordDecl *D) { return true; } +}; + +} // end namespace clang + +#endif |