Implement redeclaration checking and hiding semantics for using declarations.  There
are a couple of O(n^2) operations in this, some analogous to the usual O(n^2)
redeclaration problem and some not.  In particular, retroactively removing
shadow declarations when they're hidden by later decls is pretty unfortunate.
I'm not yet convinced it's worse than the alternative, though.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91045 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index ab54ddf..00103ce 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -916,6 +916,9 @@
   /// only happens with friends.
   void addHiddenDecl(Decl *D);
 
+  /// @brief Removes a declaration from this context.
+  void removeDecl(Decl *D);
+
   /// lookup_iterator - An iterator that provides access to the results
   /// of looking up a name within this context.
   typedef NamedDecl **lookup_iterator;
diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h
index 9a38485..c3a7495 100644
--- a/include/clang/AST/DeclContextInternals.h
+++ b/include/clang/AST/DeclContextInternals.h
@@ -131,6 +131,24 @@
     return DK == DK_DeclID || DK == DK_ID_Vector;
   }
 
+  void remove(NamedDecl *D) {
+    assert(!isNull() && "removing from empty list");
+    if (NamedDecl *Singleton = getAsDecl()) {
+      assert(Singleton == D && "list is different singleton");
+      Data = 0;
+      return;
+    }
+
+    VectorTy &Vec = *getAsVector();
+    VectorTy::iterator I = std::find(Vec.begin(), Vec.end(),
+                                     reinterpret_cast<uintptr_t>(D));
+    assert(I != Vec.end() && "list does not contain decl");
+    Vec.erase(I);
+
+    assert(std::find(Vec.begin(), Vec.end(), reinterpret_cast<uintptr_t>(D))
+             == Vec.end() && "list still contains decl");
+  }
+
   /// getLookupResult - Return an array of all the decls that this list
   /// represents.
   DeclContext::lookup_result getLookupResult(ASTContext &Context) {
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index d75c49b..4db1d15 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -121,8 +121,13 @@
   "using declaration can not refer to a destructor">;
 def err_using_decl_template_id : Error<
   "using declaration can not refer to a template specialization">;
-def note_using_decl_target : Note<
-  "target of using declaration">;
+def note_using_decl_target : Note<"target of using declaration">;
+def note_using_decl_conflict : Note<"conflicting declaration">;
+def err_using_decl_redeclaration : Error<"redeclaration of using decl">;
+def note_previous_using_decl : Note<"previous using decl">;
+def err_using_decl_conflict : Error<
+  "%select{function|non-function}0 target of using declaration conflicts "
+  "with %select{function|non-function}1 declaration already in scope">;
 
 def err_invalid_thread : Error<
   "'__thread' is only allowed on variable declarations">;
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index c557e61..2022b4a 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -636,6 +636,46 @@
   return !FirstDecl;
 }
 
+void DeclContext::removeDecl(Decl *D) {
+  assert(D->getLexicalDeclContext() == this &&
+         "decl being removed from non-lexical context");
+  assert((D->NextDeclInContext || D == LastDecl) &&
+         "decl is not in decls list");
+
+  // Remove D from the decl chain.  This is O(n) but hopefully rare.
+  if (D == FirstDecl) {
+    if (D == LastDecl)
+      FirstDecl = LastDecl = 0;
+    else
+      FirstDecl = D->NextDeclInContext;
+  } else {
+    for (Decl *I = FirstDecl; true; I = I->NextDeclInContext) {
+      assert(I && "decl not found in linked list");
+      if (I->NextDeclInContext == D) {
+        I->NextDeclInContext = D->NextDeclInContext;
+        if (D == LastDecl) LastDecl = I;
+        break;
+      }
+    }
+  }
+  
+  // Mark that D is no longer in the decl chain.
+  D->NextDeclInContext = 0;
+
+  // Remove D from the lookup table if necessary.
+  if (isa<NamedDecl>(D)) {
+    NamedDecl *ND = cast<NamedDecl>(D);
+
+    void *OpaqueMap = getPrimaryContext()->LookupPtr;
+    if (!OpaqueMap) return;
+
+    StoredDeclsMap *Map = static_cast<StoredDeclsMap*>(OpaqueMap);
+    StoredDeclsMap::iterator Pos = Map->find(ND->getDeclName());
+    assert(Pos != Map->end() && "no lookup entry for decl");
+    Pos->second.remove(ND);
+  }
+}
+
 void DeclContext::addHiddenDecl(Decl *D) {
   assert(D->getLexicalDeclContext() == this &&
          "Decl inserted into wrong lexical context");
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index ad903a0..22e6b14 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -616,7 +616,8 @@
                                      bool IsFunctionDefinition,
                                      bool &Redeclaration);
   void AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
