-Add DeclChain member to DeclContext.

-ScopedDecls get chained to their DeclContext.
-DeclContext's DeclChain replaces FunctionDecl's DeclChain and EnumDecl's ElementList.

llvm-svn: 52164
This commit is contained in:
Argyrios Kyrtzidis 2008-06-10 01:32:09 +00:00
parent 1b095b443c
commit 406fb231f8
5 changed files with 85 additions and 53 deletions

View File

@ -379,10 +379,6 @@ private:
Stmt *Body; // Null if a prototype.
/// DeclChain - Linked list of declarations that are defined inside this
/// function.
ScopedDecl *DeclChain;
/// 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
@ -405,7 +401,7 @@ protected:
StorageClass S, bool isInline, ScopedDecl *PrevDecl)
: ValueDecl(DK, DC, L, Id, T, PrevDecl),
DeclContext(DK),
ParamInfo(0), Body(0), DeclChain(0), PreviousDeclaration(0),
ParamInfo(0), Body(0), PreviousDeclaration(0),
SClass(S), IsInline(isInline), IsImplicit(0) {}
virtual ~FunctionDecl();
@ -438,9 +434,6 @@ public:
bool isImplicit() { return IsImplicit; }
void setImplicit() { IsImplicit = true; }
ScopedDecl *getDeclChain() const { return DeclChain; }
void setDeclChain(ScopedDecl *D) { DeclChain = D; }
/// getPreviousDeclaration - Return the previous declaration of this
/// function.
@ -720,10 +713,9 @@ protected:
/// EnumDecl - Represents an enum. As an extension, we allow forward-declared
/// enums.
class EnumDecl : public TagDecl, public DeclContext {
/// ElementList - this is a linked list of EnumConstantDecl's which are linked
/// together through their getNextDeclarator pointers.
EnumConstantDecl *ElementList;
// EnumDecl's DeclChain points to a linked list of EnumConstantDecl's which
// are linked together through their getNextDeclarator pointers.
/// IntegerType - This represent the integer type that the enum corresponds
/// to for code generation purposes. Note that the enumerator constants may
/// have a different type than this does.
@ -732,7 +724,6 @@ class EnumDecl : public TagDecl, public DeclContext {
EnumDecl(DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, ScopedDecl *PrevDecl)
: TagDecl(Enum, DC, L, Id, PrevDecl), DeclContext(Enum) {
ElementList = 0;
IntegerType = QualType();
}
public:
@ -747,7 +738,7 @@ public:
/// specified list of enums.
void defineElements(EnumConstantDecl *ListHead, QualType NewType) {
assert(!isDefinition() && "Cannot redefine enums!");
ElementList = ListHead;
setDeclChain(ListHead);
setDefinition(true);
IntegerType = NewType;
@ -759,8 +750,12 @@ public:
/// getEnumConstantList - Return the first EnumConstantDecl in the enum.
///
EnumConstantDecl *getEnumConstantList() { return ElementList; }
const EnumConstantDecl *getEnumConstantList() const { return ElementList; }
EnumConstantDecl *getEnumConstantList() {
return cast_or_null<EnumConstantDecl>(getDeclChain());
}
const EnumConstantDecl *getEnumConstantList() const {
return cast_or_null<const EnumConstantDecl>(getDeclChain());
}
static bool classof(const Decl *D) { return D->getKind() == Enum; }
static bool classof(const EnumDecl *D) { return true; }

View File

@ -237,6 +237,10 @@ 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.
@ -271,7 +275,7 @@ class DeclContext {
}
protected:
DeclContext(Decl::Kind K) : DeclKind(K) {}
DeclContext(Decl::Kind K) : DeclKind(K), DeclChain(0) {}
public:
/// getParent - Returns the containing DeclContext if this is a ScopedDecl,
@ -289,6 +293,9 @@ public:
}
}
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.
@ -321,6 +328,12 @@ public:
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> {

View File

@ -116,7 +116,7 @@ RecordDecl *RecordDecl::Create(ASTContext &C, TagKind TK, DeclContext *DC,
}
void EnumDecl::Destroy(ASTContext& C) {
if (ElementList) ElementList->Destroy(C);
if (getEnumConstantList()) getEnumConstantList()->Destroy(C);
Decl::Destroy(C);
}

View File

@ -30,10 +30,13 @@ using namespace clang;
void Decl::Emit(Serializer& S) const {
S.EmitInt(getKind());
EmitImpl(S);
if (const DeclContext *DC = dyn_cast<const DeclContext>(this))
DC->EmitOutRec(S);
}
Decl* Decl::Create(Deserializer& D, ASTContext& C) {
Decl *Dcl;
Kind k = static_cast<Kind>(D.ReadInt());
switch (k) {
@ -42,39 +45,56 @@ Decl* Decl::Create(Deserializer& D, ASTContext& C) {
break;
case TranslationUnit:
return TranslationUnitDecl::CreateImpl(D, C);
Dcl = TranslationUnitDecl::CreateImpl(D, C);
break;
case Namespace:
return NamespaceDecl::CreateImpl(D, C);
Dcl = NamespaceDecl::CreateImpl(D, C);
break;
case Var:
return VarDecl::CreateImpl(D, C);
Dcl = VarDecl::CreateImpl(D, C);
break;
case Enum:
return EnumDecl::CreateImpl(D, C);
Dcl = EnumDecl::CreateImpl(D, C);
break;
case EnumConstant:
return EnumConstantDecl::CreateImpl(D, C);
Dcl = EnumConstantDecl::CreateImpl(D, C);
break;
case Field:
return FieldDecl::CreateImpl(D, C);
Dcl = FieldDecl::CreateImpl(D, C);
break;
case ParmVar:
return ParmVarDecl::CreateImpl(D, C);
Dcl = ParmVarDecl::CreateImpl(D, C);
break;
case Function:
return FunctionDecl::CreateImpl(D, C);
Dcl = FunctionDecl::CreateImpl(D, C);
break;
case Class:
case Union:
case Struct:
return RecordDecl::CreateImpl(k, D, C);
Dcl = RecordDecl::CreateImpl(k, D, C);
break;
case Typedef:
return TypedefDecl::CreateImpl(D, C);
Dcl = TypedefDecl::CreateImpl(D, C);
break;
case FileScopeAsm:
return FileScopeAsmDecl::CreateImpl(D, C);
Dcl = FileScopeAsmDecl::CreateImpl(D, C);
break;
}
if (DeclContext *DC = dyn_cast<DeclContext>(Dcl))
DC->ReadOutRec(D, C);
return Dcl;
}
//===----------------------------------------------------------------------===//
@ -89,6 +109,18 @@ void Decl::ReadInRec(Deserializer& D, ASTContext& C) {
Loc = SourceLocation::ReadVal(D); // From Decl.
}
//===----------------------------------------------------------------------===//
// Common serialization logic for subclasses of DeclContext.
//===----------------------------------------------------------------------===//
void DeclContext::EmitOutRec(Serializer& S) const {
S.EmitPtr(DeclChain);
}
void DeclContext::ReadOutRec(Deserializer& D, ASTContext& C) {
D.ReadPtr(DeclChain);
}
//===----------------------------------------------------------------------===//
// Common serialization logic for subclasses of NamedDecl.
//===----------------------------------------------------------------------===//
@ -283,7 +315,7 @@ void EnumDecl::EmitImpl(Serializer& S) const {
ScopedDecl::EmitInRec(S);
S.EmitBool(isDefinition());
S.Emit(IntegerType);
S.BatchEmitOwnedPtrs(ElementList,getNextDeclarator());
S.BatchEmitOwnedPtrs(getEnumConstantList(),getNextDeclarator());
}
EnumDecl* EnumDecl::CreateImpl(Deserializer& D, ASTContext& C) {
@ -299,7 +331,7 @@ EnumDecl* EnumDecl::CreateImpl(Deserializer& D, ASTContext& C) {
D.BatchReadOwnedPtrs(Elist, next_declarator, C);
decl->ElementList = cast_or_null<EnumConstantDecl>(Elist);
decl->setDeclChain(cast_or_null<EnumConstantDecl>(Elist));
decl->setNextDeclarator(cast_or_null<ScopedDecl>(next_declarator));
return decl;
@ -361,7 +393,6 @@ void FunctionDecl::EmitImpl(Serializer& S) const {
S.EmitInt(SClass); // From FunctionDecl.
S.EmitBool(IsInline); // From FunctionDecl.
ValueDecl::EmitInRec(S);
S.EmitPtr(DeclChain);
S.EmitPtr(PreviousDeclaration);
// NOTE: We do not need to serialize out the number of parameters, because
@ -388,7 +419,6 @@ FunctionDecl* FunctionDecl::CreateImpl(Deserializer& D, ASTContext& C) {
QualType(), SClass, IsInline, 0);
decl->ValueDecl::ReadInRec(D, C);
D.ReadPtr(decl->DeclChain);
D.ReadPtr(decl->PreviousDeclaration);
Decl* next_declarator;

View File

@ -17,6 +17,7 @@
#include "clang/AST/Attr.h"
#include "clang/AST/Builtins.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/Parse/DeclSpec.h"
@ -90,34 +91,27 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
if (S->decl_empty()) return;
assert((S->getFlags() & Scope::DeclScope) &&"Scope shouldn't contain decls!");
// We only want to remove the decls from the identifier decl chains for local
// scopes, when inside a function/method.
if (S->getFnParent() == 0)
return;
for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
I != E; ++I) {
Decl *TmpD = static_cast<Decl*>(*I);
assert(TmpD && "This decl didn't get pushed??");
ScopedDecl *D = dyn_cast<ScopedDecl>(TmpD);
assert(D && "This decl isn't a ScopedDecl?");
if (isa<CXXFieldDecl>(TmpD)) continue;
assert(isa<ScopedDecl>(TmpD) && "Decl isn't ScopedDecl?");
ScopedDecl *D = cast<ScopedDecl>(TmpD);
IdentifierInfo *II = D->getIdentifier();
if (!II) continue;
// Unlink this decl from the identifier.
IdResolver.RemoveDecl(D);
// We only want to remove the decls from the identifier decl chains for local
// scopes, when inside a function/method.
if (S->getFnParent() != 0)
IdResolver.RemoveDecl(D);
// This will have to be revisited for C++: there we want to nest stuff in
// namespace decls etc. Even for C, we might want a top-level translation
// unit decl or something.
if (!CurFunctionDecl)
continue;
// Chain this decl to the containing function, it now owns the memory for
// the decl.
D->setNext(CurFunctionDecl->getDeclChain());
CurFunctionDecl->setDeclChain(D);
// Chain this decl to the containing DeclContext.
D->setNext(CurContext->getDeclChain());
CurContext->setDeclChain(D);
}
}