aboutsummaryrefslogtreecommitdiff
path: root/gcc/expr.c
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2020-08-18 12:57:18 -0600
committerMartin Sebor <msebor@redhat.com>2020-08-18 12:59:09 -0600
commitd367f5fcb579d21c3093cf5c464f5787fe584a1d (patch)
tree0d1778f66517b2fb0db3927b124acca6097b5282 /gcc/expr.c
parentbb04901d14f7749eb949092fd3dfcb6ca1958701 (diff)
downloadgcc-d367f5fcb579d21c3093cf5c464f5787fe584a1d.zip
gcc-d367f5fcb579d21c3093cf5c464f5787fe584a1d.tar.gz
gcc-d367f5fcb579d21c3093cf5c464f5787fe584a1d.tar.bz2
PR middle-end/96665 - memcmp of a constant string not folded
Related: PR middle-end/78257 - missing memcmp optimization with constant arrays gcc/ChangeLog: PR middle-end/96665 PR middle-end/78257 * expr.c (convert_to_bytes): Replace statically allocated buffer with a dynamically allocated one of sufficient size. gcc/testsuite/ChangeLog: PR middle-end/96665 PR middle-end/78257 * gcc.dg/memcmp-5.c: New test.
Diffstat (limited to 'gcc/expr.c')
-rw-r--r--gcc/expr.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/gcc/expr.c b/gcc/expr.c
index dd2200d..437faea 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -11683,16 +11683,27 @@ convert_to_bytes (tree type, tree expr, vec<unsigned char> *bytes)
return true;
}
- unsigned char charbuf[MAX_BITSIZE_MODE_ANY_MODE / BITS_PER_UNIT];
- int len = native_encode_expr (expr, charbuf, sizeof charbuf, 0);
- if (len <= 0)
+ /* Except for RECORD_TYPE which may have an initialized flexible array
+ member, the size of a type is the same as the size of the initializer
+ (including any implicitly zeroed out members and padding). Allocate
+ just enough for that many bytes. */
+ tree expr_size = TYPE_SIZE_UNIT (TREE_TYPE (expr));
+ if (!expr_size || !tree_fits_uhwi_p (expr_size))
+ return false;
+ const unsigned HOST_WIDE_INT expr_bytes = tree_to_uhwi (expr_size);
+ const unsigned bytes_sofar = bytes->length ();
+ /* native_encode_expr can convert at most INT_MAX bytes. vec is limited
+ to at most UINT_MAX. */
+ if (bytes_sofar + expr_bytes > INT_MAX)
return false;
- unsigned n = bytes->length ();
- bytes->safe_grow (n + len);
- unsigned char *p = bytes->address ();
- memcpy (p + n, charbuf, len);
- return true;
+ /* Unlike for RECORD_TYPE, there is no need to clear the memory since
+ it's completely overwritten by native_encode_expr. */
+ bytes->safe_grow (bytes_sofar + expr_bytes);
+ unsigned char *pnext = bytes->begin () + bytes_sofar;
+ int nbytes = native_encode_expr (expr, pnext, expr_bytes, 0);
+ /* NBYTES is zero on failure. Otherwise it should equal EXPR_BYTES. */
+ return (unsigned HOST_WIDE_INT) nbytes == expr_bytes;
}
/* Return a STRING_CST corresponding to ARG's constant initializer either