From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-1.mimecast.com (us-smtp-2.mimecast.com [205.139.110.61]) by sourceware.org (Postfix) with ESMTP id 27AB23851C35 for ; Sun, 6 Sep 2020 15:34:32 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 27AB23851C35 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-116-Prr6TuNxO7-GxguU1CyDBQ-1; Sun, 06 Sep 2020 11:34:29 -0400 X-MC-Unique: Prr6TuNxO7-GxguU1CyDBQ-1 Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id BCBC318A2244 for ; Sun, 6 Sep 2020 15:34:28 +0000 (UTC) Received: from pdp-11.redhat.com (ovpn-112-118.rdu2.redhat.com [10.10.112.118]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5920D60C0F; Sun, 6 Sep 2020 15:34:28 +0000 (UTC) From: Marek Polacek To: Jason Merrill , GCC Patches Subject: [PATCH] c++: Further tweaks for new-expression and paren-init [PR77841] Date: Sun, 6 Sep 2020 11:34:21 -0400 Message-Id: <20200906153421.3225331-1-polacek@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Mimecast-Spam-Score: 0.001 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-14.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 06 Sep 2020 15:34:33 -0000 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 **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 **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 **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 **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