Hi!

The match.pd framework uses op0 == op1 || operand_equal_p (op0, op1, 0)
style comparisons heavily; the reason why we don't optimize away say
volatile int i;
...
  int j = i - i;
into int j = (i, 0);
is only because both the C and C++ FE convert the volatile arguments to
non-volatile ones before the arithmetic operation (e.g. c_common_type
returns a non-qualified type).  Unfortunately, in C FE this doesn't happen
for POINTER_DIFF_EXPR, where no conversion happens.  The following patch
makes sure we convert the pointer arguments to some non-qualified pointers
first.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/8.2?

2018-06-15  Jakub Jelinek  <ja...@redhat.com>

        PR c/86093
        * c-typeck.c (pointer_diff): Cast both pointers to unqualified types
        before doing POINTER_DIFF_EXPR.

        * c-c++-common/pr86093.c: New test.

--- gcc/c/c-typeck.c.jj 2018-05-31 20:53:32.003439351 +0200
+++ gcc/c/c-typeck.c    2018-06-15 15:35:44.185308552 +0200
@@ -3840,7 +3840,12 @@ pointer_diff (location_t loc, tree op0,
     op0 = build_binary_op (loc, MINUS_EXPR, convert (inttype, op0),
                           convert (inttype, op1), false);
   else
-    op0 = build2_loc (loc, POINTER_DIFF_EXPR, inttype, op0, op1);
+    {
+      /* Cast away qualifiers.  */
+      op0 = convert (c_common_type (TREE_TYPE (op0), TREE_TYPE (op0)), op0);
+      op1 = convert (c_common_type (TREE_TYPE (op1), TREE_TYPE (op1)), op1);
+      op0 = build2_loc (loc, POINTER_DIFF_EXPR, inttype, op0, op1);
+    }
 
   /* This generates an error if op1 is pointer to incomplete type.  */
   if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
--- gcc/testsuite/c-c++-common/pr86093.c.jj     2018-06-15 15:51:40.344192815 
+0200
+++ gcc/testsuite/c-c++-common/pr86093.c        2018-06-15 15:51:23.340177502 
+0200
@@ -0,0 +1,12 @@
+/* PR c/86093 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "return 0;" "optimized" } } */
+
+char *volatile p;
+
+__PTRDIFF_TYPE__
+foo (void)
+{
+  return p - p;
+}

        Jakub

Reply via email to