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:
parent
ba98f89388
commit
9324db12b2
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue