r300370 - [ubsan] Reduce alignment checking of C++ object pointers

Vedant Kumar via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 14 15:03:34 PDT 2017


Author: vedantk
Date: Fri Apr 14 17:03:34 2017
New Revision: 300370

URL: http://llvm.org/viewvc/llvm-project?rev=300370&view=rev
Log:
[ubsan] Reduce alignment checking of C++ object pointers

This patch teaches ubsan to insert an alignment check for the 'this'
pointer at the start of each method/lambda. This allows clang to emit
significantly fewer alignment checks overall, because if 'this' is
aligned, so are its fields.

This is essentially the same thing r295515 does, but for the alignment
check instead of the null check. One difference is that we keep the
alignment checks on member expressions where the base is a DeclRefExpr.
There's an opportunity to diagnose unaligned accesses in this situation
(as pointed out by Eli, see PR32630).

Testing: check-clang, check-ubsan, and a stage2 ubsan build.

Along with the patch from D30285, this roughly halves the amount of
alignment checks we emit when compiling X86FastISel.cpp. Here are the
numbers from patched/unpatched clangs based on r298160.

  ------------------------------------------
  | Setup          | # of alignment checks |
  ------------------------------------------
  | unpatched, -O0 |                 24326 |
  | patched, -O0   |                 12717 | (-47.7%)
  ------------------------------------------

Differential Revision: https://reviews.llvm.org/D30283

Added:
    cfe/trunk/test/CodeGenCXX/ubsan-global-alignment.cpp
    cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp
Removed:
    cfe/trunk/test/CodeGenCXX/ubsan-suppress-null-checks.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGExpr.cpp
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.h
    cfe/trunk/test/CodeGenCXX/ubsan-type-checks.cpp

Modified: cfe/trunk/lib/CodeGen/CGExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExpr.cpp?rev=300370&r1=300369&r2=300370&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExpr.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExpr.cpp Fri Apr 14 17:03:34 2017
@@ -954,10 +954,7 @@ LValue CodeGenFunction::EmitUnsupportedL
                         E->getType());
 }
 
