llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-static-analyzer-1 @llvm/pr-subscribers-clang Author: M. Zeeshan Siddiqui (codemzs) <details> <summary>Changes</summary> Implements Core language changes based on [P1467R9](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p1467r9.html) Extended floating-point types and standard names. As per the proposal's definition the following two types are marked as extended floating point: `Float16` (aka `_Float16`) and `Bfloat16` (aka `decltype (0.0bf16)` or `__bf16`). Future work can extend this to support other floating-point types such as `Float32`, `Float64`, and `Float128`. RFC: https://discourse.llvm.org/t/rfc-c-23-p1467r9-extended-floating-point-types-and-standard-names/70033 This pull request is a carryover from the now offline phabricator differential revision: https://reviews.llvm.org/D149573 --- Patch is 86.64 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/78503.diff 18 Files Affected: - (modified) clang/include/clang/AST/ASTContext.h (+41-7) - (modified) clang/include/clang/AST/Type.h (+7) - (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+1) - (modified) clang/include/clang/Lex/LiteralSupport.h (+1) - (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h (+4-3) - (modified) clang/lib/AST/ASTContext.cpp (+129-8) - (modified) clang/lib/AST/StmtPrinter.cpp (+1) - (modified) clang/lib/AST/Type.cpp (+27) - (modified) clang/lib/Frontend/InitPreprocessor.cpp (+5-1) - (modified) clang/lib/Lex/LiteralSupport.cpp (+17) - (modified) clang/lib/Sema/Sema.cpp (+17) - (modified) clang/lib/Sema/SemaCast.cpp (+13) - (modified) clang/lib/Sema/SemaChecking.cpp (+11-6) - (modified) clang/lib/Sema/SemaExpr.cpp (+47-13) - (modified) clang/lib/Sema/SemaOverload.cpp (+79-2) - (added) clang/test/CodeGenCXX/cxx23-fp-ext-std-names-p1467r9.cpp (+499) - (added) clang/test/CodeGenCXX/cxx23-vector-bfloat16.cpp (+67) - (added) clang/test/Sema/cxx23-fp-ext-std-names-p1467r9.cpp (+505) ``````````diff diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 3e46a5da3fc043..beec40b4a8197b 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -52,6 +52,16 @@ template <typename T, unsigned N> class SmallPtrSet; namespace clang { +// Conversion ranks introduced in C++23 6.8.6p2 [conv.rank] +enum FloatingRankCompareResult { + FRCR_Unordered, + FRCR_Lesser, + FRCR_Greater, + FRCR_Equal, + FRCR_Equal_Lesser_Subrank, + FRCR_Equal_Greater_Subrank, +}; + class APValue; class ASTMutationListener; class ASTRecordLayout; @@ -1105,8 +1115,8 @@ class ASTContext : public RefCountedBase<ASTContext> { CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy, SatUnsignedLongFractTy; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON - CanQualType BFloat16Ty; - CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 + CanQualType BFloat16Ty; // [C++23 6.8.3p5][basic.extended.fp] + CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 and [C++23 6.8.3p5][basic.extended.fp] CanQualType VoidPtrTy, NullPtrTy; CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; CanQualType BuiltinFnTy; @@ -2803,14 +2813,38 @@ class ASTContext : public RefCountedBase<ASTContext> { /// Compare the rank of the two specified floating point types, /// ignoring the domain of the type (i.e. 'double' == '_Complex double'). /// - /// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If - /// \p LHS < \p RHS, return -1. - int getFloatingTypeOrder(QualType LHS, QualType RHS) const; + /// If \p LHS > \p RHS, returns FRCR_Greater. If \p LHS == \p RHS, returns + /// FRCR_Equal. If \p LHS < \p RHS, return FRCR_Lesser. If \p LHS and \p RHS + /// are unordered, return FRCR_Unordered. If \p LHS and \p RHS are equal but + /// the subrank of \p LHS is greater than \p RHS, return + /// FRCR_Equal_Greater_Subrank. If \p LHS and \p RHS are equal but the subrank + /// of \p LHS is less than \p RHS, return FRCR_Equal_Lesser_Subrank. Subrank + /// and Unordered comparison were introduced in C++23. + FloatingRankCompareResult getFloatingTypeOrder(QualType LHS, + QualType RHS) const; /// Compare the rank of two floating point types as above, but compare equal /// if both types have the same floating-point semantics on the target (i.e. - /// long double and double on AArch64 will return 0). - int getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const; + /// long double and double on AArch64 will return FRCR_Equal). + FloatingRankCompareResult getFloatingTypeSemanticOrder(QualType LHS, + QualType RHS) const; + + /// C++23 6.8.2p12 [basic.fundamental] + /// Checks if extended floating point rules apply to a pair of types. + /// It returns true if both the types are C++23 floating point types and + /// at least one of them is a C++23 extended floating point type. It returns + /// false for pairs of standard C++23 floating point types. + bool doCXX23ExtendedFpTypesRulesApply(QualType T1, QualType T2) const; + + /// C++23 6.8.2p12 [basic.fundamental] + /// Returns true if \p Result is FRCR_Lesser or FRCR_Unordered rank. + bool + isCXX23SmallerOrUnorderedFloatingPointRank(FloatingRankCompareResult Result) const; + + /// C++23 6.8.2p12 [basic.fundamental] + /// Returns true if \p Result is FRCR_Equal, FRCR_Equal_Lesser_Subrank or + /// FRCR_Equal_Greater_Subrank. + bool isCXX23EqualFloatingPointRank(FloatingRankCompareResult Result) const; unsigned getTargetAddressSpace(LangAS AS) const; diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index a7efe78591635e..5dc3ac9e3c7498 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -2242,6 +2242,13 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase { bool isComplexType() const; // C99 6.2.5p11 (complex) bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int. bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) + /// C++23 6.8.2p12 [basic.fundamental] (standard floating point + extended + /// floating point) + bool isCXX23FloatingPointType(const ASTContext &Ctx) const; + /// C++23 6.8.2p12 [basic.fundamental] (standard floating point) + bool isCXX23StandardFloatingPointType(const ASTContext &Ctx) const; + /// C++23 6.8.2p12 [basic.fundamental] (extended floating point) + bool isCXX23ExtendedFloatingPointType(const ASTContext &Ctx) const; bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661 bool isBFloat16Type() const; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 03b0122d1c08f7..d635ea14004284 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -8982,6 +8982,7 @@ def err_cast_pointer_to_non_pointer_int : Error< def err_nullptr_cast : Error< "cannot cast an object of type %select{'nullptr_t' to %1|%1 to 'nullptr_t'}0" >; +def err_cxx23_invalid_implicit_floating_point_cast : Error<"floating point cast results in loss of precision">; def err_typecheck_expect_scalar_operand : Error< "operand of type %0 where arithmetic or pointer type is required">; def err_typecheck_cond_incompatible_operands : Error< diff --git a/clang/include/clang/Lex/LiteralSupport.h b/clang/include/clang/Lex/LiteralSupport.h index 643ddbdad8c87d..c1301e56af97f3 100644 --- a/clang/include/clang/Lex/LiteralSupport.h +++ b/clang/include/clang/Lex/LiteralSupport.h @@ -81,6 +81,7 @@ class NumericLiteralParser { bool isFract : 1; // 1.0hr/r/lr/uhr/ur/ulr bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk bool isBitInt : 1; // 1wb, 1uwb (C23) + bool isBFloat16 : 1; // 1.0bf uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h index fcc9c02999b3b0..b2cd4cd7c76f12 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONV_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONV_H +#include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" @@ -775,11 +776,11 @@ class SMTConv { // If we have two real floating types, convert the smaller operand to the // bigger result // Note: Safe to skip updating bitwidth because this must terminate - int order = Ctx.getFloatingTypeOrder(LTy, RTy); - if (order > 0) { + FloatingRankCompareResult order = Ctx.getFloatingTypeOrder(LTy, RTy); + if ((order == FRCR_Greater) || (order == FRCR_Equal_Greater_Subrank)) { RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth); RTy = LTy; - } else if (order == 0) { + } else if ((order == FRCR_Equal) || (order == FRCR_Equal_Lesser_Subrank)) { LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth); LTy = RTy; } else { diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index d9cefcaa84d7e5..989dee9fca148d 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -112,6 +112,85 @@ enum FloatingRank { Ibm128Rank }; +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] +// Grid to determine the rank of a floating point type when compared with +// another floating point type. +constexpr std::array<std::array<FloatingRankCompareResult, 5>, 5> + CXX23FloatingPointConversionRankMap = { + {// Float16 x Float16 + // Float16 x BFloat16 + // Float16 x Float + // Float16 x Double + // Float16 x LongDouble + {{FloatingRankCompareResult::FRCR_Equal, + FloatingRankCompareResult::FRCR_Unordered, + FloatingRankCompareResult::FRCR_Lesser, + FloatingRankCompareResult::FRCR_Lesser, + FloatingRankCompareResult::FRCR_Lesser}}, + + // BFloat16 x Float16 + // BFloat16 x BFloat16 + // BFloat16 x Float + // BFloat16 x Double + // BFloat16 x LongDouble + {{FloatingRankCompareResult::FRCR_Unordered, + FloatingRankCompareResult::FRCR_Equal, + FloatingRankCompareResult::FRCR_Lesser, + FloatingRankCompareResult::FRCR_Lesser, + FloatingRankCompareResult::FRCR_Lesser}}, + + // Float x Float16 + // Float x BFloat16 + // Float x Float + // Float x Double + // Float x LongDouble + {{FloatingRankCompareResult::FRCR_Greater, + FloatingRankCompareResult::FRCR_Greater, + FloatingRankCompareResult::FRCR_Equal, + FloatingRankCompareResult::FRCR_Lesser, + FloatingRankCompareResult::FRCR_Lesser}}, + + // Double x Float16 + // Double x BFloat16 + // Double x Float + // Double x Double + // Double x LongDouble + {{FloatingRankCompareResult::FRCR_Greater, + FloatingRankCompareResult::FRCR_Greater, + FloatingRankCompareResult::FRCR_Greater, + FloatingRankCompareResult::FRCR_Equal, + FloatingRankCompareResult::FRCR_Lesser}}, + + // LongDouble x Float16 + // LongDouble x BFloat16 + // LongDouble x Float + // LongDouble x Double + // LongDouble x LongDouble + {{FloatingRankCompareResult::FRCR_Greater, + FloatingRankCompareResult::FRCR_Greater, + FloatingRankCompareResult::FRCR_Greater, + FloatingRankCompareResult::FRCR_Greater, + FloatingRankCompareResult::FRCR_Equal}}}}; + /// \returns The locations that are relevant when searching for Doc comments /// related to \p D. static SmallVector<SourceLocation, 2> @@ -7007,27 +7086,69 @@ static FloatingRank getFloatingRank(QualType T) { } } +/// C++23 6.8.5 [conv.rank] /// getFloatingTypeOrder - Compare the rank of the two specified floating /// point types, ignoring the domain of the type (i.e. 'double' == -/// '_Complex double'). If LHS > RHS, return 1. If LHS == RHS, return 0. If -/// LHS < RHS, return -1. -int ASTContext::getFloatingTypeOrder(QualType LHS, QualType RHS) const { +/// '_Complex double'). +/// If LHS > RHS, return FRCR_Greater. If LHS == RHS, return FRCR_Equal. If +/// LHS < RHS, return FRCR_Lesser. If the values representedable by the two +/// are not subset of each other, return FRCR_Unordered. If LHS == RHS but +/// LHS has a higher subrank than RHS return FRCR_Equal_Greater_Subrank else +/// return FRCR_Equal_Lesser_Subrank. +FloatingRankCompareResult ASTContext::getFloatingTypeOrder(QualType LHS, + QualType RHS) const { + if (LHS->isCXX23FloatingPointType(*this) && + RHS->isCXX23FloatingPointType(*this)) { + BuiltinType::Kind LHSKind; + BuiltinType::Kind RHSKind; + if (const auto *CT = LHS->getAs<ComplexType>()) + LHSKind = CT->getElementType()->castAs<BuiltinType>()->getKind(); + else + LHSKind = LHS->castAs<BuiltinType>()->getKind(); + if (const auto *CT = RHS->getAs<ComplexType>()) + RHSKind = CT->getElementType()->castAs<BuiltinType>()->getKind(); + else + RHSKind = RHS->castAs<BuiltinType>()->getKind(); + return CXX23FloatingPointConversionRankMap[CXX23FloatRankToIndex(LHSKind)] + [CXX23FloatRankToIndex(RHSKind)]; + } + FloatingRank LHSR = getFloatingRank(LHS); FloatingRank RHSR = getFloatingRank(RHS); if (LHSR == RHSR) - return 0; + return FRCR_Equal; if (LHSR > RHSR) - return 1; - return -1; + return FRCR_Greater; + return FRCR_Lesser; } -int ASTContext::getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const { +FloatingRankCompareResult +ASTContext::getFloatingTypeSemanticOrder(QualType LHS, QualType RHS) const { if (&getFloatTypeSemantics(LHS) == &getFloatTypeSemantics(RHS)) - return 0; + return FRCR_Equal; return getFloatingTypeOrder(LHS, RHS); } +bool ASTContext::doCXX23ExtendedFpTypesRulesApply(QualType T1, + QualType T2) const { + return (((T1->isCXX23FloatingPointType(*this) && + T2->isCXX23FloatingPointType(*this))) && + (T1->isCXX23ExtendedFloatingPointType(*this) || + T2->isCXX23ExtendedFloatingPointType(*this))); +} + +bool ASTContext::isCXX23SmallerOrUnorderedFloatingPointRank( + FloatingRankCompareResult Result) const { + return (Result == FRCR_Lesser) || (Result == FRCR_Unordered); +} + +bool ASTContext::isCXX23EqualFloatingPointRank( + FloatingRankCompareResult Result) const { + return (Result == FRCR_Equal) || (Result == FRCR_Equal_Greater_Subrank) || + (Result == FRCR_Equal_Lesser_Subrank); +} + /// getIntegerRank - Return an integer conversion rank (C99 6.3.1.1p1). This /// routine will assert if passed a built-in type that isn't an integer or enum, /// or if it is not canonicalized. diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index c04cb313c3387a..b762b581857abf 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -1358,6 +1358,7 @@ static void PrintFloatingLiteral(raw_ostream &OS, FloatingLiteral *Node, case BuiltinType::Float: OS << 'F'; break; case BuiltinType::LongDouble: OS << 'L'; break; case BuiltinType::Float128: OS << 'Q'; break; + case BuiltinType::BFloat16: OS << "BF16"; break; } } diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index b419fc8836b032..d15b04e46a9c5c 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -2192,6 +2192,33 @@ bool Type::isFloatingType() const { return false; } +bool Type::isCXX23StandardFloatingPointType(const ASTContext &Ctx) const { + if (!Ctx.getLangOpts().CPlusPlus23) + return false; + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() >= BuiltinType::Float && + BT->getKind() <= BuiltinType::LongDouble; + if (const auto *CT = dyn_cast<ComplexType>(CanonicalType)) + return CT->getElementType()->isCXX23StandardFloatingPointType(Ctx); + return false; +} + +bool Type::isCXX23ExtendedFloatingPointType(const ASTContext &Ctx) const { + if (!Ctx.getLangOpts().CPlusPlus23) + return false; + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Float16 || + BT->getKind() == BuiltinType::BFloat16; + if (const auto *CT = dyn_cast<ComplexType>(CanonicalType)) + return CT->getElementType()->isCXX23ExtendedFloatingPointType(Ctx); + return false; +} + +bool Type::isCXX23FloatingPointType(const ASTContext &Ctx) const { + return isCXX23StandardFloatingPointType(Ctx) || + isCXX23ExtendedFloatingPointType(Ctx); +} + bool Type::hasFloatingRepresentation() const { if (const auto *VT = dyn_cast<VectorType>(CanonicalType)) return VT->getElementType()->isFloatingType(); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index d83128adb511ef..f22ba2f5eae8f2 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -453,8 +453,12 @@ static void InitializeStandardPredefinedMacros(const TargetInfo &TI, if (LangOpts.CPlusPlus26) // FIXME: Use correct value for C++26. Builder.defineMacro("__cplusplus", "202400L"); - else if (LangOpts.CPlusPlus23) + else if (LangOpts.CPlusPlus23) { Builder.defineMacro("__cplusplus", "202302L"); + // [C++23] 15.11p2 [cpp.predefined] + Builder.defineMacro("__STDCPP_FLOAT16_T__", "1"); + Builder.defineMacro("__STDCPP_BFLOAT16_T__", "1"); + } // [C++20] The integer literal 202002L. else if (LangOpts.CPlusPlus20) Builder.defineMacro("__cplusplus", "202002L"); diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index 0a78638f680511..21734c2c19fb54 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -925,6 +925,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, isAccum = false; hadError = false; isBitInt = false; + isBFloat16 = false; // This routine assumes that the range begin/end matches the regex for integer // and FP constants (specifically, the 'pp-number' regex), and assumes that @@ -1029,6 +1030,21 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, isFloat = true; continue; // Success. + // C++23 5.13.4 [lex.fcon] + case 'b': + case 'B': + if (!isFPConstant) + break; // Error for integer constant. + if (s + 3 < ThisTokEnd && (s[1] == 'f' || s[1] == 'F') && s[2] == '1' && + s[3] == '6') { + if (HasSize) + break; + HasSize = true; + s += 3; + isBFloat16 = true; + continue; + } + break; case 'q': // FP Suffix for "__float128" case 'Q': if (!isFPConstant) break; // Error for integer constant. @@ -1161,6 +1177,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling, saw_fixed_point_suffix = false; isFract = false; isAccum = false; + isBFloat16 = false; } saw_ud_suffix = true; diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index cafbecebc8a119..e8aeca735260c0 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -700,6 +700,23 @@ ExprResult Sema::ImpCastExprToType(Expr *E, QualType Ty, } } + // C++23 7.3.10 [conv.double] + // A prvalue of floating-point type can be converted to a prvalue of another + // floating-point type with a greater or equal conversion rank ([conv.rank]). + // A prvalue of standard floating-point type can be converted to a prvalue of + // another standard floating-point type + if (Context.doCXX23ExtendedFpTypesRulesApply(ExprTy, TypeTy) && + Kind == CK_FloatingCast && E->isPRValue() && + (CCK == CCK_ImplicitConversion)) { + if (Context.isCXX23SmallerOrUnorderedFloatingPointRank( + Context.getFloatingTypeOrder(TypeTy, ExprTy))) { + Diag(E->getExprLoc(), + diag::err_cxx23_invalid_implicit_floating_point_cast) + << E->getSourceRange(); + return ExprError(); + } + } + if (ImplicitCastExpr *ImpCast = dyn_cast<ImplicitCastExpr>(E)) { if (ImpCast->getCastKind() == Kind && (!BasePath || BasePath->empty())) { ImpCast->setType(Ty); diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 9d85568d97b2d2..c905d11b8af82a 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -1386,6 +1386,19 @@ static TryCastResult TryStaticCast(Sema &Self, ExprResult &SrcExpr, } } + // [expr.static.cast] 7.6.1.9p11, A prvalue of floating-point type can + // be explicitly converted to any other floating-point type. + // Conversion between fp16 and bf16 is not supported yet. + if (SrcExpr.get()->isPRValue() && + Self.Context.doCXX23ExtendedFpTypesRulesApply(DestType, SrcType)) { + // FIXME: Support for cast between fp16 and bf16 doesn't exist yet. + if (!((DestType->isBFloat16Type() || DestType->isFloat16Type()) && + (SrcType->isBFloat16Type() || SrcType->isFlo... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/78503 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits