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" }