Index: cfe/trunk/lib/CodeGen/CGExpr.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGExpr.cpp +++ cfe/trunk/lib/CodeGen/CGExpr.cpp @@ -954,10 +954,7 @@ E->getType()); } -bool CodeGenFunction::IsDeclRefOrWrappedCXXThis(const Expr *Obj) { - if (isa(Obj)) - return true; - +bool CodeGenFunction::IsWrappedCXXThis(const Expr *Obj) { const Expr *Base = Obj; while (!isa(Base)) { // The result of a dynamic_cast can be null. @@ -988,9 +985,13 @@ LV = EmitLValue(E); if (!isa(E) && !LV.isBitField() && LV.isSimple()) { SanitizerSet SkippedChecks; - if (const auto *ME = dyn_cast(E)) - if (IsDeclRefOrWrappedCXXThis(ME->getBase())) + if (const auto *ME = dyn_cast(E)) { + bool IsBaseCXXThis = IsWrappedCXXThis(ME->getBase()); + if (IsBaseCXXThis) + SkippedChecks.set(SanitizerKind::Alignment, true); + if (IsBaseCXXThis || isa(ME->getBase())) SkippedChecks.set(SanitizerKind::Null, true); + } EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(), E->getType(), LV.getAlignment(), SkippedChecks); } @@ -3429,7 +3430,10 @@ 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(BaseExpr)) SkippedChecks.set(SanitizerKind::Null, true); EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, /*Alignment=*/CharUnits::Zero(), SkippedChecks); Index: cfe/trunk/lib/CodeGen/CGExprCXX.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGExprCXX.cpp +++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp @@ -301,9 +301,14 @@ CallLoc = CE->getExprLoc(); SanitizerSet SkippedChecks; - if (const auto *CMCE = dyn_cast(CE)) - if (IsDeclRefOrWrappedCXXThis(CMCE->getImplicitObjectArgument())) + if (const auto *CMCE = dyn_cast(CE)) { + auto *IOA = CMCE->getImplicitObjectArgument(); + bool IsImplicitObjectCXXThis = IsWrappedCXXThis(IOA); + if (IsImplicitObjectCXXThis) + SkippedChecks.set(SanitizerKind::Alignment, true); + if (IsImplicitObjectCXXThis || isa(IOA)) SkippedChecks.set(SanitizerKind::Null, true); + } EmitTypeCheck( isa(CalleeDecl) ? CodeGenFunction::TCK_ConstructorCall : CodeGenFunction::TCK_MemberCall, Index: cfe/trunk/lib/CodeGen/CodeGenFunction.h =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.h +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h @@ -2077,9 +2077,8 @@ 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 Index: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp @@ -963,13 +963,14 @@ 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); } } Index: cfe/trunk/test/CodeGenCXX/ubsan-global-alignment.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/ubsan-global-alignment.cpp +++ cfe/trunk/test/CodeGenCXX/ubsan-global-alignment.cpp @@ -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; +} Index: cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp +++ cfe/trunk/test/CodeGenCXX/ubsan-suppress-checks.cpp @@ -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(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(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(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(static_cast(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(); +} Index: cfe/trunk/test/CodeGenCXX/ubsan-suppress-null-checks.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/ubsan-suppress-null-checks.cpp +++ cfe/trunk/test/CodeGenCXX/ubsan-suppress-null-checks.cpp @@ -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(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(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(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(static_cast(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(); -} Index: cfe/trunk/test/CodeGenCXX/ubsan-type-checks.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/ubsan-type-checks.cpp +++ cfe/trunk/test/CodeGenCXX/ubsan-type-checks.cpp @@ -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