]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
varasm: check float size [PR109359]
authorJason Merrill <jason@redhat.com>
Thu, 1 Jun 2023 18:41:07 +0000 (14:41 -0400)
committerJason Merrill <jason@redhat.com>
Mon, 5 Feb 2024 21:39:17 +0000 (16:39 -0500)
In PR95226, the testcase was failing because we tried to output_constant a
NOP_EXPR to float from a double REAL_CST, and so we output a double where
the caller wanted a float.  That doesn't happen anymore, but with the
output_constant hunk we will ICE in that situation rather than emit the
wrong number of bytes.

Part of the problem was that initializer_constant_valid_p_1 returned true
for that NOP_EXPR, because it compared the sizes of integer types but not
floating-point types.  So the C++ front end assumed it didn't need to fold
the initializer.

This also fixed the test for PR109359.

PR c++/95226
PR c++/109359

gcc/ChangeLog:

* varasm.cc (output_constant) [REAL_TYPE]: Check that sizes match.
(initializer_constant_valid_p_1): Compare float precision.

gcc/testsuite/ChangeLog:

* g++.dg/ext/frounding-math1.C: New test.

(cherry picked from commit e7cc4d703bceb9095316c106eba0d1939c6c8044)

gcc/testsuite/g++.dg/ext/frounding-math1.C [new file with mode: 0644]
gcc/varasm.cc

diff --git a/gcc/testsuite/g++.dg/ext/frounding-math1.C b/gcc/testsuite/g++.dg/ext/frounding-math1.C
new file mode 100644 (file)
index 0000000..ecc46fd
--- /dev/null
@@ -0,0 +1,8 @@
+// PR c++/109359
+// { dg-additional-options -frounding-math }
+
+// For a while we were emitting two doubles (4 .long directives) as the value
+// of a float array; it should only be two .longs.
+
+// { dg-final { scan-assembler-times "long" 2 { target x86_64-*-* } } }
+float xs[] = {0.001914, 0.630539};
index a4b1cc68680d3cd0159801d705d5d382fcc60b89..dc9f733791ab0d26b90ded45d5e29d7878832a38 100644 (file)
@@ -4897,16 +4897,16 @@ initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
        tree src_type = TREE_TYPE (src);
        tree dest_type = TREE_TYPE (value);
 
-       /* Allow conversions between pointer types, floating-point
-          types, and offset types.  */
+       /* Allow conversions between pointer types and offset types.  */
        if ((POINTER_TYPE_P (dest_type) && POINTER_TYPE_P (src_type))
-           || (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type))
            || (TREE_CODE (dest_type) == OFFSET_TYPE
                && TREE_CODE (src_type) == OFFSET_TYPE))
          return initializer_constant_valid_p_1 (src, endtype, cache);
 
-       /* Allow length-preserving conversions between integer types.  */
-       if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)
+       /* Allow length-preserving conversions between integer types and
+          floating-point types.  */
+       if (((INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type))
+            || (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type)))
            && (TYPE_PRECISION (dest_type) == TYPE_PRECISION (src_type)))
          return initializer_constant_valid_p_1 (src, endtype, cache);
 
@@ -5276,6 +5276,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
       break;
 
     case REAL_TYPE:
+      gcc_assert (size == thissize);
       if (TREE_CODE (exp) != REAL_CST)
        error ("initializer for floating value is not a floating constant");
       else