aboutsummaryrefslogtreecommitdiff
path: root/gcc/c-family/c-common.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-08-13 17:57:51 +0000
committerMartin Sebor <msebor@gcc.gnu.org>2018-08-13 11:57:51 -0600
commit23aa9f7c4637ad51587e536e245ae6adb5391bbc (patch)
treef8eac004f5eeb0fa8a2376e0ab0e5fb0844532e2 /gcc/c-family/c-common.c
parente6a1e5fe7346458208ede97741382061a6191024 (diff)
downloadgcc-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.c92
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"