]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix artificial overflow during GENERIC folding
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 29 May 2023 07:45:57 +0000 (09:45 +0200)
committerEric Botcazou <ebotcazou@adacore.com>
Mon, 29 May 2023 09:13:08 +0000 (11:13 +0200)
The Ada compiler gives a bogus warning:
storage_offset1.ads:16:52: warning: Constraint_Error will be raised at run
time [enabled by default]

Ironically enough, this occurs because of an intermediate conversion to an
unsigned type which is supposed to hide overflows but is counter-productive
for constants because TREE_OVERFLOW is always set for them, so it ends up
setting a bogus TREE_OVERFLOW when converting back to the original type.

The fix simply redirects INTEGER_CSTs to the other, direct path without the
intermediate conversion to the unsigned type.

gcc/
* match.pd ((T)P - (T)(P + A) -> -(T) A): Avoid artificial overflow
on constants.

gcc/testsuite/
* gnat.dg/specs/storage_offset1.ads: New test.

gcc/match.pd
gcc/testsuite/gnat.dg/specs/storage_offset1.ads [new file with mode: 0644]

index 6e32f476e973c91259bde36054dd5548a756d1d4..577f4ba0ed99d9a7c2ed9cef12a7b510b8e6a415 100644 (file)
@@ -3194,6 +3194,13 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (convert (plus:c @@0 @1)))
    (if (INTEGRAL_TYPE_P (type)
        && TYPE_OVERFLOW_UNDEFINED (type)
+       /* For integer literals, using an intermediate unsigned type to avoid
+          an overflow at run time is counter-productive because it introduces
+          spurious overflows at compile time, in the form of TREE_OVERFLOW on
+          the result, which may be problematic in GENERIC for some front-ends:
+            (T)P - (T)(P + 4) -> (T)(-(U)4) -> (T)(4294967292) -> -4(OVF)
+          so we use the direct path for them.  */
+       && TREE_CODE (@1) != INTEGER_CST
        && element_precision (type) <= element_precision (TREE_TYPE (@1)))
     (with { tree utype = unsigned_type_for (type); }
      (convert (negate (convert:utype @1))))
@@ -3213,6 +3220,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
     (convert (pointer_plus @@0 @1)))
    (if (INTEGRAL_TYPE_P (type)
        && TYPE_OVERFLOW_UNDEFINED (type)
+       /* See above the rationale for this condition.  */
+       && TREE_CODE (@1) != INTEGER_CST
        && element_precision (type) <= element_precision (TREE_TYPE (@1)))
     (with { tree utype = unsigned_type_for (type); }
      (convert (negate (convert:utype @1))))
diff --git a/gcc/testsuite/gnat.dg/specs/storage_offset1.ads b/gcc/testsuite/gnat.dg/specs/storage_offset1.ads
new file mode 100644 (file)
index 0000000..f0f7a61
--- /dev/null
@@ -0,0 +1,18 @@
+-- { dg-do compile }
+
+with System.Storage_Elements; use System.Storage_Elements;
+with System;
+
+package Storage_Offset1 is
+
+  type Rec is record
+    I1, I2 : Integer;
+  end record;
+
+  type Ptr is access all Rec;
+
+  R : Ptr := new Rec;
+
+  Offset : constant Storage_Offset := R.I1'Address - R.I2'Address;
+
+end Storage_Offset1;