Added new C++ AST Decl subclasses.

llvm-svn: 52155
This commit is contained in:
Argyrios Kyrtzidis 2008-06-09 21:05:31 +00:00
parent 7192a54772
commit 2951e14520
8 changed files with 343 additions and 39 deletions

View File

@ -17,6 +17,7 @@
// This header exports all AST interfaces.
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"

View File

@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
// This file defines the Decl interface and subclasses.
// This file defines the Decl subclasses.
//
//===----------------------------------------------------------------------===//
@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECL_H
#include "clang/AST/DeclBase.h"
#include "clang/Parse/AccessSpecifier.h"
namespace clang {
class Expr;
@ -382,11 +383,6 @@ private:
/// function.
ScopedDecl *DeclChain;
// NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
unsigned SClass : 2;
bool IsInline : 1;
bool IsImplicit : 1;
/// PreviousDeclaration - A link to the previous declaration of this
/// same function, NULL if this is the first declaration. For
/// example, in the following code, the PreviousDeclaration can be
@ -398,13 +394,19 @@ private:
/// int f(int x, int y) { return x + y; }
FunctionDecl *PreviousDeclaration;
FunctionDecl(DeclContext *DC, SourceLocation L,
// NOTE: VC++ treats enums as signed, avoid using the StorageClass enum
unsigned SClass : 2;
bool IsInline : 1;
bool IsImplicit : 1;
protected:
FunctionDecl(Kind DK, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, QualType T,
StorageClass S, bool isInline, ScopedDecl *PrevDecl)
: ValueDecl(Function, DC, L, Id, T, PrevDecl),
DeclContext(Function),
ParamInfo(0), Body(0), DeclChain(0), SClass(S),
IsInline(isInline), IsImplicit(0), PreviousDeclaration(0) {}
: ValueDecl(DK, DC, L, Id, T, PrevDecl),
DeclContext(DK),
ParamInfo(0), Body(0), DeclChain(0), PreviousDeclaration(0),
SClass(S), IsInline(isInline), IsImplicit(0) {}
virtual ~FunctionDecl();
virtual void Destroy(ASTContext& C);
@ -498,7 +500,9 @@ public:
bool isInline() const { return IsInline; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == Function; }
static bool classof(const Decl *D) {
return D->getKind() >= FunctionFirst && D->getKind() <= FunctionLast;
}
static bool classof(const FunctionDecl *D) { return true; }
protected:
@ -608,6 +612,9 @@ protected:
IdentifierInfo *Id, ScopedDecl *PrevDecl)
: ScopedDecl(DK, DC, L, Id, PrevDecl), TypeForDecl(0) {}
public:
void setAccess(AccessSpecifier AS) { Access = AS; }
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {
return D->getKind() >= TypeFirst && D->getKind() <= TypeLast;
@ -759,7 +766,8 @@ class RecordDecl : public TagDecl {
/// Members/NumMembers - This is a new[]'d array of pointers to Decls.
FieldDecl **Members; // Null if not defined.
int NumMembers; // -1 if not defined.
protected:
RecordDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
ScopedDecl *PrevDecl) : TagDecl(DK, DC, L, Id, PrevDecl) {
HasFlexibleArrayMember = false;

View File

@ -21,9 +21,11 @@
namespace clang {
class TranslationUnitDecl;
class NamespaceDecl;
class ScopedDecl;
class FunctionDecl;
class ObjCMethodDecl;
class CXXRecordDecl;
class EnumDecl;
class ObjCMethodDecl;
class ObjCInterfaceDecl;
/// Decl - This represents one declaration (or definition), e.g. a variable,
@ -35,11 +37,13 @@ public:
// 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] indicatea that the class also inherits from DeclContext.
// Decl
TranslationUnit,
TranslationUnit, // [DeclContext]
// NamedDecl
Field,
CXXField,
ObjCIvar,
ObjCCategory,
ObjCCategoryImpl,
@ -47,23 +51,29 @@ public:
ObjCProtocol,
ObjCProperty,
// ScopedDecl
Namespace,
Namespace, // [DeclContext]
// TypeDecl
Typedef,
// TagDecl
Enum,
Enum, // [DeclContext]
// RecordDecl
Struct,
Union,
Class,
// CXXRecordDecl [DeclContext]
CXXStruct,
CXXUnion,
CXXClass,
// ValueDecl
EnumConstant,
Function,
Function, // [DeclContext]
CXXMethod,
Var,
CXXClassVar,
ParmVar,
ObjCInterface,
ObjCInterface, // [DeclContext]
ObjCCompatibleAlias,
ObjCMethod,
ObjCMethod, // [DeclContext]
ObjCClass,
ObjCForwardProtocol,
ObjCPropertyImpl,
@ -72,14 +82,16 @@ public:
// 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 = Class,
TagFirst = Enum , TagLast = Class,
RecordFirst = Struct , RecordLast = Class,
ValueFirst = EnumConstant , ValueLast = ParmVar,
VarFirst = Var , VarLast = ParmVar
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,
@ -118,7 +130,13 @@ private:
/// HasAttrs - This indicates whether the decl has attributes or not.
unsigned int HasAttrs : 1;
protected:
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);
@ -161,10 +179,14 @@ public:
case EnumConstant:
case ObjCInterface:
case ObjCCompatibleAlias:
case CXXField:
return IDNS_Ordinary;
case Struct:
case Union:
case Class:
case CXXStruct:
case CXXUnion:
case CXXClass:
case Enum:
return IDNS_Tag;
case Namespace:
@ -206,8 +228,9 @@ protected:
/// TranslationUnitDecl
/// NamespaceDecl
/// FunctionDecl
/// ObjCMethodDecl
/// CXXRecordDecl
/// EnumDecl
/// ObjCMethodDecl
/// ObjCInterfaceDecl
///
class DeclContext {
@ -230,15 +253,18 @@ class DeclContext {
return static_cast<TranslationUnitDecl*>(const_cast<From*>(D));
case Decl::Namespace:
return static_cast<NamespaceDecl*>(const_cast<From*>(D));
case Decl::Function:
return static_cast<FunctionDecl*>(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));
case Decl::Enum:
return static_cast<EnumDecl*>(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;
}
@ -255,6 +281,7 @@ public:
bool isFunctionOrMethod() const {
switch (DeclKind) {
case Decl::Function:
case Decl::CXXMethod:
case Decl::ObjCMethod:
return true;
default:
@ -272,12 +299,17 @@ public:
switch (D->getKind()) {
case Decl::TranslationUnit:
case Decl::Namespace:
case Decl::Function:
case Decl::Enum:
case Decl::ObjCMethod:
case Decl::ObjCInterface:
case Decl::Enum:
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;
}
}
@ -285,8 +317,9 @@ public:
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 ObjCMethodDecl *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; }
};

View File

@ -0,0 +1,195 @@
//===-- DeclCXX.h - Classes for representing C++ 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 C++ Decl subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLCXX_H
#define LLVM_CLANG_AST_DECLCXX_H
#include "clang/AST/Decl.h"
namespace clang {
class CXXRecordDecl;
/// CXXFieldDecl - Represents an instance field of a C++ struct/union/class.
class CXXFieldDecl : public FieldDecl {
CXXRecordDecl *Parent;
CXXFieldDecl(CXXRecordDecl *RD, SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *BW = NULL)
: FieldDecl(CXXField, L, Id, T, BW), Parent(RD) {}
public:
static CXXFieldDecl *Create(ASTContext &C, CXXRecordDecl *RD,SourceLocation L,
IdentifierInfo *Id, QualType T, Expr *BW = NULL);
void setAccess(AccessSpecifier AS) { Access = AS; }
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
CXXRecordDecl *getParent() const { return Parent; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == CXXField; }
static bool classof(const CXXFieldDecl *D) { return true; }
};
/// CXXRecordDecl - Represents a C++ struct/union/class.
/// The only difference with RecordDecl is that CXXRecordDecl is a DeclContext.
class CXXRecordDecl : public RecordDecl, public DeclContext {
protected:
CXXRecordDecl(Kind DK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
ScopedDecl *PrevDecl) : RecordDecl(DK, DC, L, Id, PrevDecl),
DeclContext(DK) {
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
}
public:
static CXXRecordDecl *Create(ASTContext &C, Kind DK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
ScopedDecl *PrevDecl);
const CXXFieldDecl *getMember(unsigned i) const {
return cast<const CXXFieldDecl>(RecordDecl::getMember(i));
}
CXXFieldDecl *getMember(unsigned i) {
return cast<CXXFieldDecl>(RecordDecl::getMember(i));
}
/// getMember - If the member doesn't exist, or there are no members, this
/// function will return 0;
CXXFieldDecl *getMember(IdentifierInfo *name) {
return cast_or_null<CXXFieldDecl>(RecordDecl::getMember(name));
}
static bool classof(const Decl *D) {
return D->getKind() >= CXXRecordFirst && D->getKind() <= CXXRecordLast;
}
static bool classof(const CXXRecordDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this CXXRecordDecl. Called by Decl::Emit.
// FIXME: Implement this.
//virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a CXXRecordDecl. Called by Decl::Create.
// FIXME: Implement this.
static CXXRecordDecl* CreateImpl(Kind DK, llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// CXXMethodDecl - Represents a static or instance method of a
/// struct/union/class.
class CXXMethodDecl : public FunctionDecl {
CXXMethodDecl(CXXRecordDecl *RD, SourceLocation L,
IdentifierInfo *Id, QualType T,
bool isStatic, bool isInline, ScopedDecl *PrevDecl)
: FunctionDecl(CXXMethod, RD, L, Id, T, (isStatic ? Static : None),
isInline, PrevDecl) {}
public:
static CXXMethodDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, IdentifierInfo *Id,
QualType T, bool isStatic = false,
bool isInline = false, ScopedDecl *PrevDecl = 0);
bool isStatic() const { return getStorageClass() == Static; }
bool isInstance() const { return !isStatic(); }
void setAccess(AccessSpecifier AS) { Access = AS; }
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
/// getThisType - Returns the type of 'this' pointer.
/// Should only be called for instance methods.
QualType getThisType(ASTContext &C) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == CXXMethod; }
static bool classof(const CXXMethodDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this CXXMethodDecl. Called by Decl::Emit.
// FIXME: Implement this.
//virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a CXXMethodDecl. Called by Decl::Create.
// FIXME: Implement this.
static CXXMethodDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// CXXClassVarDecl - Represents a static data member of a struct/union/class.
class CXXClassVarDecl : public VarDecl {
CXXClassVarDecl(CXXRecordDecl *RD, SourceLocation L,
IdentifierInfo *Id, QualType T, ScopedDecl *PrevDecl)
: VarDecl(CXXClassVar, RD, L, Id, T, None, PrevDecl) {}
public:
static CXXClassVarDecl *Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L,IdentifierInfo *Id,
QualType T, ScopedDecl *PrevDecl);
void setAccess(AccessSpecifier AS) { Access = AS; }
AccessSpecifier getAccess() const { return AccessSpecifier(Access); }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == CXXClassVar; }
static bool classof(const CXXClassVarDecl *D) { return true; }
protected:
/// EmitImpl - Serialize this CXXClassVarDecl. Called by Decl::Emit.
// FIXME: Implement this.
//virtual void EmitImpl(llvm::Serializer& S) const;
/// CreateImpl - Deserialize a CXXClassVarDecl. Called by Decl::Create.
// FIXME: Implement this.
static CXXClassVarDecl* CreateImpl(llvm::Deserializer& D, ASTContext& C);
friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C);
};
/// CXXClassMemberWrapper - A wrapper class for C++ class member decls.
/// Common functions like set/getAccess are included here to avoid bloating
/// the interface of non-C++ specific decl classes, like NamedDecl.
class CXXClassMemberWrapper {
Decl *MD;
public:
CXXClassMemberWrapper(Decl *D) : MD(D) {
assert(isMember(D) && "Not a C++ class member!");
}
AccessSpecifier getAccess() const {
return AccessSpecifier(MD->Access);
}
void setAccess(AccessSpecifier AS) {
assert(AS != AS_none && "Access must be specified.");
MD->Access = AS;
}
CXXRecordDecl *getParent() const {
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(MD)) {
return cast<CXXRecordDecl>(SD->getDeclContext());
}
return cast<CXXFieldDecl>(MD)->getParent();
}
static bool isMember(Decl *D) {
if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D)) {
return isa<CXXRecordDecl>(SD->getDeclContext());
}
return isa<CXXFieldDecl>(D);
}
};
} // end namespace clang
#endif

