diff options
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r-- | src/codegen/mod.rs | 70 |
1 files changed, 34 insertions, 36 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index 2b285766..607f57ac 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -2172,56 +2172,54 @@ impl CodeGenerator for CompInfo { let should_skip_field_offset_checks = is_opaque || too_many_base_vtables; - let (check_field_offset_decls, check_field_offset_invocs) = if should_skip_field_offset_checks + let (uninit_decl, check_field_offset) = if should_skip_field_offset_checks { - (vec![], vec![]) + (None, vec![]) } else { - self.fields() - .iter() - .filter_map(|field| match *field { - Field::DataMember(ref f) if f.name().is_some() => Some(f), - _ => None, - }) - .flat_map(|field| { - let name = field.name().unwrap(); - field.offset().map(|offset| { - let field_offset = offset / 8; - let field_name = ctx.rust_ident(name); - // Put each check in its own function, so - // that rustc with opt-level=0 doesn't take - // too much stack space, see #2218. - let test_fn = Ident::new(&format!("test_field_{}", name), Span::call_site()); - ( + ( + Some(quote! { + // Use a shared MaybeUninit so that rustc with + // opt-level=0 doesn't take too much stack + // space, see #2218. + const UNINIT: ::#prefix::mem::MaybeUninit<#canonical_ident> = ::#prefix::mem::MaybeUninit::uninit(); + }), + self.fields() + .iter() + .filter_map(|field| match *field { + Field::DataMember(ref f) if f.name().is_some() => Some(f), + _ => None, + }) + .flat_map(|field| { + let name = field.name().unwrap(); + field.offset().map(|offset| { + let field_offset = offset / 8; + let field_name = ctx.rust_ident(name); quote! { - fn #test_fn() { - assert_eq!( - unsafe { - let uninit = ::#prefix::mem::MaybeUninit::<#canonical_ident>::uninit(); - let ptr = uninit.as_ptr(); - ::#prefix::ptr::addr_of!((*ptr).#field_name) as usize - ptr as usize - }, - #field_offset, - concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name)) - ); - } - }, - quote! { #test_fn(); } - ) + assert_eq!( + unsafe { + let ptr = UNINIT.as_ptr(); + ::#prefix::ptr::addr_of!((*ptr).#field_name) as usize - ptr as usize + }, + #field_offset, + concat!("Offset of field: ", stringify!(#canonical_ident), "::", stringify!(#field_name)) + ); + } + }) }) - }) - .unzip() + .collect() + ) }; let item = quote! { #[test] fn #fn_name() { - #( #check_field_offset_decls )* + #uninit_decl assert_eq!(#size_of_expr, #size, concat!("Size of: ", stringify!(#canonical_ident))); #check_struct_align - #( #check_field_offset_invocs )* + #( #check_field_offset )* } }; result.push(item); |