@@ -132,6 +132,84 @@ template <> struct llvm::DenseMapInfo<llvm::FoldingSetNodeID> {
132132 return LHS == RHS;
133133 }
134134};
135+ constexpr unsigned CXX23FloatRankToIndex(clang::BuiltinType::Kind Kind) {
136+ switch (Kind) {
137+ case clang::BuiltinType::Float16:
138+ return 0;
139+ case clang::BuiltinType::BFloat16:
140+ return 1;
141+ case clang::BuiltinType::Float:
142+ return 2;
143+ case clang::BuiltinType::Double:
144+ return 3;
145+ case clang::BuiltinType::LongDouble:
146+ return 4;
147+ default:
148+ // Both __float128 and __ibm128 are compiler extensions, not extended floating points.
149+ // __float128 also predates the invention of floating-point types.
150+ llvm_unreachable("Not a CXX23+ floating point builtin type");
151+ }
152+ }
153+
154+ // 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}}}};
135213
136214/// \returns The locations that are relevant when searching for Doc comments
137215/// related to \p D.
@@ -1917,6 +1995,10 @@ bool ASTContext::isPromotableIntegerType(QualType T) const {
19171995 return false;
19181996}
19191997
1998+ bool ASTContext::isPromotableFloatingType(QualType T) const {
1999+ return T->getAs<BuiltinType>()->getKind() == BuiltinType::Float;
2000+ }
2001+
19202002bool ASTContext::isAlignmentRequired(const Type *T) const {
19212003 return getTypeInfo(T).AlignRequirement != AlignRequirementKind::None;
19222004}
@@ -7670,27 +7752,69 @@ static FloatingRank getFloatingRank(QualType T) {
76707752 }
76717753}
76727754
7755+ /// C++23 6.8.5 [conv.rank]
76737756/// getFloatingTypeOrder - Compare the rank of the two specified floating
76747757/// point types, ignoring the domain of the type (i.e. 'double' ==
7675- /// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If
7676- /// LHS < RHS, return -1.
7677- int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const {
7758+ /// '_Complex double').
7759+ /// 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
7761+ /// are not subset of each other, return FRCR_Unordered. If LHS == RHS but
7762+ /// LHS has a higher subrank than RHS return FRCR_Equal_Greater_Subrank else
7763+ /// return FRCR_Equal_Lesser_Subrank.
7764+ FloatConvRankCompareResult
7765+ ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const {
7766+ if (LHS->isCXX23FloatingPointType(*this) &&
7767+ RHS->isCXX23FloatingPointType(*this)) {
7768+ BuiltinType::Kind LHSKind;
7769+ BuiltinType::Kind RHSKind;
7770+ if (const auto *CT = LHS->getAs<ComplexType>())
7771+ LHSKind = CT->getElementType()->castAs<BuiltinType>()->getKind();
7772+ else
7773+ LHSKind = LHS->castAs<BuiltinType>()->getKind();
7774+ if (const auto *CT = RHS->getAs<ComplexType>())
7775+ RHSKind = CT->getElementType()->castAs<BuiltinType>()->getKind();
7776+ else
7777+ RHSKind = RHS->castAs<BuiltinType>()->getKind();
7778+ return CXX23FloatingPointConversionRankMap[CXX23FloatRankToIndex(LHSKind)]
7779+ [CXX23FloatRankToIndex(RHSKind)];
7780+ }
7781+
76787782 FloatingRank LHSR = getFloatingRank(LHS);
76797783 FloatingRank RHSR = getFloatingRank(RHS);
76807784
76817785 if (LHSR == RHSR)
7682- return 0 ;
7786+ return FRCR_Equal ;
76837787 if (LHSR > RHSR)
7684- return 1 ;
7685- return -1 ;
7788+ return FRCR_Greater ;
7789+ return FRCR_Lesser ;
76867790}
76877791
7688- int ASTContext::getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const {
7792+ FloatConvRankCompareResult
7793+ ASTContext::getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const {
76897794 if (&getFloatTypeSemantics(LHS) == &getFloatTypeSemantics(RHS))
7690- return 0 ;
7795+ return FRCR_Equal ;
76917796 return getFloatingTypeOrder(LHS, RHS);
76927797}
76937798
7799+ bool ASTContext::doCXX23ExtendedFpTypesRulesApply(QualType T1,
7800+ QualType T2) const {
7801+ return (((T1->isCXX23FloatingPointType(*this) &&
7802+ T2->isCXX23FloatingPointType(*this))) &&
7803+ (T1->isCXX23ExtendedFloatingPointType(*this) ||
7804+ T2->isCXX23ExtendedFloatingPointType(*this)));
7805+ }
7806+
7807+ bool ASTContext::isCXX23SmallerOrUnorderedFloatingPointRank(
7808+ FloatConvRankCompareResult Result) const {
7809+ return (Result == FRCR_Lesser) || (Result == FRCR_Unordered);
7810+ }
7811+
7812+ bool ASTContext::isCXX23EqualFloatingPointRank(
7813+ FloatConvRankCompareResult Result) const {
7814+ return (Result == FRCR_Equal) || (Result == FRCR_Equal_Greater_Subrank) ||
7815+ (Result == FRCR_Equal_Lesser_Subrank);
7816+ }
7817+
76947818/// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1). This
76957819/// routine will assert if passed a built-in type that isn't an integer or enum,
76967820/// or if it is not canonicalized.
@@ -7853,6 +7977,13 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const {
78537977 return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy;
78547978}
78557979
7980+ QualType ASTContext::getPromotedFloatingType(QualType Promotable) const {
7981+ assert(!Promotable.isNull());
7982+ assert(isPromotableFloatingType(Promotable));
7983+ assert(Promotable->getAs<BuiltinType>()->getKind() == BuiltinType::Float);
7984+ return DoubleTy;
7985+ }
7986+
78567987/// Recurses in pointer/array types until it finds an objc retainable
78577988/// type and returns its ownership.
78587989Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const {
0 commit comments