6565#include "clang/Basic/TargetInfo.h"
6666#include "clang/Basic/XRayLists.h"
6767#include "llvm/ADT/APFixedPoint.h"
68+ #include "llvm/ADT/APFloat.h"
6869#include "llvm/ADT/APInt.h"
6970#include "llvm/ADT/APSInt.h"
7071#include "llvm/ADT/ArrayRef.h"
@@ -152,64 +153,50 @@ constexpr unsigned CXX23FloatRankToIndex(clang::BuiltinType::Kind Kind) {
152153}
153154
154155// C++23 6.8.6p2 [conv.rank]
155- // Grid to determine the rank of a floating point type when compared with
156- // another floating point type.
157- constexpr std::array<std::array<FloatConvRankCompareResult, 5>, 5>
158- CXX23FloatingPointConversionRankMap = {
159- {// Float16 x Float16
160- // Float16 x BFloat16
161- // Float16 x Float
162- // Float16 x Double
163- // Float16 x LongDouble
164- {{FloatConvRankCompareResult::FRCR_Equal,
165- FloatConvRankCompareResult::FRCR_Unordered,
166- FloatConvRankCompareResult::FRCR_Lesser,
167- FloatConvRankCompareResult::FRCR_Lesser,
168- FloatConvRankCompareResult::FRCR_Lesser}},
169-
170- // BFloat16 x Float16
171- // BFloat16 x BFloat16
172- // BFloat16 x Float
173- // BFloat16 x Double
174- // BFloat16 x LongDouble
175- {{FloatConvRankCompareResult::FRCR_Unordered,
176- FloatConvRankCompareResult::FRCR_Equal,
177- FloatConvRankCompareResult::FRCR_Lesser,
178- FloatConvRankCompareResult::FRCR_Lesser,
179- FloatConvRankCompareResult::FRCR_Lesser}},
180-
181- // Float x Float16
182- // Float x BFloat16
183- // Float x Float
184- // Float x Double
185- // Float x LongDouble
186- {{FloatConvRankCompareResult::FRCR_Greater,
187- FloatConvRankCompareResult::FRCR_Greater,
188- FloatConvRankCompareResult::FRCR_Equal,
189- FloatConvRankCompareResult::FRCR_Lesser,
190- FloatConvRankCompareResult::FRCR_Lesser}},
191-
192- // Double x Float16
193- // Double x BFloat16
194- // Double x Float
195- // Double x Double
196- // Double x LongDouble
197- {{FloatConvRankCompareResult::FRCR_Greater,
198- FloatConvRankCompareResult::FRCR_Greater,
199- FloatConvRankCompareResult::FRCR_Greater,
200- FloatConvRankCompareResult::FRCR_Equal,
201- FloatConvRankCompareResult::FRCR_Lesser}},
202-
203- // LongDouble x Float16
204- // LongDouble x BFloat16
205- // LongDouble x Float
206- // LongDouble x Double
207- // LongDouble x LongDouble
208- {{FloatConvRankCompareResult::FRCR_Greater,
209- FloatConvRankCompareResult::FRCR_Greater,
210- FloatConvRankCompareResult::FRCR_Greater,
211- FloatConvRankCompareResult::FRCR_Greater,
212- FloatConvRankCompareResult::FRCR_Equal}}}};
156+ FloatConvRankCompareResult
157+ CXX23CompareFpConversionRanks(BuiltinType::Kind LHSKind,
158+ BuiltinType::Kind RHSKind, QualType LHS,
159+ QualType RHS, const ASTContext &Ctx) {
160+
161+ // Same types.
162+ if (LHSKind == RHSKind)
163+ return FloatConvRankCompareResult::FRCR_Equal;
164+
165+ // Special case comparision between float, double and long double.
166+ if (LHSKind == BuiltinType::Float && RHSKind == BuiltinType::Double)
167+ return FloatConvRankCompareResult::FRCR_Lesser;
168+ if (LHSKind == BuiltinType::Double && RHSKind == BuiltinType::Float)
169+ return FloatConvRankCompareResult::FRCR_Greater;
170+ if (LHSKind == BuiltinType::Float && RHSKind == BuiltinType::LongDouble)
171+ return FloatConvRankCompareResult::FRCR_Lesser;
172+ if (LHSKind == BuiltinType::LongDouble && RHSKind == BuiltinType::Float)
173+ return FloatConvRankCompareResult::FRCR_Greater;
174+ if (LHSKind == BuiltinType::Double && RHSKind == BuiltinType::LongDouble)
175+ return FloatConvRankCompareResult::FRCR_Lesser;
176+ if (LHSKind == BuiltinType::LongDouble && RHSKind == BuiltinType::Double)
177+ return FloatConvRankCompareResult::FRCR_Greater;
178+
179+ const llvm::fltSemantics &LHSSemantics = Ctx.getFloatTypeSemantics(LHS);
180+ const llvm::fltSemantics &RHSSemantics = Ctx.getFloatTypeSemantics(RHS);
181+
182+ bool LHSRepresentableByRHS =
183+ llvm::APFloat::isRepresentableBy(LHSSemantics, RHSSemantics);
184+ bool RHSRepresentableByLHS =
185+ llvm::APFloat::isRepresentableBy(RHSSemantics, LHSSemantics);
186+
187+ if (LHSRepresentableByRHS && !RHSRepresentableByLHS)
188+ return FloatConvRankCompareResult::FRCR_Lesser;
189+ if (!LHSRepresentableByRHS && RHSRepresentableByLHS)
190+ return FloatConvRankCompareResult::FRCR_Greater;
191+
192+ if (!LHSRepresentableByRHS && !RHSRepresentableByLHS)
193+ return FloatConvRankCompareResult::FRCR_Unordered;
194+
195+ // Both types are representable by each other, compare sub-ranks, however, as
196+ // of today this scenario doesn't exist.
197+ llvm_unreachable(
198+ "Both types are representable by each other, compare sub-ranks");
199+ }
213200
214201/// \returns The locations that are relevant when searching for Doc comments
215202/// related to \p D.
@@ -7757,7 +7744,7 @@ static FloatingRank getFloatingRank(QualType T) {
77577744/// point types, ignoring the domain of the type (i.e. 'double' ==
77587745/// '_Complex double').
77597746/// If LHS > RHS, return FRCR_Greater. If LHS == RHS, return FRCR_Equal. If
7760- /// LHS < RHS, return FRCR_Lesser. If the values representedable by the two
7747+ /// LHS < RHS, return FRCR_Lesser. If the values representable by the two
77617748/// are not subset of each other, return FRCR_Unordered. If LHS == RHS but
77627749/// LHS has a higher subrank than RHS return FRCR_Equal_Greater_Subrank else
77637750/// return FRCR_Equal_Lesser_Subrank.
@@ -7775,8 +7762,7 @@ ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const {
77757762 RHSKind = CT->getElementType()->castAs<BuiltinType>()->getKind();
77767763 else
77777764 RHSKind = RHS->castAs<BuiltinType>()->getKind();
7778- return CXX23FloatingPointConversionRankMap[CXX23FloatRankToIndex(LHSKind)]
7779- [CXX23FloatRankToIndex(RHSKind)];
7765+ return CXX23CompareFpConversionRanks(LHSKind, RHSKind, LHS, RHS, *this);
77807766 }
77817767
77827768 FloatingRank LHSR = getFloatingRank(LHS);
0 commit comments