https://gcc.gnu.org/g:70bf0ee44017e8e26bb1bdcb6a3fd114c25c39c7

commit r15-9177-g70bf0ee44017e8e26bb1bdcb6a3fd114c25c39c7
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Thu Apr 3 13:21:56 2025 +0200

    c++: Fix typo in RAW_DATA_CST build_list_conv subsubconv hanling [PR119563]
    
    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.
    
    2025-04-03  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.

Diff:
---
 gcc/cp/call.cc                        |  2 +-
 gcc/testsuite/g++.dg/cpp/embed-26.C   | 63 ++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/cpp0x/pr119563.C | 79 +++++++++++++++++++++++++++++++++++
 3 files changed, 143 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index b1469cb5a4c9..d8533623c015 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -917,7 +917,7 @@ build_list_conv (tree type, tree ctor, int flags, 
tsubst_flags_t complain)
          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)
diff --git a/gcc/testsuite/g++.dg/cpp/embed-26.C 
b/gcc/testsuite/g++.dg/cpp/embed-26.C
new file mode 100644
index 000000000000..ad3f9de6b1f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/embed-26.C
@@ -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 ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr119563.C 
b/gcc/testsuite/g++.dg/cpp0x/pr119563.C
new file mode 100644
index 000000000000..9363a09e8bb3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr119563.C
@@ -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 ();
+}

Reply via email to