[cfe-commits] r89263 - in /cfe/trunk: lib/Sema/Lookup.h lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaOverload.cpp lib/Sema/SemaTemplate.cpp lib/Sema/SemaTemplateInstantiateDecl.cpp test/SemaCXX/using-directive.cpp

John McCall rjmccall at apple.com
Wed Nov 18 14:49:29 PST 2009


Author: rjmccall
Date: Wed Nov 18 16:49:29 2009
New Revision: 89263

URL: http://llvm.org/viewvc/llvm-project?rev=89263&view=rev
Log:
Overhaul previous-declaration and overload checking to work on lookup results
rather than NamedDecl*.  This is a major step towards eliminating
OverloadedFunctionDecl.


Modified:
    cfe/trunk/lib/Sema/Lookup.h
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/test/SemaCXX/using-directive.cpp

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

==============================================================================
--- cfe/trunk/lib/Sema/Lookup.h (original)
+++ cfe/trunk/lib/Sema/Lookup.h Wed Nov 18 16:49:29 2009
@@ -201,6 +201,13 @@
     return getResultKind() == Ambiguous;
   }
 
+  /// Determines if this names a single result which is not an
+  /// unresolved value using decl.  If so, it is safe to call
+  /// getFoundDecl().
+  bool isSingleResult() const {
+    return getResultKind() == Found;
+  }
+
   LookupResultKind getResultKind() const {
     sanity();
     return ResultKind;
@@ -248,12 +255,24 @@
     Decls.set_size(N);
   }
 
-  /// \brief Resolves the kind of the lookup, possibly hiding decls.
+  /// \brief Resolves the result kind of the lookup, possibly hiding
+  /// decls.
   ///
   /// This should be called in any environment where lookup might
   /// generate multiple lookup results.
   void resolveKind();
 
+  /// \brief Re-resolves the result kind of the lookup after a set of
+  /// removals has been performed.
+  void resolveKindAfterFilter() {
+    if (Decls.empty())
+      ResultKind = NotFound;
+    else {
+      ResultKind = Found;
+      resolveKind();
+    }
+  }
+
   /// \brief Fetch this as an unambiguous single declaration
   /// (possibly an overloaded one).
   ///
@@ -272,6 +291,12 @@
     return Decls[0]->getUnderlyingDecl();
   }
 
+  /// Fetches a representative decl.  Useful for lazy diagnostics.
+  NamedDecl *getRepresentativeDecl() const {
+    assert(!Decls.empty() && "cannot get representative of empty set");
+    return Decls[0];
+  }
+
   /// \brief Asks if the result is a single tag decl.
   bool isSingleTagDecl() const {
     return getResultKind() == Found && isa<TagDecl>(getFoundDecl());
@@ -337,6 +362,65 @@
     return NameLoc;
   }
 
+  /// A class for iterating through a result set and possibly
+  /// filtering out results.  The results returned are possibly
+  /// sugared.
+  class Filter {
+    LookupResult &Results;
+    unsigned I;
+    bool ErasedAny;
+#ifndef NDEBUG
+    bool CalledDone;
+#endif
+    
+    friend class LookupResult;
+    Filter(LookupResult &Results)
+      : Results(Results), I(0), ErasedAny(false)
+#ifndef NDEBUG
+      , CalledDone(false)
+#endif
+    {}
+
+  public:
+#ifndef NDEBUG
+    ~Filter() {
+      assert(CalledDone &&
+             "LookupResult::Filter destroyed without done() call");
+    }
+#endif
+
+    bool hasNext() const {
+      return I != Results.Decls.size();
+    }
+
+    NamedDecl *next() {
+      assert(I < Results.Decls.size() && "next() called on empty filter");
+      return Results.Decls[I++];
+    }
+
+    /// Erase the last element returned from this iterator.
+    void erase() {
+      Results.Decls[--I] = Results.Decls.back();
+      Results.Decls.pop_back();
+      ErasedAny = true;
+    }
+
+    void done() {
+#ifndef NDEBUG
+      assert(!CalledDone && "done() called twice");
+      CalledDone = true;
+#endif
+
+      if (ErasedAny)
+        Results.resolveKindAfterFilter();
+    }
+  };
+
+  /// Create a filter for this result set.
+  Filter makeFilter() {
+    return Filter(*this);
+  }
+
 private:
   void diagnose() {
     if (isAmbiguous())

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

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Nov 18 16:49:29 2009
@@ -548,27 +548,32 @@
   DeclPtrTy HandleDeclarator(Scope *S, Declarator &D,
                              MultiTemplateParamsArg TemplateParameterLists,
                              bool IsFunctionDefinition);
-  void RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl,
+  void RegisterLocallyScopedExternCDecl(NamedDecl *ND,
+                                        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, DeclaratorInfo *DInfo,
-                                    NamedDecl* PrevDecl, bool &Redeclaration);
+                                    LookupResult &Previous, bool &Redeclaration);
   NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                      QualType R, DeclaratorInfo *DInfo,
-                                     NamedDecl* PrevDecl,
+                                     LookupResult &Previous,
                                      MultiTemplateParamsArg TemplateParamLists,
                                      bool &Redeclaration);
-  void CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
+  void CheckVariableDeclaration(VarDecl *NewVD, LookupResult &Previous,
                                 bool &Redeclaration);
   NamedDecl* ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                                      QualType R, DeclaratorInfo *DInfo,
-                                     NamedDecl* PrevDecl,
+                                     LookupResult &Previous,
                                      MultiTemplateParamsArg TemplateParamLists,
                                      bool IsFunctionDefinition,
                                      bool &Redeclaration);
   void AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
-  void CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+  void CheckFunctionDeclaration(FunctionDecl *NewFD, LookupResult &Previous,
                                 bool IsExplicitSpecialization,
                                 bool &Redeclaration,
                                 bool &OverloadableAttrRequired);
@@ -780,15 +785,17 @@
   /// Subroutines of ActOnDeclarator().
   TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T,
                                 DeclaratorInfo *DInfo);
-  void MergeTypeDefDecl(TypedefDecl *New, Decl *Old);
+  void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls);
   bool MergeFunctionDecl(FunctionDecl *New, Decl *Old);
   bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old);
-  void MergeVarDecl(VarDecl *New, Decl *Old);
+  void MergeVarDecl(VarDecl *New, LookupResult &OldDecls);
   bool MergeCXXFunctionDecl(FunctionDecl *New, FunctionDecl *Old);
 
   /// C++ Overloading.
