public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: Fix ICEs with large initializer lists or ones including #embed [PR118124]
@ 2024-12-19 16:07 Jakub Jelinek
  2024-12-19 16:52 ` Jason Merrill
  0 siblings, 1 reply; 7+ messages in thread
From: Jakub Jelinek @ 2024-12-19 16:07 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

Hi!

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.

Ok for trunk if this passes bootstrap/regtest?  Wouldn't like to
leave this broken over Christmas holidays.

2024-12-19  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.

--- gcc/cp/call.cc.jj	2024-12-11 17:27:52.481221310 +0100
+++ gcc/cp/call.cc	2024-12-19 16:10:12.977071898 +0100
@@ -8766,8 +8766,8 @@ convert_like_internal (conversion *convs
 
 	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);
@@ -8775,13 +8775,75 @@ convert_like_internal (conversion *convs
 	  }
 	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;
+		    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)
+			    && (complain & tf_warning)
+			    && (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)
+			      {
+				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;
+			      }
+			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);
@@ -8796,8 +8858,8 @@ convert_like_internal (conversion *convs
 		  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.  */
--- gcc/testsuite/g++.dg/cpp/embed-15.C.jj	2024-12-19 15:07:28.564605983 +0100
+++ gcc/testsuite/g++.dg/cpp/embed-15.C	2024-12-19 15:08:14.194998077 +0100
@@ -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__
+};
--- gcc/testsuite/g++.dg/cpp/embed-16.C.jj	2024-12-19 15:09:20.929109016 +0100
+++ gcc/testsuite/g++.dg/cpp/embed-16.C	2024-12-19 15:11:12.811618467 +0100
@@ -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'" }
--- gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C.jj	2024-12-19 14:52:17.389013179 +0100
+++ gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C	2024-12-19 15:06:28.652404163 +0100
@@ -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 };
--- gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C.jj	2024-12-19 14:52:46.517612306 +0100
+++ gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C	2024-12-19 15:06:52.513086275 +0100
@@ -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'" }

	Jakub


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2025-01-15  0:52 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-12-19 16:07 [PATCH] c++: Fix ICEs with large initializer lists or ones including #embed [PR118124] Jakub Jelinek
2024-12-19 16:52 ` Jason Merrill
2024-12-19 18:01   ` [PATCH] c++, v2: " Jakub Jelinek
2024-12-20  9:24     ` [PATCH] c++, v3: " Jakub Jelinek
2025-01-10  2:30       ` Jason Merrill
2025-01-10  9:21         ` Jakub Jelinek
2025-01-15  0:52           ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).