blob: ec3c753051cc3240b39819f81ebac2ac6cff2457 [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 FunctionDecl;
class ObjCMethodDecl;
class EnumDecl;
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.
// Decl
// NamedDecl
Field,
ObjCIvar,
ObjCCategory,
ObjCCategoryImpl,
ObjCImplementation,
ObjCProtocol,
ObjCProperty,
// ScopedDecl
// TypeDecl
Typedef,
// TagDecl
Enum,
// RecordDecl
Struct,
Union,
Class,
// ValueDecl
EnumConstant,
Function,
// VarDecl
BlockVar,
FileVar,
ParmVar,
ObjCInterface,
ObjCCompatibleAlias,
ObjCMethod,
ObjCClass,
ObjCForwardProtocol,
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 = Typedef, ScopedLast = ParmVar,
TypeFirst = Typedef, TypeLast = Class,
TagFirst = Enum , TagLast = Class,
RecordFirst = Struct , RecordLast = Class,
ValueFirst = EnumConstant , ValueLast = ParmVar,
VarFirst = BlockVar , VarLast = ParmVar
};
/// 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
};
/// 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:
Decl(Kind DK, SourceLocation L) : Loc(L), DeclKind(DK), InvalidDecl(0),
HasAttrs(false) {
if (Decl::CollectingStats()) addDeclKind(DK);
}
public:
// TODO: This should probably be made protected once derived classes have
// destructors.
virtual ~Decl();
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;
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 Typedef:
case Function:
case BlockVar:
case FileVar:
case ParmVar:
case EnumConstant:
case ObjCInterface:
case ObjCCompatibleAlias:
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(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.
void Destroy(ASTContext& C) const;
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:
///
/// FunctionDecl
/// ObjCMethodDecl
/// EnumDecl
/// ObjCInterfaceDecl
///
class DeclContext {
/// DeclKind - This indicates which class this is.
Decl::Kind DeclKind : 8;
// 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::Function:
return static_cast<FunctionDecl*>(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));
case Decl::Enum:
return static_cast<EnumDecl*>(const_cast<From*>(D));
default:
assert(false && "a decl that inherits DeclContext isn't handled");
return 0;
}
}
protected:
DeclContext(Decl::Kind K) : DeclKind(K) {}
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::ObjCMethod:
return true;
default:
return false;
}
}
/// 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::Function:
case Decl::ObjCMethod:
case Decl::ObjCInterface:
case Decl::Enum:
return true;
default:
return false;
}
}
static bool classof(const DeclContext *D) { return true; }
static bool classof(const FunctionDecl *D) { return true; }
static bool classof(const ObjCMethodDecl *D) { return true; }
static bool classof(const EnumDecl *D) { return true; }
static bool classof(const ObjCInterfaceDecl *D) { return true; }
};
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