aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-01-15 08:46:48 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2025-01-15 08:59:45 +0100
commitf263f2d525eb9a1b60c2a356eb64262819b6bab0 (patch)
tree19a6a0af33b1aec9c7093eb61318b611f9f4e94a /gcc
parent40ad10f708b19d3e88948ac820fbfb9f3c3689ae (diff)
downloadgcc-f263f2d525eb9a1b60c2a356eb64262819b6bab0.zip
gcc-f263f2d525eb9a1b60c2a356eb64262819b6bab0.tar.gz
gcc-f263f2d525eb9a1b60c2a356eb64262819b6bab0.tar.bz2
c++: Fix ICEs with large initializer lists or ones including #embed [PR118124]
The following testcases ICE due to RAW_DATA_CST not being handled where it should be during ck_list conversions. The last 2 testcases started ICEing with r15-6339 committed yesterday (speedup of large initializers), the first two already with r15-5958 (#embed optimization for C++). For conversion to initializer_list<unsigned char> or char/signed char we can optimize and keep RAW_DATA_CST with adjusted type if we report narrowing errors if needed, for others this converts each element separately. 2025-01-15 Jakub Jelinek <jakub@redhat.com> PR c++/118124 * call.cc (convert_like_internal): Handle RAW_DATA_CST in ck_list handling. Formatting fixes. * g++.dg/cpp/embed-15.C: New test. * g++.dg/cpp/embed-16.C: New test. * g++.dg/cpp0x/initlist-opt3.C: New test. * g++.dg/cpp0x/initlist-opt4.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/call.cc95
-rw-r--r--gcc/testsuite/g++.dg/cpp/embed-15.C35
-rw-r--r--gcc/testsuite/g++.dg/cpp/embed-16.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C47
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C20
5 files changed, 209 insertions, 6 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 602f496..65d613e 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -8806,8 +8806,9 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
if (tree init = maybe_init_list_as_array (elttype, expr))
{
- elttype = cp_build_qualified_type
- (elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST);
+ elttype
+ = cp_build_qualified_type (elttype, (cp_type_quals (elttype)
+ | TYPE_QUAL_CONST));
array = build_array_of_n_type (elttype, len);
array = build_vec_init_expr (array, init, complain);
array = get_target_expr (array);
@@ -8815,13 +8816,94 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
}
else if (len)
{
- tree val; unsigned ix;
-
+ tree val;
+ unsigned ix;
tree new_ctor = build_constructor (init_list_type_node, NULL);
/* Convert all the elements. */
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val)
{
+ if (TREE_CODE (val) == RAW_DATA_CST)
+ {
+ tree elt_type;
+ conversion *next;
+ /* For conversion to initializer_list<unsigned char> or
+ initializer_list<char> or initializer_list<signed char>
+ we can optimize and keep RAW_DATA_CST with adjusted
+ type if we report narrowing errors if needed, for
+ others this converts each element separately. */
+ if (convs->u.list[ix]->kind == ck_std
+ && (elt_type = convs->u.list[ix]->type)
+ && (TREE_CODE (elt_type) == INTEGER_TYPE
+ || is_byte_access_type (elt_type))
+ && TYPE_PRECISION (elt_type) == CHAR_BIT
+ && (next = next_conversion (convs->u.list[ix]))
+ && next->kind == ck_identity)
+ {
+ if (!TYPE_UNSIGNED (elt_type)
+ /* For RAW_DATA_CST, TREE_TYPE (val) can be
+ either integer_type_node (when it has been
+ created by the lexer from CPP_EMBED) or
+ after digestion/conversion some integral
+ type with CHAR_BIT precision. For int with
+ precision higher than CHAR_BIT or unsigned char
+ diagnose narrowing conversions from
+ that int/unsigned char to signed char if any
+ byte has most significant bit set. */
+ && (TYPE_UNSIGNED (TREE_TYPE (val))
+ || (TYPE_PRECISION (TREE_TYPE (val))
+ > CHAR_BIT)))
+ for (int i = 0; i < RAW_DATA_LENGTH (val); ++i)
+ {
+ if (RAW_DATA_SCHAR_ELT (val, i) >= 0)
+ continue;
+ else if (complain & tf_error)
+ {
+ location_t loc
+ = cp_expr_loc_or_input_loc (val);
+ int savederrorcount = errorcount;
+ permerror_opt (loc, OPT_Wnarrowing,
+ "narrowing conversion of "
+ "%qd from %qH to %qI",
+ RAW_DATA_UCHAR_ELT (val, i),
+ TREE_TYPE (val), elt_type);
+ if (errorcount != savederrorcount)
+ return error_mark_node;
+ }
+ else
+ return error_mark_node;
+ }
+ tree sub = copy_node (val);
+ TREE_TYPE (sub) = elt_type;
+ CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor),
+ NULL_TREE, sub);
+ }
+ else
+ {
+ for (int i = 0; i < RAW_DATA_LENGTH (val); ++i)
+ {
+ tree elt
+ = build_int_cst (TREE_TYPE (val),
+ RAW_DATA_UCHAR_ELT (val, i));
+ tree sub
+ = convert_like (convs->u.list[ix], elt,
+ fn, argnum, false, false,
+ /*nested_p=*/true, complain);
+ if (sub == error_mark_node)
+ return sub;
+ if (!check_narrowing (TREE_TYPE (sub), elt,
+ complain))
+ return error_mark_node;
+ tree nc = new_ctor;
+ CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (nc),
+ NULL_TREE, sub);
+ if (!TREE_CONSTANT (sub))
+ TREE_CONSTANT (new_ctor) = false;
+ }
+ }
+ len += RAW_DATA_LENGTH (val) - 1;
+ continue;
+ }
tree sub = convert_like (convs->u.list[ix], val, fn,
argnum, false, false,
/*nested_p=*/true, complain);
@@ -8836,8 +8918,9 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
TREE_CONSTANT (new_ctor) = false;
}
/* Build up the array. */
- elttype = cp_build_qualified_type
- (elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST);
+ elttype
+ = cp_build_qualified_type (elttype, (cp_type_quals (elttype)
+ | TYPE_QUAL_CONST));
array = build_array_of_n_type (elttype, len);
array = finish_compound_literal (array, new_ctor, complain);
/* This is dubious now, should be blessed by P2752. */
diff --git a/gcc/testsuite/g++.dg/cpp/embed-15.C b/gcc/testsuite/g++.dg/cpp/embed-15.C
new file mode 100644
index 0000000..a399453
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/embed-15.C
@@ -0,0 +1,35 @@
+// PR c++/118124
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+
+namespace std {
+template <class T> struct initializer_list {
+private:
+ const T *_M_array;
+ __SIZE_TYPE__ _M_len;
+};
+}
+struct A {
+ A (std::initializer_list<char>);
+};
+A a {
+#embed __FILE__
+};
+struct B {
+ B (std::initializer_list<unsigned char>);
+};
+B b {
+#embed __FILE__
+};
+struct C {
+ C (std::initializer_list<int>);
+};
+C c {
+#embed __FILE__
+};
+struct D {
+ D (std::initializer_list<float>);
+};
+D d {
+#embed __FILE__
+};
diff --git a/gcc/testsuite/g++.dg/cpp/embed-16.C b/gcc/testsuite/g++.dg/cpp/embed-16.C
new file mode 100644
index 0000000..868dce2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/embed-16.C
@@ -0,0 +1,18 @@
+// PR c++/118124
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+// non-ASCII chars here: áéí
+
+namespace std {
+template <class T> struct initializer_list {
+private:
+ const T *_M_array;
+ __SIZE_TYPE__ _M_len;
+};
+}
+struct A {
+ A (std::initializer_list<signed char>);
+};
+A a {
+#embed __FILE__
+}; // { dg-error "narrowing conversion of '\[0-9]*' from 'int' to 'signed char'" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C b/gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C
new file mode 100644
index 0000000..fa27988
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C
@@ -0,0 +1,47 @@
+// PR c++/118124
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+
+namespace std {
+template <class T> struct initializer_list {
+private:
+ const T *_M_array;
+ __SIZE_TYPE__ _M_len;
+};
+}
+struct A {
+ A (std::initializer_list<char>);
+};
+A a { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 };
+struct B {
+ B (std::initializer_list<unsigned char>);
+};
+B b { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 };
+struct C {
+ C (std::initializer_list<int>);
+};
+C c { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 };
+struct D {
+ D (std::initializer_list<float>);
+};
+D d { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 };
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C b/gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C
new file mode 100644
index 0000000..080dee3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C
@@ -0,0 +1,20 @@
+// PR c++/118124
+// { dg-do compile { target c++11 } }
+// { dg-options "-O2" }
+
+namespace std {
+template <class T> struct initializer_list {
+private:
+ const T *_M_array;
+ __SIZE_TYPE__ _M_len;
+};
+}
+struct A {
+ A (std::initializer_list<signed char>);
+};
+A a { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
+ 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 209, 0, 1, 2, 3,
+ 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
+ 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; // { dg-error "narrowing conversion of '209' from 'int' to 'signed char'" }