<div dir="ltr"><div><div>Hello Vedant,<br><br>This commit broke tests on some of our builders:<br><br>Failing Tests (1):<br>    Clang :: CodeGen/ubsan-pointer-overflow.m<br><br><a href="http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/2865/steps/test-check-all/logs/stdio">http://lab.llvm.org:8011/builders/llvm-clang-x86_64-expensive-checks-win/builds/2865/steps/test-check-all/logs/stdio</a><br><a href="http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/10259">http://lab.llvm.org:8011/builders/llvm-clang-lld-x86_64-scei-ps4-windows10pro-fast/builds/10259</a><br><a href="http://lab.llvm.org:8011/builders/clang-with-lto-ubuntu/builds/3097">http://lab.llvm.org:8011/builders/clang-with-lto-ubuntu/builds/3097</a><br></div><div>etc<br></div><div><br></div>Thanks<br><br></div>Galina<br></div><div class="gmail_extra"><br><div class="gmail_quote">On Thu, Jun 1, 2017 at 12:22 PM, Vedant Kumar via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: vedantk<br>
Date: Thu Jun  1 14:22:18 2017<br>
New Revision: 304459<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=304459&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=304459&view=rev</a><br>
Log:<br>
[ubsan] Add a check for pointer overflow UB<br>
<br>
Check pointer arithmetic for overflow.<br>
<br>
For some more background on this check, see:<br>
<br>
  <a href="https://wdtz.org/catching-pointer-overflow-bugs.html" rel="noreferrer" target="_blank">https://wdtz.org/catching-<wbr>pointer-overflow-bugs.html</a><br>
  <a href="https://reviews.llvm.org/D20322" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D20322</a><br>
<br>
Patch by Will Dietz and John Regehr!<br>
<br>
This version of the patch is different from the original in a few ways:<br>
<br>
  - It introduces the EmitCheckedInBoundsGEP utility which inserts<br>
    checks when the pointer overflow check is enabled.<br>
<br>
  - It does some constant-folding to reduce instrumentation overhead.<br>
<br>
  - It does not check some GEPs in CGExprCXX. I'm not sure that<br>
    inserting checks here, or in CGClass, would catch many bugs.<br>
<br>
Possible future directions for this check:<br>
<br>
  - Introduce CGF.EmitCheckedStructGEP, to detect overflows when<br>
    accessing structures.<br>
<br>
Testing: Apart from the added lit test, I ran check-llvm and check-clang<br>
with a stage2, ubsan-instrumented clang. Will and John have also done<br>
extensive testing on numerous open source projects.<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D33305" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D33305</a><br>
<br>
Added:<br>
    cfe/trunk/test/CodeGen/ubsan-<wbr>pointer-overflow.m<br>
Modified:<br>
    cfe/trunk/docs/<wbr>UndefinedBehaviorSanitizer.rst<br>
    cfe/trunk/include/clang/Basic/<wbr>Sanitizers.def<br>
    cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp<br>
    cfe/trunk/lib/CodeGen/<wbr>CGExprScalar.cpp<br>
    cfe/trunk/lib/CodeGen/<wbr>CodeGenFunction.h<br>
    cfe/trunk/test/Driver/<wbr>fsanitize.c<br>
<br>
Modified: cfe/trunk/docs/<wbr>UndefinedBehaviorSanitizer.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/UndefinedBehaviorSanitizer.rst?rev=304459&r1=304458&r2=304459&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/docs/<wbr>UndefinedBehaviorSanitizer.<wbr>rst?rev=304459&r1=304458&r2=<wbr>304459&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/docs/<wbr>UndefinedBehaviorSanitizer.rst (original)<br>
+++ cfe/trunk/docs/<wbr>UndefinedBehaviorSanitizer.rst Thu Jun  1 14:22:18 2017<br>
@@ -106,6 +106,8 @@ Available checks are:<br>
      invalid pointers. These checks are made in terms of<br>
      ``__builtin_object_size``, and consequently may be able to detect more<br>
      problems at higher optimization levels.<br>
+  -  ``-fsanitize=pointer-overflow`<wbr>`: Performing pointer arithmetic which<br>
+     overflows.<br>
   -  ``-fsanitize=return``: In C++, reaching the end of a<br>
      value-returning function without returning a value.<br>
   -  ``-fsanitize=returns-nonnull-<wbr>attribute``: Returning null pointer<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>Sanitizers.def<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Sanitizers.def?rev=304459&r1=304458&r2=304459&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/Sanitizers.def?<wbr>rev=304459&r1=304458&r2=<wbr>304459&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>Sanitizers.def (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>Sanitizers.def Thu Jun  1 14:22:18 2017<br>
@@ -73,6 +73,7 @@ SANITIZER("nullability-return"<wbr>, Nullabil<br>
 SANITIZER_GROUP("nullability", Nullability,<br>
                 NullabilityArg | NullabilityAssign | NullabilityReturn)<br>
 SANITIZER("object-size", ObjectSize)<br>
+SANITIZER("pointer-overflow", PointerOverflow)<br>
 SANITIZER("return", Return)<br>
 SANITIZER("returns-nonnull-<wbr>attribute", ReturnsNonnullAttribute)<br>
 SANITIZER("shift-base", ShiftBase)<br>
@@ -108,9 +109,9 @@ SANITIZER("safe-stack", SafeStack)<br>
 SANITIZER_GROUP("undefined", Undefined,<br>
                 Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow |<br>
                     FloatDivideByZero | IntegerDivideByZero | NonnullAttribute |<br>
-                    Null | ObjectSize | Return | ReturnsNonnullAttribute |<br>
-                    Shift | SignedIntegerOverflow | Unreachable | VLABound |<br>
-                    Function | Vptr)<br>
+                    Null | ObjectSize | PointerOverflow | Return |<br>
+                    ReturnsNonnullAttribute | Shift | SignedIntegerOverflow |<br>
+                    Unreachable | VLABound | Function | Vptr)<br>
<br>
 // -fsanitize=undefined-trap is an alias for -fsanitize=undefined.<br>
 SANITIZER_GROUP("undefined-<wbr>trap", UndefinedTrap, Undefined)<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=304459&r1=304458&r2=304459&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CGExpr.cpp?rev=304459&r1=<wbr>304458&r2=304459&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp Thu Jun  1 14:22:18 2017<br>
@@ -3002,9 +3002,10 @@ static llvm::Value *emitArraySubscriptGE<br>
                                           llvm::Value *ptr,<br>
                                           ArrayRef<llvm::Value*> indices,<br>
                                           bool inbounds,<br>
+                                          SourceLocation loc,<br>
                                     const llvm::Twine &name = "arrayidx") {<br>
   if (inbounds) {<br>
-    return CGF.Builder.CreateInBoundsGEP(<wbr>ptr, indices, name);<br>
+    return CGF.EmitCheckedInBoundsGEP(<wbr>ptr, indices, loc, name);<br>
   } else {<br>
     return CGF.Builder.CreateGEP(ptr, indices, name);<br>
   }<br>
@@ -3035,8 +3036,9 @@ static QualType getFixedSizeElementType(<br>
 }<br>
<br>
 static Address emitArraySubscriptGEP(<wbr>CodeGenFunction &CGF, Address addr,<br>
-                                     ArrayRef<llvm::Value*> indices,<br>
+                                     ArrayRef<llvm::Value *> indices,<br>
                                      QualType eltType, bool inbounds,<br>
+                                     SourceLocation loc,<br>
                                      const llvm::Twine &name = "arrayidx") {<br>
   // All the indices except that last must be zero.<br>
 #ifndef NDEBUG<br>
@@ -3057,7 +3059,7 @@ static Address emitArraySubscriptGEP(Cod<br>
     getArrayElementAlign(addr.<wbr>getAlignment(), indices.back(), eltSize);<br>
<br>
   llvm::Value *eltPtr =<br>
-    emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, name);<br>
+    emitArraySubscriptGEP(CGF, addr.getPointer(), indices, inbounds, loc, name);<br>
   return Address(eltPtr, eltAlign);<br>
 }<br>
<br>
@@ -3110,7 +3112,8 @@ LValue CodeGenFunction::<wbr>EmitArraySubscri<br>
     Address Addr = EmitExtVectorElementLValue(LV)<wbr>;<br>
<br>
     QualType EltType = LV.getType()->castAs<<wbr>VectorType>()->getElementType(<wbr>);<br>
-    Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true);<br>
+    Addr = emitArraySubscriptGEP(*this, Addr, Idx, EltType, /*inbounds*/ true,<br>
+                                 E->getExprLoc());<br>
     return MakeAddrLValue(Addr, EltType, LV.getBaseInfo());<br>
   }<br>
