Newer
Older
//===- IdentifierResolver.cpp - Lexical Scope Name lookup -------*- C++ -*-===//
//
// 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 IdentifierResolver class, which is used for lexical
// scoped lookup, based on identifier.
//
//===----------------------------------------------------------------------===//
#include "IdentifierResolver.h"
Argyrios Kyrtzidis
committed
#include "clang/Basic/LangOptions.h"
using namespace clang;
//===----------------------------------------------------------------------===//
// IdDeclInfoMap class
//===----------------------------------------------------------------------===//
/// IdDeclInfoMap - Associates IdDeclInfos with Identifiers.
/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
/// individual IdDeclInfo to heap.
class IdentifierResolver::IdDeclInfoMap {
static const unsigned int VECTOR_SIZE = 512;
// Holds vectors of IdDeclInfos that serve as 'pools'.
// New vectors are added when the current one is full.
std::list< std::vector<IdDeclInfo> > IDIVecs;
unsigned int CurIndex;
public:
/// Returns the IdDeclInfo associated to the IdentifierInfo.
/// It creates a new IdDeclInfo if one was not created before for this id.
IdDeclInfo &operator[](IdentifierInfo *II);
};
Argyrios Kyrtzidis
committed
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//===----------------------------------------------------------------------===//
// LookupContext Implementation
//===----------------------------------------------------------------------===//
/// getContext - Returns translation unit context for non ScopedDecls and
/// for EnumConstantDecls returns the parent context of their EnumDecl.
DeclContext *IdentifierResolver::LookupContext::getContext(Decl *D) {
DeclContext *Ctx;
if (CXXFieldDecl *FD = dyn_cast<CXXFieldDecl>(D))
return FD->getParent();
if (EnumConstantDecl *EnumD = dyn_cast<EnumConstantDecl>(D)) {
Ctx = EnumD->getDeclContext()->getParent();
} else if (ScopedDecl *SD = dyn_cast<ScopedDecl>(D))
Ctx = SD->getDeclContext();
else
return TUCtx();
if (isa<TranslationUnitDecl>(Ctx))
return TUCtx();
return Ctx;
}
/// isEqOrContainedBy - Returns true of the given context is the same or a
/// parent of this one.
bool IdentifierResolver::LookupContext::isEqOrContainedBy(
const LookupContext &PC) const {
if (PC.isTU()) return true;
for (LookupContext Next = *this; !Next.isTU(); Next = Next.getParent())
if (Next.Ctx == PC.Ctx) return true;
return false;
}
//===----------------------------------------------------------------------===//
// IdDeclInfo Implementation
//===----------------------------------------------------------------------===//
/// FindContext - Returns an iterator pointing just after the decl that is
/// in the given context or in a parent of it. The search is in reverse
/// order, from end to begin.
IdentifierResolver::IdDeclInfo::DeclsTy::iterator
IdentifierResolver::IdDeclInfo::FindContext(const LookupContext &Ctx,
const DeclsTy::iterator &Start) {
for (DeclsTy::iterator I = Start; I != Decls.begin(); --I) {
if (Ctx.isEqOrContainedBy(LookupContext(*(I-1))))
return I;
}
return Decls.begin();
}
/// AddShadowed - Add a decl by putting it directly above the 'Shadow' decl.
/// Later lookups will find the 'Shadow' decl first. The 'Shadow' decl must
/// be already added to the scope chain and must be in the same context as
/// the decl that we want to add.
void IdentifierResolver::IdDeclInfo::AddShadowed(NamedDecl *D,
NamedDecl *Shadow) {
assert(LookupContext(D) == LookupContext(Shadow) &&
"Decl and Shadow not in same context!");
for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
if (Shadow == *(I-1)) {
Decls.insert(I-1, D);
return;
}
}
assert(0 && "Shadow wasn't in scope chain!");
}
/// RemoveDecl - Remove the decl from the scope chain.
/// The decl must already be part of the decl chain.
void IdentifierResolver::IdDeclInfo::RemoveDecl(NamedDecl *D) {
for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
if (D == *(I-1)) {
Decls.erase(I-1);
return;
}
}
assert(0 && "Didn't find this decl on its identifier's chain!");
}
//===----------------------------------------------------------------------===//
// IdentifierResolver Implementation
//===----------------------------------------------------------------------===//
IdentifierResolver::IdentifierResolver(const LangOptions &langOpt)
: LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) {
}
Argyrios Kyrtzidis
committed
IdentifierResolver::~IdentifierResolver() {
Argyrios Kyrtzidis
committed
}
/// isDeclInScope - If 'Ctx' is a function/method, isDeclInScope returns true
/// if 'D' is in Scope 'S', otherwise 'S' is ignored and isDeclInScope returns
/// true if 'D' belongs to the given declaration context.
Argyrios Kyrtzidis
committed
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
Scope *S) const {
if (Ctx->isFunctionOrMethod()) {
if (S->isDeclScope(D))
return true;
if (LangOpt.CPlusPlus) {
// C++ 3.3.2p4:
// Names declared in the for-init-statement, and in the condition of if,
// while, for, and switch statements are local to the if, while, for, or
// switch statement (including the controlled statement), and shall not be
// redeclared in a subsequent condition of that statement nor in the
// outermost block (or, for the if statement, any of the outermost blocks)
// of the controlled statement.
//
assert(S->getParent() && "No TUScope?");
if (S->getParent()->getFlags() & Scope::ControlScope)
return S->getParent()->isDeclScope(D);
}
return false;
}
return LookupContext(D) == LookupContext(Ctx);
}
/// AddDecl - Link the decl to its shadowed decl chain.
void IdentifierResolver::AddDecl(NamedDecl *D) {
IdentifierInfo *II = D->getIdentifier();
void *Ptr = II->getFETokenInfo<void>();
if (!Ptr) {
II->setFETokenInfo(D);
return;
}
IdDeclInfo *IDI;
if (isDeclPtr(Ptr)) {
II->setFETokenInfo(NULL);
IDI = &(*IdDeclInfos)[II];
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
IDI->AddDecl(PrevD);
} else
IDI = toIdDeclInfo(Ptr);
/// AddShadowedDecl - Link the decl to its shadowed decl chain putting it
/// after the decl that the iterator points to, thus the 'Shadow' decl will be
/// encountered before the 'D' decl.
void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
assert(D->getIdentifier() == Shadow->getIdentifier() && "Different ids!");
assert(LookupContext(D) == LookupContext(Shadow) && "Different context!");
IdentifierInfo *II = D->getIdentifier();
void *Ptr = II->getFETokenInfo<void>();
assert(Ptr && "No decl from Ptr ?");
IdDeclInfo *IDI;
if (isDeclPtr(Ptr)) {
II->setFETokenInfo(NULL);
IDI = &(*IdDeclInfos)[II];
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
assert(PrevD == Shadow && "Invalid shadow decl ?");
IDI->AddDecl(D);
IDI->AddDecl(PrevD);
return;
}
IDI = toIdDeclInfo(Ptr);
IDI->AddShadowed(D, Shadow);
/// RemoveDecl - Unlink the decl from its shadowed decl chain.
/// The decl must already be part of the decl chain.
void IdentifierResolver::RemoveDecl(NamedDecl *D) {
assert(D && "null param passed");
IdentifierInfo *II = D->getIdentifier();
void *Ptr = II->getFETokenInfo<void>();
assert(Ptr && "Didn't find this decl on its identifier's chain!");
if (isDeclPtr(Ptr)) {
assert(D == Ptr && "Didn't find this decl on its identifier's chain!");
II->setFETokenInfo(NULL);
return;
}
return toIdDeclInfo(Ptr)->RemoveDecl(D);
Argyrios Kyrtzidis
committed
/// begin - Returns an iterator for decls of identifier 'II', starting at
/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
/// decls of parent declaration contexts too.
IdentifierResolver::iterator
Argyrios Kyrtzidis
committed
IdentifierResolver::begin(const IdentifierInfo *II, DeclContext *Ctx,
bool LookInParentCtx) {
assert(Ctx && "null param passed");
void *Ptr = II->getFETokenInfo<void>();
Argyrios Kyrtzidis
committed
if (!Ptr) return end();
LookupContext LC(Ctx);
if (isDeclPtr(Ptr)) {
NamedDecl *D = static_cast<NamedDecl*>(Ptr);
Argyrios Kyrtzidis
committed
LookupContext DC(D);
Argyrios Kyrtzidis
committed
if (( LookInParentCtx && LC.isEqOrContainedBy(DC)) ||
(!LookInParentCtx && LC == DC))
return iterator(D);
else
Argyrios Kyrtzidis
committed
return end();
Argyrios Kyrtzidis
committed
IdDeclInfo *IDI = toIdDeclInfo(Ptr);
Argyrios Kyrtzidis
committed
IdDeclInfo::DeclsTy::iterator I;
if (LookInParentCtx)
I = IDI->FindContext(LC);
else {
for (I = IDI->decls_end(); I != IDI->decls_begin(); --I)
if (LookupContext(*(I-1)) == LC)
break;
}
Argyrios Kyrtzidis
committed
if (I != IDI->decls_begin())
return iterator(I-1, LookInParentCtx);
else // No decls found.
return end();
}
Argyrios Kyrtzidis
committed
/// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter.
void IdentifierResolver::iterator::PreIncIter() {
NamedDecl *D = **this;
LookupContext Ctx(D);
void *InfoPtr = D->getIdentifier()->getFETokenInfo<void>();
assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
BaseIter I = getIterator();
if (LookInParentCtx())
I = Info->FindContext(Ctx, I);
else {
if (I != Info->decls_begin() && LookupContext(*(I-1)) != Ctx) {
// The next decl is in different declaration context.
// Skip remaining decls and set the iterator to the end.
I = Info->decls_begin();
}
Argyrios Kyrtzidis
committed
if (I != Info->decls_begin())
*this = iterator(I-1, LookInParentCtx());
else // No more decls.
*this = end();
//===----------------------------------------------------------------------===//
// IdDeclInfoMap Implementation
//===----------------------------------------------------------------------===//
/// Returns the IdDeclInfo associated to the IdentifierInfo.
/// It creates a new IdDeclInfo if one was not created before for this id.
IdentifierResolver::IdDeclInfo &
IdentifierResolver::IdDeclInfoMap::operator[](IdentifierInfo *II) {
assert (II && "null IdentifierInfo passed");
void *Ptr = II->getFETokenInfo<void>();
if (Ptr) return *toIdDeclInfo(Ptr);
if (CurIndex == VECTOR_SIZE) {
// Add a IdDeclInfo vector 'pool'
IDIVecs.push_back(std::vector<IdDeclInfo>());
// Fill the vector
IDIVecs.back().resize(VECTOR_SIZE);
CurIndex = 0;
}
II->setFETokenInfo(reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(IDI) | 0x1)
);
++CurIndex;
return *IDI;
}