[cfe-commits] r63320 - in /cfe/trunk/lib/Sema: Sema.h SemaDecl.cpp

Steve Naroff snaroff at apple.com
Thu Jan 29 10:09:31 PST 2009


Author: snaroff
Date: Thu Jan 29 12:09:31 2009
New Revision: 63320

URL: http://llvm.org/viewvc/llvm-project?rev=63320&view=rev
Log:
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.

Modified:
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=63320&r1=63319&r2=63320&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Thu Jan 29 12:09:31 2009
@@ -782,7 +782,7 @@
   LookupResult LookupParsedName(Scope *S, const CXXScopeSpec &SS, 
                                 DeclarationName Name, LookupCriteria Criteria);
   LookupResult LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S,
-                                 bool LookInParent = true);
+                          bool LookInParent = true);
   LookupResult LookupDeclInContext(DeclarationName Name, unsigned NSI,
                           const DeclContext *LookupCtx,
                           bool LookInParent = true);

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=63320&r1=63319&r2=63320&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jan 29 12:09:31 2009
@@ -39,31 +39,32 @@
       return 0;
     DC = static_cast<DeclContext*>(SS->getScopeRep());
   }
-  LookupResult Result = DC ? 
-                 LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC) :
-                 LookupDeclInScope(&II, Decl::IDNS_Ordinary, S);
-                   
   Decl *IIDecl = 0;
+  
+  LookupResult Result =  DC ? LookupDeclInContext(&II, Decl::IDNS_Ordinary, DC) :
+                              LookupDeclInScope(&II, Decl::IDNS_Ordinary, S);
+                 
   switch (Result.getKind()) {
-  case LookupResult::NotFound:
-  case LookupResult::FoundOverloaded:
-  case LookupResult::AmbiguousBaseSubobjectTypes:
-  case LookupResult::AmbiguousBaseSubobjects:
-    // FIXME: In the event of an ambiguous lookup, we could visit all of
-    // the entities found to determine whether they are all types. This
-    // might provide better diagnostics.
-    return 0;
-
-  case LookupResult::Found:
-    IIDecl = Result.getAsDecl();
-    break;
+    case LookupResult::NotFound:
+    case LookupResult::FoundOverloaded:
+    case LookupResult::AmbiguousBaseSubobjectTypes:
+    case LookupResult::AmbiguousBaseSubobjects:
+      // FIXME: In the event of an ambiguous lookup, we could visit all of
+      // 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 (isa<TypedefDecl>(IIDecl) || 
-      isa<ObjCInterfaceDecl>(IIDecl) ||
-      isa<TagDecl>(IIDecl) ||
-      isa<TemplateTypeParmDecl>(IIDecl))
-    return IIDecl;
+  if (IIDecl) {
+    if (isa<TypedefDecl>(IIDecl) || 
+        isa<ObjCInterfaceDecl>(IIDecl) ||
+        isa<TagDecl>(IIDecl) ||
+        isa<TemplateTypeParmDecl>(IIDecl))
+      return IIDecl;
+  }
   return 0;
 }
 
@@ -265,19 +266,85 @@
 Sema::LookupResult
 Sema::LookupDeclInScope(DeclarationName Name, unsigned NSI, Scope *S,
                         bool LookInParent) {
-  LookupCriteria::NameKind Kind;
+  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) {
-    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;
+    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());
+    }
   }
-  // Unqualified lookup
-  return LookupName(S, Name, 
-                    LookupCriteria(Kind, !LookInParent,
-                                   getLangOptions().CPlusPlus));
+  return LookupResult::CreateLookupResult(Context, 0);
 }
 
 Sema::LookupResult
@@ -2898,9 +2965,8 @@
   } 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





More information about the cfe-commits mailing list