From 98f4d3829ca389b235a5f39361ac9dccc3d930b7 Mon Sep 17 00:00:00 2001
From: rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Sun, 4 Feb 2007 15:15:38 +0000
Subject: [PATCH] 2007-02-04  Richard Guenther  <rguenther@suse.de>

	PR middle-end/30636
	* fold-const.c (try_move_mult_to_index): Make sure to not
	overflow one dimension of a multi-dimensional array access.

	* g++.dg/warn/pr30636.C: New testcase.
	* g++.dg/tree-ssa/tmmti-2.C: XFAIL parts.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121575 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/ChangeLog                           |  6 +++++
 gcc/fold-const.c                        | 29 +++++++++++++++++++++++++
 gcc/testsuite/ChangeLog                 |  6 +++++
 gcc/testsuite/g++.dg/tree-ssa/tmmti-2.C |  2 +-
 gcc/testsuite/g++.dg/warn/pr30636.C     | 17 +++++++++++++++
 5 files changed, 59 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/pr30636.C

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index e757d1e8f74c..d2c30766facb 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2007-02-04  Richard Guenther  <rguenther@suse.de>
+
+	PR middle-end/30636
+	* fold-const.c (try_move_mult_to_index): Make sure to not
+	overflow one dimension of a multi-dimensional array access.
+
 2007-02-04  Jan Hubicka  <jh@suse.cz>
 
 	* passes.c (init_optimization_passes): Reindent.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index 085fcd8275be..ee2c469921c5 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -6642,6 +6642,7 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
   tree ref = TREE_OPERAND (addr, 0), pref;
   tree ret, pos;
   tree itype;
+  bool mdim = false;
 
   /* Canonicalize op1 into a possibly non-constant delta
      and an INTEGER_CST s.  */
@@ -6681,6 +6682,10 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
     {
       if (TREE_CODE (ref) == ARRAY_REF)
 	{
+	  /* Remember if this was a multi-dimensional array.  */
+	  if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
+	    mdim = true;
+
 	  itype = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
 	  if (! itype)
 	    continue;
@@ -6703,8 +6708,32 @@ try_move_mult_to_index (enum tree_code code, tree addr, tree op1)
 	      delta = tmp;
 	    }
 
+	  /* Only fold here if we can verify we do not overflow one
+	     dimension of a multi-dimensional array.  */
+	  if (mdim)
+	    {
+	      tree tmp;
+
+	      if (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST
+		  || !INTEGRAL_TYPE_P (itype)
+		  || !TYPE_MAX_VALUE (itype)
+		  || TREE_CODE (TYPE_MAX_VALUE (itype)) != INTEGER_CST)
+		continue;
+
+	      tmp = fold_binary (code, itype,
+				 fold_convert (itype,
+					       TREE_OPERAND (ref, 1)),
+				 fold_convert (itype, delta));
+	      if (!tmp
+		  || TREE_CODE (tmp) != INTEGER_CST
+		  || tree_int_cst_lt (TYPE_MAX_VALUE (itype), tmp))
+		continue;
+	    }
+
 	  break;
 	}
+      else
+	mdim = false;
 
       if (!handled_component_p (ref))
 	return NULL_TREE;
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2193c9563861..d53a458a6e41 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2007-02-04  Richard Guenther  <rguenther@suse.de>
+
+	PR middle-end/30636
+	* g++.dg/warn/pr30636.C: New testcase.
+	* g++.dg/tree-ssa/tmmti-2.C: XFAIL parts.
+
 2007-02-03  Uros Bizjak  <ubizjak@gmail.com>
 
 	PR middle-end/30667
diff --git a/gcc/testsuite/g++.dg/tree-ssa/tmmti-2.C b/gcc/testsuite/g++.dg/tree-ssa/tmmti-2.C
index 9735adc6c7db..fc5899465af2 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/tmmti-2.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/tmmti-2.C
@@ -17,6 +17,6 @@ double bar(int i)
 	return *(&b[0].x + i*2); // b[i].x
 }
 
-/* { dg-final { scan-tree-dump "a\\\[.*i.*\\\]\\\[0\\\]" "optimized" } } */
+/* { dg-final { scan-tree-dump "a\\\[.*i.*\\\]\\\[0\\\]" "optimized" { xfail *-*-* } } } */
 /* { dg-final { scan-tree-dump "b\\\[.*i.*\\\].x" "optimized" } } */
 /* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/g++.dg/warn/pr30636.C b/gcc/testsuite/g++.dg/warn/pr30636.C
new file mode 100644
index 000000000000..32ce6edbd61c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/pr30636.C
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -Warray-bounds" } */
+
+typedef char one_buffer[512];
+static one_buffer emergency_buffer[4];
+
+void free_exception (void *vptr)
+{
+  char *base = (char *) &emergency_buffer[0][0];
+  char *ptr = (char *) vptr;
+  if (ptr >= base && ptr < base + sizeof (emergency_buffer)) /* { dg-bogus "subscript" } */
+    {
+      /* Do something. */
+      __builtin_exit (0);
+    }
+}
+
-- 
GitLab