Message ID | 20191122141911.GC2466@tucnak |
---|---|
State | New |
Headers | show |
Series | [C++] Fix ICE in build_ctor_subob_ref during replace_placeholders (PR c++/92524) | expand |
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 >
--- 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}; +}