This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C PATCH] Discard P - (P + CST) optimization in pointer_diff (PR c/61240)
- From: Marek Polacek <polacek at redhat dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>, "Joseph S. Myers" <joseph at codesourcery dot com>, Richard Biener <rguenther at suse dot de>, Jakub Jelinek <jakub at redhat dot com>
- Date: Mon, 4 Aug 2014 12:18:56 +0200
- Subject: [C PATCH] Discard P - (P + CST) optimization in pointer_diff (PR c/61240)
- Authentication-results: sourceware.org; auth=none
This PR is about bogus overflow warning that we issue for e.g.
int *q = &i + 1;
q - (q - 1);
because pointer_diff receives p - (p + -1U) which gets simplified to
1U - with overflow. We could drop the overflow flag to suppress the
warning, but I think we should just remove the optimization
altogether. First, FE shouldn't perform such transformations at
all. Second, C++ FE has its own pointer_diff function that doesn't
do such optimization. With this patch, the C FE will generate the
same expression as the C++ FE. It's true that we should try to
optimize this, but not in the front end. It ought to be easy to
write a pattern for match-and-simplify that would handle this.
Bootstrapped/regtested on x86_64-linux, ok for trunk?
2014-08-04 Marek Polacek <polacek@redhat.com>
PR c/61240
* c-typeck.c (pointer_diff): Remove P - (P + CST) optimization.
* gcc.dg/pr61240.c: New test.
diff --git gcc/c/c-typeck.c gcc/c/c-typeck.c
index fe9440c..5f46944 100644
--- gcc/c/c-typeck.c
+++ gcc/c/c-typeck.c
@@ -3460,7 +3460,6 @@ pointer_diff (location_t loc, tree op0, tree op1)
addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
tree target_type = TREE_TYPE (TREE_TYPE (op0));
- tree con0, con1, lit0, lit1;
tree orig_op1 = op1;
/* If the operands point into different address spaces, we need to
@@ -3490,7 +3489,6 @@ pointer_diff (location_t loc, tree op0, tree op1)
else
inttype = restype;
-
if (TREE_CODE (target_type) == VOID_TYPE)
pedwarn (loc, OPT_Wpointer_arith,
"pointer of type %<void *%> used in subtraction");
@@ -3498,50 +3496,6 @@ pointer_diff (location_t loc, tree op0, tree op1)
pedwarn (loc, OPT_Wpointer_arith,
"pointer to a function used in subtraction");
- /* If the conversion to ptrdiff_type does anything like widening or
- converting a partial to an integral mode, we get a convert_expression
- that is in the way to do any simplifications.
- (fold-const.c doesn't know that the extra bits won't be needed.
- split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a
- different mode in place.)
- So first try to find a common term here 'by hand'; we want to cover
- at least the cases that occur in legal static initializers. */
- if (CONVERT_EXPR_P (op0)
- && (TYPE_PRECISION (TREE_TYPE (op0))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
- con0 = TREE_OPERAND (op0, 0);
- else
- con0 = op0;
- if (CONVERT_EXPR_P (op1)
- && (TYPE_PRECISION (TREE_TYPE (op1))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
- con1 = TREE_OPERAND (op1, 0);
- else
- con1 = op1;
-
- if (TREE_CODE (con0) == POINTER_PLUS_EXPR)
- {
- lit0 = TREE_OPERAND (con0, 1);
- con0 = TREE_OPERAND (con0, 0);
- }
- else
- lit0 = integer_zero_node;
-
- if (TREE_CODE (con1) == POINTER_PLUS_EXPR)
- {
- lit1 = TREE_OPERAND (con1, 1);
- con1 = TREE_OPERAND (con1, 0);
- }
- else
- lit1 = integer_zero_node;
-
- if (operand_equal_p (con0, con1, 0))
- {
- op0 = lit0;
- op1 = lit1;
- }
-
-
/* First do the subtraction as integers;
then drop through to build the divide operator.
Do not do default conversions on the minus operator
diff --git gcc/testsuite/gcc.dg/pr61240.c gcc/testsuite/gcc.dg/pr61240.c
index e69de29..e90c070 100644
--- gcc/testsuite/gcc.dg/pr61240.c
+++ gcc/testsuite/gcc.dg/pr61240.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+void
+foo (void)
+{
+ volatile __PTRDIFF_TYPE__ t;
+ int i;
+ int *p = &i;
+ int *q = &i + 1;
+ t = q - (q - 1);
+ t = (q - 1) - q; /* { dg-warning "integer overflow in expression" } */
+ t = p - (p - 1);
+ t = (p - 1) - p ; /* { dg-warning "integer overflow in expression" } */
+}
Marek