<div dir="ltr">Hi Vedant,<div><br></div><div>after this change our ubsanvptr bot fails like so:</div><div><br></div><div><div>clang-6.0: error: implicitly disabling vptr sanitizer because null checking wasn't enabled [-Werror,-Wauto-disable-vptr-sanitizer]</div></div><div><br></div><div>The bot uses -fsanitize=vptr. I have no idea what this warning is supposed to tell me. Maybe it could be reworded, or maybe it shouldn't be emitted?</div><div><br></div><div>Thanks,</div><div>Nico</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Jul 25, 2017 at 3:34 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: Tue Jul 25 12:34:23 2017<br>
New Revision: 309007<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=309007&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=309007&view=rev</a><br>
Log:<br>
[ubsan] Null-check pointers in -fsanitize=vptr (PR33881)<br>
<br>
The instrumentation generated by -fsanitize=vptr does not null check a<br>
user pointer before loading from it. This causes crashes in the face of<br>
UB member calls (this=nullptr), i.e it's causing user programs to crash<br>
only after UBSan is turned on.<br>
<br>
The fix is to make run-time null checking a prerequisite for enabling<br>
-fsanitize=vptr, and to then teach UBSan to reuse these run-time null<br>
checks to make -fsanitize=vptr safe.<br>
<br>
Testing: check-clang, check-ubsan, a stage2 ubsan-enabled build<br>
<br>
Differential Revision: <a href="https://reviews.llvm.org/D35735" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D35735</a><br>
<br>
<a href="https://bugs.llvm.org/show_bug.cgi?id=33881" rel="noreferrer" target="_blank">https://bugs.llvm.org/show_<wbr>bug.cgi?id=33881</a><br>
<br>
Modified:<br>
    cfe/trunk/docs/ReleaseNotes.<wbr>rst<br>
    cfe/trunk/docs/<wbr>UndefinedBehaviorSanitizer.rst<br>
    cfe/trunk/include/clang/Basic/<wbr>DiagnosticDriverKinds.td<br>
    cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td<br>
    cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp<br>
    cfe/trunk/lib/Driver/<wbr>SanitizerArgs.cpp<br>
    cfe/trunk/test/CodeGenCXX/<wbr>catch-undef-behavior.cpp<br>
    cfe/trunk/test/CodeGenCXX/<wbr>ubsan-devirtualized-calls.cpp<br>
    cfe/trunk/test/CodeGenCXX/<wbr>ubsan-type-checks.cpp<br>
    cfe/trunk/test/CodeGenCXX/<wbr>ubsan-vtable-checks.cpp<br>
    cfe/trunk/test/Driver/<wbr>fsanitize.c<br>
    cfe/trunk/test/Driver/rtti-<wbr>options.cpp<br>
<br>
Modified: cfe/trunk/docs/ReleaseNotes.<wbr>rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/ReleaseNotes.rst?rev=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/docs/<wbr>ReleaseNotes.rst?rev=309007&<wbr>r1=309006&r2=309007&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/docs/ReleaseNotes.<wbr>rst (original)<br>
+++ cfe/trunk/docs/ReleaseNotes.<wbr>rst Tue Jul 25 12:34:23 2017<br>
@@ -155,7 +155,9 @@ Static Analyzer<br>
 Undefined Behavior Sanitizer (UBSan)<br>
 ------------------------------<wbr>------<br>
<br>
-...<br>
+The C++ dynamic type check now requires run-time null checking (i.e,<br>
+`-fsanitize=vptr` cannot be used without `-fsanitize=null`). This change does<br>
+not impact users who rely on UBSan check groups (e.g `-fsanitize=undefined`).<br>
<br>
 Core Analysis Improvements<br>
 ==========================<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=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/docs/<wbr>UndefinedBehaviorSanitizer.<wbr>rst?rev=309007&r1=309006&r2=<wbr>309007&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/docs/<wbr>UndefinedBehaviorSanitizer.rst (original)<br>
