[clang] [llvm] [Clang][C++23] Core language changes from P1467R9 extended floating-point types and standard names. (PR #78503)

Joshua Cranmer via llvm-commits llvm-commits at lists.llvm.org
Mon Jan 6 14:37:54 PST 2025


================
@@ -132,6 +133,70 @@ template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> {
     return LHS == RHS;
   }
 };
+constexpr unsigned CXX23FloatRankToIndex(clang::BuiltinType::Kind Kind) {
+  switch (Kind) {
+  case clang::BuiltinType::Float16:
+    return 0;
+  case clang::BuiltinType::BFloat16:
+    return 1;
+  case clang::BuiltinType::Float:
+    return 2;
+  case clang::BuiltinType::Double:
+    return 3;
+  case clang::BuiltinType::LongDouble:
+    return 4;
+  default:
+    // Both __float128 and __ibm128 are compiler extensions, not extended floating points.
+    // __float128 also predates the invention of floating-point types.
+    llvm_unreachable("Not a CXX23+ floating point builtin type");
+  }
+}
+
+// C++23 6.8.6p2 [conv.rank]
+FloatConvRankCompareResult
+CXX23CompareFpConversionRanks(BuiltinType::Kind LHSKind,
+                              BuiltinType::Kind RHSKind, QualType LHS,
+                              QualType RHS, const ASTContext &Ctx) {
+
+  // Same types.
+  if (LHSKind == RHSKind)
+    return FloatConvRankCompareResult::FRCR_Equal;
+
+  // Special case comparision between float, double and long double.
+  if (LHSKind == BuiltinType::Float && RHSKind == BuiltinType::Double)
+    return FloatConvRankCompareResult::FRCR_Lesser;
+  if (LHSKind == BuiltinType::Double && RHSKind == BuiltinType::Float)
+    return FloatConvRankCompareResult::FRCR_Greater;
+  if (LHSKind == BuiltinType::Float && RHSKind == BuiltinType::LongDouble)
+    return FloatConvRankCompareResult::FRCR_Lesser;
+  if (LHSKind == BuiltinType::LongDouble && RHSKind == BuiltinType::Float)
+    return FloatConvRankCompareResult::FRCR_Greater;
+  if (LHSKind == BuiltinType::Double && RHSKind == BuiltinType::LongDouble)
+    return FloatConvRankCompareResult::FRCR_Lesser;
+  if (LHSKind == BuiltinType::LongDouble && RHSKind == BuiltinType::Double)
+    return FloatConvRankCompareResult::FRCR_Greater;
+
+  const llvm::fltSemantics &LHSSemantics = Ctx.getFloatTypeSemantics(LHS);
+  const llvm::fltSemantics &RHSSemantics = Ctx.getFloatTypeSemantics(RHS);
+
+  bool LHSRepresentableByRHS =
+      llvm::APFloat::isRepresentableBy(LHSSemantics, RHSSemantics);
+  bool RHSRepresentableByLHS =
+      llvm::APFloat::isRepresentableBy(RHSSemantics, LHSSemantics);
----------------
jcranmer-intel wrote:

If you look at the definition of `fltSemantics::isRepresentableBy`, it doesn't precisely match the definition of 2.1, since that requires the set of values of one type to be a proper subset of the other, and the function is only checking finite, nonzero values. That said, the distinction is only going to be relevant for the weird tiny FP types, which I hope do not become extended floating-point types, so it probably doesn't matter.

Where it does matter is I think the `ppc_fp128` semantics return bogus values that don't reflect the reality, so that the conversion rank of `long double` and `_Float16` is going to come out wrong on systems where `long double` is `ppc_fp128`.

https://github.com/llvm/llvm-project/pull/78503


More information about the llvm-commits mailing list