-  void CheckFunctionDeclaration(FunctionDecl *NewFD, LookupResult &Previous,
+  void CheckFunctionDeclaration(Scope *S,
+                                FunctionDecl *NewFD, LookupResult &Previous,
                                 bool IsExplicitSpecialization,
                                 bool &Redeclaration,
                                 bool &OverloadableAttrRequired);
@@ -839,7 +840,7 @@
     Ovl_NonFunction
   };
   OverloadKind CheckOverload(FunctionDecl *New,
-                             LookupResult &OldDecls,
+                             const LookupResult &OldDecls,
                              NamedDecl *&OldDecl);
   bool IsOverload(FunctionDecl *New, FunctionDecl *Old);
 
@@ -1123,6 +1124,10 @@
     /// namespace alias definition, ignoring non-namespace names (C++
     /// [basic.lookup.udir]p1).
     LookupNamespaceName,
+    /// Look up all declarations in a scope with the given name,
+    /// including resolved using declarations.  This is appropriate
+    /// for checking redeclarations for a using declaration.
+    LookupUsingDeclName,
     /// Look up an ordinary name that is going to be redeclared as a
     /// name with linkage. This lookup ignores any declarations that
     /// are outside of the current scope unless they have linkage. See
@@ -1154,6 +1159,7 @@
     case Sema::LookupTagName:
     case Sema::LookupMemberName:
     case Sema::LookupRedeclarationWithLinkage: // FIXME: check linkage, scoping
+    case Sema::LookupUsingDeclName:
     case Sema::LookupObjCProtocolName:
     case Sema::LookupObjCImplementationName:
     case Sema::LookupObjCCategoryImplName:
@@ -1739,9 +1745,17 @@
                                            SourceLocation IdentLoc,
                                            IdentifierInfo *Ident);
 
-  UsingShadowDecl *BuildUsingShadowDecl(Scope *S, AccessSpecifier AS,
-                                        UsingDecl *UD, NamedDecl *Target);
+  void HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow);
+  bool CheckUsingShadowDecl(UsingDecl *UD, NamedDecl *Target,
+                            const LookupResult &PreviousDecls);
+  UsingShadowDecl *BuildUsingShadowDecl(Scope *S, UsingDecl *UD,
+                                        NamedDecl *Target);
 
+  bool CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
+                                   bool isTypeName,
+                                   const CXXScopeSpec &SS,
+                                   SourceLocation NameLoc,
+                                   const LookupResult &Previous);
   bool CheckUsingDeclQualifier(SourceLocation UsingLoc,
                                const CXXScopeSpec &SS,
                                SourceLocation NameLoc);
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 55a5e7b..3fa7e65 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -3015,7 +3015,7 @@
     
   // Perform semantic checking on the function declaration.
   bool OverloadableAttrRequired = false; // FIXME: HACK!
