Revert r186040 to fix PR16597 while Richard investigates what the best
fix is.

Original commit log:
  If we friend a declaration twice, that should not make it visible to
  name lookup in the surrounding context. Slightly rework how we handle
  friend declarations to inherit the visibility of the prior
  declaration, rather than setting a friend declaration to be visible
  whenever there was a prior declaration.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186185 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 2b2bf1a..e90f454 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -3402,12 +3402,6 @@
   First->RedeclLink = LatestDeclLink(static_cast<decl_type*>(this));
   assert(!isa<NamedDecl>(static_cast<decl_type*>(this)) ||
          cast<NamedDecl>(static_cast<decl_type*>(this))->isLinkageValid());
-
-  // If the declaration was previously visible, a redeclaration of it remains
-  // visible even if it wouldn't be visible by itself.
-  static_cast<decl_type*>(this)->IdentifierNamespace |=
-    First->getIdentifierNamespace() &
-    (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type);
 }
 
 // Inline function definitions.
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index 157506d..4f289d3 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -295,8 +295,6 @@
   friend class ASTReader;
   friend class LinkageComputer;
 
-  template<typename decl_type> friend class Redeclarable;
-
 private:
   void CheckAccessDeclContext() const;
 
@@ -826,7 +824,7 @@
   /// class, but in the semantic context of the actual entity.  This property
   /// applies only to a specific decl object;  other redeclarations of the
   /// same entity may not (and probably don't) share this property.
-  void setObjectOfFriendDecl(bool PerformFriendInjection = false) {
+  void setObjectOfFriendDecl(bool PreviouslyDeclared) {
     unsigned OldNS = IdentifierNamespace;
     assert((OldNS & (IDNS_Tag | IDNS_Ordinary |
                      IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
@@ -835,20 +833,15 @@
                        IDNS_TagFriend | IDNS_OrdinaryFriend)) &&
            "namespace includes other than ordinary or tag");
 
-    Decl *Prev = getPreviousDecl();
     IdentifierNamespace = 0;
     if (OldNS & (IDNS_Tag | IDNS_TagFriend)) {
       IdentifierNamespace |= IDNS_TagFriend;
-      if (PerformFriendInjection || 
-          (Prev && Prev->getIdentifierNamespace() & IDNS_Tag))
-        IdentifierNamespace |= IDNS_Tag | IDNS_Type;
+      if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type;
     }
 
     if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) {
       IdentifierNamespace |= IDNS_OrdinaryFriend;
-      if (PerformFriendInjection ||
-          (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary))
-        IdentifierNamespace |= IDNS_Ordinary;
+      if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary;
     }
   }
 
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index fd4ddcf..5e535da 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -6328,11 +6328,12 @@
     }
 
     if (isFriend) {
+      // For now, claim that the objects have no previous declaration.
       if (FunctionTemplate) {
-        FunctionTemplate->setObjectOfFriendDecl();
+        FunctionTemplate->setObjectOfFriendDecl(false);
         FunctionTemplate->setAccess(AS_public);
       }
-      NewFD->setObjectOfFriendDecl();
+      NewFD->setObjectOfFriendDecl(false);
       NewFD->setAccess(AS_public);
     }
 
@@ -6651,6 +6652,8 @@
 
       NewFD->setAccess(Access);
       if (FunctionTemplate) FunctionTemplate->setAccess(Access);
+
+      PrincipalDecl->setObjectOfFriendDecl(true);
     }
 
     if (NewFD->isOverloadedOperator() && !DC->isRecord() &&
@@ -10381,8 +10384,9 @@
   // declaration so we always pass true to setObjectOfFriendDecl to make
   // the tag name visible.
   if (TUK == TUK_Friend)
-    New->setObjectOfFriendDecl(!FriendSawTagOutsideEnclosingNamespace &&
-                               getLangOpts().MicrosoftExt);
+    New->setObjectOfFriendDecl(/* PreviouslyDeclared = */ !Previous.empty() ||
+                               (!FriendSawTagOutsideEnclosingNamespace &&
+                                getLangOpts().MicrosoftExt));
 
   // Set the access specifier.
   if (!Invalid && SearchDC->isRecord())
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index 0667b8a..8d954ca 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -2757,15 +2757,8 @@
       // If the only declaration here is an ordinary friend, consider
       // it only if it was declared in an associated classes.
       if (D->getIdentifierNamespace() == Decl::IDNS_OrdinaryFriend) {
-        bool DeclaredInAssociatedClass = false;
-        for (Decl *DI = D; DI; DI = D->getPreviousDecl()) {
-          DeclContext *LexDC = DI->getLexicalDeclContext();
-          if (AssociatedClasses.count(cast<CXXRecordDecl>(LexDC))) {
-            DeclaredInAssociatedClass = true;
-            break;
-          }
-        }
-        if (!DeclaredInAssociatedClass)
+        DeclContext *LexDC = D->getLexicalDeclContext();
+        if (!AssociatedClasses.count(cast<CXXRecordDecl>(LexDC)))
           continue;
       }
 
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 6f1ab19..e6006b6 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -1120,7 +1120,8 @@
       NewClass->setAccess(PrevClassTemplate->getAccess());
     }
 
