public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: Further tweaks for new-expression and paren-init [PR77841]
@ 2020-09-06 15:34 Marek Polacek
  2020-09-08  3:19 ` Jason Merrill
  0 siblings, 1 reply; 8+ messages in thread
From: Marek Polacek @ 2020-09-06 15:34 UTC (permalink / raw)
  To: Jason Merrill, GCC Patches

This patch corrects our handling of array new-expression with ()-init:

  new int[4](1, 2, 3, 4);

should work even with the explicit array bound, and

  new char[3]("so_sad");

should cause an error, but we weren't giving any.

Fixed by handling array new-expressions with ()-init in the same spot
where we deduce the array bound in array new-expression.  I'm now
always passing STRING_CSTs to build_new_1 wrapped in { } which allowed
me to remove the special handling of STRING_CSTs in build_new_1.  And
since the DIRECT_LIST_INIT_P block in build_new_1 calls digest_init, we
report errors about too short arrays.

I took a stab at cp_complete_array_type's "FIXME: this code is duplicated
from reshape_init", but calling reshape_init there, I ran into issues
with has_designator_problem: when we reshape an already reshaped
CONSTRUCTOR again, d.cur.index has been filled, so we think that we
have a user-provided designator (though there was no designator in the
source code), and report an error.

Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

gcc/cp/ChangeLog:

	PR c++/77841
	* init.c (build_new_1): Don't handle string-initializers here.
	(build_new): Handle new-expression with paren-init when the
	array bound is known.  Always pass string constants to build_new_1
	enclosed in braces.

gcc/testsuite/ChangeLog:

	PR c++/77841
	* g++.old-deja/g++.ext/arrnew2.C: Expect the error only in C++17
	and less.
	* g++.old-deja/g++.robertl/eb58.C: Adjust dg-error.
	* g++.dg/cpp2a/paren-init36.C: New test.
---
 gcc/cp/init.c                                 | 37 ++++++++++---------
 gcc/testsuite/g++.dg/cpp2a/paren-init36.C     | 14 +++++++
 gcc/testsuite/g++.old-deja/g++.ext/arrnew2.C  |  2 +-
 gcc/testsuite/g++.old-deja/g++.robertl/eb58.C |  2 +-
 4 files changed, 35 insertions(+), 20 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/paren-init36.C

diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 3268ae4ad3f..537651778b9 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3596,15 +3596,6 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 		  vecinit = digest_init (arraytype, vecinit, complain);
 		}
 	    }
-	  /* This handles code like new char[]{"foo"}.  */
-	  else if (len == 1
-		   && char_type_p (TYPE_MAIN_VARIANT (type))
-		   && TREE_CODE (tree_strip_any_location_wrapper ((**init)[0]))
-		      == STRING_CST)
-	    {
-	      vecinit = (**init)[0];
-	      STRIP_ANY_LOCATION_WRAPPER (vecinit);
-	    }
 	  else if (*init)
             {
               if (complain & tf_error)
@@ -3944,9 +3935,9 @@ build_new (location_t loc, vec<tree, va_gc> **placement, tree type,
     }
 
   /* P1009: Array size deduction in new-expressions.  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      && !TYPE_DOMAIN (type)
-      && *init)
+  const bool deduce_array_p = (TREE_CODE (type) == ARRAY_TYPE
+			       && !TYPE_DOMAIN (type));
+  if (*init && (deduce_array_p || (nelts && cxx_dialect >= cxx20)))
     {
       /* This means we have 'new T[]()'.  */
       if ((*init)->is_empty ())
@@ -3955,16 +3946,20 @@ build_new (location_t loc, vec<tree, va_gc> **placement, tree type,
 	  CONSTRUCTOR_IS_DIRECT_INIT (ctor) = true;
 	  vec_safe_push (*init, ctor);
 	}
+      tree array_type = deduce_array_p ? TREE_TYPE (type) : type;
       tree &elt = (**init)[0];
       /* The C++20 'new T[](e_0, ..., e_k)' case allowed by P0960.  */
       if (!DIRECT_LIST_INIT_P (elt) && cxx_dialect >= cxx20)
 	{
-	  /* Handle new char[]("foo").  */
+	  /* Handle new char[]("foo"): turn it into new char[]{"foo"}.  */
 	  if (vec_safe_length (*init) == 1
-	      && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))
+	      && char_type_p (TYPE_MAIN_VARIANT (array_type))
 	      && TREE_CODE (tree_strip_any_location_wrapper (elt))
 		 == STRING_CST)
-	    /* Leave it alone: the string should not be wrapped in {}.  */;
+	    {
+	      elt = build_constructor_single (init_list_type_node, NULL_TREE, elt);
+	      CONSTRUCTOR_IS_DIRECT_INIT (elt) = true;
+	    }
 	  else
 	    {
 	      tree ctor = build_constructor_from_vec (init_list_type_node, *init);
@@ -3977,9 +3972,15 @@ build_new (location_t loc, vec<tree, va_gc> **placement, tree type,
 	    }
 	}
       /* Otherwise we should have 'new T[]{e_0, ..., e_k}'.  */
-      if (BRACE_ENCLOSED_INITIALIZER_P (elt))
-	elt = reshape_init (type, elt, complain);
-      cp_complete_array_type (&type, elt, /*do_default*/false);
+      if (deduce_array_p)
+	{
+	  /* Don't reshape ELT itself: we want to pass a list-initializer to
+	     build_new_1, even for STRING_CSTs.  */
+	  tree e = elt;
+	  if (BRACE_ENCLOSED_INITIALIZER_P (e))
+	    e = reshape_init (type, e, complain);
+	  cp_complete_array_type (&type, e, /*do_default*/false);
+	}
     }
 
   /* The type allocated must be complete.  If the new-type-id was
diff --git a/gcc/testsuite/g++.dg/cpp2a/paren-init36.C b/gcc/testsuite/g++.dg/cpp2a/paren-init36.C
new file mode 100644
index 00000000000..996249515bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/paren-init36.C
@@ -0,0 +1,14 @@
+// PR c++/77841
+// { dg-do compile { target c++20 } }
+
+int *p0 = new int[1]();
+int *p1 = new int[1](1);
+int *p2 = new int[4](1, 2, 3, 4);
+int *p3 = new int[2](1, 2, 3, 4); // { dg-error "too many initializers" }
+
+char *c1 = new char[]("foo");
+char *c2 = new char[4]("foo");
+char *c3 = new char[]{"foo"};
+char *c4 = new char[4]{"foo"};
+char *c5 = new char[3]("so_sad"); // { dg-error "too long" }
+char *c6 = new char[3]{"so_sad"}; // { dg-error "too long" }
diff --git a/gcc/testsuite/g++.old-deja/g++.ext/arrnew2.C b/gcc/testsuite/g++.old-deja/g++.ext/arrnew2.C
index aff6b9c7c63..fceb95e9ee5 100644
--- a/gcc/testsuite/g++.old-deja/g++.ext/arrnew2.C
+++ b/gcc/testsuite/g++.old-deja/g++.ext/arrnew2.C
@@ -1,7 +1,7 @@
 // { dg-do compile }
 // { dg-options "-w -fpermissive" }
 
-int *foo = new int[1](42); // { dg-error "parenthesized" }
+int *foo = new int[1](42); // { dg-error "parenthesized" "" { target c++17_down } }
 int main ()
 {
   return foo[0] != 42;
diff --git a/gcc/testsuite/g++.old-deja/g++.robertl/eb58.C b/gcc/testsuite/g++.old-deja/g++.robertl/eb58.C
index d702296bdc7..1e51e14c51d 100644
--- a/gcc/testsuite/g++.old-deja/g++.robertl/eb58.C
+++ b/gcc/testsuite/g++.old-deja/g++.robertl/eb58.C
@@ -11,5 +11,5 @@ private:
 
 main()
 {
-  A *list = new A[10](4); // { dg-error "parenthesized" }
+  A *list = new A[10](4); // { dg-error "parenthesized|could not convert" }
 }

base-commit: 0dc80505562c89df617ea11c733ee2cfab53c3f7
-- 
2.26.2


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

end of thread, other threads:[~2020-09-09 21:43 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-06 15:34 [PATCH] c++: Further tweaks for new-expression and paren-init [PR77841] Marek Polacek
2020-09-08  3:19 ` Jason Merrill
2020-09-08 20:06   ` [PATCH v2] " Marek Polacek
2020-09-08 20:19     ` Jason Merrill
2020-09-09  2:34       ` [PATCH v3] " Marek Polacek
2020-09-09 21:02         ` Jason Merrill
2020-09-09 21:35           ` Marek Polacek
2020-09-09 21:43             ` 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).