]> granicus.if.org Git - clang/commitdiff
Pull Sema::isAcceptableLookupResult into SemaLookup. Extract the criteria into
authorJohn McCall <rjmccall@apple.com>
Fri, 18 Dec 2009 10:40:03 +0000 (10:40 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 18 Dec 2009 10:40:03 +0000 (10:40 +0000)
different functions and pick the function at lookup initialization time.
In theory we could actually divide the criteria functions into N different
functions for the N cases, but it's so not worth it.

Among other things, lets us invoke LookupQualifiedName without recomputing
IDNS info every time.

Do some refactoring in SemaDecl to avoid an awkward special case in LQN
that was only necessary for redeclaration testing for anonymous structs/unions ---
which could be done more efficiently with a scoped lookup anyway.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91676 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/Lookup.h
lib/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaLookup.cpp
test/SemaCXX/nested-name-spec.cpp

index 78f79eac2ba113470f9905189a15e033f0b7e5b3..6b7e28ce3dcc58d711e0747f8fa40768c9e5a061 100644 (file)
@@ -121,6 +121,8 @@ public:
   typedef llvm::SmallVector<NamedDecl*, 4> DeclsTy;
   typedef DeclsTy::const_iterator iterator;
 
+  typedef bool (*ResultFilter)(NamedDecl*, unsigned IDNS);
+
   LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc,
                Sema::LookupNameKind LookupKind,
                Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration)
@@ -130,11 +132,14 @@ public:
       Name(Name),
       NameLoc(NameLoc),
       LookupKind(LookupKind),
+      IsAcceptableFn(0),
       IDNS(0),
       Redecl(Redecl != Sema::NotForRedeclaration),
       HideTags(true),
       Diagnose(Redecl == Sema::NotForRedeclaration)
-  {}
+  {
+    configure();
+  }
 
   /// Creates a temporary lookup result, initializing its core data
   /// using the information from another result.  Diagnostics are always
@@ -146,6 +151,7 @@ public:
       Name(Other.Name),
       NameLoc(Other.NameLoc),
       LookupKind(Other.LookupKind),
+      IsAcceptableFn(Other.IsAcceptableFn),
       IDNS(Other.IDNS),
       Redecl(Other.Redecl),
       HideTags(Other.HideTags),
@@ -178,17 +184,6 @@ public:
     HideTags = Hide;
   }
 
-  /// The identifier namespace of this lookup.  This information is
-  /// private to the lookup routines.
-  unsigned getIdentifierNamespace() const {
-    assert(IDNS);
-    return IDNS;
-  }
-
-  void setIdentifierNamespace(unsigned NS) {
-    IDNS = NS;
-  }
-
   bool isAmbiguous() const {
     return getResultKind() == Ambiguous;
   }
@@ -231,7 +226,19 @@ public:
     return Paths;
   }
 
-  /// \brief Add a declaration to these results.
+  /// \brief Tests whether the given declaration is acceptable.
+  bool isAcceptableDecl(NamedDecl *D) const {
+    assert(IsAcceptableFn);
+    return IsAcceptableFn(D, IDNS);
+  }
+
+  /// \brief Returns the identifier namespace mask for this lookup.
+  unsigned getIdentifierNamespace() const {
+    return IDNS;
+  }
+
+  /// \brief Add a declaration to these results.  Does not test the
+  /// acceptance criteria.
   void addDecl(NamedDecl *D) {
     Decls.push_back(D);
     ResultKind = Found;
@@ -334,6 +341,7 @@ public:
   void clear(Sema::LookupNameKind Kind) {
     clear();
     LookupKind = Kind;
+    configure();
   }
 
   void print(llvm::raw_ostream &);
@@ -438,6 +446,7 @@ private:
   }
 
   void addDeclsFromBasePaths(const CXXBasePaths &P);
+  void configure();
 
   // Sanity checks.
   void sanity() const {
@@ -476,7 +485,9 @@ private:
   SourceLocation NameLoc;
   SourceRange NameContextRange;
   Sema::LookupNameKind LookupKind;
-  unsigned IDNS; // ill-defined until set by lookup
+  ResultFilter IsAcceptableFn; // set by configure()
+  unsigned IDNS; // set by configure()
+
   bool Redecl;
 
   /// \brief True if tag declarations should be hidden if non-tags
index 9d40a13786bb19cfa79f4e29a12803eda2d3afe5..24101c67029b78706f1e4ce97baed8fd1c7f751a 100644 (file)
@@ -613,10 +613,6 @@ public:
                                         const LookupResult &Previous,
                                         Scope *S);
   void DiagnoseFunctionSpecifiers(Declarator& D);
