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?

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 ();
+}

        Jakub

Reply via email to