Index: cfe/trunk/docs/UndefinedBehaviorSanitizer.rst =================================================================== --- cfe/trunk/docs/UndefinedBehaviorSanitizer.rst +++ cfe/trunk/docs/UndefinedBehaviorSanitizer.rst @@ -83,9 +83,13 @@ type. - ``-fsanitize=float-cast-overflow``: Conversion to, from, or between floating-point types which would overflow the - destination. + destination. Because the range of representable values for all + floating-point types supported by Clang is [-inf, +inf], the only + cases detected are conversions from floating point to integer types. - ``-fsanitize=float-divide-by-zero``: Floating point division by - zero. + zero. This is undefined per the C and C++ standards, but is defined + by Clang (and by ISO/IEC/IEEE 60559 / IEEE 754) as producing either an + infinity or NaN value, so is not included in ``-fsanitize=undefined``. - ``-fsanitize=function``: Indirect call of a function through a function pointer of the wrong type (Darwin/Linux, C++ and x86/x86_64 only). @@ -163,8 +167,8 @@ You can also use the following check groups: - ``-fsanitize=undefined``: All of the checks listed above other than - ``unsigned-integer-overflow``, ``implicit-conversion`` and the - ``nullability-*`` group of checks. + ``float-divide-by-zero``, ``unsigned-integer-overflow``, + ``implicit-conversion``, and the ``nullability-*`` group of checks. - ``-fsanitize=undefined-trap``: Deprecated alias of ``-fsanitize=undefined``. - ``-fsanitize=implicit-integer-truncation``: Catches lossy integral @@ -174,16 +178,16 @@ conversions that change the arithmetic value of the integer. Enables ``implicit-signed-integer-truncation`` and ``implicit-integer-sign-change``. - ``-fsanitize=implicit-conversion``: Checks for suspicious - behaviour of implicit conversions. Enables + behavior of implicit conversions. Enables ``implicit-unsigned-integer-truncation``, - ``implicit-signed-integer-truncation`` and + ``implicit-signed-integer-truncation``, and ``implicit-integer-sign-change``. - ``-fsanitize=integer``: Checks for undefined or suspicious integer behavior (e.g. unsigned integer overflow). Enables ``signed-integer-overflow``, ``unsigned-integer-overflow``, ``shift``, ``integer-divide-by-zero``, ``implicit-unsigned-integer-truncation``, - ``implicit-signed-integer-truncation`` and + ``implicit-signed-integer-truncation``, and ``implicit-integer-sign-change``. - ``-fsanitize=nullability``: Enables ``nullability-arg``, ``nullability-assign``, and ``nullability-return``. While violating Index: cfe/trunk/include/clang/Basic/Sanitizers.def =================================================================== --- cfe/trunk/include/clang/Basic/Sanitizers.def +++ cfe/trunk/include/clang/Basic/Sanitizers.def @@ -130,7 +130,7 @@ // ABI or address space layout implications, and only catch undefined behavior. SANITIZER_GROUP("undefined", Undefined, Alignment | Bool | Builtin | ArrayBounds | Enum | - FloatCastOverflow | FloatDivideByZero | + FloatCastOverflow | IntegerDivideByZero | NonnullAttribute | Null | ObjectSize | PointerOverflow | Return | ReturnsNonnullAttribute | Shift | SignedIntegerOverflow | Unreachable | VLABound | Function | Index: cfe/trunk/lib/AST/ExprConstant.cpp =================================================================== --- cfe/trunk/lib/AST/ExprConstant.cpp +++ cfe/trunk/lib/AST/ExprConstant.cpp @@ -2212,10 +2212,8 @@ 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 @@ 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 @@ 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(); } Index: cfe/trunk/lib/CodeGen/CGExprScalar.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGExprScalar.cpp +++ cfe/trunk/lib/CodeGen/CGExprScalar.cpp @@ -313,7 +313,7 @@ /// boolean (i1) truth value. This is equivalent to "Val != 0". Value *EmitConversionToBool(Value *Src, QualType DstTy); - /// Emit a check that a conversion to or from a floating-point type does not + /// Emit a check that a conversion from a floating-point type does not /// overflow. void EmitFloatConversionCheck(Value *OrigSrc, QualType OrigSrcType, Value *Src, QualType SrcType, QualType DstType, @@ -864,128 +864,63 @@ void ScalarExprEmitter::EmitFloatConversionCheck( Value *OrigSrc, QualType OrigSrcType, Value *Src, QualType SrcType, QualType DstType, llvm::Type *DstTy, SourceLocation Loc) { + assert(SrcType->isFloatingType() && "not a conversion from floating point"); + if (!isa(DstTy)) + return; + CodeGenFunction::SanitizerScope SanScope(&CGF); using llvm::APFloat; using llvm::APSInt; - llvm::Type *SrcTy = Src->getType(); - llvm::Value *Check = nullptr; - if (llvm::IntegerType *IntTy = dyn_cast(SrcTy)) { - // Integer to floating-point. This can fail for unsigned short -> __half - // or unsigned __int128 -> float. - assert(DstType->isFloatingType()); - bool SrcIsUnsigned = OrigSrcType->isUnsignedIntegerOrEnumerationType(); - - APFloat LargestFloat = - APFloat::getLargest(CGF.getContext().getFloatTypeSemantics(DstType)); - APSInt LargestInt(IntTy->getBitWidth(), SrcIsUnsigned); - - bool IsExact; - if (LargestFloat.convertToInteger(LargestInt, APFloat::rmTowardZero, - &IsExact) != APFloat::opOK) - // The range of representable values of this floating point type includes - // all values of this integer type. Don't need an overflow check. - return; + const llvm::fltSemantics &SrcSema = + CGF.getContext().getFloatTypeSemantics(OrigSrcType); - llvm::Value *Max = llvm::ConstantInt::get(VMContext, LargestInt); - if (SrcIsUnsigned) - Check = Builder.CreateICmpULE(Src, Max); - else { - llvm::Value *Min = llvm::ConstantInt::get(VMContext, -LargestInt); - llvm::Value *GE = Builder.CreateICmpSGE(Src, Min); - llvm::Value *LE = Builder.CreateICmpSLE(Src, Max); - Check = Builder.CreateAnd(GE, LE); - } - } else { - const llvm::fltSemantics &SrcSema = - CGF.getContext().getFloatTypeSemantics(OrigSrcType); - if (isa(DstTy)) { - // Floating-point to integer. This has undefined behavior if the source is - // +-Inf, NaN, or doesn't fit into the destination type (after truncation - // to an integer). - unsigned Width = CGF.getContext().getIntWidth(DstType); - bool Unsigned = DstType->isUnsignedIntegerOrEnumerationType(); - - APSInt Min = APSInt::getMinValue(Width, Unsigned); - APFloat MinSrc(SrcSema, APFloat::uninitialized); - if (MinSrc.convertFromAPInt(Min, !Unsigned, APFloat::rmTowardZero) & - APFloat::opOverflow) - // Don't need an overflow check for lower bound. Just check for - // -Inf/NaN. - 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); - APFloat MaxSrc(SrcSema, APFloat::uninitialized); - 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::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); - - // If we're converting from __half, convert the range to float to match - // the type of src. - if (OrigSrcType->isHalfType()) { - const llvm::fltSemantics &Sema = - CGF.getContext().getFloatTypeSemantics(SrcType); - bool IsInexact; - MinSrc.convert(Sema, APFloat::rmTowardZero, &IsInexact); - MaxSrc.convert(Sema, APFloat::rmTowardZero, &IsInexact); - } - - 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 { - // FIXME: Maybe split this sanitizer out from float-cast-overflow. - // - // Floating-point to floating-point. This has undefined behavior if the - // source is not in the range of representable values of the destination - // type. The C and C++ standards are spectacularly unclear here. We - // diagnose finite out-of-range conversions, but allow infinities and NaNs - // to convert to the corresponding value in the smaller type. - // - // C11 Annex F gives all such conversions defined behavior for IEC 60559 - // conforming implementations. Unfortunately, LLVM's fptrunc instruction - // does not. - - // Converting from a lower rank to a higher rank can never have - // undefined behavior, since higher-rank types must have a superset - // of values of lower-rank types. - if (CGF.getContext().getFloatingTypeOrder(OrigSrcType, DstType) != 1) - return; - - assert(!OrigSrcType->isHalfType() && - "should not check conversion from __half, it has the lowest rank"); - - const llvm::fltSemantics &DstSema = - CGF.getContext().getFloatTypeSemantics(DstType); - APFloat MinBad = APFloat::getLargest(DstSema, false); - APFloat MaxBad = APFloat::getInf(DstSema, false); - - bool IsInexact; - MinBad.convert(SrcSema, APFloat::rmTowardZero, &IsInexact); - MaxBad.convert(SrcSema, APFloat::rmTowardZero, &IsInexact); - - Value *AbsSrc = CGF.EmitNounwindRuntimeCall( - CGF.CGM.getIntrinsic(llvm::Intrinsic::fabs, Src->getType()), Src); - llvm::Value *GE = - Builder.CreateFCmpOGT(AbsSrc, llvm::ConstantFP::get(VMContext, MinBad)); - llvm::Value *LE = - Builder.CreateFCmpOLT(AbsSrc, llvm::ConstantFP::get(VMContext, MaxBad)); - Check = Builder.CreateNot(Builder.CreateAnd(GE, LE)); - } - } + // Floating-point to integer. This has undefined behavior if the source is + // +-Inf, NaN, or doesn't fit into the destination type (after truncation + // to an integer). + unsigned Width = CGF.getContext().getIntWidth(DstType); + bool Unsigned = DstType->isUnsignedIntegerOrEnumerationType(); + + APSInt Min = APSInt::getMinValue(Width, Unsigned); + APFloat MinSrc(SrcSema, APFloat::uninitialized); + if (MinSrc.convertFromAPInt(Min, !Unsigned, APFloat::rmTowardZero) & + APFloat::opOverflow) + // Don't need an overflow check for lower bound. Just check for + // -Inf/NaN. + 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); + APFloat MaxSrc(SrcSema, APFloat::uninitialized); + 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::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); + + // If we're converting from __half, convert the range to float to match + // the type of src. + if (OrigSrcType->isHalfType()) { + const llvm::fltSemantics &Sema = + CGF.getContext().getFloatTypeSemantics(SrcType); + bool IsInexact; + MinSrc.convert(Sema, APFloat::rmTowardZero, &IsInexact); + MaxSrc.convert(Sema, APFloat::rmTowardZero, &IsInexact); + } + + 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); llvm::Constant *StaticArgs[] = {CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(OrigSrcType), @@ -1391,9 +1326,12 @@ llvm::Type *ResTy = DstTy; // An overflowing conversion has undefined behavior if either the source type - // or the destination type is a floating-point type. + // or the destination type is a floating-point type. However, we consider the + // range of representable values for all floating-point types to be + // [-inf,+inf], so no overflow can ever happen when the destination type is a + // floating-point type. if (CGF.SanOpts.has(SanitizerKind::FloatCastOverflow) && - (OrigSrcType->isFloatingType() || DstType->isFloatingType())) + OrigSrcType->isFloatingType()) EmitFloatConversionCheck(OrigSrc, OrigSrcType, Src, SrcType, DstType, DstTy, Loc); Index: cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp =================================================================== --- cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp +++ cfe/trunk/test/CXX/expr/expr.const/p2-0x.cpp @@ -136,9 +136,9 @@ case (int)10000000000ll: // expected-note {{here}} case (unsigned int)10000000000ll: // expected-error {{duplicate case value}} case (int)(unsigned)(long long)4.4e9: // ok - case (int)(float)1e300: // expected-error {{constant expression}} expected-note {{value 1.0E+300 is outside the range of representable values of type 'float'}} + case (int)(float)1e300: // expected-error {{constant expression}} expected-note {{value +Inf is outside the range of representable values of type 'int'}} case (int)((float)1e37 / 1e30): // ok - case (int)(__fp16)65536: // expected-error {{constant expression}} expected-note {{value 65536 is outside the range of representable values of type '__fp16'}} + case (int)(__fp16)65536: // expected-error {{constant expression}} expected-note {{value +Inf is outside the range of representable values of type 'int'}} break; } } @@ -264,14 +264,28 @@ static_assert(0u - 1u == 4294967295u, ""); // ok static_assert(~0u * ~0u == 1u, ""); // ok + template constexpr bool isinf(T v) { return v && v / 2 == v; } + // Floating-point overflow and NaN. constexpr float f1 = 1e38f * 3.4028f; // ok - constexpr float f2 = 1e38f * 3.4029f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} + constexpr float f2 = 1e38f * 3.4029f; // ok, +inf is in range of representable values constexpr float f3 = 1e38f / -.2939f; // ok - constexpr float f4 = 1e38f / -.2938f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} - constexpr float f5 = 2e38f + 2e38f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} - constexpr float f6 = -2e38f - 2e38f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces an infinity}} - constexpr float f7 = 0.f / 0.f; // expected-error {{constant expression}} expected-note {{floating point arithmetic produces a NaN}} + constexpr float f4 = 1e38f / -.2938f; // ok, -inf is in range of representable values + constexpr float f5 = 2e38f + 2e38f; // ok, +inf is in range of representable values + constexpr float f6 = -2e38f - 2e38f; // ok, -inf is in range of representable values + constexpr float f7 = 0.f / 0.f; // expected-error {{constant expression}} expected-note {{division by zero}} + constexpr float f8 = 1.f / 0.f; // expected-error {{constant expression}} expected-note {{division by zero}} + constexpr float f9 = 1e308 / 1e-308; // ok, +inf + constexpr float f10 = f2 - f2; // expected-error {{constant expression}} expected-note {{produces a NaN}} + constexpr float f11 = f2 + f4; // expected-error {{constant expression}} expected-note {{produces a NaN}} + constexpr float f12 = f2 / f2; // expected-error {{constant expression}} expected-note {{produces a NaN}} + static_assert(!isinf(f1), ""); + static_assert(isinf(f2), ""); + static_assert(!isinf(f3), ""); + static_assert(isinf(f4), ""); + static_assert(isinf(f5), ""); + static_assert(isinf(f6), ""); + static_assert(isinf(f9), ""); } } Index: cfe/trunk/test/CodeGen/catch-undef-behavior.c =================================================================== --- cfe/trunk/test/CodeGen/catch-undef-behavior.c +++ cfe/trunk/test/CodeGen/catch-undef-behavior.c @@ -17,9 +17,7 @@ // CHECK-UBSAN: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 14 {{.*}} @[[STRUCT_S]], i8 2, i8 3 } // CHECK-UBSAN: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 12 {{.*}} @{{.*}} } // CHECK-UBSAN: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 11 {{.*}} @{{.*}} } -// CHECK-UBSAN: @[[LINE_1000:.*]] = {{.*}}, i32 1000, i32 10 {{.*}} @{{.*}} } // CHECK-UBSAN: @[[FP16:.*]] = private unnamed_addr constant { i16, i16, [9 x i8] } { i16 1, i16 16, [9 x i8] c"'__fp16'\00" } -// CHECK-UBSAN: @[[LINE_1100:.*]] = {{.*}}, i32 1100, i32 8 {{.*}} @{{.*}} } // CHECK-UBSAN: @[[LINE_1200:.*]] = {{.*}}, i32 1200, i32 10 {{.*}} @{{.*}} } // CHECK-UBSAN: @[[LINE_1300:.*]] = {{.*}}, i32 1300, i32 10 {{.*}} @{{.*}} } // CHECK-UBSAN: @[[LINE_1400:.*]] = {{.*}}, i32 1400, i32 10 {{.*}} @{{.*}} } @@ -27,7 +25,6 @@ // CHECK-UBSAN: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 10 {{.*}} @[[FP16]], {{.*}} } // CHECK-UBSAN: @[[SCHAR:.*]] = private unnamed_addr constant { i16, i16, [14 x i8] } { i16 0, i16 7, [14 x i8] c"'signed char'\00" } // CHECK-UBSAN: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 10 {{.*}} @[[FP16]], {{.*}} } -// CHECK-UBSAN: @[[LINE_1600:.*]] = {{.*}}, i32 1600, i32 10 {{.*}} @{{.*}} } // PR6805 // CHECK-COMMON-LABEL: @foo @@ -197,30 +194,16 @@ // CHECK-COMMON-LABEL: @int_float_overflow float int_float_overflow(unsigned __int128 n) { - // This is 2**104. FLT_MAX is 2**128 - 2**104. - // CHECK-COMMON: %[[INBOUNDS:.*]] = icmp ule i128 %{{.*}}, -20282409603651670423947251286016 - // CHECK-COMMON-NEXT: br i1 %[[INBOUNDS]] - - // CHECK-UBSAN: call void @__ubsan_handle_float_cast_overflow(i8* bitcast ({{.*}} @[[LINE_1000]] to i8*), - - // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] - // CHECK-TRAP-NEXT: unreachable -#line 1000 + // CHECK-UBSAN-NOT: call {{.*}} @__ubsan_handle_float_cast_overflow( + // CHECK-TRAP-NOT: call {{.*}} @llvm.trap( + // CHECK-COMMON: } return n; } // CHECK-COMMON-LABEL: @int_fp16_overflow void int_fp16_overflow(int n, __fp16 *p) { - // CHECK-COMMON: %[[GE:.*]] = icmp sge i32 %{{.*}}, -65504 - // CHECK-COMMON: %[[LE:.*]] = icmp sle i32 %{{.*}}, 65504 - // CHECK-COMMON: %[[INBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] - // CHECK-COMMON-NEXT: br i1 %[[INBOUNDS]] - - // CHECK-UBSAN: call void @__ubsan_handle_float_cast_overflow(i8* bitcast ({{.*}} @[[LINE_1100]] to i8*), - - // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] - // CHECK-TRAP-NEXT: unreachable -#line 1100 + // CHECK-UBSAN-NOT: call {{.*}} @__ubsan_handle_float_cast_overflow( + // CHECK-COMMON: } *p = n; } @@ -292,18 +275,9 @@ // CHECK-COMMON-LABEL: @float_float_overflow float float_float_overflow(double f) { - // CHECK-COMMON: %[[F:.*]] = call double @llvm.fabs.f64( - // CHECK-COMMON: %[[GE:.*]] = fcmp ogt double %[[F]], 0x47EFFFFFE0000000 - // CHECK-COMMON: %[[LE:.*]] = fcmp olt double %[[F]], 0x7FF0000000000000 - // CHECK-COMMON: %[[OUTOFBOUNDS:.*]] = and i1 %[[GE]], %[[LE]] - // CHECK-COMMON: %[[INBOUNDS:.*]] = xor i1 %[[OUTOFBOUNDS]], true - // CHECK-COMMON-NEXT: br i1 %[[INBOUNDS]] - - // CHECK-UBSAN: call void @__ubsan_handle_float_cast_overflow(i8* bitcast ({{.*}} @[[LINE_1600]] to i8*), - - // CHECK-TRAP: call void @llvm.trap() [[NR_NUW]] - // CHECK-TRAP-NEXT: unreachable -#line 1600 + // CHECK-UBSAN-NOT: call {{.*}} @__ubsan_handle_float_cast_overflow(i8* bitcast ({{.*}} @[[LINE_1600]] to i8*), + // CHECK-TRAP-NOT: call {{.*}} @llvm.trap() [[NR_NUW]] + // CHECK-COMMON: } return f; } Index: cfe/trunk/test/Driver/fsanitize.c =================================================================== --- cfe/trunk/test/Driver/fsanitize.c +++ cfe/trunk/test/Driver/fsanitize.c @@ -4,15 +4,15 @@ // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined-trap -fsanitize-undefined-trap-on-error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP // RUN: %clang -target x86_64-linux-gnu -fsanitize-undefined-trap-on-error -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-TRAP // CHECK-UNDEFINED-TRAP-NOT: -fsanitize-recover -// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){19}"}} -// CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" -// CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,float-divide-by-zero,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" +// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} +// CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,signed-integer-overflow,unreachable,vla-bound" +// CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,array-bounds,bool,builtin,enum,float-cast-overflow,function,integer-divide-by-zero,nonnull-attribute,null,pointer-overflow,return,returns-nonnull-attribute,shift-base,shift-exponent,unreachable,vla-bound" // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED -// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){20}"}} +// CHECK-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|vptr|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){19}"}} // RUN: %clang -target x86_64-apple-darwin10 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-DARWIN -// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){19}"}} +// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){18}"}} // RUN: %clang -target i386-pc-win32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32 // RUN: %clang -target i386-pc-win32 -fsanitize=undefined -x c++ %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED-WIN --check-prefix=CHECK-UNDEFINED-WIN32 --check-prefix=CHECK-UNDEFINED-WIN-CXX @@ -23,7 +23,7 @@ // CHECK-UNDEFINED-WIN64: "--dependent-lib={{[^"]*}}ubsan_standalone-x86_64.lib" // CHECK-UNDEFINED-WIN64-MINGW: "--dependent-lib={{[^"]*}}libclang_rt.ubsan_standalone-x86_64.a" // CHECK-UNDEFINED-WIN-CXX: "--dependent-lib={{[^"]*}}ubsan_standalone_cxx{{[^"]*}}.lib" -// CHECK-UNDEFINED-WIN-SAME: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){18}"}} +// CHECK-UNDEFINED-WIN-SAME: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){17}"}} // RUN: %clang -target i386-pc-win32 -fsanitize-coverage=bb %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-COVERAGE-WIN32 // CHECK-COVERAGE-WIN32: "--dependent-lib={{[^"]*}}ubsan_standalone-i386.lib" @@ -88,7 +88,7 @@ // CHECK-FNO-SANITIZE-ALL: "-fsanitize=thread" // RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined -fno-sanitize=thread -fno-sanitize=float-cast-overflow,vptr,bool,builtin,enum %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-UNDEFINED -// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|array-bounds|returns-nonnull-attribute|nonnull-attribute),?){15}"}} +// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|function|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|array-bounds|returns-nonnull-attribute|nonnull-attribute),?){14}"}} // RUN: %clang -target x86_64-linux-gnu -fsanitize=shift -fno-sanitize=shift-base %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-FSANITIZE-SHIFT-PARTIAL // CHECK-FSANITIZE-SHIFT-PARTIAL: "-fsanitize=shift-exponent" @@ -339,7 +339,7 @@ // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=undefined -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-UBSAN // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=all -fsanitize-recover=thread -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-UBSAN // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fsanitize-recover=all -fno-sanitize-recover=undefined -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-RECOVER-UBSAN -// CHECK-RECOVER-UBSAN: "-fsanitize-recover={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|function|shift-base|shift-exponent|vla-bound|alignment|null|vptr|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){18}"}} +// CHECK-RECOVER-UBSAN: "-fsanitize-recover={{((signed-integer-overflow|integer-divide-by-zero|function|shift-base|shift-exponent|vla-bound|alignment|null|vptr|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute),?){17}"}} // CHECK-NO-RECOVER-UBSAN-NOT: sanitize-recover // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=all -fsanitize-recover=object-size,shift-base -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-RECOVER @@ -749,7 +749,7 @@ // CHECK-TSAN-MINIMAL: error: invalid argument '-fsanitize-minimal-runtime' not allowed with '-fsanitize=thread' // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-MINIMAL -// CHECK-UBSAN-MINIMAL: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|float-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){19}"}} +// CHECK-UBSAN-MINIMAL: "-fsanitize={{((signed-integer-overflow|integer-divide-by-zero|shift-base|shift-exponent|unreachable|return|vla-bound|alignment|null|pointer-overflow|float-cast-overflow|array-bounds|enum|bool|builtin|returns-nonnull-attribute|nonnull-attribute|function),?){18}"}} // CHECK-UBSAN-MINIMAL: "-fsanitize-minimal-runtime" // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize=vptr -fsanitize-minimal-runtime %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UBSAN-VPTR-MINIMAL Index: cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp =================================================================== --- cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp +++ cfe/trunk/test/SemaCXX/constant-expression-cxx1y.cpp @@ -425,7 +425,7 @@ constexpr bool test_overflow() { T a = 1; while (a != a / 2) - a *= 2; // expected-note {{value 2147483648 is outside the range}} expected-note {{ 9223372036854775808 }} expected-note {{floating point arithmetic produces an infinity}} + a *= 2; // expected-note {{value 2147483648 is outside the range}} expected-note {{ 9223372036854775808 }} return true; } @@ -435,7 +435,8 @@ static_assert(test_overflow(), ""); // ok static_assert(test_overflow(), ""); // ok static_assert(test_overflow(), ""); // expected-error {{constant}} expected-note {{call}} - static_assert(test_overflow(), ""); // expected-error {{constant}} expected-note {{call}} + static_assert(test_overflow(), ""); // ok + static_assert(test_overflow(), ""); // ok constexpr short test_promotion(short k) { short s = k;