brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.7 KiB · 15feebe Raw
740 lines · cpp
1// RUN: %clang_cc1 -no-enable-noundef-analysis -std=c++11 -Wno-error=return-type -fsanitize=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,unreachable,return,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -fsanitize-recover=signed-integer-overflow,integer-divide-by-zero,float-divide-by-zero,shift-base,shift-exponent,vla-bound,alignment,null,vptr,object-size,float-cast-overflow,bool,enum,array-bounds,function -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-FUNCSAN2// RUN: %clang_cc1 -no-enable-noundef-analysis -std=c++11 -Wno-error=return-type -fsanitize=vptr,address -fsanitize-recover=vptr,address -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=CHECK-ASAN3// RUN: %clang_cc1 -no-enable-noundef-analysis -std=c++11 -Wno-error=return-type -fsanitize=vptr -fsanitize-recover=vptr -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefix=DOWNCAST-NULL4// RUN: %clang_cc1 -no-enable-noundef-analysis -std=c++11 -Wno-error=return-type -fsanitize=function -emit-llvm %s -o - -triple x86_64-linux-gnux32 | FileCheck %s --check-prefix=CHECK-FUNCSAN5// RUN: %clang_cc1 -no-enable-noundef-analysis -std=c++11 -Wno-error=return-type -fsanitize=function -emit-llvm %s -o - -triple i386-linux-gnu | FileCheck %s --check-prefix=CHECK-FUNCSAN6 7struct S {8  double d;9  int a, b;10  virtual int f();11};12 13// Check that type descriptor global is not modified by ASan.14// CHECK-ASAN: [[TYPE_DESCR:@[0-9]+]] = private unnamed_addr constant { i16, i16, [4 x i8] } { i16 -1, i16 0, [4 x i8] c"'S'\00" }15 16// Check that type mismatch handler is not modified by ASan.17// CHECK-ASAN: private unnamed_addr global { { ptr, i32, i32 }, ptr, ptr, i8 } { {{.*}}, ptr [[TYPE_DESCR]], {{.*}} }18 19struct T : S {};20 21// CHECK-LABEL: @_Z17reference_binding22void reference_binding(int *p, S *q) {23  // C++ core issue 453: If an lvalue to which a reference is directly bound24  // designates neither an existing object or function of an appropriate type,25  // nor a region of storage of suitable size and alignment to contain an object26  // of the reference's type, the behavior is undefined.27 28  // CHECK: icmp ne {{.*}}, null29 30  // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i6431  // CHECK-NEXT: icmp uge i64 %[[SIZE]], 432 33  // CHECK: %[[PTRINT:.*]] = ptrtoint34  // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 335  // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 036  int &r = *p;37 38  // A reference is not required to refer to an object within its lifetime.39  // CHECK-NOT: __ubsan_handle_dynamic_type_cache_miss40  S &r2 = *q;41}42 43// CHECK-LABEL: @_Z13member_access44// CHECK-ASAN-LABEL: @_Z13member_access45void member_access(S *p) {46  // (1a) Check 'p' is appropriately sized and aligned for member access.47 48  // CHECK: icmp ne {{.*}}, null49 50  // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i6451  // CHECK-NEXT: icmp uge i64 %[[SIZE]], 2452 53  // CHECK: %[[PTRINT:.*]] = ptrtoint54  // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 755  // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 056 57  // (1b) Check that 'p' actually points to an 'S'.58 59  // CHECK: %[[VTABLE:.*]] = load ptr, ptr %060  // CHECK: %[[VPTR:.*]] = ptrtoint ptr %[[VTABLE]] to i6461  // hash_16_bytes:62  //63  // If this number changes, it indicates that either the mangled name of ::S64  // has changed, or that LLVM's hashing function has changed. The latter case65  // is OK if the hashing function is still stable.66  //67  // The two hash values are for 64- and 32-bit Clang binaries, respectively.68  // FIXME: We should produce a 64-bit value either way.69  //70  // CHECK-NEXT: mul i64 %[[VPTR]], -4658895280553007687, !nosanitize71  // CHECK-NEXT: lshr i64 {{.*}}, 3172  // CHECK-NEXT: xor i64 %[[#]], %[[#]]73  // CHECK-NEXT: %[[HASH:.*]] = xor i64 4589795628539611399, %[[#]], !nosanitize74  //75  // Check the hash against the table:76  //77  // CHECK-NEXT: %[[IDX:.*]] = and i64 %{{.*}}, 12778  // CHECK-NEXT: getelementptr inbounds [128 x i64], ptr @__ubsan_vptr_type_cache, i32 0, i64 %[[IDX]]79  // CHECK-NEXT: %[[CACHEVAL:.*]] = load i64, ptr80  // CHECK-NEXT: icmp eq i64 %[[CACHEVAL]], %[[HASH]]81  // CHECK-NEXT: br i182 83  // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %[[HASH]])84  // CHECK-NOT: unreachable85  // CHECK: {{.*}}:86 87  // (2) Check 'p->b' is appropriately sized and aligned for a load.88 89  // FIXME: Suppress this in the trivial case of a member access, because we90  // know we've just checked the member access expression itself.91 92  // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i6493  // CHECK-NEXT: icmp uge i64 %[[SIZE]], 494 95  // CHECK: %[[PTRINT:.*]] = ptrtoint96  // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 397  // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 098  int k = p->b;99 100  // (3a) Check 'p' is appropriately sized and aligned for member function call.101 102  // CHECK: icmp ne {{.*}}, null103 104  // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64105  // CHECK-NEXT: icmp uge i64 %[[SIZE]], 24106 107  // CHECK: %[[PTRINT:.*]] = ptrtoint108  // CHECK-NEXT: %[[MISALIGN:.*]] = and i64 %[[PTRINT]], 7109  // CHECK-NEXT: icmp eq i64 %[[MISALIGN]], 0110 111  // (3b) Check that 'p' actually points to an 'S'112 113  // CHECK: [[VTABLE2:%.*]] = load ptr, ptr114  // CHECK: ptrtoint ptr [[VTABLE2]] to i64115  // CHECK-NEXT: mul i64 %[[#]], -4658895280553007687, !nosanitize116  // [...]117  // CHECK: getelementptr inbounds [128 x i64], ptr @__ubsan_vptr_type_cache, i32 0, i64 %118  // CHECK: br i1119  // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss({{.*}}, i64 %{{.*}}, i64 %{{.*}})120  // CHECK-NOT: unreachable121  // CHECK: {{.*}}:122 123  k = p->f();124}125 126// CHECK-LABEL: @_Z12lsh_overflow127int lsh_overflow(int a, int b) {128  // CHECK: %[[RHS_inbounds:.*]] = icmp ule i32 %[[RHS:.*]], 31129  // CHECK-NEXT: br i1 %[[RHS_inbounds]], label %[[CHECK_BB:.*]], label %[[CONT_BB:.*]],130 131  // CHECK:      [[CHECK_BB]]:132  // CHECK-NEXT: %[[SHIFTED_OUT_WIDTH:.*]] = sub nuw nsw i32 31, %[[RHS]]133  // CHECK-NEXT: %[[SHIFTED_OUT:.*]] = lshr i32 %[[LHS:.*]], %[[SHIFTED_OUT_WIDTH]]134 135  // This is present for C++11 but not for C: C++ core issue 1457 allows a '1'136  // to be shifted into the sign bit, but not out of it.137  // CHECK-NEXT: %[[SHIFTED_OUT_NOT_SIGN:.*]] = lshr i32 %[[SHIFTED_OUT]], 1138 139  // CHECK-NEXT: %[[NO_OVERFLOW:.*]] = icmp eq i32 %[[SHIFTED_OUT_NOT_SIGN]], 0140  // CHECK-NEXT: br label %[[CONT_BB]]141 142  // CHECK:      [[CONT_BB]]:143  // CHECK-NEXT: %[[VALID_BASE:.*]] = phi i1 [ true, {{.*}} ], [ %[[NO_OVERFLOW]], %[[CHECK_BB]] ]144  // CHECK-NEXT: %[[VALID:.*]] = and i1 %[[RHS_inbounds]], %[[VALID_BASE]]145  // CHECK-NEXT: br i1 %[[VALID]]146 147  // CHECK: call void @__ubsan_handle_shift_out_of_bounds148  // CHECK-NOT: call void @__ubsan_handle_shift_out_of_bounds149 150  // CHECK: %[[RET:.*]] = shl i32 %[[LHS]], %[[RHS]]151  // CHECK-NEXT: ret i32 %[[RET]]152  return a << b;153}154 155// CHECK-LABEL: @_Z9no_return156int no_return() {157  // CHECK:      call void @__ubsan_handle_missing_return(ptr @{{.*}}) [[NR_NUW:#[0-9]+]]158  // CHECK-NEXT: unreachable159}160 161// CHECK-LABEL: @_Z9sour_bool162bool sour_bool(bool *p) {163  // CHECK: %[[OK:.*]] = icmp ule i8 {{.*}}, 1164  // CHECK: br i1 %[[OK]]165  // CHECK: call void @__ubsan_handle_load_invalid_value(ptr @{{.*}}, i64 {{.*}})166  return *p;167}168 169enum E1 { e1a = 0, e1b = 127 } e1;170enum E2 { e2a = -1, e2b = 64 } e2;171enum E3 { e3a = (1u << 31) - 1 } e3;172 173// CHECK-LABEL: @_Z14bad_enum_value174int bad_enum_value() {175  // CHECK: %[[E1:.*]] = icmp ule i32 {{.*}}, 127176  // CHECK: br i1 %[[E1]]177  // CHECK: call void @__ubsan_handle_load_invalid_value(178  int a = e1;179 180  // CHECK: %[[E2HI:.*]] = icmp sle i32 {{.*}}, 127181  // CHECK: %[[E2LO:.*]] = icmp sge i32 {{.*}}, -128182  // CHECK: %[[E2:.*]] = and i1 %[[E2HI]], %[[E2LO]]183  // CHECK: br i1 %[[E2]]184  // CHECK: call void @__ubsan_handle_load_invalid_value(185  int b = e2;186 187  // CHECK: %[[E3:.*]] = icmp ule i32 {{.*}}, 2147483647188  // CHECK: br i1 %[[E3]]189  // CHECK: call void @__ubsan_handle_load_invalid_value(190  int c = e3;191  return a + b + c;192}193 194// CHECK-LABEL: @_Z20bad_downcast_pointer195// DOWNCAST-NULL-LABEL: @_Z20bad_downcast_pointer196void bad_downcast_pointer(S *p) {197  // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null198  // CHECK: br i1 %[[NONNULL]],199 200  // A null pointer access is guarded without -fsanitize=null.201  // DOWNCAST-NULL: %[[NONNULL:.*]] = icmp ne {{.*}}, null202  // DOWNCAST-NULL: br i1 %[[NONNULL]],203 204  // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0(205  // CHECK: %[[E1:.*]] = icmp uge i64 %[[SIZE]], 24206  // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7207  // CHECK: %[[E2:.*]] = icmp eq i64 %[[MISALIGN]], 0208  // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]]209  // CHECK: br i1 %[[E12]],210 211  // CHECK: call void @__ubsan_handle_type_mismatch212  // CHECK: br label213 214  // CHECK: br i1 %{{.*}},215 216  // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss217  // CHECK: br label218  (void) static_cast<T*>(p);219}220 221// CHECK-LABEL: @_Z22bad_downcast_reference222void bad_downcast_reference(S &p) {223  // CHECK: %[[E1:.*]] = icmp ne {{.*}}, null224  // CHECK-NOT: br i1225 226  // CHECK: %[[SIZE:.*]] = call i64 @llvm.objectsize.i64.p0(227  // CHECK: %[[E2:.*]] = icmp uge i64 %[[SIZE]], 24228 229  // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7230  // CHECK: %[[E3:.*]] = icmp eq i64 %[[MISALIGN]], 0231 232  // CHECK: %[[E12:.*]] = and i1 %[[E1]], %[[E2]]233  // CHECK: %[[E123:.*]] = and i1 %[[E12]], %[[E3]]234  // CHECK: br i1 %[[E123]],235 236  // CHECK: call void @__ubsan_handle_type_mismatch237  // CHECK: br label238 239  // CHECK: br i1 %{{.*}},240 241  // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss242  // CHECK: br label243  (void) static_cast<T&>(p);244}245 246// CHECK-LABEL: @_Z11array_index247int array_index(const int (&a)[4], int n) {248  // CHECK: %[[K1_OK:.*]] = icmp ult i64 %{{.*}}, 4249  // CHECK: br i1 %[[K1_OK]]250  // CHECK: call void @__ubsan_handle_out_of_bounds(251  int k1 = a[n];252 253  // CHECK: %[[R1_OK:.*]] = icmp ule i64 %{{.*}}, 4254  // CHECK: br i1 %[[R1_OK]]255  // CHECK: call void @__ubsan_handle_out_of_bounds(256  const int *r1 = &a[n];257 258  // CHECK: %[[K2_OK:.*]] = icmp ult i64 %{{.*}}, 8259  // CHECK: br i1 %[[K2_OK]]260  // CHECK: call void @__ubsan_handle_out_of_bounds(261  int k2 = ((const int(&)[8])a)[n];262 263  // CHECK: %[[K3_OK:.*]] = icmp ult i64 %{{.*}}, 4264  // CHECK: br i1 %[[K3_OK]]265  // CHECK: call void @__ubsan_handle_out_of_bounds(266  int k3 = n[a];267 268  return k1 + *r1 + k2;269}270 271// CHECK-LABEL: @_Z17multi_array_index272int multi_array_index(int n, int m) {273  int arr[4][6];274 275  // CHECK: %[[IDX1_OK:.*]] = icmp ult i64 %{{.*}}, 4276  // CHECK: br i1 %[[IDX1_OK]]277  // CHECK: call void @__ubsan_handle_out_of_bounds(278 279  // CHECK: %[[IDX2_OK:.*]] = icmp ult i64 %{{.*}}, 6280  // CHECK: br i1 %[[IDX2_OK]]281  // CHECK: call void @__ubsan_handle_out_of_bounds(282  return arr[n][m];283}284 285// CHECK-LABEL: @_Z11array_arith286int array_arith(const int (&a)[4], int n) {287  // CHECK: %[[K1_OK:.*]] = icmp ule i64 %{{.*}}, 4288  // CHECK: br i1 %[[K1_OK]]289  // CHECK: call void @__ubsan_handle_out_of_bounds(290  const int *k1 = a + n;291 292  // CHECK: %[[K2_OK:.*]] = icmp ule i64 %{{.*}}, 8293  // CHECK: br i1 %[[K2_OK]]294  // CHECK: call void @__ubsan_handle_out_of_bounds(295  const int *k2 = (const int(&)[8])a + n;296 297  return *k1 + *k2;298}299 300struct ArrayMembers {301  int a1[5];302  int a2[1];303};304// CHECK-LABEL: @_Z18struct_array_index305int struct_array_index(ArrayMembers *p, int n) {306  // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 5307  // CHECK: br i1 %[[IDX_OK]]308  // CHECK: call void @__ubsan_handle_out_of_bounds(309  return p->a1[n];310}311 312// CHECK-LABEL: @_Z16flex_array_index313int flex_array_index(ArrayMembers *p, int n) {314  // CHECK-NOT: call void @__ubsan_handle_out_of_bounds(315  return p->a2[n];316}317 318extern int incomplete[];319// CHECK-LABEL: @_Z22incomplete_array_index320int incomplete_array_index(int n) {321  // CHECK-NOT: call void @__ubsan_handle_out_of_bounds(322  return incomplete[n];323}324 325typedef __attribute__((ext_vector_type(4))) int V4I;326// CHECK-LABEL: @_Z12vector_index327int vector_index(V4I v, int n) {328  // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 4329  // CHECK: br i1 %[[IDX_OK]]330  // CHECK: call void @__ubsan_handle_out_of_bounds(331  return v[n];332}333 334// CHECK-LABEL: @_Z12string_index335char string_index(int n) {336  // CHECK: %[[IDX_OK:.*]] = icmp ult i64 %{{.*}}, 6337  // CHECK: br i1 %[[IDX_OK]]338  // CHECK: call void @__ubsan_handle_out_of_bounds(339  return "Hello"[n];340}341 342class A // align=4343{344  int a1, a2, a3;345};346 347class B // align=8348{349  long b1, b2;350};351 352class C : public A, public B // align=16353{354  alignas(16) int c1;355};356 357// Make sure we check the alignment of the pointer after subtracting any358// offset. The pointer before subtraction doesn't need to be aligned for359// the destination type.360 361// CHECK-LABEL: define{{.*}} void @_Z16downcast_pointerP1B(ptr %b)362void downcast_pointer(B *b) {363  (void) static_cast<C*>(b);364  // Alignment check from EmitTypeCheck(TCK_DowncastPointer, ...)365  // CHECK: [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, ptr {{.*}}, i64 -16366  // null check goes here367  // CHECK: [[FROM_PHI:%.+]] = phi ptr [ [[SUB]], {{.*}} ], {{.*}}368  // Objectsize check goes here369  // CHECK: [[C_INT:%.+]] = ptrtoint ptr [[FROM_PHI]] to i64370  // CHECK-NEXT: [[MASKED:%.+]] = and i64 [[C_INT]], 15371  // CHECK-NEXT: [[TEST:%.+]] = icmp eq i64 [[MASKED]], 0372  // AND the alignment test with the objectsize test.373  // CHECK-NEXT: [[AND:%.+]] = and i1 {{.*}}, [[TEST]]374  // CHECK-NEXT: br i1 [[AND]]375}376 377// CHECK-LABEL: define{{.*}} void @_Z18downcast_referenceR1B(ptr nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) %b)378void downcast_reference(B &b) {379  (void) static_cast<C&>(b);380  // Alignment check from EmitTypeCheck(TCK_DowncastReference, ...)381  // CHECK:      [[SUB:%[.a-z0-9]*]] = getelementptr inbounds i8, ptr {{.*}}, i64 -16382  // Objectsize check goes here383  // CHECK:      [[C_INT:%.+]] = ptrtoint ptr [[SUB]] to i64384  // CHECK-NEXT: [[MASKED:%.+]] = and i64 [[C_INT]], 15385  // CHECK-NEXT: [[TEST:%.+]] = icmp eq i64 [[MASKED]], 0386  // AND the alignment test with the objectsize test.387  // CHECK:      [[AND:%.+]] = and i1 {{.*}}, [[TEST]]388  // CHECK-NEXT: br i1 [[AND]]389}390 391// CHECK-FUNCSAN: @_Z22indirect_function_callPFviE({{.*}} !func_sanitize ![[FUNCSAN:.*]] {392void indirect_function_call(void (*p)(int)) {393  // CHECK: [[PTR:%.+]] = load ptr, ptr394 395  // Signature check396  // CHECK-NEXT: [[SIGPTR:%.+]] = getelementptr <{ i32, i32 }>, ptr [[PTR]], i32 -1, i32 0397  // CHECK-NEXT: [[SIG:%.+]] = load i32, ptr [[SIGPTR]]398  // CHECK-NEXT: [[SIGCMP:%.+]] = icmp eq i32 [[SIG]], -1056584962399  // CHECK-NEXT: br i1 [[SIGCMP]]400 401  // CalleeTypeHash check402  // CHECK: [[CalleeTypeHashPtr:%.+]] = getelementptr <{ i32, i32 }>, ptr [[PTR]], i32 -1, i32 1403  // CHECK-NEXT: [[CalleeTypeHash:%.+]] = load i32, ptr [[CalleeTypeHashPtr]]404  // CHECK-NEXT: [[CalleeTypeHashMatch:%.+]] = icmp eq i32 [[CalleeTypeHash]], -1988405058405  // CHECK-NEXT: br i1 [[CalleeTypeHashMatch]]406 407  p(42);408}409 410namespace VBaseObjectSize {411  // Note: C is laid out such that offsetof(C, B) + sizeof(B) extends outside412  // the C object.413  struct alignas(16) A { void *a1, *a2; };414  struct B : virtual A { void *b; void* g(); };415  struct C : virtual A, virtual B { };416  // CHECK-LABEL: define {{.*}} @_ZN15VBaseObjectSize1fERNS_1BE(417  B &f(B &b) {418    // Size check: check for nvsize(B) == 16 (do not require size(B) == 32)419    // CHECK: [[SIZE:%.+]] = call i{{32|64}} @llvm.objectsize.i64.p0(420    // CHECK: icmp uge i{{32|64}} [[SIZE]], 16,421 422    // Alignment check: check for nvalign(B) == 8 (do not require align(B) == 16)423    // CHECK: [[PTRTOINT:%.+]] = ptrtoint {{.*}} to i64,424    // CHECK: and i64 [[PTRTOINT]], 7,425    return b;426  }427 428  // CHECK-LABEL: define {{.*}} @_ZN15VBaseObjectSize1B1gEv(429  void *B::g() {430    // Ensure that the check on the "this" pointer also uses the proper431    // alignment. We should be using nvalign(B) == 8, not 16.432    // CHECK: [[PTRTOINT:%.+]] = ptrtoint {{.*}} to i64,433    // CHECK: and i64 [[PTRTOINT]], 7434    return nullptr;435  }436}437 438namespace FunctionSanitizerVirtualCalls {439struct A {440  virtual void f() {}441  virtual void g() {}442  void h() {}443};444 445struct B : virtual A {446  virtual void b() {}447  virtual void f();448  void g() final {}449  static void q() {}450};451 452void B::f() {}453 454void force_irgen() {455  A a;456  a.g();457  a.h();458 459  B b;460  b.f();461  b.b();462  b.g();463  B::q();464}465 466// CHECK-LABEL: define{{.*}} void @_ZN29FunctionSanitizerVirtualCalls1B1fEv467// CHECK-NOT: !func_sanitize468//469// CHECK-LABEL: define{{.*}} void @_ZTv0_n24_N29FunctionSanitizerVirtualCalls1B1fEv470// CHECK-NOT: !func_sanitize471//472// CHECK-LABEL: define{{.*}} void @_ZN29FunctionSanitizerVirtualCalls11force_irgenEv()473// CHECK: !func_sanitize474//475// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1AC1Ev476// CHECK-NOT: !func_sanitize477//478// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1gEv479// CHECK-NOT: !func_sanitize480//481// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1A1hEv482// CHECK-NOT: !func_sanitize483//484// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1BC1Ev485// CHECK-NOT: !func_sanitize486//487// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1bEv488// CHECK-NOT: !func_sanitize489//490// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1gEv491// CHECK-NOT: !func_sanitize492//493// CHECK-LABEL: define linkonce_odr void @_ZN29FunctionSanitizerVirtualCalls1B1qEv494// CHECK: !func_sanitize495 496}497 498namespace UpcastPointerTest {499struct S {};500struct T : S { double d; };501struct V : virtual S {};502 503// CHECK-LABEL: upcast_pointer504S* upcast_pointer(T* t) {505  // Check for null pointer506  // CHECK: %[[NONNULL:.*]] = icmp ne {{.*}}, null507  // CHECK: br i1 %[[NONNULL]]508 509  // Check alignment510  // CHECK: %[[MISALIGN:.*]] = and i64 %{{.*}}, 7511  // CHECK: icmp eq i64 %[[MISALIGN]], 0512 513  // CHECK: call void @__ubsan_handle_type_mismatch514  return t;515}516 517V getV();518 519// CHECK-LABEL: upcast_to_vbase520void upcast_to_vbase() {521  // No need to check for null here, as we have a temporary here.522 523  // CHECK-NOT: br i1524 525  // CHECK: call i64 @llvm.objectsize526  // CHECK: call void @__ubsan_handle_type_mismatch527  // CHECK: call void @__ubsan_handle_dynamic_type_cache_miss528  const S& s = getV();529}530}531 532struct nothrow {};533void *operator new[](__SIZE_TYPE__, nothrow) noexcept;534 535namespace NothrowNew {536  struct X { X(); };537 538  // CHECK-LABEL: define{{.*}}nothrow_new_trivial539  void *nothrow_new_trivial() {540    // CHECK: %[[is_null:.*]] = icmp eq ptr{{.*}}, null541    // CHECK: br i1 %[[is_null]], label %[[null:.*]], label %[[nonnull:.*]]542 543    // CHECK: [[nonnull]]:544    // CHECK: llvm.objectsize545    // CHECK: icmp uge i64 {{.*}}, 123456,546    // CHECK: br i1547    //548    // CHECK: call {{.*}}__ubsan_handle_type_mismatch549    //550    // CHECK: [[null]]:551    // CHECK-NOT: {{ }}br{{ }}552    // CHECK: ret553    return new (nothrow{}) char[123456];554  }555 556  // CHECK-LABEL: define{{.*}}nothrow_new_nontrivial557  void *nothrow_new_nontrivial() {558    // CHECK: %[[is_null:.*]] = icmp eq ptr{{.*}}, null559    // CHECK: br i1 %[[is_null]], label %[[null:.*]], label %[[nonnull:.*]]560 561    // CHECK: [[nonnull]]:562    // CHECK: llvm.objectsize563    // CHECK: icmp uge i64 {{.*}}, 123456,564    // CHECK: br i1565    //566    // CHECK: call {{.*}}__ubsan_handle_type_mismatch567    //568    // CHECK: call {{.*}}_ZN10NothrowNew1XC1Ev569    //570    // CHECK: [[null]]:571    // CHECK-NOT: {{ }}br{{ }}572    // CHECK: ret573    return new (nothrow{}) X[123456];574  }575 576  // CHECK-LABEL: define{{.*}}throwing_new577  void *throwing_new(int size) {578    // CHECK: icmp ne ptr{{.*}}, null579    // CHECK: %[[size:.*]] = mul580    // CHECK: llvm.objectsize581    // CHECK: icmp uge i64 {{.*}}, %[[size]],582    // CHECK: %[[ok:.*]] = and583    // CHECK: br i1 %[[ok]], label %[[good:.*]], label %[[bad:[^,]*]]584    //585    // CHECK: [[bad]]:586    // CHECK: call {{.*}}__ubsan_handle_type_mismatch587    //588    // CHECK: [[good]]:589    // CHECK-NOT: {{ }}br{{ }}590    // CHECK: ret591    return new char[size];592  }593 594  // CHECK-LABEL: define{{.*}}nothrow_new_zero_size595  void *nothrow_new_zero_size() {596    // CHECK: %[[nonnull:.*]] = icmp ne ptr{{.*}}, null597    // CHECK-NOT: llvm.objectsize598    // CHECK: br i1 %[[nonnull]], label %[[good:.*]], label %[[bad:[^,]*]]599    //600    // CHECK: [[bad]]:601    // CHECK: call {{.*}}__ubsan_handle_type_mismatch602    //603    // CHECK: [[good]]:604    // CHECK-NOT: {{ }}br{{ }}605    // CHECK: ret606    return new char[0];607  }608 609  // CHECK-LABEL: define{{.*}}throwing_new_zero_size610  void *throwing_new_zero_size() {611    // Nothing to check here.612    // CHECK-NOT: __ubsan_handle_type_mismatch613    return new (nothrow{}) char[0];614    // CHECK: ret615  }616}617 618struct ThisAlign {619  void this_align_lambda();620  void this_align_lambda_2();621};622void ThisAlign::this_align_lambda() {623  // CHECK-LABEL: define internal ptr @"_ZZN9ThisAlign17this_align_lambdaEvENK3$_0clEv"624  // CHECK-SAME: (ptr {{[^,]*}} %[[this:[^)]*]])625  // CHECK: %[[this_addr:.*]] = alloca626  // CHECK: store ptr %[[this]], ptr %[[this_addr]],627  // CHECK: %[[this_inner:.*]] = load ptr, ptr %[[this_addr]],628  // CHECK: %[[this_outer_addr:.*]] = getelementptr inbounds nuw %{{.*}}, ptr %[[this_inner]], i32 0, i32 0629  // CHECK: %[[this_outer:.*]] = load ptr, ptr %[[this_outer_addr]],630  //631  // CHECK: %[[this_inner_isnonnull:.*]] = icmp ne ptr %[[this_inner]], null632  // CHECK: %[[this_inner_asint:.*]] = ptrtoint ptr %[[this_inner]] to i633  // CHECK: %[[this_inner_misalignment:.*]] = and i{{32|64}} %[[this_inner_asint]], {{3|7}},634  // CHECK: %[[this_inner_isaligned:.*]] = icmp eq i{{32|64}} %[[this_inner_misalignment]], 0635  // CHECK: %[[this_inner_valid:.*]] = and i1 %[[this_inner_isnonnull]], %[[this_inner_isaligned]],636  // CHECK: br i1 %[[this_inner_valid:.*]]637  [&] { return this; } ();638}639 640namespace CopyValueRepresentation {641  // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S3aSERKS0_642  // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value643  // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S4aSEOS0_644  // CHECK-NOT: call {{.*}} @__ubsan_handle_load_invalid_value645  // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S1C2ERKS0_646  // CHECK-NOT: call {{.*}} __ubsan_handle_load_invalid_value647  // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S2C2ERKS0_648  // CHECK: __ubsan_handle_load_invalid_value649  // CHECK-LABEL: define {{.*}} @_ZN23CopyValueRepresentation2S5C2ERKS0_650  // CHECK-NOT: call {{.*}} __ubsan_handle_load_invalid_value651 652  struct CustomCopy { CustomCopy(); CustomCopy(const CustomCopy&); };653  struct S1 {654    CustomCopy CC;655    bool b;656  };657  void callee1(S1);658  void test1() {659    S1 s11;660    callee1(s11);661    S1 s12;662    s12 = s11;663  }664 665  static bool some_global_bool;666  struct ExprCopy {667    ExprCopy();668    ExprCopy(const ExprCopy&, bool b = some_global_bool);669  };670  struct S2 {671    ExprCopy EC;672    bool b;673  };674  void callee2(S2);675  void test2(void) {676    S2 s21;677    callee2(s21);678    S2 s22;679    s22 = s21;680  }681 682  struct CustomAssign { CustomAssign &operator=(const CustomAssign&); };683  struct S3 {684    CustomAssign CA;685    bool b;686  };687  void test3() {688    S3 x, y;689    x = y;690  }691 692  struct CustomMove {693    CustomMove();694    CustomMove(const CustomMove&&);695    CustomMove &operator=(const CustomMove&&);696  };697  struct S4 {698    CustomMove CM;699    bool b;700  };701  void test4() {702    S4 x, y;703    x = static_cast<S4&&>(y);704  }705 706  struct EnumCustomCopy {707    EnumCustomCopy();708    EnumCustomCopy(const EnumCustomCopy&);709  };710  struct S5 {711    EnumCustomCopy ECC;712    bool b;713  };714  void callee5(S5);715  void test5() {716    S5 s51;717    callee5(s51);718    S5 s52;719    s52 = s51;720  }721}722 723void ThisAlign::this_align_lambda_2() {724  // CHECK-LABEL: define internal void @"_ZZN9ThisAlign19this_align_lambda_2EvENK3$_0clEv"725  // CHECK-SAME: (ptr {{[^,]*}} %[[this:[^)]*]])726  // CHECK: %[[this_addr:.*]] = alloca727  // CHECK: store ptr %[[this]], ptr %[[this_addr]],728  // CHECK: %[[this_inner:.*]] = load ptr, ptr %[[this_addr]],729  //730  // Do not perform a null check on the 'this' pointer if the function might be731  // called from a static invoker.732  // CHECK-NOT: icmp ne ptr %[[this_inner]], null733  auto *p = +[] {};734  p();735}736 737// CHECK: attributes [[NR_NUW]] = { nomerge noreturn nounwind }738 739// CHECK-FUNCSAN: ![[FUNCSAN]] = !{i32 -1056584962, i32 -1000226989}740