From a25171b688f03d1e446d448e307594e473200a01 Mon Sep 17 00:00:00 2001 From: Ramon de C Valle Date: Tue, 3 Oct 2023 14:57:31 -0700 Subject: [PATCH] CFI: Fix (3) of core and std have explict CFI violations Fixes (3) of #115199 by transforming function items, closures, and Fn trait objects into function pointers. --- compiler/rustc_middle/src/ty/sty.rs | 62 +++ compiler/rustc_symbol_mangling/src/lib.rs | 2 + compiler/rustc_symbol_mangling/src/typeid.rs | 64 +-- .../src/typeid/typeid_itanium_cxx_abi.rs | 393 ++++++++++-------- ...pe-metadata-id-itanium-cxx-abi-closures.rs | 55 +++ ...adata-id-itanium-cxx-abi-trait-objects.rs} | 81 ++-- ...i-emit-type-metadata-id-itanium-cxx-abi.rs | 304 ++++++-------- .../kcfi-emit-type-metadata-trait-objects.rs | 174 -------- 8 files changed, 552 insertions(+), 583 deletions(-) create mode 100644 tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-closures.rs rename tests/codegen/sanitizer/{cfi-emit-type-metadata-trait-objects.rs => cfi-emit-type-metadata-id-itanium-cxx-abi-trait-objects.rs} (50%) delete mode 100644 tests/codegen/sanitizer/kcfi-emit-type-metadata-trait-objects.rs diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e5f418bbb4b11..fe1548d285131 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -744,6 +744,52 @@ impl<'tcx> PolyExistentialPredicate<'tcx> { } impl<'tcx> List> { + /// Returns the list of arguments if principal is an Fn trait. + pub fn fn_trait_args(&self, tcx: TyCtxt<'tcx>) -> Option<&List>> { + if self.is_fn_trait(tcx) { + if let Some(args) = self.principal_args() && !args.is_empty() && args[0].expect_ty().is_tuple() { + Some(args[0].expect_ty().tuple_fields()) + } else { + Some(List::empty()) + } + } else { + None + } + } + + /// Returns the output if principal is an Fn trait. + pub fn fn_trait_output(&self, tcx: TyCtxt<'tcx>) -> Option> { + if self.is_fn_trait(tcx) { + if let Some(projection) = self.projection_bounds().next() && let Some(ty) = projection.skip_binder().term.ty() { + Some(ty) + } else { + Some(Ty::new_unit(tcx)) + } + } else { + None + } + } + + /// Returns the signature if principal is an Fn trait. + pub fn fn_trait_sig(&self, tcx: TyCtxt<'tcx>) -> Option> { + if self.is_fn_trait(tcx) { + Some(tcx.mk_fn_sig( + self.fn_trait_args(tcx).unwrap(), + self.fn_trait_output(tcx).unwrap(), + false, + hir::Unsafety::Normal, + Abi::Rust, + )) + } else { + None + } + } + + /// Returns true if principal is an Fn trait. + pub fn is_fn_trait(&self, tcx: TyCtxt<'tcx>) -> bool { + if let Some(principal) = self.principal() && tcx.is_fn_trait(principal.skip_binder().def_id) { true } else { false } + } + /// Returns the "principal `DefId`" of this set of existential predicates. /// /// A Rust trait object type consists (in addition to a lifetime bound) @@ -778,6 +824,12 @@ impl<'tcx> List> { .transpose() } + /// Returns the principal list of arguments. + pub fn principal_args(&self) -> Option<&List>> { + self.principal().map(|trait_ref| trait_ref.skip_binder().args) + } + + /// Returns the principal DefId. pub fn principal_def_id(&self) -> Option { self.principal().map(|trait_ref| trait_ref.skip_binder().def_id) } @@ -2252,6 +2304,11 @@ impl<'tcx> Ty<'tcx> { self.0.0.flags } + #[inline] + pub fn is_tuple(self) -> bool { + matches!(self.kind(), Tuple(..)) + } + #[inline] pub fn is_unit(self) -> bool { match self.kind() { @@ -2605,6 +2662,11 @@ impl<'tcx> Ty<'tcx> { matches!(self.kind(), FnDef(..) | FnPtr(_)) } + #[inline] + pub fn is_fn_def(self) -> bool { + matches!(self.kind(), FnDef(..)) + } + #[inline] pub fn is_fn_ptr(self) -> bool { matches!(self.kind(), FnPtr(_)) diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index 535a3ea2d7e05..4f0d301590d74 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -88,6 +88,8 @@ //! DefPaths which are much more robust in the face of changes to the code base. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] +#![feature(iter_order_by)] +#![feature(let_chains)] #![feature(never_type)] #![recursion_limit = "256"] #![allow(rustc::potential_query_instability)] diff --git a/compiler/rustc_symbol_mangling/src/typeid.rs b/compiler/rustc_symbol_mangling/src/typeid.rs index cda16e3a3f566..e9ff569ab77c9 100644 --- a/compiler/rustc_symbol_mangling/src/typeid.rs +++ b/compiler/rustc_symbol_mangling/src/typeid.rs @@ -4,7 +4,7 @@ /// For more information about LLVM CFI and cross-language LLVM CFI support for the Rust compiler, /// see design document in the tracking issue #89653. use bitflags::bitflags; -use rustc_middle::ty::{FnSig, Instance, Ty, TyCtxt}; +use rustc_middle::ty::{Instance, List, Ty, TyCtxt}; use rustc_target::abi::call::FnAbi; use std::hash::Hasher; use twox_hash::XxHash64; @@ -26,16 +26,11 @@ pub fn typeid_for_fnabi<'tcx>( fn_abi: &FnAbi<'tcx, Ty<'tcx>>, options: TypeIdOptions, ) -> String { - typeid_itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, options) -} - -/// Returns a type metadata identifier for the specified FnSig. -pub fn typeid_for_fnsig<'tcx>( - tcx: TyCtxt<'tcx>, - fn_sig: &FnSig<'tcx>, - options: TypeIdOptions, -) -> String { - typeid_itanium_cxx_abi::typeid_for_fnsig(tcx, fn_sig, options) + typeid_itanium_cxx_abi::typeid_for_fnabi( + tcx, + &typeid_itanium_cxx_abi::transform_fnabi(tcx, &fn_abi, options, None), + options, + ) } /// Returns a type metadata identifier for the specified Instance. @@ -44,7 +39,16 @@ pub fn typeid_for_instance<'tcx>( instance: &Instance<'tcx>, options: TypeIdOptions, ) -> String { - typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options) + let fn_abi = tcx + .fn_abi_of_instance(tcx.param_env(instance.def_id()).and((*instance, List::empty()))) + .unwrap_or_else(|instance| { + bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance) + }); + typeid_itanium_cxx_abi::typeid_for_fnabi( + tcx, + &typeid_itanium_cxx_abi::transform_fnabi(tcx, &fn_abi, options, Some(instance)), + options, + ) } /// Returns a KCFI type metadata identifier for the specified FnAbi. @@ -56,20 +60,14 @@ pub fn kcfi_typeid_for_fnabi<'tcx>( // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the // xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.) let mut hash: XxHash64 = Default::default(); - hash.write(typeid_itanium_cxx_abi::typeid_for_fnabi(tcx, fn_abi, options).as_bytes()); - hash.finish() as u32 -} - -/// Returns a KCFI type metadata identifier for the specified FnSig. -pub fn kcfi_typeid_for_fnsig<'tcx>( - tcx: TyCtxt<'tcx>, - fn_sig: &FnSig<'tcx>, - options: TypeIdOptions, -) -> u32 { - // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the - // xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.) - let mut hash: XxHash64 = Default::default(); - hash.write(typeid_itanium_cxx_abi::typeid_for_fnsig(tcx, fn_sig, options).as_bytes()); + hash.write( + typeid_itanium_cxx_abi::typeid_for_fnabi( + tcx, + &typeid_itanium_cxx_abi::transform_fnabi(tcx, &fn_abi, options, None), + options, + ) + .as_bytes(), + ); hash.finish() as u32 } @@ -79,9 +77,21 @@ pub fn kcfi_typeid_for_instance<'tcx>( instance: &Instance<'tcx>, options: TypeIdOptions, ) -> u32 { + let fn_abi = tcx + .fn_abi_of_instance(tcx.param_env(instance.def_id()).and((*instance, List::empty()))) + .unwrap_or_else(|instance| { + bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance) + }); // A KCFI type metadata identifier is a 32-bit constant produced by taking the lower half of the // xxHash64 of the type metadata identifier. (See llvm/llvm-project@cff5bef.) let mut hash: XxHash64 = Default::default(); - hash.write(typeid_itanium_cxx_abi::typeid_for_instance(tcx, instance, options).as_bytes()); + hash.write( + typeid_itanium_cxx_abi::typeid_for_fnabi( + tcx, + &typeid_itanium_cxx_abi::transform_fnabi(tcx, &fn_abi, options, Some(instance)), + options, + ) + .as_bytes(), + ); hash.finish() as u32 } diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index 6ad3e7155e825..443720d979551 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -627,35 +627,6 @@ fn encode_ty<'tcx>( typeid.push_str(&s); } - // Function types - ty::FnDef(def_id, args) | ty::Closure(def_id, args) => { - // u[IE], where is , - // as vendor extended type. - let mut s = String::new(); - let name = encode_ty_name(tcx, *def_id); - let _ = write!(s, "u{}{}", name.len(), &name); - s.push_str(&encode_args(tcx, args, dict, options)); - compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); - typeid.push_str(&s); - } - - ty::Generator(def_id, args, ..) => { - // u[IE], where is , - // as vendor extended type. - let mut s = String::new(); - let name = encode_ty_name(tcx, *def_id); - let _ = write!(s, "u{}{}", name.len(), &name); - // Encode parent args only - s.push_str(&encode_args( - tcx, - tcx.mk_args(args.as_generator().parent_args()), - dict, - options, - )); - compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); - typeid.push_str(&s); - } - // Pointer types ty::Ref(region, ty0, ..) => { // [U3mut]u3refIE as vendor extended type qualifier and type @@ -707,6 +678,18 @@ fn encode_ty<'tcx>( typeid.push_str(&s); } + // Associated type projections + ty::Alias(_, alias_ty) => { + // u[IE], where is , + // as vendor extended type. + let mut s = String::new(); + let name = encode_ty_name(tcx, alias_ty.def_id); + let _ = write!(s, "u{}{}", name.len(), &name); + s.push_str(&encode_args(tcx, alias_ty.args, dict, options)); + compress(dict, DictKey::Ty(ty, TyQ::None), &mut s); + typeid.push_str(&s); + } + // Type parameters ty::Param(..) => { // u5param as vendor extended type @@ -716,9 +699,11 @@ fn encode_ty<'tcx>( } // Unexpected types - ty::Alias(..) - | ty::Bound(..) + ty::Bound(..) + | ty::Closure(..) | ty::Error(..) + | ty::FnDef(..) + | ty::Generator(..) | ty::GeneratorWitness(..) | ty::Infer(..) | ty::Placeholder(..) => { @@ -729,26 +714,161 @@ fn encode_ty<'tcx>( typeid } +/// Returns true if the FnAbi is an unpacked "rust-call" ABI closure call. +fn is_closure_call<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> bool { + if fn_abi.conv == Conv::Rust && !fn_abi.c_variadic && !fn_abi.args.is_empty() && let ty::Closure(_, args) = fn_abi.args[0].layout.ty.peel_refs().kind() { + let fn_sig = tcx.signature_unclosure(args.as_closure().sig(), hir::Unsafety::Normal); + return fn_sig + .skip_binder() + .inputs() + .iter() + .eq_by(&fn_abi.args[1..], |ty, arg| *ty == arg.layout.ty) && fn_sig.output().skip_binder() == fn_abi.ret.layout.ty; + } + false +} + +/// Returns true if the FnAbi is a dynamic Fn trait call. +fn is_dynamic_fn_call<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> bool { + if fn_abi.conv == Conv::Rust && !fn_abi.c_variadic && !fn_abi.args.is_empty() && let ty::Dynamic(predicates, ..) = fn_abi.args[0].layout.ty.peel_refs().kind() { + if predicates.is_fn_trait(tcx) { + return predicates.fn_trait_args(tcx).unwrap().iter().eq_by(&fn_abi.args[1..], |ty, arg| ty == arg.layout.ty) && predicates.fn_trait_output(tcx).unwrap() == fn_abi.ret.layout.ty; + } + } + false +} + +/// Returns true if the trait object is an Fn trait object. +fn is_dynamic_fn_trait<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.kind() { + ty::Dynamic(predicates, ..) => predicates.is_fn_trait(tcx), + _ => false, + } +} + +/// Creates a trait object. +fn new_dynamic_trait<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + args: GenericArgsRef<'tcx>, +) -> Ty<'tcx> { + let predicate = + ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef { def_id: def_id, args: args }); + let predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy(predicate)]); + Ty::new_dynamic(tcx, predicates, tcx.lifetimes.re_erased, ty::Dyn) +} + +/// Transforms an FnAbi for being encoded and used in the substitution dictionary. For trait default +/// implementations and trait implementations, replace the concrete self by a reference to a trait +/// object. For closure and Fn trait object calls, transform them into function pointer calls. +pub fn transform_fnabi<'tcx>( + tcx: TyCtxt<'tcx>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + _options: EncodeTyOptions, + instance: Option<&Instance<'tcx>>, +) -> FnAbi<'tcx, Ty<'tcx>> { + if let Some(instance) = instance && matches!(instance.def, ty::InstanceDef::Item(..)) && let Some(impl_def_id) = tcx.impl_of_method(instance.def_id()) && let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) && !fn_abi.args.is_empty() && fn_abi.args[0].layout.ty.is_ref() { + // Replace the concrete self by a reference to a trait object + let self_ty = if fn_abi.args[0].layout.ty.is_mutable_ptr() { + Ty::new_mut_ref( + tcx, + tcx.lifetimes.re_erased, + new_dynamic_trait( + tcx, + trait_ref.skip_binder().def_id, + trait_ref.skip_binder().args, + ), + ) + } else { + Ty::new_imm_ref( + tcx, + tcx.lifetimes.re_erased, + new_dynamic_trait( + tcx, + trait_ref.skip_binder().def_id, + trait_ref.skip_binder().args, + ), + ) + }; + let mut fn_abi = fn_abi.clone(); + // HACK(rcvalle): It is okay to not replace or update the entire ArgAbi here because the + // other fields are never used. + fn_abi.args[0].layout.ty = self_ty; + + return fn_abi; + } else if is_closure_call(tcx, fn_abi) && let ty::Closure(_, args) = fn_abi.args[0].layout.ty.peel_refs().kind() { + let fn_sig = tcx.signature_unclosure(args.as_closure().sig(), hir::Unsafety::Normal); + return tcx.fn_abi_of_fn_ptr(ty::ParamEnv::empty().and((fn_sig, List::empty()))).unwrap_or_else(|fn_abi_error| { + bug!("transform_fnabi: couldn't get fn_abi of fn_sig {:?}", fn_abi_error) + }).clone(); + } else if is_dynamic_fn_call(tcx, fn_abi) { + let fn_sig = ty::Binder::bind_with_vars(tcx.mk_fn_sig( + fn_abi.args[1..].iter().map(|arg| arg.layout.ty ), + fn_abi.ret.layout.ty, + false, + hir::Unsafety::Normal, + Abi::Rust, + ), List::empty()); + return tcx.fn_abi_of_fn_ptr(ty::ParamEnv::empty().and((fn_sig, List::empty()))).unwrap_or_else(|fn_abi_error| { + bug!("transform_fnabi: couldn't get fn_abi of fn_sig {:?}", fn_abi_error) + }).clone(); + } + + fn_abi.clone() +} + +/// Transforms a predicate for being encoded and used in the substitution dictionary. +fn transform_predicate<'tcx>( + tcx: TyCtxt<'tcx>, + predicate: ty::PolyExistentialPredicate<'tcx>, + _options: EncodeTyOptions, +) -> ty::PolyExistentialPredicate<'tcx> { + match predicate.as_ref().skip_binder() { + ty::ExistentialPredicate::Trait(trait_ref) => { + if tcx.is_fn_trait(trait_ref.def_id) { + bug!("transform_predicate: unexpected Fn trait `{}`", trait_ref) + } else { + // Transform non Fn traits into their identities + let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id); + ty::Binder::dummy(ty::ExistentialPredicate::Trait( + ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref), + )) + } + } + _ => predicate, + } +} + /// Transforms predicates for being encoded and used in the substitution dictionary. fn transform_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: &List>, - _options: EncodeTyOptions, + options: EncodeTyOptions, ) -> &'tcx List> { let predicates: Vec> = predicates + .iter() + .filter_map(|predicate| Some(transform_predicate(tcx, predicate, options))) + .collect(); + + // Use either the base trait or autotraits only as discriminant + let (base_trait, autotraits): ( + Vec>, + Vec>, + ) = predicates .iter() .filter_map(|predicate| match predicate.skip_binder() { - ty::ExistentialPredicate::Trait(trait_ref) => { - let trait_ref = ty::TraitRef::identity(tcx, trait_ref.def_id); - Some(ty::Binder::dummy(ty::ExistentialPredicate::Trait( - ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref), - ))) - } + ty::ExistentialPredicate::Trait(..) => Some(predicate), ty::ExistentialPredicate::Projection(..) => None, ty::ExistentialPredicate::AutoTrait(..) => Some(predicate), }) - .collect(); - tcx.mk_poly_existential_predicates(&predicates) + .partition(|predicate| match predicate.skip_binder() { + ty::ExistentialPredicate::AutoTrait(..) => true, + _ => false, + }); + if !base_trait.is_empty() { + tcx.mk_poly_existential_predicates(&base_trait) + } else { + tcx.mk_poly_existential_predicates(&autotraits) + } } /// Transforms args for being encoded and used in the substitution dictionary. @@ -765,20 +885,21 @@ fn transform_args<'tcx>( tcx.mk_args_from_iter(args) } -// Transforms a ty:Ty for being encoded and used in the substitution dictionary. It transforms all -// c_void types into unit types unconditionally, generalizes pointers if -// TransformTyOptions::GENERALIZE_POINTERS option is set, and normalizes integers if -// TransformTyOptions::NORMALIZE_INTEGERS option is set. +/// Transforms a ty:Ty for being encoded and used in the substitution dictionary. It transforms all +/// c_void types into unit types unconditionally, generalizes pointers if +/// TransformTyOptions::GENERALIZE_POINTERS option is set, and normalizes integers if +/// TransformTyOptions::NORMALIZE_INTEGERS option is set. fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptions) -> Ty<'tcx> { let mut ty = ty; match ty.kind() { - ty::Float(..) + ty::Alias(..) + | ty::Float(..) | ty::Char | ty::Str | ty::Never | ty::Foreign(..) - | ty::GeneratorWitness(..) => {} + | ty::Param(..) => {} ty::Bool => { if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) { @@ -884,30 +1005,53 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio } } - ty::FnDef(def_id, args) => { - ty = Ty::new_fn_def(tcx, *def_id, transform_args(tcx, args, options)); + ty::FnDef(def_id, ..) => { + // Transform function items into function pointers + let fn_sig = tcx.fn_sig(def_id).skip_binder(); + let fn_ptr = Ty::new_fn_ptr(tcx, fn_sig); + // Transform fn_sig inputs and output + ty = transform_ty(tcx, fn_ptr, options); } - ty::Closure(def_id, args) => { - ty = Ty::new_closure(tcx, *def_id, transform_args(tcx, args, options)); + ty::Closure(_, args) => { + // Transform closures into function pointers + let fn_sig = tcx.signature_unclosure(args.as_closure().sig(), hir::Unsafety::Normal); + let fn_ptr = Ty::new_fn_ptr(tcx, fn_sig); + // Transform fn_sig inputs and output + ty = transform_ty(tcx, fn_ptr, options); } - ty::Generator(def_id, args, movability) => { - ty = Ty::new_generator(tcx, *def_id, transform_args(tcx, args, options), *movability); + ty::Generator(_, args, _) => { + let def_id = tcx.require_lang_item(hir::LangItem::Generator, None); + let gen_sig = args.as_generator().sig(); + ty = new_dynamic_trait( + tcx, + def_id, + tcx.mk_args(&[ + gen_sig.resume_ty.into(), + gen_sig.yield_ty.into(), + gen_sig.return_ty.into(), + ]), + ); } ty::Ref(region, ty0, ..) => { - if options.contains(TransformTyOptions::GENERALIZE_POINTERS) { - if ty.is_mutable_ptr() { - ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, Ty::new_unit(tcx)); - } else { - ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_unit(tcx)); - } + // Remove references from function items, closures, and Fn trait objects + if ty0.is_fn_def() || ty0.is_closure() || is_dynamic_fn_trait(tcx, *ty0) { + ty = transform_ty(tcx, *ty0, options); } else { - if ty.is_mutable_ptr() { - ty = Ty::new_mut_ref(tcx, *region, transform_ty(tcx, *ty0, options)); + if options.contains(TransformTyOptions::GENERALIZE_POINTERS) { + if ty.is_mutable_ptr() { + ty = Ty::new_mut_ref(tcx, tcx.lifetimes.re_static, Ty::new_unit(tcx)); + } else { + ty = Ty::new_imm_ref(tcx, tcx.lifetimes.re_static, Ty::new_unit(tcx)); + } } else { - ty = Ty::new_imm_ref(tcx, *region, transform_ty(tcx, *ty0, options)); + if ty.is_mutable_ptr() { + ty = Ty::new_mut_ref(tcx, *region, transform_ty(tcx, *ty0, options)); + } else { + ty = Ty::new_imm_ref(tcx, *region, transform_ty(tcx, *ty0, options)); + } } } } @@ -956,23 +1100,30 @@ fn transform_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, options: TransformTyOptio } ty::Dynamic(predicates, _region, kind) => { - ty = Ty::new_dynamic( - tcx, - transform_predicates(tcx, predicates, options), - tcx.lifetimes.re_erased, - *kind, - ); - } - - ty::Alias(..) => { - ty = transform_ty( - tcx, - tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), ty), - options, - ); + if predicates.is_fn_trait(tcx) { + // Transform Fn trait objects into function pointers + let fn_sig = ty::Binder::bind_with_vars( + predicates.fn_trait_sig(tcx).unwrap(), + List::empty(), + ); + let fn_ptr = Ty::new_fn_ptr(tcx, fn_sig); + // Transform fn_sig inputs and output + ty = transform_ty(tcx, fn_ptr, options); + } else { + ty = Ty::new_dynamic( + tcx, + transform_predicates(tcx, predicates, options), + tcx.lifetimes.re_erased, + *kind, + ); + } } - ty::Bound(..) | ty::Error(..) | ty::Infer(..) | ty::Param(..) | ty::Placeholder(..) => { + ty::Bound(..) + | ty::Error(..) + | ty::GeneratorWitness(..) + | ty::Infer(..) + | ty::Placeholder(..) => { bug!("transform_ty: unexpected `{:?}`", ty.kind()); } } @@ -1056,93 +1207,3 @@ pub fn typeid_for_fnabi<'tcx>( typeid } - -/// Returns a type metadata identifier for the specified FnSig using the Itanium C++ ABI with vendor -/// extended type qualifiers and types for Rust types that are not used at the FFI boundary. -pub fn typeid_for_fnsig<'tcx>( - tcx: TyCtxt<'tcx>, - fn_sig: &FnSig<'tcx>, - options: TypeIdOptions, -) -> String { - // A name is mangled by prefixing "_Z" to an encoding of its name, and in the case of functions - // its type. - let mut typeid = String::from("_Z"); - - // Clang uses the Itanium C++ ABI's virtual tables and RTTI typeinfo structure name as type - // metadata identifiers for function pointers. The typeinfo name encoding is a two-character - // code (i.e., 'TS') prefixed to the type encoding for the function. - typeid.push_str("TS"); - - // A dictionary of substitution candidates used for compression (see - // https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling-compression). - let mut dict: FxHashMap, usize> = FxHashMap::default(); - - // Encode the function signature - typeid.push_str(&encode_fnsig(tcx, fn_sig, &mut dict, options)); - - // Add encoding suffixes - if options.contains(EncodeTyOptions::NORMALIZE_INTEGERS) { - typeid.push_str(".normalized"); - } - - if options.contains(EncodeTyOptions::GENERALIZE_POINTERS) { - typeid.push_str(".generalized"); - } - - typeid -} - -/// Returns a type metadata identifier for the specified Instance using the Itanium C++ ABI with -/// vendor extended type qualifiers and types for Rust types that are not used at the FFI boundary. -pub fn typeid_for_instance<'tcx>( - tcx: TyCtxt<'tcx>, - instance: &Instance<'tcx>, - options: TypeIdOptions, -) -> String { - let fn_abi = tcx - .fn_abi_of_instance(tcx.param_env(instance.def_id()).and((*instance, ty::List::empty()))) - .unwrap_or_else(|instance| { - bug!("typeid_for_instance: couldn't get fn_abi of instance {:?}", instance) - }); - - // If this instance is a method and self is a reference, get the impl it belongs to - let impl_def_id = tcx.impl_of_method(instance.def_id()); - if impl_def_id.is_some() && !fn_abi.args.is_empty() && fn_abi.args[0].layout.ty.is_ref() { - // If this impl is not an inherent impl, get the trait it implements - if let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id.unwrap()) { - // Transform the concrete self into a reference to a trait object - let existential_predicate = trait_ref.map_bound(|trait_ref| { - ty::ExistentialPredicate::Trait(ty::ExistentialTraitRef::erase_self_ty( - tcx, trait_ref, - )) - }); - let existential_predicates = tcx.mk_poly_existential_predicates(&[ty::Binder::dummy( - existential_predicate.skip_binder(), - )]); - // Is the concrete self mutable? - let self_ty = if fn_abi.args[0].layout.ty.is_mutable_ptr() { - Ty::new_mut_ref( - tcx, - tcx.lifetimes.re_erased, - Ty::new_dynamic(tcx, existential_predicates, tcx.lifetimes.re_erased, ty::Dyn), - ) - } else { - Ty::new_imm_ref( - tcx, - tcx.lifetimes.re_erased, - Ty::new_dynamic(tcx, existential_predicates, tcx.lifetimes.re_erased, ty::Dyn), - ) - }; - - // Replace the concrete self in an fn_abi clone by the reference to a trait object - let mut fn_abi = fn_abi.clone(); - // HACK(rcvalle): It is okay to not replace or update the entire ArgAbi here because the - // other fields are never used. - fn_abi.args[0].layout.ty = self_ty; - - return typeid_for_fnabi(tcx, &fn_abi, options); - } - } - - typeid_for_fnabi(tcx, &fn_abi, options) -} diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-closures.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-closures.rs new file mode 100644 index 0000000000000..b6dab6fb34a23 --- /dev/null +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-closures.rs @@ -0,0 +1,55 @@ +// Verifies that type metadata identifiers for closures are emitted correctly. +// +// needs-sanitizer-cfi +// compile-flags: -Clto -Cno-prepopulate-passes -Copt-level=0 -Ctarget-feature=-crt-static -Zsanitizer=cfi + +#![crate_type="lib"] +pub fn foo1(a: fn(i32) -> i32) { + // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}} + // CHECK: call i1 @llvm.type.test(ptr {{%[0-9A-Za-z]}}, metadata !"[[TYPE1B:_ZTSFu3i32S_E]]") + a(1); +} + +pub fn bar1() { + foo1(|a| -> i32 { a + 1 }); + // CHECK-LABEL: define{{.*}}4bar1{{.*}}$u7b$$u7b$closure$u7d$$u7d + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} + fn a(a: i32) -> i32 { a + 1 } + foo1(a); + // CHECK-LABEL: define{{.*}}4bar11a + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +} + +pub fn foo2(a: &dyn Fn(i32) -> i32) { + // CHECK-LABEL: define{{.*}}4foo2{{.*}}!type !{{[0-9]+}} + // CHECK: call i1 @llvm.type.test(ptr {{%[0-9A-Za-z]}}, metadata !"[[TYPE1B]]") + a(1); +} + +pub fn bar2() { + foo2(&|a: i32| -> i32 { a + 1 }); + // CHECK-LABEL: define{{.*}}4bar2{{.*}}$u7b$$u7b$closure$u7d$$u7d + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} + fn a(a: i32) -> i32 { a + 1 } + foo2(&a); + // CHECK-LABEL: define{{.*}}4bar21a + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +} + +pub fn foo3(a: &mut dyn FnMut(i32) -> i32) { + // CHECK-LABEL: define{{.*}}4foo3{{.*}}!type !{{[0-9]+}} + // CHECK: call i1 @llvm.type.test(ptr {{%[0-9A-Za-z]}}, metadata !"[[TYPE1B]]") + a(1); +} + +pub fn bar3() { + foo3(&mut |a: i32| -> i32 { a + 1 }); + // CHECK-LABEL: define{{.*}}4bar3{{.*}}$u7b$$u7b$closure$u7d$$u7d + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} + fn a(a: i32) -> i32 { a + 1 } + foo3(&mut a); + // CHECK-LABEL: define{{.*}}4bar31a + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} +} + +// CHECK: ![[TYPE1A]] = !{i64 0, !"[[TYPE1B]]"} diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-trait-objects.rs similarity index 50% rename from tests/codegen/sanitizer/cfi-emit-type-metadata-trait-objects.rs rename to tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-trait-objects.rs index b69e57261a8e5..16e3323a72768 100644 --- a/tests/codegen/sanitizer/cfi-emit-type-metadata-trait-objects.rs +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi-trait-objects.rs @@ -6,144 +6,155 @@ #![crate_type="lib"] pub trait Trait1 { - fn foo(&self); + fn foo1(&self); } #[derive(Clone, Copy)] pub struct Type1; impl Trait1 for Type1 { - fn foo(&self) { + fn foo1(&self) { } + // CHECK-LABEL: define{{.*}}Type1$u20$as$u20${{.*}}Trait1$GT$4foo1 + // CHECK-SAME: {{.*}}!type ![[TYPE1A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub trait Trait2 { - fn bar(&self); + fn foo2(&self); } pub struct Type2; impl Trait2 for Type2 { - fn bar(&self) { + fn foo2(&self) { } + // CHECK-LABEL: define{{.*}}Type2$u20$as$u20${{.*}}Trait2$LT$i32$GT$$GT$4foo2 + // CHECK-SAME: {{.*}}!type ![[TYPE2A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub trait Trait3 { - fn baz(&self, _: &T); + fn foo3(&self, _: &T); } pub struct Type3; impl Trait3 for T { - fn baz(&self, _: &U) { + fn foo3(&self, _: &U) { } + // CHECK-LABEL: define{{.*}}T$u20$as$u20{{.*}}Trait3$LT$U$GT$$GT$4foo3 + // CHECK-SAME: {{.*}}!type ![[TYPE3A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub trait Trait4<'a, T> { type Output: 'a; - fn qux(&self, _: &T) -> Self::Output; + fn foo4(&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 { + fn foo4(&self, _: &U) -> Self::Output { &0 } + // CHECK-LABEL: define{{.*}}T$u20$as$u20{{.*}}Trait4$LT$U$GT$$GT$4foo4 + // CHECK-SAME: {{.*}}!type ![[TYPE4A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub trait Trait5 { - fn quux(&self, _: &[T; N]); + fn foo5(&self, _: &[T; N]); } #[derive(Copy, Clone)] pub struct Type5; impl Trait5 for T { - fn quux(&self, _: &[U; N]) { + fn foo5(&self, _: &[U; N]) { } + // CHECK-LABEL: define{{.*}}T$u20$as$u20{{.*}}Trait5$LT$U$C$_$GT$$GT$4foo5 + // CHECK-SAME: {{.*}}!type ![[TYPE5A:[[:print:]]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} } pub fn foo1(a: &dyn Trait1) { - a.foo(); + a.foo1(); // CHECK-LABEL: define{{.*}}4foo1{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE1:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE1B:_ZTSFvu3refIu3dynIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects6Trait1u6regionEEE]]") } pub fn bar1() { let a = Type1; + foo1(&a); let b = &a as &dyn Trait1; - b.foo(); + b.foo1(); // CHECK-LABEL: define{{.*}}4bar1{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE1B]]") } pub fn foo2(a: &dyn Trait2) { - a.bar(); + a.foo2(); // CHECK-LABEL: define{{.*}}4foo2{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2B:_ZTSFvu3refIu3dynIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects6Trait2Iu5paramEu6regionEEE]]") } pub fn bar2() { let a = Type2; foo2(&a); let b = &a as &dyn Trait2; - b.bar(); + b.foo2(); // CHECK-LABEL: define{{.*}}4bar2{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE2B]]") } pub fn foo3(a: &dyn Trait3) { let b = Type3; - a.baz(&b); + a.foo3(&b); // CHECK-LABEL: define{{.*}}4foo3{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3B:_ZTSFvu3refIu3dynIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects6Trait3Iu5paramEu6regionEEu3refIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects5Type3EE]]") } pub fn bar3() { let a = Type3; foo3(&a); let b = &a as &dyn Trait3; - b.baz(&a); + b.foo3(&a); // CHECK-LABEL: define{{.*}}4bar3{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE3B]]") } pub fn foo4<'a>(a: &dyn Trait4<'a, Type4, Output = &'a i32>) { let b = Type4; - a.qux(&b); + a.foo4(&b); // CHECK-LABEL: define{{.*}}4foo4{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4B:_ZTSFu3refIu3i32Eu3refIu3dynIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects6Trait4Iu6regionu5paramEu6regionEEu3refIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects5Type4EE]]") } pub fn bar4<'a>() { let a = Type4; foo4(&a); let b = &a as &dyn Trait4<'a, Type4, Output = &'a i32>; - b.qux(&a); + b.foo4(&a); // CHECK-LABEL: define{{.*}}4bar4{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE4B]]") } pub fn foo5(a: &dyn Trait5) { let b = &[Type5; 32]; - a.quux(&b); + a.foo5(&b); // CHECK-LABEL: define{{.*}}4foo5{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5B:_ZTSFvu3refIu3dynIu[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects6Trait5Iu5paramLu5usizeEEu6regionEEu3refIA32u[0-9]+NtC[[:print:]]+_55cfi_emit_type_metadata_id_itanium_cxx_abi_trait_objects5Type5EE]]") } pub fn bar5() { let a = &[Type5; 32]; foo5(&a); let b = &a as &dyn Trait5; - b.quux(&a); + b.foo5(&a); // CHECK-LABEL: define{{.*}}4bar5{{.*}}!type !{{[0-9]+}} - // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5:[[:print:]]+]]") + // CHECK: call i1 @llvm.type.test(ptr {{%f|%[0-9]}}, metadata !"[[TYPE5B]]") } -// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE1]]"} -// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE2]]"} -// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE3]]"} -// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE4]]"} -// CHECK: !{{[0-9]+}} = !{i64 0, !"[[TYPE5]]"} +// CHECK: ![[TYPE1A]] = !{i64 0, !"[[TYPE1B]]"} +// CHECK: ![[TYPE2A]] = !{i64 0, !"[[TYPE2B]]"} +// CHECK: ![[TYPE3A]] = !{i64 0, !"[[TYPE3B]]"} +// CHECK: ![[TYPE4A]] = !{i64 0, !"[[TYPE4B]]"} +// CHECK: ![[TYPE5A]] = !{i64 0, !"[[TYPE5B]]"} diff --git a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs index 2d8b13e2080ef..2a6123a36137d 100644 --- a/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs +++ b/tests/codegen/sanitizer/cfi-emit-type-metadata-id-itanium-cxx-abi.rs @@ -7,7 +7,7 @@ #![allow(dead_code)] #![allow(incomplete_features)] #![allow(unused_must_use)] -#![feature(adt_const_params, extern_types, inline_const, type_alias_impl_trait)] +#![feature(adt_const_params, extern_types, generators, inline_const, type_alias_impl_trait)] extern crate core; use core::ffi::*; @@ -43,15 +43,33 @@ impl Trait1 for i32 { fn foo(&self) { } } -// Trait implementation -impl Trait1 for Struct1 { - fn foo(&self) { } +// Helper type to make Type1 have an unique id +struct Foo(i32); + +// repr(transparent) user-defined type +#[repr(transparent)] +pub struct Type1 { + member1: (), + member2: PhantomData, + member3: Foo, } +// Self-referencing repr(transparent) user-defined type +#[repr(transparent)] +pub struct Type2<'a> { + member1: (), + member2: PhantomData, + member3: &'a Type2<'a>, +} + +// Helper type to make Type3 have an unique id +pub struct Bar; + +// repr(transparent) user-defined generic type +#[repr(transparent)] +pub struct Type3(T); + // impl Trait type aliases for helping with defining other types (see below) -pub type Type1 = impl Send; -pub type Type2 = impl Send; -pub type Type3 = impl Send; pub type Type4 = impl Send; pub type Type5 = impl Send; pub type Type6 = impl Send; @@ -62,9 +80,6 @@ pub type Type10 = impl Send; pub type Type11 = impl Send; pub fn fn1<'a>() where - Type1: 'static, - Type2: 'static, - Type3: 'static, Type4: 'static, Type5: 'static, Type6: 'static, @@ -74,47 +89,36 @@ pub fn fn1<'a>() where Type10: 'static, Type11: 'static, { - // Closure - let closure1 = || { }; - let _: Type1 = closure1; - // Constructor pub struct Foo(i32); - let _: Type2 = Foo; + let _: Type4 = Foo; + + // Closure + let closure1 = |_: i64| { }; + let _: Type5 = closure1; + + // Generator + let generator1 = || { yield 1; 1 }; + let _: Type6 = generator1; // Type in extern path extern { fn foo(); } - let _: Type3 = foo; + let _: Type7 = foo; // Type in closure path || { pub struct Foo; - let _: Type4 = Foo; + let _: Type8 = Foo; }; // Type in const path const { pub struct Foo; - fn foo() -> Type5 { Foo } + fn foo() -> Type9 { Foo } }; - // Type in impl path - impl Struct1 { - fn foo(&self) { } - } - let _: Type6 = >::foo; - - // Trait method - let _: Type7 = >::foo; - - // Trait method - let _: Type8 = >::foo; - - // Trait method - let _: Type9 = as Trait1>::foo; - // Const generics pub struct Qux([T; N]); let _: Type10 = Qux([0; 32]); @@ -125,32 +129,6 @@ pub fn fn1<'a>() where let _: Type11 = Quuux; } -// Helper type to make Type12 have an unique id -struct Foo(i32); - -// repr(transparent) user-defined type -#[repr(transparent)] -pub struct Type12 { - member1: (), - member2: PhantomData, - member3: Foo, -} - -// Self-referencing repr(transparent) user-defined type -#[repr(transparent)] -pub struct Type13<'a> { - member1: (), - member2: PhantomData, - member3: &'a Type13<'a>, -} - -// Helper type to make Type14 have an unique id -pub struct Bar; - -// repr(transparent) user-defined generic type -#[repr(transparent)] -pub struct Type14(T); - pub fn foo0(_: ()) { } // CHECK: define{{.*}}foo0{{.*}}!type ![[TYPE0:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} pub fn foo1(_: (), _: c_void) { } @@ -339,118 +317,94 @@ pub fn foo92(_: *const i32, _: *mut i32, _: *mut i32) { } // CHECK: define{{.*}}foo92{{.*}}!type ![[TYPE92:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} pub fn foo93(_: fn(i32) -> i32) { } // CHECK: define{{.*}}foo93{{.*}}!type ![[TYPE93:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo94(_: fn(i32) -> i32, _: fn(i32) -> i32) { } +pub fn foo94(_: fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { } // CHECK: define{{.*}}foo94{{.*}}!type ![[TYPE94:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo95(_: fn(i32) -> i32, _: fn(i32) -> i32, _: fn(i32) -> i32) { } +pub fn foo95(_: fn(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnOnce(i32) -> i32) { } // CHECK: define{{.*}}foo95{{.*}}!type ![[TYPE95:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo96(_: &dyn Fn(i32) -> i32) { } +pub fn foo96(_: &dyn Trait1) { } // CHECK: define{{.*}}foo96{{.*}}!type ![[TYPE96:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo97(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { } +pub fn foo97(_: &dyn Trait1, _: &dyn Trait1) { } // CHECK: define{{.*}}foo97{{.*}}!type ![[TYPE97:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo98(_: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32, _: &dyn Fn(i32) -> i32) { } +pub fn foo98(_: &dyn Trait1, _: &dyn Trait1, _: &dyn Trait1) { } // CHECK: define{{.*}}foo98{{.*}}!type ![[TYPE98:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo99(_: &dyn FnMut(i32) -> i32) { } +pub fn foo99(_: &dyn Send) { } // CHECK: define{{.*}}foo99{{.*}}!type ![[TYPE99:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo100(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { } +pub fn foo100(_: &dyn Send, _: &dyn Send) { } // CHECK: define{{.*}}foo100{{.*}}!type ![[TYPE100:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo101(_: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32, _: &dyn FnMut(i32) -> i32) { } +pub fn foo101(_: &dyn Send, _: &dyn Send, _: &dyn Send) { } // CHECK: define{{.*}}foo101{{.*}}!type ![[TYPE101:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo102(_: &dyn FnOnce(i32) -> i32) { } +pub fn foo102(_: &(dyn Send + Sync)) { } // CHECK: define{{.*}}foo102{{.*}}!type ![[TYPE102:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo103(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) { } +pub fn foo103(_: &(dyn Send + Sync), _: &(dyn Send + Sync)) { } // CHECK: define{{.*}}foo103{{.*}}!type ![[TYPE103:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo104(_: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32, _: &dyn FnOnce(i32) -> i32) {} +pub fn foo104(_: &(dyn Send + Sync), _: &(dyn Send + Sync), _: &(dyn Send + Sync)) { } // CHECK: define{{.*}}foo104{{.*}}!type ![[TYPE104:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo105(_: &dyn Send) { } +pub fn foo105(_: Type1) { } // CHECK: define{{.*}}foo105{{.*}}!type ![[TYPE105:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo106(_: &dyn Send, _: &dyn Send) { } +pub fn foo106(_: Type1, _: Type1) { } // CHECK: define{{.*}}foo106{{.*}}!type ![[TYPE106:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo107(_: &dyn Send, _: &dyn Send, _: &dyn Send) { } +pub fn foo107(_: Type1, _: Type1, _: Type1) { } // CHECK: define{{.*}}foo107{{.*}}!type ![[TYPE107:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo108(_: Type1) { } +pub fn foo108(_: Type2) { } // CHECK: define{{.*}}foo108{{.*}}!type ![[TYPE108:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo109(_: Type1, _: Type1) { } +pub fn foo109(_: Type2, _: Type2) { } // CHECK: define{{.*}}foo109{{.*}}!type ![[TYPE109:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo110(_: Type1, _: Type1, _: Type1) { } +pub fn foo110(_: Type2, _: Type2, _: Type2) { } // CHECK: define{{.*}}foo110{{.*}}!type ![[TYPE110:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo111(_: Type2) { } +pub fn foo111(_: Type3) { } // CHECK: define{{.*}}foo111{{.*}}!type ![[TYPE111:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo112(_: Type2, _: Type2) { } +pub fn foo112(_: Type3, _: Type3) { } // CHECK: define{{.*}}foo112{{.*}}!type ![[TYPE112:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo113(_: Type2, _: Type2, _: Type2) { } +pub fn foo113(_: Type3, _: Type3, _: Type3) { } // CHECK: define{{.*}}foo113{{.*}}!type ![[TYPE113:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo114(_: Type3) { } +pub fn foo114(_: Type4) { } // CHECK: define{{.*}}foo114{{.*}}!type ![[TYPE114:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo115(_: Type3, _: Type3) { } +pub fn foo115(_: Type4, _: Type4) { } // CHECK: define{{.*}}foo115{{.*}}!type ![[TYPE115:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo116(_: Type3, _: Type3, _: Type3) { } +pub fn foo116(_: Type4, _: Type4, _: Type4) { } // CHECK: define{{.*}}foo116{{.*}}!type ![[TYPE116:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo117(_: Type4) { } +pub fn foo117(_: Type5) { } // CHECK: define{{.*}}foo117{{.*}}!type ![[TYPE117:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo118(_: Type4, _: Type4) { } +pub fn foo118(_: Type5, _: Type5) { } // CHECK: define{{.*}}foo118{{.*}}!type ![[TYPE118:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo119(_: Type4, _: Type4, _: Type4) { } +pub fn foo119(_: Type5, _: Type5, _: Type5) { } // CHECK: define{{.*}}foo119{{.*}}!type ![[TYPE119:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo120(_: Type5) { } +pub fn foo120(_: Type6) { } // CHECK: define{{.*}}foo120{{.*}}!type ![[TYPE120:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo121(_: Type5, _: Type5) { } +pub fn foo121(_: Type6, _: Type6) { } // CHECK: define{{.*}}foo121{{.*}}!type ![[TYPE121:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo122(_: Type5, _: Type5, _: Type5) { } +pub fn foo122(_: Type6, _: Type6, _: Type6) { } // CHECK: define{{.*}}foo122{{.*}}!type ![[TYPE122:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo123(_: Type6) { } +pub fn foo123(_: Type7) { } // CHECK: define{{.*}}foo123{{.*}}!type ![[TYPE123:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo124(_: Type6, _: Type6) { } +pub fn foo124(_: Type7, _: Type7) { } // CHECK: define{{.*}}foo124{{.*}}!type ![[TYPE124:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo125(_: Type6, _: Type6, _: Type6) { } +pub fn foo125(_: Type7, _: Type7, _: Type7) { } // CHECK: define{{.*}}foo125{{.*}}!type ![[TYPE125:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo126(_: Type7) { } +pub fn foo126(_: Type8) { } // CHECK: define{{.*}}foo126{{.*}}!type ![[TYPE126:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo127(_: Type7, _: Type7) { } +pub fn foo127(_: Type8, _: Type8) { } // CHECK: define{{.*}}foo127{{.*}}!type ![[TYPE127:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo128(_: Type7, _: Type7, _: Type7) { } +pub fn foo128(_: Type8, _: Type8, _: Type8) { } // CHECK: define{{.*}}foo128{{.*}}!type ![[TYPE128:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo129(_: Type8) { } +pub fn foo129(_: Type9) { } // CHECK: define{{.*}}foo129{{.*}}!type ![[TYPE129:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo130(_: Type8, _: Type8) { } +pub fn foo130(_: Type9, _: Type9) { } // CHECK: define{{.*}}foo130{{.*}}!type ![[TYPE130:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo131(_: Type8, _: Type8, _: Type8) { } +pub fn foo131(_: Type9, _: Type9, _: Type9) { } // CHECK: define{{.*}}foo131{{.*}}!type ![[TYPE131:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo132(_: Type9) { } +pub fn foo132(_: Type10) { } // CHECK: define{{.*}}foo132{{.*}}!type ![[TYPE132:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo133(_: Type9, _: Type9) { } +pub fn foo133(_: Type10, _: Type10) { } // CHECK: define{{.*}}foo133{{.*}}!type ![[TYPE133:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo134(_: Type9, _: Type9, _: Type9) { } +pub fn foo134(_: Type10, _: Type10, _: Type10) { } // CHECK: define{{.*}}foo134{{.*}}!type ![[TYPE134:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo135(_: Type10) { } +pub fn foo135(_: Type11) { } // CHECK: define{{.*}}foo135{{.*}}!type ![[TYPE135:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo136(_: Type10, _: Type10) { } +pub fn foo136(_: Type11, _: Type11) { } // CHECK: define{{.*}}foo136{{.*}}!type ![[TYPE136:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo137(_: Type10, _: Type10, _: Type10) { } +pub fn foo137(_: Type11, _: Type11, _: Type11) { } // CHECK: define{{.*}}foo137{{.*}}!type ![[TYPE137:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo138(_: Type11) { } -// CHECK: define{{.*}}foo138{{.*}}!type ![[TYPE138:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo139(_: Type11, _: Type11) { } -// CHECK: define{{.*}}foo139{{.*}}!type ![[TYPE139:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo140(_: Type11, _: Type11, _: Type11) { } -// CHECK: define{{.*}}foo140{{.*}}!type ![[TYPE140:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo141(_: Type12) { } -// CHECK: define{{.*}}foo141{{.*}}!type ![[TYPE141:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo142(_: Type12, _: Type12) { } -// CHECK: define{{.*}}foo142{{.*}}!type ![[TYPE142:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo143(_: Type12, _: Type12, _: Type12) { } -// CHECK: define{{.*}}foo143{{.*}}!type ![[TYPE143:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo144(_: Type13) { } -// CHECK: define{{.*}}foo144{{.*}}!type ![[TYPE144:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo145(_: Type13, _: Type13) { } -// CHECK: define{{.*}}foo145{{.*}}!type ![[TYPE145:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo146(_: Type13, _: Type13, _: Type13) { } -// CHECK: define{{.*}}foo146{{.*}}!type ![[TYPE146:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo147(_: Type14) { } -// CHECK: define{{.*}}foo147{{.*}}!type ![[TYPE147:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo148(_: Type14, _: Type14) { } -// CHECK: define{{.*}}foo148{{.*}}!type ![[TYPE148:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} -pub fn foo149(_: Type14, _: Type14, _: Type14) { } -// CHECK: define{{.*}}foo149{{.*}}!type ![[TYPE149:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}} // CHECK: ![[TYPE0]] = !{i64 0, !"_ZTSFvvE"} // CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvvvE"} @@ -548,57 +502,45 @@ pub fn foo149(_: Type14, _: Type14, _: Type14) { } // CHECK: ![[TYPE93]] = !{i64 0, !"_ZTSFvPFu3i32S_EE"} // CHECK: ![[TYPE94]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_E"} // CHECK: ![[TYPE95]] = !{i64 0, !"_ZTSFvPFu3i32S_ES0_S0_E"} -// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEEE"} -// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_E"} -// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function2FnIu5paramEu6regionEES3_S3_E"} -// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEEE"} -// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_E"} -// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function5FnMutIu5paramEu6regionEES3_S3_E"} -// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEEE"} -// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_E"} -// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops8function6FnOnceIu5paramEu6regionEES3_S3_E"} -// CHECK: ![[TYPE105]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEEE"} -// CHECK: ![[TYPE106]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_E"} -// CHECK: ![[TYPE107]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_S2_E"} -// CHECK: ![[TYPE108]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn111{{[{}][{}]}}closure{{[}][}]}}Iu2i8PFvvEvEE"} -// CHECK: ![[TYPE109]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn111{{[{}][{}]}}closure{{[}][}]}}Iu2i8PFvvEvES1_E"} -// CHECK: ![[TYPE110]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn111{{[{}][{}]}}closure{{[}][}]}}Iu2i8PFvvEvES1_S1_E"} -// CHECK: ![[TYPE111]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foo15{{[{}][{}]}}constructor{{[}][}]}}E"} -// CHECK: ![[TYPE112]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foo15{{[{}][{}]}}constructor{{[}][}]}}S_E"} -// CHECK: ![[TYPE113]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foo15{{[{}][{}]}}constructor{{[}][}]}}S_S_E"} -// CHECK: ![[TYPE114]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn110{{[{}][{}]}}extern{{[}][}]}}3fooE"} -// CHECK: ![[TYPE115]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn110{{[{}][{}]}}extern{{[}][}]}}3fooS_E"} -// CHECK: ![[TYPE116]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn110{{[{}][{}]}}extern{{[}][}]}}3fooS_S_E"} -// CHECK: ![[TYPE117]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s0_11{{[{}][{}]}}closure{{[}][}]}}3FooE"} -// CHECK: ![[TYPE118]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s0_11{{[{}][{}]}}closure{{[}][}]}}3FooS_E"} -// CHECK: ![[TYPE119]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s0_11{{[{}][{}]}}closure{{[}][}]}}3FooS_S_E"} -// CHECK: ![[TYPE120]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooE"} -// CHECK: ![[TYPE121]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooS_E"} -// CHECK: ![[TYPE122]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooS_S_E"} -// CHECK: ![[TYPE123]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32EE"} -// CHECK: ![[TYPE124]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_E"} -// CHECK: ![[TYPE125]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn18{{[{}][{}]}}impl{{[}][}]}}3fooIu3i32ES0_S0_E"} -// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEu3i32EE"} -// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEu3i32ES4_E"} -// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEu3i32ES4_S4_E"} -// CHECK: ![[TYPE129]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3i32S_EE"} -// CHECK: ![[TYPE130]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3i32S_ES0_E"} -// CHECK: ![[TYPE131]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu3i32S_ES0_S0_E"} -// CHECK: ![[TYPE132]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]7Struct1Iu3i32ES_EE"} -// CHECK: ![[TYPE133]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]7Struct1Iu3i32ES_ES1_E"} -// CHECK: ![[TYPE134]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NvNtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait13fooIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]7Struct1Iu3i32ES_ES1_S1_E"} -// CHECK: ![[TYPE135]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EEE"} -// CHECK: ![[TYPE136]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EES2_E"} -// CHECK: ![[TYPE137]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EES2_S2_E"} -// CHECK: ![[TYPE138]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15Quuux15{{[{}][{}]}}constructor{{[}][}]}}Iu6regionS_EE"} -// CHECK: ![[TYPE139]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15Quuux15{{[{}][{}]}}constructor{{[}][}]}}Iu6regionS_ES0_E"} -// CHECK: ![[TYPE140]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NcNtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15Quuux15{{[{}][{}]}}constructor{{[}][}]}}Iu6regionS_ES0_S0_E"} -// CHECK: ![[TYPE141]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooE"} -// CHECK: ![[TYPE142]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooS_E"} -// CHECK: ![[TYPE143]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooS_S_E"} -// CHECK: ![[TYPE144]] = !{i64 0, !"_ZTSFvu3refIvEE"} -// CHECK: ![[TYPE145]] = !{i64 0, !"_ZTSFvu3refIvES_E"} -// CHECK: ![[TYPE146]] = !{i64 0, !"_ZTSFvu3refIvES_S_E"} -// CHECK: ![[TYPE147]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarE"} -// CHECK: ![[TYPE148]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarS_E"} -// CHECK: ![[TYPE149]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarS_S_E"} +// CHECK: ![[TYPE96]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEEE"} +// CHECK: ![[TYPE97]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEES3_E"} +// CHECK: ![[TYPE98]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]6Trait1Iu5paramEu6regionEES3_S3_E"} +// CHECK: ![[TYPE99]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEEE"} +// CHECK: ![[TYPE100]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_E"} +// CHECK: ![[TYPE101]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4Sendu6regionEES2_S2_E"} +// CHECK: ![[TYPE102]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u6regionEEE"} +// CHECK: ![[TYPE103]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u6regionEES3_E"} +// CHECK: ![[TYPE104]] = !{i64 0, !"_ZTSFvu3refIu3dynIu{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u{{[0-9]+}}NtNtC{{[[:print:]]+}}_4core6marker4{{(Send|Sync)}}u6regionEES3_S3_E"} +// CHECK: ![[TYPE105]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooE"} +// CHECK: ![[TYPE106]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooS_E"} +// CHECK: ![[TYPE107]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3FooS_S_E"} +// CHECK: ![[TYPE108]] = !{i64 0, !"_ZTSFvu3refIvEE"} +// CHECK: ![[TYPE109]] = !{i64 0, !"_ZTSFvu3refIvES_E"} +// CHECK: ![[TYPE110]] = !{i64 0, !"_ZTSFvu3refIvES_S_E"} +// CHECK: ![[TYPE111]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarE"} +// CHECK: ![[TYPE112]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarS_E"} +// CHECK: ![[TYPE113]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3BarS_S_E"} +// CHECK: ![[TYPE114]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foou3i32EE"} +// CHECK: ![[TYPE115]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foou3i32ES1_E"} +// CHECK: ![[TYPE116]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13Foou3i32ES1_S1_E"} +// CHECK: ![[TYPE117]] = !{i64 0, !"_ZTSFvPFvu3i64EE"} +// CHECK: ![[TYPE118]] = !{i64 0, !"_ZTSFvPFvu3i64ES0_E"} +// CHECK: ![[TYPE119]] = !{i64 0, !"_ZTSFvPFvu3i64ES0_S0_E"} +// CHECK: ![[TYPE120]] = !{i64 0, !"_ZTSFvu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops9generator9GeneratorIvu3i32S_Eu6regionEE"} +// CHECK: ![[TYPE121]] = !{i64 0, !"_ZTSFvu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops9generator9GeneratorIvu3i32S_Eu6regionES2_E"} +// CHECK: ![[TYPE122]] = !{i64 0, !"_ZTSFvu3dynIu{{[0-9]+}}NtNtNtC{{[[:print:]]+}}_4core3ops9generator9GeneratorIvu3i32S_Eu6regionES2_S2_E"} +// CHECK: ![[TYPE123]] = !{i64 0, !"_ZTSFvPFvvEE"} +// CHECK: ![[TYPE124]] = !{i64 0, !"_ZTSFvPFvvES_E"} +// CHECK: ![[TYPE125]] = !{i64 0, !"_ZTSFvPFvvES_S_E"} +// CHECK: ![[TYPE126]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s1_11{{[{}][{}]}}closure{{[}][}]}}3FooE"} +// CHECK: ![[TYPE127]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s1_11{{[{}][{}]}}closure{{[}][}]}}3FooS_E"} +// CHECK: ![[TYPE128]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn1s1_11{{[{}][{}]}}closure{{[}][}]}}3FooS_S_E"} +// CHECK: ![[TYPE129]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooE"} +// CHECK: ![[TYPE130]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooS_E"} +// CHECK: ![[TYPE131]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn112{{[{}][{}]}}constant{{[}][}]}}3FooS_S_E"} +// CHECK: ![[TYPE132]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EEE"} +// CHECK: ![[TYPE133]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EES2_E"} +// CHECK: ![[TYPE134]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn13QuxIu3i32Lu5usize32EES2_S2_E"} +// CHECK: ![[TYPE135]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15QuuuxIu6regionu6regionEu3refIu3i32Eu3refIu70NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn14QuuxIS0_EEEE"} +// CHECK: ![[TYPE136]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15QuuuxIu6regionu6regionEu3refIu3i32Eu3refIu70NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn14QuuxIS0_EEES6_E"} +// CHECK: ![[TYPE137]] = !{i64 0, !"_ZTSFvPFu{{[0-9]+}}NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn15QuuuxIu6regionu6regionEu3refIu3i32Eu3refIu70NtNvC{{[[:print:]]+}}_[[ITANIUMED_FILENAME]]3fn14QuuxIS0_EEES6_S6_E"} diff --git a/tests/codegen/sanitizer/kcfi-emit-type-metadata-trait-objects.rs b/tests/codegen/sanitizer/kcfi-emit-type-metadata-trait-objects.rs deleted file mode 100644 index 7aed137f215ce..0000000000000 --- a/tests/codegen/sanitizer/kcfi-emit-type-metadata-trait-objects.rs +++ /dev/null @@ -1,174 +0,0 @@ -// 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 trait Trait5 { - fn quux(&self, _: &[T; N]); -} - -pub struct Type5; - -impl Copy for Type5 {} - -impl Trait5 for T { - fn quux(&self, _: &[U; N]) { - } -} - -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 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 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 %{{[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{{.*}}!{{|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) { - let b = &[Type5; 32]; - a.quux(&b); - // CHECK-LABEL: define{{.*}}4foo5{{.*}}!{{|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; - b.quux(&a); - // CHECK-LABEL: define{{.*}}4bar5{{.*}}!{{|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]]}