diff options
author | Richard Biener <rguenther@suse.de> | 2023-04-25 14:56:44 +0200 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2023-04-25 16:53:06 +0200 |
commit | e8d00353017f895d03a9eabae3506fd126ce1a2d (patch) | |
tree | 7d3780af9e37ee55cfbc7adf07d90c8513d0cc3c | |
parent | 1c101fcfaac8f609d618f83b124bd50aea012132 (diff) | |
download | gcc-e8d00353017f895d03a9eabae3506fd126ce1a2d.zip gcc-e8d00353017f895d03a9eabae3506fd126ce1a2d.tar.gz gcc-e8d00353017f895d03a9eabae3506fd126ce1a2d.tar.bz2 |
tree-optimization/109609 - correctly interpret arg size in fnspec
By majority vote and a hint from the API name which is
arg_max_access_size_given_by_arg_p this interprets a memory access
size specified as given as other argument such as for strncpy
in the testcase which has "1cO313" as specifying the _maximum_
size read/written rather than the exact size. There are two
uses interpreting it that way already and one differing. The
following adjusts the differing and clarifies the documentation.
PR tree-optimization/109609
* attr-fnspec.h (arg_max_access_size_given_by_arg_p):
Clarify semantics.
* tree-ssa-alias.cc (check_fnspec): Correctly interpret
the size given by arg_max_access_size_given_by_arg_p as
maximum, not exact, size.
* gcc.dg/torture/pr109609.c: New testcase.
-rw-r--r-- | gcc/attr-fnspec.h | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/torture/pr109609.c | 26 | ||||
-rw-r--r-- | gcc/tree-ssa-alias.cc | 18 |
3 files changed, 43 insertions, 5 deletions
diff --git a/gcc/attr-fnspec.h b/gcc/attr-fnspec.h index acf1c5f..99d5f89 100644 --- a/gcc/attr-fnspec.h +++ b/gcc/attr-fnspec.h @@ -54,7 +54,7 @@ ' ' nothing is known 't' the size of value written/read corresponds to the size of of the pointed-to type of the argument type - '1'...'9' specifies the size of value written/read is given by the + '1'...'9' specifies the size of value written/read is bound by the specified argument */ @@ -169,7 +169,7 @@ public: && str[idx] != 'x' && str[idx] != 'X'; } - /* Return true if load of memory pointed to by argument I is specified + /* Return true if load of memory pointed to by argument I is bound by another argument. In this case set ARG. */ bool arg_max_access_size_given_by_arg_p (unsigned int i, unsigned int *arg) diff --git a/gcc/testsuite/gcc.dg/torture/pr109609.c b/gcc/testsuite/gcc.dg/torture/pr109609.c new file mode 100644 index 0000000..0e191cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr109609.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ + +#define N 23 +#define MAX_LEN 13 +char dst[N + 1]; + +void __attribute__((noipa)) +invert(const char *id) +{ + char buf[MAX_LEN]; + char *ptr = buf + sizeof(buf); // start from the end of buf + *(--ptr) = '\0'; // terminate string + while (*id && ptr > buf) { + *(--ptr) = *(id++); // copy id backwards + } + __builtin_strncpy(dst, ptr, N); // copy ptr/buf to dst +} + + +int main() +{ + invert("abcde"); + if (__builtin_strcmp(dst, "edcba")) + __builtin_abort(); + return 0; +} diff --git a/gcc/tree-ssa-alias.cc b/gcc/tree-ssa-alias.cc index 8a1ec90..e0693e1 100644 --- a/gcc/tree-ssa-alias.cc +++ b/gcc/tree-ssa-alias.cc @@ -2726,9 +2726,21 @@ check_fnspec (gcall *call, ao_ref *ref, bool clobber) t = TREE_CHAIN (t); size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_VALUE (t))); } - ao_ref_init_from_ptr_and_size (&dref, - gimple_call_arg (call, i), - size); + poly_int64 size_hwi; + if (size + && poly_int_tree_p (size, &size_hwi) + && coeffs_in_range_p (size_hwi, 0, + HOST_WIDE_INT_MAX / BITS_PER_UNIT)) + { + size_hwi = size_hwi * BITS_PER_UNIT; + ao_ref_init_from_ptr_and_range (&dref, + gimple_call_arg (call, i), + true, 0, -1, size_hwi); + } + else + ao_ref_init_from_ptr_and_range (&dref, + gimple_call_arg (call, i), + false, 0, -1, -1); if (refs_may_alias_p_1 (&dref, ref, false)) return 1; } |