Re: [PATCH v2] c++: fix string literal member initializer bug [PR90926]
On 2/3/21 6:31 AM, Tom Greenslade (thomgree) via Gcc-patches wrote: Update of https://gcc.gnu.org/pipermail/gcc-patches/2020-December/562259.html build_aggr_conv did not correctly handle string literal member initializers. Extended can_convert_array to handle this case. For the additional check of compatibility of character types, factored out code from digest_init_r into a new function. 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. * typeck2.c (character_array_from_string_literal): New function. (digest_init_r): call character_array_from_string_literal * cp-tree.h: (character_array_from_string_literal): Declare. * g++.dg/cpp1y/nsdmi-aggr12.C: New test. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 87a7af12796..b917c67204f 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -895,28 +895,40 @@ 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) +{ + return character_array_from_string_literal(atype, from); +} We generally don't wrap a single statement in { }. And you need a space before the (. + + /* 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 @@ -973,8 +985,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, @@ -1021,9 +1032,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/cp/cp-tree.h b/gcc/cp/cp-tree.h index f31319904eb..8dfc581 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7946,6 +7946,7 @@ extern tree split_nonconstant_init(tree, tree); extern bool check_narrowing (tree, tree, tsubst_flags_t, bool = false); extern bool ordinary_char_type_p (tree); +extern bool character_array_from_string_literal (tree, tree); extern tree digest_init (tree, tree, tsubst_flags_t); extern tree digest_init_flags (tree, tree, int, tsubst_flags_t); extern tree digest_nsdmi_init (tree, tree, tsubst_flags_t); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index
[PATCH v2] c++: fix string literal member initializer bug [PR90926]
Update of https://gcc.gnu.org/pipermail/gcc-patches/2020-December/562259.html build_aggr_conv did not correctly handle string literal member initializers. Extended can_convert_array to handle this case. For the additional check of compatibility of character types, factored out code from digest_init_r into a new function. 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. * typeck2.c (character_array_from_string_literal): New function. (digest_init_r): call character_array_from_string_literal * cp-tree.h: (character_array_from_string_literal): Declare. * g++.dg/cpp1y/nsdmi-aggr12.C: New test. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 87a7af12796..b917c67204f 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -895,28 +895,40 @@ 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) +{ + return character_array_from_string_literal(atype, from); +} + + /* 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 @@ -973,8 +985,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, @@ -1021,9 +1032,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/cp/cp-tree.h b/gcc/cp/cp-tree.h index f31319904eb..8dfc581 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7946,6 +7946,7 @@ extern tree split_nonconstant_init(tree, tree); extern bool check_narrowing(tree, tree, tsubst_flags_t, bool = false); extern bool ordinary_char_type_p (tree); +extern bool character_array_from_string_literal (tree, tree); extern tree digest_init(tree, tree, tsubst_flags_t); extern tree digest_init_flags (tree, tree, int, tsubst_flags_t); extern tree digest_nsdmi_init (tree, tree, tsubst_flags_t); diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 9ba2897390a..8fbabeb46d9 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1003,6 +1003,28 @@ ordinary_char_type_p (tree type) || type == unsigned_char_type_node); } +/* Checks if