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

Reply via email to