-  bool IsOverload(FunctionDecl *New, Decl* OldD,
-                  OverloadedFunctionDecl::function_iterator &MatchedDecl);
+  bool IsOverload(FunctionDecl *New, LookupResult &OldDecls,
+                  NamedDecl *&OldDecl);
+  bool IsOverload(FunctionDecl *New, FunctionDecl *Old);
+
   ImplicitConversionSequence
   TryImplicitConversion(Expr* From, QualType ToType,
                         bool SuppressUserConversions,
@@ -2325,8 +2332,8 @@
                             const TemplateArgumentLoc *ExplicitTemplateArgs,
                                            unsigned NumExplicitTemplateArgs,
                                            SourceLocation RAngleLoc,
-                                           NamedDecl *&PrevDecl);
-  bool CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl);
+                                           LookupResult &Previous);
+  bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous);
     
   virtual DeclResult
   ActOnExplicitInstantiation(Scope *S,

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Nov 18 16:49:29 2009
@@ -311,14 +311,16 @@
 /// extension, in C when the previous function is already an
 /// overloaded function declaration or has the "overloadable"
 /// attribute.
-static bool AllowOverloadingOfFunction(Decl *PrevDecl, ASTContext &Context) {
+static bool AllowOverloadingOfFunction(LookupResult &Previous,
+                                       ASTContext &Context) {
   if (Context.getLangOptions().CPlusPlus)
     return true;
 
-  if (isa<OverloadedFunctionDecl>(PrevDecl))
+  if (Previous.getResultKind() == LookupResult::FoundOverloaded)
     return true;
 
-  return PrevDecl->getAttr<OverloadableAttr>() != 0;
+  return (Previous.getResultKind() == LookupResult::Found
+          && Previous.getFoundDecl()->hasAttr<OverloadableAttr>());
 }
 
 /// Add this decl to the scope shadowed decl chains.
@@ -396,6 +398,48 @@
   return IdResolver.isDeclInScope(D, Ctx, Context, S);
 }
 
+static bool isOutOfScopePreviousDeclaration(NamedDecl *,
+                                            DeclContext*,
+                                            ASTContext&);
+
+/// Filters out lookup results that don't fall within the given scope
+/// as determined by isDeclInScope.
+static void FilterLookupForScope(Sema &SemaRef, LookupResult &R,
+                                 DeclContext *Ctx, Scope *S,
+                                 bool ConsiderLinkage) {
+  LookupResult::Filter F = R.makeFilter();
+  while (F.hasNext()) {
+    NamedDecl *D = F.next();
+
+    if (SemaRef.isDeclInScope(D, Ctx, S))
+      continue;
+
+    if (ConsiderLinkage &&
+        isOutOfScopePreviousDeclaration(D, Ctx, SemaRef.Context))
+      continue;
+    
+    F.erase();
+  }
+
+  F.done();
+}
+
+static bool isUsingDecl(NamedDecl *D) {
+  return isa<UsingShadowDecl>(D) ||
+         isa<UnresolvedUsingTypenameDecl>(D) ||
+         isa<UnresolvedUsingValueDecl>(D);
+}
+
+/// Removes using shadow declarations from the lookup results.
+static void RemoveUsingDecls(LookupResult &R) {
+  LookupResult::Filter F = R.makeFilter();
+  while (F.hasNext())
+    if (isUsingDecl(F.next()))
+      F.erase();
+
+  F.done();
+}
+
 static bool ShouldDiagnoseUnusedDecl(const NamedDecl *D) {
   if (D->isUsed() || D->hasAttr<UnusedAttr>())
     return false;
@@ -572,11 +616,10 @@
 /// how to resolve this situation, merging decls or emitting
 /// diagnostics as appropriate. If there was an error, set New to be invalid.
 ///
-void Sema::MergeTypeDefDecl(TypedefDecl *New, Decl *OldD) {
-  // If either decl is known invalid already, set the new one to be invalid and
-  // don't bother doing any merging checks.
-  if (New->isInvalidDecl() || OldD->isInvalidDecl())
-    return New->setInvalidDecl();
+void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
+  // If the new decl is known invalid already, don't bother doing any
+  // merging checks.
+  if (New->isInvalidDecl()) return;
 
   // Allow multiple definitions for ObjC built-in typedefs.
   // FIXME: Verify the underlying types are equivalent!
@@ -611,16 +654,25 @@
     }
     // Fall through - the typedef name was not a builtin type.
   }
+
   // Verify the old decl was also a type.
-  TypeDecl *Old = dyn_cast<TypeDecl>(OldD);
-  if (!Old) {
+  TypeDecl *Old = 0;
+  if (!OldDecls.isSingleResult() ||
+      !(Old = dyn_cast<TypeDecl>(OldDecls.getFoundDecl()))) {
     Diag(New->getLocation(), diag::err_redefinition_different_kind)
       << New->getDeclName();
+
+    NamedDecl *OldD = OldDecls.getRepresentativeDecl();
     if (OldD->getLocation().isValid())
       Diag(OldD->getLocation(), diag::note_previous_definition);
+
     return New->setInvalidDecl();
   }
 
+  // If the old declaration is invalid, just give up here.
+  if (Old->isInvalidDecl())
+    return New->setInvalidDecl();
+
   // Determine the "old" type we'll use for checking and diagnostics.
   QualType OldType;
   if (TypedefDecl *OldTypedef = dyn_cast<TypedefDecl>(Old))
@@ -977,18 +1029,19 @@
 /// FinalizeDeclaratorGroup. Unfortunately, we can't analyze tentative
 /// definitions here, since the initializer hasn't been attached.
 ///
-void Sema::MergeVarDecl(VarDecl *New, Decl *OldD) {
-  // If either decl is invalid, make sure the new one is marked invalid and
-  // don't do any other checking.
-  if (New->isInvalidDecl() || OldD->isInvalidDecl())
-    return New->setInvalidDecl();
+void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) {
+  // If the new decl is already invalid, don't do any other checking.
+  if (New->isInvalidDecl())
+    return;
 
   // Verify the old decl was also a variable.
-  VarDecl *Old = dyn_cast<VarDecl>(OldD);
-  if (!Old) {
+  VarDecl *Old = 0;
+  if (!Previous.isSingleResult() ||
+      !(Old = dyn_cast<VarDecl>(Previous.getFoundDecl()))) {
     Diag(New->getLocation(), diag::err_redefinition_different_kind)
       << New->getDeclName();
-    Diag(OldD->getLocation(), diag::note_previous_definition);
+    Diag(Previous.getRepresentativeDecl()->getLocation(),
+         diag::note_previous_definition);
     return New->setInvalidDecl();
   }
 
@@ -1403,6 +1456,33 @@
   return DeclPtrTy::make(Tag);
 }
 
+/// We are trying to introduce the given name into the given context;
+/// 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()))
+    return false;
+
+  // Pick a representative declaration.
+  NamedDecl *PrevDecl = (*R.begin())->getUnderlyingDecl();
+
+  Diag(NameLoc, diagnostic) << Name;
+  Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
+
+  return true;
+}
+
 /// InjectAnonymousStructOrUnionMembers - Inject the members of the
 /// anonymous struct or union AnonRecord into the owning context Owner
 /// and scope S. This routine will be invoked just after we realize
@@ -1421,26 +1501,21 @@
 /// structs/unions into the owning context and scope as well.
 bool Sema::InjectAnonymousStructOrUnionMembers(Scope *S, DeclContext *Owner,
                                                RecordDecl *AnonRecord) {
+  unsigned diagKind
+    = AnonRecord->isUnion() ? diag::err_anonymous_union_member_redecl
+                            : diag::err_anonymous_struct_member_redecl;
+
   bool Invalid = false;
   for (RecordDecl::field_iterator F = AnonRecord->field_begin(),
                                FEnd = AnonRecord->field_end();
        F != FEnd; ++F) {
     if ((*F)->getDeclName()) {
-      LookupResult R(*this, (*F)->getDeclName(), SourceLocation(),
-                     LookupOrdinaryName, ForRedeclaration);
-      LookupQualifiedName(R, Owner);
-      NamedDecl *PrevDecl = R.getAsSingleDecl(Context);
-      if (PrevDecl && !isa<TagDecl>(PrevDecl)) {
+      if (CheckRedeclaration(Owner, (*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
         //   scope in which the anonymous union is declared.
-        unsigned diagKind
-          = AnonRecord->isUnion()? diag::err_anonymous_union_member_redecl
-                                 : diag::err_anonymous_struct_member_redecl;
-        Diag((*F)->getLocation(), diagKind)
-          << (*F)->getDeclName();
-        Diag(PrevDecl->getLocation(), diag::note_previous_declaration);
         Invalid = true;
       } else {
         // C++ [class.union]p2:
@@ -1765,19 +1840,20 @@
   }
 
   DeclContext *DC;
-  NamedDecl *PrevDecl;
   NamedDecl *New;
 
   DeclaratorInfo *DInfo = 0;
   QualType R = GetTypeForDeclarator(D, S, &DInfo);
 
+  LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+                        ForRedeclaration);
+
   // See if this is a redefinition of a variable in the same scope.
   if (D.getCXXScopeSpec().isInvalid()) {
     DC = CurContext;
-    PrevDecl = 0;
     D.setInvalidType();
   } else if (!D.getCXXScopeSpec().isSet()) {
-    LookupNameKind NameKind = LookupOrdinaryName;
+    bool IsLinkageLookup = false;
 
     // If the declaration we're planning to build will be a function
     // or object with linkage, then look for another declaration with
@@ -1787,19 +1863,18 @@
     else if (R->isFunctionType()) {
       if (CurContext->isFunctionOrMethod() ||
           D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
-        NameKind = LookupRedeclarationWithLinkage;
+        IsLinkageLookup = true;
     } else if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern)
-      NameKind = LookupRedeclarationWithLinkage;
+      IsLinkageLookup = true;
     else if (CurContext->getLookupContext()->isTranslationUnit() &&
              D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static)
-      NameKind = LookupRedeclarationWithLinkage;
+      IsLinkageLookup = true;
 
-    DC = CurContext;
-    LookupResult R(*this, Name, D.getIdentifierLoc(), NameKind,
-                   ForRedeclaration);
+    if (IsLinkageLookup)
+      Previous.clear(LookupRedeclarationWithLinkage);
 
-    LookupName(R, S, NameKind == LookupRedeclarationWithLinkage);
-    PrevDecl = R.getAsSingleDecl(Context);
+    DC = CurContext;
+    LookupName(Previous, S, /* CreateBuiltins = */ IsLinkageLookup);
   } else { // Something like "int foo::x;"
     DC = computeDeclContext(D.getCXXScopeSpec(), true);
 
@@ -1819,10 +1894,11 @@
         RequireCompleteDeclContext(D.getCXXScopeSpec()))
       return DeclPtrTy();
     
-    LookupResult Res(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
-                     ForRedeclaration);
-    LookupQualifiedName(Res, DC);
-    PrevDecl = Res.getAsSingleDecl(Context);
+    LookupQualifiedName(Previous, DC);
+
+    // Don't consider using declarations as previous declarations for
+    // out-of-line members.
+    RemoveUsingDecls(Previous);
 
     // C++ 7.3.1.2p2:
     // Members (including explicit specializations of templates) of a named
@@ -1870,23 +1946,25 @@
     }
   }
 
-  if (PrevDecl && PrevDecl->isTemplateParameter()) {
+  if (Previous.isSingleResult() &&
+      Previous.getFoundDecl()->isTemplateParameter()) {
     // Maybe we will complain about the shadowed template parameter.
     if (!D.isInvalidType())
-      if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(), PrevDecl))
+      if (DiagnoseTemplateParameterShadow(D.getIdentifierLoc(),
+                                          Previous.getFoundDecl()))
         D.setInvalidType();
 
     // Just pretend that we didn't see the previous declaration.
-    PrevDecl = 0;
+    Previous.clear();
   }
 
   // In C++, the previous declaration we find might be a tag type
   // (class or enum). In this case, the new declaration will hide the
   // tag type. Note that this does does not apply if we're declaring a
   // typedef (C++ [dcl.typedef]p4).
-  if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag &&
+  if (Previous.isSingleTagDecl() &&
       D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef)
-    PrevDecl = 0;
+    Previous.clear();
 
   bool Redeclaration = false;
   if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) {
@@ -1895,13 +1973,13 @@
       return DeclPtrTy();
     }
 
-    New = ActOnTypedefDeclarator(S, D, DC, R, DInfo, PrevDecl, Redeclaration);
+    New = ActOnTypedefDeclarator(S, D, DC, R, DInfo, Previous, Redeclaration);
   } else if (R->isFunctionType()) {
-    New = ActOnFunctionDeclarator(S, D, DC, R, DInfo, PrevDecl,
+    New = ActOnFunctionDeclarator(S, D, DC, R, DInfo, Previous,
                                   move(TemplateParamLists),
                                   IsFunctionDefinition, Redeclaration);
   } else {
-    New = ActOnVariableDeclarator(S, D, DC, R, DInfo, PrevDecl,
+    New = ActOnVariableDeclarator(S, D, DC, R, DInfo, Previous,
                                   move(TemplateParamLists),
                                   Redeclaration);
   }
@@ -1970,16 +2048,19 @@
 /// \brief Register the given locally-scoped external C declaration so
 /// that it can be found later for redeclarations
 void
-Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, NamedDecl *PrevDecl,
+Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND,
+                                       const LookupResult &Previous,
                                        Scope *S) {
   assert(ND->getLexicalDeclContext()->isFunctionOrMethod() &&
          "Decl is not a locally-scoped decl!");
   // Note that we have a locally-scoped external with this name.
   LocallyScopedExternalDecls[ND->getDeclName()] = ND;
 
-  if (!PrevDecl)
+  if (!Previous.isSingleResult())
     return;
 
+  NamedDecl *PrevDecl = Previous.getFoundDecl();
+
   // If there was a previous declaration of this variable, it may be
   // in our identifier chain. Update the identifier chain with the new
   // declaration.
@@ -2015,7 +2096,7 @@
 NamedDecl*
 Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                              QualType R,  DeclaratorInfo *DInfo,
-                             NamedDecl* PrevDecl, bool &Redeclaration) {
+                             LookupResult &Previous, bool &Redeclaration) {
   // Typedef declarators cannot be qualified (C++ [dcl.meaning]p1).
   if (D.getCXXScopeSpec().isSet()) {
     Diag(D.getIdentifierLoc(), diag::err_qualified_typedef_declarator)
@@ -2040,11 +2121,13 @@
 
   // Handle attributes prior to checking for duplicates in MergeVarDecl
   ProcessDeclAttributes(S, NewTD, D);
+
   // Merge the decl with the existing one if appropriate. If the decl is
   // in an outer scope, it isn't the same thing.
-  if (PrevDecl && isDeclInScope(PrevDecl, DC, S)) {
+  FilterLookupForScope(*this, Previous, DC, S, /*ConsiderLinkage*/ false);
+  if (!Previous.empty()) {
     Redeclaration = true;
-    MergeTypeDefDecl(NewTD, PrevDecl);
+    MergeTypeDefDecl(NewTD, Previous);
   }
 
   // C99 6.7.7p2: If a typedef name specifies a variably modified type
@@ -2155,7 +2238,7 @@
 NamedDecl*
 Sema::ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                               QualType R, DeclaratorInfo *DInfo,
-                              NamedDecl* PrevDecl,
+                              LookupResult &Previous,
                               MultiTemplateParamsArg TemplateParamLists,
                               bool &Redeclaration) {
   DeclarationName Name = GetNameForDeclarator(D);
@@ -2285,22 +2368,21 @@
                                                         SE->getByteLength())));
   }
 
-  // If name lookup finds a previous declaration that is not in the
-  // same scope as the new declaration, this may still be an
-  // acceptable redeclaration.
-  if (PrevDecl && !isDeclInScope(PrevDecl, DC, S) &&
-      !(NewVD->hasLinkage() &&
-        isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
-    PrevDecl = 0;
+  // Don't consider existing declarations that are in a different
+  // scope and are out-of-semantic-context declarations (if the new
+  // declaration has linkage).
+  FilterLookupForScope(*this, Previous, DC, S, NewVD->hasLinkage());
   
   // Merge the decl with the existing one if appropriate.
-  if (PrevDecl) {
-    if (isa<FieldDecl>(PrevDecl) && D.getCXXScopeSpec().isSet()) {
+  if (!Previous.empty()) {
+    if (Previous.isSingleResult() &&
+        isa<FieldDecl>(Previous.getFoundDecl()) &&
+        D.getCXXScopeSpec().isSet()) {
       // The user tried to define a non-static data member
       // out-of-line (C++ [dcl.meaning]p1).
       Diag(NewVD->getLocation(), diag::err_nonstatic_member_out_of_line)
         << D.getCXXScopeSpec().getRange();
-      PrevDecl = 0;
+      Previous.clear();
       NewVD->setInvalidDecl();
     }
   } else if (D.getCXXScopeSpec().isSet()) {
@@ -2311,17 +2393,18 @@
     NewVD->setInvalidDecl();
   }
 
-  CheckVariableDeclaration(NewVD, PrevDecl, Redeclaration);
+  CheckVariableDeclaration(NewVD, Previous, Redeclaration);
 
   // This is an explicit specialization of a static data member. Check it.
   if (isExplicitSpecialization && !NewVD->isInvalidDecl() &&
-      CheckMemberSpecialization(NewVD, PrevDecl))
+      CheckMemberSpecialization(NewVD, Previous))
     NewVD->setInvalidDecl();
-  
+
   // attributes declared post-definition are currently ignored
-  if (PrevDecl) {
-    const VarDecl *Def = 0, *PrevVD = dyn_cast<VarDecl>(PrevDecl);
-    if (PrevVD->getDefinition(Def) && D.hasAttributes()) {
+  if (Previous.isSingleResult()) {
+    const VarDecl *Def = 0;
+    VarDecl *PrevDecl = dyn_cast<VarDecl>(Previous.getFoundDecl());
+    if (PrevDecl && PrevDecl->getDefinition(Def) && D.hasAttributes()) {
       Diag(NewVD->getLocation(), diag::warn_attribute_precede_definition);
       Diag(Def->getLocation(), diag::note_previous_definition);
     }
@@ -2331,7 +2414,7 @@
   // such variables.
   if (CurContext->isFunctionOrMethod() && NewVD->isExternC() &&
       !NewVD->isInvalidDecl())
-    RegisterLocallyScopedExternCDecl(NewVD, PrevDecl, S);
+    RegisterLocallyScopedExternCDecl(NewVD, Previous, S);
 
   return NewVD;
 }
@@ -2346,7 +2429,8 @@
 /// that have been instantiated from a template.
 ///
 /// Sets NewVD->isInvalidDecl() if an error was encountered.
-void Sema::CheckVariableDeclaration(VarDecl *NewVD, NamedDecl *PrevDecl,
+void Sema::CheckVariableDeclaration(VarDecl *NewVD,
+                                    LookupResult &Previous,
                                     bool &Redeclaration) {
   // If the decl is already known invalid, don't check it.
   if (NewVD->isInvalidDecl())
@@ -2419,14 +2503,14 @@
     NewVD->setType(FixedTy);
   }
 
-  if (!PrevDecl && NewVD->isExternC()) {
+  if (Previous.empty() && NewVD->isExternC()) {
     // Since we did not find anything by this name and we're declaring
     // an extern "C" variable, look for a non-visible extern "C"
     // declaration with the same name.
     llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
       = LocallyScopedExternalDecls.find(NewVD->getDeclName());
     if (Pos != LocallyScopedExternalDecls.end())
-      PrevDecl = Pos->second;
+      Previous.addDecl(Pos->second);
   }
 
   if (T->isVoidType() && !NewVD->hasExternalStorage()) {
@@ -2445,18 +2529,12 @@
     return NewVD->setInvalidDecl();
   }
 
-  if (PrevDecl) {
+  if (!Previous.empty()) {
     Redeclaration = true;
-    MergeVarDecl(NewVD, PrevDecl);
+    MergeVarDecl(NewVD, Previous);
   }
 }
 
-static bool isUsingDecl(Decl *D) {
-  return isa<UsingDecl>(D) ||
-         isa<UnresolvedUsingTypenameDecl>(D) ||
-         isa<UnresolvedUsingValueDecl>(D);
-}
-
 /// \brief Data used with FindOverriddenMethod
 struct FindOverriddenMethodData {
   Sema *S;
@@ -2477,8 +2555,7 @@
        Path.Decls.first != Path.Decls.second;
        ++Path.Decls.first) {
     if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(*Path.Decls.first)) {
-      OverloadedFunctionDecl::function_iterator MatchedDecl;
-      if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD, MatchedDecl))
+      if (MD->isVirtual() && !Data->S->IsOverload(Data->Method, MD))
         return true;
     }
   }
@@ -2509,7 +2586,7 @@
 NamedDecl*
 Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
                               QualType R, DeclaratorInfo *DInfo,
-                              NamedDecl* PrevDecl,
+                              LookupResult &Previous,
                               MultiTemplateParamsArg TemplateParamLists,
                               bool IsFunctionDefinition, bool &Redeclaration) {
   assert(R.getTypePtr()->isFunctionType());
@@ -2574,10 +2651,6 @@
   FunctionDecl *NewFD;
 
   if (isFriend) {
-    // DC is the namespace in which the function is being declared.
-    assert((DC->isFileContext() || PrevDecl) && "previously-undeclared "
-           "friend function being created in a non-namespace context");
-
     // C++ [class.friend]p5
     //   A function can be defined in a friend declaration of a
     //   class . . . . Such a function is implicitly inline.
@@ -2753,14 +2826,22 @@
     }
   }
 
+  // Filter out previous declarations that don't match the scope.
+  FilterLookupForScope(*this, Previous, DC, S, NewFD->hasLinkage());
+
   if (isFriend) {
+    // DC is the namespace in which the function is being declared.
+    assert((DC->isFileContext() || !Previous.empty()) &&
+           "previously-undeclared friend function being created "
+           "in a non-namespace context");
+
     if (FunctionTemplate) {
       FunctionTemplate->setObjectOfFriendDecl(
-                                   /* PreviouslyDeclared= */ PrevDecl != NULL);
+                                   /* PreviouslyDeclared= */ !Previous.empty());
       FunctionTemplate->setAccess(AS_public);
     }
     else
-      NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ PrevDecl != NULL);
+      NewFD->setObjectOfFriendDecl(/* PreviouslyDeclared= */ !Previous.empty());
 
     NewFD->setAccess(AS_public);
   }
@@ -2851,14 +2932,6 @@
   // Finally, we know we have the right number of parameters, install them.
   NewFD->setParams(Context, Params.data(), Params.size());
 
-  // If name lookup finds a previous declaration that is not in the
-  // same scope as the new declaration, this may still be an
-  // acceptable redeclaration.
-  if (PrevDecl && !isDeclInScope(PrevDecl, DC, S) &&
-      !(NewFD->hasLinkage() &&
-        isOutOfScopePreviousDeclaration(PrevDecl, DC, Context)))
-    PrevDecl = 0;
-
   // If the declarator is a template-id, translate the parser's template 
   // argument list into our AST format.
   bool HasExplicitTemplateArgs = false;
@@ -2895,22 +2968,26 @@
       isFunctionTemplateSpecialization = true;
     }
   }
-  
+
   if (isFunctionTemplateSpecialization) {
       if (CheckFunctionTemplateSpecialization(NewFD, HasExplicitTemplateArgs,
                                               LAngleLoc, TemplateArgs.data(),
                                               TemplateArgs.size(), RAngleLoc,
-                                              PrevDecl))
+                                              Previous))
         NewFD->setInvalidDecl();
   } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) &&