View File

@ -62,7 +62,7 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC,
StorageClass S, bool isInline,
ScopedDecl *PrevDecl) {
void *Mem = C.getAllocator().Allocate<FunctionDecl>();
return new (Mem) FunctionDecl(DC, L, Id, T, S, isInline, PrevDecl);
return new (Mem) FunctionDecl(Function, DC, L, Id, T, S, isInline, PrevDecl);
}
FieldDecl *FieldDecl::Create(ASTContext &C, SourceLocation L,

View File

@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ASTContext.h"
#include "llvm/ADT/DenseMap.h"
using namespace clang;
@ -206,6 +207,13 @@ void Decl::addDeclKind(Kind k) {
case LinkageSpec: nLinkageSpecDecl++; break;
case FileScopeAsm: nFileScopeAsmDecl++; break;
case TranslationUnit: break;
// FIXME: Statistics for C++ decls.
case CXXField:
case CXXStruct: case CXXUnion: case CXXClass:
case CXXMethod:
case CXXClassVar:
break;
}
}

58
clang/lib/AST/DeclCXX.cpp Normal file
View File

@ -0,0 +1,58 @@
//===--- DeclCXX.cpp - C++ Declaration AST Node Implementation ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the C++ related Decl classes.
//
//===----------------------------------------------------------------------===//
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ASTContext.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// Decl Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===//
CXXFieldDecl *CXXFieldDecl::Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, IdentifierInfo *Id,
QualType T, Expr *BW) {
void *Mem = C.getAllocator().Allocate<CXXFieldDecl>();
return new (Mem) CXXFieldDecl(RD, L, Id, T, BW);
}
CXXRecordDecl *CXXRecordDecl::Create(ASTContext &C, Kind DK, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id,
ScopedDecl *PrevDecl) {
void *Mem = C.getAllocator().Allocate<CXXRecordDecl>();
return new (Mem) CXXRecordDecl(DK, DC, L, Id, PrevDecl);
}
CXXMethodDecl *
CXXMethodDecl::Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, IdentifierInfo *Id,
QualType T, bool isStatic, bool isInline,
ScopedDecl *PrevDecl) {
void *Mem = C.getAllocator().Allocate<CXXMethodDecl>();
return new (Mem) CXXMethodDecl(RD, L, Id, T, isStatic, isInline, PrevDecl);
}
QualType CXXMethodDecl::getThisType(ASTContext &C) const {
assert(isInstance() && "No 'this' for static methods!");
QualType ClassTy = C.getTagDeclType(cast<CXXRecordDecl>(getParent()));
QualType ThisTy = C.getPointerType(ClassTy);
ThisTy.addConst();
return ThisTy;
}
CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
SourceLocation L, IdentifierInfo *Id,
QualType T, ScopedDecl *PrevDecl) {
void *Mem = C.getAllocator().Allocate<CXXClassVarDecl>();
return new (Mem) CXXClassVarDecl(RD, L, Id, T, PrevDecl);
}

View File

@ -384,7 +384,8 @@ FunctionDecl* FunctionDecl::CreateImpl(Deserializer& D, ASTContext& C) {
void *Mem = C.getAllocator().Allocate<FunctionDecl>();
FunctionDecl* decl = new (Mem)
FunctionDecl(0, SourceLocation(), NULL, QualType(), SClass, IsInline, 0);
FunctionDecl(Function, 0, SourceLocation(), NULL,
QualType(), SClass, IsInline, 0);
decl->ValueDecl::ReadInRec(D, C);
D.ReadPtr(decl->DeclChain);