]> granicus.if.org Git - clang/commitdiff
Ensure that the tag decls of friend decls aren't added to the friending class's
authorJohn McCall <rjmccall@apple.com>
Wed, 2 Sep 2009 00:55:30 +0000 (00:55 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 2 Sep 2009 00:55:30 +0000 (00:55 +0000)
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

lib/AST/DeclBase.cpp
lib/AST/DeclPrinter.cpp
lib/Sema/SemaDecl.cpp
test/CXX/class/class.friend/p1.cpp
test/SemaCXX/friend-class-nodecl.cpp [new file with mode: 0644]

index c24dac9104253c205368ca0cf7de96260eef7826..acdbdbe4223b01809ded1990d8ed390854d2ac33 100644 (file)
@@ -385,11 +385,6 @@ void Decl::CheckAccessDeclContext() const {
       !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");
 }
index 275f2db82b52f84969612a64a24139f98be0c11f..275fa6972376275aebbf9b971924e063e06db63b 100644 (file)
@@ -203,9 +203,7 @@ void DeclPrinter::VisitDeclContext(DeclContext *DC, bool Indent) {
     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;
index 8eb2c717b4177ed7a3eedcb6f600664f053cc54a..86222ffe14727324d067b7f40b2bb8eaa3eab662 100644 (file)
@@ -4328,7 +4328,15 @@ CreateNewDecl:
     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 {
index 5a9114006f04db09716365f16b851eafe27f17af..9ba02727a0682cb76d3fbe8fab0c4eab6060cc5a 100644 (file)
@@ -63,8 +63,6 @@ class A {
   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 (file)
index 0000000..de12eaf
--- /dev/null
@@ -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;
+};
+