From patchwork Mon Nov 22 02:51:12 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: will wray X-Patchwork-Id: 47983 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id AB75D385841A for ; Mon, 22 Nov 2021 02:53:02 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org AB75D385841A DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1637549582; bh=OGuVGW0YcOuC97syf68quPjIiuIZ33uPSW+f5FEqi4I=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=eWpHKemRpMhhSJM/sKu+cOiCTlhsTvfwuKxnHCRv7LlwuBm/2xhO+jHwnmlnOvmI+ XE8HrMARLEMqzjK9CWV8yKO86CCP87sLIkoOWYvReZPNK+WPcTYaq09r62K5lFvpPB 42lxoX5IKUBB/BqCs1BA/fQ8523gUJieADIDJNfk= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qv1-xf29.google.com (mail-qv1-xf29.google.com [IPv6:2607:f8b0:4864:20::f29]) by sourceware.org (Postfix) with ESMTPS id AA5293858013 for ; Mon, 22 Nov 2021 02:51:46 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org AA5293858013 Received: by mail-qv1-xf29.google.com with SMTP id bu11so11551724qvb.0 for ; Sun, 21 Nov 2021 18:51:46 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=OGuVGW0YcOuC97syf68quPjIiuIZ33uPSW+f5FEqi4I=; b=biLS98+eFiF16RQiqL+tcDBkN8Ihad45IEoEqKeaFrt3T9zHnt750ebT1ro6/fT3fx 6A+QfOHnX1AR2U2v2xx4URJFqgdUltIpvIc5SAXYcyqHIxnYlgozEUufIIWhauIog+/p Q6kXIFJ3J9EOfPmBOFJPH23lBZxX28tmebva0DWDLTvSMaYhJ90tarcIN2x4Q6HDmqck c57df9+uNWs3CvwBcoBEeJpTplYsvhWe++gsqTO9xDAkFIPIPCMPl8McDZXEDMsyUlJb /Qxi1uuqhFs7xu+bXLnNs967QwGHj/X2CnBlWXy1pmDUwM7ao2dsag61fWOf5naHcQq6 HN3A== X-Gm-Message-State: AOAM533r0Adz7SWbGpOhm4toI7ZbG8nEh7/Unxt99oIhbEVD6so7DRBe rQImqAHR20cwCtQBZ+6DKT65vZT3ot8= X-Google-Smtp-Source: ABdhPJxbEpw56bdC7OS1jotUVAEVN93GA31driIVIBtq955dgHpu4OTYviqZPs7YlQMMPGV4tzE0sA== X-Received: by 2002:a05:6214:ace:: with SMTP id g14mr96754680qvi.12.1637549505969; Sun, 21 Nov 2021 18:51:45 -0800 (PST) Received: from localhost.localdomain (bras-base-sttnpq8102w-grc-16-142-115-13-133.dsl.bell.ca. [142.115.13.133]) by smtp.googlemail.com with ESMTPSA id t35sm3947822qtc.83.2021.11.21.18.51.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 21 Nov 2021 18:51:45 -0800 (PST) To: gcc-patches@gcc.gnu.org Subject: [PATCH 1/3] c++: designated init of char array by string constant [PR55227] Date: Sun, 21 Nov 2021 21:51:12 -0500 Message-Id: <20211122025114.3167997-2-wjwray@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211122025114.3167997-1-wjwray@gmail.com> References: <20211122025114.3167997-1-wjwray@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-9.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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-Patchwork-Original-From: Will Wray via Gcc-patches From: will wray Reply-To: Will Wray Cc: Will Wray Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Also address "FIXME: this code is duplicated from reshape_init" in cp_complete_array_type by always calling reshape_init on init-list. PR c++/55227 gcc/cp/ChangeLog: * decl.c (reshape_init_r): Only call has_designator_check when first_initializer_p or for the inner constructor element. (cp_complete_array_type): Call reshape_init on braced-init-list. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/desig20.C: New test. --- gcc/cp/decl.c | 42 +++++++++++++------------------ gcc/testsuite/g++.dg/cpp2a/desig20.C | 48 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 25 deletions(-) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2ddf0e4a524..83a2d3bf8f1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6824,28 +6824,31 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, if (TREE_CODE (type) == ARRAY_TYPE && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))) { - tree str_init = init; - tree stripped_str_init = stripped_init; + tree arr_init = init; + tree stripped_arr_init = stripped_init; + reshape_iter stripd = {}; /* Strip one level of braces if and only if they enclose a single element (as allowed by [dcl.init.string]). */ if (!first_initializer_p - && TREE_CODE (stripped_str_init) == CONSTRUCTOR - && CONSTRUCTOR_NELTS (stripped_str_init) == 1) + && TREE_CODE (stripped_arr_init) == CONSTRUCTOR + && CONSTRUCTOR_NELTS (stripped_arr_init) == 1) { - str_init = (*CONSTRUCTOR_ELTS (stripped_str_init))[0].value; - stripped_str_init = tree_strip_any_location_wrapper (str_init); + stripd.cur = CONSTRUCTOR_ELT (stripped_arr_init, 0); + arr_init = stripd.cur->value; + stripped_arr_init = tree_strip_any_location_wrapper (arr_init); } /* If it's a string literal, then it's the initializer for the array as a whole. Otherwise, continue with normal initialization for array types (one value per array element). */ - if (TREE_CODE (stripped_str_init) == STRING_CST) + if (TREE_CODE (stripped_arr_init) == STRING_CST) { - if (has_designator_problem (d, complain)) + if ((first_initializer_p && has_designator_problem (d, complain)) + || (stripd.cur && has_designator_problem (&stripd, complain))) return error_mark_node; d->cur++; - return str_init; + return arr_init; } } @@ -9545,22 +9548,11 @@ cp_complete_array_type (tree *ptype, tree initial_value, bool do_default) if (initial_value) { /* An array of character type can be initialized from a - brace-enclosed string constant. - - FIXME: this code is duplicated from reshape_init. Probably - we should just call reshape_init here? */ - if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (*ptype))) - && TREE_CODE (initial_value) == CONSTRUCTOR - && !vec_safe_is_empty (CONSTRUCTOR_ELTS (initial_value))) - { - vec *v = CONSTRUCTOR_ELTS (initial_value); - tree value = (*v)[0].value; - STRIP_ANY_LOCATION_WRAPPER (value); - - if (TREE_CODE (value) == STRING_CST - && v->length () == 1) - initial_value = value; - } + brace-enclosed string constant so call reshape_init to + remove the optional braces from a braced string literal. */ + if (BRACE_ENCLOSED_INITIALIZER_P (initial_value)) + initial_value = reshape_init (*ptype, initial_value, + tf_warning_or_error); /* If any of the elements are parameter packs, we can't actually complete this type now because the array size is dependent. */ diff --git a/gcc/testsuite/g++.dg/cpp2a/desig20.C b/gcc/testsuite/g++.dg/cpp2a/desig20.C new file mode 100644 index 00000000000..daadfa58855 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/desig20.C @@ -0,0 +1,48 @@ +// PR c++/55227 +// Test designated initializer for char array by string constant + +// { dg-options "" } + +struct C {char a[2];}; + +/* Case a, designated, unbraced, string-literal of the exact same size + as the initialized char array; valid and accepted before and after. */ +C a = {.a="a"}; + +/* Cases b,c,d, designated, braced or mimatched-size, string literal, + previously rejected; "C99 designator 'a' outside aggregate initializer". */ +C b = {.a=""}; +C c = {.a={""}}; +C d = {.a={"a"}}; + +/* Case e, designated char array field and braced, designated array element(s) + (with GNU [N]= extension) valid and accepted before and after. */ +C e = {.a={[0]='a'}}; + +/* Cases f,g,h, braced string literal, 'designated' within inner braces; + invalid, previously accepted as positional with 'designator' ignored. */ +C f = {{[0]="a"}}; // { dg-error "C99 designator .0. outside aggregate initializer" } +C g = {{.a="a"}}; // { dg-error "C99 designator .a. outside aggregate initializer" } +C h = {{.b="a"}}; // { dg-error "C99 designator .b. outside aggregate initializer" } + +char a2[][10] = { [0] = { "aaa" } }; + +struct D { C c; int a[8]; }; + +D x = { .c {.a={"a"}}, .a={1,2,3,4,5,6,7,8} }; + +struct A { union { int a; char c[4]; }; }; + +A non = { .c = "c++" }; + +template +void t() +{ + C ca[] = { {.a=""}, {.a={""}}, }; + +} + +void u() +{ + return t(); +} From patchwork Mon Nov 22 02:51:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: will wray X-Patchwork-Id: 47984 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id E77D03858424 for ; Mon, 22 Nov 2021 02:53:59 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E77D03858424 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1637549639; bh=cu2K3XRsaYLNH2DdOPiPeAwaGRyJQe4FXXHjuY52+Jk=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=AoVEo3Pw+PeXIehUUkTI4zVst5ExTflurJxmAQ3lkybNY3cHT+MWN96CSvX3ZI2ku x49KR9WEmMxMOgutD5ii+XfzcajorxtjBZKObeW6Fs7kWSFQuO9ZsGfdQk60v/v9io IqbFsZfxWELZATX4HnECRGL3dBLWCJkEl7XxS5nw= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qt1-x830.google.com (mail-qt1-x830.google.com [IPv6:2607:f8b0:4864:20::830]) by sourceware.org (Postfix) with ESMTPS id 6D9AE3858002 for ; Mon, 22 Nov 2021 02:51:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 6D9AE3858002 Received: by mail-qt1-x830.google.com with SMTP id p19so15241848qtw.12 for ; Sun, 21 Nov 2021 18:51:49 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=cu2K3XRsaYLNH2DdOPiPeAwaGRyJQe4FXXHjuY52+Jk=; b=jx77gNz4olaZU9Qs7EMERnBvkF3QugQr5jHwHHxlOKV5vZL0WtO4CkQqL9VsIqiVDP yOoKjd1ktloX4lSIRWqo6iuyfxyGxlblHni1dqKeD7yc+IkiVEf74nN7zxE+CWQ5AP3z AzsHsQiAAYyzfE2metK0GI0zw9eQie5bkB1E+V47QyxgQJUU5+bqyJ13Yrlm2tQqCDfU hnLSbLC/aUeojMFJ/sXloOJL1LXdyTQInvE41eSHWwYTKmo9E3bR7EeG9FcToQ44US9m BBQS4oQ99hduYZk0e4Ucfd8rUnPeiF/sJWVRRovMwjuhn1+P7QskbzAavrG23iDLDk9L 6bMA== X-Gm-Message-State: AOAM5331OcjCEnQRc2JoF3RCCMH2DoN7JPIEXvIwev51IzNqQhbunaV1 buZFRp5SrUNQ02DiEXUNfaah60RrGXQ= X-Google-Smtp-Source: ABdhPJzq7g+0yKUpZ5pAcP3BoOnxo8LFZmULdIArp7VKSbCpgCZuxCF2iFnhiyg6vW7cYqxp5eHNxw== X-Received: by 2002:ac8:5cc6:: with SMTP id s6mr28321442qta.136.1637549508256; Sun, 21 Nov 2021 18:51:48 -0800 (PST) Received: from localhost.localdomain (bras-base-sttnpq8102w-grc-16-142-115-13-133.dsl.bell.ca. [142.115.13.133]) by smtp.googlemail.com with ESMTPSA id t35sm3947822qtc.83.2021.11.21.18.51.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 21 Nov 2021 18:51:47 -0800 (PST) To: gcc-patches@gcc.gnu.org Subject: [PATCH 2/3] c++: P1997 array-copy extensions: Initialization [PR103238] Date: Sun, 21 Nov 2021 21:51:13 -0500 Message-Id: <20211122025114.3167997-3-wjwray@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211122025114.3167997-1-wjwray@gmail.com> References: <20211122025114.3167997-1-wjwray@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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-Patchwork-Original-From: Will Wray via Gcc-patches From: will wray Reply-To: Will Wray Cc: Will Wray Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This patch implements initializations of arrays from array values. The first of two 'array-copy' patches, it adds the option -farray-copy (flag_array_copy) to enable all features of P1997 (copy related or not), documented as experimental extensions. It deals with initialization of array variables and member array fields. Initialization of an array variable from an array of the same type performs array copy-initialization; elementwise move or copy from an rvalue or lvalue array respectively, in index order from begin to end. The existing code path for a structured binding declaration with array initializer, auto[e...]{a}; performs the same array copy-initialization (as a special case superpower). Borrowing from that, this was a relatively quick and easy change. Initialization of member arrays proved much more difficult to do in general. I resorted to trial and error, running gcc in gdb with test cases to work out where and what to change, until eventually converging on this set of changes. One starting point was the C special case of char array initialization from string literals (as char array lvalue constants). However, a long-standing bug in designated initialization of char arrays by string literals blocked the task of extending this special case to general array type initializers. A bugfix patch was separated out, to be merged ahead of these patches: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55227 https://gcc.gnu.org/pipermail/gcc-patches/2021-November/584897.html Other cases to consider, array initializations: * by optionally brace-enclosed or paren-enclosed array values * by possibly-designated array-valued aggregate initializers (within possibly-elided braced init-lists) * by brace or paren-enclosed array values in member initialization lists * by array-valued member initializers The patch adds tests for these cases, and for inner initializations of nested array elements of array type. The work has diverged in details from the P1997 wording, including catching up with C++20 changes such as parenthesised initialization of aggregates. The paper will be revised to reflect the implementation experience. It is likely that there are omissions, errors in the conditions or that changed code is inappropriate. For example, I inserted a new call to build_array_copy in typeck2.c:digest_init_r which may not be correct for move-enabled elements. Please review carefully with this in mind and suggest test cases to exercise. PR c++/103238 gcc/c-family/ChangeLog: * c-common.c (complete_array_type): Accept array type initial_value. * c.opt: New option -farray-copy "experimental extensions for P1997". gcc/cp/ChangeLog: * decl.c (do_aggregate_paren_init): Accept single array type init. (maybe_deduce_size_from_array_init): Include same-type array inits, or complain for not same-type arrays. (reshape_init_r): Extend string-literal handling to all array types. * init.c (build_aggr_init): Follow existing path for array rhs. * typeck.c (cp_build_modify_expr): Follow path for synthetic op=. * typeck2.c (digest_init_r): Add call to build_array_copy for same-type arrays ('copy' feels wrong for move-eligible rhs). gcc/ChangeLog: * doc/invoke.texi: -farray-copy help info documentation. gcc/testsuite/ChangeLog: * g++.dg/init/array-copy1.C: New test. Variable init 'before' XFAILs * g++.dg/init/array-copy2.C: New test. Variable init 'after' PASSes * g++.dg/init/array-copy3.C: New test. Member init 'before' XFAILs * g++.dg/init/array-copy4.C: New test. Member init 'after' PASSes * g++.dg/init/array-copy5.C: New test. Member nsdmi & desig XFAILs * g++.dg/init/array-copy6.C: New test. Member nsdmi & desig PASSes --- gcc/c-family/c-common.c | 5 +++ gcc/c-family/c.opt | 4 ++ gcc/cp/decl.c | 61 ++++++++++++++++++++--------- gcc/cp/init.c | 6 ++- gcc/cp/typeck.c | 9 +++-- gcc/cp/typeck2.c | 30 +++++++++++---- gcc/doc/invoke.texi | 6 +++ gcc/testsuite/g++.dg/init/array-copy1.C | 66 ++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/init/array-copy2.C | 68 +++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/init/array-copy3.C | 41 ++++++++++++++++++++ gcc/testsuite/g++.dg/init/array-copy4.C | 42 ++++++++++++++++++++ gcc/testsuite/g++.dg/init/array-copy5.C | 36 +++++++++++++++++ gcc/testsuite/g++.dg/init/array-copy6.C | 51 +++++++++++++++++++++++++ 13 files changed, 395 insertions(+), 30 deletions(-) diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 86c007f53de..fb0b1ef294f 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -6796,6 +6796,11 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value))); maxindex = size_int (TREE_STRING_LENGTH (initial_value)/eltsize - 1); } + else if (flag_array_copy + && TREE_CODE (TREE_TYPE (initial_value)) == ARRAY_TYPE) + { + maxindex = array_type_nelts (TREE_TYPE (initial_value)); + } else if (TREE_CODE (initial_value) == CONSTRUCTOR) { vec *v = CONSTRUCTOR_ELTS (initial_value); diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 3976fc368db..9d2a6ad8e1c 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -1579,6 +1579,10 @@ fcilkplus C ObjC C++ ObjC++ LTO Undocumented Ignore Removed in GCC 8. This switch has no effect. +farray-copy +C ObjC C++ ObjC++ Var(flag_array_copy) +Enable experimental extension for P1997; C array copy semantics. + fconcepts C++ ObjC++ Var(flag_concepts) Enable support for C++ concepts. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 83a2d3bf8f1..1010fa2c53f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5834,15 +5834,19 @@ tree do_aggregate_paren_init (tree init, tree type) { tree val = TREE_VALUE (init); + tree stripped_val = tree_strip_any_location_wrapper (val); if (TREE_CHAIN (init) == NULL_TREE) { /* If the list has a single element and it's a string literal, then it's the initializer for the array as a whole. */ - if (TREE_CODE (type) == ARRAY_TYPE - && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))) - && TREE_CODE (tree_strip_any_location_wrapper (val)) - == STRING_CST) + if ((TREE_CODE (type) == ARRAY_TYPE + && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))) + && TREE_CODE (stripped_val) == STRING_CST) + || (flag_array_copy + && TREE_CODE (TREE_TYPE (stripped_val)) == ARRAY_TYPE + && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type), + TREE_TYPE (TREE_TYPE (stripped_val))))) return val; /* Handle non-standard extensions like compound literals. This also prevents triggering aggregate parenthesized-initialization in @@ -6007,9 +6011,10 @@ maybe_deduce_size_from_array_init (tree decl, tree init) { tree type = TREE_TYPE (decl); - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_DOMAIN (type) == NULL_TREE - && TREE_CODE (decl) != TYPE_DECL) + if (TREE_CODE (type) != ARRAY_TYPE + || TREE_CODE (decl) == TYPE_DECL) + ; + else if (TYPE_DOMAIN (type) == NULL_TREE) { /* do_default is really a C-ism to deal with tentative definitions. But let's leave it here to ease the eventual merge. */ @@ -6072,6 +6077,17 @@ maybe_deduce_size_from_array_init (tree decl, tree init) relayout_decl (decl); } + else if (flag_array_copy && init + && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE + && TREE_CODE (tree_strip_any_location_wrapper (init)) != STRING_CST + && !same_type_ignoring_top_level_qualifiers_p (type, + TREE_TYPE (init))) + { + error_at (DECL_SOURCE_LOCATION (decl), + "array of type %qT cannot be initialized with an " + "array of type %qT in %qD", type, TREE_TYPE (init), decl); + TREE_TYPE (decl) = error_mark_node; + } } /* Set DECL_SIZE, DECL_ALIGN, etc. for DECL (a VAR_DECL), and issue @@ -6815,21 +6831,23 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, return init; } - /* [dcl.init.string] + /* [dcl.init.string] or flag_array_copy extension P1997 A char array (whether plain char, signed char, or unsigned char) can be initialized by a string-literal (optionally enclosed in braces); a wchar_t array can be initialized by a wide - string-literal (optionally enclosed in braces). */ - if (TREE_CODE (type) == ARRAY_TYPE - && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))) + string-literal (optionally enclosed in braces). + With flag_array_copy an array can be initialized by an array value + (optionally enclosed in braces). */ + if (TREE_CODE (type) == ARRAY_TYPE) { tree arr_init = init; tree stripped_arr_init = stripped_init; reshape_iter stripd = {}; - /* Strip one level of braces if and only if they enclose a single - element (as allowed by [dcl.init.string]). */ + /* Strip one level of braces if they enclose a single element, + provisionally for elison in the optionally-braced case if the + initializer is of compatible array type, as checked next. */ if (!first_initializer_p && TREE_CODE (stripped_arr_init) == CONSTRUCTOR && CONSTRUCTOR_NELTS (stripped_arr_init) == 1) @@ -6839,10 +6857,19 @@ reshape_init_r (tree type, reshape_iter *d, tree first_initializer_p, stripped_arr_init = tree_strip_any_location_wrapper (arr_init); } - /* If it's a string literal, then it's the initializer for the array - as a whole. Otherwise, continue with normal initialization for - array types (one value per array element). */ - if (TREE_CODE (stripped_arr_init) == STRING_CST) + tree init_type = TREE_TYPE (stripped_arr_init); + + /* If it's a string literal initializer for a char array target, + or, with flag_array_copy, an array value of same element type, + then it's the initializer for the array as a whole. + Else, continue with element by element array initialization. */ + if ((TREE_CODE (stripped_arr_init) == STRING_CST + && char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))) + || (flag_array_copy + && TREE_CODE (init_type) == ARRAY_TYPE + && TYPE_DOMAIN (init_type) != NULL_TREE + && same_type_ignoring_top_level_qualifiers_p ( + TREE_TYPE (type), TREE_TYPE (init_type)))) { if ((first_initializer_p && has_designator_problem (d, complain)) || (stripd.cur && has_designator_problem (&stripd, complain))) diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 3ba2e3bbe04..fd9a065ed95 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1787,7 +1787,11 @@ build_aggr_init (tree exp, tree init, int flags, tsubst_flags_t complain) tree itype = init ? TREE_TYPE (init) : NULL_TREE; int from_array = 0; - if (VAR_P (exp) && DECL_DECOMPOSITION_P (exp)) + if (VAR_P (exp) + && (DECL_DECOMPOSITION_P (exp) + || (flag_array_copy + && TREE_CODE (tree_strip_any_location_wrapper (init)) + != STRING_CST))) { from_array = 1; init = mark_rvalue_use (init); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index cb20329ceb5..8e96a925186 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -9144,11 +9144,12 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, } /* Allow array assignment in compiler-generated code. */ - else if (!current_function_decl - || !DECL_DEFAULTED_FN (current_function_decl)) + else if ((!current_function_decl + || !DECL_DEFAULTED_FN (current_function_decl)) + && !flag_array_copy) { - /* This routine is used for both initialization and assignment. - Make sure the diagnostic message differentiates the context. */ + /* This routine is used for both initialization and assignment. + Make sure the diagnostic message differentiates the context. */ if (complain & tf_error) { if (modifycode == INIT_EXPR) diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index e98fbf7f5fa..20d46716279 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1175,6 +1175,9 @@ digest_init_r (tree type, tree init, int nested, int flags, } return init; } + if (flag_array_copy + && same_type_ignoring_top_level_qualifiers_p(type, TREE_TYPE (init))) + return build_array_copy(init); } /* Handle scalar types (including conversions) and references. */ @@ -1244,13 +1247,18 @@ digest_init_r (tree type, tree init, int nested, int flags, complain); else { - if (COMPOUND_LITERAL_P (stripped_init) && code == ARRAY_TYPE) + if (COMPOUND_LITERAL_P (stripped_init) && code == ARRAY_TYPE + && (complain & tf_error)) { - if (complain & tf_error) - error_at (loc, "cannot initialize aggregate of type %qT with " - "a compound literal", type); - - return error_mark_node; + if (flag_array_copy) + pedwarn (loc, OPT_Wpedantic, "ISO C++ doesn%'t allow initialization" + "of an array of type %qT with a compound literal", type); + else + { + error_at (loc, "cannot initialize aggregate of type %qT with " + "a compound literal", type); + return error_mark_node; + } } if (code == ARRAY_TYPE @@ -1265,8 +1273,14 @@ digest_init_r (tree type, tree init, int nested, int flags, return init; if (complain & tf_error) - error_at (loc, "array must be initialized with a brace-enclosed" - " initializer"); + { + if (!flag_array_copy) + error_at (loc, "array must be initialized with a brace-enclosed" + " initializer"); + else + error_at (loc, "array must be initialized with a brace-enclosed" + " initializer or an array value of the same type"); + } return error_mark_node; } diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index d62ec08150e..32a34ca74bb 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -213,6 +213,7 @@ in the following sections. @xref{C++ Dialect Options,,Options Controlling C++ Dialect}. @gccoptlist{-fabi-version=@var{n} -fno-access-control @gol -faligned-new=@var{n} -fargs-in-order=@var{n} -fchar8_t -fcheck-new @gol +-farray-copy @gol -fconstexpr-depth=@var{n} -fconstexpr-cache-depth=@var{n} @gol -fconstexpr-loop-limit=@var{n} -fconstexpr-ops-limit=@var{n} @gol -fno-elide-constructors @gol @@ -3001,6 +3002,11 @@ return value even without this option. In all other cases, when exhaustion is signalled by throwing @code{std::bad_alloc}. See also @samp{new (nothrow)}. +@item -farray-copy +@opindex farray-copy +Enables experimental support for P1997; C array copy semantics, pseudo- +destructors and auto placeholder for array element type. + @item -fconcepts @itemx -fconcepts-ts @opindex fconcepts diff --git a/gcc/testsuite/g++.dg/init/array-copy1.C b/gcc/testsuite/g++.dg/init/array-copy1.C new file mode 100644 index 00000000000..15986a00d1b --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy1.C @@ -0,0 +1,66 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array variable initialization nocompile tests - +// should give same errors before and after the array-copy patch. + +// { dg-do compile { target c++11 } } c++11 for uniform init + +typedef int int2[2]; +int2 u = {11,66}; + +int* p = new int2{u}; // { dg-error "invalid conversion from .int\\*. to .int. .\\-fpermissive." } + +// Initializations from from rvalue array +int2 g = int2{11,66}; +int2 j ( int2{11,66} ); // takes P0960 paren-init path in c++20 +int2 k = { int2{11,66} }; +int2 l { int2{11,66} }; +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-4 } +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-4 } +// { dg-error "taking address of temporary array" "address of temporary" { target *-*-* } .-4 } +// { dg-error "taking address of temporary array" "address of temporary" { target *-*-* } .-4 } + +// Initializations from from lvalue array +int2 gc = u; +int2 jc (u); // takes P0960 paren-init path in c++20 +int2 kc = {u}; +int2 lc {u}; +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-4 } +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-4 } +// { dg-error "invalid conversion from .int\\*. to .int. .\\-fpermissive." "bad conv" { target *-*-* } .-4 } +// { dg-error "invalid conversion from .int\\*. to .int. .\\-fpermissive." "bad conv" { target *-*-* } .-4 } + +char str[] = "str"; + +char cpy[] = str; +char cpp[] (str); // takes P0960 paren-init path in c++20 +char cpu[] = {str}; +char cpw[] {str}; +// { dg-error "initializer fails to determine size of .cpy." "deduce size" { target *-*-* } .-4 } +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-5 } +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target c++17_down } .-5 } +// { dg-error "initializer fails to determine size of .cpp." "deduce size" { target c++17_down } .-6 } +// { dg-error "invalid conversion from .char\\*. to .char. .\\-fpermissive." "bad conv" { target c++20 } .-7 } +// { dg-error "invalid conversion from .char\\*. to .char. .\\-fpermissive." "bad conv" { target *-*-* } .-7 } +// { dg-error "invalid conversion from .char\\*. to .char. .\\-fpermissive." "bad conv" { target *-*-* } .-7 } + +char cp5[5] = str; +char cp3[3] = str; +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-2 } +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-2 } + +int2 s[2] = { u }; +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-1 } +int2 x[2] = { u + , u }; +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-2 } +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-2 } +int2 y[2] = { 1,2 + , {u} }; +// { dg-error "invalid conversion from .int\\*. to .int. .\\-fpermissive." "bad conv" { target *-*-* } .-1 } +int2 z[2] = { {u}, + 3,{4} }; +// { dg-error "invalid conversion from .int\\*. to .int. .\\-fpermissive." "bad conv" { target *-*-* } .-2 } + +__UINT8_TYPE__ m222[2][2][2] {0,1,2,3,4,5,6,7}; +__UINT8_TYPE__ c222[2][2][2] { m222[0], m222[1][0], 6,7 }; +// { dg-error "array must be initialized with a brace-enclosed initializer" "array init" { target *-*-* } .-1 } diff --git a/gcc/testsuite/g++.dg/init/array-copy2.C b/gcc/testsuite/g++.dg/init/array-copy2.C new file mode 100644 index 00000000000..7e1ad23592b --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy2.C @@ -0,0 +1,68 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array variable initialization compile tests, -farray-copy enabled +// (c.f. array-copy1.C for compile fail tests) + +// { dg-do compile { target c++11 } } c++11 for uniform init +// { dg-additional-options "-farray-copy" } + +typedef int int2[2]; +int2 u = {11,66}; + +int* p = new int2{u}; + +// Initializations from from rvalue array +int2 g = int2{11,66}; +int2 j ( int2{11,66} ); // takes P0960 paren-init path in c++20 +int2 k = { int2{11,66} }; +int2 l { int2{11,66} }; + +// Initializations from from lvalue array +int2 gc = u; +int2 jc (u); // takes P0960 paren-init path in c++20 +int2 kc = {u}; +int2 lc {u}; + +char str[] = "str"; + +char cpy[] = str; +char cpp[] (str); // takes P0960 paren-init path in c++20 +char cpu[] = {str}; +char cpw[] {str}; + +char cp5[5] = str; +char cp3[3] = str; +// { dg-error "array of type .char .5.. cannot be initialized with an array of type .char .4.." "" { target *-*-* } .-2 } +// { dg-error "array of type .char .3.. cannot be initialized with an array of type .char .4.." "" { target *-*-* } .-2 } + +constexpr char cstr[] = "str"; +constexpr char ccpy[] = cstr; +static_assert( + __builtin_bit_cast(__UINT32_TYPE__, ccpy) + == __builtin_bit_cast(__UINT32_TYPE__, "str") +, "" +); + +constexpr __UINT32_TYPE__ ci[] = {11,66}; +constexpr __UINT32_TYPE__ cc[] = ci; +static_assert( + __builtin_bit_cast(__UINT64_TYPE__, ci) + == __builtin_bit_cast(__UINT64_TYPE__, cc) +, "" +); + +int2 s[2] = { u }; +int2 x[2] = { u + , u }; +int2 y[2] = { 1,2 + , {u} }; +int2 z[2] = { {u} + , 3,{4} }; + +__UINT8_TYPE__ m222[2][2][2] {0,1,2,3,4,5,6,7}; +__UINT8_TYPE__ c222[2][2][2] { m222[0], m222[1][0], 6,7 }; + +int main() { + if (__builtin_bit_cast(__UINT64_TYPE__, m222) + != __builtin_bit_cast(__UINT64_TYPE__, c222)) + __builtin_abort (); +} diff --git a/gcc/testsuite/g++.dg/init/array-copy3.C b/gcc/testsuite/g++.dg/init/array-copy3.C new file mode 100644 index 00000000000..bec78cb8435 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy3.C @@ -0,0 +1,41 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array member initialization nocompile tests - +// should give same errors before and after the array-copy patch. + +// { dg-do compile { target c++11 } } c++11 for uniform init +// + +typedef int int2[2]; + +struct A { int2 a; }; + +A ad { int2{11,66} }; // { dg-error "array must be initialized with a brace-enclosed initializer" } +A ai = { int2{11,66} }; // { dg-error "array must be initialized with a brace-enclosed initializer" } + +struct B { int2 a, b, c, d; }; + +constexpr +B b { + {11,66} + , {b.a} // { dg-error "invalid conversion from .const int\\*. to .int. .\\-fpermissive." } + , (b.b) // { dg-error "array must be initialized with a brace-enclosed initializer" } + , b.c +}; + +struct C { + int2 a, b, c; + C(const int2& r = {11,66}) + : a{r} // { dg-error "invalid conversion from .const int\\*. to .int. .\\-fpermissive." } + , b(a) // { dg-error "array used as initializer" } + , c{b} // { dg-error "invalid conversion from .int\\*. to .int. .\\-fpermissive." } + {} +}; + +// Not a test; a workaround to construct a single array member from array +struct D { + int2 d; + constexpr D(const int2& r = {}) + : D{__builtin_bit_cast(D,r)} {} +}; +constexpr D d{{11,66}}; +constexpr D e{b.a}; diff --git a/gcc/testsuite/g++.dg/init/array-copy4.C b/gcc/testsuite/g++.dg/init/array-copy4.C new file mode 100644 index 00000000000..8db2852011a --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy4.C @@ -0,0 +1,42 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array member initialization compile tests - +// (c.f. array-copy3.C for compile fail tests) + +// { dg-do compile { target c++11 } } c++11 for uniform init +// { dg-additional-options "-farray-copy" } + +typedef int int2[2]; + +struct A { int2 a; }; + +A ad { int2{11,66} }; +A ai = { int2{11,66} }; + +struct B { int2 a, b, c, d; }; + +constexpr +B b { + {11,66} + , {b.a} + , (b.b) + , b.c +}; + +struct C { + int2 a, b, c; + C(const int2& r = {11,66}) + : a{r} + , b(a) + , c{b} + {} +}; + +template +constexpr int equal(T const& a, T const& b) { + using bytes = unsigned char[sizeof(T)]; + return __builtin_memcmp( + __builtin_bit_cast(bytes,a), + __builtin_bit_cast(bytes,b), + sizeof(T)) == 0; +} +static_assert( equal(b, B{{11,66},{11,66},{11,66},{11,66}}), ""); diff --git a/gcc/testsuite/g++.dg/init/array-copy5.C b/gcc/testsuite/g++.dg/init/array-copy5.C new file mode 100644 index 00000000000..a3b6c275f2b --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy5.C @@ -0,0 +1,36 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array member initialization nocompile tests, nsdmi and designated init +// should give same errors before and after the array-copy patch. + +// { dg-do compile { target c++14 } } c++14 for aggregate with member inits +// { dg-options "" } +// + +typedef int int2[2]; + +struct A { int2 a = int2{11,66}; }; // { dg-error "array must be initialized with a brace-enclosed initializer" } + +constexpr +A a { .a = int2{11,66} }; // { dg-error "array must be initialized with a brace-enclosed initializer" } +A y = { .a{int2{11,66}} }; // { dg-error "taking address of temporary array" } + +struct B { + int2 a = {11,66}; + int2 b = a; // { dg-error "array must be initialized with a brace-enclosed initializer" } + int2 c = {b}; // { dg-error "invalid conversion from .int\\*. to .int. .\\-fpermissive." } + int2 d {c}; // { dg-error "invalid conversion from .int\\*. to .int. .\\-fpermissive." } +}; + +constexpr +B b { + {11,66} + , {b.a} // { dg-error "invalid conversion from .const int\\*. to .int. .\\-fpermissive." } + , (b.b) // { dg-error "array must be initialized with a brace-enclosed initializer" } + , b.c +}; + +B bd { .a{11,66}, .b = bd.a, .c {bd.b}, .d = {bd.c} }; // { dg-error "array must be initialized with a brace-enclosed initializer" } + +struct D : A { + B b {.a{11,66}, .b = b.a, .c {b.b}, .d = {b.c}}; // { dg-error "array must be initialized with a brace-enclosed initializer" } +}; diff --git a/gcc/testsuite/g++.dg/init/array-copy6.C b/gcc/testsuite/g++.dg/init/array-copy6.C new file mode 100644 index 00000000000..09b7478e07f --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy6.C @@ -0,0 +1,51 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array member initialization compile tests, nsdmi and designated init +// (c.f. array-copy5.C for compile fail tests) + +// { dg-do compile { target c++20 } } +// +// { dg-additional-options "-farray-copy" } + +typedef int int2[2]; + +struct A { int2 a = int2{11,66}; }; + +constexpr +A a { .a = int2{11,66} }; +A y = { .a{int2{11,66}} }; + +struct B { + int2 a = {11,66}; + int2 b = a; + int2 c = {b}; + int2 d {c}; +}; + +constexpr +B b { + {11,66} + , {b.a} + , (b.b) + , b.c +}; + +B bd { .a{11,66}, .b = bd.a, .c {bd.b}, .d = {bd.c} }; + +struct D : A { + B b {.a{11,66}, .b = b.a, .c {b.b}, .d = {b.c}}; +}; + +constexpr +D d; + +template +constexpr int equal(T const& a, T const& b) { + using bytes = unsigned char[sizeof(T)]; + return __builtin_memcmp( + __builtin_bit_cast(bytes,a), + __builtin_bit_cast(bytes,b), + sizeof(T)) == 0; +} +static_assert( equal(b, B{}), ""); +static_assert( equal(d, D{}), ""); +static_assert( equal(d, D{a,b}), ""); From patchwork Mon Nov 22 02:51:14 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: will wray X-Patchwork-Id: 47985 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4ACE03858430 for ; Mon, 22 Nov 2021 02:55:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4ACE03858430 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1637549703; bh=/9NWDlm+2JczvIVoPB9vhjOT2k/LBhutzyel4vC37dY=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=JKz8kmkB9VcerV6krtd95qvSnfFpIx8W+s2hnMFQzqDoLveJeX8gIjFuSgZ7By6W4 vTYGAmM9yJKrDLkU33pPSYwWJKlvhye/X9SN0E+YWCJzBoiRK7hX6ASxDST0BCQ+zB AuKMjbUSKglqDSeI3j/2lDiOKdgOBnkYDyqOXUaU= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-qt1-x82f.google.com (mail-qt1-x82f.google.com [IPv6:2607:f8b0:4864:20::82f]) by sourceware.org (Postfix) with ESMTPS id 4EAAD3858411 for ; Mon, 22 Nov 2021 02:51:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 4EAAD3858411 Received: by mail-qt1-x82f.google.com with SMTP id l8so15289679qtk.6 for ; Sun, 21 Nov 2021 18:51:51 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=/9NWDlm+2JczvIVoPB9vhjOT2k/LBhutzyel4vC37dY=; b=cwgoIR1WaEQOgC+BEmh+EE9zIulCSqfsdmtcujb2M7kYmudbxNcYo4JtY/K29pIr7Z YBnC4TKBT9NZ95778MVtN5tpK2RttWsguTWViPBGcwweT0qxnLrLcsxxif3wUx2w230T +l7639jzU00Yp/WFIaMRwxntwx2yu1Y8iyeuOG4SuWtpbdZQS7KQsWzqHWvjE9tfO752 KA1Y/mLz3IDsLagGz4FuAO5XLh69UDxqm5QsYARA/9O7OHdZ6TgsO5pIStuf2uGnwyS0 YxlGKKuP3LXQMP47UPDH3IEvjKPLd7cCNEwKcvorskLAO6auSFhFuL1JEqtPEWGgjVHR Rucw== X-Gm-Message-State: AOAM5318XWnw2q3ZONHIVT3hJHGLio/fUBjpHUnwoZp/6XCFUV6p6S9y UYdmmdLdmWui0nc8WY25aLjQR7cJBKw= X-Google-Smtp-Source: ABdhPJwIeviwvwiLuzza92qkJFflhFqaKYJstGqsmQ5YWicZEQfcztfKzGiEZSLzTCXX23Wi8nEJPw== X-Received: by 2002:ac8:5fc2:: with SMTP id k2mr27739678qta.310.1637549510288; Sun, 21 Nov 2021 18:51:50 -0800 (PST) Received: from localhost.localdomain (bras-base-sttnpq8102w-grc-16-142-115-13-133.dsl.bell.ca. [142.115.13.133]) by smtp.googlemail.com with ESMTPSA id t35sm3947822qtc.83.2021.11.21.18.51.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 21 Nov 2021 18:51:49 -0800 (PST) To: gcc-patches@gcc.gnu.org Subject: [PATCH 3/3] c++: P1997 array-copy extensions: Assignment, return, etc. [PR103238] Date: Sun, 21 Nov 2021 21:51:14 -0500 Message-Id: <20211122025114.3167997-4-wjwray@gmail.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211122025114.3167997-1-wjwray@gmail.com> References: <20211122025114.3167997-1-wjwray@gmail.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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-Patchwork-Original-From: Will Wray via Gcc-patches From: will wray Reply-To: Will Wray Cc: Will Wray Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This second patch completes the work of the first 'array-copy' patch to provide first-cut implementations of all P1997 features. It adds: * Assignments to arrays from array values, a = b; * Placeholder auto in array declarations, auto cp[] = a; * Array as a return type from functions WIP, auto f() -> T[N]; * Parsing of array pseudo-destructors a.~A() (only parsing for now, untested) Assignments a = b were easily allowed by changing branch conditions. Assignments a = {e...} were trickier (a case not mentioned in P1997): int a[16]; a = {0,1,1,2}; a = {}; // assignments from init-lists The semantics is the same as for struct aggregates: (1) Aggregate initialization of an rhs array of the lhs type (so trailing elements with no initializer are value initialized) (2) Copy-initialization of the lhs from the rhs. The special case of an optionally-braced array value is allowed so that a = b and a = {b} are generally equivalent for same type arrays a and b. However, the now special-special case of assignment from a braced string- literal currently only supports exact-match (same as for other arrays): char a[4]; a={"c++"} /* OK */; a={"c"} /* FAILs but should work */; Array return from function is work in progress. The tests show what works. I'm stuck in unfamiliar territory so it's best to submit what I have to be reviewed for hints on how to progress. Please try the patch; play, stress it, and report the FAILS. PR c++/103238 gcc/c/ChangeLog: * c-decl.c (grokdeclarator): Don't complain of array returns. gcc/cp/ChangeLog: * call.c (can_convert_array): Extend to include array inits. (standard_conversion): No decay for same-type array. Call build_conv. (implicit_conversion_1): Call reshape_init for arrays too. * decl.c (grokdeclarator): Don't complain of array returns. * parser.c (cp_parser_postfix_dot_deref_expression): parse array ~A(). * pt.c (tsubst_function_type): Array type return is not a failure. (do_auto_deduction): Placeholder auto deduction of array element type. * tree.c (lvalue_kind): clk_class should include array (I think?). * typeck.c (cp_build_modify_expr): Call reshape init to strip optional braces. Allow NOP_EXPR for array assignment. (convert_for_assignment): New if-block for same-type array convert, strips optional braces, but rejects STRING_CST rhs shorter than lhs. gcc/testsuite/ChangeLog: * g++.dg/init/array-copy10.C: New test. auto[] deduce 'after' PASSes * g++.dg/init/array-copy11.C: New test. Array return 'before' XFAILs * g++.dg/init/array-copy12.C: New test. Array return 'after' PASSes * g++.dg/init/array-copy7.C: New test. Array assign 'before' XFAILs * g++.dg/init/array-copy8.C: New test. Array assign 'after' PASSes * g++.dg/init/array-copy9.C: New test. auto[] deduce 'before' XFAILs --- gcc/c/c-decl.c | 2 +- gcc/cp/call.c | 43 +++++++++++------ gcc/cp/decl.c | 2 +- gcc/cp/parser.c | 4 +- gcc/cp/pt.c | 13 +++++- gcc/cp/tree.c | 3 +- gcc/cp/typeck.c | 26 +++++++++-- gcc/testsuite/g++.dg/init/array-copy10.C | 57 +++++++++++++++++++++++ gcc/testsuite/g++.dg/init/array-copy11.C | 13 ++++++ gcc/testsuite/g++.dg/init/array-copy12.C | 79 ++++++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/init/array-copy7.C | 40 ++++++++++++++++ gcc/testsuite/g++.dg/init/array-copy8.C | 56 ++++++++++++++++++++++ gcc/testsuite/g++.dg/init/array-copy9.C | 57 +++++++++++++++++++++++ 13 files changed, 372 insertions(+), 23 deletions(-) diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 3e28a038095..031c43d189f 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -7055,7 +7055,7 @@ grokdeclarator (const struct c_declarator *declarator, "returning a function"); type = integer_type_node; } - if (TREE_CODE (type) == ARRAY_TYPE) + if (TREE_CODE (type) == ARRAY_TYPE && !flag_array_copy) { if (name) error_at (loc, "%qE declared as function returning an array", diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 4ee21c7bdbd..c73fb73d86e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -908,29 +908,34 @@ static bool can_convert_array (tree atype, tree from, int flags, tsubst_flags_t complain) { tree elttype = TREE_TYPE (atype); - unsigned i; if (TREE_CODE (from) == CONSTRUCTOR) { - for (i = 0; i < CONSTRUCTOR_NELTS (from); ++i) + for (auto&& ce : CONSTRUCTOR_ELTS (from)) { - tree val = CONSTRUCTOR_ELT (from, i)->value; - bool ok; - if (TREE_CODE (elttype) == ARRAY_TYPE) - ok = can_convert_array (elttype, val, flags, complain); - else - ok = can_convert_arg (elttype, TREE_TYPE (val), val, flags, - complain); - if (!ok) + tree val = tree_strip_any_location_wrapper (ce.value); + if ((TREE_CODE (val) == STRING_CST + && !can_convert_array (elttype, val, flags, complain)) + || (TREE_CODE (elttype) == ARRAY_TYPE + ? !can_convert_array (elttype, val, flags, complain) + : !can_convert_arg (elttype, TREE_TYPE (val), val, flags, + complain))) return false; } return true; } + from = tree_strip_any_location_wrapper (from); + if (char_type_p (TYPE_MAIN_VARIANT (elttype)) - && TREE_CODE (tree_strip_any_location_wrapper (from)) == STRING_CST) + && TREE_CODE (from) == STRING_CST) return array_string_literal_compatible_p (atype, from); + if (flag_array_copy + && TREE_CODE (from) == ARRAY_TYPE) + return same_type_ignoring_top_level_qualifiers_p (atype, + tree_strip_any_location_wrapper (from)); + /* No other valid way to aggregate initialize an array. */ return false; } @@ -1241,7 +1246,10 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, tcode = TREE_CODE (to); conv = build_identity_conv (from, expr); - if (fcode == FUNCTION_TYPE || fcode == ARRAY_TYPE) + if (fcode == FUNCTION_TYPE + || (fcode == ARRAY_TYPE + && !(flag_array_copy && tcode == ARRAY_TYPE + && same_type_ignoring_top_level_qualifiers_p (to, from)))) { from = type_decays_to (from); fcode = TREE_CODE (from); @@ -1538,6 +1546,10 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p, else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE && vector_types_convertible_p (from, to, false)) return build_conv (ck_std, to, conv); + else if (flag_array_copy + && fcode == ARRAY_TYPE && tcode == ARRAY_TYPE + && same_type_ignoring_top_level_qualifiers_p (from, to)) + return build_conv (ck_std, to, conv); else if (MAYBE_CLASS_TYPE_P (to) && MAYBE_CLASS_TYPE_P (from) && is_properly_derived_from (from, to)) { @@ -2015,9 +2027,10 @@ implicit_conversion_1 (tree to, tree from, tree expr, bool c_cast_p, /* Call reshape_init early to remove redundant braces. */ if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr) - && CLASS_TYPE_P (to) - && COMPLETE_TYPE_P (complete_type (to)) - && !CLASSTYPE_NON_AGGREGATE (to)) + && ((CLASS_TYPE_P (to) + && COMPLETE_TYPE_P (complete_type (to)) + && !CLASSTYPE_NON_AGGREGATE (to)) + || (flag_array_copy && TREE_CODE (to) == ARRAY_TYPE))) { expr = reshape_init (to, expr, complain); if (expr == error_mark_node) diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 1010fa2c53f..872403b1ac1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -12719,7 +12719,7 @@ grokdeclarator (const cp_declarator *declarator, "a function", name); return error_mark_node; } - if (TREE_CODE (type) == ARRAY_TYPE) + if (TREE_CODE (type) == ARRAY_TYPE && !flag_array_copy) { error_at (typespec_loc, "%qs declared as function returning " "an array", name); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 65f0f112011..5dd6126dc50 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -8120,7 +8120,9 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser, we must be looking at a pseudo-destructor-name. If POSTFIX_EXPRESSION is type dependent, it can be pseudo-destructor-name or something else. Try to parse it as pseudo-destructor-name first. */ - if ((scope && SCALAR_TYPE_P (scope)) || dependent_p) + if ((scope && (SCALAR_TYPE_P (scope) + || (flag_array_copy && TREE_CODE (scope) == ARRAY_TYPE))) + || dependent_p) /* TODO: P1997 array pseudo-destructor. */ { tree s; tree type; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b27eea33272..66ed90699cd 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -15152,7 +15152,7 @@ tsubst_function_type (tree t, return error_mark_node; /* DR 486 clarifies that creation of a function type with an invalid return type is a deduction failure. */ - if (TREE_CODE (return_type) == ARRAY_TYPE + if ((TREE_CODE (return_type) == ARRAY_TYPE && !flag_array_copy) || TREE_CODE (return_type) == FUNCTION_TYPE) { if (complain & tf_error) @@ -29812,6 +29812,17 @@ do_auto_deduction (tree type, tree init, tree auto_node, targs = make_tree_vec (1); TREE_VEC_ELT (targs, 0) = TREE_TYPE (init); } + else if (flag_array_copy + && (context == adc_variable_type + || context == adc_return_type) + && auto_node == TREE_TYPE (type) + && !TYPE_REF_P (type) + && init != error_mark_node + && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) + { + targs = make_tree_vec (1); + TREE_VEC_ELT (targs, 0) = TREE_TYPE (TREE_TYPE (init)); + } else if (AUTO_IS_DECLTYPE (auto_node)) { tree stripped_init = tree_strip_any_location_wrapper (init); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 32ddf835a91..e10c574de94 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -280,7 +280,8 @@ lvalue_kind (const_tree ref) case CALL_EXPR: /* We can see calls outside of TARGET_EXPR in templates. */ - if (CLASS_TYPE_P (TREE_TYPE (ref))) + if (CLASS_TYPE_P (TREE_TYPE (ref)) + || TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE) return clk_class; return clk_none; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 8e96a925186..e1a9446fd0f 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -9105,9 +9105,11 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, { int from_array; + if (flag_array_copy && BRACE_ENCLOSED_INITIALIZER_P (newrhs)) + newrhs = reshape_init (lhstype, newrhs, complain); if (BRACE_ENCLOSED_INITIALIZER_P (newrhs)) { - if (modifycode != INIT_EXPR) + if (modifycode != INIT_EXPR && !flag_array_copy) { if (complain & tf_error) error_at (loc, @@ -9127,7 +9129,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode, else if ((TREE_CODE (tree_strip_any_location_wrapper (newrhs)) == STRING_CST) && char_type_p (TREE_TYPE (TYPE_MAIN_VARIANT (lhstype))) - && modifycode == INIT_EXPR) + && (modifycode == INIT_EXPR + || (modifycode == NOP_EXPR && flag_array_copy))) { newrhs = digest_init (lhstype, newrhs, complain); if (newrhs == error_mark_node) @@ -9682,7 +9685,24 @@ convert_for_assignment (tree type, tree rhs, rhs = mark_rvalue_use (rhs); return convert (type, rhs); } - + /* Deal with array-valued rhs of same type as lhs 'type', optionally braced. + This includes STRING_CST, but only of same type - i.e. same size; + TODO: P1997 convert STRING_CST shorter than 'type' to full size. */ + if (flag_array_copy && TREE_CODE (type) == ARRAY_TYPE) + { + if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (rhs))) + { + rhs = mark_rvalue_use (rhs); + return convert (type, rhs); + } + if (BRACE_ENCLOSED_INITIALIZER_P (rhs) + && CONSTRUCTOR_NELTS (rhs) == 1 + && same_type_ignoring_top_level_qualifiers_p (type, + TREE_TYPE (tree_strip_any_location_wrapper ( + CONSTRUCTOR_ELT (rhs, 0)->value)))) + return convert (type, mark_rvalue_use ( + CONSTRUCTOR_ELT (rhs, 0)->value)); + } if (rhs == error_mark_node || rhstype == error_mark_node) return error_mark_node; if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node) diff --git a/gcc/testsuite/g++.dg/init/array-copy10.C b/gcc/testsuite/g++.dg/init/array-copy10.C new file mode 100644 index 00000000000..5fc2df727fa --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy10.C @@ -0,0 +1,57 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array auto placeholder element deduction compile tests +// (c.f. array-copy9.C for compile fail tests) + +// { dg-do compile { target c++11 } } +// { dg-additional-options "-farray-copy" } + +template struct same{ enum:bool{v=false}; }; +template struct same{ enum:bool{v=true}; }; +template +struct same{ enum:bool{v = same::v && same::v}; }; +template +constexpr bool all_same_t(T const&...){return same::v;} + +typedef int int2[2]; +int2 a {11,66}; + +auto er[2] {1,2}; +// { dg-error "direct-list-initialization of .auto. requires exactly one element .\\-fpermissive." "" { target *-*-* } .-1 } +// { dg-error "deducing from brace-enclosed initializer list requires" "" { target *-*-* } .-2 } +auto il[2] = {1,2}; +// { dg-error "deducing from brace-enclosed initializer list requires" "" { target *-*-* } .-1 } +auto um[2] = {a}; +// { dg-error "deducing from brace-enclosed initializer list requires" "" { target *-*-* } .-1 } + +// Initializations from from rvalue array +auto g[2] = int2{11,66}; +auto j[2] ( int2{11,66} ); // P0960 +auto l[2] { int2{11,66} }; +// auto + size deduction : +auto m[] = int2{11,66}; +auto n[] ( int2{11,66} ); // P0960 +auto p[] { int2{11,66} }; + +static_assert( all_same_t(a,g,j,l,m,n,p), ""); + +auto str[] = "str"; + +auto cpy[4] = str; +auto cpp[4] (str); // P0960 +auto cpw[4] {str}; +// auto + size deduction : +auto cpu[] = str; +auto cpv[] (str); // P0960 +auto cpx[] {str}; + +static_assert( all_same_t(str,cpy,cpp,cpw,cpu,cpv,cpx), ""); + +auto const& ref = "str"; + +auto rpy[4] = ref; +auto rpp[4] (ref); // P0960 +auto rpw[4] {ref}; +// auto + size deduction : +auto rpu[] = ref; +auto rpv[] (ref); // P0960 +auto rpx[] {ref}; diff --git a/gcc/testsuite/g++.dg/init/array-copy11.C b/gcc/testsuite/g++.dg/init/array-copy11.C new file mode 100644 index 00000000000..ac4d0c0dcb8 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy11.C @@ -0,0 +1,13 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array function return nocompile tests - +// should give same errors before and after the array-copy patch. + +// { dg-do compile { target c++11 } } +// + +constexpr auto a() -> char[2] {return "a";} // { dg-error "declared as function returning an array" } + +constexpr char char2(char,char)[2]; // { dg-error "declared as function returning an array" } +constexpr auto char2(char,char) -> char[2]; // { dg-error "declared as function returning an array" } + +constexpr char char2(char a,char b)[2] {return{a,b};} // { dg-error "declared as function returning an array" } diff --git a/gcc/testsuite/g++.dg/init/array-copy12.C b/gcc/testsuite/g++.dg/init/array-copy12.C new file mode 100644 index 00000000000..f6588b002ab --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy12.C @@ -0,0 +1,79 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array function return compile tests - +// (c.f. array-copy11.C for compile fail tests) + +// { dg-do run { target c++11 } } +// { dg-additional-options "-farray-copy" } + +constexpr bool equal(const char(&a)[2] + ,const char(&b)[2]) +{ + return a[0]==b[0] + && a[1]==b[1]; +} + +template +using charN = char[N]; +using chars = char[]; + +// Note a() return is const qualified, else constexpr test below fails FIXME +constexpr auto a() -> const char[2] {return "a";} +constexpr auto b() -> char[2] {return{'b'};} // init-list not folding causes ICE +constexpr auto c() -> char[2] {return{"c"};} +constexpr auto d() -> char[2] {return chars{"d"};} + +// Note the lambda return is not const qualified yet works constexpr below +auto e = []() -> char[2] {char ce[2]{'e'}; return ce;}; + +static_assert( equal(a(),"a"), ""); +//static_assert( equal(b(),"b"), ""); // ICE gcc assert +static_assert( equal(c(),"c"), ""); +static_assert( equal(d(),"d"), ""); +static_assert( equal(e(),"e"), ""); +// { dg-error "non-constant condition for static assertion" "" { target c++14_down } .-1 } +// { dg-error "call to non-.constexpr. function ..lambda" "" { target c++14_down } .-2 } + +constexpr auto bc[] = b(); +static_assert( equal(bc,"b"), ""); + +constexpr char char2(char,char)[2]; +constexpr auto char2(char,char) -> char[2]; // same type redeclaration +constexpr char char2(char a,char b)[2] {return{a,b};} // .. definition + +//static_assert( equal(char2('a','b'),{'a','b'}), ""); // ICE gcc assert + +constexpr charN<2> char2cp(const charN<2>& a) {return a;} +constexpr charN<2> char2cb(const charN<2>& a) {return{a};} + +constexpr char c2a[2] = char2('a',0); +constexpr char cpa[] = char2cp("a"); +constexpr auto cpb[] = char2cb("a"); + +static_assert( equal( c2a, "a") ,""); +static_assert( equal( cpa, "a") ,""); +static_assert( equal( cpb, "a") ,""); + +constexpr auto f8(const float(&a)[8]) -> float[8] {return{};} + +template +constexpr int atoi()[N] { return {__integer_pack(N)...}; } + +template +constexpr int ind(const T (&r)[N], int i) { return r[i]; } + +constexpr auto atoi6[] = atoi<6>(); + +static_assert(ind(atoi6,4) == 4, ""); + +// FAILs below, can't pass array return to a reference argument + +//static_assert(ind(atoi<6>(),4) == 4, ""); // ICE + +int main() { + if (!equal(a(),"a")) __builtin_abort(); + // if (!equal(b(),"b")) __builtin_abort(); // ICE + if (!equal(c(),"c")) __builtin_abort(); + if (!equal(d(),"d")) __builtin_abort(); + if (!equal(e(),"e")) __builtin_abort(); + // if (ind(atoi<6>(),4) != 4) __builtin_abort(); // ICE +} diff --git a/gcc/testsuite/g++.dg/init/array-copy7.C b/gcc/testsuite/g++.dg/init/array-copy7.C new file mode 100644 index 00000000000..9cee097d560 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy7.C @@ -0,0 +1,40 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array assignment nocompile tests +// should give same errors before and after the array-copy patch. + +// { dg-do compile { target c++11 } } +// + +int aggr_ass() +{ + int a[2] = {11,66}, b[2] = {}; + + b = a; // { dg-error "invalid array assignment" } + b = {a}; // { dg-error "assigning to an array from an initializer list" } + b = {11,66}; // { dg-error "assigning to an array from an initializer list" } + b = {}; // { dg-error "assigning to an array from an initializer list" } + a = {11}; // { dg-error "assigning to an array from an initializer list" } + return a[1] + b[0] + b[1]; +} + +char clr() +{ + char abc[] = {'a','b','c'}; + abc = {""}; // { dg-error "assigning to an array from an initializer list" } + return abc[0] + abc[1] + abc[2]; +} + +struct A +{ + int a[2]; + A(const int(&b)[2]) { a = b; } // { dg-error "invalid array assignment" } +}; + +char strtab[4][8] = {"hello","world"}; + +void str_ass() +{ + strtab = {"Hello","World"}; // { dg-error "assigning to an array from an initializer list" } + strtab[0] = {"hi"}; // { dg-error "assigning to an array from an initializer list" } + strtab[1] = strtab[0]; // { dg-error "invalid array assignment" } +} diff --git a/gcc/testsuite/g++.dg/init/array-copy8.C b/gcc/testsuite/g++.dg/init/array-copy8.C new file mode 100644 index 00000000000..582f35f4340 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy8.C @@ -0,0 +1,56 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array assignment compile tests - +// (c.f. array-copy7.C for compile fail tests) + +// { dg-do run { target c++11 } } +// { dg-additional-options "-farray-copy" } + +int aggr_ass() +{ + int a[2] = {11,66}, b[2] = {}; + + b = a; + b = {a}; + b = {11,66}; + b = {}; + a = {11}; + return a[1] + b[0] + b[1]; +} + +char clr() +{ + char abc[] = {'a','b','c'}; + abc = {""}; + return abc[0] + abc[1] + abc[2]; +} + +struct A +{ + int a[2]; + A(const int(&b)[2]) { a = b; } +}; + +char strtab[4][8] = {"hello","world"}; + +void str_ass() +{ + strtab = {"Hello","World"}; + strtab[0] = {"hi"}; + strtab[1] = strtab[0]; +} + +int main() +{ + char hi[8] = "hi"; + str_ass(); + if (__builtin_memcmp(strtab[0],hi,8) != 0 + || __builtin_memcmp(strtab[1],hi,8) != 0) + __builtin_abort(); + + if (aggr_ass() || clr()) + __builtin_abort(); + + A a({11,66}); + if (a.a[0] != 11 || a.a[1] != 66) + __builtin_abort(); +} diff --git a/gcc/testsuite/g++.dg/init/array-copy9.C b/gcc/testsuite/g++.dg/init/array-copy9.C new file mode 100644 index 00000000000..7bbc615a204 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array-copy9.C @@ -0,0 +1,57 @@ +// PR c++/103238 (array-copy extensions for P1997) +// Array auto placeholder element deduction nocompile tests +// should give same errors before and after the array-copy patch. + +// { dg-do compile { target c++11 } } +// + +template struct same{ enum:bool{v=false}; }; +template struct same{ enum:bool{v=true}; }; +template +struct same{ enum:bool{v = same::v && same::v}; }; +template +constexpr bool all_same_t(T const&...){return same::v;} + +typedef int int2[2]; +int2 a {11,66}; + +auto er[2] {1,2}; +// { dg-error "direct-list-initialization of .auto. requires exactly one element .\\-fpermissive." "" { target *-*-* } .-1 } +// { dg-error "deducing from brace-enclosed initializer list requires" "" { target *-*-* } .-2 } +auto il[2] = {1,2}; +// { dg-error "deducing from brace-enclosed initializer list requires" "" { target *-*-* } .-1 } +auto um[2] = {a}; +// { dg-error "deducing from brace-enclosed initializer list requires" "" { target *-*-* } .-1 } + +// Initializations from from rvalue array +auto g[2] = int2{11,66}; // { dg-error "unable to deduce" } +auto j[2] ( int2{11,66} ); // { dg-error "unable to deduce" } +auto l[2] { int2{11,66} }; // { dg-error "unable to deduce" } +// auto + size deduction : +auto m[] = int2{11,66}; // { dg-error "unable to deduce" } +auto n[] ( int2{11,66} ); // { dg-error "unable to deduce" } +auto p[] { int2{11,66} }; // { dg-error "unable to deduce" } + +static_assert( all_same_t(a,g,j,l,m,n,p), ""); + +auto stp[] = "str"; // { dg-error "unable to deduce" } +char str[] = "str"; +auto cpy[4] = str; // { dg-error "unable to deduce" } +auto cpp[4] (str); // { dg-error "unable to deduce" } +auto cpw[4] {str}; // { dg-error "unable to deduce" } +// auto + size deduction : +auto cpu[] = str; // { dg-error "unable to deduce" } +auto cpv[] (str); // { dg-error "unable to deduce" } +auto cpx[] {str}; // { dg-error "unable to deduce" } + +static_assert( all_same_t(str,cpy,cpp,cpw,cpu,cpv,cpx), ""); + +auto const& ref = "str"; + +auto rpy[4] = ref; // { dg-error "unable to deduce" } +auto rpp[4] (ref); // { dg-error "unable to deduce" } +auto rpw[4] {ref}; // { dg-error "unable to deduce" } +// auto + size deduction : +auto rpu[] = ref; // { dg-error "unable to deduce" } +auto rpv[] (ref); // { dg-error "unable to deduce" } +auto rpx[] {ref}; // { dg-error "unable to deduce" }