From patchwork Wed Jun 29 22:25:41 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 102685 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id C1770B6F72 for ; Thu, 30 Jun 2011 08:26:02 +1000 (EST) Received: (qmail 17157 invoked by alias); 29 Jun 2011 22:26:01 -0000 Received: (qmail 17142 invoked by uid 22791); 29 Jun 2011 22:25:59 -0000 X-SWARE-Spam-Status: No, hits=-6.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 29 Jun 2011 22:25:43 +0000 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p5TMPgUB002843 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 29 Jun 2011 18:25:43 -0400 Received: from [127.0.0.1] (ovpn-113-39.phx2.redhat.com [10.3.113.39]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p5TMPg5Z012154 for ; Wed, 29 Jun 2011 18:25:42 -0400 Message-ID: <4E0BA665.5040105@redhat.com> Date: Wed, 29 Jun 2011 18:25:41 -0400 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.17) Gecko/20110428 Fedora/3.1.10-1.fc14 Lightning/1.0b2 Thunderbird/3.1.10 MIME-Version: 1.0 To: gcc-patches List Subject: Re: C++ PATCH for c++/49216 (problems with new T[1]{}) References: <4DFFFEB9.6070901@redhat.com> In-Reply-To: <4DFFFEB9.6070901@redhat.com> Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org As reported, this still wasn't working properly for an array of scalar type. We still need to handle {} in the case of iterating over all the elements. While I was poking at related code, I fixed a wrong-code bug with the ancient and permerrored new T[n](init) extension because it was easy. Tested x86_64-pc-linux-gnu, applying to trunk. commit dd6c8f64eec3752e9a7cf63b8ef2e46627fb5af1 Author: Jason Merrill Date: Wed Jun 29 17:13:49 2011 -0400 PR c++/49216 * init.c (build_new_1): Pass {} down to build_vec_init. (build_vec_init): Handle it. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index ac2b733..f80c475 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2396,24 +2396,31 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *init, 0)) && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *init, 0))) { - tree arraytype, domain; vecinit = VEC_index (tree, *init, 0); - if (TREE_CONSTANT (nelts)) - domain = compute_array_index_type (NULL_TREE, nelts, complain); + if (CONSTRUCTOR_NELTS (vecinit) == 0) + /* List-value-initialization, leave it alone. */; else { - domain = NULL_TREE; - if (CONSTRUCTOR_NELTS (vecinit) > 0) - warning (0, "non-constant array size in new, unable to " - "verify length of initializer-list"); + tree arraytype, domain; + if (TREE_CONSTANT (nelts)) + domain = compute_array_index_type (NULL_TREE, nelts, + complain); + else + { + domain = NULL_TREE; + if (CONSTRUCTOR_NELTS (vecinit) > 0) + warning (0, "non-constant array size in new, unable " + "to verify length of initializer-list"); + } + arraytype = build_cplus_array_type (type, domain); + vecinit = digest_init (arraytype, vecinit, complain); } - arraytype = build_cplus_array_type (type, domain); - vecinit = digest_init (arraytype, vecinit, complain); } else if (*init) { if (complain & tf_error) - permerror (input_location, "ISO C++ forbids initialization in array new"); + permerror (input_location, + "parenthesized initializer in array new"); else return error_mark_node; vecinit = build_tree_list_vec (*init); @@ -3090,9 +3097,23 @@ build_vec_init (tree base, tree maxindex, tree init, try_block = begin_try_block (); } + /* If the initializer is {}, then all elements are initialized from {}. + But for non-classes, that's the same as value-initialization. */ + if (init && BRACE_ENCLOSED_INITIALIZER_P (init) + && CONSTRUCTOR_NELTS (init) == 0) + { + if (CLASS_TYPE_P (type)) + /* Leave init alone. */; + else + { + init = NULL_TREE; + explicit_value_init_p = true; + } + } + /* Maybe pull out constant value when from_array? */ - if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR) + else if (init != NULL_TREE && TREE_CODE (init) == CONSTRUCTOR) { /* Do non-default initialization of non-trivial arrays resulting from brace-enclosed initializers. */ @@ -3210,7 +3231,7 @@ build_vec_init (tree base, tree maxindex, tree init, We do need to keep going if we're copying an array. */ if (from_array - || ((type_build_ctor_call (type) || explicit_value_init_p) + || ((type_build_ctor_call (type) || init || explicit_value_init_p) && ! (host_integerp (maxindex, 0) && (num_initialized_elts == tree_low_cst (maxindex, 0) + 1)))) @@ -3276,8 +3297,16 @@ build_vec_init (tree base, tree maxindex, tree init, } else { - gcc_assert (type_build_ctor_call (type)); - elt_init = build_aggr_init (to, init, 0, complain); + gcc_assert (type_build_ctor_call (type) || init); + if (CLASS_TYPE_P (type)) + elt_init = build_aggr_init (to, init, 0, complain); + else + { + if (TREE_CODE (init) == TREE_LIST) + init = build_x_compound_expr_from_list (init, ELK_INIT, + complain); + elt_init = build2 (INIT_EXPR, type, to, init); + } } if (elt_init == error_mark_node) diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-value.C b/gcc/testsuite/g++.dg/cpp0x/initlist-value.C index 25a3373..215bb90 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist-value.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-value.C @@ -2,6 +2,9 @@ // { dg-options -std=c++0x } // { dg-do run } +void * operator new (__SIZE_TYPE__, void *p) { return p; } +void * operator new[] (__SIZE_TYPE__, void *p) { return p; } + // Empty base so A isn't an aggregate struct B {}; struct A: B { @@ -18,8 +21,14 @@ int main() { A a{}; C c; + int space = 42; + A* ap = new (&space) A{}; + int space1[1] = { 42 }; + A* a1p = new (space1) A[1]{}; if (a.i != 0 || c.i != 0 + || ap->i != 0 + || a1p[0].i != 0 || A{}.i != 0 || f({}) != 0) return 1; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist53.C b/gcc/testsuite/g++.dg/cpp0x/initlist53.C index 750ebba..22633f9 100644 --- a/gcc/testsuite/g++.dg/cpp0x/initlist53.C +++ b/gcc/testsuite/g++.dg/cpp0x/initlist53.C @@ -4,6 +4,7 @@ #include extern "C" void abort(); +void * operator new[] (__SIZE_TYPE__, void *p) { return p; } bool constructed; @@ -14,7 +15,8 @@ struct A int main() { new A[1]{}; - int *p = new int[1]{}; + int space[1] = { 42 }; + int *p = new (space) int[1]{}; if (p[0] != 0 || !constructed) abort(); } diff --git a/gcc/testsuite/g++.old-deja/g++.ext/arrnew2.C b/gcc/testsuite/g++.old-deja/g++.ext/arrnew2.C index 93d15d0..5bd113f 100644 --- a/gcc/testsuite/g++.old-deja/g++.ext/arrnew2.C +++ b/gcc/testsuite/g++.old-deja/g++.ext/arrnew2.C @@ -1,4 +1,3 @@ -// { dg-do run { xfail *-*-* } } // { dg-options "-w -fpermissive" } int *foo = new int[1](42); // { dg-bogus "" }