On Wed, 27 May 2020, Patrick Palka wrote:

> 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 RANGE_EXPR
> indexes.
> 
> This patch adds limited support for RANGE_EXPR indexes to
> get_or_insert_ctor_field.  The limited scope of this patch should make
> it more suitable for backporting, and support for more access patterns
> would be needed only to handle self-modifying CONSTRUCTORs containing a
> RANGE_EXPR index, but I haven't yet been able to come up with a testcase
> that exhibits such a CONSTRUCTOR.
> 
> Passes 'make check-c++', does this look OK to commit to master and to
> the GCC 10 branch after a full bootstrap and regtest?
> 
> gcc/cp/ChangeLog:
> 
>       PR c++/95241
>       * constexpr.c (get_or_insert_ctor_field): Add limited support
>       for RANGE_EXPR indexes.
> 
> gcc/testsuite/ChangeLog:
> 
>       PR c++/95241
>       * g++.dg/cpp0x/constexpr-array25.C: New test.
> ---
>  gcc/cp/constexpr.c                            | 12 +++++++++++
>  .../g++.dg/cpp0x/constexpr-array25.C          | 21 +++++++++++++++++++
>  2 files changed, 33 insertions(+)
>  create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-array25.C
> 
> diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
> index 4e441ac8d2f..6f9bafbe8d8 100644
> --- a/gcc/cp/constexpr.c
> +++ b/gcc/cp/constexpr.c
> @@ -3301,6 +3301,18 @@ 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)
> +     {
> +       /* Our support for RANGE_EXPR indexes is limited to accessing an
> +          existing one via POS_HINT, and appending a new one to the end of
> +          CTOR.  ??? Support for other access patterns might be needed.  */
> +       tree lo = TREE_OPERAND (index, 0);
> +       auto *elts = CONSTRUCTOR_ELTS (ctor);
> +       gcc_assert (vec_safe_is_empty (elts)
> +                   || array_index_cmp (lo, elts->last().index) > 0);
> +       return vec_safe_push (elts, {index, NULL_TREE});
> +     }
> +

Oops, it just occurred to me that the use of C++11 features here would
make this patch unsuitable for backporting.  C++98-compatible patch
incoming...

>        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, "");
> -- 
> 2.27.0.rc1.5.gae92ac8ae3
> 
> 

Reply via email to