public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] avoid user-constructible types in reshape_init_array (PR 90938)
@ 2020-02-11 20:00 Martin Sebor
  2020-02-12  0:01 ` Marek Polacek
  2020-02-12  0:29 ` Jason Merrill
  0 siblings, 2 replies; 14+ messages in thread
From: Martin Sebor @ 2020-02-11 20:00 UTC (permalink / raw)
  To: gcc-patches, Jason Merrill

[-- Attachment #1: Type: text/plain, Size: 959 bytes --]

r270155, committed in GCC 9, introduced a transformation that strips
redundant trailing zero initializers from array initializer lists in
order to support string literals as template arguments.

The transformation neglected to consider the case of array elements
of trivial class types with user-defined conversion ctors and either
defaulted or deleted default ctors.  (It didn't occur to me that
those qualify as trivial types despite the user-defined ctors.)  As
a result, some valid initialization expressions are rejected when
the explicit zero-initializers are dropped in favor of the (deleted)
default ctor, and others are eliminated in favor of the defaulted
ctor instead of invoking a user-defined conversion ctor, leading to
wrong code.

The attached patch fixes that but avoiding this transformation for
such types.

Tested on x86_64-linux.  I'd like to commit the patch to both trunk
and to GCC 9 (with testsuite adjustments if necessary).

Martin

[-- Attachment #2: gcc-90938.diff --]
[-- Type: text/x-patch, Size: 3716 bytes --]

PR c++/90938 - Initializing array with {1} works but not {0}

gcc/cp/ChangeLog:

	PR c++/90938
	* decl.c (reshape_init_array_1): Avoid types with non-trivial
	user-defined ctors.

gcc/testsuite/ChangeLog:

	PR c++/90938
	* g++.dg/init/array55.C: New test.
	* g++.dg/init/array56.C: New test.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 31a556a0a1f..60731cb3f9d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -6051,11 +6051,14 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d,
 	break;
     }
 
-  if (sized_array_p && trivial_type_p (elt_type))
+  if (sized_array_p
+      && trivial_type_p (elt_type)
+      && !TYPE_NEEDS_CONSTRUCTING (elt_type))
     {
       /* Strip trailing zero-initializers from an array of a trivial
-	 type of known size.  They are redundant and get in the way
-	 of telling them apart from those with implicit zero value.  */
+	 type with no user-defined ctor of known size.  They are
+	 redundant and get in the way of telling them apart from those
+	 with implicit zero value.  */
       unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (new_init);
       if (last_nonzero > nelts)
 	nelts = 0;
diff --git a/gcc/testsuite/g++.dg/init/array55.C b/gcc/testsuite/g++.dg/init/array55.C
new file mode 100644
index 00000000000..00a4cf6c616
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array55.C
@@ -0,0 +1,12 @@
+/* PR c++/90938 - Initializing array with {1} works, but not {0}
+   { dg-do compile { target c++11 } } */
+
+struct X
+{
+  X () = delete;
+  X (int) { }
+};
+
+X x0[1] { 1 };
+X x1[1] { 0 };
+X x2[1] { };         // { dg-error "use of deleted function" }
diff --git a/gcc/testsuite/g++.dg/init/array56.C b/gcc/testsuite/g++.dg/init/array56.C
new file mode 100644
index 00000000000..63e16663ec1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array56.C
@@ -0,0 +1,107 @@
+/* PR c++/90938 - Initializing array with {1} works, but not {0}
+   { dg-do compile { target c++11 } }
+   { dg-options "-O -Wall -fdump-tree-optimized" } */
+
+#define assert(e)						\
+  ((e) ? (void)0						\
+   : (__builtin_printf ("assertion failed on line %i: %s\n",	\
+			__LINE__, #e),				\
+      __builtin_abort ()))
+
+namespace A {
+
+struct X
+{
+  X () = default;
+  X (int n) : n (n + 1) { }
+  int n;
+};
+
+static_assert (__is_trivial (X), "X is trivial");
+
+static void test ()
+{
+  {
+    X x[] { 0 };
+    assert (1 == x->n);
+  }
+
+  {
+    X x[1] { 0 };
+    assert (1 == x->n);                     // fails
+  }
+
+  {
+    X x[2] { 0 };
+    assert (1 == x[0].n && 0 == x[1].n);    // fails
+  }
+
+  {
+    X x[] { 1, 0 };
+    assert (2 == x[0].n && 1 == x[1].n);    // passes
+  }
+
+  {
+    X x[2] { 1, 0 };
+    assert (2 == x[0].n && 1 == x[1].n);    // fails
+  }
+}
+
+}
+
+namespace B {
+
+struct X
+{
+  X () = default;
+  X (int *p) : p (p ? p : new int (1)) { }
+  int *p;
+};
+
+static_assert (__is_trivial (X), "X is trivial");
+
+static void test ()
+{
+  X x[1] { nullptr };
+  assert (*x->p == 1);   // fails
+
+  X y[1] { 0 };
+  assert (*y->p == 1);   // fails
+}
+
+}
+
+namespace C {
+
+static const char *vector_swizzle (int vecsize, int index)
+{
+  static const char *swizzle[4][4] =
+    {
+     { ".x", ".y", ".z", ".w" },
+     { ".xy", ".yz", ".zw", nullptr },
+     { ".xyz", ".yzw", nullptr, nullptr },
+     { "", nullptr, nullptr, nullptr },
+    };
+
+  assert (vecsize >= 1 && vecsize <= 4);
+  assert (index >= 0 && index < 4);
+  assert (swizzle[vecsize - 1][index]);
+
+  return swizzle[vecsize - 1][index];
+}
+
+static void test ()
+{
+  assert (!*vector_swizzle(4, 0));
+}
+
+}
+
+int main ()
+{
+  A::test ();
+  B::test ();
+  C::test ();
+}
+
+// { dg-final { scan-tree-dump-not "abort" "optimized" } }

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

end of thread, other threads:[~2020-03-04 22:24 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-02-11 20:00 [PATCH] avoid user-constructible types in reshape_init_array (PR 90938) Martin Sebor
2020-02-12  0:01 ` Marek Polacek
2020-02-12  0:38   ` Martin Sebor
2020-02-12  0:29 ` Jason Merrill
2020-02-12 20:22   ` Martin Sebor
2020-02-12 21:57     ` Marek Polacek
2020-02-13 22:59     ` Jason Merrill
2020-02-14 20:06       ` Martin Sebor
2020-02-17 17:54         ` Jason Merrill
2020-02-22  0:42           ` Martin Sebor
2020-02-24 22:04             ` Jason Merrill
2020-03-04 17:41         ` Jason Merrill
2020-03-04 21:16           ` Martin Sebor
2020-03-04 22:24             ` 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).