-  CheckFunctionDeclaration(NewFD, Previous, isExplicitSpecialization,
+  CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization,
                            Redeclaration, /*FIXME:*/OverloadableAttrRequired);
 
   assert((NewFD->isInvalidDecl() || !Redeclaration ||
@@ -3137,7 +3137,7 @@
 /// an explicit specialization of the previous declaration.
 ///
 /// This sets NewFD->isInvalidDecl() to true if there was an error.
-void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD,
+void Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
                                     LookupResult &Previous,
                                     bool IsExplicitSpecialization,
                                     bool &Redeclaration,
@@ -3202,8 +3202,11 @@
 
       switch (CheckOverload(NewFD, Previous, OldDecl)) {
       case Ovl_Match:
-        // FIXME: hide or conflict with using shadow decls as appropriate
-        Redeclaration = !isa<UsingShadowDecl>(OldDecl);
+        Redeclaration = true;
+        if (isa<UsingShadowDecl>(OldDecl) && CurContext->isRecord()) {
+          HideUsingShadowDecl(S, cast<UsingShadowDecl>(OldDecl));
+          Redeclaration = false;
+        }
         break;
 
       case Ovl_NonFunction:
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index d977ad6..f97b763 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -2925,12 +2925,146 @@
   return DeclPtrTy::make(UD);
 }
 
+/// Determines whether to create a using shadow decl for a particular
+/// decl, given the set of decls existing prior to this using lookup.
+bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
+                                const LookupResult &Previous) {
+  // Diagnose finding a decl which is not from a base class of the
+  // current class.  We do this now because there are cases where this
+  // function will silently decide not to build a shadow decl, which
+  // will pre-empt further diagnostics.
+  //
+  // We don't need to do this in C++0x because we do the check once on
+  // the qualifier.
+  //
+  // FIXME: diagnose the following if we care enough:
+  //   struct A { int foo; };
+  //   struct B : A { using A::foo; };
+  //   template <class T> struct C : A {};
+  //   template <class T> struct D : C<T> { using B::foo; } // <---
+  // This is invalid (during instantiation) in C++03 because B::foo
+  // resolves to the using decl in B, which is not a base class of D<T>.
+  // We can't diagnose it immediately because C<T> is an unknown
+  // specialization.  The UsingShadowDecl in D<T> then points directly
+  // to A::foo, which will look well-formed when we instantiate.
+  // The right solution is to not collapse the shadow-decl chain.
+  if (!getLangOptions().CPlusPlus0x && CurContext->isRecord()) {
+    DeclContext *OrigDC = Orig->getDeclContext();
+
+    // Handle enums and anonymous structs.
+    if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent();
+    CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
+    while (OrigRec->isAnonymousStructOrUnion())
+      OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
+
+    if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
+      if (OrigDC == CurContext) {
+        Diag(Using->getLocation(),
+             diag::err_using_decl_nested_name_specifier_is_current_class)
+          << Using->getNestedNameRange();
+        Diag(Orig->getLocation(), diag::note_using_decl_target);
+        return true;
+      }
+
+      Diag(Using->getNestedNameRange().getBegin(),
+           diag::err_using_decl_nested_name_specifier_is_not_base_class)
+        << Using->getTargetNestedNameDecl()
+        << cast<CXXRecordDecl>(CurContext)
+        << Using->getNestedNameRange();
+      Diag(Orig->getLocation(), diag::note_using_decl_target);
+      return true;
+    }
+  }
+
+  if (Previous.empty()) return false;
+
+  NamedDecl *Target = Orig;
+  if (isa<UsingShadowDecl>(Target))
+    Target = cast<UsingShadowDecl>(Target)->getTargetDecl();
+
+  if (Target->isFunctionOrFunctionTemplate()) {
+    FunctionDecl *FD;
+    if (isa<FunctionTemplateDecl>(Target))
+      FD = cast<FunctionTemplateDecl>(Target)->getTemplatedDecl();
+    else
+      FD = cast<FunctionDecl>(Target);
+
+    NamedDecl *OldDecl = 0;
+    switch (CheckOverload(FD, Previous, OldDecl)) {
+    case Ovl_Overload:
+      return false;
+
+    case Ovl_NonFunction:
+      Diag(Using->getLocation(), diag::err_using_decl_conflict)
+        << 0  // target decl is a function
+        << 1; // other decl is not a function
+      break;
+      
+    // We found a decl with the exact signature.
+    case Ovl_Match:
+      if (isa<UsingShadowDecl>(OldDecl)) {
+        // Silently ignore the possible conflict.
+        return false;
+      }
+
+      // If we're in a record, we want to hide the target, so we
+      // return true (without a diagnostic) to tell the caller not to
+      // build a shadow decl.
+      if (CurContext->isRecord())
+        return true;
+
+      // If we're not in a record, this is an error.
+      Diag(Using->getLocation(), diag::err_using_decl_conflict)
+        << 0  // target decl is a function
+        << 0; // other decl is a function
+      break;
+    }
+
+    Diag(Target->getLocation(), diag::note_using_decl_target);
+    Diag(OldDecl->getLocation(), diag::note_using_decl_conflict);
+    return true;
+  }
+
+  // Target is not a function.
+
+  // If the target happens to be one of the previous declarations, we
+  // don't have a conflict.
+  NamedDecl *NonTag = 0, *Tag = 0;
+  for (LookupResult::iterator I = Previous.begin(), E = Previous.end();
+         I != E; ++I) {
+    NamedDecl *D = (*I)->getUnderlyingDecl();
+    if (D->getCanonicalDecl() == Target->getCanonicalDecl())
+      return false;
+
+    (isa<TagDecl>(D) ? Tag : NonTag) = D;
+  }
+
+  if (isa<TagDecl>(Target)) {
+    // No conflict between a tag and a non-tag.
+    if (!Tag) return false;
+
+    Diag(Using->getLocation(), diag::err_using_decl_conflict)
+      << 1 << 1; // both non-functions
+    Diag(Target->getLocation(), diag::note_using_decl_target);
+    Diag(Tag->getLocation(), diag::note_using_decl_conflict);
+    return true;
+  }
+
+  // No conflict between a tag and a non-tag.
+  if (!NonTag) return false;
+
+  Diag(Using->getLocation(), diag::err_using_decl_conflict)
+    << 1  // target not a function
+    << int(NonTag->isFunctionOrFunctionTemplate());
+  Diag(Target->getLocation(), diag::note_using_decl_target);
+  Diag(NonTag->getLocation(), diag::note_using_decl_conflict);
+  return true;
+}
+
 /// Builds a shadow declaration corresponding to a 'using' declaration.
 UsingShadowDecl *Sema::BuildUsingShadowDecl(Scope *S,
-                                            AccessSpecifier AS,
                                             UsingDecl *UD,
                                             NamedDecl *Orig) {
-  // FIXME: diagnose hiding, collisions
 
   // If we resolved to another shadow declaration, just coalesce them.
   NamedDecl *Target = Orig;
@@ -2948,45 +3082,56 @@
     PushOnScopeChains(Shadow, S);
   else
     CurContext->addDecl(Shadow);
-  Shadow->setAccess(AS);
+  Shadow->setAccess(UD->getAccess());
 
   if (Orig->isInvalidDecl() || UD->isInvalidDecl())
     Shadow->setInvalidDecl();
 
-  // If we haven't already declared the shadow decl invalid, check
-  // whether the decl comes from a base class of the current class.
-  // We don't have to do this in C++0x because we do the check once on
-  // the qualifier.
-  else if (!getLangOptions().CPlusPlus0x && CurContext->isRecord()) {
-    DeclContext *OrigDC = Orig->getDeclContext();
+  return Shadow;
+}
 
-    // Handle enums and anonymous structs.
-    if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent();
-    CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
-    while (OrigRec->isAnonymousStructOrUnion())
-      OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
+/// Hides a using shadow declaration.  This is required by the current
+/// using-decl implementation when a resolvable using declaration in a
+/// class is followed by a declaration which would hide or override
+/// one or more of the using decl's targets; for example:
+///
+///   struct Base { void foo(int); };
+///   struct Derived : Base {
+///     using Base::foo;
+///     void foo(int);
+///   };
+///
+/// The governing language is C++03 [namespace.udecl]p12:
+///
+///   When a using-declaration brings names from a base class into a
+///   derived class scope, member functions in the derived class
+///   override and/or hide member functions with the same name and
+///   parameter types in a base class (rather than conflicting).
+///
+/// There are two ways to implement this:
+///   (1) optimistically create shadow decls when they're not hidden
+///       by existing declarations, or
+///   (2) don't create any shadow decls (or at least don't make them
+///       visible) until we've fully parsed/instantiated the class.
+/// The problem with (1) is that we might have to retroactively remove
+/// a shadow decl, which requires several O(n) operations because the
+/// decl structures are (very reasonably) not designed for removal.
+/// (2) avoids this but is very fiddly and phase-dependent.
+void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) {
+  // Remove it from the DeclContext...
+  Shadow->getDeclContext()->removeDecl(Shadow);
 
-    if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
-      if (OrigDC == CurContext) {
-        Diag(UD->getLocation(),
-             diag::err_using_decl_nested_name_specifier_is_current_class)
-          << UD->getNestedNameRange();
-        Diag(Orig->getLocation(), diag::note_using_decl_target);
-        Shadow->setInvalidDecl();
-        return Shadow;
-      }
-
-      Diag(UD->getNestedNameRange().getBegin(),
-           diag::err_using_decl_nested_name_specifier_is_not_base_class)
-        << UD->getTargetNestedNameDecl()
-        << cast<CXXRecordDecl>(CurContext)
-        << UD->getNestedNameRange();
-      Diag(Orig->getLocation(), diag::note_using_decl_target);
-      return Shadow;
-    }
+  // ...and the scope, if applicable...
+  if (S) {
+    S->RemoveDecl(DeclPtrTy::make(static_cast<Decl*>(Shadow)));
+    IdResolver.RemoveDecl(Shadow);
   }
 
