2008-04-11 11:06:57 +04:00
|
|
|
//===- 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.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
2008-04-12 05:50:47 +04:00
|
|
|
// This file implements the IdentifierResolver class, which is used for lexical
|
2008-11-17 23:34:05 +03:00
|
|
|
// scoped lookup, based on declaration names.
|
2008-04-11 11:06:57 +04:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "IdentifierResolver.h"
|
2008-09-10 01:57:58 +04:00
|
|
|
#include "clang/Basic/LangOptions.h"
|
2008-04-11 11:06:57 +04:00
|
|
|
#include <list>
|
2008-04-12 05:50:47 +04:00
|
|
|
#include <vector>
|
2008-04-11 11:06:57 +04:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2008-09-09 23:28:27 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// IdDeclInfoMap class
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-04-11 11:06:57 +04:00
|
|
|
|
2008-11-17 23:34:05 +03:00
|
|
|
/// IdDeclInfoMap - Associates IdDeclInfos with declaration names.
|
2008-04-12 05:50:47 +04:00
|
|
|
/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
|
2008-04-11 11:06:57 +04:00
|
|
|
/// individual IdDeclInfo to heap.
|
2008-05-10 03:39:43 +04:00
|
|
|
class IdentifierResolver::IdDeclInfoMap {
|
2008-04-12 05:50:47 +04:00
|
|
|
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;
|
2008-04-11 11:06:57 +04:00
|
|
|
unsigned int CurIndex;
|
|
|
|
|
|
|
|
public:
|
2008-04-12 05:50:47 +04:00
|
|
|
IdDeclInfoMap() : CurIndex(VECTOR_SIZE) {}
|
2008-04-11 11:06:57 +04:00
|
|
|
|
2008-11-17 23:34:05 +03:00
|
|
|
/// Returns the IdDeclInfo associated to the DeclarationName.
|
2008-04-11 11:06:57 +04:00
|
|
|
/// It creates a new IdDeclInfo if one was not created before for this id.
|
2008-11-17 23:34:05 +03:00
|
|
|
IdDeclInfo &operator[](DeclarationName Name);
|
2008-04-11 11:06:57 +04:00
|
|
|
};
|
|
|
|
|
2008-04-14 04:09:21 +04:00
|
|
|
|
2008-09-09 23:28:27 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// IdDeclInfo Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// 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) {
|
|
|
|
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!");
|
|
|
|
}
|
|
|
|
|
2009-03-02 03:19:53 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-09-09 23:28:27 +04:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// IdentifierResolver Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-09-10 01:32:02 +04:00
|
|
|
IdentifierResolver::IdentifierResolver(const LangOptions &langOpt)
|
|
|
|
: LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) {
|
|
|
|
}
|
2008-04-14 04:09:21 +04:00
|
|
|
IdentifierResolver::~IdentifierResolver() {
|
2008-05-10 03:39:43 +04:00
|
|
|
delete IdDeclInfos;
|
2008-04-14 04:09:21 +04:00
|
|
|
}
|
2008-04-11 11:06:57 +04:00
|
|
|
|
2008-09-09 23:28:27 +04:00
|
|
|
/// 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.
|
2008-09-10 01:57:58 +04:00
|
|
|
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
|
2008-12-11 19:49:14 +03:00
|
|
|
ASTContext &Context, Scope *S) const {
|
2009-01-07 02:51:29 +03:00
|
|
|
Ctx = Ctx->getLookupContext();
|
2009-01-05 22:45:36 +03:00
|
|
|
|
2008-09-10 01:57:58 +04:00
|
|
|
if (Ctx->isFunctionOrMethod()) {
|
2009-01-05 22:45:36 +03:00
|
|
|
// Ignore the scopes associated within transparent declaration contexts.
|
|
|
|
while (S->getEntity() &&
|
|
|
|
((DeclContext *)S->getEntity())->isTransparentContext())
|
|
|
|
S = S->getParent();
|
|
|
|
|
2009-03-28 22:18:32 +03:00
|
|
|
if (S->isDeclScope(Action::DeclPtrTy::make(D)))
|
2008-09-10 01:57:58 +04:00
|
|
|
return true;
|
|
|
|
if (LangOpt.CPlusPlus) {
|
2008-12-21 19:41:36 +03:00
|
|
|
// C++ 3.3.2p3:
|
|
|
|
// The name declared in a catch exception-declaration is local to the
|
|
|
|
// handler and shall not be redeclared in the outermost block of the
|
|
|
|
// handler.
|
2008-09-10 01:57:58 +04:00
|
|
|
// 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)
|
2009-03-28 22:18:32 +03:00
|
|
|
return S->getParent()->isDeclScope(Action::DeclPtrTy::make(D));
|
2008-09-10 01:57:58 +04:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2008-09-09 23:28:27 +04:00
|
|
|
|
2009-08-26 22:54:58 +04:00
|
|
|
return D->getDeclContext()->getLookupContext()->getPrimaryContext() ==
|
|
|
|
Ctx->getPrimaryContext();
|
2008-09-09 23:28:27 +04:00
|
|
|
}
|
|
|
|
|
2008-04-12 05:50:47 +04:00
|
|
|
/// AddDecl - Link the decl to its shadowed decl chain.
|
2008-05-10 03:39:43 +04:00
|
|
|
void IdentifierResolver::AddDecl(NamedDecl *D) {
|
2008-11-17 23:34:05 +03:00
|
|
|
DeclarationName Name = D->getDeclName();
|
|
|
|
void *Ptr = Name.getFETokenInfo<void>();
|
2008-04-11 11:06:57 +04:00
|
|
|
|
|
|
|
if (!Ptr) {
|
2008-11-17 23:34:05 +03:00
|
|
|
Name.setFETokenInfo(D);
|
2008-04-11 11:06:57 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
IdDeclInfo *IDI;
|
|
|
|
|
|
|
|
if (isDeclPtr(Ptr)) {
|
2008-11-17 23:34:05 +03:00
|
|
|
Name.setFETokenInfo(NULL);
|
|
|
|
IDI = &(*IdDeclInfos)[Name];
|
2008-05-10 03:39:43 +04:00
|
|
|
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
|
|
|
|
IDI->AddDecl(PrevD);
|
2008-04-11 11:06:57 +04:00
|
|
|
} else
|
|
|
|
IDI = toIdDeclInfo(Ptr);
|
|
|
|
|
2008-05-10 03:39:43 +04:00
|
|
|
IDI->AddDecl(D);
|
2008-04-11 11:06:57 +04:00
|
|
|
}
|
|
|
|
|
2008-05-10 03:39:43 +04:00
|
|
|
/// AddShadowedDecl - Link the decl to its shadowed decl chain putting it
|
2008-05-15 21:26:35 +04:00
|
|
|
/// after the decl that the iterator points to, thus the 'Shadow' decl will be
|
2008-05-10 03:39:43 +04:00
|
|
|
/// encountered before the 'D' decl.
|
|
|
|
void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
|
2008-11-17 23:34:05 +03:00
|
|
|
assert(D->getDeclName() == Shadow->getDeclName() && "Different ids!");
|
2008-05-10 03:39:43 +04:00
|
|
|
|
2008-11-17 23:34:05 +03:00
|
|
|
DeclarationName Name = D->getDeclName();
|
|
|
|
void *Ptr = Name.getFETokenInfo<void>();
|
2008-05-10 03:39:43 +04:00
|
|
|
assert(Ptr && "No decl from Ptr ?");
|
2008-04-11 11:06:57 +04:00
|
|
|
|
|
|
|
IdDeclInfo *IDI;
|
|
|
|
|
|
|
|
if (isDeclPtr(Ptr)) {
|
2008-11-17 23:34:05 +03:00
|
|
|
Name.setFETokenInfo(NULL);
|
|
|
|
IDI = &(*IdDeclInfos)[Name];
|
2008-05-10 03:39:43 +04:00
|
|
|
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
|
|
|
|
assert(PrevD == Shadow && "Invalid shadow decl ?");
|
|
|
|
IDI->AddDecl(D);
|
|
|
|
IDI->AddDecl(PrevD);
|
|
|
|
return;
|
|
|
|
}
|
2008-04-11 11:06:57 +04:00
|
|
|
|
2008-05-10 03:39:43 +04:00
|
|
|
IDI = toIdDeclInfo(Ptr);
|
|
|
|
IDI->AddShadowed(D, Shadow);
|
2008-04-11 11:06:57 +04:00
|
|
|
}
|
|
|
|
|
2008-04-12 05:50:47 +04:00
|
|
|
/// RemoveDecl - Unlink the decl from its shadowed decl chain.
|
2008-04-11 11:06:57 +04:00
|
|
|
/// The decl must already be part of the decl chain.
|
|
|
|
void IdentifierResolver::RemoveDecl(NamedDecl *D) {
|
|
|
|
assert(D && "null param passed");
|
2008-11-17 23:34:05 +03:00
|
|
|
DeclarationName Name = D->getDeclName();
|
|
|
|
void *Ptr = Name.getFETokenInfo<void>();
|
2008-04-11 11:06:57 +04:00
|
|
|
|
|
|
|
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!");
|
2008-11-17 23:34:05 +03:00
|
|
|
Name.setFETokenInfo(NULL);
|
2008-04-11 11:06:57 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-05-10 03:39:43 +04:00
|
|
|
return toIdDeclInfo(Ptr)->RemoveDecl(D);
|
2008-04-11 11:06:57 +04:00
|
|
|
}
|
|
|
|
|
2009-03-02 03:19:53 +03:00
|
|
|
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();
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63354 91177308-0d34-0410-b5e6-96231b3b80d8
2009-01-30 04:04:22 +03:00
|
|
|
/// begin - Returns an iterator for decls with name 'Name'.
|
2008-05-10 03:39:43 +04:00
|
|
|
IdentifierResolver::iterator
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63354 91177308-0d34-0410-b5e6-96231b3b80d8
2009-01-30 04:04:22 +03:00
|
|
|
IdentifierResolver::begin(DeclarationName Name) {
|
2008-11-17 23:34:05 +03:00
|
|
|
void *Ptr = Name.getFETokenInfo<void>();
|
2008-07-17 21:49:50 +04:00
|
|
|
if (!Ptr) return end();
|
2008-04-11 11:06:57 +04:00
|
|
|
|
2009-03-04 09:34:08 +03:00
|
|
|
if (isDeclPtr(Ptr))
|
|
|
|
return iterator(static_cast<NamedDecl*>(Ptr));
|
2008-04-11 11:06:57 +04:00
|
|
|
|
2008-07-17 21:49:50 +04:00
|
|
|
IdDeclInfo *IDI = toIdDeclInfo(Ptr);
|
2008-05-10 03:39:43 +04:00
|
|
|
|
2009-01-05 22:45:36 +03:00
|
|
|
IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
|
2008-07-17 21:49:50 +04:00
|
|
|
if (I != IDI->decls_begin())
|
Eliminated LookupCriteria, whose creation was causing a bottleneck for
LookupName et al. Instead, use an enum and a bool to describe its
contents.
Optimized the C/Objective-C path through LookupName, eliminating any
unnecessarily C++isms. Simplify IdentifierResolver::iterator, removing
some code and arguments that are no longer used.
Eliminated LookupDeclInScope/LookupDeclInContext, moving all callers
over to LookupName, LookupQualifiedName, or LookupParsedName, as
appropriate.
All together, I'm seeing a 0.2% speedup on Cocoa.h with PTH and
-disable-free. Plus, we're down to three name-lookup routines.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63354 91177308-0d34-0410-b5e6-96231b3b80d8
2009-01-30 04:04:22 +03:00
|
|
|
return iterator(I-1);
|
2009-03-04 09:34:08 +03:00
|
|
|
// No decls found.
|
|
|
|
return end();
|
2008-07-17 21:49:50 +04:00
|
|
|
}
|
2008-04-11 11:06:57 +04:00
|
|
|
|
Lazy deserialization of the declaration chains associated with
identifiers from a precompiled header.
This patch changes the primary name lookup method for entities within
a precompiled header. Previously, we would load all of the names of
declarations at translation unit scope into a large DenseMap (inside
the TranslationUnitDecl's DeclContext), and then perform a special
"last resort" lookup into this DeclContext when we knew there was a
PCH file (see Sema::LookupName). Now, when we see an identifier named
for the first time, we load all of the declarations with that name
that are visible from the translation unit into the IdentifierInfo's
chain of declarations. Thus, the explicit "look into the translation
unit's DeclContext" code is gone, and Sema effectively uses the same
IdentifierInfo-based name lookup mechanism whether we are using a PCH
file or not.
This approach should help PCH scale with the size of the input program
rather than the size of the PCH file. The "Hello, World!" application
with Carbon.h as a PCH file now loads 20% of the identifiers in the
PCH file rather than 85% of the identifiers.
90% of the 20% of identifiers loaded are actually loaded when we
deserialize the preprocessor state. The next step is to make the
preprocessor load macros lazily, which should drastically reduce the
number of types, declarations, and identifiers loaded for "Hello,
World".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69737 91177308-0d34-0410-b5e6-96231b3b80d8
2009-04-22 02:25:48 +04:00
|
|
|
void IdentifierResolver::AddDeclToIdentifierChain(IdentifierInfo *II,
|
|
|
|
NamedDecl *D) {
|
|
|
|
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);
|
|
|
|
|
|
|
|
IDI->AddDecl(D);
|
|
|
|
}
|
|
|
|
|
2008-09-09 23:28:27 +04:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// IdDeclInfoMap Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-11-17 23:34:05 +03:00
|
|
|
/// Returns the IdDeclInfo associated to the DeclarationName.
|
2008-04-11 11:06:57 +04:00
|
|
|
/// It creates a new IdDeclInfo if one was not created before for this id.
|
2008-05-10 03:39:43 +04:00
|
|
|
IdentifierResolver::IdDeclInfo &
|
2008-11-17 23:34:05 +03:00
|
|
|
IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
|
|
|
|
void *Ptr = Name.getFETokenInfo<void>();
|
2008-04-11 11:06:57 +04:00
|
|
|
|
2008-05-10 03:39:43 +04:00
|
|
|
if (Ptr) return *toIdDeclInfo(Ptr);
|
2008-04-11 11:06:57 +04:00
|
|
|
|
2008-04-12 05:50:47 +04:00
|
|
|
if (CurIndex == VECTOR_SIZE) {
|
|
|
|
// Add a IdDeclInfo vector 'pool'
|
2008-04-12 16:38:58 +04:00
|
|
|
IDIVecs.push_back(std::vector<IdDeclInfo>());
|
2008-04-12 05:50:47 +04:00
|
|
|
// Fill the vector
|
|
|
|
IDIVecs.back().resize(VECTOR_SIZE);
|
2008-04-11 11:06:57 +04:00
|
|
|
CurIndex = 0;
|
|
|
|
}
|
2008-04-12 05:50:47 +04:00
|
|
|
IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
|
2008-11-17 23:34:05 +03:00
|
|
|
Name.setFETokenInfo(reinterpret_cast<void*>(
|
2008-04-11 11:06:57 +04:00
|
|
|
reinterpret_cast<uintptr_t>(IDI) | 0x1)
|
|
|
|
);
|
|
|
|
++CurIndex;
|
|
|
|
return *IDI;
|
|
|
|
}
|