<br>
@@ -3138,7 +3141,8 @@ LValue CodeGenFunction::<wbr>EmitArraySubscri<br>
     }<br>
<br>
     Addr = emitArraySubscriptGEP(*this, Addr, Idx, vla->getElementType(),<br>
-                                 !getLangOpts().<wbr>isSignedOverflowDefined());<br>
+                                 !getLangOpts().<wbr>isSignedOverflowDefined(),<br>
+                                 E->getExprLoc());<br>
<br>
   } else if (const ObjCObjectType *OIT = E->getType()->getAs<<wbr>ObjCObjectType>()){<br>
     // Indexing over an interface, as in "NSString *P; P[4];"<br>
@@ -3163,8 +3167,8 @@ LValue CodeGenFunction::<wbr>EmitArraySubscri<br>
     // Do the GEP.<br>
     CharUnits EltAlign =<br>
       getArrayElementAlign(Addr.<wbr>getAlignment(), Idx, InterfaceSize);<br>
-    llvm::Value *EltPtr =<br>
-      emitArraySubscriptGEP(*this, Addr.getPointer(), ScaledIdx, false);<br>
+    llvm::Value *EltPtr = emitArraySubscriptGEP(<br>
+        *this, Addr.getPointer(), ScaledIdx, false, E->getExprLoc());<br>
     Addr = Address(EltPtr, EltAlign);<br>
<br>
     // Cast back.<br>
@@ -3189,14 +3193,16 @@ LValue CodeGenFunction::<wbr>EmitArraySubscri<br>
     Addr = emitArraySubscriptGEP(*this, ArrayLV.getAddress(),<br>
                                  {CGM.getSize(CharUnits::Zero()<wbr>), Idx},<br>
                                  E->getType(),<br>
-                                 !getLangOpts().<wbr>isSignedOverflowDefined());<br>
+                                 !getLangOpts().<wbr>isSignedOverflowDefined(),<br>
+                                 E->getExprLoc());<br>
     BaseInfo = ArrayLV.getBaseInfo();<br>
   } else {<br>
     // The base must be a pointer; emit it with an estimate of its alignment.<br>
     Addr = EmitPointerWithAlignment(E-><wbr>getBase(), &BaseInfo);<br>
     auto *Idx = EmitIdxAfterBase(/*Promote*/<wbr>true);<br>
     Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(),<br>
-                                 !getLangOpts().<wbr>isSignedOverflowDefined());<br>
+                                 !getLangOpts().<wbr>isSignedOverflowDefined(),<br>
+                                 E->getExprLoc());<br>
   }<br>
<br>
   LValue LV = MakeAddrLValue(Addr, E->getType(), BaseInfo);<br>
@@ -3368,7 +3374,8 @@ LValue CodeGenFunction::<wbr>EmitOMPArraySect<br>
     else<br>
       Idx = Builder.CreateNSWMul(Idx, NumElements);<br>
     EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(),<br>
-                                   !getLangOpts().<wbr>isSignedOverflowDefined());<br>
+                                   !getLangOpts().<wbr>isSignedOverflowDefined(),<br>
+                                   E->getExprLoc());<br>
   } else if (const Expr *Array = isSimpleArrayDecayOperand(E-><wbr>getBase())) {<br>
     // If this is A[i] where A is an array, the frontend will have decayed the<br>
     // base to be a ArrayToPointerDecay implicit cast.  While correct, it is<br>
@@ -3387,13 +3394,15 @@ LValue CodeGenFunction::<wbr>EmitOMPArraySect<br>
     // Propagate the alignment from the array itself to the result.<br>
     EltPtr = emitArraySubscriptGEP(<br>
         *this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()<wbr>), Idx},<br>
-        ResultExprTy, !getLangOpts().<wbr>isSignedOverflowDefined());<br>
+        ResultExprTy, !getLangOpts().<wbr>isSignedOverflowDefined(),<br>
+        E->getExprLoc());<br>
     BaseInfo = ArrayLV.getBaseInfo();<br>
   } else {<br>
     Address Base = emitOMPArraySectionBase(*this, E->getBase(), BaseInfo,<br>
                                            BaseTy, ResultExprTy, IsLowerBound);<br>
     EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy,<br>
-                                   !getLangOpts().<wbr>isSignedOverflowDefined());<br>
+                                   !getLangOpts().<wbr>isSignedOverflowDefined(),<br>
+                                   E->getExprLoc());<br>
   }<br>
<br>
   return MakeAddrLValue(EltPtr, ResultExprTy, BaseInfo);<br>
<br>
Modified: cfe/trunk/lib/CodeGen/<wbr>CGExprScalar.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprScalar.cpp?rev=304459&r1=304458&r2=304459&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CGExprScalar.cpp?rev=304459&<wbr>r1=304458&r2=304459&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/<wbr>CGExprScalar.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/<wbr>CGExprScalar.cpp Thu Jun  1 14:22:18 2017<br>
@@ -30,6 +30,7 @@<br>
 #include "llvm/IR/Constants.h"<br>
 #include "llvm/IR/DataLayout.h"<br>
 #include "llvm/IR/Function.h"<br>
