Hi!

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.

Bootstrapped/regtested on x86_64-linux and i686-linux and checked with
a cross-compiler to avr-none on the testcase, which previously ICEd because
the function returned _Float32 and float have the same rank, just different
subrank and for _Float32 vs. double also returned they have the same rank.
Committed to trunk as obvious, will backport to 14/13 soon.

2024-06-17  Jakub Jelinek  <ja...@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.

--- gcc/cp/typeck.cc.jj 2024-06-04 13:19:03.755604346 +0200
+++ gcc/cp/typeck.cc    2024-06-17 10:32:02.063088961 +0200
@@ -393,6 +393,9 @@ cp_compare_floating_point_conversion_ran
      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
--- gcc/testsuite/g++.dg/cpp23/ext-floating18.C.jj      2024-06-17 
18:39:01.740020581 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating18.C 2024-06-17 18:47:19.152779782 
+0200
@@ -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

        Jakub

Reply via email to