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
This commit is contained in:
Douglas Gregor 2009-01-30 01:04:22 +00:00
Родитель e620ecdd41
Коммит 4c921ae760
15 изменённых файлов: 223 добавлений и 431 удалений

Просмотреть файл

@ -225,14 +225,9 @@ void IdentifierResolver::RemoveDecl(NamedDecl *D) {
return toIdDeclInfo(Ptr)->RemoveDecl(D);
}
/// begin - Returns an iterator for decls with name 'Name', starting at
/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
/// decls of parent declaration contexts too.
/// begin - Returns an iterator for decls with name 'Name'.
IdentifierResolver::iterator
IdentifierResolver::begin(DeclarationName Name, const DeclContext *Ctx,
bool LookInParentCtx) {
assert(Ctx && "null param passed");
IdentifierResolver::begin(DeclarationName Name) {
void *Ptr = Name.getFETokenInfo<void>();
if (!Ptr) return end();
@ -245,26 +240,11 @@ IdentifierResolver::begin(DeclarationName Name, const DeclContext *Ctx,
IdDeclInfo::DeclsTy::iterator I = IDI->decls_end();
if (I != IDI->decls_begin())
return iterator(I-1, LookInParentCtx);
return iterator(I-1);
else // No decls found.
return end();
}
/// PreIncIter - Do a preincrement when 'Ptr' is a BaseIter.
void IdentifierResolver::iterator::PreIncIter() {
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, LookInParentCtx());
else // No more decls.
*this = end();
}
//===----------------------------------------------------------------------===//
// IdDeclInfoMap Implementation
//===----------------------------------------------------------------------===//

Просмотреть файл

@ -136,19 +136,12 @@ public:
}
/// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration
/// contexts depending on 'LookInParentCtx'.
iterator(BaseIter I, bool LookInParentCtx) {
iterator(BaseIter I) {
Ptr = reinterpret_cast<uintptr_t>(I) | 0x1;
assert((Ptr & 0x2) == 0 && "Invalid Ptr!");
if (LookInParentCtx) Ptr |= 0x2;
}
bool isIterator() const { return (Ptr & 0x1); }
bool LookInParentCtx() const {
assert(isIterator() && "Ptr not an iterator!");
return (Ptr & 0x2) != 0;
}
BaseIter getIterator() const {
assert(isIterator() && "Ptr not an iterator!");
return reinterpret_cast<BaseIter>(Ptr & ~0x3);
@ -176,29 +169,32 @@ public:
iterator& operator++() {
if (!isIterator()) // common case.
Ptr = 0;
else
PreIncIter();
else {
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 // No more decls.
*this = iterator();
}
return *this;
}
uintptr_t getAsOpaqueValue() const { return Ptr; }
static iterator getFromOpaqueValue(uintptr_t P) {
iterator Result(0);
iterator Result;
Result.Ptr = P;
return Result;
}
private:
void PreIncIter();
};
/// begin - Returns an iterator for decls with the name 'Name', starting at
/// declaration context 'Ctx'. If 'LookInParentCtx' is true, it will walk the
/// decls of parent declaration contexts too.
/// Default for 'LookInParentCtx is true.
static iterator begin(DeclarationName Name, const DeclContext *Ctx,
bool LookInParentCtx = true);
/// begin - Returns an iterator for decls with the name 'Name'.
static iterator begin(DeclarationName Name);
/// end - Returns an iterator that has 'finished'.
static iterator end() {

Просмотреть файл

@ -559,7 +559,7 @@ public:
/// for capturing language semantics (certain lookups will ignore
/// certain names, for example) and for performance, since name
/// lookup is often a bottleneck in the compilation of C++. Name
/// lookup criteria is specified via the LookupCriteria class.
/// lookup criteria is specified via the LookupCriteria enumeration.
///
/// The results of name lookup can vary based on the kind of name
/// lookup performed, the current language, and the translation
@ -571,65 +571,26 @@ public:
/// the ability to distinguish among them.
//@{
/// @brief Describes the criteria by which name lookup will
/// determine whether a given name will be found.
///
/// The LookupCriteria class captures the information required to
/// direct name lookup to find the appropriate kind of name. It
/// includes information about which kinds of names to consider
/// (ordinary names, tag names, class/struct/union member names,
/// namespace names, etc.) and where to look for those
/// names. LookupCriteria is used throughout semantic analysis to
/// specify how to search for a name, e.g., with the LookupName and
/// LookupQualifiedName functions.
struct LookupCriteria {
/// NameKind - The kinds of names that we are looking for.
enum NameKind {
/// Ordinary - Ordinary name lookup, which finds ordinary names
/// (functions, variables, typedefs, etc.) in C and most kinds
/// of names (functions, variables, members, types, etc.) in
/// C++.
Ordinary,
/// Tag - Tag name lookup, which finds the names of enums,
/// classes, structs, and unions.
Tag,
/// Member - Member name lookup, which finds the names of
/// class/struct/union members.
Member,
/// NestedNameSpecifier - Look up of a name that precedes the
/// '::' scope resolution operator in C++. This lookup
/// completely ignores operator, function, and enumerator names
/// (C++ [basic.lookup.qual]p1).
NestedNameSpecifier,
/// Namespace - Look up a namespace name within a C++
/// using directive or namespace alias definition, ignoring
/// non-namespace names (C++ [basic.lookup.udir]p1).
Namespace
} Kind;
/// AllowLazyBuiltinCreation - If true, permits name lookup to
/// lazily build declarations for built-in names, e.g.,
/// __builtin_expect.
bool AllowLazyBuiltinCreation;
/// RedeclarationOnly - If true, the lookup will only
/// consider entities within the scope where the lookup
/// began. Entities that might otherwise meet the lookup criteria
/// but are not within the original lookup scope will be ignored.
bool RedeclarationOnly;
/// IDNS - Bitwise OR of the appropriate Decl::IDNS_* flags that
/// describe the namespaces where we should look for names. This
/// field is determined by the kind of name we're searching for.
unsigned IDNS;
LookupCriteria()
: Kind(Ordinary), AllowLazyBuiltinCreation(true),
RedeclarationOnly(false), IDNS(Decl::IDNS_Ordinary) { }
LookupCriteria(NameKind K, bool RedeclarationOnly, bool CPlusPlus);
bool isLookupResult(Decl *D) const;
/// @brief Describes the kind of name lookup to perform.
enum LookupNameKind {
/// Ordinary name lookup, which finds ordinary names (functions,
/// variables, typedefs, etc.) in C and most kinds of names
/// (functions, variables, members, types, etc.) in C++.
LookupOrdinaryName = 0,
/// Tag name lookup, which finds the names of enums, classes,
/// structs, and unions.
LookupTagName,
/// Member name lookup, which finds the names of
/// class/struct/union members.
LookupMemberName,
/// Look up of a name that precedes the '::' scope resolution
/// operator in C++. This lookup completely ignores operator,
/// function, and enumerator names (C++ [basic.lookup.qual]p1).
LookupNestedNameSpecifierName,
/// Look up a namespace name within a C++ using directive or
/// namespace alias definition, ignoring non-namespace names (C++
/// [basic.lookup.udir]p1).
LookupNamespaceName
};
/// @brief Represents the results of name lookup.
@ -775,18 +736,38 @@ public:
BasePaths *getBasePaths() const;
};
LookupResult LookupName(Scope *S, DeclarationName Name,
LookupCriteria Criteria);
LookupResult LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
LookupCriteria Criteria);
LookupResult LookupParsedName(Scope *S, const CXXScopeSpec &SS,
DeclarationName Name, LookupCriteria Criteria);
LookupResult LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S,
bool LookInParent = true);
LookupResult LookupDeclInContext(DeclarationName Name, unsigned NSI,
const DeclContext *LookupCtx,
bool LookInParent = true);
/// Determines whether D is a suitable lookup result according to the
/// lookup criteria.
bool isAcceptableLookupResult(Decl *D, LookupNameKind NameKind,
unsigned IDNS) const {
switch (NameKind) {
case Sema::LookupOrdinaryName:
case Sema::LookupTagName:
case Sema::LookupMemberName:
return D->isInIdentifierNamespace(IDNS);
case Sema::LookupNestedNameSpecifierName:
return isa<TypedefDecl>(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag);
case Sema::LookupNamespaceName:
return isa<NamespaceDecl>(D);
}
assert(false &&
"isNameAcceptableLookupResult always returns before this point");
return false;
}
LookupResult LookupName(Scope *S, DeclarationName Name,
LookupNameKind NameKind,
bool RedeclarationOnly = false);
LookupResult LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
LookupNameKind NameKind,
bool RedeclarationOnly = false);
LookupResult LookupParsedName(Scope *S, const CXXScopeSpec *SS,
DeclarationName Name,
LookupNameKind NameKind,
bool RedeclarationOnly = false);
bool DiagnoseAmbiguousLookup(LookupResult &Result, DeclarationName Name,
SourceLocation NameLoc,
SourceRange LookupRange = SourceRange());

Просмотреть файл

@ -36,10 +36,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
SourceLocation IdLoc,
SourceLocation CCLoc,
IdentifierInfo &II) {
Decl *SD = LookupParsedName(S, SS, &II,
LookupCriteria(LookupCriteria::NestedNameSpecifier,
/*RedeclarationOnly=*/false,
/*CPlusPlus=*/true));
Decl *SD = LookupParsedName(S, &SS, &II, LookupNestedNameSpecifierName);
if (SD) {
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
@ -60,10 +57,7 @@ Sema::CXXScopeTy *Sema::ActOnCXXNestedNameSpecifier(Scope *S,
// ordinary name lookup, which can help us produce better error
// messages.
if (!SD)
SD = LookupParsedName(S, SS, &II,
LookupCriteria(LookupCriteria::Ordinary,
/*RedeclarationOnly=*/false,
/*CPlusPlus=*/true));
SD = LookupParsedName(S, &SS, &II, LookupOrdinaryName);
unsigned DiagID;
if (SD)
DiagID = diag::err_expected_class_or_namespace;

Просмотреть файл

@ -32,18 +32,8 @@ using namespace clang;
Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, Scope *S,
const CXXScopeSpec *SS) {
DeclContext *DC = 0;
if (SS) {
if (SS->isInvalid())
return 0;
DC = static_cast<DeclContext*>(SS->getScopeRep());
}
Decl *IIDecl = 0;
LookupResult Result = DC ? LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC) :
LookupDeclInScope(&II, Decl::IDNS_Ordinary, S);
LookupResult Result = LookupParsedName(S, SS, &II, LookupOrdinaryName, false);
switch (Result.getKind()) {
case LookupResult::NotFound:
case LookupResult::FoundOverloaded:
@ -139,8 +129,7 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
// We're pushing the tag into the current context, which might
// require some reshuffling in the identifier resolver.
IdentifierResolver::iterator
I = IdResolver.begin(TD->getDeclName(), CurContext,
false/*LookInParentCtx*/),
I = IdResolver.begin(TD->getDeclName()),
IEnd = IdResolver.end();
if (I != IEnd && isDeclInScope(*I, CurContext, S)) {
NamedDecl *PrevDecl = *I;
@ -175,10 +164,8 @@ void Sema::PushOnScopeChains(NamedDecl *D, Scope *S) {
// We are pushing the name of a function, which might be an
// overloaded name.
FunctionDecl *FD = cast<FunctionDecl>(D);
DeclContext *DC = FD->getDeclContext()->getLookupContext();
IdentifierResolver::iterator Redecl
= std::find_if(IdResolver.begin(FD->getDeclName(), DC,
false/*LookInParentCtx*/),
= std::find_if(IdResolver.begin(FD->getDeclName()),
IdResolver.end(),
std::bind1st(std::mem_fun(&NamedDecl::declarationReplaces),
FD));
@ -218,7 +205,7 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) {
ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *Id) {
// The third "scope" argument is 0 since we aren't enabling lazy built-in
// creation from this context.
Decl *IDecl = LookupDeclInScope(Id, Decl::IDNS_Ordinary, 0);
Decl *IDecl = LookupName(TUScope, Id, LookupOrdinaryName);
return dyn_cast_or_null<ObjCInterfaceDecl>(IDecl);
}
@ -255,123 +242,12 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
return S;
}
/// LookupDeclInScope - Look up the inner-most declaration in the specified
/// namespace. NamespaceNameOnly - during lookup only namespace names
/// are considered as required in C++ [basic.lookup.udir] 3.4.6.p1
/// 'When looking up a namespace-name in a using-directive or
/// namespace-alias-definition, only namespace names are considered.'
///
/// Note: The use of this routine is deprecated. Please use
/// LookupName, LookupQualifiedName, or LookupParsedName instead.
Sema::LookupResult
Sema::LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S,
bool LookInParent) {
if (getLangOptions().CPlusPlus) {
LookupCriteria::NameKind Kind;
if (NSI == Decl::IDNS_Ordinary) {
Kind = LookupCriteria::Ordinary;
} else if (NSI == Decl::IDNS_Tag)
Kind = LookupCriteria::Tag;
else {
assert(NSI == Decl::IDNS_Member &&"Unable to grok LookupDecl NSI argument");
Kind = LookupCriteria::Member;
}
// Unqualified lookup
return LookupName(S, Name,
LookupCriteria(Kind, !LookInParent,
getLangOptions().CPlusPlus));
}
// Fast path for C/ObjC.
// Unqualified name lookup in C/Objective-C is purely lexical, so
// search in the declarations attached to the name.
// For the purposes of unqualified name lookup, structs and unions
// don't have scopes at all. For example:
//
// struct X {
// struct T { int i; } x;
// };
//
// void f() {
// struct T t; // okay: T is defined lexically within X, but
// // semantically at global scope
// };
//
// FIXME: Is there a better way to deal with this?
DeclContext *SearchCtx = CurContext;
while (isa<RecordDecl>(SearchCtx) || isa<EnumDecl>(SearchCtx))
SearchCtx = SearchCtx->getParent();
IdentifierResolver::iterator I
= IdResolver.begin(Name, SearchCtx, LookInParent);
// 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 (; I != IdResolver.end(); ++I) {
switch (NSI) {
case Decl::IDNS_Ordinary:
case Decl::IDNS_Tag:
case Decl::IDNS_Member:
if ((*I)->isInIdentifierNamespace(NSI))
return LookupResult::CreateLookupResult(Context, *I);
break;
default:
assert(0 && "Unable to grok LookupDecl NSI argument");
}
}
if (NSI == Decl::IDNS_Ordinary) {
IdentifierInfo *II = Name.getAsIdentifierInfo();
if (II) {
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID())
return LookupResult::CreateLookupResult(Context,
LazilyCreateBuiltin((IdentifierInfo *)II, BuiltinID,
S));
}
if (getLangOptions().ObjC1 && II) {
// @interface and @compatibility_alias introduce typedef-like names.
// Unlike typedef's, they can only be introduced at file-scope (and are
// therefore not scoped decls). They can, however, be shadowed by
// other names in IDNS_Ordinary.
ObjCInterfaceDeclsTy::iterator IDI = ObjCInterfaceDecls.find(II);
if (IDI != ObjCInterfaceDecls.end())
return LookupResult::CreateLookupResult(Context, IDI->second);
ObjCAliasTy::iterator I = ObjCAliasDecls.find(II);
if (I != ObjCAliasDecls.end())
return LookupResult::CreateLookupResult(Context,
I->second->getClassInterface());
}
}
return LookupResult::CreateLookupResult(Context, 0);
}
Sema::LookupResult
Sema::LookupDeclInContext(DeclarationName Name, unsigned NSI,
const DeclContext *LookupCtx,
bool LookInParent) {
assert(LookupCtx && "LookupDeclInContext(): Missing DeclContext");
LookupCriteria::NameKind Kind;
if (NSI == Decl::IDNS_Ordinary) {
Kind = LookupCriteria::Ordinary;
} else if (NSI == Decl::IDNS_Tag)
Kind = LookupCriteria::Tag;
else {
assert(NSI == Decl::IDNS_Member &&"Unable to grok LookupDecl NSI argument");
Kind = LookupCriteria::Member;
}
return LookupQualifiedName(const_cast<DeclContext *>(LookupCtx), Name,
LookupCriteria(Kind, !LookInParent,
getLangOptions().CPlusPlus));
}
void Sema::InitBuiltinVaListType() {
if (!Context.getBuiltinVaListType().isNull())
return;
IdentifierInfo *VaIdent = &Context.Idents.get("__builtin_va_list");
Decl *VaDecl = LookupDeclInScope(VaIdent, Decl::IDNS_Ordinary, TUScope);
Decl *VaDecl = LookupName(TUScope, VaIdent, LookupOrdinaryName);
TypedefDecl *VaTypedef = cast<TypedefDecl>(VaDecl);
Context.setBuiltinVaListType(Context.getTypedefType(VaTypedef));
}
@ -420,7 +296,7 @@ NamespaceDecl *Sema::GetStdNamespace() {
if (!StdNamespace) {
IdentifierInfo *StdIdent = &PP.getIdentifierTable().get("std");
DeclContext *Global = Context.getTranslationUnitDecl();
Decl *Std = LookupDeclInContext(StdIdent, Decl::IDNS_Ordinary, Global);
Decl *Std = LookupQualifiedName(Global, StdIdent, LookupNamespaceName);
StdNamespace = dyn_cast_or_null<NamespaceDecl>(Std);
}
return StdNamespace;
@ -689,10 +565,9 @@ void Sema::CheckForFileScopedRedefinitions(Scope *S, VarDecl *VD) {
// FIXME: I don't think this will actually see all of the
// redefinitions. Can't we check this property on-the-fly?
for (IdentifierResolver::iterator
I = IdResolver.begin(VD->getIdentifier(),
VD->getDeclContext(), false/*LookInParentCtx*/),
E = IdResolver.end(); I != E; ++I) {
for (IdentifierResolver::iterator I = IdResolver.begin(VD->getIdentifier()),
E = IdResolver.end();
I != E; ++I) {
if (*I != VD && isDeclInScope(*I, VD->getDeclContext(), S)) {
VarDecl *OldDecl = dyn_cast<VarDecl>(*I);
@ -864,8 +739,8 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
FEnd = AnonRecord->field_end();
F != FEnd; ++F) {
if ((*F)->getDeclName()) {
Decl *PrevDecl = LookupDeclInContext((*F)->getDeclName(),
Decl::IDNS_Ordinary, Owner, false);
Decl *PrevDecl = LookupQualifiedName(Owner, (*F)->getDeclName(),
LookupOrdinaryName, true);
if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
// C++ [class.union]p2:
// The names of the members of an anonymous union shall be
@ -1312,13 +1187,12 @@ Sema::ActOnDeclarator(Scope *S, Declarator &D, DeclTy *lastDecl,
bool InvalidDecl = false;
// See if this is a redefinition of a variable in the same scope.
if (!D.getCXXScopeSpec().isSet()) {
if (!D.getCXXScopeSpec().isSet() && !D.getCXXScopeSpec().isInvalid()) {
DC = CurContext;
PrevDecl = LookupDeclInScope(Name, Decl::IDNS_Ordinary, S);
PrevDecl = LookupName(S, Name, LookupOrdinaryName);
} else { // Something like "int foo::x;"
DC = static_cast<DeclContext*>(D.getCXXScopeSpec().getScopeRep());
PrevDecl = DC ? LookupDeclInContext(Name, Decl::IDNS_Ordinary, DC)
: LookupDeclInScope(Name, Decl::IDNS_Ordinary, S);
PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName);
// C++ 7.3.1.2p2:
// Members (including explicit specializations of templates) of a named
@ -1807,7 +1681,7 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
<< D.getCXXScopeSpec().getRange();
InvalidDecl = true;
PrevDecl = LookupDeclInContext(Name, Decl::IDNS_Ordinary, DC);
PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName);
if (!PrevDecl) {
// Nothing to suggest.
} else if (OverloadedFunctionDecl *Ovl
@ -2662,7 +2536,7 @@ Sema::ActOnParamDeclarator(Scope *S, Declarator &D) {
// among each other. Here they can only shadow globals, which is ok.
IdentifierInfo *II = D.getIdentifier();
if (II) {
if (Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Ordinary, S)) {
if (Decl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) {
if (PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl);
@ -2954,7 +2828,7 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
DC = static_cast<DeclContext*>(SS.getScopeRep());
// Look-up name inside 'foo::'.
PrevDecl = dyn_cast_or_null<TagDecl>(
LookupDeclInContext(Name, Decl::IDNS_Tag, DC).getAsDecl());
LookupQualifiedName(DC, Name, LookupTagName).getAsDecl());
// A tag 'foo::bar' must already exist.
if (PrevDecl == 0) {
@ -2965,14 +2839,14 @@ Sema::DeclTy *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagKind TK,
} else if (Name) {
// If this is a named struct, check to see if there was a previous forward
// declaration or definition.
Decl *D = LookupDeclInScope(Name, Decl::IDNS_Tag, S);
Decl *D = LookupName(S, Name, LookupTagName);
PrevDecl = dyn_cast_or_null<NamedDecl>(D);
if (!getLangOptions().CPlusPlus && TK != TK_Reference) {
// FIXME: This makes sure that we ignore the contexts associated
// with C structs, unions, and enums when looking for a matching
// tag declaration or definition. See the similar lookup tweak
// in Sema::LookupDecl; is there a better way to deal with this?
// in Sema::LookupName; is there a better way to deal with this?
while (isa<RecordDecl>(SearchDC) || isa<EnumDecl>(SearchDC))
SearchDC = SearchDC->getParent();
}
@ -3158,9 +3032,7 @@ CreateNewDecl:
// shall not be declared with the same name as a typedef-name
// that is declared in that scope and refers to a type other
// than the class or enumeration itself.
LookupResult Lookup = LookupName(S, Name,
LookupCriteria(LookupCriteria::Ordinary,
true, true));
LookupResult Lookup = LookupName(S, Name, LookupOrdinaryName, true);
TypedefDecl *PrevTypedef = 0;
if (Lookup.getKind() == LookupResult::Found)
PrevTypedef = dyn_cast<TypedefDecl>(Lookup.getAsDecl());
@ -3352,8 +3224,7 @@ Sema::DeclTy *Sema::ActOnField(Scope *S, DeclTy *TagD,
DeclSpec::SCS_mutable);
if (II) {
Decl *PrevDecl
= LookupDeclInScope(II, Decl::IDNS_Member, S, false);
Decl *PrevDecl = LookupName(S, II, LookupMemberName, true);
if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S)
&& !isa<TagDecl>(PrevDecl)) {
Diag(Loc, diag::err_duplicate_member) << II;
@ -3445,7 +3316,7 @@ Sema::DeclTy *Sema::ActOnIvar(Scope *S,
(Expr *)BitfieldWidth);
if (II) {
Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Member, S, false);
Decl *PrevDecl = LookupName(S, II, LookupMemberName, true);
if (PrevDecl && isDeclInScope(PrevDecl, CurContext, S)
&& !isa<TagDecl>(PrevDecl)) {
Diag(Loc, diag::err_duplicate_member) << II;
@ -3621,7 +3492,7 @@ Sema::DeclTy *Sema::ActOnEnumConstant(Scope *S, DeclTy *theEnumDecl,
// Verify that there isn't already something declared with this name in this
// scope.
Decl *PrevDecl = LookupDeclInScope(Id, Decl::IDNS_Ordinary, S);
Decl *PrevDecl = LookupName(S, Id, LookupOrdinaryName);
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(IdLoc, PrevDecl);

Просмотреть файл

@ -1375,8 +1375,8 @@ Sema::DeclTy *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
// original-namespace-definition is the name of the namespace. Subsequently
// in that declarative region, it is treated as an original-namespace-name.
Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Ordinary, DeclRegionScope,
/*LookupInParent=*/false);
Decl *PrevDecl = LookupName(DeclRegionScope, II, LookupOrdinaryName,
true);
if (NamespaceDecl *OrigNS = dyn_cast_or_null<NamespaceDecl>(PrevDecl)) {
// This is an extended namespace definition.
@ -1437,14 +1437,7 @@ Sema::DeclTy *Sema::ActOnUsingDirective(Scope *S,
// FIXME: This still requires lot more checks, and AST support.
// Lookup namespace name.
LookupCriteria Criteria(LookupCriteria::Namespace, /*RedeclarationOnly=*/false,
/*CPlusPlus=*/true);
Decl *NS = 0;
if (SS.isSet())
NS = LookupQualifiedName(static_cast<DeclContext*>(SS.getScopeRep()),
NamespcName, Criteria);
else
NS = LookupName(S, NamespcName, Criteria);
Decl *NS = LookupParsedName(S, &SS, NamespcName, LookupNamespaceName, false);
if (NS) {
assert(isa<NamespaceDecl>(NS) && "expected namespace decl");
@ -2179,7 +2172,7 @@ Sema::DeclTy *Sema::ActOnExceptionDeclarator(Scope *S, Declarator &D)
// FIXME: Need to check for abstract classes.
IdentifierInfo *II = D.getIdentifier();
if (Decl *PrevDecl = LookupDeclInScope(II, Decl::IDNS_Ordinary, S)) {
if (Decl *PrevDecl = LookupName(S, II, LookupOrdinaryName)) {
// The scope should be freshly made just for us. There is just no way
// it contains any previous declaration.
assert(!S->isDeclScope(PrevDecl));

Просмотреть файл

@ -64,7 +64,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
assert(ClassName && "Missing class identifier");
// Check for another declaration kind with the same name.
Decl *PrevDecl = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope);
Decl *PrevDecl = LookupName(TUScope, ClassName, LookupOrdinaryName);
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(ClassLoc, PrevDecl);
@ -107,7 +107,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
if (SuperName) {
ObjCInterfaceDecl* SuperClassEntry = 0;
// Check if a different kind of symbol declared in this scope.
PrevDecl = LookupDeclInScope(SuperName, Decl::IDNS_Ordinary, TUScope);
PrevDecl = LookupName(TUScope, SuperName, LookupOrdinaryName);
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
Diag(SuperLoc, diag::err_redefinition_different_kind) << SuperName;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
@ -149,7 +149,7 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
IdentifierInfo *ClassName,
SourceLocation ClassLocation) {
// Look for previous declaration of alias name
Decl *ADecl = LookupDeclInScope(AliasName, Decl::IDNS_Ordinary, TUScope);
Decl *ADecl = LookupName(TUScope, AliasName, LookupOrdinaryName);
if (ADecl) {
if (isa<ObjCCompatibleAliasDecl>(ADecl))
Diag(AliasLocation, diag::warn_previous_alias_decl);
@ -159,13 +159,13 @@ Sema::DeclTy *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc,
return 0;
}
// Check for class declaration
Decl *CDeclU = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope);
Decl *CDeclU = LookupName(TUScope, ClassName, LookupOrdinaryName);
if (const TypedefDecl *TDecl = dyn_cast_or_null<TypedefDecl>(CDeclU)) {
QualType T = TDecl->getUnderlyingType();
if (T->isObjCInterfaceType()) {
if (NamedDecl *IDecl = T->getAsObjCInterfaceType()->getDecl()) {
ClassName = IDecl->getIdentifier();
CDeclU = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope);
CDeclU = LookupName(TUScope, ClassName, LookupOrdinaryName);
}
}
}
@ -535,7 +535,7 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation(
SourceLocation SuperClassLoc) {
ObjCInterfaceDecl* IDecl = 0;
// Check for another declaration kind with the same name.
Decl *PrevDecl = LookupDeclInScope(ClassName, Decl::IDNS_Ordinary, TUScope);
Decl *PrevDecl = LookupName(TUScope, ClassName, LookupOrdinaryName);
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
Diag(ClassLoc, diag::err_redefinition_different_kind) << ClassName;
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
@ -551,7 +551,7 @@ Sema::DeclTy *Sema::ActOnStartClassImplementation(
ObjCInterfaceDecl* SDecl = 0;
if (SuperClassname) {
// Check if a different kind of symbol declared in this scope.
PrevDecl = LookupDeclInScope(SuperClassname, Decl::IDNS_Ordinary, TUScope);
PrevDecl = LookupName(TUScope, SuperClassname, LookupOrdinaryName);
if (PrevDecl && !isa<ObjCInterfaceDecl>(PrevDecl)) {
Diag(SuperClassLoc, diag::err_redefinition_different_kind)
<< SuperClassname;
@ -909,7 +909,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
for (unsigned i = 0; i != NumElts; ++i) {
// Check for another declaration kind with the same name.
Decl *PrevDecl = LookupDeclInScope(IdentList[i], Decl::IDNS_Ordinary, TUScope);
Decl *PrevDecl = LookupName(TUScope, IdentList[i], LookupOrdinaryName);
if (PrevDecl && PrevDecl->isTemplateParameter()) {
// Maybe we will complain about the shadowed template parameter.
DiagnoseTemplateParameterShadow(AtClassLoc, PrevDecl);

Просмотреть файл

@ -555,14 +555,9 @@ Sema::ActOnDeclarationNameExpr(Scope *S, SourceLocation Loc,
// Could be enum-constant, value decl, instance variable, etc.
Decl *D = 0;
LookupResult Lookup;
if (SS && !SS->isEmpty()) {
DeclContext *DC = static_cast<DeclContext*>(SS->getScopeRep());
if (DC == 0)
return ExprError();
Lookup = LookupDeclInContext(Name, Decl::IDNS_Ordinary, DC);
} else
Lookup = LookupDeclInScope(Name, Decl::IDNS_Ordinary, S);
if (SS && SS->isInvalid())
return ExprError();
LookupResult Lookup = LookupParsedName(S, SS, Name, LookupOrdinaryName);
if (Lookup.isAmbiguous()) {
DiagnoseAmbiguousLookup(Lookup, Name, Loc,
@ -1519,9 +1514,7 @@ Sema::ActOnMemberReferenceExpr(Scope *S, ExprArg Base, SourceLocation OpLoc,
// than this.
LookupResult Result
= LookupQualifiedName(RDecl, DeclarationName(&Member),
LookupCriteria(LookupCriteria::Member,
/*RedeclarationOnly=*/false,
getLangOptions().CPlusPlus));
LookupMemberName, false);
Decl *MemberDecl = 0;
if (!Result)
@ -4030,9 +4023,9 @@ Sema::ExprResult Sema::ActOnBuiltinOffsetOf(Scope *S,
// Get the decl corresponding to this.
RecordDecl *RD = RC->getDecl();
FieldDecl *MemberDecl
= dyn_cast_or_null<FieldDecl>(LookupDeclInContext(OC.U.IdentInfo,
Decl::IDNS_Ordinary,
RD, false).getAsDecl());
= dyn_cast_or_null<FieldDecl>(LookupQualifiedName(RD, OC.U.IdentInfo,
LookupMemberName)
.getAsDecl());
if (!MemberDecl)
return Diag(BuiltinLoc, diag::err_typecheck_no_member)
<< OC.U.IdentInfo << SourceRange(OC.LocStart, OC.LocEnd);

Просмотреть файл

@ -55,12 +55,12 @@ Sema::ActOnCXXOperatorFunctionIdExpr(Scope *S, SourceLocation OperatorLoc,
Action::ExprResult
Sema::ActOnCXXTypeid(SourceLocation OpLoc, SourceLocation LParenLoc,
bool isType, void *TyOrExpr, SourceLocation RParenLoc) {
const NamespaceDecl *StdNs = GetStdNamespace();
NamespaceDecl *StdNs = GetStdNamespace();
if (!StdNs)
return Diag(OpLoc, diag::err_need_header_before_typeid);
IdentifierInfo *TypeInfoII = &PP.getIdentifierTable().get("type_info");
Decl *TypeInfoDecl = LookupDeclInContext(TypeInfoII, Decl::IDNS_Tag, StdNs);
Decl *TypeInfoDecl = LookupQualifiedName(StdNs, TypeInfoII, LookupTagName);
RecordDecl *TypeInfoRecordDecl = dyn_cast_or_null<RecordDecl>(TypeInfoDecl);
if (!TypeInfoRecordDecl)
return Diag(OpLoc, diag::err_need_header_before_typeid);

Просмотреть файл

@ -52,7 +52,7 @@ Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs,
// Initialize the constant string interface lazily. This assumes
// the NSConstantString interface is seen in this translation unit.
IdentifierInfo *NSIdent = &Context.Idents.get("NSConstantString");
Decl *IFace = LookupDeclInScope(NSIdent, Decl::IDNS_Ordinary, TUScope);
Decl *IFace = LookupName(TUScope, NSIdent, LookupOrdinaryName);
ObjCInterfaceDecl *strIFace = dyn_cast_or_null<ObjCInterfaceDecl>(IFace);
if (strIFace)
Context.setObjCConstantStringInterface(strIFace);
@ -209,7 +209,7 @@ Sema::ExprResult Sema::ActOnClassMessage(
} else {
// 'super' has been used outside a method context. If a variable named
// 'super' has been declared, redirect. If not, produce a diagnostic.
Decl *SuperDecl = LookupDeclInScope(receiverName, Decl::IDNS_Ordinary, S);
Decl *SuperDecl = LookupName(S, receiverName, LookupOrdinaryName);
ValueDecl *VD = dyn_cast_or_null<ValueDecl>(SuperDecl);
if (VD) {
ExprResult ReceiverExpr = new DeclRefExpr(VD, VD->getType(),
@ -234,7 +234,7 @@ Sema::ExprResult Sema::ActOnClassMessage(
//
// If necessary, the following lookup could move to getObjCInterfaceDecl().
if (!ClassDecl) {
Decl *IDecl = LookupDeclInScope(receiverName, Decl::IDNS_Ordinary, 0);
Decl *IDecl = LookupName(TUScope, receiverName, LookupOrdinaryName);
if (TypedefDecl *OCTD = dyn_cast_or_null<TypedefDecl>(IDecl)) {
const ObjCInterfaceType *OCIT;
OCIT = OCTD->getUnderlyingType()->getAsObjCInterfaceType();

Просмотреть файл

@ -153,7 +153,8 @@ bool Sema::LookupInBases(CXXRecordDecl *Class,
} else {
Paths.ScratchPath.Decls = BaseRecord->lookup(Criteria.Name);
while (Paths.ScratchPath.Decls.first != Paths.ScratchPath.Decls.second) {
if (Criteria.Criteria.isLookupResult(*Paths.ScratchPath.Decls.first)) {
if (isAcceptableLookupResult(*Paths.ScratchPath.Decls.first,
Criteria.NameKind, Criteria.IDNS)) {
FoundPathToThisBase = true;
break;
}

Просмотреть файл

@ -193,8 +193,9 @@ namespace clang {
/// MemberLookupCriteria - Constructs member lookup criteria to
/// search for a class member with the given Name.
explicit MemberLookupCriteria(DeclarationName Name,
Sema::LookupCriteria Criteria)
: LookupBase(false), Name(Name), Criteria(Criteria) { }
Sema::LookupNameKind NameKind,
unsigned IDNS)
: LookupBase(false), Name(Name), NameKind(NameKind), IDNS(IDNS) { }
/// LookupBase - True if we are looking for a base class (whose
/// type is Base). If false, we are looking for a named member of
@ -209,9 +210,8 @@ namespace clang {
/// LookupBase is false.
DeclarationName Name;
/// Criteria - The criteria by which we evaluate a named member,
/// if LookupBase is false.
Sema::LookupCriteria Criteria;
Sema::LookupNameKind NameKind;
unsigned IDNS;
};
}

Просмотреть файл

@ -31,8 +31,8 @@ using namespace clang;
/// OverloadeFunctionDecl that represents the overloaded functions in
/// [I, IEnd).
///
/// The existance of this routine is temporary; LookupDecl should
/// probably be able to return multiple results, to deal with cases of
/// The existance of this routine is temporary; users of LookupResult
/// should be able to handle multiple results, to deal with cases of
/// ambiguity and overloaded functions without needing to create a
/// Decl node.
template<typename DeclIterator>
@ -69,64 +69,6 @@ MaybeConstructOverloadSet(ASTContext &Context,
return *I;
}
/// @brief Constructs name lookup criteria.
///
/// @param K The kind of name that we're searching for.
///
/// @param RedeclarationOnly If true, then name lookup will only look
/// into the current scope for names, not in parent scopes. This
/// option should be set when we're looking to introduce a new
/// declaration into scope.
///
/// @param CPlusPlus Whether we are performing C++ name lookup or not.
Sema::LookupCriteria::LookupCriteria(NameKind K, bool RedeclarationOnly,
bool CPlusPlus)
: Kind(K), AllowLazyBuiltinCreation(K == Ordinary),
RedeclarationOnly(RedeclarationOnly) {
switch (Kind) {
case Ordinary:
IDNS = Decl::IDNS_Ordinary;
if (CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
break;
case Tag:
IDNS = Decl::IDNS_Tag;
break;
case Member:
IDNS = Decl::IDNS_Member;
if (CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary;
break;
case NestedNameSpecifier:
case Namespace:
IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member;
break;
}
}
/// isLookupResult - Determines whether D is a suitable lookup result
/// according to the lookup criteria.
bool Sema::LookupCriteria::isLookupResult(Decl *D) const {
switch (Kind) {
case Ordinary:
case Tag:
case Member:
return D->isInIdentifierNamespace(IDNS);
case NestedNameSpecifier:
return isa<TypedefDecl>(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag);
case Namespace:
return isa<NamespaceDecl>(D);
}
assert(false && "isLookupResult always returns before this point");
return false;
}
/// @brief Moves the name-lookup results from Other to this LookupResult.
Sema::LookupResult
Sema::LookupResult::CreateLookupResult(ASTContext &Context,
@ -239,6 +181,37 @@ BasePaths *Sema::LookupResult::getBasePaths() const {
return reinterpret_cast<BasePaths *>(First);
}
// Retrieve the set of identifier namespaces that correspond to a
// specific kind of name lookup.
inline unsigned
getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind,
bool CPlusPlus) {
unsigned IDNS = 0;
switch (NameKind) {
case Sema::LookupOrdinaryName:
IDNS = Decl::IDNS_Ordinary;
if (CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
break;
case Sema::LookupTagName:
IDNS = Decl::IDNS_Tag;
break;
case Sema::LookupMemberName:
IDNS = Decl::IDNS_Member;
if (CPlusPlus)
IDNS |= Decl::IDNS_Tag | Decl::IDNS_Ordinary;
break;
case Sema::LookupNestedNameSpecifierName:
case Sema::LookupNamespaceName:
IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member;
break;
}
return IDNS;
}
/// @brief Perform unqualified name lookup starting from a given
/// scope.
///
@ -276,52 +249,58 @@ BasePaths *Sema::LookupResult::getBasePaths() const {
/// declarations and possibly additional information used to diagnose
/// ambiguities.
Sema::LookupResult
Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria Criteria) {
Sema::LookupName(Scope *S, DeclarationName Name, LookupNameKind NameKind,
bool RedeclarationOnly) {
if (!Name) return LookupResult::CreateLookupResult(Context, 0);
if (!getLangOptions().CPlusPlus) {
// Unqualified name lookup in C/Objective-C is purely lexical, so
// search in the declarations attached to the name.
unsigned IDNS = 0;
switch (NameKind) {
case Sema::LookupOrdinaryName:
IDNS = Decl::IDNS_Ordinary;
break;
case Sema::LookupTagName:
IDNS = Decl::IDNS_Tag;
break;
case Sema::LookupMemberName:
IDNS = Decl::IDNS_Member;
break;
case Sema::LookupNestedNameSpecifierName:
case Sema::LookupNamespaceName:
assert(false && "C does not perform these kinds of name lookup");
break;
}
// For the purposes of unqualified name lookup, structs and unions
// don't have scopes at all. For example:
//
// struct X {
// struct T { int i; } x;
// };
//
// void f() {
// struct T t; // okay: T is defined lexically within X, but
// // semantically at global scope
// };
//
// FIXME: Is there a better way to deal with this?
DeclContext *SearchCtx = CurContext;
while (isa<RecordDecl>(SearchCtx) || isa<EnumDecl>(SearchCtx))
SearchCtx = SearchCtx->getParent();
IdentifierResolver::iterator I
= IdResolver.begin(Name, SearchCtx, !Criteria.RedeclarationOnly);
// 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 (; I != IdResolver.end(); ++I)
if (Criteria.isLookupResult(*I))
for (IdentifierResolver::iterator I = IdResolver.begin(Name),
IEnd = IdResolver.end();
I != IEnd; ++I)
if ((*I)->isInIdentifierNamespace(IDNS))
return LookupResult::CreateLookupResult(Context, *I);
} else {
unsigned IDNS
= getIdentifierNamespacesFromLookupNameKind(NameKind,
getLangOptions().CPlusPlus);
// Unqualified name lookup in C++ requires looking into scopes
// that aren't strictly lexical, and therefore we walk through the
// context as well as walking through the scopes.
// FIXME: does "true" for LookInParentCtx actually make sense?
IdentifierResolver::iterator
I = IdResolver.begin(Name, CurContext, true/*LookInParentCtx*/),
IEnd = IdResolver.end();
IdentifierResolver::iterator I = IdResolver.begin(Name),
IEnd = IdResolver.end();
for (; S; S = S->getParent()) {
// Check whether the IdResolver has anything in this scope.
for (; I != IEnd && S->isDeclScope(*I); ++I) {
if (Criteria.isLookupResult(*I)) {
if (isAcceptableLookupResult(*I, NameKind, IDNS)) {
// We found something. Look for anything else in our scope
// with this same name and in an acceptable identifier
// namespace, so that we can construct an overload set if we
@ -356,10 +335,11 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria Criteria) {
Ctx = Ctx->getParent();
while (Ctx && (Ctx->isNamespace() || Ctx->isRecord())) {
// Look for declarations of this name in this scope.
if (LookupResult Result = LookupQualifiedName(Ctx, Name, Criteria))
if (LookupResult Result = LookupQualifiedName(Ctx, Name, NameKind,
RedeclarationOnly))
return Result;
if (Criteria.RedeclarationOnly && !Ctx->isTransparentContext())
if (RedeclarationOnly && !Ctx->isTransparentContext())
return LookupResult::CreateLookupResult(Context, 0);
Ctx = Ctx->getParent();
@ -370,9 +350,9 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria Criteria) {
// If we didn't find a use of this identifier, and if the identifier
// corresponds to a compiler builtin, create the decl object for the builtin
// now, injecting it into translation unit scope, and return it.
if (Criteria.Kind == LookupCriteria::Ordinary) {
if (NameKind == LookupOrdinaryName) {
IdentifierInfo *II = Name.getAsIdentifierInfo();
if (Criteria.AllowLazyBuiltinCreation && II) {
if (II) {
// If this is a builtin on this (or all) targets, create the decl.
if (unsigned BuiltinID = II->getBuiltinID())
return LookupResult::CreateLookupResult(Context,
@ -428,25 +408,28 @@ Sema::LookupName(Scope *S, DeclarationName Name, LookupCriteria Criteria) {
/// ambiguities.
Sema::LookupResult
Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
LookupCriteria Criteria) {
LookupNameKind NameKind, bool RedeclarationOnly) {
assert(LookupCtx && "Sema::LookupQualifiedName requires a lookup context");
if (!Name) return LookupResult::CreateLookupResult(Context, 0);
// If we're performing qualified name lookup (e.g., lookup into a
// struct), find fields as part of ordinary name lookup.
if (Criteria.Kind == LookupCriteria::Ordinary)
Criteria.IDNS |= Decl::IDNS_Member;
unsigned IDNS
= getIdentifierNamespacesFromLookupNameKind(NameKind,
getLangOptions().CPlusPlus);
if (NameKind == LookupOrdinaryName)
IDNS |= Decl::IDNS_Member;
// Perform qualified name lookup into the LookupCtx.
DeclContext::lookup_iterator I, E;
for (llvm::tie(I, E) = LookupCtx->lookup(Name); I != E; ++I)
if (Criteria.isLookupResult(*I))
if (isAcceptableLookupResult(*I, NameKind, IDNS))
return LookupResult::CreateLookupResult(Context, I, E);
// If this isn't a C++ class or we aren't allowed to look into base
// classes, we're done.
if (Criteria.RedeclarationOnly || !isa<CXXRecordDecl>(LookupCtx))
if (RedeclarationOnly || !isa<CXXRecordDecl>(LookupCtx))
return LookupResult::CreateLookupResult(Context, 0);
// Perform lookup into our base classes.
@ -455,7 +438,7 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
// Look for this member in our base classes
if (!LookupInBases(cast<CXXRecordDecl>(LookupCtx),
MemberLookupCriteria(Name, Criteria), Paths))
MemberLookupCriteria(Name, NameKind, IDNS), Paths))
return LookupResult::CreateLookupResult(Context, 0);
// C++ [class.member.lookup]p2:
@ -552,18 +535,21 @@ Sema::LookupQualifiedName(DeclContext *LookupCtx, DeclarationName Name,
/// @param Name The name of the entity that name lookup will
/// search for.
///
/// @param Criteria The criteria that will determine which entities
/// are visible to name lookup.
///
/// @returns The result of qualified or unqualified name lookup.
Sema::LookupResult
Sema::LookupParsedName(Scope *S, const CXXScopeSpec &SS,
DeclarationName Name, LookupCriteria Criteria) {
if (SS.isSet())
return LookupQualifiedName(static_cast<DeclContext *>(SS.getScopeRep()),
Name, Criteria);
Sema::LookupParsedName(Scope *S, const CXXScopeSpec *SS,
DeclarationName Name, LookupNameKind NameKind,
bool RedeclarationOnly) {
if (SS) {
if (SS->isInvalid())
return LookupResult::CreateLookupResult(Context, 0);
return LookupName(S, Name, Criteria);
if (SS->isSet())
return LookupQualifiedName(static_cast<DeclContext *>(SS->getScopeRep()),
Name, NameKind, RedeclarationOnly);
}
return LookupName(S, Name, NameKind, RedeclarationOnly);
}
/// @brief Produce a diagnostic describing the ambiguity that resulted

Просмотреть файл

@ -2279,9 +2279,8 @@ void Sema::AddOperatorCandidates(OverloadedOperatorKind Op, Scope *S,
// of type T2 or “reference to (possibly cv-qualified) T2”,
// when T2 is an enumeration type, are candidate functions.
{
IdentifierResolver::iterator
I = IdResolver.begin(OpName, CurContext, true/*LookInParentCtx*/),
IEnd = IdResolver.end();
IdentifierResolver::iterator I = IdResolver.begin(OpName),
IEnd = IdResolver.end();
for (; I != IEnd; ++I) {
// We don't need to check the identifier namespace, because
// operator names can only be ordinary identifiers.

Просмотреть файл

@ -32,9 +32,7 @@ Sema::DeclTy *Sema::isTemplateName(IdentifierInfo &II, Scope *S,
return 0;
DC = static_cast<DeclContext*>(SS->getScopeRep());
}
Decl *IIDecl = DC ?
LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC, false) :
LookupDeclInScope(&II, Decl::IDNS_Ordinary, S, false);
Decl *IIDecl = LookupParsedName(S, SS, &II, LookupOrdinaryName);
if (IIDecl) {
// FIXME: We need to represent templates via some kind of
@ -96,7 +94,7 @@ Sema::DeclTy *Sema::ActOnTypeParameter(Scope *S, bool Typename,
bool Invalid = false;
if (ParamName) {
Decl *PrevDecl = LookupDeclInScope(ParamName, Decl::IDNS_Tag, S);
Decl *PrevDecl = LookupName(S, ParamName, LookupTagName);
if (PrevDecl && PrevDecl->isTemplateParameter())
Invalid = Invalid || DiagnoseTemplateParameterShadow(ParamNameLoc,
PrevDecl);
@ -132,7 +130,7 @@ Sema::DeclTy *Sema::ActOnNonTypeTemplateParameter(Scope *S, Declarator &D,
IdentifierInfo *ParamName = D.getIdentifier();
if (ParamName) {
Decl *PrevDecl = LookupDeclInScope(ParamName, Decl::IDNS_Tag, S);
Decl *PrevDecl = LookupName(S, ParamName, LookupTagName);
if (PrevDecl && PrevDecl->isTemplateParameter())
Invalid = Invalid || DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
PrevDecl);