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  <ja...@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


Reply via email to