Hi,

IPA-SRA asserts that an offset obtained from get_ref_base_and_extent
is non-negative (after it verifies it is based on a parameter).  That
assumption is invalid as the testcase shows.  One could probably also write a
testcase with defined behavior, but unless I see a reasonable one
where the transformation is really desirable, I'd like to just punt on
those cases.

Bootstrapped and tested on x86_64-linux.  OK for trunk?

Thanks,

Martin

2019-09-23  Martin Jambor  <mjam...@suse.cz>

        PR ipa/91832
        * ipa-sra.c (scan_expr_access): Check that offset is non-negative.

        testsuite/
        * gcc.dg/ipa/pr91832.c: New test.
---
 gcc/ipa-sra.c                      |  7 ++++++-
 gcc/testsuite/gcc.dg/ipa/pr91832.c | 12 ++++++++++++
 2 files changed, 18 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/gcc.dg/ipa/pr91832.c

diff --git a/gcc/ipa-sra.c b/gcc/ipa-sra.c
index a32defb59bd..0ccebbd4607 100644
--- a/gcc/ipa-sra.c
+++ b/gcc/ipa-sra.c
@@ -1692,7 +1692,12 @@ scan_expr_access (tree expr, gimple *stmt, 
isra_scan_context ctx,
       disqualify_split_candidate (desc, "Encountered a bit-field access.");
       return;
     }
-  gcc_assert (offset >= 0);
+  if (offset < 0)
+    {
+      disqualify_split_candidate (desc, "Encountered an access at a "
+                                 "negative offset.");
+      return;
+    }
   gcc_assert ((offset % BITS_PER_UNIT) == 0);
   gcc_assert ((size % BITS_PER_UNIT) == 0);
   if ((offset / BITS_PER_UNIT) >= (UINT_MAX - ISRA_ARG_SIZE_LIMIT)
diff --git a/gcc/testsuite/gcc.dg/ipa/pr91832.c 
b/gcc/testsuite/gcc.dg/ipa/pr91832.c
new file mode 100644
index 00000000000..4a0d62ec1d9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr91832.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2"  } */
+
+struct A1 {
+  char a1[1];
+};
+
+void fn2(char a);
+
+void fn1(struct A1 *p1) {
+  fn2(p1->a1[-1]);
+}
-- 
2.23.0

Reply via email to