-  bool CheckRedeclaration(DeclContext *DC,
-                          DeclarationName Name,
-                          SourceLocation NameLoc,
-                          unsigned Diagnostic);
   NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                     QualType R, TypeSourceInfo *TInfo,
                                     LookupResult &Previous, bool &Redeclaration);
@@ -1176,36 +1172,6 @@ private:
   bool CppLookupName(LookupResult &R, Scope *S);
 
 public:
-  /// Determines whether D is a suitable lookup result according to the
-  /// lookup criteria.
-  static bool isAcceptableLookupResult(NamedDecl *D, LookupNameKind NameKind,
-                                       unsigned IDNS) {
-    switch (NameKind) {
-    case Sema::LookupOrdinaryName:
-    case Sema::LookupTagName:
-    case Sema::LookupMemberName:
-    case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
-    case Sema::LookupUsingDeclName:
-    case Sema::LookupObjCProtocolName:
-    case Sema::LookupObjCImplementationName:
-      return D->isInIdentifierNamespace(IDNS);
-
-    case Sema::LookupOperatorName:
-      return D->isInIdentifierNamespace(IDNS) &&
-             !D->getDeclContext()->isRecord();
-
-    case Sema::LookupNestedNameSpecifierName:
-      return isa<TypedefDecl>(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag);
-
-    case Sema::LookupNamespaceName:
-      return isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D);
-    }
-
-    assert(false &&
-           "isAcceptableLookupResult always returns before this point");
-    return false;
-  }
-
   /// \brief Look up a name, looking for a single declaration.  Return
   /// null if the results were absent, ambiguous, or overloaded.
   ///
index 5bb168068f5f3410edd7e6503747f7fe920c4ded..587c141b4b65e144eb32995ad603ba670bccd8d5 100644 (file)
@@ -1519,29 +1519,27 @@ Sema::DeclPtrTy Sema::ParsedFreeStandingDeclSpec(Scope *S, DeclSpec &DS) {
   return DeclPtrTy::make(Tag);
 }
 
-/// We are trying to introduce the given name into the given context;
+/// We are trying to inject an anonymous member into the given scope;
 /// check if there's an existing declaration that can't be overloaded.
 ///
 /// \return true if this is a forbidden redeclaration
