When PTA gets support for special-handling more builtins in find_func_aliases the corresponding code in find_func_clobbers needs updating as well since for unhandled cases it assumes the former will populate ESCAPED accordingly. The following fixes a few omissions, the testcase runs into the missing strdup handling. I believe the more advanced handling using modref results and fnspecs opened a larger gap, the proper fix is to merge both functions, gating the clobber/use part on a parameter to avoid diverging.
Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed to trunk. PR ipa/120006 * tree-ssa-structalias.cc (find_func_clobbers): Handle strdup, strndup, realloc, index, strchr, strrchr, memchr, strstr, strpbrk builtins like find_func_aliases does. * gcc.dg/torture/pr120006.c: New testcase. --- gcc/testsuite/gcc.dg/torture/pr120006.c | 31 +++++++++++++++++++++ gcc/tree-ssa-structalias.cc | 36 +++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 gcc/testsuite/gcc.dg/torture/pr120006.c diff --git a/gcc/testsuite/gcc.dg/torture/pr120006.c b/gcc/testsuite/gcc.dg/torture/pr120006.c new file mode 100644 index 00000000000..c067f0ef9ca --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr120006.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-additional-options "-fipa-pta" } */ + +char *b; +int f = 1; + +char *xstrdup(char *i) { + char *c = __builtin_strdup(i); + if (!c) + __builtin_exit(1); + return c; +} + +int main() { + char g; + char h[8]; + + for (int i = 0; i < 2; i++) { + char c = *__builtin_strdup(""); + b = &g; + + if (f) { + h[0] = '-'; + h[1] = 'a'; + h[2] = '\0'; + b = xstrdup(h); + } + } + if (__builtin_strcmp(b, "-a") != 0) + __builtin_abort(); +} diff --git a/gcc/tree-ssa-structalias.cc b/gcc/tree-ssa-structalias.cc index f79b54284c6..3ad0c69930c 100644 --- a/gcc/tree-ssa-structalias.cc +++ b/gcc/tree-ssa-structalias.cc @@ -5583,6 +5583,42 @@ find_func_clobbers (struct function *fn, gimple *origt) process_ipa_clobber (fi, gimple_call_arg (t, 2)); return; } + /* The following functions use what their first argument + points to. */ + case BUILT_IN_STRDUP: + case BUILT_IN_STRNDUP: + case BUILT_IN_REALLOC: + case BUILT_IN_INDEX: + case BUILT_IN_STRCHR: + case BUILT_IN_STRRCHR: + case BUILT_IN_MEMCHR: + { + tree src = gimple_call_arg (t, 0); + get_constraint_for_ptr_offset (src, NULL_TREE, &rhsc); + lhs = get_function_part_constraint (fi, fi_uses); + struct constraint_expr *rhsp; + FOR_EACH_VEC_ELT (rhsc, i, rhsp) + process_constraint (new_constraint (lhs, *rhsp)); + return; + } + /* The following functions use what their first and second argument + point to. */ + case BUILT_IN_STRSTR: + case BUILT_IN_STRPBRK: + { + tree src = gimple_call_arg (t, 0); + get_constraint_for_ptr_offset (src, NULL_TREE, &rhsc); + lhs = get_function_part_constraint (fi, fi_uses); + struct constraint_expr *rhsp; + FOR_EACH_VEC_ELT (rhsc, i, rhsp) + process_constraint (new_constraint (lhs, *rhsp)); + rhsc.truncate (0); + src = gimple_call_arg (t, 1); + get_constraint_for_ptr_offset (src, NULL_TREE, &rhsc); + FOR_EACH_VEC_ELT (rhsc, i, rhsp) + process_constraint (new_constraint (lhs, *rhsp)); + return; + } /* The following functions neither read nor clobber memory. */ case BUILT_IN_ASSUME_ALIGNED: case BUILT_IN_FREE: -- 2.43.0