1 // RUN: %clang_cc1 -std=c++11 -triple %itanium_abi_triple -emit-llvm -fsanitize=null,vptr %s -o - | FileCheck %s
11 struct Derived1 final
: Base1
{
15 struct Derived2 final
: Base1
, Base2
{
19 struct Derived3
: Base1
{
20 void f1() override
/* nofinal */ {}
23 struct Derived4 final
: Base1
{
24 void f1() override final
{}
27 // CHECK: [[UBSAN_TI_DERIVED1_1:@[0-9]+]] = private unnamed_addr global {{.*}} ptr @_ZTI8Derived1
28 // CHECK: [[UBSAN_TI_DERIVED2_1:@[0-9]+]] = private unnamed_addr global {{.*}} ptr @_ZTI8Derived2
29 // CHECK: [[UBSAN_TI_DERIVED2_2:@[0-9]+]] = private unnamed_addr global {{.*}} ptr @_ZTI8Derived2
30 // CHECK: [[UBSAN_TI_DERIVED3:@[0-9]+]] = private unnamed_addr global {{.*}} ptr @_ZTI8Derived3
31 // CHECK: [[UBSAN_TI_BASE1:@[0-9]+]] = private unnamed_addr global {{.*}} ptr @_ZTI5Base1
32 // CHECK: [[UBSAN_TI_DERIVED4_1:@[0-9]+]] = private unnamed_addr global {{.*}} ptr @_ZTI8Derived4
33 // CHECK: [[UBSAN_TI_DERIVED4_2:@[0-9]+]] = private unnamed_addr global {{.*}} ptr @_ZTI8Derived4
35 // CHECK-LABEL: define {{(dso_local )?}}void @_Z2t1v
38 static_cast<Base1
*>(&d1
)->f1(); //< Devirt Base1::f1 to Derived1::f1.
39 // CHECK: %[[D1:[0-9]+]] = ptrtoint ptr %d1 to i{{[0-9]+}}, !nosanitize
40 // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED1_1]], i{{[0-9]+}} %[[D1]]
43 // CHECK-LABEL: define {{(dso_local )?}}void @_Z2t2v
46 static_cast<Base1
*>(&d2
)->f1(); //< Devirt Base1::f1 to Derived2::f1.
47 // CHECK: %[[D2_1:[0-9]+]] = ptrtoint ptr %d2 to i{{[0-9]+}}, !nosanitize
48 // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED2_1]], i{{[0-9]+}} %[[D2_1]]
51 // CHECK-LABEL: define {{(dso_local )?}}void @_Z2t3v
54 static_cast<Base2
*>(&d2
)->f1(); //< Devirt Base2::f1 to Derived2::f1.
55 // CHECK: %[[D2_2:[0-9]+]] = ptrtoint ptr %d2 to i{{[0-9]+}}, !nosanitize
56 // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED2_2]], i{{[0-9]+}} %[[D2_2]]
59 // CHECK-LABEL: define {{(dso_local )?}}void @_Z2t4v
62 Derived3
*badp
= static_cast<Derived3
*>(&p
); //< Check that &p isa Derived3.
63 // CHECK: %[[P1:[0-9]+]] = ptrtoint ptr %p to i{{[0-9]+}}, !nosanitize
64 // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED3]], i{{[0-9]+}} %[[P1]]
66 static_cast<Base1
*>(badp
)->f1(); //< No devirt, test 'badp isa Base1'.
67 // We were able to skip the null check on the first type check because 'p'
68 // is backed by an alloca. We can't skip the second null check because 'badp'
69 // is a (bitcast (load ...)).
70 // CHECK: call void @__ubsan_handle_type_mismatch
72 // CHECK: %[[BADP1:[0-9]+]] = ptrtoint ptr {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize
73 // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_BASE1]], i{{[0-9]+}} %[[BADP1]]
76 // CHECK-LABEL: define {{(dso_local )?}}void @_Z2t5v
79 Derived4
*badp
= static_cast<Derived4
*>(&p
); //< Check that &p isa Derived4.
80 // CHECK: %[[P1:[0-9]+]] = ptrtoint ptr %p to i{{[0-9]+}}, !nosanitize
81 // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED4_1]], i{{[0-9]+}} %[[P1]]
83 static_cast<Base1
*>(badp
)->f1(); //< Devirt Base1::f1 to Derived4::f1.
84 // CHECK: call void @__ubsan_handle_type_mismatch
86 // CHECK: %[[BADP1:[0-9]+]] = ptrtoint ptr {{%[0-9]+}} to i{{[0-9]+}}, !nosanitize
87 // CHECK-NEXT: call void @__ubsan_handle_dynamic_type_cache{{[_a-z]*}}({{.*}} [[UBSAN_TI_DERIVED4_2]], i{{[0-9]+}} %[[BADP1]]