+#include "llvm/IR/<wbr>GetElementPtrTypeIterator.h"<br>
 #include "llvm/IR/GlobalVariable.h"<br>
 #include "llvm/IR/Intrinsics.h"<br>
 #include "llvm/IR/Module.h"<br>
@@ -44,6 +45,43 @@ using llvm::Value;<br>
 //===-------------------------<wbr>------------------------------<wbr>---------------===//<br>
<br>
 namespace {<br>
+<br>
+/// Determine whether the given binary operation may overflow.<br>
+/// Sets \p Result to the value of the operation for BO_Add, BO_Sub, BO_Mul,<br>
+/// and signed BO_{Div,Rem}. For these opcodes, and for unsigned BO_{Div,Rem},<br>
+/// the returned overflow check is precise. The returned value is 'true' for<br>
+/// all other opcodes, to be conservative.<br>
+bool mayHaveIntegerOverflow(llvm::<wbr>ConstantInt *LHS, llvm::ConstantInt *RHS,<br>
+                             BinaryOperator::Opcode Opcode, bool Signed,<br>
+                             llvm::APInt &Result) {<br>
+  // Assume overflow is possible, unless we can prove otherwise.<br>
+  bool Overflow = true;<br>
+  const auto &LHSAP = LHS->getValue();<br>
+  const auto &RHSAP = RHS->getValue();<br>
+  if (Opcode == BO_Add) {<br>
+    if (Signed)<br>
+      Result = LHSAP.sadd_ov(RHSAP, Overflow);<br>
+    else<br>
+      Result = LHSAP.uadd_ov(RHSAP, Overflow);<br>
+  } else if (Opcode == BO_Sub) {<br>
+    if (Signed)<br>
+      Result = LHSAP.ssub_ov(RHSAP, Overflow);<br>
+    else<br>
+      Result = LHSAP.usub_ov(RHSAP, Overflow);<br>
+  } else if (Opcode == BO_Mul) {<br>
+    if (Signed)<br>
+      Result = LHSAP.smul_ov(RHSAP, Overflow);<br>
+    else<br>
+      Result = LHSAP.umul_ov(RHSAP, Overflow);<br>
+  } else if (Opcode == BO_Div || Opcode == BO_Rem) {<br>
+    if (Signed && !RHS->isZero())<br>
+      Result = LHSAP.sdiv_ov(RHSAP, Overflow);<br>
+    else<br>
+      return false;<br>
+  }<br>
+  return Overflow;<br>
+}<br>
+<br>
 struct BinOpInfo {<br>
   Value *LHS;<br>
   Value *RHS;<br>
@@ -55,37 +93,14 @@ struct BinOpInfo {<br>
   /// Check if the binop can result in integer overflow.<br>
   bool mayHaveIntegerOverflow() const {<br>
     // Without constant input, we can't rule out overflow.<br>
-    const auto *LHSCI = dyn_cast<llvm::ConstantInt>(<wbr>LHS);<br>
-    const auto *RHSCI = dyn_cast<llvm::ConstantInt>(<wbr>RHS);<br>
+    auto *LHSCI = dyn_cast<llvm::ConstantInt>(<wbr>LHS);<br>
+    auto *RHSCI = dyn_cast<llvm::ConstantInt>(<wbr>RHS);<br>
     if (!LHSCI || !RHSCI)<br>
       return true;<br>
<br>
-    // Assume overflow is possible, unless we can prove otherwise.<br>
-    bool Overflow = true;<br>
-    const auto &LHSAP = LHSCI->getValue();<br>
-    const auto &RHSAP = RHSCI->getValue();<br>
-    if (Opcode == BO_Add) {<br>
-      if (Ty-><wbr>hasSignedIntegerRepresentation<wbr>())<br>
-        (void)LHSAP.sadd_ov(RHSAP, Overflow);<br>
-      else<br>
-        (void)LHSAP.uadd_ov(RHSAP, Overflow);<br>
-    } else if (Opcode == BO_Sub) {<br>
-      if (Ty-><wbr>hasSignedIntegerRepresentation<wbr>())<br>
-        (void)LHSAP.ssub_ov(RHSAP, Overflow);<br>
-      else<br>
-        (void)LHSAP.usub_ov(RHSAP, Overflow);<br>
-    } else if (Opcode == BO_Mul) {<br>
-      if (Ty-><wbr>hasSignedIntegerRepresentation<wbr>())<br>
-        (void)LHSAP.smul_ov(RHSAP, Overflow);<br>
-      else<br>
-        (void)LHSAP.umul_ov(RHSAP, Overflow);<br>
-    } else if (Opcode == BO_Div || Opcode == BO_Rem) {<br>
-      if (Ty-><wbr>hasSignedIntegerRepresentation<wbr>() && !RHSCI->isZero())<br>
-        (void)LHSAP.sdiv_ov(RHSAP, Overflow);<br>
-      else<br>
-        return false;<br>
-    }<br>
-    return Overflow;<br>
+    llvm::APInt Result;<br>
+    return ::mayHaveIntegerOverflow(<br>
+        LHSCI, RHSCI, Opcode, Ty-><wbr>hasSignedIntegerRepresentation<wbr>(), Result);<br>
   }<br>
<br>
   /// Check if the binop computes a division or a remainder.<br>
@@ -1925,7 +1940,8 @@ ScalarExprEmitter::<wbr>EmitScalarPrePostIncD<br>
       if (CGF.getLangOpts().<wbr>isSignedOverflowDefined())<br>
         value = Builder.CreateGEP(value, numElts, "vla.inc");<br>
       else<br>
-        value = Builder.CreateInBoundsGEP(<wbr>value, numElts, "vla.inc");<br>
+        value = CGF.EmitCheckedInBoundsGEP(<wbr>value, numElts, E->getExprLoc(),<br>
+                                           "vla.inc");<br>
<br>
     // Arithmetic on function pointers (!) is just +-1.<br>
     } else if (type->isFunctionType()) {<br>
@@ -1935,7 +1951,8 @@ ScalarExprEmitter::<wbr>EmitScalarPrePostIncD<br>
       if (CGF.getLangOpts().<wbr>isSignedOverflowDefined())<br>
         value = Builder.CreateGEP(value, amt, "incdec.funcptr");<br>
       else<br>
-        value = Builder.CreateInBoundsGEP(<wbr>value, amt, "incdec.funcptr");<br>
+        value = CGF.EmitCheckedInBoundsGEP(<wbr>value, amt, E->getExprLoc(),<br>
+                                           "incdec.funcptr");<br>
       value = Builder.CreateBitCast(value, input->getType());<br>
<br>
     // For everything else, we can just do a simple increment.<br>
@@ -1944,7 +1961,8 @@ ScalarExprEmitter::<wbr>EmitScalarPrePostIncD<br>
       if (CGF.getLangOpts().<wbr>isSignedOverflowDefined())<br>
         value = Builder.CreateGEP(value, amt, "incdec.ptr");<br>
       else<br>
-        value = Builder.CreateInBoundsGEP(<wbr>value, amt, "incdec.ptr");<br>
+        value = CGF.EmitCheckedInBoundsGEP(<wbr>value, amt, E->getExprLoc(),<br>
+                                           "incdec.ptr");<br>
     }<br>
<br>
   // Vector increment/decrement.<br>
@@ -2025,7 +2043,8 @@ ScalarExprEmitter::<wbr>EmitScalarPrePostIncD<br>
     if (CGF.getLangOpts().<wbr>isSignedOverflowDefined())<br>
       value = Builder.CreateGEP(value, sizeValue, "incdec.objptr");<br>
     else<br>
-      value = Builder.CreateInBoundsGEP(<wbr>value, sizeValue, "incdec.objptr");<br>
+      value = CGF.EmitCheckedInBoundsGEP(<wbr>value, sizeValue, E->getExprLoc(),<br>
+                                         "incdec.objptr");<br>
     value = Builder.CreateBitCast(value, input->getType());<br>
   }<br>
<br>
@@ -2692,7 +2711,8 @@ static Value *emitPointerArithmetic(Code<br>
       pointer = CGF.Builder.CreateGEP(pointer, index, "add.ptr");<br>
     } else {<br>
       index = CGF.Builder.CreateNSWMul(<wbr>index, numElements, "vla.index");<br>
-      pointer = CGF.Builder.CreateInBoundsGEP(<wbr>pointer, index, "add.ptr");<br>
+      pointer = CGF.EmitCheckedInBoundsGEP(<wbr>pointer, index, op.E->getExprLoc(),<br>
+                                           "add.ptr");<br>
     }<br>
     return pointer;<br>
   }<br>
