On Tue, Apr 01, 2025 at 04:31:38PM +0200, Jakub Jelinek wrote:
> Hi!
> 
> The following testcase ICEs (the embed one actually doesn't but
> dereferences random uninitialized pointer far after allocated memory)
> because of a typo.  In the RAW_DATA_CST handling of list conversion
> where there are conversions to something other than
> initializer_list<{{,un}signed ,}char>, the code now calls
> implicit_conversion for all the RAW_DATA_CST elements and stores them
> into subsubconvs array.
> The next loop (done in a separate loop because subsubconvs[0] is
> handled differently) attempts to do the
>   for (i = 0; i < len; ++i)
>     {
>       conversion *sub = subconvs[i];
>       if (sub->rank > t->rank)
>         t->rank = sub->rank;
>       if (sub->user_conv_p)
>         t->user_conv_p = true;
>       if (sub->bad_p)
>         t->bad_p = true;
>     }
> rank/user_conv_p/bad_p merging, but I mistyped the index, the loop
> iterates with j iterator and i is subconvs index, so the loop effectively
> doesn't do anything interesting except for merging from one of the
> subsubconvs element, if lucky within the subsubconvs array, if unlucky
> not even from inside of the array.
> 
> The following patch fixes that.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

LGTM.
 
> 2025-04-01  Andrew Pinski  <quic_apin...@quicinc.com>
>           Jakub Jelinek  <ja...@redhat.com>
> 
>       PR c++/119563
>       * call.cc (build_list_conv): Fix a typo in loop gathering
>       summary information from subsubconvs.
> 
>       * g++.dg/cpp0x/pr119563.C: New test.
>       * g++.dg/cpp/embed-26.C: New test.
> 
> --- gcc/cp/call.cc.jj 2025-03-06 11:08:20.657231238 +0100
> +++ gcc/cp/call.cc    2025-04-01 11:25:14.030321320 +0200
> @@ -917,7 +917,7 @@ build_list_conv (tree type, tree ctor, i
>         t->rank = cr_exact;
>         for (j = 0; j < (unsigned) RAW_DATA_LENGTH (val); ++j)
>           {
> -           sub = subsubconvs[i];
> +           sub = subsubconvs[j];
>             if (sub->rank > t->rank)
>               t->rank = sub->rank;
>             if (sub->user_conv_p)
> --- gcc/testsuite/g++.dg/cpp0x/pr119563.C.jj  2025-04-01 11:14:24.702394749 
> +0200
> +++ gcc/testsuite/g++.dg/cpp0x/pr119563.C     2025-04-01 11:13:50.962866358 
> +0200
> @@ -0,0 +1,79 @@
> +// PR c++/119563
> +// { dg-do run { target c++11 } }
> +// { dg-options "-O2" }
> +
> +namespace std {
> +template <typename T>
> +struct initializer_list {
> +private:
> +  T *_M_array;
> +  decltype (sizeof 0) _M_len;
> +public:
> +  constexpr decltype (sizeof 0)
> +  size () const noexcept { return _M_len; }
> +  constexpr const T *
> +  begin () const noexcept { return _M_array; }
> +  constexpr const T *
> +  end () const noexcept { return begin () + size (); }
> +};
> +}
> +
> +struct A {} a;
> +
> +struct B {
> +  constexpr B (int x) : B (a, x) {}
> +  template <typename... T>
> +  constexpr B (A, T... x) : b(x...) {}
> +  int b;
> +};
> +
> +struct C {
> +  C (std::initializer_list<B> x)
> +  {
> +    if (x.size () != 130 + 1024 + 130)
> +      __builtin_abort ();
> +    unsigned int i = 1, j = 0;
> +    for (auto a = x.begin (); a < x.end (); ++a)
> +      if (a->b != i)
> +     __builtin_abort ();
> +      else
> +     {
> +       if (j == 129 || j == 129 + 1024)
> +         i = 0;
> +       i = (i & 15) + 1;
> +       ++j;
> +     }
> +    c = true;
> +  }
> +  bool c;
> +};
> +
> +#define D 1 + 0, 2 + 0, 3 + 0, 4 + 0, 5 + 0, 6 + 0, 7 + 0, 8 + 0, \
> +       9 + 0, 10 + 0, 11 + 0, 12 + 0, 13 + 0, 14 + 0, 15 + 0, 16 + 0
> +#define E D, D, D, D, D, D, D, D
> +
> +C c { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, E, E, E, E, E, E, E, E,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
> +      1, 2 };
> +
> +int
> +main ()
> +{
> +  if (!c.c)
> +    __builtin_abort ();
> +}
> --- gcc/testsuite/g++.dg/cpp/embed-26.C.jj    2025-04-01 11:18:56.563595381 
> +0200
> +++ gcc/testsuite/g++.dg/cpp/embed-26.C       2025-04-01 11:18:35.444890450 
> +0200
> @@ -0,0 +1,63 @@
> +// PR c++/119563
> +// { dg-do run { target c++11 } }
> +// { dg-options "-O2" }
> +
> +namespace std {
> +template <typename T>
> +struct initializer_list {
> +private:
> +  T *_M_array;
> +  decltype (sizeof 0) _M_len;
> +public:
> +  constexpr decltype (sizeof 0)
> +  size () const noexcept { return _M_len; }
> +  constexpr const T *
> +  begin () const noexcept { return _M_array; }
> +  constexpr const T *
> +  end () const noexcept { return begin () + size (); }
> +};
> +}
> +
> +struct A {} a;
> +
> +struct B {
> +  constexpr B (int x) : B (a, x) {}
> +  template <typename... T>
> +  constexpr B (A, T... x) : b(x...) {}
> +  int b;
> +};
> +
> +struct C {
> +  C (std::initializer_list<B> x)
> +  {
> +    unsigned char buf[] = {
> +#embed __FILE__
> +    };
> +    if (x.size () != 2 * sizeof (buf) + 1024)
> +      __builtin_abort ();
> +    unsigned int i = 0;
> +    for (auto a = x.begin (); a < x.end (); ++a, ++i)
> +      if (a->b != (i < sizeof (buf) ? buf[i]
> +                : i < sizeof (buf) + 1024 ? ((i - sizeof (buf)) & 7) + 1
> +                : buf[i - sizeof (buf) - 1024]))
> +     __builtin_abort ();
> +    c = true;
> +  }
> +  bool c;
> +};
> +
> +#define D 1 + 0, 2 + 0, 3 + 0, 4 + 0, 5 + 0, 6 + 0, 7 + 0, 8 + 0
> +#define E D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D
> +
> +C c {
> +#embed __FILE__ suffix (,)
> +  E, E, E, E, E, E, E, E,
> +#embed __FILE__
> +};
> +
> +int
> +main ()
> +{
> +  if (!c.c)
> +    __builtin_abort ();
> +}

Marek

Reply via email to