Re: [PATCH v2] c++: Implement P1009: Array size deduction in new-expressions.

2020-08-24 Thread Jason Merrill via Gcc-patches

On 8/24/20 5:44 PM, Marek Polacek wrote:

On Fri, Aug 21, 2020 at 05:04:43PM -0400, Jason Merrill wrote:

On 8/20/20 4:22 PM, Marek Polacek wrote:

@@ -3917,6 +3926,47 @@ build_new (location_t loc, vec **placement, 
tree type,
 return error_mark_node;
   }
+  /* P1009: Array size deduction in new-expressions.  */
+  if (TREE_CODE (type) == ARRAY_TYPE
+  && !TYPE_DOMAIN (type)
+  && *init)
+{
+  /* This means we have 'new T[]()'.  */
+  if ((*init)->is_empty ())
+   {
+ tree ctor = build_constructor (init_list_type_node, NULL);
+ CONSTRUCTOR_IS_DIRECT_INIT (ctor) = true;
+ vec_safe_push (*init, ctor);
+   }
+  tree  = (**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").  */
+ if (vec_safe_length (*init) == 1
+ && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))
+ && TREE_CODE (tree_strip_any_location_wrapper (elt))
+== STRING_CST)
+   /* Leave it alone: the string should not be wrapped in {}.  */;
+ else
+   {
+ /* Create a CONSTRUCTOR from the vector INIT.  */
+ tree list = build_tree_list_vec (*init);
+ tree ctor = build_constructor_from_list (init_list_type_node, 
list);
+ CONSTRUCTOR_IS_DIRECT_INIT (ctor) = true;
+ CONSTRUCTOR_IS_PAREN_INIT (ctor) = true;


It seems wasteful to build a TREE_LIST only to throw it away; let's add a
function to build a CONSTRUCTOR directly from a vec*.  And use it in
build_new_method_call_1 as well.


Good point.  Done.


@@ -9082,14 +9084,17 @@ cp_parser_direct_new_declarator (cp_parser* parser)
 cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE);
 token = cp_lexer_peek_token (parser->lexer);
-  expression = cp_parser_expression (parser);
+  if (token->type == CPP_CLOSE_SQUARE)
+   expression = NULL_TREE;


Only the first bound is optional; we need to require the expression for
subsequent bounds.


Fixed (though the diagnostic we gave was pretty good).  New test added.

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

-- >8 --
This patch implements C++20 P1009, allowing code like

   new double[]{1,2,3}; // array bound will be deduced

Since this proposal makes the initialization rules more consistent, it is
applied to all previous versions of C++ (thus, effectively, all the way back
to C++11).

My patch is based on Jason's patch that handled the basic case.  I've
extended it to work with ()-init and also the string literal case.
Further testing revealed that to handle stuff like

   new int[]{t...};

in a template, we have to consider such a NEW_EXPR type-dependent.
Obviously, we first have to expand the pack to be able to deduce the
number of elements in the array.

Curiously, while implementing this proposal, I noticed that we fail
to accept

   new char[4]{"abc"};

so I've assigned 77841 to self.  I think the fix will depend on the
build_new_1 hunk in this patch.

The new tree.c function build_constructor_from_vec helps us morph
a vector into a CONSTRUCTOR more efficiently.

gcc/cp/ChangeLog:

PR c++/93529
* call.c (build_new_method_call_1): Use build_constructor_from_vec
instead of build_tree_list_vec + build_constructor_from_list.
* init.c (build_new_1): Handle new char[]{"foo"}.  Use
build_constructor_from_vec instead of build_tree_list_vec +
build_constructor_from_list.
(build_new): Deduce the array size in new-expression if not
present.  Handle ()-init.  Handle initializing an array from
a string literal.
* parser.c (cp_parser_new_type_id): Leave [] alone.
(cp_parser_direct_new_declarator): Allow [].
* pt.c (type_dependent_expression_p): In a NEW_EXPR, consider
array types whose dimension has to be deduced type-dependent.

gcc/ChangeLog:

PR c++/93529
* tree.c (build_constructor_from_vec): New.
* tree.h (build_constructor_from_vec): Declare.

gcc/testsuite/ChangeLog:

PR c++/93529
* g++.dg/cpp0x/sfinae4.C: Adjust expected result after P1009.
* g++.dg/cpp2a/new-array1.C: New test.
* g++.dg/cpp2a/new-array2.C: New test.
* g++.dg/cpp2a/new-array3.C: New test.
* g++.dg/cpp2a/new-array4.C: New test.

Co-authored-by: Jason Merrill 
---
  gcc/cp/call.c   |  4 +-
  gcc/cp/init.c   | 55 +--
  gcc/cp/parser.c | 13 +++--
  gcc/cp/pt.c |  4 ++
  gcc/testsuite/g++.dg/cpp0x/sfinae4.C|  8 ++-
  gcc/testsuite/g++.dg/cpp2a/new-array1.C | 70 +
  gcc/testsuite/g++.dg/cpp2a/new-array2.C | 22 
  gcc/testsuite/g++.dg/cpp2a/new-array3.C | 17 ++
  

Re: [PATCH v2] c++: Implement P1009: Array size deduction in new-expressions.

