aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/c-family/c-common.c2
-rw-r--r--gcc/testsuite/c-c++-common/pr95903.c19
2 files changed, 20 insertions, 1 deletions
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index b73ad2e..a9fa0d1 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -3141,7 +3141,7 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
/* If the constant is unsigned, and smaller than the pointer size,
then we must skip this optimization. This is because it could cause
an overflow error if the constant is negative but INTOP is not. */
- && (!TYPE_UNSIGNED (TREE_TYPE (intop))
+ && (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (intop))
|| (TYPE_PRECISION (TREE_TYPE (intop))
== TYPE_PRECISION (TREE_TYPE (ptrop)))))
{
diff --git a/gcc/testsuite/c-c++-common/pr95903.c b/gcc/testsuite/c-c++-common/pr95903.c
new file mode 100644
index 0000000..6e9f68e
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/pr95903.c
@@ -0,0 +1,19 @@
+/* PR middle-end/95903 */
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-O2 -fwrapv -fdump-tree-optimized" } */
+/* Verify that for -fwrapv the + 1 addition is performed in the parameter's
+ type before sign extending it. */
+/* { dg-final { scan-tree-dump-times "off_\[0-9]+\\\(D\\\) \\+ 1" 2 "optimized" } } */
+
+char
+foo (const char *ptr, int off)
+{
+ off += 1;
+ return ptr[off];
+}
+
+char
+bar (const char *ptr, int off)
+{
+ return ptr[off + 1];
+}