1 // RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-derived-cast -fsanitize-trap=cfi-derived-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-DCAST %s 2 // RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-unrelated-cast -fsanitize-trap=cfi-unrelated-cast -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST %s 3 // RUN: %clang_cc1 -triple x86_64-unknown-linux -fsanitize=cfi-unrelated-cast,cfi-cast-strict -fsanitize-trap=cfi-unrelated-cast,cfi-cast-strict -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-UCAST-STRICT %s 4 5 // In this test the main thing we are searching for is something like 6 // 'metadata !"1B"' where "1B" is the mangled name of the class we are 7 // casting to (or maybe its base class in non-strict mode). 8 9 struct A { 10 virtual void f(); 11 }; 12 13 struct B : A { 14 virtual void f(); 15 }; 16 17 struct C : A {}; 18 19 // CHECK-DCAST-LABEL: define void @_Z3abpP1A 20 void abp(A *a) { 21 // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 22 // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 23 24 // CHECK-DCAST: [[TRAPBB]] 25 // CHECK-DCAST-NEXT: call void @llvm.trap() 26 // CHECK-DCAST-NEXT: unreachable 27 28 // CHECK-DCAST: [[CONTBB]] 29 // CHECK-DCAST: ret 30 static_cast<B*>(a); 31 } 32 33 // CHECK-DCAST-LABEL: define void @_Z3abrR1A 34 void abr(A &a) { 35 // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 36 // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 37 38 // CHECK-DCAST: [[TRAPBB]] 39 // CHECK-DCAST-NEXT: call void @llvm.trap() 40 // CHECK-DCAST-NEXT: unreachable 41 42 // CHECK-DCAST: [[CONTBB]] 43 // CHECK-DCAST: ret 44 static_cast<B&>(a); 45 } 46 47 // CHECK-DCAST-LABEL: define void @_Z4abrrO1A 48 void abrr(A &&a) { 49 // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 50 // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 51 52 // CHECK-DCAST: [[TRAPBB]] 53 // CHECK-DCAST-NEXT: call void @llvm.trap() 54 // CHECK-DCAST-NEXT: unreachable 55 56 // CHECK-DCAST: [[CONTBB]] 57 // CHECK-DCAST: ret 58 static_cast<B&&>(a); 59 } 60 61 // CHECK-UCAST-LABEL: define void @_Z3vbpPv 62 void vbp(void *p) { 63 // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 64 // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 65 66 // CHECK-UCAST: [[TRAPBB]] 67 // CHECK-UCAST-NEXT: call void @llvm.trap() 68 // CHECK-UCAST-NEXT: unreachable 69 70 // CHECK-UCAST: [[CONTBB]] 71 // CHECK-UCAST: ret 72 static_cast<B*>(p); 73 } 74 75 // CHECK-UCAST-LABEL: define void @_Z3vbrRc 76 void vbr(char &r) { 77 // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 78 // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 79 80 // CHECK-UCAST: [[TRAPBB]] 81 // CHECK-UCAST-NEXT: call void @llvm.trap() 82 // CHECK-UCAST-NEXT: unreachable 83 84 // CHECK-UCAST: [[CONTBB]] 85 // CHECK-UCAST: ret 86 reinterpret_cast<B&>(r); 87 } 88 89 // CHECK-UCAST-LABEL: define void @_Z4vbrrOc 90 void vbrr(char &&r) { 91 // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 92 // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 93 94 // CHECK-UCAST: [[TRAPBB]] 95 // CHECK-UCAST-NEXT: call void @llvm.trap() 96 // CHECK-UCAST-NEXT: unreachable 97 98 // CHECK-UCAST: [[CONTBB]] 99 // CHECK-UCAST: ret 100 reinterpret_cast<B&&>(r); 101 } 102 103 // CHECK-UCAST-LABEL: define void @_Z3vcpPv 104 // CHECK-UCAST-STRICT-LABEL: define void @_Z3vcpPv 105 void vcp(void *p) { 106 // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") 107 // CHECK-UCAST-STRICT: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") 108 static_cast<C*>(p); 109 } 110 111 // CHECK-UCAST-LABEL: define void @_Z3bcpP1B 112 // CHECK-UCAST-STRICT-LABEL: define void @_Z3bcpP1B 113 void bcp(B *p) { 114 // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") 115 // CHECK-UCAST-STRICT: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") 116 (C *)p; 117 } 118 119 // CHECK-UCAST-LABEL: define void @_Z8bcp_callP1B 120 // CHECK-UCAST-STRICT-LABEL: define void @_Z8bcp_callP1B 121 void bcp_call(B *p) { 122 // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") 123 // CHECK-UCAST-STRICT: [[P:%[^ ]*]] = call i1 @llvm.bitset.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") 124 ((C *)p)->f(); 125 } 126