OSDN Git Service

cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 8 Jun 2001 12:49:02 +0000 (12:49 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 8 Jun 2001 12:49:02 +0000 (12:49 +0000)
PR c++/2929
* friend.c (do_friend): Use push_decl_namespace for classes at
namespace scope.
testsuite:
* g++.old-deja/g++.pt/friend49.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@43013 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/friend.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.old-deja/g++.pt/friend49.C [new file with mode: 0644]

index 1fa95c8..5b03f59 100644 (file)
@@ -1,4 +1,10 @@
 2001-06-08  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/2929
+       * friend.c (do_friend): Use push_decl_namespace for classes at
+       namespace scope.
+
+2001-06-08  Nathan Sidwell  <nathan@codesourcery.com>
            Jason Merrill <jason_merrill@redhat.com>
 
        PR c++/3061
index 913ed9c..8b2e8f8 100644 (file)
@@ -388,18 +388,31 @@ do_friend (ctype, declarator, decl, parmdecls, attrlist,
                      && current_template_parms
                      && uses_template_parms (decl));
 
-         /* We can call pushdecl here, because the TREE_CHAIN of this
-            FUNCTION_DECL is not needed for other purposes.  Don't do
-            this for a template instantiation.  However, we don't
-            call pushdecl() for a friend function of a template
-            class, since in general, such a declaration depends on
-            template parameters.  Instead, we call pushdecl when the
-            class is instantiated.  */
-         if (!is_friend_template
-             && template_class_depth (current_class_type) == 0)
-           decl = pushdecl (decl);
-         else 
+         if (is_friend_template
+             || template_class_depth (current_class_type) != 0)
+           /* We can't call pushdecl for a template class, since in
+              general, such a declaration depends on template
+              parameters.  Instead, we call pushdecl when the class
+              is instantiated.  */
            decl = push_template_decl_real (decl, /*is_friend=*/1); 
+         else if (current_function_decl)
+           /* This must be a local class, so pushdecl will be ok, and
+              insert an unqualified friend into the local scope
+              (rather than the containing namespace scope, which the
+              next choice will do). */
+           decl = pushdecl (decl);
+         else
+           {
+             /* We can't use pushdecl, as we might be in a template
+                class specialization, and pushdecl will insert an
+                unqualified friend decl into the template parameter
+                scope, rather than the namespace containing it. */
+             tree ns = decl_namespace_context (decl);
+             
+             push_nested_namespace (ns);
+             decl = pushdecl_namespace_level (decl);
+             pop_nested_namespace (ns);
+           }
 
          if (warn)
            {
index 4a77568..1c83b60 100644 (file)
@@ -1,3 +1,7 @@
+2001-06-08  Nathan Sidwell  <nathan@codesourcery.com>
+
+       * g++.old-deja/g++.pt/friend49.C: New test.
+
 2001-06-07  Nathan Sidwell  <nathan@codesourcery.com>
 
        * g++.old-deja/g++.ext/anon3.C: New test.
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend49.C b/gcc/testsuite/g++.old-deja/g++.pt/friend49.C
new file mode 100644 (file)
index 0000000..3b243f0
--- /dev/null
@@ -0,0 +1,26 @@
+// Build don't link:
+
+// Copyright (C) 2001 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 5 Jun 2001 <nathan@codesourcery.com>
+
+// Bug 2929. We were forgetting about template parm scope when
+// injecting a friend decl into a class template specialization's
+// containing scope.
+
+template <class Type> class Vec;
+
+template <> class Vec<double>
+{
+public:
+  Vec ();
+  Vec<double> & Fn (double);
+  friend Vec<double> Fn (const Vec<double> &, double);
+}; // pop_binding ICE
+
+template <class _Tp> class Alloc
+{
+  template <class _Tp1> struct Rebind
+  {
+    typedef Alloc<_Tp1> other;
+  };
+};