friend.c (do_friend): Remove check for existing decl.
authorNathan Sidwell <nathan@acm.org>
Wed, 24 May 2017 23:18:58 +0000 (23:18 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Wed, 24 May 2017 23:18:58 +0000 (23:18 +0000)
cp/
* friend.c (do_friend): Remove check for existing decl.
* name-lookup.h (lookup_name_innermost_nonclass_level): Delete.
* name-lookup.c (push_local_binding): Directly look for binding.
(lookup_name_innermost_nonclass_level_1): Delete.
(lookup_name_innermost_nonclass_level): Delete.

testsuite/
* g++.dg/lookup/friend12.C: Adjust diagnostics.
* g++.dg/lookup/friend19.C: New.
* g++.dg/lookup/friend20.C: New.

From-SVN: r248435

gcc/cp/ChangeLog
gcc/cp/friend.c
gcc/cp/name-lookup.c
gcc/cp/name-lookup.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/friend12.C
gcc/testsuite/g++.dg/lookup/friend19.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/friend20.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.jason/scoping12.C

index f396832b8a666747796bb3155162bab944ddcc53..29c95c39da8f55762838582a61750f15e3b99d97 100644 (file)
@@ -1,5 +1,11 @@
 2017-05-24  Nathan Sidwell  <nathan@acm.org>
 
+       * friend.c (do_friend): Remove check for existing decl.
+       * name-lookup.h (lookup_name_innermost_nonclass_level): Delete.
+       * name-lookup.c (push_local_binding): Directly look for binding.
+       (lookup_name_innermost_nonclass_level_1): Delete.
+       (lookup_name_innermost_nonclass_level): Delete.
+
        * Make-lang.in (CXX_AND_OBJCXX_OBJS): Alphabetize.
 
        * cp-tree.h (cp_free_lang_data): Add extern.
index 194ee168298d6d30c0038fc62e006df5fb309be5..a3c2ed094721c443ca03097725e04ff54c6f54e6 100644 (file)
@@ -608,25 +608,8 @@ do_friend (tree ctype, tree declarator, tree decl,
               is instantiated.  */
            decl = push_template_decl_real (decl, /*is_friend=*/true);
          else if (current_function_decl)
-           {
-             /* This must be a local class.  11.5p11:
-
-                If a friend declaration appears in a local class (9.8) and
-                the name specified is an unqualified name, a prior
-                declaration is looked up without considering scopes that
-                are outside the innermost enclosing non-class scope. For a
-                friend function declaration, if there is no prior
-                declaration, the program is ill-formed.  */
-             tree t = lookup_name_innermost_nonclass_level (DECL_NAME (decl));
-             if (t)
-               decl = pushdecl (decl, /*is_friend=*/true);
-             else
-               {
-                 error ("friend declaration %qD in local class without "
-                        "prior declaration", decl);
-                 return error_mark_node;
-               }
-           }
+           /* pushdecl will check there's a local decl already.  */
+           decl = pushdecl (decl, /*is_friend=*/true);
          else
            {
              /* We can't use pushdecl, as we might be in a template
index 88fd7edcb21f2b13e4c8d2179bebbd1e412a660c..c689702722edc6eac2a35ae24012ecb2629e12ab 100644 (file)
@@ -2103,7 +2103,13 @@ push_local_binding (tree id, tree decl, bool is_using)
      push_local_binding with a friend decl of a local class.  */
   b = innermost_nonclass_level ();
 
-  if (lookup_name_innermost_nonclass_level (id))
+  cxx_binding *binding = NULL;
+  if (b->kind == sk_namespace)
+    binding = find_namespace_binding (current_namespace, id);
+  else
+    binding = find_local_binding (b, id);
+
+  if (binding)
     {
       /* Supplement the existing binding.  */
       if (!supplement_binding (IDENTIFIER_BINDING (id), decl))
@@ -5430,37 +5436,6 @@ lookup_type_scope (tree name, tag_scope scope)
   return ret;
 }
 
-
-/* Similar to `lookup_name' but look only in the innermost non-class
-   binding level.  */
-
-static tree
-lookup_name_innermost_nonclass_level_1 (tree name)
-{
-  cp_binding_level *b = innermost_nonclass_level ();
-  cxx_binding *binding = NULL;
-
-  if (b->kind == sk_namespace)
-    binding = find_namespace_binding (current_namespace, name);
-  else
-    binding = find_local_binding (b, name);
-
-  return binding ? binding->value : NULL_TREE;
-}
-
-/* Wrapper for lookup_name_innermost_nonclass_level_1.  */
-
-tree
-lookup_name_innermost_nonclass_level (tree name)
-{
-  tree ret;
-  bool subtime = timevar_cond_start (TV_NAME_LOOKUP);
-  ret = lookup_name_innermost_nonclass_level_1 (name);
-  timevar_cond_stop (TV_NAME_LOOKUP, subtime);
-  return ret;
-}
-
-
 /* Returns true iff DECL is a block-scope extern declaration of a function
    or variable.  */
 
index f0df1c9c30d0450b73f8ea778eebb068b7a5981d..637599c9be1b9035c61eeeef009dd66f0fc2cd6f 100644 (file)
@@ -310,7 +310,6 @@ extern tree get_namespace_binding (tree ns, tree id);
 extern void set_global_binding (tree id, tree val);
 extern tree lookup_qualified_name (tree, tree, int, bool, /*hidden*/bool = false);
 extern tree lookup_name_nonclass (tree);
-extern tree lookup_name_innermost_nonclass_level (tree);
 extern bool is_local_extern (tree);
 extern tree lookup_function_nonclass (tree, vec<tree, va_gc> *, bool);
 extern bool pushdecl_class_level (tree);
index cc8e09d9a229488d3de1c5a36bc9d4c69f2f5cbc..84026e31153439cc928631e4979b65fed81cfc81 100644 (file)
@@ -1,3 +1,9 @@
+2017-05-24  Nathan Sidwell  <nathan@acm.org>
+
+       * g++.dg/lookup/friend12.C: Adjust diagnostics.
+       * g++.dg/lookup/friend19.C: New.
+       * g++.dg/lookup/friend20.C: New.
+
 2017-05-24  Jonathan Wakely  <jwakely@redhat.com>
 
        PR c++/80544
index 98f508bbe86bf1630e8d853339dfa3c21fb8fc91..eb61fb5237869b32fe7a43aab7c6babfc0e9e58f 100644 (file)
@@ -2,9 +2,9 @@
 
 void foo()
 {
+  extern void bar (int); // not the bar we are looking for
   struct A
   {
-    friend void bar();         // { dg-error "without prior declaration" }
+    friend void bar(); // { dg-error "without prior local declaration" }
   };
-  bar();                       // { dg-error "3:'bar' was not declared" }
 }
diff --git a/gcc/testsuite/g++.dg/lookup/friend19.C b/gcc/testsuite/g++.dg/lookup/friend19.C
new file mode 100644 (file)
index 0000000..346204b
--- /dev/null
@@ -0,0 +1,29 @@
+// Make sure unhiding friends doesn't unhide similarly named friends
+
+struct X
+{
+  friend int foo (X);
+};
+
+struct Y
+{
+  friend int foo (Y);
+};
+
+void Baz ()
+{
+  foo (X());
+  foo (Y());
+}
+
+int foo (Y);
+int foo (int);
+// foo(X) still hidden
+
+void Bar ()
+{
+  foo (X());
+  foo (Y());
+  ::foo (X()); // { dg-error "" }
+  ::foo (Y());
+}
diff --git a/gcc/testsuite/g++.dg/lookup/friend20.C b/gcc/testsuite/g++.dg/lookup/friend20.C
new file mode 100644 (file)
index 0000000..ecdc763
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/80830
+
+template <int> class a;
+class b
+{
+  friend int operator>> (int, b);
+};
+template <int c> int &operator>> (int &, a<c> &);
+template <int = 3> class a
+{
+  friend int &operator>><> (int &, a &);
+  a<>
+  d ()
+  {
+  }
+};
index 35731e78f67180d091f56d002202727f9c0e3957..38915a7ffab5dfe4274986c856cc13918b3e99e1 100644 (file)
@@ -2,9 +2,9 @@
 void f ()
 {
   struct A {
-    friend void g ();          // { dg-error "without prior declaration" }
+    friend void g ();  // { dg-error "without prior local declaration" }
   };
 }
 void h () {
-  g ();                                // { dg-error "3:'g' was not declared" } no g in scope
+  g ();                        // { dg-error "3:'g' was not declared" } no g in scope
 }