https://github.com/spavloff created https://github.com/llvm/llvm-project/pull/90877
Conversion of floating-point literal to binary representation must be made using constant rounding mode, which can be changed using pragma FENV_ROUND. For example, the literal "0.1F" should be representes by either 0.099999994 or 0.100000001 depending on the rounding direction. >From 5d906b537636ca0d8706a8a888dd78edfbec684f Mon Sep 17 00:00:00 2001 From: Serge Pavlov <sepavl...@gmail.com> Date: Thu, 2 May 2024 22:28:05 +0700 Subject: [PATCH] [clang] Use constant rounding mode for floating literals Conversion of floating-point literal to binary representation must be made using constant rounding mode, which can be changed using pragma FENV_ROUND. For example, the literal "0.1F" should be representes by either 0.099999994 or 0.100000001 depending on the rounding direction. --- clang/include/clang/Lex/LiteralSupport.h | 10 ++++------ clang/lib/Lex/LiteralSupport.cpp | 6 +++--- clang/lib/Sema/SemaExpr.cpp | 3 ++- clang/test/AST/const-fpfeatures.c | 6 ++++++ 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Lex/LiteralSupport.h b/clang/include/clang/Lex/LiteralSupport.h index 2ed42d1c5f9aae..705021fcfa5b11 100644 --- a/clang/include/clang/Lex/LiteralSupport.h +++ b/clang/include/clang/Lex/LiteralSupport.h @@ -118,12 +118,10 @@ class NumericLiteralParser { /// bits of the result and return true. Otherwise, return false. bool GetIntegerValue(llvm::APInt &Val); - /// GetFloatValue - Convert this numeric literal to a floating value, using - /// the specified APFloat fltSemantics (specifying float, double, etc). - /// The optional bool isExact (passed-by-reference) has its value - /// set to true if the returned APFloat can represent the number in the - /// literal exactly, and false otherwise. - llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result); + /// Convert this numeric literal to a floating value, using the specified + /// APFloat fltSemantics (specifying float, double, etc) and rounding mode. + llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result, + llvm::RoundingMode RM); /// GetFixedPointValue - Convert this numeric literal value into a /// scaled integer that represents this value. Returns true if an overflow diff --git a/clang/lib/Lex/LiteralSupport.cpp b/clang/lib/Lex/LiteralSupport.cpp index 9c0cbea5052cb2..3df0391bdda772 100644 --- a/clang/lib/Lex/LiteralSupport.cpp +++ b/clang/lib/Lex/LiteralSupport.cpp @@ -1520,7 +1520,8 @@ bool NumericLiteralParser::GetIntegerValue(llvm::APInt &Val) { } llvm::APFloat::opStatus -NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) { +NumericLiteralParser::GetFloatValue(llvm::APFloat &Result, + llvm::RoundingMode RM) { using llvm::APFloat; unsigned n = std::min(SuffixBegin - ThisTokBegin, ThisTokEnd - ThisTokBegin); @@ -1534,8 +1535,7 @@ NumericLiteralParser::GetFloatValue(llvm::APFloat &Result) { Str = Buffer; } - auto StatusOrErr = - Result.convertFromString(Str, APFloat::rmNearestTiesToEven); + auto StatusOrErr = Result.convertFromString(Str, RM); assert(StatusOrErr && "Invalid floating point representation"); return !errorToBool(StatusOrErr.takeError()) ? *StatusOrErr : APFloat::opInvalidOp; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0cca02c338954a..db96c8692f2516 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3858,7 +3858,8 @@ static Expr *BuildFloatingLiteral(Sema &S, NumericLiteralParser &Literal, using llvm::APFloat; APFloat Val(Format); - APFloat::opStatus result = Literal.GetFloatValue(Val); + APFloat::opStatus result = + Literal.GetFloatValue(Val, S.CurFPFeatures.getRoundingMode()); // Overflow is always an error, but underflow is only an error if // we underflowed to zero (APFloat reports denormals as underflow). diff --git a/clang/test/AST/const-fpfeatures.c b/clang/test/AST/const-fpfeatures.c index 6600ea27405d9c..247245c776fed1 100644 --- a/clang/test/AST/const-fpfeatures.c +++ b/clang/test/AST/const-fpfeatures.c @@ -19,6 +19,9 @@ float FI1u = 0xFFFFFFFFU; float _Complex C1u = C0; // CHECK: @C1u = {{.*}} { float, float } { float 0x3FF0000020000000, float 0x3FF0000020000000 } +float FLu = 0.1F; +// CHECK: @FLu = {{.*}} float 0x3FB9999980000000 + #pragma STDC FENV_ROUND FE_DOWNWARD @@ -35,3 +38,6 @@ float FI1d = 0xFFFFFFFFU; float _Complex C1d = C0; // CHECK: @C1d = {{.*}} { float, float } { float 1.000000e+00, float 1.000000e+00 } + +float FLd = 0.1F; +// CHECK: @FLd = {{.*}} float 0x3FB99999A0000000 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits