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]]
reference_binding(int * p,S * q)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
member_access(S * p)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