-bool Sema::CheckRedeclaration(DeclContext *DC,
-                              DeclarationName Name,
-                              SourceLocation NameLoc,
-                              unsigned diagnostic) {
-  LookupResult R(*this, Name, NameLoc, LookupOrdinaryName,
-                 ForRedeclaration);
-  LookupQualifiedName(R, DC);
-
-  if (R.empty()) return false;
-
-  if (R.getResultKind() == LookupResult::Found &&
-      isa<TagDecl>(R.getFoundDecl()))
+static bool CheckAnonMemberRedeclaration(Sema &SemaRef,
+                                         Scope *S,
+                                         DeclarationName Name,
+                                         SourceLocation NameLoc,
+                                         unsigned diagnostic) {
+  LookupResult R(SemaRef, Name, NameLoc, Sema::LookupMemberName,
+                 Sema::ForRedeclaration);
+  if (!SemaRef.LookupName(R, S)) return false;
+
+  if (R.getAsSingle<TagDecl>())
     return false;
 
   // Pick a representative declaration.
-  NamedDecl *PrevDecl = (*R.begin())->getUnderlyingDecl();
+  NamedDecl *PrevDecl = R.getRepresentativeDecl()->getUnderlyingDecl();
 
-  Diag(NameLoc, diagnostic) << Name;
-  Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+  SemaRef.Diag(NameLoc, diagnostic) << Name;
+  SemaRef.Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
 
   return true;
 }
@@ -1573,8 +1571,8 @@ bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
                                FEnd = AnonRecord->field_end();
        F != FEnd; ++F) {
     if ((*F)->getDeclName()) {
-      if (CheckRedeclaration(Owner, (*F)->getDeclName(),
-                             (*F)->getLocation(), diagKind)) {
+      if (CheckAnonMemberRedeclaration(*this, S, (*F)->getDeclName(),
+                                       (*F)->getLocation(), diagKind)) {
         // C++ [class.union]p2:
         //   The names of the members of an anonymous union shall be
         //   distinct from the names of any other entity in the
index 724e2fc1e4f586c7c312783233181dbfe7770ed8..5e60cc8727aa8bfed53a9c49d497724110b9d588 100644 (file)
@@ -192,23 +192,71 @@ namespace {
   };
 }
 
+static bool IsAcceptableIDNS(NamedDecl *D, unsigned IDNS) {
+  return D->isInIdentifierNamespace(IDNS);
+}
+
+static bool IsAcceptableOperatorName(NamedDecl *D, unsigned IDNS) {
+  return D->isInIdentifierNamespace(IDNS) &&
+    !D->getDeclContext()->isRecord();
+}
+
+static bool IsAcceptableNestedNameSpecifierName(NamedDecl *D, unsigned IDNS) {
+  return isa<TypedefDecl>(D) || D->isInIdentifierNamespace(Decl::IDNS_Tag);
+}
+
+static bool IsAcceptableNamespaceName(NamedDecl *D, unsigned IDNS) {
+  return isa<NamespaceDecl>(D) || isa<NamespaceAliasDecl>(D);
+}
+
+/// Gets the default result filter for the given lookup.
+static inline
+LookupResult::ResultFilter getResultFilter(Sema::LookupNameKind NameKind) {
+  switch (NameKind) {
+  case Sema::LookupOrdinaryName:
+  case Sema::LookupTagName:
+  case Sema::LookupMemberName:
+  case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
+  case Sema::LookupUsingDeclName:
+  case Sema::LookupObjCProtocolName:
+  case Sema::LookupObjCImplementationName:
+    return &IsAcceptableIDNS;
+
+  case Sema::LookupOperatorName:
+    return &IsAcceptableOperatorName;
+
+  case Sema::LookupNestedNameSpecifierName:
+    return &IsAcceptableNestedNameSpecifierName;
+
+  case Sema::LookupNamespaceName:
+    return &IsAcceptableNamespaceName;
+  }
+
+  llvm_unreachable("unkknown lookup kind");
+  return 0;
+}
+
 // Retrieve the set of identifier namespaces that correspond to a
 // specific kind of name lookup.
-inline unsigned
-getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind,
-                                          bool CPlusPlus) {
+static inline unsigned getIDNS(Sema::LookupNameKind NameKind,
+                               bool CPlusPlus,
+                               bool Redeclaration) {
   unsigned IDNS = 0;
   switch (NameKind) {
   case Sema::LookupOrdinaryName:
   case Sema::LookupOperatorName:
   case Sema::LookupRedeclarationWithLinkage:
     IDNS = Decl::IDNS_Ordinary;
-    if (CPlusPlus)
+    if (CPlusPlus) {
       IDNS |= Decl::IDNS_Tag | Decl::IDNS_Member;
+      if (Redeclaration) IDNS |= Decl::IDNS_TagFriend | Decl::IDNS_OrdinaryFriend;
+    }
     break;
 
   case Sema::LookupTagName:
     IDNS = Decl::IDNS_Tag;
+    if (CPlusPlus && Redeclaration)
+      IDNS |= Decl::IDNS_TagFriend;
     break;
 
   case Sema::LookupMemberName:
@@ -238,6 +286,13 @@ getIdentifierNamespacesFromLookupNameKind(Sema::LookupNameKind NameKind,
   return IDNS;
 }
 
+void LookupResult::configure() {
+  IDNS = getIDNS(LookupKind,
+                 SemaRef.getLangOptions().CPlusPlus,
+                 isForRedeclaration());
+  IsAcceptableFn = getResultFilter(LookupKind);
+}
+
 // Necessary because CXXBasePaths is not complete in Sema.h
 void LookupResult::deletePaths(CXXBasePaths *Paths) {
   delete Paths;
@@ -377,8 +432,7 @@ static bool LookupDirect(LookupResult &R, const DeclContext *DC) {
 
   DeclContext::lookup_const_iterator I, E;
   for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I)
-    if (Sema::isAcceptableLookupResult(*I, R.getLookupKind(),
-                                       R.getIdentifierNamespace()))
+    if (R.isAcceptableDecl(*I))
       R.addDecl(*I), Found = true;
 
   return Found;
@@ -424,19 +478,7 @@ static DeclContext *findOuterContext(Scope *S) {
 }
 
 bool Sema::CppLookupName(LookupResult &R, Scope *S) {
-  assert(getLangOptions().CPlusPlus &&
-         "Can perform only C++ lookup");
-  LookupNameKind NameKind = R.getLookupKind();
-  unsigned IDNS
-    = getIdentifierNamespacesFromLookupNameKind(NameKind, /*CPlusPlus*/ true);
-
-  // If we're testing for redeclarations, also look in the friend namespaces.
-  if (R.isForRedeclaration()) {
-    if (IDNS & Decl::IDNS_Tag) IDNS |= Decl::IDNS_TagFriend;
-    if (IDNS & Decl::IDNS_Ordinary) IDNS |= Decl::IDNS_OrdinaryFriend;
-  }
-
-  R.setIdentifierNamespace(IDNS);
+  assert(getLangOptions().CPlusPlus && "Can perform only C++ lookup");
 
   DeclarationName Name = R.getLookupName();
 
@@ -467,7 +509,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
     // Check whether the IdResolver has anything in this scope.
     bool Found = false;
     for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
-      if (isAcceptableLookupResult(*I, NameKind, IDNS)) {
+      if (R.isAcceptableDecl(*I)) {
         Found = true;
         R.addDecl(*I);
       }
@@ -531,7 +573,7 @@ bool Sema::CppLookupName(LookupResult &R, Scope *S) {
     // Check whether the IdResolver has anything in this scope.
     bool Found = false;
     for (; I != IEnd && S->isDeclScope(DeclPtrTy::make(*I)); ++I) {
-      if (isAcceptableLookupResult(*I, NameKind, IDNS)) {
+      if (R.isAcceptableDecl(*I)) {
         // 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
@@ -597,47 +639,18 @@ bool Sema::LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation) {
   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::LookupOperatorName:
-    case Sema::LookupNestedNameSpecifierName:
-    case Sema::LookupNamespaceName:
-    case Sema::LookupUsingDeclName:
-      assert(false && "C does not perform these kinds of name lookup");
-      break;
-
-    case Sema::LookupRedeclarationWithLinkage:
+    if (NameKind == Sema::LookupRedeclarationWithLinkage) {
       // Find the nearest non-transparent declaration scope.
       while (!(S->getFlags() & Scope::DeclScope) ||
              (S->getEntity() &&
               static_cast<DeclContext *>(S->getEntity())
                 ->isTransparentContext()))
         S = S->getParent();
-      IDNS = Decl::IDNS_Ordinary;
-      break;
-
-    case Sema::LookupObjCProtocolName:
-      IDNS = Decl::IDNS_ObjCProtocol;
-      break;
-
-    case Sema::LookupObjCImplementationName:
-      IDNS = Decl::IDNS_ObjCImplementation;
-      break;
-
     }
 
+    unsigned IDNS = R.getIdentifierNamespace();
+
     // 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
@@ -864,17 +877,6 @@ bool Sema::LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx) {
   if (!R.getLookupName())
     return false;
 
-  // If we're performing qualified name lookup (e.g., lookup into a
-  // struct), find fields as part of ordinary name lookup.
-  LookupNameKind NameKind = R.getLookupKind();
-  unsigned IDNS
-    = getIdentifierNamespacesFromLookupNameKind(NameKind,
-                                                getLangOptions().CPlusPlus);
-  if (NameKind == LookupOrdinaryName)
-    IDNS |= Decl::IDNS_Member;
-
-  R.setIdentifierNamespace(IDNS);
-
   // Make sure that the declaration context is complete.
   assert((!isa<TagDecl>(LookupCtx) ||
           LookupCtx->isDependentContext() ||
index 223e6ff6689c77f8d430ee89176f65e8cd1ce67a..dc8eda59942300c5e7e18c2d1b28fb9c84ebd3db 100644 (file)
@@ -191,6 +191,19 @@ foo<somens:a> a2;  // expected-error {{unexpected ':' in nested name specifier}}
 
 somens::a a3 = a2; // expected-error {{cannot initialize 'a3' with an lvalue of type 'foo<somens::a>'}}
 
+// typedefs and using declarations.
+namespace test1 {
+  namespace ns {
+    class Counter { static int count; };
+    typedef Counter counter;
+  }
+  using ns::counter;
 
-
-
+  class Test {
+    void test1() {
+      counter c;
+      c.count++;
+      counter::count++;
+    }
+  };
+}