Add "ScopedDecl" AST, used by ValueDecl and TypeDecl.

This allows us to sink the "Next" field, which isn't used by FieldDecl and ObjcIvarDecl.

llvm-svn: 41931
This commit is contained in:
Steve Naroff 2007-09-13 18:10:37 +00:00
parent ba98f89388
commit 9324db12b2
3 changed files with 55 additions and 36 deletions

View File

@ -29,6 +29,7 @@ namespace clang {
class ASTContext;
class Preprocessor;
class Decl;
class ScopedDecl;
class Expr;
class InitListExpr;
class VarDecl;
@ -175,9 +176,9 @@ private:
/// More parsing and symbol table subroutines...
ParmVarDecl *ParseParamDeclarator(DeclaratorChunk &FI, unsigned ArgNo,
Scope *FnBodyScope);
Decl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI, SourceLocation IdLoc,
Scope *S);
Decl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S);
ScopedDecl *LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
SourceLocation IdLoc, Scope *S);
ScopedDecl *LazilyCreateBuiltin(IdentifierInfo *II, unsigned ID, Scope *S);
Decl *ImplicitlyDefineFunction(SourceLocation Loc, IdentifierInfo &II,
Scope *S);
// Decl attributes - this routine is the top level dispatcher.

View File

@ -39,8 +39,11 @@ void Sema::PopScope(SourceLocation Loc, Scope *S) {
for (Scope::decl_iterator I = S->decl_begin(), E = S->decl_end();
I != E; ++I) {
Decl *D = static_cast<Decl*>(*I);
assert(D && "This decl didn't get pushed??");
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?");
IdentifierInfo *II = D->getIdentifier();
if (!II) continue;
@ -53,7 +56,7 @@ void Sema::PopScope(SourceLocation Loc, Scope *S) {
} else {
// Scan ahead. There are only three namespaces in C, so this loop can
// never execute more than 3 times.
Decl *SomeDecl = II->getFETokenInfo<Decl>();
ScopedDecl *SomeDecl = II->getFETokenInfo<ScopedDecl>();
while (SomeDecl->getNext() != D) {
SomeDecl = SomeDecl->getNext();
assert(SomeDecl && "Didn't find this decl on its identifier's chain!");
@ -76,15 +79,15 @@ void Sema::PopScope(SourceLocation Loc, Scope *S) {
/// LookupScopedDecl - Look up the inner-most declaration in the specified
/// namespace.
Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
SourceLocation IdLoc, Scope *S) {
ScopedDecl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
SourceLocation IdLoc, Scope *S) {
if (II == 0) return 0;
Decl::IdentifierNamespace NS = (Decl::IdentifierNamespace)NSI;
// Scan up the scope chain looking for a decl that matches this identifier
// that is in the appropriate namespace. This search should not take long, as
// shadowing of names is uncommon, and deep shadowing is extremely uncommon.
for (Decl *D = II->getFETokenInfo<Decl>(); D; D = D->getNext())
for (ScopedDecl *D = II->getFETokenInfo<ScopedDecl>(); D; D = D->getNext())
if (D->getIdentifierNamespace() == NS)
return D;
@ -110,7 +113,7 @@ Decl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI,
/// LazilyCreateBuiltin - The specified Builtin-ID was first used at file scope.
/// lazily create a decl for it.
Decl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S) {
ScopedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S) {
Builtin::ID BID = (Builtin::ID)bid;
QualType R = Context.BuiltinInfo.GetBuiltinType(BID, Context);
@ -125,7 +128,7 @@ Decl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, Scope *S) {
S->AddDecl(New);
// Add this decl to the end of the identifier info.
if (Decl *LastDecl = II->getFETokenInfo<Decl>()) {
if (ScopedDecl *LastDecl = II->getFETokenInfo<ScopedDecl>()) {
// Scan until we find the last (outermost) decl in the id chain.
while (LastDecl->getNext())
LastDecl = LastDecl->getNext();
@ -446,12 +449,12 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, DeclTy *lastDeclarator) {
S = S->getParent();
// See if this is a redefinition of a variable in the same scope.
Decl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
D.getIdentifierLoc(), S);
ScopedDecl *PrevDecl = LookupScopedDecl(II, Decl::IDNS_Ordinary,
D.getIdentifierLoc(), S);
if (PrevDecl && !S->isDeclScope(PrevDecl))
PrevDecl = 0; // If in outer scope, it isn't the same thing.
Decl *New;
ScopedDecl *New;
bool InvalidDecl = false;
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
@ -545,7 +548,7 @@ Sema::ParseDeclarator(Scope *S, Declarator &D, DeclTy *lastDeclarator) {
// If this has an identifier, add it to the scope stack.
if (II) {
New->setNext(II->getFETokenInfo<Decl>());
New->setNext(II->getFETokenInfo<ScopedDecl>());
II->setFETokenInfo(New);
S->AddDecl(New);
}
@ -715,7 +718,7 @@ Sema::ParseParamDeclarator(DeclaratorChunk &FTI, unsigned ArgNo,
// If this has an identifier, add it to the scope stack.
if (II) {
New->setNext(II->getFETokenInfo<Decl>());
New->setNext(II->getFETokenInfo<ScopedDecl>());
II->setFETokenInfo(New);
FnScope->AddDecl(New);
}
@ -867,7 +870,7 @@ Sema::DeclTy *Sema::ObjcStartClassInterface(SourceLocation AtInterfaceLoc,
IDecl = new ObjcInterfaceDecl(AtInterfaceLoc, ClassName);
// Chain & install the interface decl into the identifier.
IDecl->setNext(ClassName->getFETokenInfo<Decl>());
IDecl->setNext(ClassName->getFETokenInfo<ScopedDecl>());
ClassName->setFETokenInfo(IDecl);
return IDecl;
}
@ -914,7 +917,7 @@ Sema::ObjcClassDeclaration(Scope *S, SourceLocation AtClassLoc,
// FIXME: before we create one, look up the interface decl in a hash table.
IDecl = new ObjcInterfaceDecl(SourceLocation(), IdentList[i], true);
// Chain & install the interface decl into the identifier.
IDecl->setNext(IdentList[i]->getFETokenInfo<Decl>());
IDecl->setNext(IdentList[i]->getFETokenInfo<ScopedDecl>());
IdentList[i]->setFETokenInfo(IDecl);
// Remember that this needs to be removed when the scope is popped.
@ -1020,7 +1023,7 @@ Sema::DeclTy *Sema::ParseTag(Scope *S, unsigned TagType, TagKind TK,
S = S->getParent();
// Add it to the decl chain.
New->setNext(Name->getFETokenInfo<Decl>());
New->setNext(Name->getFETokenInfo<ScopedDecl>());
Name->setFETokenInfo(New);
S->AddDecl(New);
}
@ -1325,7 +1328,7 @@ Sema::DeclTy *Sema::ParseEnumConstant(Scope *S, DeclTy *theEnumDecl,
LastEnumConst);
// Register this decl in the current scope stack.
New->setNext(Id->getFETokenInfo<Decl>());
New->setNext(Id->getFETokenInfo<ScopedDecl>());
Id->setFETokenInfo(New);
S->AddDecl(New);
return New;

View File

@ -63,19 +63,13 @@ private:
/// 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), InvalidDecl(0), Loc(L), Identifier(Id), Next(0),
: DeclKind(DK), InvalidDecl(0), Loc(L), Identifier(Id),
NextDeclarator(NextDecl) {
if (Decl::CollectingStats()) addDeclKind(DK);
}
@ -88,8 +82,6 @@ public:
const char *getName() const;
Kind getKind() const { return DeclKind; }
Decl *getNext() const { return Next; }
void setNext(Decl *N) { Next = N; }
/// setInvalidDecl - Indicates the Decl had a semantic error. This
/// allows for graceful error recovery.
@ -129,14 +121,37 @@ public:
static bool classof(const Decl *) { return true; }
};
/// ScopedDecl - Represent lexically scoped names, used for all ValueDecl's
/// and TypeDecl's.
class ScopedDecl : public Decl {
/// 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.
///
ScopedDecl *Next;
protected:
ScopedDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl)
: Decl(DK, L, Id, PrevDecl), Next(0) {}
public:
ScopedDecl *getNext() const { return Next; }
void setNext(ScopedDecl *N) { Next = N; }
// Implement isa/cast/dyncast/etc. - true for all ValueDecl's and TypeDecl's.
static bool classof(const Decl *D) {
return (D->getKind() >= Function && D->getKind() <= EnumConstant) ||
(D->getKind() >= Typedef && D->getKind() <= Enum);
}
static bool classof(const ScopedDecl *D) { 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 {
class ValueDecl : public ScopedDecl {
QualType DeclType;
protected:
ValueDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, QualType T,
Decl *PrevDecl) : Decl(DK, L, Id, PrevDecl), DeclType(T) {}
Decl *PrevDecl) : ScopedDecl(DK, L, Id, PrevDecl), DeclType(T) {}
public:
QualType getType() const { return DeclType; }
void setType(QualType newType) { DeclType = newType; }
@ -258,8 +273,8 @@ public:
Stmt *getBody() const { return Body; }
void setBody(Stmt *B) { Body = B; }
Decl *getDeclChain() const { return DeclChain; }
void setDeclChain(Decl *D) { DeclChain = D; }
ScopedDecl *getDeclChain() const { return DeclChain; }
void setDeclChain(ScopedDecl *D) { DeclChain = D; }
unsigned getNumParams() const;
const ParmVarDecl *getParamDecl(unsigned i) const {
@ -292,7 +307,7 @@ private:
/// DeclChain - Linked list of declarations that are defined inside this
/// function.
Decl *DeclChain;
ScopedDecl *DeclChain;
StorageClass SClass : 2;
bool IsInline : 1;
@ -348,7 +363,7 @@ public:
/// TypeDecl - Represents a declaration of a type.
///
class TypeDecl : public Decl {
class TypeDecl : public ScopedDecl {
/// TypeForDecl - This indicates the Type object that represents this
/// TypeDecl. It is a cache maintained by ASTContext::getTypedefType and
/// ASTContext::getTagDeclType.
@ -356,7 +371,7 @@ class TypeDecl : public Decl {
friend class ASTContext;
protected:
TypeDecl(Kind DK, SourceLocation L, IdentifierInfo *Id, Decl *PrevDecl)
: Decl(DK, L, Id, PrevDecl), TypeForDecl(0) {}
: ScopedDecl(DK, L, Id, PrevDecl), TypeForDecl(0) {}
public:
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) {