Add iterators to LookupResult, allowing one to iterate over the
non-ambiguous name lookup results without allocating any memory, e.g.,
for sets of overloaded functions.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63549 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 6036205..b0a0a5e 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -735,6 +735,55 @@
     Decl* getAsDecl() const;
 
     BasePaths *getBasePaths() const;
+
+    /// \brief Iterate over the results of name lookup.
+    ///
+    /// The @c iterator class provides iteration over the results of a
+    /// non-ambiguous name lookup.
+    class iterator {
+      /// The LookupResult structure we're iterating through.
+      LookupResult *Result;
+
+      /// The current position of this iterator within the sequence of
+      /// results. This value will have the same representation as the
+      /// @c First field in the LookupResult structure.
+      mutable uintptr_t Current;
+
+    public:
+      typedef Decl *                     value_type;
+      typedef Decl *                     reference;
+      typedef Decl *                     pointer;
+      typedef std::ptrdiff_t             difference_type;
+      typedef std::forward_iterator_tag  iterator_category;
+
+      iterator() : Result(0), Current(0) { }
+
+      iterator(LookupResult *Res, uintptr_t Cur) : Result(Res), Current(Cur) { }
+
+      reference operator*() const;
+
+      pointer operator->() const { return **this; }
+
+      iterator &operator++();
+
+      iterator operator++(int) {
+        iterator tmp(*this);
+        ++(*this);
+        return tmp;
+      }
+
+      friend inline bool operator==(iterator const& x, iterator const& y) {
+        return x.Current == y.Current;
+      }
+
+      friend inline bool operator!=(iterator const& x, iterator const& y) {
+        return x.Current != y.Current;
+      }
+    };
+    friend class iterator;
+
+    iterator begin();
+    iterator end();
   };
 
   /// Determines whether D is a suitable lookup result according to the
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index fe7ab92..d03879e 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1666,35 +1666,22 @@
         << D.getCXXScopeSpec().getRange();
       InvalidDecl = true;
         
-      PrevDecl = LookupQualifiedName(DC, Name, LookupOrdinaryName);
-      if (!PrevDecl) {
-        // Nothing to suggest.
-      } else if (OverloadedFunctionDecl *Ovl 
-                 = dyn_cast<OverloadedFunctionDecl>(PrevDecl)) {
-        for (OverloadedFunctionDecl::function_iterator 
-               Func = Ovl->function_begin(),
-               FuncEnd = Ovl->function_end();
-             Func != FuncEnd; ++Func) {
-          if (isNearlyMatchingMemberFunction(Context, *Func, NewFD))
-            Diag((*Func)->getLocation(), diag::note_member_def_close_match);
-            
-        }
-      } else if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(PrevDecl)) {
-        // Suggest this no matter how mismatched it is; it's the only
-        // thing we have.
-        unsigned diag;
-        if (isNearlyMatchingMemberFunction(Context, Method, NewFD))
-          diag = diag::note_member_def_close_match;
-        else if (Method->getBody())
-          diag = diag::note_previous_definition;
-        else
-          diag = diag::note_previous_declaration;
-        Diag(Method->getLocation(), diag);
+      LookupResult Prev = LookupQualifiedName(DC, Name, LookupOrdinaryName, 
+                                              true);
+      assert(!Prev.isAmbiguous() && 
+             "Cannot have an ambiguity in previous-declaration lookup");
+      for (LookupResult::iterator Func = Prev.begin(), FuncEnd = Prev.end();
+           Func != FuncEnd; ++Func) {
+        if (isa<CXXMethodDecl>(*Func) &&
+            isNearlyMatchingMemberFunction(Context, cast<FunctionDecl>(*Func),
+                                           NewFD))
+          Diag((*Func)->getLocation(), diag::note_member_def_close_match);
       }
-        
+ 
       PrevDecl = 0;
     }
   }
+
   // Handle attributes. We need to have merged decls when handling attributes
   // (for example to check for conflicts, etc).
   ProcessDeclAttributes(NewFD, D);
diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp
index 8bc3496..5ef6de3 100644
--- a/lib/Sema/SemaInit.cpp
+++ b/lib/Sema/SemaInit.cpp
@@ -1342,6 +1342,8 @@
     //   [...] A program that calls for default-initialization or
     //   value-initialization of an entity of reference type is
     //   ill-formed. [...]
+    // FIXME: Once we have code that goes through this path, add an
+    // actual diagnostic :)
   }
 
   return false;
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index abb265d..da2deec 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -181,6 +181,66 @@
   return reinterpret_cast<BasePaths *>(First);
 }
 
+Sema::LookupResult::iterator::reference 
+Sema::LookupResult::iterator::operator*() const {
+  switch (Result->StoredKind) {
+  case SingleDecl:
+    return reinterpret_cast<Decl*>(Current);
+
+  case OverloadedDeclFromIdResolver:
+    return *IdentifierResolver::iterator::getFromOpaqueValue(Current);
+
+  case OverloadedDeclFromDeclContext:
+    return *reinterpret_cast<DeclContext::lookup_iterator>(Current);
+
+  case AmbiguousLookup:
+    assert(false && "Cannot look into ambiguous lookup results");
+    break;
+  }
+
+  return 0;
+}
+
+Sema::LookupResult::iterator& Sema::LookupResult::iterator::operator++() {
+  switch (Result->StoredKind) {
+  case SingleDecl:
+    Current = reinterpret_cast<uintptr_t>((Decl*)0);
+    break;
+
+  case OverloadedDeclFromIdResolver: {
+    IdentifierResolver::iterator I 
+      = IdentifierResolver::iterator::getFromOpaqueValue(Current);
+    ++I;
+    Current = I.getAsOpaqueValue();
+    break;
+  }
+
+  case OverloadedDeclFromDeclContext: {
+    DeclContext::lookup_iterator I 
+      = reinterpret_cast<DeclContext::lookup_iterator>(Current);
+    ++I;
+    Current = reinterpret_cast<uintptr_t>(I);
+    break;
+  }
+
+  case AmbiguousLookup:
+    assert(false && "Cannot look into ambiguous lookup results");
+    break;
+  }
+
+  return *this;
+}
+
+Sema::LookupResult::iterator Sema::LookupResult::begin() {
+  assert(StoredKind != AmbiguousLookup && "Lookup into an ambiguous result");
+  return iterator(this, First);
+}
+
+Sema::LookupResult::iterator Sema::LookupResult::end() {
+  assert(StoredKind != AmbiguousLookup && "Lookup into an ambiguous result");
+  return iterator(this, Last);
+}
+
 // Retrieve the set of identifier namespaces that correspond to a
 // specific kind of name lookup.
 inline unsigned