-             CheckMemberSpecialization(NewFD, PrevDecl))
+             CheckMemberSpecialization(NewFD, Previous))
     NewFD->setInvalidDecl();
     
   // Perform semantic checking on the function declaration.
   bool OverloadableAttrRequired = false; // FIXME: HACK!
-  CheckFunctionDeclaration(NewFD, PrevDecl, isExplicitSpecialization,
+  CheckFunctionDeclaration(NewFD, Previous, isExplicitSpecialization,
                            Redeclaration, /*FIXME:*/OverloadableAttrRequired);
 
+  assert((NewFD->isInvalidDecl() || !Redeclaration ||
+          Previous.getResultKind() != LookupResult::FoundOverloaded) &&
+         "previous declaration set still overloaded");
+
   if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
     // An out-of-line member function declaration must also be a
     // definition (C++ [dcl.meaning]p1).
@@ -2922,7 +2999,7 @@
       Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
         << D.getCXXScopeSpec().getRange();
       NewFD->setInvalidDecl();
-    } else if (!Redeclaration && (!PrevDecl || !isUsingDecl(PrevDecl))) {
+    } else if (!Redeclaration) {
       // The user tried to provide an out-of-line definition for a
       // function that is a member of a class or namespace, but there
       // was no such member function declared (C++ [class.mfct]p2,
@@ -2952,8 +3029,6 @@
             isNearlyMatchingFunction(Context, cast<FunctionDecl>(*Func), NewFD))
           Diag((*Func)->getLocation(), diag::note_member_def_close_match);
       }