+++ cfe/trunk/docs/<wbr>UndefinedBehaviorSanitizer.rst Tue Jul 25 12:34:23 2017<br>
@@ -130,11 +130,11 @@ Available checks are:<br>
      it is often unintentional, so UBSan offers to catch it.<br>
   -  ``-fsanitize=vla-bound``: A variable-length array whose bound<br>
      does not evaluate to a positive value.<br>
-  -  ``-fsanitize=vptr``: Use of an object whose vptr indicates that<br>
-     it is of the wrong dynamic type, or that its lifetime has not<br>
-     begun or has ended. Incompatible with ``-fno-rtti``. Link must<br>
-     be performed by ``clang++``, not ``clang``, to make sure C++-specific<br>
-     parts of the runtime library and C++ standard libraries are present.<br>
+  -  ``-fsanitize=vptr``: Use of an object whose vptr indicates that it is of<br>
+     the wrong dynamic type, or that its lifetime has not begun or has ended.<br>
+     Incompatible with ``-fno-rtti`` and ``-fno-sanitize=null``. Link must be<br>
+     performed by ``clang++``, not ``clang``, to make sure C++-specific parts of<br>
+     the runtime library and C++ standard libraries are present.<br>
<br>
 You can also use the following check groups:<br>
   -  ``-fsanitize=undefined``: All of the checks listed above other than<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticDriverKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticDriverKinds.td?rev=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/<wbr>DiagnosticDriverKinds.td?rev=<wbr>309007&r1=309006&r2=309007&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticDriverKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticDriverKinds.td Tue Jul 25 12:34:23 2017<br>
@@ -230,7 +230,10 @@ def warn_drv_enabling_rtti_with_<wbr>exceptio<br>
   InGroup<DiagGroup<"rtti-for-<wbr>exceptions">>;<br>
 def warn_drv_disabling_vptr_no_<wbr>rtti_default : Warning<<br>
   "implicitly disabling vptr sanitizer because rtti wasn't enabled">,<br>
-  InGroup<DiagGroup<"auto-<wbr>disable-vptr-sanitizer">>;<br>
+  InGroup<<wbr>AutoDisableVptrSanitizer>;<br>
+def warn_drv_disabling_vptr_no_<wbr>null_check : Warning<<br>
+  "implicitly disabling vptr sanitizer because null checking wasn't enabled">,<br>
+  InGroup<<wbr>AutoDisableVptrSanitizer>;<br>
 def warn_drv_object_size_disabled_<wbr>O0 : Warning<<br>
   "the object size sanitizer has no effect at -O0, but is explicitly enabled: %0">,<br>
   InGroup<<wbr>InvalidCommandLineArgument>;<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticGroups.td?rev=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/DiagnosticGroups.<wbr>td?rev=309007&r1=309006&r2=<wbr>309007&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>DiagnosticGroups.td Tue Jul 25 12:34:23 2017<br>
@@ -27,6 +27,7 @@ def GNUAnonymousStruct : DiagGroup<"gnu-<br>
 def GNUAutoType : DiagGroup<"gnu-auto-type">;<br>
 def ArrayBounds : DiagGroup<"array-bounds">;<br>
 def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-<wbr>pointer-arithmetic">;<br>
+def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-<wbr>sanitizer">;<br>
 def Availability : DiagGroup<"availability">;<br>
 def Section : DiagGroup<"section">;<br>
 def AutoImport : DiagGroup<"auto-import">;<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=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/CodeGen/<wbr>CGExpr.cpp?rev=309007&r1=<wbr>309006&r2=309007&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGExpr.<wbr>cpp Tue Jul 25 12:34:23 2017<br>
