This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix ICE in pop_binding (regression against 2.95.x)
- To: jason at redhat dot com, mmitchell at codesourcery dot com
- Subject: [PATCH] Fix ICE in pop_binding (regression against 2.95.x)
- From: Jakub Jelinek <jakub at redhat dot com>
- Date: Fri, 8 Jun 2001 14:05:58 +0200
- Cc: gcc-patches at gcc dot gnu dot org
- Reply-To: Jakub Jelinek <jakub at redhat dot com>
Hi!
The following testcase ICEs in pop_binding.
The issue is that the foo method is inserted into class_shadowed list, but
as there is a friend with the same name which comes after it, at pop_binding
time when all class_shadowed bindings are poped up the foo method is not
BINDING_VALUE() in the innermost IDENTIFIER_BINDING (but in TREE_CHAIN() of
it). Exchanging the two foo lines in the testcase causes it to work, since
foo method comes last and thus is in the innermost IDENTIFIER_BINDING.
The following patch seems to fix it, bootstrap pending.
Ok to commit if it is succeeds (and no regressions)?
2001-06-08 Jakub Jelinek <jakub@redhat.com>
* decl.c (pop_binding): Allow DECL not to be present in the
innermost binding for ID.
* g++.old-deja/g++.other/binding1.C: New test.
--- gcc/cp/decl.c.jj Fri Jun 8 11:37:19 2001
+++ gcc/cp/decl.c Fri Jun 8 13:53:38 2001
@@ -1174,7 +1174,7 @@ pop_binding (id, decl)
tree id;
tree decl;
{
- tree binding;
+ tree binding, orig_binding, last_binding = NULL_TREE;
if (id == NULL_TREE)
/* It's easiest to write the loops that call this function without
@@ -1183,20 +1183,28 @@ pop_binding (id, decl)
return;
/* Get the innermost binding for ID. */
- binding = IDENTIFIER_BINDING (id);
+ orig_binding = IDENTIFIER_BINDING (id);
+
+ for (binding = orig_binding; binding; binding = TREE_CHAIN (binding))
+ {
+ /* The DECL will be either the ordinary binding or the type
+ binding for this identifier. Remove that binding. */
+ if (BINDING_VALUE (binding) == decl)
+ {
+ BINDING_VALUE (binding) = NULL_TREE;
+ break;
+ }
+ else if (BINDING_TYPE (binding) == decl)
+ {
+ BINDING_TYPE (binding) = NULL_TREE;
+ break;
+ }
+ last_binding = binding;
+ }
/* The name should be bound. */
my_friendly_assert (binding != NULL_TREE, 0);
- /* The DECL will be either the ordinary binding or the type
- binding for this identifier. Remove that binding. */
- if (BINDING_VALUE (binding) == decl)
- BINDING_VALUE (binding) = NULL_TREE;
- else if (BINDING_TYPE (binding) == decl)
- BINDING_TYPE (binding) = NULL_TREE;
- else
- my_friendly_abort (0);
-
if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
{
/* We're completely done with the innermost binding for this
@@ -1210,6 +1218,14 @@ pop_binding (id, decl)
/* Clear the BINDING_LEVEL so the garbage collector doesn't walk
it. */
BINDING_LEVEL (binding) = NULL;
+ }
+
+ if (last_binding != NULL_TREE)
+ {
+ /* This can happen if a class method is followed by friend with the same
+ name. */
+ TREE_CHAIN (last_binding) = IDENTIFIER_BINDING (id);
+ IDENTIFIER_BINDING (id) = orig_binding;
}
}
--- gcc/testsuite/g++.old-deja/g++.other/binding1.C.jj Fri Jun 8 13:57:19 2001
+++ gcc/testsuite/g++.old-deja/g++.other/binding1.C Fri Jun 8 13:57:29 2001
@@ -0,0 +1,9 @@
+// Build don't link:
+
+template <class T> struct A;
+
+template <> struct A<int>
+{
+ A<int> & foo (int);
+ friend A<int> foo (const A<int> &, int);
+};
Jakub