-
-      PrevDecl = 0;
     }
   }
 
@@ -2964,8 +3039,9 @@
   ProcessDeclAttributes(S, NewFD, D);
 
   // attributes declared post-definition are currently ignored
-  if (Redeclaration && PrevDecl) {
-    const FunctionDecl *Def, *PrevFD = dyn_cast<FunctionDecl>(PrevDecl);
+  if (Redeclaration && Previous.isSingleResult()) {
+    const FunctionDecl *Def;
+    FunctionDecl *PrevFD = dyn_cast<FunctionDecl>(Previous.getFoundDecl());
     if (PrevFD && PrevFD->getBody(Def) && D.hasAttributes()) {
       Diag(NewFD->getLocation(), diag::warn_attribute_precede_definition);
       Diag(Def->getLocation(), diag::note_previous_definition);
@@ -2979,8 +3055,8 @@
     // with that name must be marked "overloadable".
     Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)
       << Redeclaration << NewFD;
-    if (PrevDecl)
-      Diag(PrevDecl->getLocation(),
+    if (!Previous.empty())
+      Diag(Previous.getRepresentativeDecl()->getLocation(),
            diag::note_attribute_overloadable_prev_overload);
     NewFD->addAttr(::new (Context) OverloadableAttr());
   }
@@ -2989,7 +3065,7 @@
   // map of such names.
   if (CurContext->isFunctionOrMethod() && NewFD->isExternC()
       && !NewFD->isInvalidDecl())
-    RegisterLocallyScopedExternCDecl(NewFD, PrevDecl, S);
+    RegisterLocallyScopedExternCDecl(NewFD, Previous, S);
 
   // Set this FunctionDecl's range up to the right paren.
   NewFD->setLocEnd(D.getSourceRange().getEnd());
@@ -3017,7 +3093,8 @@
 /// an explicit specialization of the previous declaration.
 ///
 /// This sets NewFD->isInvalidDecl() to true if there was an error.
-void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl,
+void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD,
+                                    LookupResult &Previous,
                                     bool IsExplicitSpecialization,
                                     bool &Redeclaration,
                                     bool &OverloadableAttrRequired) {
@@ -3036,27 +3113,26 @@
     CheckMain(NewFD);
 
   // Check for a previous declaration of this name.
-  if (!PrevDecl && NewFD->isExternC()) {
+  if (Previous.empty() && NewFD->isExternC()) {
     // Since we did not find anything by this name and we're declaring
     // an extern "C" function, look for a non-visible extern "C"
     // declaration with the same name.
     llvm::DenseMap<DeclarationName, NamedDecl *>::iterator Pos
       = LocallyScopedExternalDecls.find(NewFD->getDeclName());
     if (Pos != LocallyScopedExternalDecls.end())
-      PrevDecl = Pos->second;
+      Previous.addDecl(Pos->second);
   }
 
   // Merge or overload the declaration with an existing declaration of
   // the same name, if appropriate.
-  if (PrevDecl) {
+  if (!Previous.empty()) {
     // Determine whether NewFD is an overload of PrevDecl or
     // a declaration that requires merging. If it's an overload,
     // there's no more work to do here; we'll just add the new
     // function to the scope.
-    OverloadedFunctionDecl::function_iterator MatchedDecl;
 
     if (!getLangOptions().CPlusPlus &&
-        AllowOverloadingOfFunction(PrevDecl, Context)) {
+        AllowOverloadingOfFunction(Previous, Context)) {
       OverloadableAttrRequired = true;
 
       // Functions marked "overloadable" must have a prototype (that
@@ -3075,22 +3151,26 @@
       }
     }
 
-    if (PrevDecl &&
-        (!AllowOverloadingOfFunction(PrevDecl, Context) ||
-         !IsOverload(NewFD, PrevDecl, MatchedDecl)) && !isUsingDecl(PrevDecl)) {
-      Redeclaration = true;
-      Decl *OldDecl = PrevDecl;
-
-      // If PrevDecl was an overloaded function, extract the
-      // FunctionDecl that matched.
-      if (isa<OverloadedFunctionDecl>(PrevDecl))
-        OldDecl = *MatchedDecl;
+    NamedDecl *OldDecl = 0;
+    if (!Previous.empty()) {
+      if (!AllowOverloadingOfFunction(Previous, Context)) {
+        Redeclaration = true;
+        OldDecl = Previous.getFoundDecl();
+      } else if (!IsOverload(NewFD, Previous, OldDecl)) {
+        if (!isUsingDecl(OldDecl))
+          Redeclaration = true;
+      }
+    }
 
+    if (Redeclaration) {
       // NewFD and OldDecl represent declarations that need to be
       // merged.
       if (MergeFunctionDecl(NewFD, OldDecl))
         return NewFD->setInvalidDecl();
 
+      Previous.clear();
+      Previous.addDecl(OldDecl);
+
       if (FunctionTemplateDecl *OldTemplateDecl
                                     = dyn_cast<FunctionTemplateDecl>(OldDecl)) {
         NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl());        
@@ -4317,11 +4397,13 @@
 
   DeclContext *SearchDC = CurContext;
   DeclContext *DC = CurContext;
-  NamedDecl *PrevDecl = 0;
   bool isStdBadAlloc = false;
   bool Invalid = false;
 
-  RedeclarationKind Redecl = (RedeclarationKind) (TUK != TUK_Reference);
+  RedeclarationKind Redecl = (TUK != TUK_Reference ? ForRedeclaration
+                                                   : NotForRedeclaration);
+
+  LookupResult Previous(*this, Name, NameLoc, LookupTagName, Redecl);
 
   if (Name && SS.isNotEmpty()) {
     // We have a nested-name tag ('struct foo::bar').
@@ -4348,17 +4430,13 @@
     DC = computeDeclContext(SS, true);
     SearchDC = DC;
     // Look-up name inside 'foo::'.
-    LookupResult R(*this, Name, NameLoc, LookupTagName, Redecl);
-    LookupQualifiedName(R, DC);
+    LookupQualifiedName(Previous, DC);
 
-    if (R.isAmbiguous())
+    if (Previous.isAmbiguous())
       return DeclPtrTy();
 
-    if (R.getResultKind() == LookupResult::Found)
-      PrevDecl = dyn_cast<TagDecl>(R.getFoundDecl());
-
     // A tag 'foo::bar' must already exist.
-    if (!PrevDecl) {
+    if (Previous.empty()) {
       Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange();
       Name = 0;
       Invalid = true;
@@ -4370,19 +4448,11 @@
     // FIXME: We're looking into outer scopes here, even when we
     // shouldn't be. Doing so can result in ambiguities that we
     // shouldn't be diagnosing.
-    LookupResult R(*this, Name, NameLoc, LookupTagName, Redecl);
-    LookupName(R, S);
-    if (R.isAmbiguous()) {
-      // FIXME: This is not best way to recover from case like:
-      //
-      // struct S s;
-      //
-      // causes needless "incomplete type" error later.
-      Name = 0;
-      PrevDecl = 0;
-      Invalid = true;
-    } else
-      PrevDecl = R.getAsSingleDecl(Context);
+    LookupName(Previous, S);
+
+    // Note:  there used to be some attempt at recovery here.
+    if (Previous.isAmbiguous())
+      return DeclPtrTy();
 
     if (!getLangOptions().CPlusPlus && TUK != TUK_Reference) {
       // FIXME: This makes sure that we ignore the contexts associated
@@ -4394,11 +4464,12 @@
     }
   }
 
-  if (PrevDecl && PrevDecl->isTemplateParameter()) {
+  if (Previous.isSingleResult() &&
+      Previous.getFoundDecl()->isTemplateParameter()) {
     // Maybe we will complain about the shadowed template parameter.
-    DiagnoseTemplateParameterShadow(NameLoc, PrevDecl);
+    DiagnoseTemplateParameterShadow(NameLoc, Previous.getFoundDecl());
     // Just pretend that we didn't see the previous declaration.
-    PrevDecl = 0;
+    Previous.clear();
   }
 
   if (getLangOptions().CPlusPlus && Name && DC && StdNamespace &&
@@ -4406,15 +4477,17 @@
     // This is a declaration of or a reference to "std::bad_alloc".
     isStdBadAlloc = true;
     
-    if (!PrevDecl && StdBadAlloc) {
+    if (Previous.empty() && StdBadAlloc) {
       // std::bad_alloc has been implicitly declared (but made invisible to
       // name lookup). Fill in this implicit declaration as the previous 
       // declaration, so that the declarations get chained appropriately.
-      PrevDecl = StdBadAlloc;
+      Previous.addDecl(StdBadAlloc);
     }
   }
-      
-  if (PrevDecl) {
+
+  if (!Previous.empty()) {
+    assert(Previous.isSingleResult());
+    NamedDecl *PrevDecl = Previous.getFoundDecl();
     if (TagDecl *PrevTagDecl = dyn_cast<TagDecl>(PrevDecl)) {
       // If this is a use of a previous tag, or if the tag is already declared
       // in the same scope (so that the definition/declaration completes or
@@ -4434,14 +4507,14 @@
                                                   PrevTagDecl->getKindName());
           else
             Diag(KWLoc, diag::err_use_with_wrong_tag) << Name;
-          Diag(PrevDecl->getLocation(), diag::note_previous_use);
+          Diag(PrevTagDecl->getLocation(), diag::note_previous_use);
 
           if (SafeToContinue)
             Kind = PrevTagDecl->getTagKind();
           else {
             // Recover by making this an anonymous redefinition.
             Name = 0;
-            PrevDecl = 0;
+            Previous.clear();
             Invalid = true;
           }
         }
@@ -4454,7 +4527,7 @@
           // For our current ASTs this shouldn't be a problem, but will
           // need to be changed with DeclGroups.
           if (TUK == TUK_Reference || TUK == TUK_Friend)
-            return DeclPtrTy::make(PrevDecl);
+            return DeclPtrTy::make(PrevTagDecl);
 
           // Diagnose attempts to redefine a tag.
           if (TUK == TUK_Definition) {
@@ -4472,7 +4545,7 @@
                 // struct be anonymous, which will make any later
                 // references get the previous definition.
                 Name = 0;
-                PrevDecl = 0;
+                Previous.clear();
                 Invalid = true;
               }
             } else {
@@ -4484,7 +4557,7 @@
                 Diag(PrevTagDecl->getLocation(),
                      diag::note_previous_definition);
                 Name = 0;
-                PrevDecl = 0;
+                Previous.clear();
                 Invalid = true;
               }
             }
@@ -4501,7 +4574,7 @@
         // scope, e.g. "struct foo; void bar() { struct foo; }", just create a
         // new decl/type.  We set PrevDecl to NULL so that the entities
         // have distinct types.
-        PrevDecl = 0;
+        Previous.clear();
       }
       // If we get here, we're going to create a new Decl. If PrevDecl
       // is non-NULL, it's a definition of the tag declared by
@@ -4515,12 +4588,12 @@
         Diag(NameLoc, diag::err_redefinition_different_kind) << Name;
         Diag(PrevDecl->getLocation(), diag::note_previous_definition);
         Name = 0;
-        PrevDecl = 0;
+        Previous.clear();
         Invalid = true;
       } else {
         // The existing declaration isn't relevant to us; we're in a
         // new scope, so clear out the previous declaration.
-        PrevDecl = 0;
+        Previous.clear();
       }
     }
   } else if (TUK == TUK_Reference && SS.isEmpty() && Name &&
@@ -4574,6 +4647,10 @@
 
 CreateNewDecl:
 
+  TagDecl *PrevDecl = 0;
+  if (Previous.isSingleResult())
+    PrevDecl = cast<TagDecl>(Previous.getFoundDecl());
+
   // If there is an identifier, use the location of the identifier as the
   // location of the decl, otherwise use the location of the struct/union
   // keyword.
@@ -4655,7 +4732,7 @@
 
   // If this is a specialization of a member class (of a class template),
   // check the specialization.
-  if (isExplicitSpecialization && CheckMemberSpecialization(New, PrevDecl))
+  if (isExplicitSpecialization && CheckMemberSpecialization(New, Previous))
     Invalid = true;
       
   if (Invalid)
@@ -4675,7 +4752,7 @@
 
   // Mark this as a friend decl if applicable.
   if (TUK == TUK_Friend)
-    New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ PrevDecl != NULL);
+    New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty());
 
   // Set the access specifier.
   if (!Invalid && TUK != TUK_Friend)

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Nov 18 16:49:29 2009
@@ -4668,7 +4668,8 @@
   // FIXME: handle local classes
 
   // Recover from invalid scope qualifiers as if they just weren't there.
-  NamedDecl *PrevDecl = 0;
+  LookupResult Previous(*this, Name, D.getIdentifierLoc(), LookupOrdinaryName,
+                        ForRedeclaration);
   if (!ScopeQual.isInvalid() && ScopeQual.isSet()) {
     // FIXME: RequireCompleteDeclContext
     DC = computeDeclContext(ScopeQual);
@@ -4676,15 +4677,15 @@
     // FIXME: handle dependent contexts
     if (!DC) return DeclPtrTy();
 
-    LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration);
-    LookupQualifiedName(R, DC);
-    PrevDecl = R.getAsSingleDecl(Context);
+    LookupQualifiedName(Previous, DC);
 
     // If searching in that context implicitly found a declaration in
     // a different context, treat it like it wasn't found at all.
     // TODO: better diagnostics for this case.  Suggesting the right
     // qualified scope would be nice...
-    if (!PrevDecl || !PrevDecl->getDeclContext()->Equals(DC)) {
+    // FIXME: getRepresentativeDecl() is not right here at all
+    if (Previous.empty() ||
+        !Previous.getRepresentativeDecl()->getDeclContext()->Equals(DC)) {
       D.setInvalidType();
       Diag(Loc, diag::err_qualified_friend_not_found) << Name << T;
       return DeclPtrTy();
@@ -4711,12 +4712,10 @@
       while (DC->isRecord()) 
         DC = DC->getParent();
 
-      LookupResult R(*this, Name, Loc, LookupOrdinaryName, ForRedeclaration);
-      LookupQualifiedName(R, DC);
-      PrevDecl = R.getAsSingleDecl(Context);
+      LookupQualifiedName(Previous, DC);
 
       // TODO: decide what we think about using declarations.
-      if (PrevDecl)
+      if (!Previous.empty())
         break;
       
       if (DC->isFileContext()) break;
@@ -4728,7 +4727,8 @@
     // C++0x changes this for both friend types and functions.
     // Most C++ 98 compilers do seem to give an error here, so
     // we do, too.
-    if (PrevDecl && DC->Equals(CurContext) && !getLangOptions().CPlusPlus0x)
+    if (!Previous.empty() && DC->Equals(CurContext)
+        && !getLangOptions().CPlusPlus0x)
       Diag(DS.getFriendSpecLoc(), diag::err_friend_is_member);
   }
 
@@ -4745,7 +4745,7 @@
   }
 
   bool Redeclaration = false;
-  NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo, PrevDecl,
+  NamedDecl *ND = ActOnFunctionDeclarator(S, D, DC, T, DInfo, Previous,
                                           move(TemplateParams),
                                           IsDefinition,
                                           Redeclaration);

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Nov 18 16:49:29 2009
@@ -246,7 +246,11 @@
   unsigned N = Decls.size();
 
   // Fast case: no possible ambiguity.
-  if (N == 0) return;
+  if (N == 0) {
+    assert(ResultKind == NotFound);
+    return;
+  }
+
   if (N == 1) {
     if (isa<UnresolvedUsingValueDecl>(Decls[0]))
       ResultKind = FoundUnresolvedValue;

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Nov 18 16:49:29 2009
@@ -284,100 +284,102 @@
 // signature), IsOverload returns false and MatchedDecl will be set to
 // point to the FunctionDecl for #2.
 bool
-Sema::IsOverload(FunctionDecl *New, Decl* OldD,
-                 OverloadedFunctionDecl::function_iterator& MatchedDecl) {
-  if (OverloadedFunctionDecl* Ovl = dyn_cast<OverloadedFunctionDecl>(OldD)) {
-    // Is this new function an overload of every function in the
-    // overload set?
-    OverloadedFunctionDecl::function_iterator Func = Ovl->function_begin(),
-                                           FuncEnd = Ovl->function_end();
-    for (; Func != FuncEnd; ++Func) {
-      if (!IsOverload(New, *Func, MatchedDecl)) {
-        MatchedDecl = Func;
+Sema::IsOverload(FunctionDecl *New, LookupResult &Previous, NamedDecl *&Match) {
+  for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+         I != E; ++I) {
+    NamedDecl *Old = (*I)->getUnderlyingDecl();
+    if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(Old)) {
+      if (!IsOverload(New, OldT->getTemplatedDecl())) {
+        Match = Old;
         return false;
       }
+    } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(Old)) {
+      if (!IsOverload(New, OldF)) {
+        Match = Old;
+        return false;
+      }
+    } else {
+      // (C++ 13p1):
+      //   Only function declarations can be overloaded; object and type
+      //   declarations cannot be overloaded.
+      Match = Old;
+      return false;
     }
+  }
 
-    // This function overloads every function in the overload set.
-    return true;
-  } else if (FunctionTemplateDecl *Old = dyn_cast<FunctionTemplateDecl>(OldD))
-    return IsOverload(New, Old->getTemplatedDecl(), MatchedDecl);
-  else if (FunctionDecl* Old = dyn_cast<FunctionDecl>(OldD)) {
-    FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
-    FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
-
-    // C++ [temp.fct]p2:
-    //   A function template can be overloaded with other function templates
-    //   and with normal (non-template) functions.
-    if ((OldTemplate == 0) != (NewTemplate == 0))
-      return true;
+  return true;
+}
 
-    // Is the function New an overload of the function Old?
-    QualType OldQType = Context.getCanonicalType(Old->getType());
-    QualType NewQType = Context.getCanonicalType(New->getType());
-
-    // Compare the signatures (C++ 1.3.10) of the two functions to
-    // determine whether they are overloads. If we find any mismatch
-    // in the signature, they are overloads.
-
-    // If either of these functions is a K&R-style function (no
-    // prototype), then we consider them to have matching signatures.
-    if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
-        isa<FunctionNoProtoType>(NewQType.getTypePtr()))
-      return false;
+bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old) {
+  FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();
+  FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();
+
+  // C++ [temp.fct]p2:
+  //   A function template can be overloaded with other function templates
+  //   and with normal (non-template) functions.
+  if ((OldTemplate == 0) != (NewTemplate == 0))
+    return true;
 
-    FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
-    FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
+  // Is the function New an overload of the function Old?
+  QualType OldQType = Context.getCanonicalType(Old->getType());
+  QualType NewQType = Context.getCanonicalType(New->getType());
+
+  // Compare the signatures (C++ 1.3.10) of the two functions to
+  // determine whether they are overloads. If we find any mismatch
+  // in the signature, they are overloads.
+
+  // If either of these functions is a K&R-style function (no
+  // prototype), then we consider them to have matching signatures.
+  if (isa<FunctionNoProtoType>(OldQType.getTypePtr()) ||
+      isa<FunctionNoProtoType>(NewQType.getTypePtr()))
+    return false;
 
-    // The signature of a function includes the types of its
-    // parameters (C++ 1.3.10), which includes the presence or absence
-    // of the ellipsis; see C++ DR 357).
-    if (OldQType != NewQType &&
-        (OldType->getNumArgs() != NewType->getNumArgs() ||
-         OldType->isVariadic() != NewType->isVariadic() ||
-         !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
-                     NewType->arg_type_begin())))
-      return true;
+  FunctionProtoType* OldType = cast<FunctionProtoType>(OldQType);
+  FunctionProtoType* NewType = cast<FunctionProtoType>(NewQType);
 
-    // C++ [temp.over.link]p4:
-    //   The signature of a function template consists of its function
-    //   signature, its return type and its template parameter list. The names
-    //   of the template parameters are significant only for establishing the
-    //   relationship between the template parameters and the rest of the
-    //   signature.
-    //
-    // We check the return type and template parameter lists for function
-    // templates first; the remaining checks follow.
-    if (NewTemplate &&
-        (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
-                                         OldTemplate->getTemplateParameters(),
-                                         false, TPL_TemplateMatch) ||
-         OldType->getResultType() != NewType->getResultType()))
-      return true;
+  // The signature of a function includes the types of its
+  // parameters (C++ 1.3.10), which includes the presence or absence
+  // of the ellipsis; see C++ DR 357).
+  if (OldQType != NewQType &&
+      (OldType->getNumArgs() != NewType->getNumArgs() ||
+       OldType->isVariadic() != NewType->isVariadic() ||
+       !std::equal(OldType->arg_type_begin(), OldType->arg_type_end(),
+                   NewType->arg_type_begin())))
+    return true;
 
-    // If the function is a class member, its signature includes the
-    // cv-qualifiers (if any) on the function itself.
-    //
-    // As part of this, also check whether one of the member functions
-    // is static, in which case they are not overloads (C++
-    // 13.1p2). While not part of the definition of the signature,
-    // this check is important to determine whether these functions
-    // can be overloaded.
-    CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
-    CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
-    if (OldMethod && NewMethod &&
-        !OldMethod->isStatic() && !NewMethod->isStatic() &&
-        OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers())
-      return true;
+  // C++ [temp.over.link]p4:
+  //   The signature of a function template consists of its function
+  //   signature, its return type and its template parameter list. The names
+  //   of the template parameters are significant only for establishing the
+  //   relationship between the template parameters and the rest of the
+  //   signature.
+  //
+  // We check the return type and template parameter lists for function
+  // templates first; the remaining checks follow.
+  if (NewTemplate &&
+      (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),
+                                       OldTemplate->getTemplateParameters(),
+                                       false, TPL_TemplateMatch) ||
+       OldType->getResultType() != NewType->getResultType()))
+    return true;
 
-    // The signatures match; this is not an overload.
-    return false;
-  } else {
-    // (C++ 13p1):
-    //   Only function declarations can be overloaded; object and type
-    //   declarations cannot be overloaded.
-    return false;
-  }
+  // If the function is a class member, its signature includes the
+  // cv-qualifiers (if any) on the function itself.
+  //
+  // As part of this, also check whether one of the member functions
+  // is static, in which case they are not overloads (C++
+  // 13.1p2). While not part of the definition of the signature,
+  // this check is important to determine whether these functions
+  // can be overloaded.
+  CXXMethodDecl* OldMethod = dyn_cast<CXXMethodDecl>(Old);
+  CXXMethodDecl* NewMethod = dyn_cast<CXXMethodDecl>(New);
+  if (OldMethod && NewMethod &&
+      !OldMethod->isStatic() && !NewMethod->isStatic() &&
+      OldMethod->getTypeQualifiers() != NewMethod->getTypeQualifiers())
+    return true;
+  
+  // The signatures match; this is not an overload.
+  return false;
 }
 
 /// TryImplicitConversion - Attempt to perform an implicit conversion

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed Nov 18 16:49:29 2009
@@ -3538,15 +3538,17 @@
                            const TemplateArgumentLoc *ExplicitTemplateArgs,
                                           unsigned NumExplicitTemplateArgs,
                                           SourceLocation RAngleLoc,
