]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/35109 (ICE in lookup_name_real, at cp/name-lookup.c:4056)
authorJason Merrill <jason@redhat.com>
Tue, 13 Jan 2009 01:23:34 +0000 (20:23 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 13 Jan 2009 01:23:34 +0000 (20:23 -0500)
        PR c++/35109
        * name-lookup.c (lookup_name_real): Keep looking past a hidden
        binding.

Co-Authored-By: Steve Ellcey <sje@cup.hp.com>
From-SVN: r143320

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/friend11.C
gcc/testsuite/g++.dg/lookup/friend14.C [new file with mode: 0644]
gcc/testsuite/g++.dg/lookup/friend15.C [new file with mode: 0644]

index 542b71d71be115fa7af900b3e11502436f72cd02..7e35ecde16d1b3e23d163b663a3c0ab4370709fa 100644 (file)
@@ -1,3 +1,10 @@
+2009-01-12  Jason Merrill  <jason@redhat.com>
+           Steve Ellcey  <sje@cup.hp.com>
+
+       PR c++/35109
+       * name-lookup.c (lookup_name_real): Keep looking past a hidden 
+       binding.
+
 2009-01-12  Dodji Seketeli  <dodji@redhat.com>
 
        PR c++/36019
index 889d9ef559fbf2b091943d7799d30a62d95bb939..d0f85f99061581fe776a9cb478e6d9e945e98d2d 100644 (file)
@@ -4149,16 +4149,25 @@ lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
          {
            if (hidden_name_p (binding))
              {
-               /* A non namespace-scope binding can only be hidden if
-                  we are in a local class, due to friend declarations.
+               /* A non namespace-scope binding can only be hidden in the
+                  presence of a local class, due to friend declarations.
+
                   In particular, consider:
 
+                  struct C;
                   void f() {
                     struct A {
                       friend struct B;
-                      void g() { B* b; } // error: B is hidden
-                    }
+                      friend struct C;
+                      void g() {
+                        B* b; // error: B is hidden
+                        C* c; // OK, finds ::C
+                      } 
+                    };
+                    B *b;  // error: B is hidden
+                    C *c;  // OK, finds ::C
                     struct B {};
+                    B *bb; // OK
                   }
 
                   The standard says that "B" is a local class in "f"
@@ -4174,21 +4183,19 @@ lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
                   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 class declaration, if there is no
-                  prior declaration, the class that is specified 
-                  belongs to the innermost enclosing non-class scope,
-                  but if it is subsequently referenced, its name is not
-                  found by name lookup until a matching declaration is
-                  provided in the innermost enclosing nonclass scope.
+                  scope. For a friend function declaration, if there is
+                  no prior declaration, the program is ill-formed. For a
+                  friend class declaration, if there is no prior
+                  declaration, the class that is specified belongs to the
+                  innermost enclosing non-class scope, but if it is
+                  subsequently referenced, its name is not found by name
+                  lookup until a matching declaration is provided in the
+                  innermost enclosing nonclass scope.
+
+                  So just keep looking for a non-hidden binding.
                */
-               gcc_assert (current_class_type &&
-                           LOCAL_CLASS_P (current_class_type));
-
-               /* This binding comes from a friend declaration in the local
-                  class. The standard (11.4.8) states that the lookup can
-                  only succeed if there is a non-hidden declaration in the
-                  current scope, which is not the case here.  */
-               POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
+               gcc_assert (TREE_CODE (binding) == TYPE_DECL);
+               continue;
              }
            val = binding;
            break;
index 6d2fe902c0a578fb14000894f94e259f2d146dcc..513f6bcf2557086f487d7988b9657ffb692c2ab6 100644 (file)
@@ -1,3 +1,10 @@
+2009-01-12  Jason Merrill  <jason@redhat.com>
+
+       PR c++/35109
+       * g++.dg/lookup/friend11.C: Remove expected error.
+       * g++.dg/lookup/friend14.C: New test.
+       * g++.dg/lookup/friend15.C: New test.
+
 2009-01-12  Dodji Seketeli  <dodji@redhat.com>
 
        PR c++/36019
@@ -15,6 +22,7 @@
 
 2009-01-12  Jason Merrill  <jason@redhat.com>
 
+       PR c++/31488
        * g++.dg/other/vararg-3.C: New test.
 
 2009-01-12  Daniel Jacobowitz  <dan@codesourcery.com>
index ab8a9e507365c6f9f12955d926533196dcc8fada..cd112ca8a4befb192b1bd514e1d6a6f88da4be06 100644 (file)
@@ -3,12 +3,11 @@
 /* { dg-do "compile" } */
 
 
-// This is invalid: QGList must only be looked up in count.
 class QGList;
 unsigned count() {
   class QGListIterator {
     friend class QGList;
-    QGListIterator( const QGList & ); /* { dg-error "expected|with no type" } */
+    QGListIterator( const QGList & ); // OK, finds ::QGList.
   };
   return 0;
 }
diff --git a/gcc/testsuite/g++.dg/lookup/friend14.C b/gcc/testsuite/g++.dg/lookup/friend14.C
new file mode 100644 (file)
index 0000000..5c24411
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/35109
+
+struct C;
+void f() {
+  struct A {
+    friend struct B;
+    friend struct C;
+    void g()
+    {
+      B *b;                    // { dg-error "not declared" }
+      C* c;                    // OK, finds ::C
+    } 
+  };
+  C *c; // OK, finds ::C
+  struct B {};
+  B *b; // OK, now it isn't hidden
+}
diff --git a/gcc/testsuite/g++.dg/lookup/friend15.C b/gcc/testsuite/g++.dg/lookup/friend15.C
new file mode 100644 (file)
index 0000000..1e271fc
--- /dev/null
@@ -0,0 +1,12 @@
+// Origin: PR c++/35109
+// { dg-do compile }
+
+void foo()
+{
+  struct A
+  {
+    friend class B;
+  };
+  B::B() {} // { dg-error "has not been declared" }
+// { dg-error "expected" "expected" { target *-*-* } 10 }
+}