blob: ef92b42424f5a4a3e6d31cf7c135bdb54d841a39 [file] [log] [blame]
//===-- DeclBase.h - Base 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 and DeclContext interfaces.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLBASE_H
#define LLVM_CLANG_AST_DECLBASE_H
#include "clang/AST/Attr.h"
#include "clang/AST/Type.h"
#include "clang/Basic/SourceLocation.h"
namespace clang {
class TranslationUnitDecl;
class NamespaceDecl;
class ScopedDecl;
class FunctionDecl;
class CXXRecordDecl;
class EnumDecl;
class ObjCMethodDecl;
class ObjCInterfaceDecl;
/// Decl - This represents one declaration (or definition), e.g. a variable,
/// typedef, function, struct, etc.
///
class Decl {
public:
enum Kind {
// This lists the concrete classes of Decl in order of the inheritance
// hierarchy. This allows us to do efficient classof tests based on the
// enums below. The commented out names are abstract class names.
// [DeclContext] indicates that the class also inherits from DeclContext.
// Decl
TranslationUnit, // [DeclContext]
// NamedDecl
Field,
CXXField,
ObjCIvar,
ObjCCategory,
ObjCCategoryImpl,
ObjCImplementation,
ObjCProtocol,
ObjCProperty,
// ScopedDecl
Namespace, // [DeclContext]
// TypeDecl
Typedef,
// TagDecl
Enum, // [DeclContext]
// RecordDecl
Struct,
Union,
Class,
// CXXRecordDecl [DeclContext]
CXXStruct,
CXXUnion,
CXXClass,
// ValueDecl
EnumConstant,
Function, // [DeclContext]
CXXMethod,
Var,
ImplicitParam,
CXXClassVar,
ParmVar,
ObjCInterface, // [DeclContext]
ObjCCompatibleAlias,
ObjCMethod, // [DeclContext]
ObjCClass,
ObjCForwardProtocol,
ObjCPropertyImpl,
LinkageSpec,
FileScopeAsm,
// For each non-leaf class, we now define a mapping to the first/last member
// of the class, to allow efficient classof.
NamedFirst = Field , NamedLast = ParmVar,
FieldFirst = Field , FieldLast = ObjCIvar,
ScopedFirst = Namespace , ScopedLast = ParmVar,
TypeFirst = Typedef , TypeLast = CXXClass,
TagFirst = Enum , TagLast = CXXClass,
RecordFirst = Struct , RecordLast = CXXClass,
CXXRecordFirst = CXXStruct , CXXRecordLast = CXXClass,
ValueFirst = EnumConstant , ValueLast = ParmVar,
FunctionFirst = Function , FunctionLast = CXXMethod,
VarFirst = Var , VarLast = ParmVar
};
/// IdentifierNamespace - According to C99 6.2.3, there are four namespaces,
/// labels, tags, members and ordinary identifiers. These are meant
/// as bitmasks, so that searches in C++ can look into the "tag" namespace
/// during ordinary lookup.
enum IdentifierNamespace {
IDNS_Label = 0x1,
IDNS_Tag = 0x2,
IDNS_Member = 0x4,
IDNS_Ordinary = 0x8
};
/// ObjCDeclQualifier - Qualifier used on types in method declarations
/// for remote messaging. They are meant for the arguments though and
/// applied to the Decls (ObjCMethodDecl and ParmVarDecl).
enum ObjCDeclQualifier {
OBJC_TQ_None = 0x0,
OBJC_TQ_In = 0x1,
OBJC_TQ_Inout = 0x2,
OBJC_TQ_Out = 0x4,
OBJC_TQ_Bycopy = 0x8,
OBJC_TQ_Byref = 0x10,
OBJC_TQ_Oneway = 0x20
};
private:
/// Loc - The location that this decl.
SourceLocation Loc;
/// DeclKind - This indicates which class this is.
Kind DeclKind : 8;
/// InvalidDecl - This indicates a semantic error occurred.
unsigned int InvalidDecl : 1;
/// HasAttrs - This indicates whether the decl has attributes or not.
unsigned int HasAttrs : 1;
protected:
/// Access - Used by C++ decls for the access specifier.
// NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum
unsigned Access : 2;
friend class CXXClassMemberWrapper;
Decl(Kind DK, SourceLocation L) : Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false) {
if (Decl::CollectingStats()) addDeclKind(DK);
}
virtual ~Decl();
public:
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation L) { Loc = L; }
Kind getKind() const { return DeclKind; }
const char *getDeclKindName() const;
void addAttr(Attr *attr);
const Attr *getAttrs() const;
void swapAttrs(Decl *D);
void invalidateAttrs();
template<typename T> const T *getAttr() const {
for (const Attr *attr = getAttrs(); attr; attr = attr->getNext())
if (const T *V = dyn_cast<T>(attr))
return V;
return 0;
}
/// setInvalidDecl - Indicates the Decl had a semantic error. This
/// allows for graceful error recovery.
void setInvalidDecl() { InvalidDecl = 1; }
bool isInvalidDecl() const { return (bool) InvalidDecl; }
IdentifierNamespace getIdentifierNamespace() const {
switch (DeclKind) {
default: assert(0 && "Unknown decl kind!");
case ImplicitParam:
case Typedef:
case Function:
case Var:
case ParmVar:
case EnumConstant:
case ObjCInterface:
case ObjCCompatibleAlias:
case CXXField:
case CXXMethod:
case CXXClassVar:
return IDNS_Ordinary;
case Struct:
case Union:
case Class:
case CXXStruct:
case CXXUnion:
case CXXClass:
case Enum:
return IDNS_Tag;
case Namespace:
return IdentifierNamespace(IDNS_Tag | IDNS_Ordinary);
}
}
// getBody - If this Decl represents a declaration for a body of code,
// such as a function or method definition, this method returns the top-level
// Stmt* of that body. Otherwise this method returns null.
virtual Stmt* getBody() const { return 0; }
// global temp stats (until we have a per-module visitor)
static void addDeclKind(Kind k);
static bool CollectingStats(bool Enable = false);
static void PrintStats();
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *) { return true; }
/// Emit - Serialize this Decl to Bitcode.
void Emit(llvm::Serializer& S) const;
/// Create - Deserialize a Decl from Bitcode.
static Decl* Create(llvm::Deserializer& D, ASTContext& C);
/// Destroy - Call destructors and release memory.
virtual void Destroy(ASTContext& C);
protected:
/// EmitImpl - Provides the subclass-specific serialization logic for
/// serializing out a decl.
virtual void EmitImpl(llvm::Serializer& S) const {
// FIXME: This will eventually be a pure virtual function.
assert (false && "Not implemented.");
}
void EmitInRec(llvm::Serializer& S) const;
void ReadInRec(llvm::Deserializer& D, ASTContext& C);
};
/// DeclContext - This is used only as base class of specific decl types that
/// can act as declaration contexts. These decls are:
///
/// TranslationUnitDecl
/// NamespaceDecl
/// FunctionDecl
/// CXXRecordDecl
/// EnumDecl
/// ObjCMethodDecl
/// ObjCInterfaceDecl
///
class DeclContext {
/// DeclKind - This indicates which class this is.
Decl::Kind DeclKind : 8;
/// DeclChain - Linked list of declarations that are defined inside this
/// declaration context.
ScopedDecl *DeclChain;
// Used in the CastTo template to get the DeclKind
// from a Decl or a DeclContext. DeclContext doesn't have a getKind() method
// to avoid 'ambiguous access' compiler errors.
template<typename T> struct KindTrait {
static Decl::Kind getKind(const T *D) { return D->getKind(); }
};
// Used only by the ToDecl and FromDecl methods
template<typename To, typename From>
static To *CastTo(const From *D) {
Decl::Kind DK = KindTrait<From>::getKind(D);
switch(DK) {
case Decl::TranslationUnit:
return static_cast<TranslationUnitDecl*>(const_cast<From*>(D));
case Decl::Namespace:
return static_cast<NamespaceDecl*>(const_cast<From*>(D));
case Decl::Enum:
return static_cast<EnumDecl*>(const_cast<From*>(D));
case Decl::ObjCMethod:
return static_cast<ObjCMethodDecl*>(const_cast<From*>(D));
case Decl::ObjCInterface:
return static_cast<ObjCInterfaceDecl*>(const_cast<From*>(D));
default:
if (DK >= Decl::FunctionFirst && DK <= Decl::FunctionLast)
return static_cast<FunctionDecl*>(const_cast<From*>(D));
if (DK >= Decl::CXXRecordFirst && DK <= Decl::CXXRecordLast)
return static_cast<CXXRecordDecl*>(const_cast<From*>(D));
assert(false && "a decl that inherits DeclContext isn't handled");
return 0;
}
}
protected:
DeclContext(Decl::Kind K) : DeclKind(K), DeclChain(0) {}
public:
/// getParent - Returns the containing DeclContext if this is a ScopedDecl,
/// else returns NULL.
DeclContext *getParent() const;
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Function:
case Decl::CXXMethod:
case Decl::ObjCMethod:
return true;
default:
return false;
}
}
ScopedDecl *getDeclChain() const { return DeclChain; }
void setDeclChain(ScopedDecl *D) { DeclChain = D; }
/// ToDecl and FromDecl make Decl <-> DeclContext castings.
/// They are intended to be used by the simplify_type and cast_convert_val
/// templates.
static Decl *ToDecl (const DeclContext *D);
static DeclContext *FromDecl (const Decl *D);
static bool classof(const Decl *D) {
switch (D->getKind()) {
case Decl::TranslationUnit:
case Decl::Namespace:
case Decl::Enum:
case Decl::ObjCMethod:
case Decl::ObjCInterface:
return true;
default:
if (D->getKind() >= Decl::FunctionFirst &&
D->getKind() <= Decl::FunctionLast)
return true;
if (D->getKind() >= Decl::CXXRecordFirst &&
D->getKind() <= Decl::CXXRecordLast)
return true;
return false;
}
}
static bool classof(const DeclContext *D) { return true; }
static bool classof(const TranslationUnitDecl *D) { return true; }
static bool classof(const NamespaceDecl *D) { return true; }
static bool classof(const FunctionDecl *D) { return true; }
static bool classof(const CXXRecordDecl *D) { return true; }
static bool classof(const EnumDecl *D) { return true; }
static bool classof(const ObjCMethodDecl *D) { return true; }
static bool classof(const ObjCInterfaceDecl *D) { return true; }
private:
void EmitOutRec(llvm::Serializer& S) const;
void ReadOutRec(llvm::Deserializer& D, ASTContext& C);
friend class Decl;
};
template<> struct DeclContext::KindTrait<DeclContext> {
static Decl::Kind getKind(const DeclContext *D) { return D->DeclKind; }
};
} // end clang.
namespace llvm {
/// Implement simplify_type for DeclContext, so that we can dyn_cast from
/// DeclContext to a specific Decl class.
template<> struct simplify_type<const ::clang::DeclContext*> {
typedef ::clang::Decl* SimpleType;
static SimpleType getSimplifiedValue(const ::clang::DeclContext *Val) {
return ::clang::DeclContext::ToDecl(Val);
}
};
template<> struct simplify_type< ::clang::DeclContext*>
: public simplify_type<const ::clang::DeclContext*> {};
template<> struct simplify_type<const ::clang::DeclContext> {
typedef ::clang::Decl SimpleType;
static SimpleType &getSimplifiedValue(const ::clang::DeclContext &Val) {
return *::clang::DeclContext::ToDecl(&Val);
}
};
template<> struct simplify_type< ::clang::DeclContext>
: public simplify_type<const ::clang::DeclContext> {};
/// Implement cast_convert_val for DeclContext, so that we can dyn_cast from
/// a Decl class to DeclContext.
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext,const FromTy,const FromTy> {
static ::clang::DeclContext &doit(const FromTy &Val) {
return *::clang::DeclContext::FromDecl(&Val);
}
};
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext,FromTy,FromTy>
: public cast_convert_val< ::clang::DeclContext,const FromTy,const FromTy>
{};
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext,const FromTy*,const FromTy*> {
static ::clang::DeclContext *doit(const FromTy *Val) {
return ::clang::DeclContext::FromDecl(Val);
}
};
template<class FromTy>
struct cast_convert_val< ::clang::DeclContext,FromTy*,FromTy*>
: public cast_convert_val< ::clang::DeclContext,const FromTy*,const FromTy*>
{};
} // end namespace llvm
#endif