Re: [PATCH v2] c++: Implement P1009: Array size deduction in new-expressions.
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.
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