diff options
author | Martin Sebor <msebor@redhat.com> | 2018-08-13 17:57:51 +0000 |
---|---|---|
committer | Martin Sebor <msebor@gcc.gnu.org> | 2018-08-13 11:57:51 -0600 |
commit | 23aa9f7c4637ad51587e536e245ae6adb5391bbc (patch) | |
tree | f8eac004f5eeb0fa8a2376e0ab0e5fb0844532e2 /gcc/c-family/c-common.c | |
parent | e6a1e5fe7346458208ede97741382061a6191024 (diff) | |
download | gcc-23aa9f7c4637ad51587e536e245ae6adb5391bbc.zip gcc-23aa9f7c4637ad51587e536e245ae6adb5391bbc.tar.gz gcc-23aa9f7c4637ad51587e536e245ae6adb5391bbc.tar.bz2 |
PR tree-optimization/71625 - missing strlen optimization on different array initialization style
gcc/c/ChangeLog:
PR tree-optimization/71625
* c-parser.c (c_parser_declaration_or_fndef): Call
braced_list_to_string.
gcc/c-family/ChangeLog:
PR tree-optimization/71625
* c-common.c (braced_list_to_string): New function.
* c-common.h (braced_list_to_string): Declare it.
gcc/cp/ChangeLog:
PR tree-optimization/71625
* decl.c (check_initializer): Call braced_list_to_string.
(eval_check_narrowing): New function.
* gcc/cp/typeck2.c (digest_init_r): Accept strings literals
as initilizers for all narrow character types.
gcc/testsuite/ChangeLog:
PR tree-optimization/71625
* g++.dg/init/string2.C: New test.
* g++.dg/init/string3.C: New test.
* g++.dg/init/string4.C: New test.
* gcc.dg/init-string-3.c: New test.
* gcc.dg/strlenopt-55.c: New test.
* gcc.dg/strlenopt-56.c: New test.
From-SVN: r263511
Diffstat (limited to 'gcc/c-family/c-common.c')
-rw-r--r-- | gcc/c-family/c-common.c | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 91e60f3..55b2e50 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -8509,4 +8509,96 @@ maybe_add_include_fixit (rich_location *richloc, const char *header) free (text); } +/* 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. */ + +tree +braced_list_to_string (tree type, tree ctor, tree (*eval)(tree, tree)) +{ + unsigned HOST_WIDE_INT nelts = CONSTRUCTOR_NELTS (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))); + + /* 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; + + tree eltype = TREE_TYPE (type); + + auto_vec<char> str; + str.reserve (nelts + 1); + + unsigned HOST_WIDE_INT i; + tree index, value; + + FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), i, index, value) + { + unsigned HOST_WIDE_INT idx = index ? tree_to_uhwi (index) : i; + + /* auto_vec is limited to UINT_MAX elements. */ + if (idx > UINT_MAX) + return NULL_TREE; + + /* Attempt to evaluate constants. */ + if (eval) + value = eval (eltype, value); + + /* Avoid non-constant initializers. */ + if (!tree_fits_shwi_p (value)) + return NULL_TREE; + + /* Skip over embedded nuls except the last one (initializer + elements are in ascending order of indices). */ + HOST_WIDE_INT val = tree_to_shwi (value); + if (!val && i + 1 < nelts) + continue; + + /* 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; + + if (nchars > 1) + { + str.reserve (idx); + str.quick_grow_cleared (idx); + } + + if (idx > maxelts) + return NULL_TREE; + + str.safe_insert (idx, val); + } + + if (!nelts) + /* Append a nul for the empty initializer { }. */ + str.safe_push (0); + + /* Build a STRING_CST with the same type as the array, which + may be an array of unknown bound. */ + tree res = build_string (str.length (), str.begin ()); + TREE_TYPE (res) = type; + return res; +} + #include "gt-c-family-c-common.h" |