Clang Project

clang_source_code/test/CodeGenCXX/cfi-cast.cpp
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
9struct A {
10  virtual void f();
11  int i() const;
12};
13
14struct B : A {
15  virtual void f();
16};
17
18struct C : A {};
19
20// CHECK-DCAST-LABEL: define hidden void @_Z3abpP1A
21void 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
35void 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
49void 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
63void 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
77void 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
91void 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
106void 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
114void 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
122void 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
130int 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