IdentifierResolver.cpp [plain text]
#include "clang/Sema/IdentifierResolver.h"
#include "clang/Sema/Scope.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Lex/ExternalPreprocessorSource.h"
#include "clang/Lex/Preprocessor.h"
using namespace clang;
class IdentifierResolver::IdDeclInfoMap {
static const unsigned int POOL_SIZE = 512;
struct IdDeclInfoPool {
IdDeclInfoPool(IdDeclInfoPool *Next) : Next(Next) {}
IdDeclInfoPool *Next;
IdDeclInfo Pool[POOL_SIZE];
};
IdDeclInfoPool *CurPool;
unsigned int CurIndex;
public:
IdDeclInfoMap() : CurPool(0), CurIndex(POOL_SIZE) {}
~IdDeclInfoMap() {
IdDeclInfoPool *Cur = CurPool;
while (IdDeclInfoPool *P = Cur) {
Cur = Cur->Next;
delete P;
}
}
IdDeclInfo &operator[](DeclarationName Name);
};
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;
}
}
llvm_unreachable("Didn't find this decl on its identifier's chain!");
}
bool
IdentifierResolver::IdDeclInfo::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
for (DeclsTy::iterator I = Decls.end(); I != Decls.begin(); --I) {
if (Old == *(I-1)) {
*(I - 1) = New;
return true;
}
}
return false;
}
IdentifierResolver::IdentifierResolver(Preprocessor &PP)
: LangOpt(PP.getLangOpts()), PP(PP),
IdDeclInfos(new IdDeclInfoMap) {
}
IdentifierResolver::~IdentifierResolver() {
delete IdDeclInfos;
}
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
ASTContext &Context, Scope *S,
bool ExplicitInstantiationOrSpecialization) const {
Ctx = Ctx->getRedeclContext();
if (Ctx->isFunctionOrMethod() || S->isFunctionPrototypeScope()) {
while (S->getEntity() &&
((DeclContext *)S->getEntity())->isTransparentContext())
S = S->getParent();
if (S->isDeclScope(D))
return true;
if (LangOpt.CPlusPlus) {
assert(S->getParent() && "No TUScope?");
if (S->getParent()->getFlags() & Scope::ControlScope)
return S->getParent()->isDeclScope(D);
}
return false;
}
DeclContext *DCtx = D->getDeclContext()->getRedeclContext();
return ExplicitInstantiationOrSpecialization
? Ctx->InEnclosingNamespaceSetOf(DCtx)
: Ctx->Equals(DCtx);
}
void IdentifierResolver::AddDecl(NamedDecl *D) {
DeclarationName Name = D->getDeclName();
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
updatingIdentifier(*II);
void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr) {
Name.setFETokenInfo(D);
return;
}
IdDeclInfo *IDI;
if (isDeclPtr(Ptr)) {
Name.setFETokenInfo(NULL);
IDI = &(*IdDeclInfos)[Name];
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
IDI->AddDecl(PrevD);
} else
IDI = toIdDeclInfo(Ptr);
IDI->AddDecl(D);
}
void IdentifierResolver::InsertDeclAfter(iterator Pos, NamedDecl *D) {
DeclarationName Name = D->getDeclName();
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
updatingIdentifier(*II);
void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr) {
AddDecl(D);
return;
}
if (isDeclPtr(Ptr)) {
if (Pos == iterator()) {
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
RemoveDecl(PrevD);
AddDecl(D);
AddDecl(PrevD);
} else {
AddDecl(D);
}
return;
}
IdDeclInfo *IDI = toIdDeclInfo(Ptr);
if (Pos.isIterator()) {
IDI->InsertDecl(Pos.getIterator() + 1, D);
} else
IDI->InsertDecl(IDI->decls_begin(), D);
}
void IdentifierResolver::RemoveDecl(NamedDecl *D) {
assert(D && "null param passed");
DeclarationName Name = D->getDeclName();
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
updatingIdentifier(*II);
void *Ptr = Name.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!");
Name.setFETokenInfo(NULL);
return;
}
return toIdDeclInfo(Ptr)->RemoveDecl(D);
}
bool IdentifierResolver::ReplaceDecl(NamedDecl *Old, NamedDecl *New) {
assert(Old->getDeclName() == New->getDeclName() &&
"Cannot replace a decl with another decl of a different name");
DeclarationName Name = Old->getDeclName();
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
updatingIdentifier(*II);
void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr)
return false;
if (isDeclPtr(Ptr)) {
if (Ptr == Old) {
Name.setFETokenInfo(New);
return true;
}
return false;
}
return toIdDeclInfo(Ptr)->ReplaceDecl(Old, New);
}
IdentifierResolver::iterator
IdentifierResolver::begin(DeclarationName Name) {
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
readingIdentifier(*II);
void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr) return end();
if (isDeclPtr(Ptr))
return iterator(static_cast<NamedDecl*>(Ptr));
IdDeclInfo *IDI = toIdDeclInfo(Ptr);
IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
if (I != IDI->decls_begin())
return iterator(I-1);
return end();
}
namespace {
enum DeclMatchKind {
DMK_Different,
DMK_Replace,
DMK_Ignore
};
}
static DeclMatchKind compareDeclarations(NamedDecl *Existing, NamedDecl *New) {
if (Existing == New)
return DMK_Ignore;
if (Existing->getKind() != New->getKind())
return DMK_Different;
if (Existing->getCanonicalDecl() == New->getCanonicalDecl()) {
for (Decl::redecl_iterator RD = New->redecls_begin(),
RDEnd = New->redecls_end();
RD != RDEnd; ++RD) {
if (*RD == Existing)
return DMK_Replace;
if (RD->isCanonicalDecl())
break;
}
return DMK_Ignore;
}
return DMK_Different;
}
bool IdentifierResolver::tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name){
if (IdentifierInfo *II = Name.getAsIdentifierInfo())
readingIdentifier(*II);
void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr) {
Name.setFETokenInfo(D);
return true;
}
IdDeclInfo *IDI;
if (isDeclPtr(Ptr)) {
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
switch (compareDeclarations(PrevD, D)) {
case DMK_Different:
break;
case DMK_Ignore:
return false;
case DMK_Replace:
Name.setFETokenInfo(D);
return true;
}
Name.setFETokenInfo(NULL);
IDI = &(*IdDeclInfos)[Name];
if (!PrevD->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
IDI->AddDecl(D);
IDI->AddDecl(PrevD);
} else {
IDI->AddDecl(PrevD);
IDI->AddDecl(D);
}
return true;
}
IDI = toIdDeclInfo(Ptr);
for (IdDeclInfo::DeclsTy::iterator I = IDI->decls_begin(),
IEnd = IDI->decls_end();
I != IEnd; ++I) {
switch (compareDeclarations(*I, D)) {
case DMK_Different:
break;
case DMK_Ignore:
return false;
case DMK_Replace:
*I = D;
return true;
}
if (!(*I)->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
IDI->InsertDecl(I, D);
return true;
}
}
IDI->AddDecl(D);
return true;
}
void IdentifierResolver::readingIdentifier(IdentifierInfo &II) {
if (II.isOutOfDate())
PP.getExternalSource()->updateOutOfDateIdentifier(II);
}
void IdentifierResolver::updatingIdentifier(IdentifierInfo &II) {
if (II.isOutOfDate())
PP.getExternalSource()->updateOutOfDateIdentifier(II);
if (II.isFromAST())
II.setChangedSinceDeserialization();
}
IdentifierResolver::IdDeclInfo &
IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
void *Ptr = Name.getFETokenInfo<void>();
if (Ptr) return *toIdDeclInfo(Ptr);
if (CurIndex == POOL_SIZE) {
CurPool = new IdDeclInfoPool(CurPool);
CurIndex = 0;
}
IdDeclInfo *IDI = &CurPool->Pool[CurIndex];
Name.setFETokenInfo(reinterpret_cast<void*>(
reinterpret_cast<uintptr_t>(IDI) | 0x1)
);
++CurIndex;
return *IDI;
}
void IdentifierResolver::iterator::incrementSlowCase() {
NamedDecl *D = **this;
void *InfoPtr = D->getDeclName().getFETokenInfo<void>();
assert(!isDeclPtr(InfoPtr) && "Decl with wrong id ?");
IdDeclInfo *Info = toIdDeclInfo(InfoPtr);
BaseIter I = getIterator();
if (I != Info->decls_begin())
*this = iterator(I-1);
else *this = iterator();
}