-    NewTemplate->setObjectOfFriendDecl();
+    NewTemplate->setObjectOfFriendDecl(/* PreviouslyDeclared = */
+                                       PrevClassTemplate != NULL);
 
     // Friend templates are visible in fairly strange ways.
     if (!CurContext->isDependentContext()) {
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 14185c3..b5a80d3 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -960,7 +960,7 @@
     else
       Inst->setAccess(D->getAccess());
 
-    Inst->setObjectOfFriendDecl();
+    Inst->setObjectOfFriendDecl(PrevClassTemplate != 0);
     // TODO: do we want to track the instantiation progeny of this
     // friend target decl?
   } else {
@@ -1110,8 +1110,8 @@
 
   // If the original function was part of a friend declaration,
   // inherit its namespace state.
-  if (D->getFriendObjectKind())
-    Record->setObjectOfFriendDecl();
+  if (Decl::FriendObjectKind FOK = D->getFriendObjectKind())
+    Record->setObjectOfFriendDecl(FOK == Decl::FOK_Declared);
 
   // Make sure that anonymous structs and unions are recorded.
   if (D->isAnonymousStructOrUnion()) {
@@ -1315,7 +1315,7 @@
     assert(isFriend && "non-friend has dependent specialization info?");
 
     // This needs to be set now for future sanity.
-    Function->setObjectOfFriendDecl();
+    Function->setObjectOfFriendDecl(/*HasPrevious*/ true);
 
     // Instantiate the explicit template arguments.
     TemplateArgumentListInfo ExplicitArgs(Info->getLAngleLoc(),
@@ -1365,7 +1365,13 @@
   // If the original function was part of a friend declaration,
   // inherit its namespace state and add it to the owner.
   if (isFriend) {
-    PrincipalDecl->setObjectOfFriendDecl();
+    NamedDecl *PrevDecl;
+    if (TemplateParams)
+      PrevDecl = FunctionTemplate->getPreviousDecl();
+    else
+      PrevDecl = Function->getPreviousDecl();
+
+    PrincipalDecl->setObjectOfFriendDecl(PrevDecl != 0);
     DC->makeDeclVisibleInContext(PrincipalDecl);
 
     bool queuedInstantiation = false;
@@ -1633,7 +1639,7 @@
                                                     TemplateParams, Method);
     if (isFriend) {
       FunctionTemplate->setLexicalDeclContext(Owner);
-      FunctionTemplate->setObjectOfFriendDecl();
+      FunctionTemplate->setObjectOfFriendDecl(true);
     } else if (D->isOutOfLine())
       FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
     Method->setDescribedFunctionTemplate(FunctionTemplate);
@@ -1660,7 +1666,7 @@
                                             TempParamLists.data());
 
     Method->setLexicalDeclContext(Owner);
-    Method->setObjectOfFriendDecl();
+    Method->setObjectOfFriendDecl(true);
   } else if (D->isOutOfLine())
     Method->setLexicalDeclContext(D->getLexicalDeclContext());
 
diff --git a/test/CXX/temp/temp.decls/temp.friend/p4.cpp b/test/CXX/temp/temp.decls/temp.friend/p4.cpp
index 8571a14..e036cef 100644
--- a/test/CXX/temp/temp.decls/temp.friend/p4.cpp
+++ b/test/CXX/temp/temp.decls/temp.friend/p4.cpp
@@ -26,20 +26,3 @@
   X2<float> xf; 
   f(xf);
 }
-
-template<typename T>
-struct X3 {
-  operator int();
-
-  friend void h(int x);
-};
-
-int array2[sizeof(X3<int>)]; 
-int array3[sizeof(X3<float>)];
-
-void i() {
-  X3<int> xi;
-  h(xi);
-  X3<float> xf; 
-  h(xf);
-}
diff --git a/test/SemaCXX/friend.cpp b/test/SemaCXX/friend.cpp
index 60eb03d..ce2f34f 100644
--- a/test/SemaCXX/friend.cpp
+++ b/test/SemaCXX/friend.cpp
@@ -163,15 +163,3 @@
     friend void C::f(int, int, int) {}  // expected-error {{no function named 'f' with type 'void (int, int, int)' was found in the specified scope}}
   };
 }
-
-namespace test10 {
-  struct A {
-    friend void f10();
-  };
-  struct B {
-    friend void f10();
-  };
-  void g() {
-    f10(); // expected-error {{undeclared identifier}}
-  }
-}