From 59802321785b4b9fc31b10456c62ba3a06d3a631 Mon Sep 17 00:00:00 2001 From: James Molloy Date: Tue, 16 Aug 2016 09:45:36 +0000 Subject: [PATCH] Left shifts of negative values are defined if -fwrapv is set This means we shouldn't emit ubsan detection code or warn. Fixes PR25552. llvm-svn: 278786 --- clang/lib/CodeGen/CGExprScalar.cpp | 3 ++- clang/lib/Sema/SemaExpr.cpp | 2 +- clang/test/CodeGen/wrapv-lshr-sanitize.c | 12 ++++++++++++ clang/test/Sema/negative-shift-wrapv.c | 9 +++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 clang/test/CodeGen/wrapv-lshr-sanitize.c create mode 100644 clang/test/Sema/negative-shift-wrapv.c diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index f39368733592..700b5374ad9d 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -2714,7 +2714,8 @@ Value *ScalarExprEmitter::EmitShl(const BinOpInfo &Ops) { RHS = Builder.CreateIntCast(RHS, Ops.LHS->getType(), false, "sh_prom"); bool SanitizeBase = CGF.SanOpts.has(SanitizerKind::ShiftBase) && - Ops.Ty->hasSignedIntegerRepresentation(); + Ops.Ty->hasSignedIntegerRepresentation() && + !CGF.getLangOpts().isSignedOverflowDefined(); bool SanitizeExponent = CGF.SanOpts.has(SanitizerKind::ShiftExponent); // OpenCL 6.3j: shift values are effectively % word size of LHS. if (CGF.getLangOpts().OpenCL) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 78fa995e256e..41c8a4c52a1b 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -8670,7 +8670,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS, // If LHS does not have a signed type and non-negative value // then, the behavior is undefined. Warn about it. - if (Left.isNegative()) { + if (Left.isNegative() && !S.getLangOpts().isSignedOverflowDefined()) { S.DiagRuntimeBehavior(Loc, LHS.get(), S.PDiag(diag::warn_shift_lhs_negative) << LHS.get()->getSourceRange()); diff --git a/clang/test/CodeGen/wrapv-lshr-sanitize.c b/clang/test/CodeGen/wrapv-lshr-sanitize.c new file mode 100644 index 000000000000..c09dab7cf7b5 --- /dev/null +++ b/clang/test/CodeGen/wrapv-lshr-sanitize.c @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -fsanitize=shift-base -emit-llvm %s -o - -triple x86_64-linux-gnu -fwrapv | FileCheck %s + +// CHECK-LABEL: @lsh_overflow +int lsh_overflow(int a, int b) { + // CHECK-NOT: br + // CHECK-NOT: call void @__ubsan_ + // CHECK-NOT: call void @llvm.trap + + // CHECK: %[[RET:.*]] = shl i32 + // CHECK-NEXT: ret i32 %[[RET]] + return a << b; +} diff --git a/clang/test/Sema/negative-shift-wrapv.c b/clang/test/Sema/negative-shift-wrapv.c new file mode 100644 index 000000000000..b8748201ffc0 --- /dev/null +++ b/clang/test/Sema/negative-shift-wrapv.c @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -Wall -ffreestanding -fsyntax-only -fwrapv -verify %s + +int test() { + int i; + i = -1 << 1; // no-warning + return i; +} + +// expected-no-diagnostics