[gcc(refs/users/aoliva/heads/testme)] c++: constexpr ctor with RANGE_EXPR index [PR95241]

Alexandre Oliva aoliva@gcc.gnu.org
Tue Jun 2 12:35:26 GMT 2020


https://gcc.gnu.org/g:e069285cdf457cc85070e522380c4e25b0d2ed25

commit e069285cdf457cc85070e522380c4e25b0d2ed25
Author: Patrick Palka <ppalka@redhat.com>
Date:   Fri May 29 09:44:09 2020 -0400

    c++: constexpr ctor with RANGE_EXPR index [PR95241]
    
    In the testcase below, the CONSTRUCTOR for 'field' contains a RANGE_EXPR
    index:
    
      {{aggr_init_expr<...>, [1...2]={.off=1}}}
    
    but get_or_insert_ctor_field isn't prepared to handle looking up a
    RANGE_EXPR index.
    
    This patch adds limited support to get_or_insert_ctor_field for looking
    up a RANGE_EXPR index.  The limited scope of this patch should make it
    more suitable for backporting, and more extensive support would be
    needed only to handle self-modifying CONSTRUCTORs that contain a
    RANGE_EXPR index, but I haven't yet been able to come up with a testcase
    that actually creates such a CONSTRUCTOR.
    
    gcc/cp/ChangeLog:
    
            PR c++/95241
            * constexpr.c (get_or_insert_ctor_field): Add limited support
            for RANGE_EXPR index lookups.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/95241
            * g++.dg/cpp0x/constexpr-array25.C: New test.

Diff:
---
 gcc/cp/constexpr.c                             | 16 ++++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/constexpr-array25.C | 21 +++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 4b1f92f989c..959f0254d09 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3299,6 +3299,22 @@ get_or_insert_ctor_field (tree ctor, tree index, int pos_hint = -1)
     }
   else if (TREE_CODE (type) == ARRAY_TYPE || TREE_CODE (type) == VECTOR_TYPE)
     {
+      if (TREE_CODE (index) == RANGE_EXPR)
+	{
+	  /* Support for RANGE_EXPR index lookups is currently limited to
+	     accessing an existing element via POS_HINT, or appending a new
+	     element to the end of CTOR.  ??? Support for other access
+	     patterns may also be needed.  */
+	  vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (ctor);
+	  if (vec_safe_length (elts))
+	    {
+	      tree lo = TREE_OPERAND (index, 0);
+	      gcc_assert (array_index_cmp (elts->last().index, lo) < 0);
+	    }
+	  CONSTRUCTOR_APPEND_ELT (elts, index, NULL_TREE);
+	  return &elts->last();
+	}
+
       HOST_WIDE_INT i = find_array_ctor_elt (ctor, index, /*insert*/true);
       gcc_assert (i >= 0);
       constructor_elt *cep = CONSTRUCTOR_ELT (ctor, i);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-array25.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-array25.C
new file mode 100644
index 00000000000..9162943249f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-array25.C
@@ -0,0 +1,21 @@
+// PR c++/95241
+// { dg-do compile { target c++11 } }
+
+struct Fragment
+{
+  int off;
+  constexpr Fragment(int _off) : off(_off) { }
+  constexpr Fragment() : Fragment(1) { }
+};
+
+struct Field
+{
+  Fragment fragments[3];
+  constexpr Field(int off) : fragments{{off}} { }
+};
+
+constexpr Field field{0};
+
+static_assert(field.fragments[0].off == 0
+	      && field.fragments[1].off == 1
+	      && field.fragments[2].off == 1, "");


More information about the Gcc-cvs mailing list