1 // RUN: %clang_cc1 -triple x86_64-unknown-linux -fvisibility hidden -std=c++11 -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 -fvisibility hidden -std=c++11 -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 -fvisibility hidden -std=c++11 -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 int i() const; 12 }; 13 14 struct B : A { 15 virtual void f(); 16 }; 17 18 struct C : A {}; 19 20 // CHECK-DCAST-LABEL: define hidden void @_Z3abpP1A 21 void abp(A *a) { 22 // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 23 // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 24 25 // CHECK-DCAST: [[TRAPBB]] 26 // CHECK-DCAST-NEXT: call void @llvm.trap() 27 // CHECK-DCAST-NEXT: unreachable 28 29 // CHECK-DCAST: [[CONTBB]] 30 // CHECK-DCAST: ret 31 (void)static_cast<B*>(a); 32 } 33 34 // CHECK-DCAST-LABEL: define hidden void @_Z3abrR1A 35 void abr(A &a) { 36 // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 37 // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 38 39 // CHECK-DCAST: [[TRAPBB]] 40 // CHECK-DCAST-NEXT: call void @llvm.trap() 41 // CHECK-DCAST-NEXT: unreachable 42 43 // CHECK-DCAST: [[CONTBB]] 44 // CHECK-DCAST: ret 45 (void)static_cast<B&>(a); 46 } 47 48 // CHECK-DCAST-LABEL: define hidden void @_Z4abrrO1A 49 void abrr(A &&a) { 50 // CHECK-DCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 51 // CHECK-DCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 52 53 // CHECK-DCAST: [[TRAPBB]] 54 // CHECK-DCAST-NEXT: call void @llvm.trap() 55 // CHECK-DCAST-NEXT: unreachable 56 57 // CHECK-DCAST: [[CONTBB]] 58 // CHECK-DCAST: ret 59 (void)static_cast<B&&>(a); 60 } 61 62 // CHECK-UCAST-LABEL: define hidden void @_Z3vbpPv 63 void vbp(void *p) { 64 // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 65 // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 66 67 // CHECK-UCAST: [[TRAPBB]] 68 // CHECK-UCAST-NEXT: call void @llvm.trap() 69 // CHECK-UCAST-NEXT: unreachable 70 71 // CHECK-UCAST: [[CONTBB]] 72 // CHECK-UCAST: ret 73 (void)static_cast<B*>(p); 74 } 75 76 // CHECK-UCAST-LABEL: define hidden void @_Z3vbrRc 77 void vbr(char &r) { 78 // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 79 // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 80 81 // CHECK-UCAST: [[TRAPBB]] 82 // CHECK-UCAST-NEXT: call void @llvm.trap() 83 // CHECK-UCAST-NEXT: unreachable 84 85 // CHECK-UCAST: [[CONTBB]] 86 // CHECK-UCAST: ret 87 (void)reinterpret_cast<B&>(r); 88 } 89 90 // CHECK-UCAST-LABEL: define hidden void @_Z4vbrrOc 91 void vbrr(char &&r) { 92 // CHECK-UCAST: [[P:%[^ ]*]] = call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1B") 93 // CHECK-UCAST-NEXT: br i1 [[P]], label %[[CONTBB:[^ ]*]], label %[[TRAPBB:[^ ,]*]] 94 95 // CHECK-UCAST: [[TRAPBB]] 96 // CHECK-UCAST-NEXT: call void @llvm.trap() 97 // CHECK-UCAST-NEXT: unreachable 98 99 // CHECK-UCAST: [[CONTBB]] 100 // CHECK-UCAST: ret 101 (void)reinterpret_cast<B&&>(r); 102 } 103 104 // CHECK-UCAST-LABEL: define hidden void @_Z3vcpPv 105 // CHECK-UCAST-STRICT-LABEL: define hidden void @_Z3vcpPv 106 void vcp(void *p) { 107 // CHECK-UCAST: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") 108 // CHECK-UCAST-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") 109 (void)static_cast<C*>(p); 110 } 111 112 // CHECK-UCAST-LABEL: define hidden void @_Z3bcpP1B 113 // CHECK-UCAST-STRICT-LABEL: define hidden void @_Z3bcpP1B 114 void bcp(B *p) { 115 // CHECK-UCAST: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") 116 // CHECK-UCAST-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") 117 (void)(C *)p; 118 } 119 120 // CHECK-UCAST-LABEL: define hidden void @_Z8bcp_callP1B 121 // CHECK-UCAST-STRICT-LABEL: define hidden void @_Z8bcp_callP1B 122 void bcp_call(B *p) { 123 // CHECK-UCAST: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1A") 124 // CHECK-UCAST-STRICT: call i1 @llvm.type.test(i8* {{%[^ ]*}}, metadata !"_ZTS1C") 125 ((C *)p)->f(); 126 } 127 128 // CHECK-UCAST-LABEL: define hidden i32 @_Z6a_callP1A 129 // CHECK-UCAST-STRICT-LABEL: define hidden i32 @_Z6a_callP1A 130 int a_call(A *a) { 131 // CHECK-UCAST-NOT: @llvm.type.test 132 // CHECK-UCAST-STRICT-NOT: @llvm.type.test 133 return a->i(); 134 } 135