diff mbox series

[C++] Fix ICE in member_vec_dedup (PR c++/83825)

Message ID 20180115214636.GC2063@tucnak
State New
Headers show
Series [C++] Fix ICE in member_vec_dedup (PR c++/83825) | expand

Commit Message

Jakub Jelinek Jan. 15, 2018, 9:46 p.m. UTC
Hi!

As the testcase shows, calls to member_vec_dedup and qsort are just guarded
by the vector being non-NULL, which doesn't mean it must be non-empty,
so we can't do (*member_vec)[0] on it.  Fixed by the second hunk, the
rest is just a small cleanup to use the vec.h methods.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2018-01-15  Jakub Jelinek  <jakub@redhat.com>

	PR c++/83825
	* name-lookup.c (member_vec_dedup): Return early if len is 0.
	(resort_type_member_vec, set_class_bindings,
	insert_late_enum_def_bindings): Use vec qsort method instead of
	calling qsort directly.

	* g++.dg/template/pr83825.C: New test.


	Jakub

Comments

Jason Merrill Jan. 16, 2018, 1:59 a.m. UTC | #1
OK.

On Mon, Jan 15, 2018 at 4:46 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> As the testcase shows, calls to member_vec_dedup and qsort are just guarded
> by the vector being non-NULL, which doesn't mean it must be non-empty,
> so we can't do (*member_vec)[0] on it.  Fixed by the second hunk, the
> rest is just a small cleanup to use the vec.h methods.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2018-01-15  Jakub Jelinek  <jakub@redhat.com>
>
>         PR c++/83825
>         * name-lookup.c (member_vec_dedup): Return early if len is 0.
>         (resort_type_member_vec, set_class_bindings,
>         insert_late_enum_def_bindings): Use vec qsort method instead of
>         calling qsort directly.
>
>         * g++.dg/template/pr83825.C: New test.
>
> --- gcc/cp/name-lookup.c.jj     2018-01-03 13:16:38.537848205 +0100
> +++ gcc/cp/name-lookup.c        2018-01-15 14:07:09.494576944 +0100
> @@ -1520,8 +1520,7 @@ resort_type_member_vec (void *obj, void
>      {
>        resort_data.new_value = new_value;
>        resort_data.cookie = cookie;
> -      qsort (member_vec->address (), member_vec->length (),
> -            sizeof (tree), resort_member_name_cmp);
> +      member_vec->qsort (resort_member_name_cmp);
>      }
>  }
>
> @@ -1597,6 +1596,9 @@ member_vec_dedup (vec<tree, va_gc> *memb
>    unsigned len = member_vec->length ();
>    unsigned store = 0;
>
> +  if (!len)
> +    return;
> +
>    tree current = (*member_vec)[0], name = OVL_NAME (current);
>    tree next = NULL_TREE, next_name = NULL_TREE;
>    for (unsigned jx, ix = 0; ix < len;
> @@ -1712,8 +1714,7 @@ set_class_bindings (tree klass, unsigned
>    if (member_vec)
>      {
>        CLASSTYPE_MEMBER_VEC (klass) = member_vec;
> -      qsort (member_vec->address (), member_vec->length (),
> -            sizeof (tree), member_name_cmp);
> +      member_vec->qsort (member_name_cmp);
>        member_vec_dedup (member_vec);
>      }
>  }
> @@ -1741,8 +1742,7 @@ insert_late_enum_def_bindings (tree klas
>        else
>         member_vec_append_class_fields (member_vec, klass);
>        CLASSTYPE_MEMBER_VEC (klass) = member_vec;
> -      qsort (member_vec->address (), member_vec->length (),
> -            sizeof (tree), member_name_cmp);
> +      member_vec->qsort (member_name_cmp);
>        member_vec_dedup (member_vec);
>      }
>  }
> --- gcc/testsuite/g++.dg/template/pr83825.C.jj  2018-01-15 14:16:55.289432205 +0100
> +++ gcc/testsuite/g++.dg/template/pr83825.C     2018-01-15 14:14:03.172490348 +0100
> @@ -0,0 +1,13 @@
> +// PR c++/83825
> +// { dg-do compile }
> +
> +template <int A>
> +class A {};    // { dg-error "shadows template parameter" }
> +
> +template <int I>
> +class B
> +{
> +  void foo () { A <I> a; }
> +};
> +
> +template void B <0>::foo ();
>
>         Jakub
Nathan Sidwell Jan. 16, 2018, 3:08 p.m. UTC | #2
On 01/15/2018 04:46 PM, Jakub Jelinek wrote:
> Hi!
> 
> As the testcase shows, calls to member_vec_dedup and qsort are just guarded
> by the vector being non-NULL, which doesn't mean it must be non-empty,
> so we can't do (*member_vec)[0] on it.  Fixed by the second hunk, the
> rest is just a small cleanup to use the vec.h methods.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Ok I'm a little surprised we get this case, but I think we've both found 
other strange boundary cases here.  thanks.

nathan
diff mbox series

Patch

--- gcc/cp/name-lookup.c.jj	2018-01-03 13:16:38.537848205 +0100
+++ gcc/cp/name-lookup.c	2018-01-15 14:07:09.494576944 +0100
@@ -1520,8 +1520,7 @@  resort_type_member_vec (void *obj, void
     {
       resort_data.new_value = new_value;
       resort_data.cookie = cookie;
-      qsort (member_vec->address (), member_vec->length (),
-	     sizeof (tree), resort_member_name_cmp);
+      member_vec->qsort (resort_member_name_cmp);
     }
 }
 
@@ -1597,6 +1596,9 @@  member_vec_dedup (vec<tree, va_gc> *memb
   unsigned len = member_vec->length ();
   unsigned store = 0;
 
+  if (!len)
+    return;
+
   tree current = (*member_vec)[0], name = OVL_NAME (current);
   tree next = NULL_TREE, next_name = NULL_TREE;
   for (unsigned jx, ix = 0; ix < len;
@@ -1712,8 +1714,7 @@  set_class_bindings (tree klass, unsigned
   if (member_vec)
     {
       CLASSTYPE_MEMBER_VEC (klass) = member_vec;
-      qsort (member_vec->address (), member_vec->length (),
-	     sizeof (tree), member_name_cmp);
+      member_vec->qsort (member_name_cmp);
       member_vec_dedup (member_vec);
     }
 }
@@ -1741,8 +1742,7 @@  insert_late_enum_def_bindings (tree klas
       else
 	member_vec_append_class_fields (member_vec, klass);
       CLASSTYPE_MEMBER_VEC (klass) = member_vec;
-      qsort (member_vec->address (), member_vec->length (),
-	     sizeof (tree), member_name_cmp);
+      member_vec->qsort (member_name_cmp);
       member_vec_dedup (member_vec);
     }
 }
--- gcc/testsuite/g++.dg/template/pr83825.C.jj	2018-01-15 14:16:55.289432205 +0100
+++ gcc/testsuite/g++.dg/template/pr83825.C	2018-01-15 14:14:03.172490348 +0100
@@ -0,0 +1,13 @@ 
+// PR c++/83825
+// { dg-do compile }
+
+template <int A>
+class A {};	// { dg-error "shadows template parameter" }
+
+template <int I>
+class B
+{ 
+  void foo () { A <I> a; }
+};
+
+template void B <0>::foo ();