Ensure that the tag decls of friend decls aren't added to the friending class's
decl list, and remove some workarounds that were due to this.  Thanks to Eli for
pointing this out and providing the test case.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@80745 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index c24dac9..acdbdbe 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -385,11 +385,6 @@
       !isa<CXXRecordDecl>(getDeclContext()))
     return;
   
-  // FIXME: This check should not be necessary - If a friend decl refers to an
-  // undeclared decl, then that decl shouldn't be in any decl context.
-  if (getFriendObjectKind() == FOK_Undeclared)
-    return;
-  
   assert(Access != AS_none && 
          "Access specifier is AS_none inside a record decl");
 }
diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp
index 275f2db..275fa69 100644
--- a/lib/AST/DeclPrinter.cpp
+++ b/lib/AST/DeclPrinter.cpp
@@ -203,9 +203,7 @@
     if (PrintAccess) {
       AccessSpecifier AS = D->getAccess();
 
-      if (AS != CurAS && 
-          // FIXME: This check shouldn't be necessary.
-          D->getFriendObjectKind() == Decl::FOK_Undeclared) {
+      if (AS != CurAS) {
         Print(AS);
         Out << ":\n";
         CurAS = AS;
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 8eb2c71..86222ff 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -4328,7 +4328,15 @@
     New->startDefinition();
   
   // If this has an identifier, add it to the scope stack.
-  if (Name && TUK != TUK_Friend) {
+  if (TUK == TUK_Friend) {
+    // Friend tag decls are visible in fairly strange ways.
+    if (!CurContext->isDependentContext()) {
+      DeclContext *DC = New->getDeclContext()->getLookupContext();
+      DC->makeDeclVisibleInContext(New, /* Recoverable = */ false);
+      if (Scope *EnclosingScope = getScopeForDeclContext(S, DC))
+        PushOnScopeChains(New, EnclosingScope, /* AddToContext = */ false);
+    }
+  } else if (Name) {
     S = getNonFieldDeclScope(S);
     PushOnScopeChains(New, S);
   } else {
diff --git a/test/CXX/class/class.friend/p1.cpp b/test/CXX/class/class.friend/p1.cpp
index 5a91140..9ba0272 100644
--- a/test/CXX/class/class.friend/p1.cpp
+++ b/test/CXX/class/class.friend/p1.cpp
@@ -63,8 +63,6 @@
   friend ftypedef typedeffed_function; // okay (because it's not declared as a member)
 };
 
-class UndeclaredSoFar { };
-
 A::UndeclaredSoFar y; // expected-error {{ unknown type name 'UndeclaredSoFar' }}
 
 class PreDeclared;
diff --git a/test/SemaCXX/friend-class-nodecl.cpp b/test/SemaCXX/friend-class-nodecl.cpp
new file mode 100644
index 0000000..de12eaf
--- /dev/null
+++ b/test/SemaCXX/friend-class-nodecl.cpp
@@ -0,0 +1,10 @@
+// RUN: clang-cc -ast-print %s -o %t &&
+// RUN: not grep '^ *class B' %t
+
+// Tests that the tag decls in friend declarations aren't added to the
+// declaring class's decl chain.
+
+class A {
+  friend class B;
+};
+