From 5094c4400a8687dcf44f5993aee3a88e98519f3b Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 4 Jun 2020 15:56:57 -0400 Subject: [PATCH] c++: Fix pretty-print of pointer minus integer. 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 | 11 ++++++++++- gcc/cp/error.c | 9 ++++++++- gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub2.C | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub2.C diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c index 32f30f2d452..71baf5e2ede 100644 --- a/gcc/c-family/c-pretty-print.c +++ b/gcc/c-family/c-pretty-print.c @@ -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: diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 46970f9b699..0d6375e5e14 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -2909,7 +2909,14 @@ dump_binary_op (cxx_pretty_printer *pp, const char *opstring, tree t, else pp_string (pp, M_("")); 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 index 00000000000..fd644ad7854 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-ptrsub2.C @@ -0,0 +1,4 @@ +// { dg-do compile { target c++11 } } + +char c; +constexpr char p2 = *(&c - 1); // { dg-error "-1" } -- 2.30.2