From d839099fb30a8ab216a7c6be7cf1788dee336815 Mon Sep 17 00:00:00 2001 From: law Date: Sun, 2 Sep 2018 15:18:30 +0000 Subject: [PATCH] * c-common.c (braced_list_to_string): Remove eval parameter. Add some more checks. Always create zero-terminated STRING_CST. * c-common.h (braced_list_to_string): Adjust prototype. * c-decl.c (finish_decl): Call braced_list_to_string here ... * c-parser.c (c_parser_declaration_or_fndef): ... instead of here. * decl.c (eval_check_narrowing): Remove. (check_initializer): Move call to braced_list_to_string from here ... * typeck2.c (store_init_value): ... to here. (digest_init_r): Remove handing of signed/unsigned char strings. * c-c++-common/array-init.c: New test. * g++.dg/init/string2.C: Remove xfail. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@264042 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/c-family/ChangeLog | 6 +++ gcc/c-family/c-common.c | 67 +++++++++++++++------------------ gcc/c-family/c-common.h | 2 +- gcc/c/ChangeLog | 5 +++ gcc/c/c-decl.c | 6 +++ gcc/c/c-parser.c | 9 ----- gcc/cp/ChangeLog | 7 ++++ gcc/cp/decl.c | 36 +----------------- gcc/cp/typeck2.c | 9 +++-- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/c-c++-common/array-init.c | 4 ++ gcc/testsuite/g++.dg/init/string2.C | 2 +- 12 files changed, 72 insertions(+), 86 deletions(-) create mode 100644 gcc/testsuite/c-c++-common/array-init.c diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 5440b250469..4129f244cd5 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,9 @@ +2018-09-02 Bernd Edlinger + + * c-common.c (braced_list_to_string): Remove eval parameter. + Add some more checks. Always create zero-terminated STRING_CST. + * c-common.h (braced_list_to_string): Adjust prototype. + 2018-08-27 David Malcolm PR 87091 diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 6a5d99171a0..13ed65cb012 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -8542,39 +8542,28 @@ maybe_add_include_fixit (rich_location *richloc, const char *header, } /* Attempt to convert a braced array initializer list CTOR for array - TYPE into a STRING_CST for convenience and efficiency. When non-null, - use EVAL to attempt to evalue constants (used by C++). Return - the converted string on success or null on failure. */ + TYPE into a STRING_CST for convenience and efficiency. Return + the converted string on success or the original ctor on failure. */ tree -braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree)) +braced_list_to_string (tree type, tree ctor) { - unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor); + if (!tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))) + return ctor; /* If the array has an explicit bound, use it to constrain the size of the string. If it doesn't, be sure to create a string that's as long as implied by the index of the last zero specified via a designator, as in: const char a[] = { [7] = 0 }; */ - unsigned HOST_WIDE_INT maxelts = HOST_WIDE_INT_M1U; - if (tree size = TYPE_SIZE_UNIT (type)) - { - if (tree_fits_uhwi_p (size)) - { - maxelts = tree_to_uhwi (size); - maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type))); + unsigned HOST_WIDE_INT maxelts = tree_to_uhwi (TYPE_SIZE_UNIT (type)); + maxelts /= tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type))); - /* Avoid converting initializers for zero-length arrays. */ - if (!maxelts) - return NULL_TREE; - } - } - else if (!nelts) - /* Avoid handling the undefined/erroneous case of an empty - initializer for an arrays with unspecified bound. */ - return NULL_TREE; + /* Avoid converting initializers for zero-length arrays. */ + if (!maxelts) + return ctor; - tree eltype = TREE_TYPE (type); + unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (ctor); auto_vec str; str.reserve (nelts + 1); @@ -8584,19 +8573,21 @@ braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree)) FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value) { - unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i; + unsigned HOST_WIDE_INT idx = i; + if (index) + { + if (!tree_fits_uhwi_p (index)) + return ctor; + idx = tree_to_uhwi (index); + } /* auto_vec is limited to UINT_MAX elements. */ if (idx > UINT_MAX) - return NULL_TREE; + return ctor; - /* Attempt to evaluate constants. */ - if (eval) - value = eval (eltype, value); - - /* Avoid non-constant initializers. */ + /* Avoid non-constant initializers. */ if (!tree_fits_shwi_p (value)) - return NULL_TREE; + return ctor; /* Skip over embedded nuls except the last one (initializer elements are in ascending order of indices). */ @@ -8604,11 +8595,14 @@ braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree)) if (!val && i + 1 < nelts) continue; + if (idx < str.length()) + return ctor; + /* Bail if the CTOR has a block of more than 256 embedded nuls due to implicitly initialized elements. */ unsigned nchars = (idx - str.length ()) + 1; if (nchars > 256) - return NULL_TREE; + return ctor; if (nchars > 1) { @@ -8616,18 +8610,17 @@ braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree)) str.quick_grow_cleared (idx); } - if (idx > maxelts) - return NULL_TREE; + if (idx >= maxelts) + return ctor; str.safe_insert (idx, val); } - if (!nelts) - /* Append a nul for the empty initializer { }. */ + /* Append a nul string termination. */ + if (str.length () < maxelts) str.safe_push (0); - /* Build a STRING_CST with the same type as the array, which - may be an array of unknown bound. */ + /* Build a STRING_CST with the same type as the array. */ tree res = build_string (str.length (), str.begin ()); TREE_TYPE (res) = type; return res; diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index c5e2028cbaa..cc168e22c6b 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1331,7 +1331,7 @@ extern void maybe_add_include_fixit (rich_location *, const char *, bool); extern void maybe_suggest_missing_token_insertion (rich_location *richloc, enum cpp_ttype token_type, location_t prev_token_loc); -extern tree braced_list_to_string (tree, tree, tree (*)(tree, tree) = NULL); +extern tree braced_list_to_string (tree, tree); #if CHECKING_P namespace selftest { diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 51b706c6231..5c18f6307f8 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,8 @@ +2018-09-02 Bernd Edlinger + + * c-decl.c (finish_decl): Call braced_list_to_string here ... + * c-parser.c (c_parser_declaration_or_fndef): ... instead of here. + 2018-08-30 Alexander Monakov * gimple-parser.c (c_parser_gimple_binary_expression): Accept infix diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index feafc022768..fd08d72b11f 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -5031,6 +5031,12 @@ finish_decl (tree decl, location_t init_loc, tree init, relayout_decl (decl); } + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_STRING_FLAG (TREE_TYPE (type)) + && DECL_INITIAL (decl) + && TREE_CODE (DECL_INITIAL (decl)) == CONSTRUCTOR) + DECL_INITIAL (decl) = braced_list_to_string (type, DECL_INITIAL (decl)); + if (VAR_P (decl)) { if (init && TREE_CODE (init) == CONSTRUCTOR) diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 28384dfe913..69ed5ae9d2f 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -2127,15 +2127,6 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok, if (d != error_mark_node) { maybe_warn_string_init (init_loc, TREE_TYPE (d), init); - - /* Try to convert a string CONSTRUCTOR into a STRING_CST. */ - tree valtype = TREE_TYPE (init.value); - if (TREE_CODE (init.value) == CONSTRUCTOR - && TREE_CODE (valtype) == ARRAY_TYPE - && TYPE_STRING_FLAG (TREE_TYPE (valtype))) - if (tree str = braced_list_to_string (valtype, init.value)) - init.value = str; - finish_decl (d, init_loc, init.value, init.original_type, asm_name); } diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9e135b34535..cec14d5d53f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2018-09-02 Bernd Edlinger + + * decl.c (eval_check_narrowing): Remove. + (check_initializer): Move call to braced_list_to_string from here ... + * typeck2.c (store_init_value): ... to here. + (digest_init_r): Remove handing of signed/unsigned char strings. + 2018-08-31 Nathan Sidwell PR c++/87155 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d743e6fef25..5962c19fbe4 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6283,30 +6283,6 @@ build_aggr_init_full_exprs (tree decl, tree init, int flags) return build_aggr_init (decl, init, flags, tf_warning_or_error); } -/* Attempt to determine the constant VALUE of integral type and convert - it to TYPE, issuing narrowing warnings/errors as necessary. Return - the constant result or null on failure. Callback for - braced_list_to_string. */ - -static tree -eval_check_narrowing (tree type, tree value) -{ - if (tree valtype = TREE_TYPE (value)) - { - if (TREE_CODE (valtype) != INTEGER_TYPE) - return NULL_TREE; - } - else - return NULL_TREE; - - value = scalar_constant_value (value); - if (!value) - return NULL_TREE; - - check_narrowing (type, value, tf_warning_or_error); - return value; -} - /* Verify INIT (the initializer for DECL), and record the initialization in DECL_INITIAL, if appropriate. CLEANUP is as for grok_reference_init. @@ -6422,17 +6398,7 @@ check_initializer (tree decl, tree init, int flags, vec **cleanups) } else { - /* Try to convert a string CONSTRUCTOR into a STRING_CST. */ - tree valtype = TREE_TYPE (decl); - if (TREE_CODE (valtype) == ARRAY_TYPE - && TYPE_STRING_FLAG (TREE_TYPE (valtype)) - && BRACE_ENCLOSED_INITIALIZER_P (init)) - if (tree str = braced_list_to_string (valtype, init, - eval_check_narrowing)) - init = str; - - if (TREE_CODE (init) != STRING_CST) - init = reshape_init (type, init, tf_warning_or_error); + init = reshape_init (type, init, tf_warning_or_error); flags |= LOOKUP_NO_NARROWING; } } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 71fbff167a5..7cd0a7ef4b4 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -807,6 +807,11 @@ store_init_value (tree decl, tree init, vec** cleanups, int flags) /* Digest the specified initializer into an expression. */ value = digest_init_flags (type, init, flags, tf_warning_or_error); + if (TREE_CODE (type) == ARRAY_TYPE + && TYPE_STRING_FLAG (TREE_TYPE (type)) + && TREE_CODE (value) == CONSTRUCTOR) + value = braced_list_to_string (type, value); + value = extend_ref_init_temps (decl, value, cleanups); /* In C++11 constant expression is a semantic, not syntactic, property. @@ -1058,9 +1063,7 @@ digest_init_r (tree type, tree init, int nested, int flags, if (TYPE_PRECISION (typ1) == BITS_PER_UNIT) { - if (char_type != char_type_node - && char_type != signed_char_type_node - && char_type != unsigned_char_type_node) + if (char_type != char_type_node) { if (complain & tf_error) error_at (loc, "char-array initialized from wide string"); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 83bab179d68..c192dcc3611 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-09-02 Bernd Edlinger + + * c-c++-common/array-init.c: New test. + * g++.dg/init/string2.C: Remove selector. + 2018-09-01 Michael Matz PR tree-optimization/87074 diff --git a/gcc/testsuite/c-c++-common/array-init.c b/gcc/testsuite/c-c++-common/array-init.c new file mode 100644 index 00000000000..0624e708987 --- /dev/null +++ b/gcc/testsuite/c-c++-common/array-init.c @@ -0,0 +1,4 @@ +/* { dg-do compile } */ +/* { dg-prune-output "sorry, unimplemented: non-trivial designated initializers not supported" } */ + +char x[] = { [-1] = 1, 2, 3 }; /* { dg-error "array index in initializer exceeds array bounds" "" { target c } } */ diff --git a/gcc/testsuite/g++.dg/init/string2.C b/gcc/testsuite/g++.dg/init/string2.C index 5da13bd81b0..19ae6b4ef1c 100644 --- a/gcc/testsuite/g++.dg/init/string2.C +++ b/gcc/testsuite/g++.dg/init/string2.C @@ -54,7 +54,7 @@ template int tmplen () { static const T - a[] = { 1, 2, 333, 0 }; // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" "" { target { ! c++98_only } } } + a[] = { 1, 2, 333, 0 }; // { dg-warning "\\\[\(-Wnarrowing|-Woverflow\)" } return __builtin_strlen (a); } -- 2.11.4.GIT