-bool CodeGenFunction::IsDeclRefOrWrappedCXXThis(const Expr *Obj) {
-  if (isa<DeclRefExpr>(Obj))
-    return true;
-
+bool CodeGenFunction::IsWrappedCXXThis(const Expr *Obj) {
   const Expr *Base = Obj;
   while (!isa<CXXThisExpr>(Base)) {
     // The result of a dynamic_cast can be null.
@@ -988,9 +985,13 @@ LValue CodeGenFunction::EmitCheckedLValu
     LV = EmitLValue(E);
   if (!isa<DeclRefExpr>(E) && !LV.isBitField() && LV.isSimple()) {
     SanitizerSet SkippedChecks;
-    if (const auto *ME = dyn_cast<MemberExpr>(E))
-      if (IsDeclRefOrWrappedCXXThis(ME->getBase()))
+    if (const auto *ME = dyn_cast<MemberExpr>(E)) {
+      bool IsBaseCXXThis = IsWrappedCXXThis(ME->getBase());
+      if (IsBaseCXXThis)
+        SkippedChecks.set(SanitizerKind::Alignment, true);
+      if (IsBaseCXXThis || isa<DeclRefExpr>(ME->getBase()))
         SkippedChecks.set(SanitizerKind::Null, true);
+    }
     EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(),
                   E->getType(), LV.getAlignment(), SkippedChecks);
   }
@@ -3429,7 +3430,10 @@ LValue CodeGenFunction::EmitMemberExpr(c
     Address Addr = EmitPointerWithAlignment(BaseExpr, &AlignSource);
     QualType PtrTy = BaseExpr->getType()->getPointeeType();
     SanitizerSet SkippedChecks;
-    if (IsDeclRefOrWrappedCXXThis(BaseExpr))
+    bool IsBaseCXXThis = IsWrappedCXXThis(BaseExpr);
+    if (IsBaseCXXThis)
+      SkippedChecks.set(SanitizerKind::Alignment, true);
+    if (IsBaseCXXThis || isa<DeclRefExpr>(BaseExpr))
       SkippedChecks.set(SanitizerKind::Null, true);
     EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy,
                   /*Alignment=*/CharUnits::Zero(), SkippedChecks);

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=300370&r1=300369&r2=300370&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Fri Apr 14 17:03:34 2017
@@ -301,9 +301,14 @@ RValue CodeGenFunction::EmitCXXMemberOrO
     CallLoc = CE->getExprLoc();
 
   SanitizerSet SkippedChecks;
-  if (const auto *CMCE = dyn_cast<CXXMemberCallExpr>(CE))
-    if (IsDeclRefOrWrappedCXXThis(CMCE->getImplicitObjectArgument()))
+  if (const auto *CMCE = dyn_cast<CXXMemberCallExpr>(CE)) {
+    auto *IOA = CMCE->getImplicitObjectArgument();
+    bool IsImplicitObjectCXXThis = IsWrappedCXXThis(IOA);
+    if (IsImplicitObjectCXXThis)
+      SkippedChecks.set(SanitizerKind::Alignment, true);
+    if (IsImplicitObjectCXXThis || isa<DeclRefExpr>(IOA))
       SkippedChecks.set(SanitizerKind::Null, true);
+  }
   EmitTypeCheck(
       isa<CXXConstructorDecl>(CalleeDecl) ? CodeGenFunction::TCK_ConstructorCall
                                           : CodeGenFunction::TCK_MemberCall,

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=300370&r1=300369&r2=300370&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Fri Apr 14 17:03:34 2017
@@ -963,13 +963,14 @@ void CodeGenFunction::StartFunction(Glob
       CXXThisValue = CXXABIThisValue;
     }
 
-    // Null-check the 'this' pointer once per function, if it's available.
+    // Check the 'this' pointer once per function, if it's available.
     if (CXXThisValue) {
       SanitizerSet SkippedChecks;
-      SkippedChecks.set(SanitizerKind::Alignment, true);
       SkippedChecks.set(SanitizerKind::ObjectSize, true);
-      EmitTypeCheck(TCK_Load, Loc, CXXThisValue, MD->getThisType(getContext()),
-                    /*Alignment=*/CharUnits::Zero(), SkippedChecks);
+      QualType ThisTy = MD->getThisType(getContext());
+      EmitTypeCheck(TCK_Load, Loc, CXXThisValue, ThisTy,
+                    getContext().getTypeAlignInChars(ThisTy->getPointeeType()),
+                    SkippedChecks);
     }
   }
 

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=300370&r1=300369&r2=300370&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Fri Apr 14 17:03:34 2017
@@ -2077,9 +2077,8 @@ public:
   llvm::BlockAddress *GetAddrOfLabel(const LabelDecl *L);
   llvm::BasicBlock *GetIndirectGotoBlock();
 
-  /// Check if \p E is a reference, or a C++ "this" pointer wrapped in value-
-  /// preserving casts.
-  static bool IsDeclRefOrWrappedCXXThis(const Expr *E);
+  /// Check if \p E is a C++ "this" pointer wrapped in value-preserving casts.
+  static bool IsWrappedCXXThis(const Expr *E);
 
   /// EmitNullInitialization - Generate code to set a value of the given type to
   /// null, If the type contains data member pointers, they will be initialized

Added: cfe/trunk/test/CodeGenCXX/ubsan-global-alignment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ubsan-global-alignment.cpp?rev=300370&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/ubsan-global-alignment.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/ubsan-global-alignment.cpp Fri Apr 14 17:03:34 2017
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s
+
+struct S {
+  int I;
+};
+
+extern S g_S;
+extern S array_S[];
+
+// CHECK-LABEL: define i32 @_Z18load_extern_global
+int load_extern_global() {
+  // FIXME: The IR builder constant-folds the alignment check away to 'true'
+  // here, so we never call the diagnostic. This is PR32630.
+  // CHECK-NOT: ptrtoint i32* {{.*}} to i32, !nosanitize
+  // CHECK: [[I:%.*]] = load i32, i32* getelementptr inbounds (%struct.S, %struct.S* @g_S, i32 0, i32 0), align 4
+  // CHECK-NEXT: ret i32 [[I]]
+  return g_S.I;
+}
+
+// CHECK-LABEL: define i32 @_Z22load_from_extern_array
+int load_from_extern_array(int I) {
+  // CHECK: [[I:%.*]] = getelementptr inbounds %struct.S, %struct.S* {{.*}}, i32 0, i32 0
+  // CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint i32* [[I]] to i64, !nosanitize
+  // CHECK-NEXT: [[AND:%.*]] = and i64 [[PTRTOINT]], 3, !nosanitize
+  // CHECK-NEXT: [[ICMP:%.*]] = icmp eq i64 [[AND]], 0, !nosanitize
+  // CHECK-NEXT: br i1 [[ICMP]]
+  // CHECK: call void @__ubsan_handle_type_mismatch
+  return array_S[I].I;
+}

Added: cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp?rev=300370&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp Fri Apr 14 17:03:34 2017
@@ -0,0 +1,221 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s --check-prefixes=CHECK,ALIGN
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s --check-prefixes=CHECK,NULL
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment,null -DCHECK_LAMBDA | FileCheck %s --check-prefixes=LAMBDA
+
+struct A {
+  int foo;
+
+  // CHECK-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv
+  void do_nothing() {
+    // ALIGN: %[[THISINT1:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %[[THISINT1]], 3, !nosanitize
+    // NULL: icmp ne %struct.A* %[[THIS1:[a-z0-9]+]], null, !nosanitize
+    // NULL: ptrtoint %struct.A* %[[THIS1]] to i64, !nosanitize
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
+    // CHECK: ret void
+  }
+
+#ifdef CHECK_LAMBDA
+  // LAMBDA-LABEL: define linkonce_odr void @_ZN1A22do_nothing_with_lambdaEv
+  void do_nothing_with_lambda() {
+    // LAMBDA: icmp ne %struct.A* %[[THIS2:[a-z0-9]+]], null, !nosanitize
+    // LAMBDA: %[[THISINT2:[0-9]+]] = ptrtoint %struct.A* %[[THIS2]] to i64, !nosanitize
+    // LAMBDA: and i64 %[[THISINT2]], 3, !nosanitize
+    // LAMBDA: call void @__ubsan_handle_type_mismatch
+
+    auto f = [&] {
+      foo = 0;
+    };
+    f();
+
+    // LAMBDA: icmp ne %class.anon* %[[FUNCVAR:.*]], null, !nosanitize
+    // LAMBDA: %[[LAMBDAINT:[0-9]+]] = ptrtoint %class.anon* %[[FUNCVAR]] to i64, !nosanitize
+    // LAMBDA: and i64 %[[LAMBDAINT]], 7, !nosanitize
+    // LAMBDA: call void @__ubsan_handle_type_mismatch
+
+    // LAMBDA-NOT: call void @__ubsan_handle_type_mismatch
+    // LAMBDA: ret void
+  }
+
+// Check the IR for the lambda:
+//
+// LAMBDA-LABEL: define linkonce_odr void @_ZZN1A22do_nothing_with_lambdaEvENKUlvE_clEv
+// LAMBDA: call void @__ubsan_handle_type_mismatch
+// LAMBDA-NOT: call void @__ubsan_handle_type_mismatch
+// LAMBDA: ret void
+#endif
+
+  // CHECK-LABEL: define linkonce_odr i32 @_ZN1A11load_memberEv
+  int load_member() {
+    // ALIGN: %[[THISINT3:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %[[THISINT3]], 3, !nosanitize
+    // NULL: icmp ne %struct.A* %[[THIS3:[a-z0-9]+]], null, !nosanitize
+    // NULL: ptrtoint %struct.A* %[[THIS3]] to i64, !nosanitize
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
+    return foo;
+    // CHECK: ret i32
+  }
+
+  // CHECK-LABEL: define linkonce_odr i32 @_ZN1A11call_methodEv
+  int call_method() {
+    // ALIGN: %[[THISINT4:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %[[THISINT4]], 3, !nosanitize
+    // NULL: icmp ne %struct.A* %[[THIS4:[a-z0-9]+]], null, !nosanitize
+    // NULL: ptrtoint %struct.A* %[[THIS4]] to i64, !nosanitize
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
+    return load_member();
+    // CHECK: ret i32
+  }
+
+  // CHECK-LABEL: define linkonce_odr void @_ZN1A15assign_member_1Ev
+  void assign_member_1() {
+    // ALIGN: %[[THISINT5:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %[[THISINT5]], 3, !nosanitize
+    // NULL: icmp ne %struct.A* %[[THIS5:[a-z0-9]+]], null, !nosanitize
+    // NULL: ptrtoint %struct.A* %[[THIS5]] to i64, !nosanitize
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
+    foo = 0;
+    // CHECK: ret void
+  }
+
+  // CHECK-LABEL: define linkonce_odr void @_ZN1A15assign_member_2Ev
+  void assign_member_2() {
+    // ALIGN: %[[THISINT6:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %[[THISINT6]], 3, !nosanitize
+    // NULL: icmp ne %struct.A* %[[THIS6:[a-z0-9]+]], null, !nosanitize
+    // NULL: ptrtoint %struct.A* %[[THIS6]] to i64, !nosanitize
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
+    (__extension__ (this))->foo = 0;
+    // CHECK: ret void
+  }
+
+  // CHECK-LABEL: define linkonce_odr void @_ZNK1A15assign_member_3Ev
+  void assign_member_3() const {
+    // ALIGN: %[[THISINT7:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %[[THISINT7]], 3, !nosanitize
+    // NULL: icmp ne %struct.A* %[[THIS7:[a-z0-9]+]], null, !nosanitize
+    // NULL: ptrtoint %struct.A* %[[THIS7]] to i64, !nosanitize
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
+    const_cast<A *>(this)->foo = 0;
+    // CHECK: ret void
+  }
+
+  // CHECK-LABEL: define linkonce_odr i32 @_ZN1A22call_through_referenceERS_
+  static int call_through_reference(A &a) {
+    // ALIGN: %[[OBJINT:[0-9]+]] = ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %[[OBJINT]], 3, !nosanitize
+    // ALIGN: call void @__ubsan_handle_type_mismatch
+    // NULL-NOT: call void @__ubsan_handle_type_mismatch
+    return a.load_member();
+    // CHECK: ret i32
+  }
+
+  // CHECK-LABEL: define linkonce_odr i32 @_ZN1A20call_through_pointerEPS_
+  static int call_through_pointer(A *a) {
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    return a->load_member();
+    // CHECK: ret i32
+  }
+};
+
+struct B {
+  operator A*() const { return nullptr; }
+
+  // CHECK-LABEL: define linkonce_odr i32 @_ZN1B11load_memberEv
+  static int load_member() {
+    // Check &b before converting it to an A*.
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    //
+    // Check the result of the conversion before using it.
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    //
+    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
+    B b;
+    return static_cast<A *>(b)->load_member();
+    // CHECK: ret i32
+  }
+};
+
+struct Base {
+  int foo;
+
+  virtual int load_member_1() = 0;
+};
+
+struct Derived : public Base {
+  int bar;
+
+  // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_2Ev
+  int load_member_2() {
+    // ALIGN: %[[THISINT8:[0-9]+]] = ptrtoint %struct.Derived* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %[[THISINT8]], 7, !nosanitize
+    // ALIGN: call void @__ubsan_handle_type_mismatch
+    // NULL: icmp ne %struct.Derived* %[[THIS8:[a-z0-9]+]], null, !nosanitize
+    // NULL: ptrtoint %struct.Derived* %[[THIS8]] to i64, !nosanitize
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    //
+    // Check the result of the cast before using it.
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    //
+    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
+    return dynamic_cast<Base *>(this)->load_member_1();
+    // CHECK: ret i32
+  }
+
+  // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_3Ev
+  int load_member_3() {
+    // ALIGN: %[[THISINT9:[0-9]+]] = ptrtoint %struct.Derived* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %[[THISINT9]], 7, !nosanitize
+    // ALIGN: call void @__ubsan_handle_type_mismatch
+    // ALIGN: call void @__ubsan_handle_type_mismatch
+    // NULL: icmp ne %struct.Derived* %[[THIS9:[a-z0-9]+]], null, !nosanitize
+    // NULL: ptrtoint %struct.Derived* %[[THIS9]] to i64, !nosanitize
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
+    return reinterpret_cast<Derived *>(static_cast<Base *>(this))->foo;
+    // CHECK: ret i32
+  }
+
+  // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_1Ev
+  int load_member_1() override {
+    // ALIGN: %[[THISINT10:[0-9]+]] = ptrtoint %struct.Derived* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %[[THISINT10]], 7, !nosanitize
+    // ALIGN: call void @__ubsan_handle_type_mismatch
+    // NULL: icmp ne %struct.Derived* %[[THIS10:[a-z0-9]+]], null, !nosanitize
+    // NULL: ptrtoint %struct.Derived* %[[THIS10]] to i64, !nosanitize
+    // CHECK: call void @__ubsan_handle_type_mismatch
+    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
+    return foo + bar;
+    // CHECK: ret i32
+  }
+};
+
+void force_irgen() {
+  A *a;
+  a->do_nothing();
+#ifdef CHECK_LAMBDA
+  a->do_nothing_with_lambda();
+#endif
+  a->load_member();
+  a->call_method();
+  a->assign_member_1();
+  a->assign_member_2();
+  a->assign_member_3();
+  A::call_through_reference(*a);
+  A::call_through_pointer(a);
+
+  B::load_member();
+
+  Base *b = new Derived;
+  b->load_member_1();
+
+  Derived *d;
+  d->load_member_2();
+  d->load_member_3();
+}

Removed: cfe/trunk/test/CodeGenCXX/ubsan-suppress-null-checks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ubsan-suppress-null-checks.cpp?rev=300369&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/ubsan-suppress-null-checks.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/ubsan-suppress-null-checks.cpp (removed)
@@ -1,188 +0,0 @@
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null | FileCheck %s
-// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=null -DCHECK_LAMBDA | FileCheck %s --check-prefix=LAMBDA
-
-struct A {
-  int foo;
-
-  // CHECK-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv
-  void do_nothing() {
-    // CHECK: icmp ne %struct.A* %[[THIS1:[a-z0-9]+]], null, !nosanitize
-    // CHECK: ptrtoint %struct.A* %[[THIS1]] to i64, !nosanitize
-    // CHECK-NEXT: call void @__ubsan_handle_type_mismatch
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    // CHECK: ret void
-  }
-
-#ifdef CHECK_LAMBDA
-  // LAMBDA-LABEL: define linkonce_odr void @_ZN1A22do_nothing_with_lambdaEv
-  void do_nothing_with_lambda() {
-    // LAMBDA: icmp ne %struct.A* %[[THIS2:[a-z0-9]+]], null, !nosanitize
-    // LAMBDA: ptrtoint %struct.A* %[[THIS2]] to i64, !nosanitize
-    // LAMBDA-NEXT: call void @__ubsan_handle_type_mismatch
-
-    auto f = [&] {
-      foo = 0;
-    };
-    f();
-
-    // LAMBDA: ret void
-  }
-
-// Check the IR for the lambda:
-//
-// LAMBDA-LABEL: define linkonce_odr void @_ZZN1A22do_nothing_with_lambdaEvENKUlvE_clEv
-// LAMBDA: call void @__ubsan_handle_type_mismatch
-// LAMBDA-NOT: call void @__ubsan_handle_type_mismatch
-// LAMBDA: ret void
-#endif
-
-  // CHECK-LABEL: define linkonce_odr i32 @_ZN1A11load_memberEv
-  int load_member() {
-    // CHECK: icmp ne %struct.A* %[[THIS3:[a-z0-9]+]], null, !nosanitize
-    // CHECK: ptrtoint %struct.A* %[[THIS3]] to i64, !nosanitize
-    // CHECK-NEXT: call void @__ubsan_handle_type_mismatch
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    return foo;
-    // CHECK: ret i32
-  }
-
-  // CHECK-LABEL: define linkonce_odr i32 @_ZN1A11call_methodEv
-  int call_method() {
-    // CHECK: icmp ne %struct.A* %[[THIS4:[a-z0-9]+]], null, !nosanitize
-    // CHECK: ptrtoint %struct.A* %[[THIS4]] to i64, !nosanitize
-    // CHECK-NEXT: call void @__ubsan_handle_type_mismatch
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    return load_member();
-    // CHECK: ret i32
-  }
-
-  // CHECK-LABEL: define linkonce_odr void @_ZN1A15assign_member_1Ev
-  void assign_member_1() {
-    // CHECK: icmp ne %struct.A* %[[THIS5:[a-z0-9]+]], null, !nosanitize
-    // CHECK: ptrtoint %struct.A* %[[THIS5]] to i64, !nosanitize
-    // CHECK-NEXT: call void @__ubsan_handle_type_mismatch
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    foo = 0;
-    // CHECK: ret void
-  }
-
-  // CHECK-LABEL: define linkonce_odr void @_ZN1A15assign_member_2Ev
-  void assign_member_2() {
-    // CHECK: icmp ne %struct.A* %[[THIS6:[a-z0-9]+]], null, !nosanitize
-    // CHECK: ptrtoint %struct.A* %[[THIS6]] to i64, !nosanitize
-    // CHECK-NEXT: call void @__ubsan_handle_type_mismatch
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    (__extension__ (this))->foo = 0;
-    // CHECK: ret void
-  }
-
-  // CHECK-LABEL: define linkonce_odr void @_ZNK1A15assign_member_3Ev
-  void assign_member_3() const {
-    // CHECK: icmp ne %struct.A* %[[THIS7:[a-z0-9]+]], null, !nosanitize
-    // CHECK: ptrtoint %struct.A* %[[THIS7]] to i64, !nosanitize
-    // CHECK-NEXT: call void @__ubsan_handle_type_mismatch
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    const_cast<A *>(this)->foo = 0;
-    // CHECK: ret void
-  }
-
-  // CHECK-LABEL: define linkonce_odr i32 @_ZN1A22call_through_referenceERS_
-  static int call_through_reference(A &a) {
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    return a.load_member();
-    // CHECK: ret i32
-  }
-
-  // CHECK-LABEL: define linkonce_odr i32 @_ZN1A20call_through_pointerEPS_
-  static int call_through_pointer(A *a) {
-    // CHECK: call void @__ubsan_handle_type_mismatch
-    return a->load_member();
-    // CHECK: ret i32
-  }
-};
-
-struct B {
-  operator A*() const { return nullptr; }
-
-  // CHECK-LABEL: define linkonce_odr i32 @_ZN1B11load_memberEv
-  static int load_member() {
-    // Null-check &b before converting it to an A*.
-    // CHECK: call void @__ubsan_handle_type_mismatch
-    //
-    // Null-check the result of the conversion before using it.
-    // CHECK: call void @__ubsan_handle_type_mismatch
-    //
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    B b;
-    return static_cast<A *>(b)->load_member();
-    // CHECK: ret i32
-  }
-};
-
-struct Base {
-  int foo;
-
-  virtual int load_member_1() = 0;
-};
-
-struct Derived : public Base {
-  int bar;
-
-  // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_2Ev
-  int load_member_2() {
-    // CHECK: icmp ne %struct.Derived* %[[THIS8:[a-z0-9]+]], null, !nosanitize
-    // CHECK: ptrtoint %struct.Derived* %[[THIS8]] to i64, !nosanitize
-    // CHECK-NEXT: call void @__ubsan_handle_type_mismatch
-    //
-    // Null-check the result of the cast before using it.
-    // CHECK: call void @__ubsan_handle_type_mismatch
-    //
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    return dynamic_cast<Base *>(this)->load_member_1();
-    // CHECK: ret i32
-  }
-
-  // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_3Ev
-  int load_member_3() {
-    // CHECK: icmp ne %struct.Derived* %[[THIS9:[a-z0-9]+]], null, !nosanitize
-    // CHECK: ptrtoint %struct.Derived* %[[THIS9]] to i64, !nosanitize
-    // CHECK-NEXT: call void @__ubsan_handle_type_mismatch
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    return reinterpret_cast<Derived *>(static_cast<Base *>(this))->foo;
-    // CHECK: ret i32
-  }
-
-  // CHECK-LABEL: define linkonce_odr i32 @_ZN7Derived13load_member_1Ev
-  int load_member_1() override {
-    // CHECK: icmp ne %struct.Derived* %[[THIS10:[a-z0-9]+]], null, !nosanitize
-    // CHECK: ptrtoint %struct.Derived* %[[THIS10]] to i64, !nosanitize
-    // CHECK-NEXT: call void @__ubsan_handle_type_mismatch
-    // CHECK-NOT: call void @__ubsan_handle_type_mismatch
-    return foo + bar;
-    // CHECK: ret i32
-  }
-};
-
-void force_irgen() {
-  A *a;
-  a->do_nothing();
-#ifdef CHECK_LAMBDA
-  a->do_nothing_with_lambda();
-#endif
-  a->load_member();
-  a->call_method();
-  a->assign_member_1();
-  a->assign_member_2();
-  a->assign_member_3();
-  A::call_through_reference(*a);
-  A::call_through_pointer(a);
-
-  B::load_member();
-
-  Base *b = new Derived;
-  b->load_member_1();
-
-  Derived *d;
-  d->load_member_2();
-  d->load_member_3();
-}

Modified: cfe/trunk/test/CodeGenCXX/ubsan-type-checks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/ubsan-type-checks.cpp?rev=300370&r1=300369&r2=300370&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/ubsan-type-checks.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/ubsan-type-checks.cpp Fri Apr 14 17:03:34 2017
@@ -5,8 +5,8 @@
 struct A {
   // COMMON-LABEL: define linkonce_odr void @_ZN1A10do_nothingEv
   void do_nothing() {
-    // ALIGN-NOT: ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
-    // ALIGN-NOT: and i64 %{{.*}}, 7, !nosanitize
+    // ALIGN: ptrtoint %struct.A* %{{.*}} to i64, !nosanitize
+    // ALIGN: and i64 %{{.*}}, 0, !nosanitize
  
     // NULL: icmp ne %struct.A* %{{.*}}, null, !nosanitize
  




More information about the cfe-commits mailing list