Testcase added for this.
Bootstrapped/regtested on x86_64-pc-linux-gnu.
gcc/cp/ChangeLog:
PR c++/90926
* call.c (can_convert_array): Extend to handle all valid aggregate
initializers of an array; including by string literals, not just by
brace-init-list.
(build_aggr_conv): Call can_convert_array more often, not just in
brace-init-list case.
* g++.dg/cpp1y/nsdmi-aggr12.C: New test.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c index
c2d62e582bf..e4ba31f3f2b 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -887,28 +887,41 @@ strip_standard_conversion (conversion *conv)
return conv;
}
-/* Subroutine of build_aggr_conv: check whether CTOR, a braced-init-list,
- is a valid aggregate initializer for array type ATYPE. */
+/* Subroutine of build_aggr_conv: check whether FROM is a valid aggregate
+ initializer for array type ATYPE. */
static bool
-can_convert_array (tree atype, tree ctor, int flags, tsubst_flags_t
complain)
+can_convert_array (tree atype, tree from, int flags, tsubst_flags_t
+complain)
{
- unsigned i;
tree elttype = TREE_TYPE (atype);
- for (i = 0; i < CONSTRUCTOR_NELTS (ctor); ++i)
+ unsigned i;
+
+ if (TREE_CODE (from) == CONSTRUCTOR)
{
- tree val = CONSTRUCTOR_ELT (ctor, i)->value;
- bool ok;
- if (TREE_CODE (elttype) == ARRAY_TYPE
- && TREE_CODE (val) == CONSTRUCTOR)
- ok = can_convert_array (elttype, val, flags, complain);
- else
- ok = can_convert_arg (elttype, TREE_TYPE (val), val, flags,
- complain);
- if (!ok)
- return false;
+ for (i = 0; i < CONSTRUCTOR_NELTS (from); ++i)
+ {
+ 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)
+ return false;
+ }
+ return true;
}
- return true;
+
+ if ( char_type_p (TYPE_MAIN_VARIANT (elttype))
+ && TREE_CODE (tree_strip_any_location_wrapper (from)) == STRING_CST)
+ /* Defer the other necessary checks (compatibility of character types and
+ whether string literal will fit) until the conversion actually takes
+ place. */
+ return true;
+
+ /* No other valid way to aggregate initialize an array. */ return
+ false;
}
/* Helper for build_aggr_conv. Return true if FIELD is in PSET, or
if @@ -965,8 +978,7 @@ build_aggr_conv (tree type, tree ctor, int flags,
tsubst_flags_t complain)
tree ftype = TREE_TYPE (idx);
bool ok;
- if (TREE_CODE (ftype) == ARRAY_TYPE
- && TREE_CODE (val) == CONSTRUCTOR)
+ if (TREE_CODE (ftype) == ARRAY_TYPE)
ok = can_convert_array (ftype, val, flags, complain);
else
ok = can_convert_arg (ftype, TREE_TYPE (val), val,
flags, @@ -1013,9 +1025,8 @@ build_aggr_conv (tree type, tree ctor, int flags,
tsubst_flags_t complain)
val = empty_ctor;
}
- if (TREE_CODE (ftype) == ARRAY_TYPE
- && TREE_CODE (val) == CONSTRUCTOR)
- ok = can_convert_array (ftype, val, flags, complain);
+ if (TREE_CODE (ftype) == ARRAY_TYPE)
+ ok = can_convert_array (ftype, val, flags, complain);
else
ok = can_convert_arg (ftype, TREE_TYPE (val), val, flags,
complain); diff --git
a/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr12.C
b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr12.C
new file mode 100644
index 00000000000..ce8c95e8aca
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr12.C
@@ -0,0 +1,21 @@
+// PR c++/90926
+// { dg-do run { target c++14 } }
+
+struct A
+{
+ char str[4] = "foo";
+ char str_array[2][4] = {"bar", "baz"}; };
+
+int
+main ()
+{
+ A a;
+ a.str[0] = 'g';
+ a.str_array[0][0] = 'g';
+ a = {};
+ if (__builtin_strcmp (a.str, "foo") != 0)
+ __builtin_abort();
+ if (__builtin_strcmp (a.str_array[0], "bar") != 0)
+ __builtin_abort();
+}