[clang] [Clang][C++23] Implement core language changes from P1467R9 extended floating-point types and standard names. (PR #78503)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 17 13:14:07 PST 2024
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
More information about the cfe-commits
mailing list