Hack Sema::LookupDeclInScope() to avoid calling Sema::LookupName() when parsing C/ObjC.

This results in a 1.7% improvement for "Cocoa.h". If we can figure out how to return a "Decl *", rather than a Sema::LookupResult(), we will likely bump the speedup from 1.7%->2.5%. I verified this, however couldn't get it to work without breaking a fair number of C++ test cases. Will discuss with Doug offline.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63320 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Steve Naroff 2009-01-29 18:09:31 +00:00
Родитель 95effa1e2d
Коммит a51890346e
2 изменённых файлов: 103 добавлений и 37 удалений

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

@ -39,11 +39,11 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, Scope *S,
return 0;
DC = static_cast<DeclContext*>(SS->getScopeRep());
}
LookupResult Result = DC ?
LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC) :
Decl *IIDecl = 0;
LookupResult Result = DC ? LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC) :
LookupDeclInScope(&II, Decl::IDNS_Ordinary, S);
Decl *IIDecl = 0;
switch (Result.getKind()) {
case LookupResult::NotFound:
case LookupResult::FoundOverloaded:
@ -53,17 +53,18 @@ Sema::TypeTy *Sema::getTypeName(IdentifierInfo &II, Scope *S,
// the entities found to determine whether they are all types. This
// might provide better diagnostics.
return 0;
case LookupResult::Found:
IIDecl = Result.getAsDecl();
break;
}
if (IIDecl) {
if (isa<TypedefDecl>(IIDecl) ||
isa<ObjCInterfaceDecl>(IIDecl) ||
isa<TagDecl>(IIDecl) ||
isa<TemplateTypeParmDecl>(IIDecl))
return IIDecl;
}
return 0;
}
@ -265,6 +266,7 @@ Scope *Sema::getNonFieldDeclScope(Scope *S) {
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;
@ -279,6 +281,71 @@ Sema::LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S,
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,
@ -2898,9 +2965,8 @@ 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.
PrevDecl = dyn_cast_or_null<NamedDecl>(LookupDeclInScope(Name,
Decl::IDNS_Tag,S)
.getAsDecl());
Decl *D = LookupDeclInScope(Name, Decl::IDNS_Tag, S);
PrevDecl = dyn_cast_or_null<NamedDecl>(D);
if (!getLangOptions().CPlusPlus && TK != TK_Reference) {
// FIXME: This makes sure that we ignore the contexts associated