re PR tree-optimization/67921 ("internal compiler error: in build_polynomial_chrec...
authorBin Cheng <bin.cheng@arm.com>
Mon, 1 Feb 2016 17:17:47 +0000 (17:17 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Mon, 1 Feb 2016 17:17:47 +0000 (17:17 +0000)
PR tree-optimization/67921
* fold-const.c (split_tree): New parameters.  Convert pointer
type variable part to proper type before negating.
(fold_binary_loc): Pass new arguments to split_tree.

gcc/testsuite/ChangeLog
PR tree-optimization/67921
* c-c++-common/ubsan/pr67921.c: New test.

From-SVN: r233042

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/ubsan/pr67921.c [new file with mode: 0644]

index cb6d8bd..ba4deed 100644 (file)
@@ -1,3 +1,10 @@
+2016-02-01  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/67921
+       * fold-const.c (split_tree): New parameters.  Convert pointer
+       type variable part to proper type before negating. 
+       (fold_binary_loc): Pass new arguments to split_tree.
+
 2016-02-01  Nathan Sidwell  <nathan@codesourcery.com>
 
        * config/nvptx/nvptx.c (PTX_GANG_DEFAULT): New.
index bece8d7..e34bc81 100644 (file)
@@ -109,7 +109,8 @@ enum comparison_code {
 
 static bool negate_expr_p (tree);
 static tree negate_expr (tree);
-static tree split_tree (tree, enum tree_code, tree *, tree *, tree *, int);
+static tree split_tree (location_t, tree, tree, enum tree_code,
+                       tree *, tree *, tree *, int);
 static tree associate_trees (location_t, tree, tree, enum tree_code, tree);
 static enum comparison_code comparison_to_compcode (enum tree_code);
 static enum tree_code compcode_to_comparison (enum comparison_code);
@@ -767,7 +768,10 @@ negate_expr (tree t)
    literal for which we use *MINUS_LITP instead.
 
    If NEGATE_P is true, we are negating all of IN, again except a literal
-   for which we use *MINUS_LITP instead.
+   for which we use *MINUS_LITP instead.  If a variable part is of pointer
+   type, it is negated after converting to TYPE.  This prevents us from
+   generating illegal MINUS pointer expression.  LOC is the location of
+   the converted variable part.
 
    If IN is itself a literal or constant, return it as appropriate.
 
@@ -775,8 +779,8 @@ negate_expr (tree t)
    same type as IN, but they will have the same signedness and mode.  */
 
 static tree
-split_tree (tree in, enum tree_code code, tree *conp, tree *litp,
-           tree *minus_litp, int negate_p)
+split_tree (location_t loc, tree in, tree type, enum tree_code code,
+           tree *conp, tree *litp, tree *minus_litp, int negate_p)
 {
   tree var = 0;
 
@@ -833,7 +837,12 @@ split_tree (tree in, enum tree_code code, tree *conp, tree *litp,
       if (neg_conp_p)
        *conp = negate_expr (*conp);
       if (neg_var_p)
-       var = negate_expr (var);
+       {
+         /* Convert to TYPE before negating a pointer type expr.  */
+         if (var && POINTER_TYPE_P (TREE_TYPE (var)))
+           var = fold_convert_loc (loc, type, var);
+         var = negate_expr (var);
+       }
     }
   else if (TREE_CODE (in) == BIT_NOT_EXPR
           && code == PLUS_EXPR)
@@ -854,6 +863,9 @@ split_tree (tree in, enum tree_code code, tree *conp, tree *litp,
       else if (*minus_litp)
        *litp = *minus_litp, *minus_litp = 0;
       *conp = negate_expr (*conp);
+      /* Convert to TYPE before negating a pointer type expr.  */
+      if (var && POINTER_TYPE_P (TREE_TYPE (var)))
+       var = fold_convert_loc (loc, type, var);
       var = negate_expr (var);
     }
 
@@ -9621,9 +9633,10 @@ fold_binary_loc (location_t loc,
             then the result with variables.  This increases the chances of
             literals being recombined later and of generating relocatable
             expressions for the sum of a constant and literal.  */
-         var0 = split_tree (arg0, code, &con0, &lit0, &minus_lit0, 0);
-         var1 = split_tree (arg1, code, &con1, &lit1, &minus_lit1,
-                            code == MINUS_EXPR);
+         var0 = split_tree (loc, arg0, type, code,
+                            &con0, &lit0, &minus_lit0, 0);
+         var1 = split_tree (loc, arg1, type, code,
+                            &con1, &lit1, &minus_lit1, code == MINUS_EXPR);
 
          /* Recombine MINUS_EXPR operands by using PLUS_EXPR.  */
          if (code == MINUS_EXPR)
index bfd6e9f..7efd95c 100644 (file)
@@ -1,3 +1,8 @@
+2016-02-01  Bin Cheng  <bin.cheng@arm.com>
+
+       PR tree-optimization/67921
+       * c-c++-common/ubsan/pr67921.c: New test.
+
 2016-02-01  Richard Biener  <rguenther@suse.de>
 
        PR middle-end/69556
diff --git a/gcc/testsuite/c-c++-common/ubsan/pr67921.c b/gcc/testsuite/c-c++-common/ubsan/pr67921.c
new file mode 100644 (file)
index 0000000..728ff93
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-fsanitize=undefined" } */
+
+struct s
+{
+  int n;
+  int arr[][6];
+};
+void bar (int);
+void foo (struct s *ptr)
+{
+  int i;
+  for (; i < 2; i++)
+    for (; ptr->n;)
+      {
+       int *a = ptr->arr[i];
+       int b[66];
+       int j = 0;
+
+       for (; j < 56; j++)
+         bar (a[j] - b[j]);
+    }
+}