diff --git a/clang/docs/UndefinedBehaviorSanitizer.rst b/clang/docs/UndefinedBehaviorSanitizer.rst --- a/clang/docs/UndefinedBehaviorSanitizer.rst +++ b/clang/docs/UndefinedBehaviorSanitizer.rst @@ -81,7 +81,9 @@ ``true`` nor ``false``. - ``-fsanitize=builtin``: Passing invalid values to compiler builtins. - ``-fsanitize=bounds``: Out of bounds array indexing, in cases - where the array bound can be statically determined. + where the array bound can be statically determined. The check includes + ``-fsanitize=array-bounds`` and ``-fsanitize=local-bounds``. Note that + ``-fsanitize=local-bounds`` is not included in ``-fsanitize=undefined``. - ``-fsanitize=enum``: Load of a value of an enumerated type which is not in the range of representable values for that enumerated type. @@ -173,7 +175,8 @@ You can also use the following check groups: - ``-fsanitize=undefined``: All of the checks listed above other than ``float-divide-by-zero``, ``unsigned-integer-overflow``, - ``implicit-conversion``, and the ``nullability-*`` group of checks. + ``implicit-conversion``, ``local-bounds`` and the ``nullability-*`` group + of checks. - ``-fsanitize=undefined-trap``: Deprecated alias of ``-fsanitize=undefined``. - ``-fsanitize=implicit-integer-truncation``: Catches lossy integral @@ -202,7 +205,7 @@ Volatile -------- -The ``null``, ``alignment``, ``object-size``, and ``vptr`` checks do not apply +The ``null``, ``alignment``, ``object-size``, ``local-bounds``, and ``vptr`` checks do not apply to pointers to types with the ``volatile`` qualifier. Minimal Runtime diff --git a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp --- a/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp +++ b/llvm/lib/Transforms/Instrumentation/BoundsChecking.cpp @@ -154,17 +154,22 @@ Value *Or = nullptr; BuilderTy IRB(I.getParent(), BasicBlock::iterator(&I), TargetFolder(DL)); if (LoadInst *LI = dyn_cast(&I)) { - Or = getBoundsCheckCond(LI->getPointerOperand(), LI, DL, TLI, - ObjSizeEval, IRB, SE); + if (!LI->isVolatile()) + Or = getBoundsCheckCond(LI->getPointerOperand(), LI, DL, TLI, + ObjSizeEval, IRB, SE); } else if (StoreInst *SI = dyn_cast(&I)) { - Or = getBoundsCheckCond(SI->getPointerOperand(), SI->getValueOperand(), - DL, TLI, ObjSizeEval, IRB, SE); + if (!SI->isVolatile()) + Or = getBoundsCheckCond(SI->getPointerOperand(), SI->getValueOperand(), + DL, TLI, ObjSizeEval, IRB, SE); } else if (AtomicCmpXchgInst *AI = dyn_cast(&I)) { - Or = getBoundsCheckCond(AI->getPointerOperand(), AI->getCompareOperand(), - DL, TLI, ObjSizeEval, IRB, SE); + if (!AI->isVolatile()) + Or = + getBoundsCheckCond(AI->getPointerOperand(), AI->getCompareOperand(), + DL, TLI, ObjSizeEval, IRB, SE); } else if (AtomicRMWInst *AI = dyn_cast(&I)) { - Or = getBoundsCheckCond(AI->getPointerOperand(), AI->getValOperand(), DL, - TLI, ObjSizeEval, IRB, SE); + if (!AI->isVolatile()) + Or = getBoundsCheckCond(AI->getPointerOperand(), AI->getValOperand(), + DL, TLI, ObjSizeEval, IRB, SE); } if (Or) TrapInfo.push_back(std::make_pair(&I, Or)); diff --git a/llvm/test/Instrumentation/BoundsChecking/simple.ll b/llvm/test/Instrumentation/BoundsChecking/simple.ll --- a/llvm/test/Instrumentation/BoundsChecking/simple.ll +++ b/llvm/test/Instrumentation/BoundsChecking/simple.ll @@ -46,6 +46,16 @@ ret void } +; CHECK: @store_volatile +define void @store_volatile(i64 %x) nounwind { + %1 = tail call i8* @calloc(i64 4, i64 %x) + %2 = bitcast i8* %1 to i32* + %idx = getelementptr inbounds i32, i32* %2, i64 8 +; CHECK-NOT: trap + store volatile i32 3, i32* %idx, align 4 + ret void +} + ; CHECK: @f4 define void @f4(i64 %x) nounwind { %1 = tail call i8* @realloc(i8* null, i64 %x) nounwind @@ -144,12 +154,23 @@ define i64 @f12(i64 %x, i64 %y) nounwind { %1 = tail call i8* @calloc(i64 1, i64 %x) ; CHECK: mul i64 %y, 8 +; CHECK: trap %2 = bitcast i8* %1 to i64* %3 = getelementptr inbounds i64, i64* %2, i64 %y %4 = load i64, i64* %3, align 8 ret i64 %4 } +; CHECK: @load_volatile +define i64 @load_volatile(i64 %x, i64 %y) nounwind { + %1 = tail call i8* @calloc(i64 1, i64 %x) +; CHECK-NOT: trap + %2 = bitcast i8* %1 to i64* + %3 = getelementptr inbounds i64, i64* %2, i64 %y + %4 = load volatile i64, i64* %3, align 8 + ret i64 %4 +} + ; PR17402 ; CHECK-LABEL: @f13 define void @f13() nounwind {