diff options
| author | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-03-19 00:01:12 +0000 |
|---|---|---|
| committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2013-03-19 00:01:12 +0000 |
| commit | 4af40c4083efdc50792dc7eecbb7b7fae713ca12 (patch) | |
| tree | c94b1ca10efb5cf84b1884bc6ee068a27c4a24ac /clang/lib | |
| parent | fc9aad64361fbd887848d190c4320e257a6219ba (diff) | |
| download | bcm5719-llvm-4af40c4083efdc50792dc7eecbb7b7fae713ca12.tar.gz bcm5719-llvm-4af40c4083efdc50792dc7eecbb7b7fae713ca12.zip | |
PR15383: When -fsanitize=float-cast-overflow checks a float-to-int conversion,
it wasn't taking into account that the float should be truncated *before* the
range check happens. Thus (unsigned)-0.99 and (unsigned char)255.9 have defined
behavior and should not be trapped.
llvm-svn: 177362
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/CodeGen/CGExprScalar.cpp | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 56b150ad38e..a75d77747b5 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -585,7 +585,7 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc, } else { // Floating-point to integer or floating-point to floating-point. This has // undefined behavior if the source is +-Inf, NaN, or doesn't fit into the - // destination type. + // destination type (after truncation to an integer for float-to-integer). const llvm::fltSemantics &SrcSema = CGF.getContext().getFloatTypeSemantics(OrigSrcType); APFloat MaxSrc(SrcSema, APFloat::uninitialized); @@ -600,14 +600,22 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc, APFloat::opOverflow) // Don't need an overflow check for lower bound. Just check for // -Inf/NaN. - MinSrc = APFloat::getLargest(SrcSema, true); + MinSrc = APFloat::getInf(SrcSema, true); + else + // Find the largest value which is too small to represent (before + // truncation toward zero). + MinSrc.subtract(APFloat(SrcSema, 1), APFloat::rmTowardNegative); APSInt Max = APSInt::getMaxValue(Width, Unsigned); if (MaxSrc.convertFromAPInt(Max, !Unsigned, APFloat::rmTowardZero) & APFloat::opOverflow) // Don't need an overflow check for upper bound. Just check for // +Inf/NaN. - MaxSrc = APFloat::getLargest(SrcSema, false); + MaxSrc = APFloat::getInf(SrcSema, false); + else + // Find the smallest value which is too large to represent (before + // truncation toward zero). + MaxSrc.add(APFloat(SrcSema, 1), APFloat::rmTowardPositive); } else { const llvm::fltSemantics &DstSema = CGF.getContext().getFloatTypeSemantics(DstType); @@ -634,11 +642,19 @@ void ScalarExprEmitter::EmitFloatConversionCheck(Value *OrigSrc, MaxSrc.convert(Sema, APFloat::rmTowardZero, &IsInexact); } - llvm::Value *GE = - Builder.CreateFCmpOGE(Src, llvm::ConstantFP::get(VMContext, MinSrc)); - llvm::Value *LE = - Builder.CreateFCmpOLE(Src, llvm::ConstantFP::get(VMContext, MaxSrc)); - Check = Builder.CreateAnd(GE, LE); + if (isa<llvm::IntegerType>(DstTy)) { + llvm::Value *GE = + Builder.CreateFCmpOGT(Src, llvm::ConstantFP::get(VMContext, MinSrc)); + llvm::Value *LE = + Builder.CreateFCmpOLT(Src, llvm::ConstantFP::get(VMContext, MaxSrc)); + Check = Builder.CreateAnd(GE, LE); + } else { + llvm::Value *GE = + Builder.CreateFCmpOGE(Src, llvm::ConstantFP::get(VMContext, MinSrc)); + llvm::Value *LE = + Builder.CreateFCmpOLE(Src, llvm::ConstantFP::get(VMContext, MaxSrc)); + Check = Builder.CreateAnd(GE, LE); + } } // FIXME: Provide a SourceLocation. |