-  return Shadow;
+  // ...and the using decl.
+  Shadow->getUsingDecl()->removeShadowDecl(Shadow);
+
+  // TODO: complain somehow if Shadow was used.  It shouldn't
+  // be possible for this to happen, because 
 }
 
 /// Builds a using declaration.
@@ -3014,9 +3159,35 @@
     return 0;
   }
 
+  // Do the redeclaration lookup in the current scope.
+  LookupResult Previous(*this, Name, IdentLoc, LookupUsingDeclName,
+                        ForRedeclaration);
+  Previous.setHideTags(false);
+  if (S) {
+    LookupName(Previous, S);
+
+    // It is really dumb that we have to do this.
+    LookupResult::Filter F = Previous.makeFilter();
+    while (F.hasNext()) {
+      NamedDecl *D = F.next();
+      if (!isDeclInScope(D, CurContext, S))
+        F.erase();
+    }
+    F.done();
+  } else {
+    assert(IsInstantiation && "no scope in non-instantiation");
+    assert(CurContext->isRecord() && "scope not record in instantiation");
+    LookupQualifiedName(Previous, CurContext);
+  }
+
   NestedNameSpecifier *NNS =
     static_cast<NestedNameSpecifier *>(SS.getScopeRep());
 
+  // Check for invalid redeclarations.
+  if (CheckUsingDeclRedeclaration(UsingLoc, IsTypeName, SS, IdentLoc, Previous))
+    return 0;
+
+  // Check for bad qualifiers.
   if (CheckUsingDeclQualifier(UsingLoc, SS, IdentLoc))
     return 0;
 
@@ -3106,12 +3277,71 @@
     return UD;
   }
 
-  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
-    BuildUsingShadowDecl(S, AS, UD, *I);
+  for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
+    if (!CheckUsingShadowDecl(UD, *I, Previous))
+      BuildUsingShadowDecl(S, UD, *I);
+  }
 
   return UD;
 }
 
+/// Checks that the given using declaration is not an invalid
+/// redeclaration.  Note that this is checking only for the using decl
+/// itself, not for any ill-formedness among the UsingShadowDecls.
+bool Sema::CheckUsingDeclRedeclaration(SourceLocation UsingLoc,
+                                       bool isTypeName,
+                                       const CXXScopeSpec &SS,
+                                       SourceLocation NameLoc,
+                                       const LookupResult &Prev) {
+  // C++03 [namespace.udecl]p8:
+  // C++0x [namespace.udecl]p10:
+  //   A using-declaration is a declaration and can therefore be used
+  //   repeatedly where (and only where) multiple declarations are
+  //   allowed.
+  // That's only in file contexts.
+  if (CurContext->getLookupContext()->isFileContext())
+    return false;
+
+  NestedNameSpecifier *Qual
+    = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
+
+  for (LookupResult::iterator I = Prev.begin(), E = Prev.end(); I != E; ++I) {
+    NamedDecl *D = *I;
+
+    bool DTypename;
+    NestedNameSpecifier *DQual;
+    if (UsingDecl *UD = dyn_cast<UsingDecl>(D)) {
+      DTypename = UD->isTypeName();
+      DQual = UD->getTargetNestedNameDecl();
+    } else if (UnresolvedUsingValueDecl *UD
+                 = dyn_cast<UnresolvedUsingValueDecl>(D)) {
+      DTypename = false;
+      DQual = UD->getTargetNestedNameSpecifier();
+    } else if (UnresolvedUsingTypenameDecl *UD
+                 = dyn_cast<UnresolvedUsingTypenameDecl>(D)) {
+      DTypename = true;
+      DQual = UD->getTargetNestedNameSpecifier();
+    } else continue;
+
+    // using decls differ if one says 'typename' and the other doesn't.
+    // FIXME: non-dependent using decls?
+    if (isTypeName != DTypename) continue;
+
+    // using decls differ if they name different scopes (but note that
+    // template instantiation can cause this check to trigger when it
+    // didn't before instantiation).
+    if (Context.getCanonicalNestedNameSpecifier(Qual) !=
+        Context.getCanonicalNestedNameSpecifier(DQual))
+      continue;
+
+    Diag(NameLoc, diag::err_using_decl_redeclaration) << SS.getRange();
+    Diag(D->getLocation(), diag::note_previous_using_decl);
+    return true;
+  }
+
+  return false;
+}
+
 
 /// Checks that the given nested-name qualifier used in a using decl
 /// in the current context is appropriately related to the current
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 48d7320..66c846b 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -222,6 +222,11 @@
     IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Member;
     break;
 
+  case Sema::LookupUsingDeclName:
+    IDNS = Decl::IDNS_Ordinary | Decl::IDNS_Tag
+         | Decl::IDNS_Member | Decl::IDNS_Using;
+    break;
+
   case Sema::LookupObjCProtocolName:
     IDNS = Decl::IDNS_ObjCProtocol;
     break;
