[PATCH 3/3] c++: P1997 array-copy extensions: Assignment, return, etc. [PR103238]
Will Wray
wjwray@gmail.com
Mon Nov 22 02:51:14 GMT 2021
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 <typename...> struct same{ enum:bool{v=false}; };
+template <typename T> struct same<T,T>{ enum:bool{v=true}; };
+template <typename T, typename X, typename...Y>
+struct same<T,X,Y...>{ enum:bool{v = same<T,X>::v && same<T,Y...>::v}; };
+template<typename...T>
+constexpr bool all_same_t(T const&...){return same<T...>::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<int N>
+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 <int N>
+constexpr int atoi()[N] { return {__integer_pack(N)...}; }
+
+template <typename T, int N>
+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 <typename...> struct same{ enum:bool{v=false}; };
+template <typename T> struct same<T,T>{ enum:bool{v=true}; };
+template <typename T, typename X, typename...Y>
+struct same<T,X,Y...>{ enum:bool{v = same<T,X>::v && same<T,Y...>::v}; };
+template<typename...T>
+constexpr bool all_same_t(T const&...){return same<T...>::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" }
--
2.31.1
More information about the Gcc-patches
mailing list