aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-01-12 20:23:34 -0500
committerJason Merrill <jason@gcc.gnu.org>2009-01-12 20:23:34 -0500
commitb9f673eb35aa687a05466b8532c25d3e56e3e1bd (patch)
tree2e2f7a94f379c6d05b2c37967205e5c492653764 /gcc
parent38a5aa4ae441872f621fa42a737b8c0dbd8184a4 (diff)
downloadgcc-b9f673eb35aa687a05466b8532c25d3e56e3e1bd.zip
gcc-b9f673eb35aa687a05466b8532c25d3e56e3e1bd.tar.gz
gcc-b9f673eb35aa687a05466b8532c25d3e56e3e1bd.tar.bz2
re PR c++/35109 (ICE in lookup_name_real, at cp/name-lookup.c:4056)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/name-lookup.c43
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/lookup/friend11.C3
-rw-r--r--gcc/testsuite/g++.dg/lookup/friend14.C17
-rw-r--r--gcc/testsuite/g++.dg/lookup/friend15.C12
6 files changed, 70 insertions, 20 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 542b71d..7e35ecd 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 889d9ef..d0f85f9 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -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;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6d2fe90..513f6bc 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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>
diff --git a/gcc/testsuite/g++.dg/lookup/friend11.C b/gcc/testsuite/g++.dg/lookup/friend11.C
index ab8a9e5..cd112ca 100644
--- a/gcc/testsuite/g++.dg/lookup/friend11.C
+++ b/gcc/testsuite/g++.dg/lookup/friend11.C
@@ -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
index 0000000..5c24411
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/friend14.C
@@ -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
index 0000000..1e271fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lookup/friend15.C
@@ -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 }
+}