2008-04-11 07:06:57 +00: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 01:50:47 +00:00
|
|
|
// This file implements the IdentifierResolver class, which is used for lexical
|
2008-11-17 20:34:05 +00:00
|
|
|
// scoped lookup, based on declaration names.
|
2008-04-11 07:06:57 +00:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "IdentifierResolver.h"
|
2008-09-09 21:57:58 +00:00
|
|
|
#include "clang/Basic/LangOptions.h"
|
2008-04-11 07:06:57 +00:00
|
|
|
#include <list>
|
2008-04-12 01:50:47 +00:00
|
|
|
#include <vector>
|
2008-04-11 07:06:57 +00:00
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2008-09-09 19:28:27 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// IdDeclInfoMap class
|
|
|
|
//===----------------------------------------------------------------------===//
|
2008-04-11 07:06:57 +00:00
|
|
|
|
2008-11-17 20:34:05 +00:00
|
|
|
/// IdDeclInfoMap - Associates IdDeclInfos with declaration names.
|
2008-04-12 01:50:47 +00:00
|
|
|
/// Allocates 'pools' (vectors of IdDeclInfos) to avoid allocating each
|
2008-04-11 07:06:57 +00:00
|
|
|
/// individual IdDeclInfo to heap.
|
2008-05-09 23:39:43 +00:00
|
|
|
class IdentifierResolver::IdDeclInfoMap {
|
2008-04-12 01:50:47 +00: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 07:06:57 +00:00
|
|
|
unsigned int CurIndex;
|
|
|
|
|
|
|
|
public:
|
2008-04-12 01:50:47 +00:00
|
|
|
IdDeclInfoMap() : CurIndex(VECTOR_SIZE) {}
|
2008-04-11 07:06:57 +00:00
|
|
|
|
2008-11-17 20:34:05 +00:00
|
|
|
/// Returns the IdDeclInfo associated to the DeclarationName.
|
2008-04-11 07:06:57 +00:00
|
|
|
/// It creates a new IdDeclInfo if one was not created before for this id.
|
2008-11-17 20:34:05 +00:00
|
|
|
IdDeclInfo &operator[](DeclarationName Name);
|
2008-04-11 07:06:57 +00:00
|
|
|
};
|
|
|
|
|
2008-04-14 00:09:21 +00:00
|
|
|
|
2008-09-09 19:28:27 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// LookupContext Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-01-20 01:17:11 +00:00
|
|
|
/// getContext - Returns translation unit context for non Decls and
|
2008-09-09 19:28:27 +00:00
|
|
|
/// for EnumConstantDecls returns the parent context of their EnumDecl.
|
|
|
|
DeclContext *IdentifierResolver::LookupContext::getContext(Decl *D) {
|
2009-01-20 01:17:11 +00:00
|
|
|
DeclContext *Ctx = D->getDeclContext();
|
2008-09-09 19:28:27 +00:00
|
|
|
|
Unify the code for defining tags in C and C++, so that we always
introduce a Scope for the body of a tag. This reduces the number of
semantic differences between C and C++ structs and unions, and will
help with other features (e.g., anonymous unions) in C. Some important
points:
- Fields are now in the "member" namespace (IDNS_Member), to keep
them separate from tags and ordinary names in C. See the new test
in Sema/member-reference.c for an example of why this matters. In
C++, ordinary and member name lookup will find members in both the
ordinary and member namespace, so the difference between
IDNS_Member and IDNS_Ordinary is erased by Sema::LookupDecl (but
only in C++!).
- We always introduce a Scope and push a DeclContext when we're
defining a tag, in both C and C++. Previously, we had different
actions and different Scope/CurContext behavior for enums, C
structs/unions, and C++ structs/unions/classes. Now, it's one pair
of actions. (Yay!)
There's still some fuzziness in the handling of struct/union/enum
definitions within other struct/union/enum definitions in C. We'll
need to do some more cleanup to eliminate some reliance on CurContext
before we can solve this issue for real. What we want is for something
like this:
struct X {
struct T { int x; } t;
};
to introduce T into translation unit scope (placing it at the
appropriate point in the IdentifierResolver chain, too), but it should
still have struct X as its lexical declaration
context. PushOnScopeChains isn't smart enough to do that yet, though,
so there's a FIXME test in nested-redef.c
llvm-svn: 61940
2009-01-08 20:45:30 +00:00
|
|
|
if (!Ctx) // FIXME: HACK! We shouldn't end up with a NULL context here.
|
|
|
|
return TUCtx();
|
|
|
|
|
2009-01-06 23:51:29 +00:00
|
|
|
Ctx = Ctx->getLookupContext();
|
2009-01-05 19:45:36 +00:00
|
|
|
|
2008-09-09 19:28:27 +00:00
|
|
|
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
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// 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!");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// IdentifierResolver Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-09-09 21:32:02 +00:00
|
|
|
IdentifierResolver::IdentifierResolver(const LangOptions &langOpt)
|
|
|
|
: LangOpt(langOpt), IdDeclInfos(new IdDeclInfoMap) {
|
|
|
|
}
|
2008-04-14 00:09:21 +00:00
|
|
|
IdentifierResolver::~IdentifierResolver() {
|
2008-05-09 23:39:43 +00:00
|
|
|
delete IdDeclInfos;
|
2008-04-14 00:09:21 +00:00
|
|
|
}
|
2008-04-11 07:06:57 +00:00
|
|
|
|
2008-09-09 19:28:27 +00: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-09 21:57:58 +00:00
|
|
|
bool IdentifierResolver::isDeclInScope(Decl *D, DeclContext *Ctx,
|
2008-12-11 16:49:14 +00:00
|
|
|
ASTContext &Context, Scope *S) const {
|
2009-01-06 23:51:29 +00:00
|
|
|
Ctx = Ctx->getLookupContext();
|
2009-01-05 19:45:36 +00:00
|
|
|
|
2008-09-09 21:57:58 +00:00
|
|
|
if (Ctx->isFunctionOrMethod()) {
|
2009-01-05 19:45:36 +00:00
|
|
|
// Ignore the scopes associated within transparent declaration contexts.
|
|
|
|
while (S->getEntity() &&
|
|
|
|
((DeclContext *)S->getEntity())->isTransparentContext())
|
|
|
|
S = S->getParent();
|
|
|
|
|
2008-09-09 21:57:58 +00:00
|
|
|
if (S->isDeclScope(D))
|
|
|
|
return true;
|
|
|
|
if (LangOpt.CPlusPlus) {
|
2008-12-21 16:41:36 +00: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-09 21:57:58 +00: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)
|
|
|
|
return S->getParent()->isDeclScope(D);
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2008-09-09 19:28:27 +00:00
|
|
|
|
2009-01-08 17:28:14 +00:00
|
|
|
return LookupContext(D) == LookupContext(Ctx->getPrimaryContext());
|
2008-09-09 19:28:27 +00:00
|
|
|
}
|
|
|
|
|
2008-04-12 01:50:47 +00:00
|
|
|
/// AddDecl - Link the decl to its shadowed decl chain.
|
2008-05-09 23:39:43 +00:00
|
|
|
void IdentifierResolver::AddDecl(NamedDecl *D) {
|
2008-11-17 20:34:05 +00:00
|
|
|
DeclarationName Name = D->getDeclName();
|
|
|
|
void *Ptr = Name.getFETokenInfo<void>();
|
2008-04-11 07:06:57 +00:00
|
|
|
|
|
|
|
if (!Ptr) {
|
2008-11-17 20:34:05 +00:00
|
|
|
Name.setFETokenInfo(D);
|
2008-04-11 07:06:57 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
IdDeclInfo *IDI;
|
|
|
|
|
|
|
|
if (isDeclPtr(Ptr)) {
|
2008-11-17 20:34:05 +00:00
|
|
|
Name.setFETokenInfo(NULL);
|
|
|
|
IDI = &(*IdDeclInfos)[Name];
|
2008-05-09 23:39:43 +00:00
|
|
|
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
|
|
|
|
IDI->AddDecl(PrevD);
|
2008-04-11 07:06:57 +00:00
|
|
|
} else
|
|
|
|
IDI = toIdDeclInfo(Ptr);
|
|
|
|
|
2008-05-09 23:39:43 +00:00
|
|
|
IDI->AddDecl(D);
|
2008-04-11 07:06:57 +00:00
|
|
|
}
|
|
|
|
|
2008-05-09 23:39:43 +00:00
|
|
|
/// AddShadowedDecl - Link the decl to its shadowed decl chain putting it
|
2008-05-15 17:26:35 +00:00
|
|
|
/// after the decl that the iterator points to, thus the 'Shadow' decl will be
|
2008-05-09 23:39:43 +00:00
|
|
|
/// encountered before the 'D' decl.
|
|
|
|
void IdentifierResolver::AddShadowedDecl(NamedDecl *D, NamedDecl *Shadow) {
|
2008-11-17 20:34:05 +00:00
|
|
|
assert(D->getDeclName() == Shadow->getDeclName() && "Different ids!");
|
2008-05-09 23:39:43 +00:00
|
|
|
|
2008-11-17 20:34:05 +00:00
|
|
|
DeclarationName Name = D->getDeclName();
|
|
|
|
void *Ptr = Name.getFETokenInfo<void>();
|
2008-05-09 23:39:43 +00:00
|
|
|
assert(Ptr && "No decl from Ptr ?");
|
2008-04-11 07:06:57 +00:00
|
|
|
|
|
|
|
IdDeclInfo *IDI;
|
|
|
|
|
|
|
|
if (isDeclPtr(Ptr)) {
|
2008-11-17 20:34:05 +00:00
|
|
|
Name.setFETokenInfo(NULL);
|
|
|
|
IDI = &(*IdDeclInfos)[Name];
|
2008-05-09 23:39:43 +00:00
|
|
|
NamedDecl *PrevD = static_cast<NamedDecl*>(Ptr);
|
|
|
|
assert(PrevD == Shadow && "Invalid shadow decl ?");
|
|
|
|
IDI->AddDecl(D);
|
|
|
|
IDI->AddDecl(PrevD);
|
|
|
|
return;
|
|
|
|
}
|
2008-04-11 07:06:57 +00:00
|
|
|
|
2008-05-09 23:39:43 +00:00
|
|
|
IDI = toIdDeclInfo(Ptr);
|
|
|
|
IDI->AddShadowed(D, Shadow);
|
2008-04-11 07:06:57 +00:00
|
|
|
}
|
|
|
|
|
2008-04-12 01:50:47 +00:00
|
|
|
/// RemoveDecl - Unlink the decl from its shadowed decl chain.
|
2008-04-11 07:06:57 +00:00
|
|
|
/// The decl must already be part of the decl chain.
|
|
|
|
void IdentifierResolver::RemoveDecl(NamedDecl *D) {
|
|
|
|
assert(D && "null param passed");
|
2008-11-17 20:34:05 +00:00
|
|
|
DeclarationName Name = D->getDeclName();
|
|
|
|
void *Ptr = Name.getFETokenInfo<void>();
|
2008-04-11 07:06:57 +00: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 20:34:05 +00:00
|
|
|
Name.setFETokenInfo(NULL);
|
2008-04-11 07:06:57 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2008-05-09 23:39:43 +00:00
|
|
|
return toIdDeclInfo(Ptr)->RemoveDecl(D);
|
2008-04-11 07:06:57 +00:00
|
|
|
}
|
|
|
|
|
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.
llvm-svn: 63354
2009-01-30 01:04:22 +00:00
|
|
|
/// begin - Returns an iterator for decls with name 'Name'.
|
2008-05-09 23:39:43 +00: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.
llvm-svn: 63354
2009-01-30 01:04:22 +00:00
|
|
|
IdentifierResolver::begin(DeclarationName Name) {
|
2008-11-17 20:34:05 +00:00
|
|
|
void *Ptr = Name.getFETokenInfo<void>();
|
2008-07-17 17:49:50 +00:00
|
|
|
if (!Ptr) return end();
|
2008-04-11 07:06:57 +00:00
|
|
|
|
|
|
|
if (isDeclPtr(Ptr)) {
|
|
|
|
NamedDecl *D = static_cast<NamedDecl*>(Ptr);
|
2009-01-05 19:45:36 +00:00
|
|
|
return iterator(D);
|
2008-04-11 07:06:57 +00:00
|
|
|
}
|
|
|
|
|
2008-07-17 17:49:50 +00:00
|
|
|
IdDeclInfo *IDI = toIdDeclInfo(Ptr);
|
2008-05-09 23:39:43 +00:00
|
|
|
|
2009-01-05 19:45:36 +00:00
|
|
|
IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
|
2008-07-17 17:49:50 +00: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.
llvm-svn: 63354
2009-01-30 01:04:22 +00:00
|
|
|
return iterator(I-1);
|
2008-07-17 17:49:50 +00:00
|
|
|
else // No decls found.
|
|
|
|
return end();
|
|
|
|
}
|
2008-04-11 07:06:57 +00:00
|
|
|
|
2008-09-09 19:28:27 +00:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// IdDeclInfoMap Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2008-11-17 20:34:05 +00:00
|
|
|
/// Returns the IdDeclInfo associated to the DeclarationName.
|
2008-04-11 07:06:57 +00:00
|
|
|
/// It creates a new IdDeclInfo if one was not created before for this id.
|
2008-05-09 23:39:43 +00:00
|
|
|
IdentifierResolver::IdDeclInfo &
|
2008-11-17 20:34:05 +00:00
|
|
|
IdentifierResolver::IdDeclInfoMap::operator[](DeclarationName Name) {
|
|
|
|
void *Ptr = Name.getFETokenInfo<void>();
|
2008-04-11 07:06:57 +00:00
|
|
|
|
2008-05-09 23:39:43 +00:00
|
|
|
if (Ptr) return *toIdDeclInfo(Ptr);
|
2008-04-11 07:06:57 +00:00
|
|
|
|
2008-04-12 01:50:47 +00:00
|
|
|
if (CurIndex == VECTOR_SIZE) {
|
|
|
|
// Add a IdDeclInfo vector 'pool'
|
2008-04-12 12:38:58 +00:00
|
|
|
IDIVecs.push_back(std::vector<IdDeclInfo>());
|
2008-04-12 01:50:47 +00:00
|
|
|
// Fill the vector
|
|
|
|
IDIVecs.back().resize(VECTOR_SIZE);
|
2008-04-11 07:06:57 +00:00
|
|
|
CurIndex = 0;
|
|
|
|
}
|
2008-04-12 01:50:47 +00:00
|
|
|
IdDeclInfo *IDI = &IDIVecs.back()[CurIndex];
|
2008-11-17 20:34:05 +00:00
|
|
|
Name.setFETokenInfo(reinterpret_cast<void*>(
|
2008-04-11 07:06:57 +00:00
|
|
|
reinterpret_cast<uintptr_t>(IDI) | 0x1)
|
|
|
|
);
|
|
|
|
++CurIndex;
|
|
|
|
return *IDI;
|
|
|
|
}
|