From 9b8e82ab45d1ad976a824cfd7c9bd2640c8bc8e3 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 1 Jun 2023 14:41:07 -0400 Subject: [PATCH] varasm: check float size [PR109359] 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 | 8 ++++++++ gcc/varasm.cc | 11 ++++++----- 2 files changed, 14 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/frounding-math1.C diff --git a/gcc/testsuite/g++.dg/ext/frounding-math1.C b/gcc/testsuite/g++.dg/ext/frounding-math1.C new file mode 100644 index 000000000000..ecc46fd6017d --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/frounding-math1.C @@ -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}; diff --git a/gcc/varasm.cc b/gcc/varasm.cc index cd0cd88321c6..9ad41c3dbdb8 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -4876,16 +4876,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); @@ -5255,6 +5255,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 -- 2.47.2