Index: lib/CodeGen/CGExpr.cpp =================================================================== --- lib/CodeGen/CGExpr.cpp +++ lib/CodeGen/CGExpr.cpp @@ -986,9 +986,12 @@ 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)) { + if (IsDeclRefOrWrappedCXXThis(ME->getBase())) { + SkippedChecks.set(SanitizerKind::Alignment, true); SkippedChecks.set(SanitizerKind::Null, true); + } + } EmitTypeCheck(TCK, E->getExprLoc(), LV.getPointer(), E->getType(), LV.getAlignment(), SkippedChecks); } @@ -3406,8 +3409,10 @@ Address Addr = EmitPointerWithAlignment(BaseExpr, &AlignSource); QualType PtrTy = BaseExpr->getType()->getPointeeType(); SanitizerSet SkippedChecks; - if (IsDeclRefOrWrappedCXXThis(BaseExpr)) + if (IsDeclRefOrWrappedCXXThis(BaseExpr)) { + SkippedChecks.set(SanitizerKind::Alignment, true); SkippedChecks.set(SanitizerKind::Null, true); + } EmitTypeCheck(TCK_MemberAccess, E->getExprLoc(), Addr.getPointer(), PtrTy, /*Alignment=*/CharUnits::Zero(), SkippedChecks); BaseLV = MakeAddrLValue(Addr, PtrTy, AlignSource); Index: lib/CodeGen/CGExprCXX.cpp =================================================================== --- lib/CodeGen/CGExprCXX.cpp +++ lib/CodeGen/CGExprCXX.cpp @@ -301,9 +301,13 @@ 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(); + if (IsDeclRefOrWrappedCXXThis(IOA)) { + SkippedChecks.set(SanitizerKind::Alignment, true); SkippedChecks.set(SanitizerKind::Null, true); + } + } EmitTypeCheck( isa(CalleeDecl) ? CodeGenFunction::TCK_ConstructorCall : CodeGenFunction::TCK_MemberCall, Index: lib/CodeGen/CodeGenFunction.cpp =================================================================== --- lib/CodeGen/CodeGenFunction.cpp +++ lib/CodeGen/CodeGenFunction.cpp @@ -967,13 +967,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: test/CodeGen/catch-undef-behavior.c =================================================================== --- test/CodeGen/catch-undef-behavior.c +++ test/CodeGen/catch-undef-behavior.c @@ -5,7 +5,7 @@ // CHECK-UBSAN: @[[INT:.*]] = private unnamed_addr constant { i16, i16, [6 x i8] } { i16 0, i16 11, [6 x i8] c"'int'\00" } // FIXME: When we only emit each type once, use [[INT]] more below. -// CHECK-UBSAN: @[[LINE_100:.*]] = private unnamed_addr global {{.*}}, i32 100, i32 5 {{.*}} @[[INT]], i8 2, i8 1 +// CHECK-UBSAN: @[[LINE_100:.*]] = private unnamed_addr global {{.*}}, i32 100, i32 5 {{.*}} @[[INT]], i8 1, i8 1 // CHECK-UBSAN: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 10 {{.*}}, i8 2, i8 0 // CHECK-UBSAN: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 12 {{.*}} @{{.*}}, {{.*}} @{{.*}} // CHECK-UBSAN: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 12 {{.*}} @{{.*}}, {{.*}} @{{.*}} @@ -38,14 +38,7 @@ // CHECK-COMMON-NEXT: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* %[[I8PTR]], i1 false) // CHECK-COMMON-NEXT: %[[CHECK0:.*]] = icmp uge i64 %[[SIZE]], 4 - // CHECK-COMMON: %[[PTRTOINT:.*]] = ptrtoint {{.*}}* %[[PTR]] to i64 - // CHECK-COMMON-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRTOINT]], 3 - // CHECK-COMMON-NEXT: %[[CHECK1:.*]] = icmp eq i64 %[[MISALIGN]], 0 - - // CHECK-COMMON: %[[OK:.*]] = and i1 %[[CHECK0]], %[[CHECK1]] - - // CHECK-UBSAN: br i1 %[[OK]], {{.*}} !prof ![[WEIGHT_MD:.*]], !nosanitize - // CHECK-TRAP: br i1 %[[OK]], {{.*}} + // CHECK-UBSAN: br i1 %[[CHECK0]], {{.*}} !prof ![[WEIGHT_MD:.*]], !nosanitize // CHECK-UBSAN: %[[ARG:.*]] = ptrtoint {{.*}} %[[PTR]] to i64 // CHECK-UBSAN-NEXT: call void @__ubsan_handle_type_mismatch_v1(i8* bitcast ({{.*}} @[[LINE_100]] to i8*), i64 %[[ARG]]) Index: test/CodeGen/sanitize-recover.c =================================================================== --- test/CodeGen/sanitize-recover.c +++ test/CodeGen/sanitize-recover.c @@ -22,15 +22,7 @@ // PARTIAL: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0i8(i8* {{.*}}, i1 false) // PARTIAL-NEXT: %[[CHECK0:.*]] = icmp uge i64 %[[SIZE]], 4 - // PARTIAL: %[[MISALIGN:.*]] = and i64 {{.*}}, 3 - // PARTIAL-NEXT: %[[CHECK1:.*]] = icmp eq i64 %[[MISALIGN]], 0 + // PARTIAL: br i1 %[[CHECK0]], {{.*}} !nosanitize - // PARTIAL: %[[CHECK01:.*]] = and i1 %[[CHECK1]], %[[CHECK0]] - - // PARTIAL: br i1 %[[CHECK01]], {{.*}} !nosanitize - // PARTIAL: br i1 %[[CHECK1]], {{.*}} !nosanitize - - // PARTIAL: call void @__ubsan_handle_type_mismatch_v1_abort( - // PARTIAL-NEXT: unreachable // PARTIAL: call void @__ubsan_handle_type_mismatch_v1( } Index: test/CodeGenCXX/ubsan-global-alignment.cpp =================================================================== --- /dev/null +++ test/CodeGenCXX/ubsan-global-alignment.cpp @@ -0,0 +1,71 @@ +// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -emit-llvm -o - %s -fsanitize=alignment | FileCheck %s + +struct S1 { + long long L; +}; + +extern int g_int; +extern S1 g_S1; +extern S1 *g_S1ptr; + +extern int int_array[]; +extern S1 S1_array[]; +extern S1 *S1ptr_array[]; + +// CHECK-LABEL: define i32 @_Z15load_extern_intv +int load_extern_int() { + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + // CHECK: [[LOAD:%.*]] = load i32, i32* @g_int, align 4 + // CHECK-NEXT: ret i32 [[LOAD]] + return g_int; +} + +long long load_extern_S1() { + // CHECK-NOT: call void @__ubsan_handle_type_mismatch + // CHECK: [[LOAD:%.*]] = load i64, i64* getelementptr inbounds (%struct.S1, %struct.S1* @g_S1, i32 0, i32 0), align 8 + // CHECK-NEXT: ret i64 [[LOAD]] + return g_S1.L; +} + +long long load_extern_S1ptr() { + // CHECK: [[L:%.*]] = getelementptr inbounds %struct.S1, %struct.S1* {{.*}}, i32 0, i32 0 + // CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint i64* [[L]] to i64, !nosanitize + // CHECK-NEXT: [[AND:%.*]] = and i64 [[PTRTOINT]], 7, !nosanitize + // CHECK-NEXT: [[ICMP:%.*]] = icmp eq i64 [[AND]], 0, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]] + // CHECK: call void @__ubsan_handle_type_mismatch + return g_S1ptr->L; +} + +// CHECK-LABEL: define i32 @_Z15index_int_arrayi +int index_int_array(int I) { + // CHECK: [[ARRAYIDX:%.*]] = getelementptr inbounds [0 x i32], [0 x i32]* @int_array, i64 0 + // CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint i32* [[ARRAYIDX]] 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 int_array[I]; +} + +// CHECK-LABEL: define i64 @_Z14index_S1_arrayi +long long index_S1_array(int I) { + // CHECK: [[L:%.*]] = getelementptr inbounds %struct.S1, %struct.S1* {{.*}}, i32 0, i32 0 + // CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint i64* [[L]] to i64, !nosanitize + // CHECK-NEXT: [[AND:%.*]] = and i64 [[PTRTOINT]], 7, !nosanitize + // CHECK-NEXT: [[ICMP:%.*]] = icmp eq i64 [[AND]], 0, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]] + // CHECK: call void @__ubsan_handle_type_mismatch + return S1_array[I].L; +} + +// CHECK-LABEL: define i64 @_Z17index_S1ptr_arrayi +long long index_S1ptr_array(int I) { + // CHECK: [[L:%.*]] = getelementptr inbounds %struct.S1, %struct.S1* {{.*}}, i32 0, i32 0 + // CHECK-NEXT: [[PTRTOINT:%.*]] = ptrtoint i64* [[L]] to i64, !nosanitize + // CHECK-NEXT: [[AND:%.*]] = and i64 [[PTRTOINT]], 7, !nosanitize + // CHECK-NEXT: [[ICMP:%.*]] = icmp eq i64 [[AND]], 0, !nosanitize + // CHECK-NEXT: br i1 [[ICMP]] + // CHECK: call void @__ubsan_handle_type_mismatch + return S1ptr_array[I]->L; +} Index: test/CodeGenCXX/ubsan-suppress-checks.cpp =================================================================== --- test/CodeGenCXX/ubsan-suppress-checks.cpp +++ test/CodeGenCXX/ubsan-suppress-checks.cpp @@ -1,14 +1,17 @@ -// 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 +// 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() { - // 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 + // 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 } @@ -17,8 +20,9 @@ // 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 + // 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; @@ -38,9 +42,11 @@ // 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 + // 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 @@ -48,9 +54,11 @@ // 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 + // 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 @@ -58,9 +66,11 @@ // 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 + // 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 @@ -68,9 +78,11 @@ // 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 + // 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 @@ -78,9 +90,11 @@ // 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 + // 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 @@ -106,10 +120,10 @@ // CHECK-LABEL: define linkonce_odr i32 @_ZN1B11load_memberEv static int load_member() { - // Null-check &b before converting it to an A*. + // 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 the result of the conversion before using it. // CHECK: call void @__ubsan_handle_type_mismatch // // CHECK-NOT: call void @__ubsan_handle_type_mismatch @@ -130,11 +144,14 @@ // 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 + // 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 // - // Null-check the result of the cast before using it. + // Check the result of the cast before using it. // CHECK: call void @__ubsan_handle_type_mismatch // // CHECK-NOT: call void @__ubsan_handle_type_mismatch @@ -144,9 +161,13 @@ // 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 + // 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 @@ -154,9 +175,12 @@ // 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 + // 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 Index: test/CodeGenCXX/ubsan-type-checks.cpp =================================================================== --- test/CodeGenCXX/ubsan-type-checks.cpp +++ 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