aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <efriedma@qti.qualcomm.com>2026-04-28 13:40:04 -0700
committerGitHub <noreply@github.com>2026-04-28 13:40:04 -0700
commit898eabc27d1f112de0e1372147db8f0573d2a63f (patch)
tree9c7f5a1332553d4f23ddfc017bc174827cf935cf
parentc147ccadae917314a7d46510936e5c275e14fc18 (diff)
downloadllvm-898eabc27d1f112de0e1372147db8f0573d2a63f.tar.gz
llvm-898eabc27d1f112de0e1372147db8f0573d2a63f.tar.bz2
llvm-898eabc27d1f112de0e1372147db8f0573d2a63f.zip
[clang] Fix interaction of __ob_wrap with signed divide. (#194474)
At first glance, signed divide overflow seems similar to other forms of signed overflow, but it's significantly different: it's the only form of signed overflow that is not affected by -fwrapv, it has undefined behavior at the LLVM IR level, and it can trigger trap on x86. Given that, make ubsan trigger on signed divide overflow even if a type is marked __ob_wrap.
-rw-r--r--clang/lib/CodeGen/CGExprScalar.cpp2
-rw-r--r--clang/test/CodeGen/overflow-behavior-types.c6
2 files changed, 5 insertions, 3 deletions
diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp
index c2188933ca2a..d60f1b37be50 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -4230,7 +4230,7 @@ void ScalarExprEmitter::EmitUndefinedBehaviorIntegerDivAndRemCheck(
if (CGF.SanOpts.has(SanitizerKind::SignedIntegerOverflow) &&
Ops.Ty->hasSignedIntegerRepresentation() &&
!IsWidenedIntegerOp(CGF.getContext(), BO->getLHS()) &&
- Ops.mayHaveIntegerOverflow() && !Ops.Ty.isWrapType() &&
+ Ops.mayHaveIntegerOverflow() &&
!CGF.getContext().isTypeIgnoredBySanitizer(
SanitizerKind::SignedIntegerOverflow, Ops.Ty)) {
llvm::IntegerType *Ty = cast<llvm::IntegerType>(Zero->getType());
diff --git a/clang/test/CodeGen/overflow-behavior-types.c b/clang/test/CodeGen/overflow-behavior-types.c
index 109888f70750..7047d88035a9 100644
--- a/clang/test/CodeGen/overflow-behavior-types.c
+++ b/clang/test/CodeGen/overflow-behavior-types.c
@@ -62,11 +62,13 @@ void test1(int __ob_wrap a, int __ob_trap b) {
// DEFAULT: llvm.sadd.with.overflow.i32
++b;
+ // Despite the fact that "a" is marked as "wrapping", we still perform an
+ // overflow check: an overflowing divide has undefined behavior at the
+ // LLVM IR level (and will trap on x86).
volatile extern int divisor;
// DEFAULT: %[[T0:.*]] = load i32, ptr %a
// DEFAULT-NEXT: %[[T1:.*]] = load volatile i32, ptr @divisor
- // DEFAULT-NOT: br {{.*}} %handler.divrem_overflow
- // DEFAULT: sdiv i32 %[[T0]], %[[T1]]
+ // DEFAULT: br {{.*}} %handler.divrem_overflow
a/divisor;
// DEFAULT: %[[T0:.*]] = load i32, ptr %b