[C++] Fix ICE in build_ctor_subob_ref during replace_placeholders (PR c++/92524)
diff mbox series

Message ID 20191122141911.GC2466@tucnak
State New
Headers show
Series
  • [C++] Fix ICE in build_ctor_subob_ref during replace_placeholders (PR c++/92524)
Related show

Commit Message

Jakub Jelinek Nov. 22, 2019, 2:19 p.m. UTC
Hi!

On the following testcase, replace_placeholders is called on a CONSTRUCTOR
{ a, [1..63] = NON_LVALUE_EXPR<42> }
and call build_ctor_subob_ref in that case.  The problem is that index is
RANGE_EXPR and as it is not INTEGER_CST, we call
build_class_member_access_expr which is not appropriate for array indexes.
cp_build_array_ref will not really work with RANGE_EXPR either, the
following patch just usesthe low bound of the range.  At least when trying
to read it, it should be equivalent to any other value in the range.

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

2019-11-22  Jakub Jelinek  <jakub@redhat.com>

	PR c++/92524
	* tree.c (build_ctor_subob_ref): For RANGE_EXPR index, build
	array reference for the low bound.

	* g++.dg/cpp0x/pr92524.C: New test.


	Jakub

Comments

Jason Merrill Nov. 26, 2019, 9:58 p.m. UTC | #1
On 11/22/19 9:19 AM, Jakub Jelinek wrote:
> Hi!
> 
> On the following testcase, replace_placeholders is called on a CONSTRUCTOR
> { a, [1..63] = NON_LVALUE_EXPR<42> }
> and call build_ctor_subob_ref in that case.  The problem is that index is
> RANGE_EXPR and as it is not INTEGER_CST, we call
> build_class_member_access_expr which is not appropriate for array indexes.
> cp_build_array_ref will not really work with RANGE_EXPR either, the
> following patch just usesthe low bound of the range.  At least when trying
> to read it, it should be equivalent to any other value in the range.

Hmm, we shouldn't have any PLACEHOLDER_EXPR under a RANGE_EXPR; if we 
did, any references to its address would end up all referring to the 
first element of the range, which would be wrong.  How about skipping 
RANGE_EXPR in replace_placeholders_r?

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

> 2019-11-22  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR c++/92524
> 	* tree.c (build_ctor_subob_ref): For RANGE_EXPR index, build
> 	array reference for the low bound.
> 
> 	* g++.dg/cpp0x/pr92524.C: New test.
> 
> --- gcc/cp/tree.c.jj	2019-11-16 18:13:28.571821577 +0100
> +++ gcc/cp/tree.c	2019-11-21 12:22:27.260660874 +0100
> @@ -3064,6 +3064,10 @@ build_ctor_subob_ref (tree index, tree t
>       obj = NULL_TREE;
>     else if (TREE_CODE (index) == INTEGER_CST)
>       obj = cp_build_array_ref (input_location, obj, index, tf_none);
> +  else if (TREE_CODE (index) == RANGE_EXPR)
> +    /* Use low bound for ranges.  */
> +    obj = cp_build_array_ref (input_location, obj, TREE_OPERAND (index, 0),
> +			      tf_none);
>     else
>       obj = build_class_member_access_expr (obj, index, NULL_TREE,
>   					  /*reference*/false, tf_none);
> --- gcc/testsuite/g++.dg/cpp0x/pr92524.C.jj	2019-11-21 12:34:53.350406680 +0100
> +++ gcc/testsuite/g++.dg/cpp0x/pr92524.C	2019-11-21 12:34:18.943925681 +0100
> @@ -0,0 +1,12 @@
> +// PR c++/92524
> +// { dg-do compile { target c++11 } }
> +
> +struct A { char a = '*'; };
> +struct B { A b[64]; };
> +
> +void
> +foo ()
> +{
> +  A a;
> +  B{a};
> +}
> 
> 	Jakub
>

Patch
diff mbox series

--- gcc/cp/tree.c.jj	2019-11-16 18:13:28.571821577 +0100
+++ gcc/cp/tree.c	2019-11-21 12:22:27.260660874 +0100
@@ -3064,6 +3064,10 @@  build_ctor_subob_ref (tree index, tree t
     obj = NULL_TREE;
   else if (TREE_CODE (index) == INTEGER_CST)
     obj = cp_build_array_ref (input_location, obj, index, tf_none);
+  else if (TREE_CODE (index) == RANGE_EXPR)
+    /* Use low bound for ranges.  */
+    obj = cp_build_array_ref (input_location, obj, TREE_OPERAND (index, 0),
+			      tf_none);
   else
     obj = build_class_member_access_expr (obj, index, NULL_TREE,
 					  /*reference*/false, tf_none);
--- gcc/testsuite/g++.dg/cpp0x/pr92524.C.jj	2019-11-21 12:34:53.350406680 +0100
+++ gcc/testsuite/g++.dg/cpp0x/pr92524.C	2019-11-21 12:34:18.943925681 +0100
@@ -0,0 +1,12 @@ 
+// PR c++/92524
+// { dg-do compile { target c++11 } }
+
+struct A { char a = '*'; };
+struct B { A b[64]; };
+
+void
+foo ()
+{
+  A a;
+  B{a};
+}