2020-08-24 Thread Marek Polacek via Gcc-patches
On Fri, Aug 21, 2020 at 05:04:43PM -0400, Jason Merrill wrote:
> On 8/20/20 4:22 PM, Marek Polacek wrote:
> > @@ -3917,6 +3926,47 @@ build_new (location_t loc, vec 
> > **placement, tree type,
> > return error_mark_node;
> >   }
> > +  /* P1009: Array size deduction in new-expressions.  */
> > +  if (TREE_CODE (type) == ARRAY_TYPE
> > +  && !TYPE_DOMAIN (type)
> > +  && *init)
> > +{
> > +  /* This means we have 'new T[]()'.  */
> > +  if ((*init)->is_empty ())
> > +   {
> > + tree ctor = build_constructor (init_list_type_node, NULL);
> > + CONSTRUCTOR_IS_DIRECT_INIT (ctor) = true;
> > + vec_safe_push (*init, ctor);
> > +   }
> > +  tree  = (**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").  */
> > + if (vec_safe_length (*init) == 1
> > + && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))
> > + && TREE_CODE (tree_strip_any_location_wrapper (elt))
> > +== STRING_CST)
> > +   /* Leave it alone: the string should not be wrapped in {}.  */;
> > + else
> > +   {
> > + /* Create a CONSTRUCTOR from the vector INIT.  */
> > + tree list = build_tree_list_vec (*init);
> > + tree ctor = build_constructor_from_list (init_list_type_node, 
> > list);
> > + CONSTRUCTOR_IS_DIRECT_INIT (ctor) = true;
> > + CONSTRUCTOR_IS_PAREN_INIT (ctor) = true;
> 
> It seems wasteful to build a TREE_LIST only to throw it away; let's add a
> function to build a CONSTRUCTOR directly from a vec*.  And use it in
> build_new_method_call_1 as well.

Good point.  Done.

> > @@ -9082,14 +9084,17 @@ cp_parser_direct_new_declarator (cp_parser* parser)
> > cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE);
> > token = cp_lexer_peek_token (parser->lexer);
> > -  expression = cp_parser_expression (parser);
> > +  if (token->type == CPP_CLOSE_SQUARE)
> > +   expression = NULL_TREE;
> 
> Only the first bound is optional; we need to require the expression for
> subsequent bounds.

Fixed (though the diagnostic we gave was pretty good).  New test added.

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

-- >8 --
This patch implements C++20 P1009, allowing code like

  new double[]{1,2,3}; // array bound will be deduced

Since this proposal makes the initialization rules more consistent, it is
applied to all previous versions of C++ (thus, effectively, all the way back
to C++11).

My patch is based on Jason's patch that handled the basic case.  I've
extended it to work with ()-init and also the string literal case.
Further testing revealed that to handle stuff like

  new int[]{t...};

in a template, we have to consider such a NEW_EXPR type-dependent.
Obviously, we first have to expand the pack to be able to deduce the
number of elements in the array.

Curiously, while implementing this proposal, I noticed that we fail
to accept

  new char[4]{"abc"};

so I've assigned 77841 to self.  I think the fix will depend on the
build_new_1 hunk in this patch.

The new tree.c function build_constructor_from_vec helps us morph
a vector into a CONSTRUCTOR more efficiently.

gcc/cp/ChangeLog:

PR c++/93529
* call.c (build_new_method_call_1): Use build_constructor_from_vec
instead of build_tree_list_vec + build_constructor_from_list.
* init.c (build_new_1): Handle new char[]{"foo"}.  Use
build_constructor_from_vec instead of build_tree_list_vec +
build_constructor_from_list.
(build_new): Deduce the array size in new-expression if not
present.  Handle ()-init.  Handle initializing an array from
a string literal.
* parser.c (cp_parser_new_type_id): Leave [] alone.
(cp_parser_direct_new_declarator): Allow [].
* pt.c (type_dependent_expression_p): In a NEW_EXPR, consider
array types whose dimension has to be deduced type-dependent.

gcc/ChangeLog:

PR c++/93529
* tree.c (build_constructor_from_vec): New.
* tree.h (build_constructor_from_vec): Declare.

gcc/testsuite/ChangeLog:

PR c++/93529
* g++.dg/cpp0x/sfinae4.C: Adjust expected result after P1009.
* g++.dg/cpp2a/new-array1.C: New test.
* g++.dg/cpp2a/new-array2.C: New test.
* g++.dg/cpp2a/new-array3.C: New test.
* g++.dg/cpp2a/new-array4.C: New test.

Co-authored-by: Jason Merrill 
---
 gcc/cp/call.c   |  4 +-
 gcc/cp/init.c   | 55 +--
 gcc/cp/parser.c | 13 +++--
 gcc/cp/pt.c |  4 ++
 gcc/testsuite/g++.dg/cpp0x/sfinae4.C|  8 ++-
 gcc/testsuite/g++.dg/cpp2a/new-array1.C | 70 +
 gcc/testsuite/g++.dg/cpp2a/new-array2.C | 22 
 gcc/testsuite/g++.dg/cpp2a/new-array3.C | 17