c++: Fix pretty-print of pointer minus integer.
authorJason Merrill <jason@redhat.com>
Thu, 4 Jun 2020 19:56:57 +0000 (15:56 -0400)
committerJason Merrill <jason@redhat.com>
Fri, 5 Jun 2020 17:54:54 +0000 (13:54 -0400)
For whatever reason, GCC internally represents a pointer minus an integer as
a pointer plus a very large unsigned integer.  But exposing that to users is
unsightly, and it's easy enough to show the real value.

gcc/cp/ChangeLog:

* error.c (dump_binary_op): Handle negative operand to
POINTER_PLUS_EXPR.

gcc/c-family/ChangeLog:

* c-pretty-print.c (pp_c_additive_expression): Handle negative
operand to POINTER_PLUS_EXPR.

gcc/testsuite/ChangeLog:

* g++.dg/cpp0x/constexpr-ptrsub2.C: New test.

gcc/c-family/c-pretty-print.c
gcc/cp/error.c
gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub2.C [new file with mode: 0644]

index 32f30f2d452692a610269b835e86d71f4e29273e..71baf5e2edeb2413b20c6688bcf4a8a7abeb18c5 100644 (file)
@@ -1898,7 +1898,16 @@ pp_c_additive_expression (c_pretty_printer *pp, tree e)
       else
        pp_minus (pp);
       pp_c_whitespace (pp);
-      pp->multiplicative_expression (TREE_OPERAND (e, 1));
+      {
+       tree op1 = TREE_OPERAND (e, 1);
+       if (code == POINTER_PLUS_EXPR
+           && TREE_CODE (op1) == INTEGER_CST
+           && tree_int_cst_sign_bit (op1))
+         /* A pointer minus an integer is represented internally as plus a very
+            large number, don't expose that to users.  */
+         op1 = convert (ssizetype, op1);
+       pp->multiplicative_expression (op1);
+      }
       break;
 
     default:
index 46970f9b69914e62337aab685b1b7e77888ed1f7..0d6375e5e14a7953a478672ed2585ba2effc116c 100644 (file)
@@ -2909,7 +2909,14 @@ dump_binary_op (cxx_pretty_printer *pp, const char *opstring, tree t,
   else
     pp_string (pp, M_("<unknown operator>"));
   pp_cxx_whitespace (pp);
-  dump_expr (pp, TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
+  tree op1 = TREE_OPERAND (t, 1);
+  if (TREE_CODE (t) == POINTER_PLUS_EXPR
+      && TREE_CODE (op1) == INTEGER_CST
+      && tree_int_cst_sign_bit (op1))
+    /* A pointer minus an integer is represented internally as plus a very
+       large number, don't expose that to users.  */
+    op1 = convert (ssizetype, op1);
+  dump_expr (pp, op1, flags | TFF_EXPR_IN_PARENS);
   pp_cxx_right_paren (pp);
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub2.C
new file mode 100644 (file)
index 0000000..fd644ad
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-do compile { target c++11 } }
+
+char c;
+constexpr char p2 = *(&c - 1); // { dg-error "-1" }