@@ -604,20 +604,23 @@ void CodeGenFunction::<wbr>EmitTypeCheck(Type<br>
   auto PtrToAlloca =<br>
       dyn_cast<llvm::AllocaInst>(<wbr>Ptr-><wbr>stripPointerCastsNoFollowAlias<wbr>es());<br>
<br>
+  llvm::Value *IsNonNull = nullptr;<br>
+  bool IsGuaranteedNonNull =<br>
+      SkippedChecks.has(<wbr>SanitizerKind::Null) || PtrToAlloca;<br>
   bool AllowNullPointers = TCK == TCK_DowncastPointer || TCK == TCK_Upcast ||<br>
                            TCK == TCK_UpcastToVirtualBase;<br>
   if ((SanOpts.has(SanitizerKind::<wbr>Null) || AllowNullPointers) &&<br>
-      !SkippedChecks.has(<wbr>SanitizerKind::Null) && !PtrToAlloca) {<br>
+      !IsGuaranteedNonNull) {<br>
     // The glvalue must not be an empty glvalue.<br>
-    llvm::Value *IsNonNull = Builder.CreateIsNotNull(Ptr);<br>
+    IsNonNull = Builder.CreateIsNotNull(Ptr);<br>
<br>
     // The IR builder can constant-fold the null check if the pointer points to<br>
     // a constant.<br>
-    bool PtrIsNonNull =<br>
+    IsGuaranteedNonNull =<br>
         IsNonNull == llvm::ConstantInt::getTrue(<wbr>getLLVMContext());<br>
<br>
     // Skip the null check if the pointer is known to be non-null.<br>
-    if (!PtrIsNonNull) {<br>
+    if (!IsGuaranteedNonNull) {<br>
       if (AllowNullPointers) {<br>
         // When performing pointer casts, it's OK if the value is null.<br>
         // Skip the remaining checks in that case.<br>
@@ -691,12 +694,24 @@ void CodeGenFunction::<wbr>EmitTypeCheck(Type<br>
   //    -- the [pointer or glvalue] is used to access a non-static data member<br>
   //       or call a non-static member function<br>
   CXXRecordDecl *RD = Ty->getAsCXXRecordDecl();<br>
+  bool HasNullCheck = IsGuaranteedNonNull || IsNonNull;<br>
   if (SanOpts.has(SanitizerKind::<wbr>Vptr) &&<br>
-      !SkippedChecks.has(<wbr>SanitizerKind::Vptr) &&<br>
+      !SkippedChecks.has(<wbr>SanitizerKind::Vptr) && HasNullCheck &&<br>
       (TCK == TCK_MemberAccess || TCK == TCK_MemberCall ||<br>
        TCK == TCK_DowncastPointer || TCK == TCK_DowncastReference ||<br>
        TCK == TCK_UpcastToVirtualBase) &&<br>
       RD && RD->hasDefinition() && RD->isDynamicClass()) {<br>
+    // Ensure that the pointer is non-null before loading it. If there is no<br>
+    // compile-time guarantee, reuse the run-time null check.<br>
+    if (!IsGuaranteedNonNull) {<br>
+      assert(IsNonNull && "Missing run-time null check");<br>
+      if (!Done)<br>
+        Done = createBasicBlock("vptr.null");<br>
+      llvm::BasicBlock *VptrNotNull = createBasicBlock("vptr.not.<wbr>null");<br>
+      Builder.CreateCondBr(<wbr>IsNonNull, VptrNotNull, Done);<br>
+      EmitBlock(VptrNotNull);<br>
+    }<br>
+<br>
     // Compute a hash of the mangled name of the type.<br>
     //<br>
     // FIXME: This is not guaranteed to be deterministic! Move to a<br>
<br>
Modified: cfe/trunk/lib/Driver/<wbr>SanitizerArgs.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/SanitizerArgs.cpp?rev=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Driver/<wbr>SanitizerArgs.cpp?rev=309007&<wbr>r1=309006&r2=309007&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Driver/<wbr>SanitizerArgs.cpp (original)<br>
+++ cfe/trunk/lib/Driver/<wbr>SanitizerArgs.cpp Tue Jul 25 12:34:23 2017<br>
@@ -306,6 +306,13 @@ SanitizerArgs::SanitizerArgs(<wbr>const ToolC<br>
     Kinds &= ~Vptr;<br>
   }<br>
<br>
+  // Disable -fsanitize=vptr if -fsanitize=null is not enabled (the vptr<br>
+  // instrumentation is broken without run-time null checks).<br>
+  if ((Kinds & Vptr) && !(Kinds & Null)) {<br>
+    Kinds &= ~Vptr;<br>
+    D.Diag(diag::warn_drv_<wbr>disabling_vptr_no_null_check);<br>
+  }<br>
+<br>
   // Check that LTO is enabled if we need it.<br>
   if ((Kinds & NeedsLTO) && !D.isUsingLTO()) {<br>
     D.Diag(diag::err_drv_argument_<wbr>only_allowed_with)<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/<wbr>catch-undef-behavior.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/catch-undef-behavior.cpp?rev=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenCXX/catch-undef-<wbr>behavior.cpp?rev=309007&r1=<wbr>309006&r2=309007&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenCXX/<wbr>catch-undef-behavior.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/<wbr>catch-undef-behavior.cpp Tue Jul 25 12:34:23 2017<br>
@@ -1,6 +1,6 @@<br>
 // RUN: %clang_cc1 -std=c++11 -fsanitize=signed-integer-<wbr>overflow,integer-divide-by-<wbr>zero,float-divide-by-zero,<wbr>shift-base,shift-exponent,<wbr>unreachable,return,vla-bound,<wbr>alignment,null,vptr,object-<wbr>size,float-cast-overflow,bool,<wbr>enum,array-bounds,function -fsanitize-recover=signed-<wbr>integer-overflow,integer-<wbr>divide-by-zero,float-divide-<wbr>by-zero,shift-base,shift-<wbr>exponent,vla-bound,alignment,<wbr>null,vptr,object-size,float-<wbr>cast-overflow,bool,enum,array-<wbr>bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | opt -instnamer -S | FileCheck %s<br>
-// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr,address -fsanitize-recover=vptr,<wbr>address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN<br>
-// RUN: %clang_cc1 -std=c++11 -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL<br>
+// RUN: %clang_cc1 -std=c++11 -fsanitize=null,vptr,address -fsanitize-recover=null,vptr,<wbr>address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN<br>
+// RUN: %clang_cc1 -std=c++11 -fsanitize=null,vptr -fsanitize-recover=null,vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL<br>
 // RUN: %clang_cc1 -std=c++11 -fsanitize=function -emit-llvm %s -o - -triple x86_64-linux-gnux32 | FileCheck %s --check-prefix=CHECK-X32<br>
 // RUN: %clang_cc1 -std=c++11 -fsanitize=function -emit-llvm %s -o - -triple i386-linux-gnu | FileCheck %s --check-prefix=CHECK-X86<br>
<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/<wbr>ubsan-devirtualized-calls.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ubsan-devirtualized-calls.cpp?rev=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenCXX/ubsan-<wbr>devirtualized-calls.cpp?rev=<wbr>309007&r1=309006&r2=309007&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenCXX/<wbr>ubsan-devirtualized-calls.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/<wbr>ubsan-devirtualized-calls.cpp Tue Jul 25 12:34:23 2017<br>
@@ -1,4 +1,4 @@<br>
-// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s<br>
+// RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s<br>
<br>
 struct Base1 {<br>
   virtual void f1() {}<br>
@@ -64,6 +64,11 @@ void t4() {<br>
   // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_<wbr>cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED3]] {{.*}}, i{{[0-9]+}} %[[P1]]<br>
<br>
   static_cast<Base1 *>(badp)->f1(); //< No devirt, test 'badp isa Base1'.<br>
+  // We were able to skip the null check on the first type check because 'p'<br>
+  // is backed by an alloca. We can't skip the second null check because 'badp'<br>
+  // is a (bitcast (load ...)).<br>
+  // CHECK: call void @__ubsan_handle_type_mismatch<br>
+  //<br>
   // CHECK: %[[BADP1:[0-9]+]] = ptrtoint %struct.Base1* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize<br>
   // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_<wbr>cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_BASE1]] {{.*}}, i{{[0-9]+}} %[[BADP1]]<br>
 }<br>
@@ -76,6 +81,8 @@ void t5() {<br>
   // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_<wbr>cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED4_1]] {{.*}}, i{{[0-9]+}} %[[P1]]<br>
<br>
   static_cast<Base1 *>(badp)->f1(); //< Devirt Base1::f1 to Derived4::f1.<br>
+  // CHECK: call void @__ubsan_handle_type_mismatch<br>
+  //<br>
   // CHECK: %[[BADP1:[0-9]+]] = ptrtoint %struct.Derived4* {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize<br>
   // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_<wbr>cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED4_2]] {{.*}}, i{{[0-9]+}} %[[BADP1]]<br>
 }<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/<wbr>ubsan-type-checks.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ubsan-type-checks.cpp?rev=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenCXX/ubsan-type-checks.<wbr>cpp?rev=309007&r1=309006&r2=<wbr>309007&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenCXX/<wbr>ubsan-type-checks.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/<wbr>ubsan-type-checks.cpp Tue Jul 25 12:34:23 2017<br>
@@ -1,6 +1,8 @@<br>
 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s -check-prefixes=ALIGN,COMMON<br>
 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s -check-prefixes=NULL,COMMON<br>
 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=object-size | FileCheck %s -check-prefixes=OBJSIZE,COMMON<br>
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null,vptr | FileCheck %s -check-prefixes=VPTR<br>
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=vptr | FileCheck %s -check-prefixes=VPTR_NO_NULL<br>
<br>
 struct A {<br>
   // COMMON-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv<br>
@@ -24,13 +26,55 @@ struct B {<br>
     // NULL: icmp ne %struct.B* %{{.*}}, null, !nosanitize<br>
<br>
     // OBJSIZE-NOT: call i64 @llvm.objectsize<br>
+    // OBJSIZE: ret void<br>
   }<br>
 };<br>
<br>
-void force_irgen() {<br>
+struct Animal {<br>
+  virtual const char *speak() = 0;<br>
+};<br>
+<br>
+struct Cat : Animal {<br>
+  const char *speak() override { return "meow"; }<br>
+};<br>
+<br>
+struct Dog : Animal {<br>
+  const char *speak() override { return "woof"; }<br>
+};<br>
+<br>
+// VPTR-LABEL: define void @_Z12invalid_castP3Cat<br>
+void invalid_cast(Cat *cat = nullptr) {<br>
+  // First, null check the pointer:<br>
+  //<br>
+  // VPTR: [[ICMP:%.*]] = icmp ne %struct.Dog* {{.*}}, null<br>
+  // VPTR-NEXT: br i1 [[ICMP]]<br>
+  // VPTR: call void @__ubsan_handle_type_mismatch<br>
+  //<br>
+  // Once we're done emitting the null check, reuse the check to see if we can<br>
+  // proceed to the vptr check:<br>
+  //<br>
+  // VPTR: br i1 [[ICMP]]<br>
+  // VPTR: call void @__ubsan_handle_dynamic_type_<wbr>cache_miss<br>
+  auto *badDog = reinterpret_cast<Dog *>(cat);<br>
+  badDog->speak();<br>
+}<br>
+<br>
+// VPTR_NO_NULL-LABEL: define void @_Z13invalid_cast2v<br>
+void invalid_cast2() {<br>
+  // We've got a pointer to an alloca, so there's no run-time null check needed.<br>
+  // VPTR_NO_NULL-NOT: call void @__ubsan_handle_type_mismatch<br>
+  // VPTR_NO_NULL: call void @__ubsan_handle_dynamic_type_<wbr>cache_miss<br>
+  Cat cat;<br>
+  cat.speak();<br>
+}<br>
+<br>
+int main() {<br>
   A a;<br>
   a.do_nothing();<br>
<br>
   B b;<br>
   b.do_nothing();<br>
+<br>
+  invalid_cast();<br>
+  return 0;<br>
 }<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/<wbr>ubsan-vtable-checks.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ubsan-vtable-checks.cpp?rev=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>CodeGenCXX/ubsan-vtable-<wbr>checks.cpp?rev=309007&r1=<wbr>309006&r2=309007&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/CodeGenCXX/<wbr>ubsan-vtable-checks.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/<wbr>ubsan-vtable-checks.cpp Tue Jul 25 12:34:23 2017<br>
@@ -1,7 +1,7 @@<br>
 // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=null %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NULL --check-prefix=ITANIUM<br>
 // RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NULL --check-prefix=MSABI<br>
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=ITANIUM<br>
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=MSABI<br>
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-linux -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=ITANIUM<br>
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-VPTR --check-prefix=MSABI<br>
 struct T {<br>
   virtual ~T() {}<br>
   virtual int v() { return 1; }<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=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Driver/<wbr>fsanitize.c?rev=309007&r1=<wbr>309006&r2=309007&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Driver/<wbr>fsanitize.c (original)<br>
+++ cfe/trunk/test/Driver/<wbr>fsanitize.c Tue Jul 25 12:34:23 2017<br>
@@ -58,6 +58,10 @@<br>
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-<wbr>UNDEFINED-NO-RTTI<br>
 // CHECK-UNDEFINED-NO-RTTI-NOT: vptr<br>
<br>
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=undefined -fno-sanitize=null %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-<wbr>NULL<br>
+// RUN: %clang -target x86_64-linux-gnu -fsanitize=vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-NO-<wbr>NULL<br>
+// CHECK-VPTR-NO-NULL: warning: implicitly disabling vptr sanitizer because null checking wasn't enabled<br>
+<br>
 // RUN: %clang -target x86_64-linux-gnu -fsanitize=address,thread -fno-rtti %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-SANA-SANT<br>
 // CHECK-SANA-SANT: '-fsanitize=address' not allowed with '-fsanitize=thread'<br>
<br>
@@ -362,8 +366,8 @@<br>
 // RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.8 -fsanitize=vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-<wbr>DARWIN-OLD<br>
 // CHECK-VPTR-DARWIN-OLD: unsupported option '-fsanitize=vptr' for target 'x86_64-apple-darwin10'<br>
<br>
-// RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.9 -fsanitize=alignment,vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-<wbr>DARWIN-NEW<br>
-// CHECK-VPTR-DARWIN-NEW: -fsanitize=alignment,vptr<br>
+// RUN: %clang -target x86_64-apple-darwin10 -mmacosx-version-min=10.9 -fsanitize=alignment,null,vptr %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-VPTR-<wbr>DARWIN-NEW<br>
+// CHECK-VPTR-DARWIN-NEW: -fsanitize=alignment,null,vptr<br>
<br>
 // RUN: %clang -target armv7-apple-ios7 -miphoneos-version-min=7.0 -fsanitize=address %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ASAN-IOS<br>
 // CHECK-ASAN-IOS: -fsanitize=address<br>
<br>
Modified: cfe/trunk/test/Driver/rtti-<wbr>options.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/rtti-options.cpp?rev=309007&r1=309006&r2=309007&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/Driver/<wbr>rtti-options.cpp?rev=309007&<wbr>r1=309006&r2=309007&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/Driver/rtti-<wbr>options.cpp (original)<br>
+++ cfe/trunk/test/Driver/rtti-<wbr>options.cpp Tue Jul 25 12:34:23 2017<br>
@@ -16,14 +16,14 @@<br>
 // Make sure we only error/warn once, when trying to enable vptr and<br>
 // undefined and have -fno-rtti<br>
 // RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=undefined -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR -check-prefix=CHECK-OK %s<br>
-// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s<br>
-// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s<br>
-// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s<br>
+// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=null,vptr %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s<br>
+// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=null,vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s<br>
+// RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=null,vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s<br>
 // RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=undefined %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s<br>
 // RUN: %clang -### -c -target x86_64-unknown-linux -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s<br>
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-WARN %s<br>
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s<br>
-// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s<br>
+// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=null,vptr %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-WARN %s<br>
+// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=null,vptr -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s<br>
+// RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=null,vptr -fno-rtti %s 2>&1 | FileCheck -check-prefix=CHECK-SAN-ERROR %s<br>
 // RUN: %clang -### -c -target x86_64-scei-ps4 -fsanitize=undefined -frtti %s 2>&1 | FileCheck -check-prefix=CHECK-OK %s<br>
<br>
 // Exceptions + no/default rtti<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>