@@ -2709,7 +2729,8 @@ static Value *emitPointerArithmetic(Code<br>
   if (CGF.getLangOpts().<wbr>isSignedOverflowDefined())<br>
     return CGF.Builder.CreateGEP(pointer, index, "add.ptr");<br>
<br>
-  return CGF.Builder.CreateInBoundsGEP(<wbr>pointer, index, "add.ptr");<br>
+  return CGF.EmitCheckedInBoundsGEP(<wbr>pointer, index, op.E->getExprLoc(),<br>
+                                    "add.ptr");<br>
 }<br>
<br>
 // Construct an fmuladd intrinsic to represent a fused mul-add of MulOp and<br>
@@ -3824,3 +3845,124 @@ LValue CodeGenFunction::<wbr>EmitCompoundAssi<br>
<br>
   llvm_unreachable("Unhandled compound assignment operator");<br>
 }<br>
+<br>
+Value *CodeGenFunction::<wbr>EmitCheckedInBoundsGEP(Value *Ptr,<br>
+                                               ArrayRef<Value *> IdxList,<br>
+                                               SourceLocation Loc,<br>
+                                               const Twine &Name) {<br>
+  Value *GEPVal = Builder.CreateInBoundsGEP(Ptr, IdxList, Name);<br>
+<br>
+  // If the pointer overflow sanitizer isn't enabled, do nothing.<br>
+  if (!SanOpts.has(SanitizerKind::<wbr>PointerOverflow))<br>
+    return GEPVal;<br>
+<br>
+  // If the GEP has already been reduced to a constant, leave it be.<br>
+  if (isa<llvm::Constant>(GEPVal))<br>
+    return GEPVal;<br>
+<br>
+  // Only check for overflows in the default address space.<br>
+  if (GEPVal->getType()-><wbr>getPointerAddressSpace())<br>
+    return GEPVal;<br>
+<br>
+  auto *GEP = cast<llvm::GEPOperator>(<wbr>GEPVal);<br>
+  assert(GEP->isInBounds() && "Expected inbounds GEP");<br>
+<br>
+  SanitizerScope SanScope(this);<br>
+  auto &VMContext = getLLVMContext();<br>
+  const auto &DL = CGM.getDataLayout();<br>
+  auto *IntPtrTy = DL.getIntPtrType(GEP-><wbr>getPointerOperandType());<br>
+<br>
+  // Grab references to the signed add/mul overflow intrinsics for intptr_t.<br>
+  auto *Zero = llvm::ConstantInt::<wbr>getNullValue(IntPtrTy);<br>
+  auto *SAddIntrinsic =<br>
+      CGM.getIntrinsic(llvm::<wbr>Intrinsic::sadd_with_overflow, IntPtrTy);<br>
+  auto *SMulIntrinsic =<br>
+      CGM.getIntrinsic(llvm::<wbr>Intrinsic::smul_with_overflow, IntPtrTy);<br>
+<br>
+  // The total (signed) byte offset for the GEP.<br>
+  llvm::Value *TotalOffset = nullptr;<br>
+  // The offset overflow flag - true if the total offset overflows.<br>
+  llvm::Value *OffsetOverflows = Builder.getFalse();<br>
+<br>
+  /// Return the result of the given binary operation.<br>
+  auto eval = [&](BinaryOperator::Opcode Opcode, llvm::Value *LHS,<br>
+                  llvm::Value *RHS) -> llvm::Value * {<br>
+    assert(Opcode == BO_Add || Opcode == BO_Mul && "Can't eval binop");<br>
+<br>
+    // If the operands are constants, return a constant result.<br>
+    if (auto *LHSCI = dyn_cast<llvm::ConstantInt>(<wbr>LHS)) {<br>
+      if (auto *RHSCI = dyn_cast<llvm::ConstantInt>(<wbr>RHS)) {<br>
+        llvm::APInt N;<br>
+        bool HasOverflow = mayHaveIntegerOverflow(LHSCI, RHSCI, Opcode,<br>
+                                                  /*Signed=*/true, N);<br>
+        if (HasOverflow)<br>
+          OffsetOverflows = Builder.getTrue();<br>
+        return llvm::ConstantInt::get(<wbr>VMContext, N);<br>
+      }<br>
+    }<br>
+<br>
+    // Otherwise, compute the result with checked arithmetic.<br>
+    auto *ResultAndOverflow = Builder.CreateCall(<br>
+        (Opcode == BO_Add) ? SAddIntrinsic : SMulIntrinsic, {LHS, RHS});<br>
+    OffsetOverflows = Builder.CreateOr(<br>
+        OffsetOverflows, Builder.CreateExtractValue(<wbr>ResultAndOverflow, 1));<br>
+    return Builder.CreateExtractValue(<wbr>ResultAndOverflow, 0);<br>
+  };<br>
+<br>
+  // Determine the total byte offset by looking at each GEP operand.<br>
+  for (auto GTI = llvm::gep_type_begin(GEP), GTE = llvm::gep_type_end(GEP);<br>
+       GTI != GTE; ++GTI) {<br>
+    llvm::Value *LocalOffset;<br>
+    auto *Index = GTI.getOperand();<br>
+    // Compute the local offset contributed by this indexing step:<br>
+    if (auto *STy = GTI.getStructTypeOrNull()) {<br>
+      // For struct indexing, the local offset is the byte position of the<br>
+      // specified field.<br>
+      unsigned FieldNo = cast<llvm::ConstantInt>(Index)<wbr>->getZExtValue();<br>
+      LocalOffset = llvm::ConstantInt::get(<br>
+          IntPtrTy, DL.getStructLayout(STy)-><wbr>getElementOffset(FieldNo));<br>
+    } else {<br>
+      // Otherwise this is array-like indexing. The local offset is the index<br>
+      // multiplied by the element size.<br>
+      auto *ElementSize = llvm::ConstantInt::get(<br>
+          IntPtrTy, DL.getTypeAllocSize(GTI.<wbr>getIndexedType()));<br>
+      auto *IndexS = Builder.CreateIntCast(Index, IntPtrTy, /*isSigned=*/true);<br>
+      LocalOffset = eval(BO_Mul, ElementSize, IndexS);<br>
+    }<br>
+<br>
+    // If this is the first offset, set it as the total offset. Otherwise, add<br>
+    // the local offset into the running total.<br>
+    if (!TotalOffset || TotalOffset == Zero)<br>
+      TotalOffset = LocalOffset;<br>
+    else<br>
+      TotalOffset = eval(BO_Add, TotalOffset, LocalOffset);<br>
+  }<br>
+<br>
+  // Common case: if the total offset is zero, don't emit a check.<br>
+  if (TotalOffset == Zero)<br>
+    return GEPVal;<br>
+<br>
+  // Now that we've computed the total offset, add it to the base pointer (with<br>
+  // wrapping semantics).<br>
+  auto *IntPtr = Builder.CreatePtrToInt(GEP-><wbr>getPointerOperand(), IntPtrTy);<br>
+  auto *ComputedGEP = Builder.CreateAdd(IntPtr, TotalOffset);<br>
+<br>
+  // The GEP is valid if:<br>
+  // 1) The total offset doesn't overflow, and<br>
+  // 2) The sign of the difference between the computed address and the base<br>
+  // pointer matches the sign of the total offset.<br>
+  llvm::Value *PosOrZeroValid = Builder.CreateICmpUGE(<wbr>ComputedGEP, IntPtr);<br>
+  llvm::Value *NegValid = Builder.CreateICmpULT(<wbr>ComputedGEP, IntPtr);<br>
+  auto *PosOrZeroOffset = Builder.CreateICmpSGE(<wbr>TotalOffset, Zero);<br>
+  llvm::Value *ValidGEP = Builder.CreateAnd(<br>
+      Builder.CreateNot(<wbr>OffsetOverflows),<br>
+      Builder.CreateSelect(<wbr>PosOrZeroOffset, PosOrZeroValid, NegValid));<br>
+<br>
+  llvm::Constant *StaticArgs[] = {EmitCheckSourceLocation(Loc)}<wbr>;<br>
+  // Pass the computed GEP to the runtime to avoid emitting poisoned arguments.<br>
+  llvm::Value *DynamicArgs[] = {IntPtr, ComputedGEP};<br>
+  EmitCheck(std::make_pair(<wbr>ValidGEP, SanitizerKind::<wbr>PointerOverflow),<br>
+            SanitizerHandler::<wbr>PointerOverflow, StaticArgs, DynamicArgs);<br>
+<br>
+  return GEPVal;<br>
+}<br>
<br>
Modified: cfe/trunk/lib/CodeGen/<wbr>CodeGenFunction.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=304459&r1=304458&r2=304459&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CodeGenFunction.h?rev=304459&<wbr>r1=304458&r2=304459&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/<wbr>CodeGenFunction.h (original)<br>
+++ cfe/trunk/lib/CodeGen/<wbr>CodeGenFunction.h Thu Jun  1 14:22:18 2017<br>
@@ -120,6 +120,7 @@ enum TypeEvaluationKind {<br>
   SANITIZER_CHECK(NonnullArg, nonnull_arg, 0)                                  \<br>
   SANITIZER_CHECK(NonnullReturn, nonnull_return, 0)                            \<br>
   SANITIZER_CHECK(OutOfBounds, out_of_bounds, 0)                               \<br>
+  SANITIZER_CHECK(<wbr>PointerOverflow, pointer_overflow, 0)                        \<br>
   SANITIZER_CHECK(<wbr>ShiftOutOfBounds, shift_out_of_bounds, 0)                    \<br>
   SANITIZER_CHECK(SubOverflow, sub_overflow, 0)                                \<br>
   SANITIZER_CHECK(TypeMismatch, type_mismatch, 1)                              \<br>
@@ -3551,6 +3552,13 @@ public:<br>
   /// nonnull, if \p LHS is marked _Nonnull.<br>
   void EmitNullabilityCheck(LValue LHS, llvm::Value *RHS, SourceLocation Loc);<br>
<br>
+  /// Same as IRBuilder::CreateInBoundsGEP, but additionally emits a check to<br>
+  /// detect undefined behavior when the pointer overflow sanitizer is enabled.<br>
+  llvm::Value *EmitCheckedInBoundsGEP(llvm::<wbr>Value *Ptr,<br>
+                                      ArrayRef<llvm::Value *> IdxList,<br>
+                                      SourceLocation Loc,<br>
+                                      const Twine &Name = "");<br>
+<br>
   /// \brief Emit a description of a type in a format suitable for passing to<br>
   /// a runtime sanitizer handler.<br>
   llvm::Constant *EmitCheckTypeDescriptor(<wbr>QualType T);<br>
<br>
Added: cfe/trunk/test/CodeGen/ubsan-<wbr>pointer-overflow.m<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/ubsan-pointer-overflow.m?rev=304459&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGen/ubsan-pointer-<wbr>overflow.m?rev=304459&view=<wbr>auto</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGen/ubsan-<wbr>pointer-overflow.m (added)<br>
+++ cfe/trunk/test/CodeGen/ubsan-<wbr>pointer-overflow.m Thu Jun  1 14:22:18 2017<br>
@@ -0,0 +1,171 @@<br>
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -w -emit-llvm -o - %s -fsanitize=pointer-overflow | FileCheck %s<br>
+<br>
+// CHECK-LABEL: define void @unary_arith<br>
+void unary_arith(char *p) {<br>
+  // CHECK:  [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize<br>
+  // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], 1, !nosanitize<br>
+  // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize<br>
+  // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize<br>
+  // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 true, i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize<br>
+  // CHECK-NEXT: [[VALID:%.*]] = and i1 true, [[DIFFVALID]], !nosanitize<br>
+  // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize<br>
+  ++p;<br>
+<br>
+  // CHECK: ptrtoint i8* {{.*}} to i64, !nosanitize<br>
+  // CHECK-NEXT: add i64 {{.*}}, -1, !nosanitize<br>
+  // CHECK: select i1 false{{.*}}, !nosanitize<br>
+  // CHECK-NEXT: and i1 true{{.*}}, !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+  --p;<br>
+<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+  p++;<br>
+<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+  p--;<br>
+}<br>
+<br>
+// CHECK-LABEL: define void @binary_arith<br>
+void binary_arith(char *p, int i) {<br>
+  // CHECK: [[SMUL:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(<wbr>i64 1, i64 %{{.*}}), !nosanitize<br>
+  // CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, !nosanitize<br>
+  // CHECK-NEXT: [[OFFSETOFLOW:%.*]] = or i1 false, [[SMULOFLOW]], !nosanitize<br>
+  // CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, !nosanitize<br>
+  // CHECK-NEXT: [[BASE:%.*]] = ptrtoint i8* {{.*}} to i64, !nosanitize<br>
+  // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], !nosanitize<br>
+  // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize<br>
+  // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize<br>
+  // CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, !nosanitize<br>
+  // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize<br>
+  // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize<br>
+  // CHECK-NEXT: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize<br>
+  // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize<br>
+  p + i;<br>
+<br>
+  // CHECK: [[OFFSET:%.*]] = sub i64 0, {{.*}}<br>
+  // CHECK-NEXT: getelementptr inbounds {{.*}} [[OFFSET]]<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+  p - i;<br>
+}<br>
+<br>
+// CHECK-LABEL: define void @fixed_len_array<br>
+void fixed_len_array(int k) {<br>
+  // CHECK: getelementptr inbounds [10 x [10 x i32]], [10 x [10 x i32]]* [[ARR:%.*]], i64 0, i64 [[IDXPROM:%.*]]<br>
+  // CHECK-NEXT: [[SMUL:%.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(<wbr>i64 40, i64 [[IDXPROM]]), !nosanitize<br>
+  // CHECK-NEXT: [[SMULOFLOW:%.*]] = extractvalue { i64, i1 } [[SMUL]], 1, !nosanitize<br>
+  // CHECK-NEXT: [[OFFSETOFLOW:%.*]] = or i1 false, [[SMULOFLOW]], !nosanitize<br>
+  // CHECK-NEXT: [[SMULVAL:%.*]] = extractvalue { i64, i1 } [[SMUL]], 0, !nosanitize<br>
+  // CHECK-NEXT: [[BASE:%.*]] = ptrtoint [10 x [10 x i32]]* [[ARR]] to i64, !nosanitize<br>
+  // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], [[SMULVAL]], !nosanitize<br>
+  // CHECK-NEXT: [[POSVALID:%.*]] = icmp uge i64 [[COMPGEP]], [[BASE]], !nosanitize<br>
+  // CHECK-NEXT: [[NEGVALID:%.*]] = icmp ult i64 [[COMPGEP]], [[BASE]], !nosanitize<br>
+  // CHECK-NEXT: [[POSOFFSET:%.*]] = icmp sge i64 [[SMULVAL]], 0, !nosanitize<br>
+  // CHECK-NEXT: [[OFFSETVALID:%.*]] = xor i1 [[OFFSETOFLOW]], true, !nosanitize<br>
+  // CHECK-NEXT: [[DIFFVALID:%.*]] = select i1 [[POSOFFSET]], i1 [[POSVALID]], i1 [[NEGVALID]], !nosanitize<br>
+  // CHECK-NEXT: [[VALID:%.*]] = and i1 [[OFFSETVALID]], [[DIFFVALID]], !nosanitize<br>
+  // CHECK-NEXT: br i1 [[VALID]]{{.*}}, !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}, i64 [[BASE]], i64 [[COMPGEP]]){{.*}}, !nosanitize<br>
+<br>
+  // CHECK: getelementptr inbounds [10 x i32], [10 x i32]* {{.*}}, i64 0, i64 [[IDXPROM1:%.*]]<br>
+  // CHECK-NEXT: @llvm.smul.with.overflow.i64(<wbr>i64 4, i64 [[IDXPROM1]]), !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+<br>
+  int arr[10][10];<br>
+  arr[k][k];<br>
+}<br>
+<br>
+// CHECK-LABEL: define void @variable_len_array<br>
+void variable_len_array(int n, int k) {<br>
+  // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM:%.*]]<br>
+  // CHECK-NEXT: @llvm.smul.with.overflow.i64(<wbr>i64 4, i64 [[IDXPROM]]), !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+<br>
+  // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM1:%.*]]<br>
+  // CHECK-NEXT: @llvm.smul.with.overflow.i64(<wbr>i64 4, i64 [[IDXPROM1]]), !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+<br>
+  int arr[n][n];<br>
+  arr[k][k];<br>
+}<br>
+<br>
+// CHECK-LABEL: define void @pointer_array<br>
+void pointer_array(int **arr, int k) {<br>
+  // CHECK: @llvm.smul.with.overflow.i64(<wbr>i64 8, i64 {{.*}}), !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+<br>
+  // CHECK: @llvm.smul.with.overflow.i64(<wbr>i64 4, i64 {{.*}}), !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+<br>
+  arr[k][k];<br>
+}<br>
+<br>
+struct S1 {<br>
+  int pad1;<br>
+  union {<br>
+    char leaf;<br>
+    struct S1 *link;<br>
+  } u;<br>
+  struct S1 *arr;<br>
+};<br>
+<br>
+// TODO: Currently, structure GEPs are not checked, so there are several<br>
+// potentially unsafe GEPs here which we don't instrument.<br>
+//<br>
+// CHECK-LABEL: define void @struct_index<br>
+void struct_index(struct S1 *p) {<br>
+  // CHECK: getelementptr inbounds %struct.S1, %struct.S1* [[P:%.*]], i64 10<br>
+  // CHECK-NEXT: [[BASE:%.*]] = ptrtoint %struct.S1* [[P]] to i64, !nosanitize<br>
+  // CHECK-NEXT: [[COMPGEP:%.*]] = add i64 [[BASE]], 240, !nosanitize<br>
+  // CHECK: @__ubsan_handle_pointer_<wbr>overflow{{.*}} i64 [[BASE]], i64 [[COMPGEP]]) {{.*}}, !nosanitize<br>
+<br>
+  // CHECK-NOT: @__ubsan_handle_pointer_<wbr>overflow<br>
+<br>
+  p->arr[10].u.link->u.leaf;<br>
+}<br>
+<br>
+typedef void (*funcptr_t)(void);<br>
+<br>
+// CHECK-LABEL: define void @function_pointer_arith<br>
+void function_pointer_arith(<wbr>funcptr_t *p, int k) {<br>
+  // CHECK: add i64 {{.*}}, 8, !nosanitize<br>
+  // CHECK: @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+  ++p;<br>
+<br>
+  // CHECK: @llvm.smul.with.overflow.i64(<wbr>i64 8, i64 {{.*}}), !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+  p + k;<br>
+}<br>
+<br>
+// CHECK-LABEL: define void @variable_len_array_arith<br>
+void variable_len_array_arith(int n, int k) {<br>
+  int vla[n];<br>
+  int (*p)[n] = &vla;<br>
+<br>
+  // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[INC:%.*]]<br>
+  // CHECK: @llvm.smul.with.overflow.i64(<wbr>i64 4, i64 [[INC]]), !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+  ++p;<br>
+<br>
+  // CHECK: getelementptr inbounds i32, i32* {{.*}}, i64 [[IDXPROM:%.*]]<br>
+  // CHECK: @llvm.smul.with.overflow.i64(<wbr>i64 4, i64 [[IDXPROM]]), !nosanitize<br>
+  // CHECK: call void @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+  p + k;<br>
+}<br>
+<br>
+// CHECK-LABEL: define void @objc_id<br>
+void objc_id(id *p) {<br>
+  // CHECK: add i64 {{.*}}, 8, !nosanitize<br>
+  // CHECK: @__ubsan_handle_pointer_<wbr>overflow{{.*}}<br>
+  p++;<br>
+}<br>
+<br>
+// CHECK-LABEL: define void @dont_emit_checks_for_no_op_<wbr>GEPs<br>
+// CHECK-NOT: __ubsan_handle_pointer_<wbr>overflow<br>
+void dont_emit_checks_for_no_op_<wbr>GEPs(char *p) {<br>
+  &p[0];<br>
+<br>
+  int arr[10][10];<br>
+  &arr[0][0];<br>
+}<br>
<br>
Modified: cfe/trunk/test/Driver/<wbr>fsanitize.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/fsanitize.c?rev=304459&r1=304458&r2=304459&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Driver/<wbr>fsanitize.c?rev=304459&r1=<wbr>304458&r2=304459&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Driver/<wbr>fsanitize.c (original)<br>
+++ cfe/trunk/test/Driver/<wbr>fsanitize.c Thu Jun  1 14:22:18 2017<br>
@@ -3,18 +3,18 @@<br>
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fsanitize-undefined-trap-on-<wbr>error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-<wbr>UNDEFINED-TRAP<br>
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined-trap -fsanitize-undefined-trap-on-<wbr>error %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-<wbr>UNDEFINED-TRAP<br>
 // RUN: %clang -target x86_64-linux-gnu -fsanitize-undefined-trap-on-<wbr>error -fsanitize=undefined-trap %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-<wbr>UNDEFINED-TRAP<br>
-// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|shift-base|shift-<wbr>exponent|unreachable|return|<wbr>vla-bound|alignment|null|<wbr>object-size|float-cast-<wbr>overflow|array-bounds|enum|<wbr>bool|returns-nonnull-<wbr>attribute|nonnull-attribute|<wbr>function),?){18}"}}<br>
-// CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,<wbr>array-bounds,bool,enum,float-<wbr>cast-overflow,float-divide-by-<wbr>zero,function,integer-divide-<wbr>by-zero,nonnull-attribute,<wbr>null,object-size,return,<wbr>returns-nonnull-attribute,<wbr>shift-base,shift-exponent,<wbr>signed-integer-overflow,<wbr>unreachable,vla-bound"<br>
-// CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,<wbr>array-bounds,bool,enum,float-<wbr>cast-overflow,float-divide-by-<wbr>zero,function,integer-divide-<wbr>by-zero,nonnull-attribute,<wbr>null,object-size,return,<wbr>returns-nonnull-attribute,<wbr>shift-base,shift-exponent,<wbr>unreachable,vla-bound"<br>
+// CHECK-UNDEFINED-TRAP: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|shift-base|shift-<wbr>exponent|unreachable|return|<wbr>vla-bound|alignment|null|<wbr>object-size|pointer-overflow|<wbr>float-cast-overflow|array-<wbr>bounds|enum|bool|returns-<wbr>nonnull-attribute|nonnull-<wbr>attribute|function),?){19}"}}<br>
+// CHECK-UNDEFINED-TRAP: "-fsanitize-trap=alignment,<wbr>array-bounds,bool,enum,float-<wbr>cast-overflow,float-divide-by-<wbr>zero,function,integer-divide-<wbr>by-zero,nonnull-attribute,<wbr>null,object-size,pointer-<wbr>overflow,return,returns-<wbr>nonnull-attribute,shift-base,<wbr>shift-exponent,signed-integer-<wbr>overflow,unreachable,vla-<wbr>bound"<br>
+// CHECK-UNDEFINED-TRAP2: "-fsanitize-trap=alignment,<wbr>array-bounds,bool,enum,float-<wbr>cast-overflow,float-divide-by-<wbr>zero,function,integer-divide-<wbr>by-zero,nonnull-attribute,<wbr>null,object-size,pointer-<wbr>overflow,return,returns-<wbr>nonnull-attribute,shift-base,<wbr>shift-exponent,unreachable,<wbr>vla-bound"<br>
<br>
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-UNDEFINED<br>
-// CHECK-UNDEFINED: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|function|shift-base|<wbr>shift-exponent|unreachable|<wbr>return|vla-bound|alignment|<wbr>null|vptr|object-size|float-<wbr>cast-overflow|array-bounds|<wbr>enum|bool|returns-nonnull-<wbr>attribute|nonnull-attribute),?<wbr>){19}"}}<br>
+// CHECK-UNDEFINED: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|function|shift-base|<wbr>shift-exponent|unreachable|<wbr>return|vla-bound|alignment|<wbr>null|vptr|object-size|pointer-<wbr>overflow|float-cast-overflow|<wbr>array-bounds|enum|bool|<wbr>returns-nonnull-attribute|<wbr>nonnull-attribute),?){20}"}}<br>
<br>
 // RUN: %clang -target x86_64-apple-darwin10 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-<wbr>UNDEFINED-DARWIN<br>
-// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|shift-base|shift-<wbr>exponent|unreachable|return|<wbr>vla-bound|alignment|null|<wbr>object-size|float-cast-<wbr>overflow|array-bounds|enum|<wbr>bool|returns-nonnull-<wbr>attribute|nonnull-attribute),?<wbr>){17}"}}<br>
+// CHECK-UNDEFINED-DARWIN: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|shift-base|shift-<wbr>exponent|unreachable|return|<wbr>vla-bound|alignment|null|<wbr>object-size|pointer-overflow|<wbr>float-cast-overflow|array-<wbr>bounds|enum|bool|returns-<wbr>nonnull-attribute|nonnull-<wbr>attribute),?){18}"}}<br>
<br>
 // RUN: %clang -target i386-unknown-openbsd -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-<wbr>UNDEFINED-OPENBSD<br>
-// CHECK-UNDEFINED-OPENBSD: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|shift-base|shift-<wbr>exponent|unreachable|return|<wbr>vla-bound|alignment|null|<wbr>object-size|float-cast-<wbr>overflow|array-bounds|enum|<wbr>bool|returns-nonnull-<wbr>attribute|nonnull-attribute),?<wbr>){17}"}}<br>
+// CHECK-UNDEFINED-OPENBSD: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|shift-base|shift-<wbr>exponent|unreachable|return|<wbr>vla-bound|alignment|null|<wbr>object-size|pointer-overflow|<wbr>float-cast-overflow|array-<wbr>bounds|enum|bool|returns-<wbr>nonnull-attribute|nonnull-<wbr>attribute),?){18}"}}<br>
<br>
 // RUN: %clang -target i386-pc-win32 -fsanitize=undefined %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-<wbr>UNDEFINED-WIN --check-prefix=CHECK-<wbr>UNDEFINED-WIN32<br>
 // RUN: %clang -target i386-pc-win32 -fsanitize=undefined -x c++ %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-<wbr>UNDEFINED-WIN --check-prefix=CHECK-<wbr>UNDEFINED-WIN32 --check-prefix=CHECK-<wbr>UNDEFINED-WIN-CXX<br>
@@ -23,7 +23,7 @@<br>
 // CHECK-UNDEFINED-WIN32: "--dependent-lib={{[^"]*}}<wbr>ubsan_standalone-i386.lib"<br>
 // CHECK-UNDEFINED-WIN64: "--dependent-lib={{[^"]*}}<wbr>ubsan_standalone-x86_64.lib"<br>
 // CHECK-UNDEFINED-WIN-CXX: "--dependent-lib={{[^"]*}}<wbr>ubsan_standalone_cxx{{[^"]*}}.<wbr>lib"<br>
-// CHECK-UNDEFINED-WIN-SAME: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|shift-base|shift-<wbr>exponent|unreachable|return|<wbr>vla-bound|alignment|null|<wbr>object-size|float-cast-<wbr>overflow|array-bounds|enum|<wbr>bool|returns-nonnull-<wbr>attribute|nonnull-attribute),?<wbr>){17}"}}<br>
+// CHECK-UNDEFINED-WIN-SAME: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|shift-base|shift-<wbr>exponent|unreachable|return|<wbr>vla-bound|alignment|null|<wbr>object-size|pointer-overflow|<wbr>float-cast-overflow|array-<wbr>bounds|enum|bool|returns-<wbr>nonnull-attribute|nonnull-<wbr>attribute),?){18}"}}<br>
<br>
 // RUN: %clang -target i386-pc-win32 -fsanitize-coverage=bb %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-COVERAGE-<wbr>WIN32<br>
 // CHECK-COVERAGE-WIN32: "--dependent-lib={{[^"]*}}<wbr>ubsan_standalone-i386.lib"<br>
@@ -43,7 +43,7 @@<br>
 // CHECK-FNO-SANITIZE-ALL: "-fsanitize=thread"<br>
<br>
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=thread,undefined -fno-sanitize=thread -fno-sanitize=float-cast-<wbr>overflow,vptr,bool,enum %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-<wbr>UNDEFINED<br>
-// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|function|shift-base|<wbr>shift-exponent|unreachable|<wbr>return|vla-bound|alignment|<wbr>null|object-size|array-bounds|<wbr>returns-nonnull-attribute|<wbr>nonnull-attribute),?){15}"}}<br>
+// CHECK-PARTIAL-UNDEFINED: "-fsanitize={{((signed-<wbr>integer-overflow|integer-<wbr>divide-by-zero|float-divide-<wbr>by-zero|function|shift-base|<wbr>shift-exponent|unreachable|<wbr>return|vla-bound|alignment|<wbr>null|object-size|pointer-<wbr>overflow|array-bounds|returns-<wbr>nonnull-attribute|nonnull-<wbr>attribute),?){16}"}}<br>
<br>
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=shift -fno-sanitize=shift-base %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-<wbr>FSANITIZE-SHIFT-PARTIAL<br>
 // CHECK-FSANITIZE-SHIFT-PARTIAL: "-fsanitize=shift-exponent"<br>
@@ -217,7 +217,7 @@<br>
 // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=<wbr>undefined -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-<wbr>RECOVER-UBSAN<br>
 // 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-<wbr>RECOVER-UBSAN<br>
 // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fsanitize-recover=all -fno-sanitize-recover=<wbr>undefined -### 2>&1 | FileCheck %s --check-prefix=CHECK-NO-<wbr>RECOVER-UBSAN<br>
-// CHECK-RECOVER-UBSAN: "-fsanitize-recover={{((<wbr>signed-integer-overflow|<wbr>integer-divide-by-zero|float-<wbr>divide-by-zero|function|shift-<wbr>base|shift-exponent|vla-bound|<wbr>alignment|null|vptr|object-<wbr>size|float-cast-overflow|<wbr>array-bounds|enum|bool|<wbr>returns-nonnull-attribute|<wbr>nonnull-attribute),?){17}"}}<br>
+// CHECK-RECOVER-UBSAN: "-fsanitize-recover={{((<wbr>signed-integer-overflow|<wbr>integer-divide-by-zero|float-<wbr>divide-by-zero|function|shift-<wbr>base|shift-exponent|vla-bound|<wbr>alignment|null|vptr|object-<wbr>size|pointer-overflow|float-<wbr>cast-overflow|array-bounds|<wbr>enum|bool|returns-nonnull-<wbr>attribute|nonnull-attribute),?<wbr>){18}"}}<br>
 // CHECK-NO-RECOVER-UBSAN-NOT: sanitize-recover<br>
<br>
 // RUN: %clang -target x86_64-linux-gnu %s -fsanitize=undefined -fno-sanitize-recover=all -fsanitize-recover=object-<wbr>size,shift-base -### 2>&1 | FileCheck %s --check-prefix=CHECK-PARTIAL-<wbr>RECOVER<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>