// 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 { } impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn<&'a U> for &'a T {} #[lang = "unsize"] trait Unsize { } #[lang = "coerce_unsized"] pub trait CoerceUnsized { } impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} #[lang="freeze"] trait Freeze { } #[lang="drop_in_place"] fn drop_in_place_fn() { } pub trait Trait1 { fn foo(&self); } pub struct Type1; impl Trait1 for Type1 { fn foo(&self) { } } pub trait Trait2 { fn bar(&self); } pub struct Type2; impl Trait2 for Type2 { fn bar(&self) { } } pub trait Trait3 { fn baz(&self, _: &T); } pub struct Type3; impl Trait3 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 fn foo1(a: &dyn Trait1) { a.foo(); // CHECK-LABEL: define{{.*}}4foo1{{.*}}!{{|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{{.*}}!{{|kcfi_type}} !{{[0-9]+}} // CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE1:[[:print:]]+]]) ] } pub fn foo2(a: &dyn Trait2) { a.bar(); // CHECK-LABEL: define{{.*}}4foo2{{.*}}!{{|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; b.bar(); // CHECK-LABEL: define{{.*}}4bar2{{.*}}!{{|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) { let b = Type3; a.baz(&b); // CHECK-LABEL: define{{.*}}4foo3{{.*}}!{{|kcfi_type}} !{{[0-9]+}} // CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} 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; b.baz(&a); // CHECK-LABEL: define{{.*}}4bar3{{.*}}!{{|kcfi_type}} !{{[0-9]+}} // CHECK: call void %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type3\*}} 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{{.*}}!{{|kcfi_type}} !{{[0-9]+}} // CHECK: call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} 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{{.*}}!{{|kcfi_type}} !{{[0-9]+}} // CHECK: call align 4 {{ptr|i32\*}} %{{[0-9]}}({{\{\}\*|ptr}} align 1 {{%[a-z]\.0|%_[0-9]}}, {{\{\}\*|ptr|%Type4\*}} align 1 {{%[a-z]\.0|%_[0-9]}}){{.*}}[ "kcfi"(i32 [[TYPE4:[[:print:]]+]]) ] } // CHECK: !{{[0-9]+}} = !{i32 [[TYPE1]]} // CHECK: !{{[0-9]+}} = !{i32 [[TYPE2]]} // CHECK: !{{[0-9]+}} = !{i32 [[TYPE3]]} // CHECK: !{{[0-9]+}} = !{i32 [[TYPE4]]}