-                                          NamedDecl *&PrevDecl) {
+                                          LookupResult &Previous) {
   // The set of function template specializations that could match this
   // explicit function template specialization.
   typedef llvm::SmallVector<FunctionDecl *, 8> CandidateSet;
   CandidateSet Candidates;
   
   DeclContext *FDLookupContext = FD->getDeclContext()->getLookupContext();
-  for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) {
-    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(*Ovl)) {
+  for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+         I != E; ++I) {
+    NamedDecl *Ovl = (*I)->getUnderlyingDecl();
+    if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(Ovl)) {
       // Only consider templates found within the same semantic lookup scope as 
       // FD.
       if (!FDLookupContext->Equals(Ovl->getDeclContext()->getLookupContext()))
@@ -3637,7 +3639,8 @@
   
   // The "previous declaration" for this function template specialization is
   // the prior function template specialization.
-  PrevDecl = Specialization;
+  Previous.clear();
+  Previous.addDecl(Specialization);
   return false;
 }
 
@@ -3652,10 +3655,11 @@
 /// \param Member the member declaration, which will be updated to become a
 /// specialization.
 ///
-/// \param PrevDecl the set of declarations, one of which may be specialized
-/// by this function specialization.
+/// \param Previous the set of declarations, one of which may be specialized
+/// by this function specialization;  the set will be modified to contain the
+/// redeclared member.
 bool 
-Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) {
+Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) {
   assert(!isa<TemplateDecl>(Member) && "Only for non-template members");
          
   // Try to find the member we are instantiating.
@@ -3663,11 +3667,13 @@
   NamedDecl *InstantiatedFrom = 0;
   MemberSpecializationInfo *MSInfo = 0;
 
-  if (!PrevDecl) {
+  if (Previous.empty()) {
     // Nowhere to look anyway.
   } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Member)) {
-    for (OverloadIterator Ovl(PrevDecl), OvlEnd; Ovl != OvlEnd; ++Ovl) {
-      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(*Ovl)) {
+    for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+           I != E; ++I) {
+      NamedDecl *D = (*I)->getUnderlyingDecl();
+      if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D)) {
         if (Context.hasSameType(Function->getType(), Method->getType())) {
           Instantiation = Method;
           InstantiatedFrom = Method->getInstantiatedFromMemberFunction();
@@ -3677,15 +3683,19 @@
       }
     }
   } else if (isa<VarDecl>(Member)) {
-    if (VarDecl *PrevVar = dyn_cast<VarDecl>(PrevDecl))
+    VarDecl *PrevVar;
+    if (Previous.isSingleResult() &&
+        (PrevVar = dyn_cast<VarDecl>(Previous.getFoundDecl())))
       if (PrevVar->isStaticDataMember()) {
-        Instantiation = PrevDecl;
+        Instantiation = PrevVar;
         InstantiatedFrom = PrevVar->getInstantiatedFromStaticDataMember();
         MSInfo = PrevVar->getMemberSpecializationInfo();
       }
   } else if (isa<RecordDecl>(Member)) {
-    if (CXXRecordDecl *PrevRecord = dyn_cast<CXXRecordDecl>(PrevDecl)) {
-      Instantiation = PrevDecl;
+    CXXRecordDecl *PrevRecord;
+    if (Previous.isSingleResult() &&
+        (PrevRecord = dyn_cast<CXXRecordDecl>(Previous.getFoundDecl()))) {
+      Instantiation = PrevRecord;
       InstantiatedFrom = PrevRecord->getInstantiatedFromMemberClass();
       MSInfo = PrevRecord->getMemberSpecializationInfo();
     }
@@ -3774,7 +3784,8 @@
              
   // Save the caller the trouble of having to figure out which declaration
   // this specialization matches.
-  PrevDecl = Instantiation;
+  Previous.clear();
+  Previous.addDecl(Instantiation);
   return false;
 }
 

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

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Wed Nov 18 16:49:29 2009
@@ -175,7 +175,10 @@
   // FIXME: In theory, we could have a previous declaration for variables that
   // are not static data members.
   bool Redeclaration = false;
-  SemaRef.CheckVariableDeclaration(Var, 0, Redeclaration);
+  // FIXME: having to fake up a LookupResult is dumb.
+  LookupResult Previous(SemaRef, Var->getDeclName(), Var->getLocation(),
+                        Sema::LookupOrdinaryName);
+  SemaRef.CheckVariableDeclaration(Var, Previous, Redeclaration);
 
   if (D->isOutOfLine()) {
     D->getLexicalDeclContext()->addDecl(Var);
@@ -680,27 +683,24 @@
   bool Redeclaration = false;
   bool OverloadableAttrRequired = false;
     
-  NamedDecl *PrevDecl = 0;
+  LookupResult Previous(SemaRef, Function->getDeclName(), SourceLocation(),
+                        Sema::LookupOrdinaryName, Sema::ForRedeclaration);
+
   if (TemplateParams || !FunctionTemplate) {
     // Look only into the namespace where the friend would be declared to 
     // find a previous declaration. This is the innermost enclosing namespace, 
     // as described in ActOnFriendFunctionDecl.
-    LookupResult R(SemaRef, Function->getDeclName(), SourceLocation(),
-                   Sema::LookupOrdinaryName,
-                   Sema::ForRedeclaration);
-    SemaRef.LookupQualifiedName(R, DC);
+    SemaRef.LookupQualifiedName(Previous, DC);
     
-    PrevDecl = R.getAsSingleDecl(SemaRef.Context);
-
     // In C++, the previous declaration we find might be a tag type
     // (class or enum). In this case, the new declaration will hide the
     // tag type. Note that this does does not apply if we're declaring a
     // typedef (C++ [dcl.typedef]p4).
-    if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
-      PrevDecl = 0;
+    if (Previous.isSingleTagDecl())
+      Previous.clear();
   }
   
-  SemaRef.CheckFunctionDeclaration(Function, PrevDecl, false, Redeclaration,
+  SemaRef.CheckFunctionDeclaration(Function, Previous, false, Redeclaration,
                                    /*FIXME:*/OverloadableAttrRequired);
 
   // If the original function was part of a friend declaration,
@@ -709,6 +709,7 @@
       = TemplateParams? cast<NamedDecl>(D->getDescribedFunctionTemplate()) : D;
   if (FromFriendD->getFriendObjectKind()) {
     NamedDecl *ToFriendD = 0;
+    NamedDecl *PrevDecl;
     if (TemplateParams) {
       ToFriendD = cast<NamedDecl>(FunctionTemplate);
       PrevDecl = FunctionTemplate->getPreviousDeclaration();
@@ -843,29 +844,26 @@
   if (InitMethodInstantiation(Method, D))
     Method->setInvalidDecl();
 
-  NamedDecl *PrevDecl = 0;
+  LookupResult Previous(SemaRef, Name, SourceLocation(),
+                        Sema::LookupOrdinaryName, Sema::ForRedeclaration);
 
   if (!FunctionTemplate || TemplateParams) {
-    LookupResult R(SemaRef, Name, SourceLocation(),
-                   Sema::LookupOrdinaryName,
-                   Sema::ForRedeclaration);
-    SemaRef.LookupQualifiedName(R, Owner);
-    PrevDecl = R.getAsSingleDecl(SemaRef.Context);
+    SemaRef.LookupQualifiedName(Previous, Owner);
 
     // In C++, the previous declaration we find might be a tag type
     // (class or enum). In this case, the new declaration will hide the
     // tag type. Note that this does does not apply if we're declaring a
     // typedef (C++ [dcl.typedef]p4).
-    if (PrevDecl && PrevDecl->getIdentifierNamespace() == Decl::IDNS_Tag)
-      PrevDecl = 0;
+    if (Previous.isSingleTagDecl())
+      Previous.clear();
   }
 
   bool Redeclaration = false;
   bool OverloadableAttrRequired = false;
-  SemaRef.CheckFunctionDeclaration(Method, PrevDecl, false, Redeclaration,
+  SemaRef.CheckFunctionDeclaration(Method, Previous, false, Redeclaration,
                                    /*FIXME:*/OverloadableAttrRequired);
 
-  if (!FunctionTemplate && (!Method->isInvalidDecl() || !PrevDecl) &&
+  if (!FunctionTemplate && (!Method->isInvalidDecl() || Previous.empty()) &&
       !Method->getFriendObjectKind())
     Owner->addDecl(Method);
 

Modified: cfe/trunk/test/SemaCXX/using-directive.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/using-directive.cpp?rev=89263&r1=89262&r2=89263&view=diff

==============================================================================
--- cfe/trunk/test/SemaCXX/using-directive.cpp (original)
+++ cfe/trunk/test/SemaCXX/using-directive.cpp Wed Nov 18 16:49:29 2009
@@ -54,9 +54,7 @@
 
 void K1::foo() {} // okay
 
-// FIXME: Do we want err_ovl_no_viable_function_in_init here?
-struct K2 k2; // expected-error{{reference to 'K2' is ambiguous}} \
-                 expected-error{{incomplete type}}
+struct K2 *k2; // expected-error{{reference to 'K2' is ambiguous}}
 
 // FIXME: This case is incorrectly diagnosed!
 //K2 k3;





More information about the cfe-commits mailing list