aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBin Cheng <bin.cheng@arm.com>2016-02-01 17:17:47 +0000
committerBin Cheng <bin.cheng@arm.com>2016-02-01 17:17:47 +0000
commit4abcbb77ecd0f968495636f6f04d5771069518c9 (patch)
tree71a5ad91eb43ad0ae0479f0aeb90f06e0084d1e5
parent5e77a28ef37eb26a6c1d0023d930ebccc4a8f579 (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@233042 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/fold-const.c29
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/c-c++-common/ubsan/pr67921.c23
4 files changed, 56 insertions, 8 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index cb6d8bdfc64..ba4deed7a24 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index bece8d74b46..e34bc81eae8 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index bfd6e9f6ce4..7efd95cebc0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..728ff93a60f
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/ubsan/pr67921.c
@@ -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]);
+ }
+}