From 9e52c43090f8cd980167bbd2719878ae36bcf6b5 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Sat, 6 Jul 2019 21:05:52 +0000 Subject: Treat the range of representable values of floating-point types as [-inf, +inf] not as [-max, +max]. Summary: Prior to r329065, we used [-max, max] as the range of representable values because LLVM's `fptrunc` did not guarantee defined behavior when truncating from a larger floating-point type to a smaller one. Now that has been fixed, we can make clang follow normal IEEE 754 semantics in this regard and take the larger range [-inf, +inf] as the range of representable values. In practice, this affects two parts of the frontend: * the constant evaluator no longer treats floating-point evaluations that result in +-inf as being undefined (because they no longer leave the range of representable values of the type) * UBSan no longer treats conversions to floating-point type that are outside the [-max, +max] range as being undefined In passing, also remove the float-divide-by-zero sanitizer from -fsanitize=undefined, on the basis that while it's undefined per C++ rules (and we disallow it in constant expressions for that reason), it is defined by Clang / LLVM / IEEE 754. Reviewers: rnk, BillyONeal Subscribers: cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D63793 llvm-svn: 365272 --- clang/lib/AST/ExprConstant.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'clang/lib/AST/ExprConstant.cpp') diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 5162eb16794..f01b42e7ff7 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2212,10 +2212,8 @@ static bool HandleFloatToFloatCast(EvalInfo &Info, const Expr *E, APFloat &Result) { APFloat Value = Result; bool ignored; - if (Result.convert(Info.Ctx.getFloatTypeSemantics(DestType), - APFloat::rmNearestTiesToEven, &ignored) - & APFloat::opOverflow) - return HandleOverflow(Info, E, Value, DestType); + Result.convert(Info.Ctx.getFloatTypeSemantics(DestType), + APFloat::rmNearestTiesToEven, &ignored); return true; } @@ -2236,10 +2234,8 @@ static bool HandleIntToFloatCast(EvalInfo &Info, const Expr *E, QualType SrcType, const APSInt &Value, QualType DestType, APFloat &Result) { Result = APFloat(Info.Ctx.getFloatTypeSemantics(DestType), 1); - if (Result.convertFromAPInt(Value, Value.isSigned(), - APFloat::rmNearestTiesToEven) - & APFloat::opOverflow) - return HandleOverflow(Info, E, Value, DestType); + Result.convertFromAPInt(Value, Value.isSigned(), + APFloat::rmNearestTiesToEven); return true; } @@ -2457,11 +2453,19 @@ static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E, LHS.subtract(RHS, APFloat::rmNearestTiesToEven); break; case BO_Div: + // [expr.mul]p4: + // If the second operand of / or % is zero the behavior is undefined. + if (RHS.isZero()) + Info.CCEDiag(E, diag::note_expr_divide_by_zero); LHS.divide(RHS, APFloat::rmNearestTiesToEven); break; } - if (LHS.isInfinity() || LHS.isNaN()) { + // [expr.pre]p4: + // If during the evaluation of an expression, the result is not + // mathematically defined [...], the behavior is undefined. + // FIXME: C++ rules require us to not conform to IEEE 754 here. + if (LHS.isNaN()) { Info.CCEDiag(E, diag::note_constexpr_float_arithmetic) << LHS.isNaN(); return Info.noteUndefinedBehavior(); } -- cgit v1.2.3