aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-06-17 18:53:21 +0200
committerJakub Jelinek <jakub@redhat.com>2024-06-17 19:17:06 +0200
commit5be6d9d2a9854c05f3c019deb9fe95eca7248140 (patch)
tree8e549bb1b8edb031612049f3b7c2a3fc2c8b60da
parent20cda2e85c307096a3856f7f27215b8a28982fb6 (diff)
downloadgcc-5be6d9d2a9854c05f3c019deb9fe95eca7248140.zip
gcc-5be6d9d2a9854c05f3c019deb9fe95eca7248140.tar.gz
gcc-5be6d9d2a9854c05f3c019deb9fe95eca7248140.tar.bz2
c++: Fix up floating point conversion rank comparison for _Float32 and float if float/double are same size [PR115511]
On AVR and SH with some options sizeof (float) == sizeof (double) and the 2 types have the same set of values. http://eel.is/c++draft/conv.rank#2.2 for this says that double still has bigger rank than float and http://eel.is/c++draft/conv.rank#2.2 says that extended type with the same set of values as more than one standard floating point type shall have the same rank as double. I've implemented the latter rule as if (cnt > 1 && mv2 == long_double_type_node) return -2; with the _Float64/double/long double case having same mode case (various targets with -mlong-double-64) in mind. But never thought there are actually targets where float and double are the same, that needs handling too, if cnt > 1 (that is the extended type mv1 has same set of values as 2 or 3 of float/double/long double) and mv2 is float, we need to return 2, because mv1 in that case should have same rank as double and double has bigger rank than float. 2024-06-17 Jakub Jelinek <jakub@redhat.com> PR target/111343 PR c++/115511 * typeck.cc (cp_compare_floating_point_conversion_ranks): If an extended floating point type mv1 has same set of values as more than one standard floating point type and mv2 is float, return 2. * g++.dg/cpp23/ext-floating18.C: New test. (cherry picked from commit 8584c98f370cd91647c184ce58141508ca478a12)
-rw-r--r--gcc/cp/typeck.cc3
-rw-r--r--gcc/testsuite/g++.dg/cpp23/ext-floating18.C26
2 files changed, 29 insertions, 0 deletions
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index a25f862..42578be 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -393,6 +393,9 @@ cp_compare_floating_point_conversion_ranks (tree t1, tree t2)
has higher rank. */
if (cnt > 1 && mv2 == long_double_type_node)
return -2;
+ /* And similarly if t2 is float, t2 has lower rank. */
+ if (cnt > 1 && mv2 == float_type_node)
+ return 2;
/* Otherwise, they have equal rank, but extended types
(other than std::bfloat16_t) have higher subrank.
std::bfloat16_t shouldn't have equal rank to any standard
diff --git a/gcc/testsuite/g++.dg/cpp23/ext-floating18.C b/gcc/testsuite/g++.dg/cpp23/ext-floating18.C
new file mode 100644
index 0000000..ece2546
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/ext-floating18.C
@@ -0,0 +1,26 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do compile { target c++23 } }
+// { dg-options "" }
+// { dg-add-options float32 }
+
+constexpr int foo (float) { return 1; }
+constexpr int foo (double) { return 2; }
+constexpr int foo (long double) { return 3; }
+
+#ifdef __STDCPP_FLOAT32_T__
+#if __FLT_MAX_EXP__ == __FLT32_MAX_EXP__ \
+ && __FLT_MAX_DIG__ == __FLT32_MAX_DIG__
+#if __FLT_MAX_EXP__ == __DBL_MAX_EXP__ \
+ && __FLT_MAX_DIG__ == __DBL_MAX_DIG__
+static_assert (foo (1.0f32) == 2);
+#else
+static_assert (foo (1.0f32) == 1);
+#endif
+#endif
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+#if __DBL_MAX_EXP__ == __FLT64_MAX_EXP__ \
+ && __DBL_MAX_DIG__ == __FLT64_MAX_DIG__
+static_assert (foo (1.0f64) == 2);
+#endif
+#endif