summaryrefslogtreecommitdiffstats
path: root/tests/codegen/sanitizer/kcfi-emit-type-metadata-trait-objects.rs
blob: 7aed137f215ce392b17290fbeec00f5bbcdce835 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
// Verifies that type metadata identifiers for trait objects are emitted correctly.
//
// revisions: aarch64 x86_64
// [aarch64] compile-flags: --target aarch64-unknown-none
// [aarch64] needs-llvm-components: aarch64
// [x86_64] compile-flags: --target x86_64-unknown-none
// [x86_64] needs-llvm-components:
// compile-flags: -Cno-prepopulate-passes -Zsanitizer=kcfi -Copt-level=0

#![crate_type="lib"]
#![feature(arbitrary_self_types, no_core, lang_items)]
#![no_core]

#[lang="sized"]
trait Sized { }
#[lang="copy"]
trait Copy { }
#[lang="receiver"]
trait Receiver { }
#[lang="dispatch_from_dyn"]
trait DispatchFromDyn<T> { }
impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {}
#[lang = "unsize"]
trait Unsize<T: ?Sized> { }
#[lang = "coerce_unsized"]
pub trait CoerceUnsized<T: ?Sized> { }
impl<'a, 'b: 'a, T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<&'a U> for &'b T {}
#[lang="freeze"]
trait Freeze { }
#[lang="drop_in_place"]
fn drop_in_place_fn<T>() { }

pub trait Trait1 {
    fn foo(&self);
}

pub struct Type1;

impl Trait1 for Type1 {
    fn foo(&self) {
    }
}

pub trait Trait2<T> {
    fn bar(&self);
}

pub struct Type2;

impl Trait2<i32> for Type2 {
    fn bar(&self) {
    }
}

pub trait Trait3<T> {
    fn baz(&self, _: &T);
}

pub struct Type3;

impl<T, U> Trait3<U> for T {
    fn baz(&self, _: &U) {
    }
}

pub trait Trait4<'a, T> {
    type Output: 'a;
    fn qux(&self, _: &T) -> Self::Output;
}

pub struct Type4;

impl<'a, T, U> Trait4<'a, U> for T {
    type Output = &'a i32;
    fn qux(&self, _: &U) -> Self::Output {
        &0
    }
}

pub trait Trait5<T, const N: usize> {
    fn quux(&self, _: &[T; N]);
}

pub struct Type5;

impl Copy for Type5 {}

impl<T, U, const N: usize> Trait5<U, N> for T {
    fn quux(&self, _: &[U; N]) {
    }
}

pub fn foo1(a: &dyn Trait1) {
    a.foo();
    // CHECK-LABEL: define{{.*}}4foo1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
}

pub fn bar1() {
    let a = Type1;
    let b = &a as &dyn Trait1;
    b.foo();
    // CHECK-LABEL: define{{.*}}4bar1{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ]
}

pub fn foo2<T>(a: &dyn Trait2<T>) {
    a.bar();
    // CHECK-LABEL: define{{.*}}4foo2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
}

pub fn bar2() {
    let a = Type2;
    foo2(&a);
    let b = &a as &dyn Trait2<i32>;
    b.bar();
    // CHECK-LABEL: define{{.*}}4bar2{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE2:[[:print:]]+]]) ]
}

pub fn foo3(a: &dyn Trait3<Type3>) {
    let b = Type3;
    a.baz(&b);
    // CHECK-LABEL: define{{.*}}4foo3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
}

pub fn bar3() {
    let a = Type3;
    foo3(&a);
    let b = &a as &dyn Trait3<Type3>;
    b.baz(&a);
    // CHECK-LABEL: define{{.*}}4bar3{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE3:[[:print:]]+]]) ]
}

pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) {
    let b = Type4;
    a.qux(&b);
    // CHECK-LABEL: define{{.*}}4foo4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
    // CHECK:       call align 4 ptr %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
}

pub fn bar4<'a>() {
    let a = Type4;
    foo4(&a);
    let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>;
    b.qux(&a);
    // CHECK-LABEL: define{{.*}}4bar4{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
    // CHECK:       call align 4 ptr %{{[0-9]}}(ptr align 1 {{%[a-z]\.0|%_[0-9]}}, ptr align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ]
}

pub fn foo5(a: &dyn Trait5<Type5, 32>) {
    let b = &[Type5; 32];
    a.quux(&b);
    // CHECK-LABEL: define{{.*}}4foo5{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, ptr align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ]
}

pub fn bar5() {
    let a = &[Type5; 32];
    foo5(&a);
    let b = &a as &dyn Trait5<Type5, 32>;
    b.quux(&a);
    // CHECK-LABEL: define{{.*}}4bar5{{.*}}!{{<unknown kind #36>|kcfi_type}} !{{[0-9]+}}
    // CHECK:       call void %{{[0-9]}}(ptr align 1 {{%[a-z](\.0)*|%_[0-9]+]}}, ptr align 1 {{%[a-z](\.0)*|%_[0-9]+}}){{.*}}[ "kcfi"(i32 [[TYPE5:[[:print:]]+]]) ]
}

// CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]}
// CHECK: !{{[0-9]+}} = !{i32 [[TYPE2]]}
// CHECK: !{{[0-9]+}} = !{i32 [[TYPE3]]}
// CHECK: !{{[0-9]+}} = !{i32 [[TYPE4]]}
// CHECK: !{{[0-9]+}} = !{i32 [[TYPE5]]}