]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gcc/cp/
authorsimartin <simartin@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 28 Jul 2007 10:48:30 +0000 (10:48 +0000)
committersimartin <simartin@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 28 Jul 2007 10:48:30 +0000 (10:48 +0000)
2007-07-28  Simon Martin  <simartin@users.sourceforge.net>
    Mark Mitchell  <mark@codesourcery.com>

PR c++/30917
* name-lookup.c (lookup_name_real): Non namespace-scope bindings can be
hidden due to friend declarations in local classes.

gcc/testsuite/

2007-07-28  Simon Martin  <simartin@users.sourceforge.net>

PR c++/30917
* g++.dg/lookup/friend11.C: New test.

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

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

index 51412983ee0d5aa5562da87bafe4b9d1e02aa314..57c1e413fd24166bc69e33ecc8402e42be85fc4c 100644 (file)
@@ -1,3 +1,10 @@
+2007-07-28  Simon Martin  <simartin@users.sourceforge.net>
+           Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/30917
+       * name-lookup.c (lookup_name_real): Non namespace-scope bindings can be
+       hidden due to friend declarations in local classes.
+
 2007-07-27  Douglas Gregor  <doug.gregor@gmail.com>
 
        * typeck.c (structural_comptypes): Compare DECLTYPE_TYPE nodes.
index 068725859ff9b0486be0ae6208e756b87b1df2be..814663819390bc0d1a64f8884ef086274dd01e55 100644 (file)
@@ -3990,8 +3990,49 @@ lookup_name_real (tree name, int prefer_type, int nonclass, bool block_p,
 
        if (binding)
          {
-           /* Only namespace-scope bindings can be hidden.  */
-           gcc_assert (!hidden_name_p (binding));
+           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.
+                  In particular, consider:
+
+                  void f() {
+                    struct A {
+                      friend struct B;
+                      void g() { B* b; } // error: B is hidden
+                    }
+                    struct B {};
+                  }
+
+                  The standard says that "B" is a local class in "f"
+                  (but not nested within "A") -- but that name lookup
+                  for "B" does not find this declaration until it is
+                  declared directly with "f".
+
+                  In particular:
+
+                  [class.friend]
+
+                  If a friend declaration appears in a local class 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 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.
+               */
+               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);
+             }
            val = binding;
            break;
          }
index 5352bce536d06cbed875bc3637482066a29a9852..52e0b5e43ed356f85b5eb492b077ce0fffcc1ab1 100644 (file)
@@ -1,3 +1,8 @@
+2007-07-28  Simon Martin  <simartin@users.sourceforge.net>
+
+       PR c++/30917
+       * g++.dg/lookup/friend11.C: New test.
+
 2007-07-28  Daniel Franke  <franke.daniel@gmail.com>
 
        * gfortran.dg/namelist_5.f90: Adjusted error message.
diff --git a/gcc/testsuite/g++.dg/lookup/friend11.C b/gcc/testsuite/g++.dg/lookup/friend11.C
new file mode 100644 (file)
index 0000000..ab8a9e5
--- /dev/null
@@ -0,0 +1,24 @@
+/* PR c++/30917 */
+/* This used to ICE */
+/* { 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" } */
+  };
+  return 0;
+}
+
+// This is valid.
+unsigned count2() {
+  class QGList2;
+  class QGListIterator2 {
+    friend class QGList2;
+    QGListIterator2( const QGList2 & );
+  };
+  return 0;
+}