blob: 2d3b01d3ced04915f2ff36e501da5d80c0bb5dfc [file] [log] [blame]
//===--- 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