From 9324db12b20a55b3c89b2b2274af2495326e8502 Mon Sep 17 00:00:00 2001 From: Steve Naroff Date: Thu, 13 Sep 2007 18:10:37 +0000 Subject: [PATCH] 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 --- clang/Sema/Sema.h | 7 ++--- clang/Sema/SemaDecl.cpp | 37 ++++++++++++++------------ clang/include/clang/AST/Decl.h | 47 ++++++++++++++++++++++------------ 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/clang/Sema/Sema.h b/clang/Sema/Sema.h index 7a3466f97d32..c4d1e4fa7f78 100644 --- a/clang/Sema/Sema.h +++ b/clang/Sema/Sema.h @@ -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. diff --git a/clang/Sema/SemaDecl.cpp b/clang/Sema/SemaDecl.cpp index 245e75c3b601..e997a050aff8 100644 --- a/clang/Sema/SemaDecl.cpp +++ b/clang/Sema/SemaDecl.cpp @@ -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(*I); - assert(D && "This decl didn't get pushed??"); + Decl *TmpD = static_cast(*I); + assert(TmpD && "This decl didn't get pushed??"); + ScopedDecl *D = dyn_cast(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(); + ScopedDecl *SomeDecl = II->getFETokenInfo(); 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(); D; D = D->getNext()) + for (ScopedDecl *D = II->getFETokenInfo(); 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()) { + if (ScopedDecl *LastDecl = II->getFETokenInfo()) { // 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()); + New->setNext(II->getFETokenInfo()); 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()); + New->setNext(II->getFETokenInfo()); 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()); + IDecl->setNext(ClassName->getFETokenInfo()); 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()); + IDecl->setNext(IdentList[i]->getFETokenInfo()); 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()); + New->setNext(Name->getFETokenInfo()); 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()); + New->setNext(Id->getFETokenInfo()); Id->setFETokenInfo(New); S->AddDecl(New); return New; diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index aba9e17ded25..d0f4aba1546f 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -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) {