@@ -245,7 +250,7 @@
 /// Resolves the result kind of this lookup.
 void LookupResult::resolveKind() {
   unsigned N = Decls.size();
-
+ 
   // Fast case: no possible ambiguity.
   if (N == 0) {
     assert(ResultKind == NotFound);
@@ -613,6 +618,7 @@
     case Sema::LookupOperatorName:
     case Sema::LookupNestedNameSpecifierName:
     case Sema::LookupNamespaceName:
+    case Sema::LookupUsingDeclName:
       assert(false && "C does not perform these kinds of name lookup");
       break;
 
@@ -928,6 +934,9 @@
     case LookupTagName:
       BaseCallback = &CXXRecordDecl::FindTagMember;
       break;
+
+    case LookupUsingDeclName:
+      // This lookup is for redeclarations only.
       
     case LookupOperatorName:
     case LookupNamespaceName:
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 9ca8d76..522272e 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -287,7 +287,8 @@
 // signature), IsOverload returns false and MatchedDecl will be set to
 // point to the FunctionDecl for #2.
 Sema::OverloadKind
-Sema::CheckOverload(FunctionDecl *New, LookupResult &Old, NamedDecl *&Match) {
+Sema::CheckOverload(FunctionDecl *New, const LookupResult &Old,
+                    NamedDecl *&Match) {
   for (LookupResult::iterator I = Old.begin(), E = Old.end();
          I != E; ++I) {
     NamedDecl *OldD = (*I)->getUnderlyingDecl();
@@ -301,12 +302,18 @@
         Match = *I;
         return Ovl_Match;
       }
-    } else if (!isa<UnresolvedUsingValueDecl>(OldD)) {
+    } else if (isa<UsingDecl>(OldD) || isa<TagDecl>(OldD)) {
+      // We can overload with these, which can show up when doing
+      // redeclaration checks for UsingDecls.
+      assert(Old.getLookupKind() == LookupUsingDeclName);
+    } else if (isa<UnresolvedUsingValueDecl>(OldD)) {
+      // Optimistically assume that an unresolved using decl will
+      // overload; if it doesn't, we'll have to diagnose during
+      // template instantiation.
+    } else {
       // (C++ 13p1):
       //   Only function declarations can be overloaded; object and type
       //   declarations cannot be overloaded.
-      // But we permit unresolved using value decls and diagnose the error
-      // during template instantiation.
       Match = *I;
       return Ovl_NonFunction;
     }
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 80dcfd4..07e9711 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -708,7 +708,8 @@
       Previous.clear();
   }
   
-  SemaRef.CheckFunctionDeclaration(Function, Previous, false, Redeclaration,
+  SemaRef.CheckFunctionDeclaration(/*Scope*/ 0, Function, Previous,
+                                   false, Redeclaration,
                                    /*FIXME:*/OverloadableAttrRequired);
 
   // If the original function was part of a friend declaration,
@@ -868,7 +869,7 @@
 
   bool Redeclaration = false;
   bool OverloadableAttrRequired = false;
-  SemaRef.CheckFunctionDeclaration(Method, Previous, false, Redeclaration,
+  SemaRef.CheckFunctionDeclaration(0, Method, Previous, false, Redeclaration,
                                    /*FIXME:*/OverloadableAttrRequired);
 
   if (D->isPure())
@@ -1040,6 +1041,14 @@
   // The nested name specifier is non-dependent, so no transformation
   // is required.
 
+  // We only need to do redeclaration lookups if we're in a class
+  // scope (in fact, it's not really even possible in non-class
+  // scopes).
+  bool CheckRedeclaration = Owner->isRecord();
+
+  LookupResult Prev(SemaRef, D->getDeclName(), D->getLocation(),
+                    Sema::LookupUsingDeclName, Sema::ForRedeclaration);
+
   UsingDecl *NewUD = UsingDecl::Create(SemaRef.Context, Owner,
                                        D->getLocation(),
                                        D->getNestedNameRange(),
@@ -1051,34 +1060,55 @@
   CXXScopeSpec SS;
   SS.setScopeRep(D->getTargetNestedNameDecl());
   SS.setRange(D->getNestedNameRange());
-  if (SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
+
+  if (CheckRedeclaration) {
+    Prev.setHideTags(false);
+    SemaRef.LookupQualifiedName(Prev, Owner);
+
+    // Check for invalid redeclarations.
+    if (SemaRef.CheckUsingDeclRedeclaration(D->getUsingLocation(),
+                                            D->isTypeName(), SS,
+                                            D->getLocation(), Prev))
+      NewUD->setInvalidDecl();
+
+  }
+
+  if (!NewUD->isInvalidDecl() &&
+      SemaRef.CheckUsingDeclQualifier(D->getUsingLocation(), SS,
                                       D->getLocation()))
     NewUD->setInvalidDecl();
+
   SemaRef.Context.setInstantiatedFromUsingDecl(NewUD, D);
   NewUD->setAccess(D->getAccess());
   Owner->addDecl(NewUD);
 
-  // We'll transform the UsingShadowDecls as we reach them.
+  // Don't process the shadow decls for an invalid decl.
+  if (NewUD->isInvalidDecl())
+    return NewUD;
+
+  // Process the shadow decls.
+  for (UsingDecl::shadow_iterator I = D->shadow_begin(), E = D->shadow_end();
+         I != E; ++I) {
+    UsingShadowDecl *Shadow = *I;
+    NamedDecl *InstTarget =
+      cast<NamedDecl>(SemaRef.FindInstantiatedDecl(Shadow->getTargetDecl(),
+                                                   TemplateArgs));
+
+    if (CheckRedeclaration &&
+        SemaRef.CheckUsingShadowDecl(NewUD, InstTarget, Prev))
+      continue;
+
+    UsingShadowDecl *InstShadow
+      = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0, NewUD, InstTarget);
+    SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstShadow, Shadow);
+  }
 
   return NewUD;
 }
 
 Decl *TemplateDeclInstantiator::VisitUsingShadowDecl(UsingShadowDecl *D) {
-  UsingDecl *InstUsing =
-    cast<UsingDecl>(SemaRef.FindInstantiatedDecl(D->getUsingDecl(),
-                                                 TemplateArgs));
-  NamedDecl *InstTarget =
-    cast<NamedDecl>(SemaRef.FindInstantiatedDecl(D->getTargetDecl(),
-                                                 TemplateArgs));
-
-  UsingShadowDecl *InstD = SemaRef.BuildUsingShadowDecl(/*Scope*/ 0,
-                                                        D->getAccess(),
-                                                        InstUsing,
-                                                        InstTarget);
-
-  SemaRef.Context.setInstantiatedFromUsingShadowDecl(InstD, D);
-
-  return InstD;
+  // Ignore these;  we handle them in bulk when processing the UsingDecl.
+  return 0;
 }
 
 Decl * TemplateDeclInstantiator
@@ -2087,7 +2117,10 @@
                                    ParentDC->decls_end());
     }
 
-    assert(Result && "Unable to find instantiation of declaration!");
+    // UsingShadowDecls can instantiate to nothing because of using hiding.
+    assert((Result || isa<UsingShadowDecl>(D))
+           && "Unable to find instantiation of declaration!");
+
     D = Result;
   }
 
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 73ca797..be3c043 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -4506,8 +4506,14 @@
   for (UnresolvedLookupExpr::decls_iterator I = Old->decls_begin(),
          E = Old->decls_end(); I != E; ++I) {
     NamedDecl *InstD = static_cast<NamedDecl*>(getDerived().TransformDecl(*I));
-    if (!InstD)
-      return SemaRef.ExprError();
+    if (!InstD) {
+      // Silently ignore these if a UsingShadowDecl instantiated to nothing.
+      // This can happen because of dependent hiding.
+      if (isa<UsingShadowDecl>(*I))
+        continue;
+      else
+        return SemaRef.ExprError();
+    }
 
     // Expand using declarations.
     if (isa<UsingDecl>(InstD)) {
@@ -4913,8 +4919,14 @@
   for (UnresolvedMemberExpr::decls_iterator I = Old->decls_begin(),
          E = Old->decls_end(); I != E; ++I) {
     NamedDecl *InstD = static_cast<NamedDecl*>(getDerived().TransformDecl(*I));
-    if (!InstD)
-      return SemaRef.ExprError();
+    if (!InstD) {
+      // Silently ignore these if a UsingShadowDecl instantiated to nothing.
+      // This can happen because of dependent hiding.
+      if (isa<UsingShadowDecl>(*I))
+        continue;
+      else
+        return SemaRef.ExprError();
+    }
 
     // Expand using declarations.
     if (isa<UsingDecl>(InstD)) {
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp
new file mode 100644
index 0000000..e6b8fc1
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p10.cpp
@@ -0,0 +1,19 @@
+// RUN: clang -fsyntax-only -verify %s
+
+namespace test0 {
+  namespace ns0 {
+    class tag;
+    int tag();
+  }
+
+  namespace ns1 {
+    using ns0::tag;
+  }
+
+  namespace ns2 {
+    using ns0::tag;
+  }
+
+  using ns1::tag;
+  using ns2::tag;
+}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
index 9386e6c..30d43ec 100644
--- a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p12.cpp
@@ -1,6 +1,13 @@
 // RUN: clang -fsyntax-only -verify %s
 
+// C++03 [namespace.udecl]p12:
+//   When a using-declaration brings names from a base class into a
+//   derived class scope, member functions in the derived class
+//   override and/or hide member functions with the same name and
+//   parameter types in a base class (rather than conflicting).
+
 // PR5727
+// This just shouldn't crash.
 namespace test0 {
   template<typename> struct RefPtr { };
   template<typename> struct PtrHash {
@@ -11,3 +18,84 @@
     static void f() { f(); }
   };
 }
+
+// Simple hiding.
+namespace test1 {
+  template <unsigned n> struct Opaque {};
+  struct Base {
+    Opaque<0> foo(Opaque<0>);
+    Opaque<0> foo(Opaque<1>);
+    Opaque<0> foo(Opaque<2>);
+  };
+
+  // using before decls
+  struct Test0 : Base {
+    using Base::foo;
+    Opaque<1> foo(Opaque<1>);
+    Opaque<1> foo(Opaque<3>);
+
+    void test0() { Opaque<0> _ = foo(Opaque<0>()); }
+    void test1() { Opaque<1> _ = foo(Opaque<1>()); }
+    void test2() { Opaque<0> _ = foo(Opaque<2>()); }
+    void test3() { Opaque<1> _ = foo(Opaque<3>()); }
+  };
+
+  // using after decls
+  struct Test1 : Base {
+    Opaque<1> foo(Opaque<1>);
+    Opaque<1> foo(Opaque<3>);
+    using Base::foo;
+
+    void test0() { Opaque<0> _ = foo(Opaque<0>()); }
+    void test1() { Opaque<1> _ = foo(Opaque<1>()); }
+    void test2() { Opaque<0> _ = foo(Opaque<2>()); }
+    void test3() { Opaque<1> _ = foo(Opaque<3>()); }
+  };
+
+  // using between decls
+  struct Test2 : Base {
+    Opaque<1> foo(Opaque<0>);
+    using Base::foo;
+    Opaque<1> foo(Opaque<2>);
+    Opaque<1> foo(Opaque<3>);
+
+    void test0() { Opaque<1> _ = foo(Opaque<0>()); }
+    void test1() { Opaque<0> _ = foo(Opaque<1>()); }
+    void test2() { Opaque<1> _ = foo(Opaque<2>()); }
+    void test3() { Opaque<1> _ = foo(Opaque<3>()); }
+  };
+}
+
+// Crazy dependent hiding.
+namespace test2 {
+  struct Base {
+    void foo(int);
+  };
+
+  template <typename T> struct Derived1 : Base {
+    using Base::foo;
+    void foo(T);
+
+    void testUnresolved(int i) { foo(i); }
+  };
+
+  void test0(int i) {
+    Derived1<int> d1;
+    d1.foo(i);
+    d1.testUnresolved(i);
+  }
+
+  // Same thing, except with the order of members reversed.
+  template <typename T> struct Derived2 : Base {
+    void foo(T);
+    using Base::foo;
+
+    void testUnresolved(int i) { foo(i); }
+  };
+
+  void test1(int i) {
+    Derived2<int> d2;
+    d2.foo(i);
+    d2.testUnresolved(i);
+  }
+}
diff --git a/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp
new file mode 100644
index 0000000..bf0f330
--- /dev/null
+++ b/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p8.cpp
@@ -0,0 +1,83 @@
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct Opaque0 {};
+struct Opaque1 {};
+
+// Redeclarations are okay in a namespace.
+namespace test0 {
+  namespace ns {
+    void foo(Opaque0); // expected-note 2 {{candidate function}}
+  }
+
+  using ns::foo;
+  using ns::foo;
+
+  void test0() {
+    foo(Opaque1()); // expected-error {{no matching function for call}}
+  }
+
+  namespace ns {
+    void foo(Opaque1);
+  }
+
+  void test1() {
+    foo(Opaque1()); // expected-error {{no matching function for call}}
+  }
+
+  using ns::foo;
+
+  void test2() {
+    foo(Opaque1());
+  }
+
+  using ns::foo;
+}
+
+// Make sure we handle transparent contexts the same way.
+namespace test1 {
+  namespace ns {
+    void foo(Opaque0); // expected-note 2 {{candidate function}}
+  }
+
+  extern "C++" {
+    using ns::foo;
+  }
+
+  void test0() {
+    foo(Opaque1()); // expected-error {{no matching function for call}}
+  }
+
+  namespace ns {
+    void foo(Opaque1);
+  }
+
+  void test1() {
+    foo(Opaque1()); // expected-error {{no matching function for call}}
+  }
+
+  extern "C++" {
+    using ns::foo;
+  }
+
+  void test2() {
+    foo(Opaque1());
+  }
+}
+
+// Make sure we detect invalid redeclarations that can't be detected
+// until template instantiation.
+namespace test2 {
+  template <class T> struct Base {
+    typedef Base type;
+    void foo();
+  };
+
+  template <class T> struct Derived : Base<T> {
+    // These are invalid redeclarations, detectable only after
+    // instantiation.
+    using Base<T>::foo; // expected-note {{previous using decl}}
+    using Base<T>::type::foo; //expected-error {{redeclaration of using decl}}
+  };
+
+  template struct Derived<int>; // expected-note {{in instantiation of template class}}
+}