diff --git a/c2rust-transpile/src/c_ast/mod.rs b/c2rust-transpile/src/c_ast/mod.rs index 572353f384..2a11934944 100644 --- a/c2rust-transpile/src/c_ast/mod.rs +++ b/c2rust-transpile/src/c_ast/mod.rs @@ -1013,6 +1013,21 @@ impl TypedAstContext { } } + /// Sort the top-level declarations with macros coming last. + /// This is needed during conversion so that when recreating macros, + /// we can look up the [`Translation::expr_override_tys`], + /// which are set when the macro expansion expressions are converted. + pub fn sort_top_decls_for_converting(&mut self) { + self.c_decls_top.sort_unstable_by_key(|decl_id| { + let reverse_order = match self.c_decls.get(decl_id).unwrap().kind { + CDeclKind::MacroFunction { .. } => 0, + CDeclKind::MacroObject { .. } => 1, + _ => 2, + }; + -reverse_order + }); + } + /// Sort the top-level declarations by file and source location /// so that we preserve the ordering of all declarations in each file. /// This preserves the order when we emit the converted declarations. diff --git a/c2rust-transpile/src/translator/mod.rs b/c2rust-transpile/src/translator/mod.rs index 9ce3b888dd..83d002b6b8 100644 --- a/c2rust-transpile/src/translator/mod.rs +++ b/c2rust-transpile/src/translator/mod.rs @@ -266,6 +266,15 @@ pub struct Translation<'c> { potential_flexible_array_members: RefCell>, macro_expansions: RefCell>>, + /// For every call to [`Self::convert_expr`], + /// we record the `override_ty` that is used for that expression. + /// + /// This is needed [`Self::recreate_const_macro_from_expansions`] + /// when we call [`Self::convert_expr`] for each of the macro expansions, + /// as unlike normal [`Self::convert_expr`]s, there is no surrounding context + /// higher in the call stack calculating the `override_ty`. + expr_override_tys: RefCell>, + // Comment support pub comment_context: CommentContext, // Incoming comments pub comment_store: RefCell, // Outgoing comments @@ -689,6 +698,8 @@ pub fn translate( } } + t.ast_context.sort_top_decls_for_converting(); + // Export top-level value declarations. // We do this in a conversion pass and then an insertion pass // so that the conversion order can differ from the order they're emitted in. @@ -1215,6 +1226,7 @@ impl<'c> Translation<'c> { function_context: RefCell::new(FuncContext::new()), potential_flexible_array_members: RefCell::new(IndexSet::new()), macro_expansions: RefCell::new(IndexMap::new()), + expr_override_tys: Default::default(), comment_context, comment_store: RefCell::new(CommentStore::new()), spans: HashMap::new(), @@ -2195,7 +2207,9 @@ impl<'c> Translation<'c> { .kind .get_type() .ok_or_else(|| format_err!("Invalid expression type"))?; - let expr = self.convert_expr(ctx, id, None)?; + let override_ty = self.expr_override_tys.borrow().get(&id).copied(); + let expr = self.convert_expr(ctx, id, override_ty)?; + let ty = override_ty.map(|ty| ty.ctype).unwrap_or(ty); // Join ty and cur_ty to the smaller of the two types. If the // types are not cast-compatible, abort the fold. @@ -3283,6 +3297,12 @@ impl<'c> Translation<'c> { expr_id: CExprId, override_ty: Option, ) -> TranslationResult>> { + if let Some(override_ty) = override_ty { + self.expr_override_tys + .borrow_mut() + .insert(expr_id, override_ty); + } + let Located { loc: src_loc, kind: expr_kind, diff --git a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap index a373790485..2930895de7 100644 --- a/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap +++ b/c2rust-transpile/tests/snapshots/snapshots__transpile@macros.c.snap @@ -35,10 +35,10 @@ pub struct ntlmdata { pub target_info_len: core::ffi::c_uint, } pub const true_0: core::ffi::c_int = 1 as core::ffi::c_int; -pub const UINTPTR_MAX: core::ffi::c_ulong = 18446744073709551615 as core::ffi::c_ulong; +pub const UINTPTR_MAX: uintptr_t = 18446744073709551615 as uintptr_t; pub const LITERAL_INT: core::ffi::c_int = 0xffff as core::ffi::c_int; pub const LITERAL_BOOL: core::ffi::c_int = true_0; -pub const LITERAL_FLOAT: core::ffi::c_double = 3.14f64; +pub const LITERAL_FLOAT: core::ffi::c_float = 3.14f32; pub const LITERAL_CHAR: core::ffi::c_int = 'x' as i32; pub const LITERAL_STR: [core::ffi::c_char; 6] = unsafe { ::core::mem::transmute::<[u8; 6], [core::ffi::c_char; 6]>(*b"hello\0") }; @@ -50,7 +50,7 @@ pub const LITERAL_STRUCT: S = { }; pub const NESTED_INT: core::ffi::c_int = LITERAL_INT; pub const NESTED_BOOL: core::ffi::c_int = LITERAL_BOOL; -pub const NESTED_FLOAT: core::ffi::c_double = LITERAL_FLOAT; +pub const NESTED_FLOAT: core::ffi::c_float = LITERAL_FLOAT; pub const NESTED_CHAR: core::ffi::c_int = LITERAL_CHAR; pub const NESTED_STR: [core::ffi::c_char; 6] = LITERAL_STR; pub const NESTED_STRUCT: S = LITERAL_STRUCT; @@ -67,7 +67,7 @@ pub const CONVERSION_CAST: core::ffi::c_double = LITERAL_INT as core::ffi::c_dou pub unsafe extern "C" fn local_muts() { let mut literal_int: core::ffi::c_int = LITERAL_INT; let mut literal_bool: bool = LITERAL_BOOL != 0; - let mut literal_float: core::ffi::c_float = LITERAL_FLOAT as core::ffi::c_float; + let mut literal_float: core::ffi::c_float = LITERAL_FLOAT; let mut literal_char: core::ffi::c_char = LITERAL_CHAR as core::ffi::c_char; let mut literal_str_ptr: *const core::ffi::c_char = LITERAL_STR.as_ptr(); let mut literal_str: [core::ffi::c_char; 6] = LITERAL_STR; @@ -79,7 +79,7 @@ pub unsafe extern "C" fn local_muts() { let mut literal_struct: S = LITERAL_STRUCT; let mut nested_int: core::ffi::c_int = NESTED_INT; let mut nested_bool: bool = NESTED_BOOL != 0; - let mut nested_float: core::ffi::c_float = NESTED_FLOAT as core::ffi::c_float; + let mut nested_float: core::ffi::c_float = NESTED_FLOAT; let mut nested_char: core::ffi::c_char = NESTED_CHAR as core::ffi::c_char; let mut nested_str_ptr: *const core::ffi::c_char = NESTED_STR.as_ptr(); let mut nested_str: [core::ffi::c_char; 6] = NESTED_STR; @@ -90,15 +90,17 @@ pub unsafe extern "C" fn local_muts() { ]; let mut nested_struct: S = NESTED_STRUCT; let mut int_arithmetic: core::ffi::c_int = NESTED_INT + LITERAL_INT + 1 as core::ffi::c_int; - let mut mixed_arithmetic: core::ffi::c_float = - (LITERAL_INT as core::ffi::c_double + NESTED_FLOAT * LITERAL_CHAR as core::ffi::c_double - - true_0 as core::ffi::c_double) as core::ffi::c_float; + let mut mixed_arithmetic: core::ffi::c_float = (LITERAL_INT as core::ffi::c_double + + NESTED_FLOAT as core::ffi::c_double * LITERAL_CHAR as core::ffi::c_double + - true_0 as core::ffi::c_double) + as core::ffi::c_float; let mut parens: core::ffi::c_int = PARENS; let mut ptr_arithmetic: *const core::ffi::c_char = PTR_ARITHMETIC; let mut widening_cast: core::ffi::c_ulonglong = WIDENING_CAST; let mut narrowing_cast: core::ffi::c_char = LITERAL_INT as core::ffi::c_char; let mut conversion_cast: core::ffi::c_double = CONVERSION_CAST; - let mut indexing: core::ffi::c_char = NESTED_STR[LITERAL_FLOAT as core::ffi::c_int as usize]; + let mut indexing: core::ffi::c_char = + NESTED_STR[LITERAL_FLOAT as core::ffi::c_double as core::ffi::c_int as usize]; let mut str_concatenation_ptr: *const core::ffi::c_char = b"hello hello world\0" as *const u8 as *const core::ffi::c_char; let mut str_concatenation: [core::ffi::c_char; 18] = @@ -106,7 +108,7 @@ pub unsafe extern "C" fn local_muts() { let mut builtin: core::ffi::c_int = (LITERAL_INT as core::ffi::c_uint).leading_zeros() as i32; let mut ref_indexing: *const core::ffi::c_char = &*NESTED_STR .as_ptr() - .offset(LITERAL_FLOAT as core::ffi::c_int as isize) + .offset(LITERAL_FLOAT as core::ffi::c_double as core::ffi::c_int as isize) as *const core::ffi::c_char; let mut ref_struct: *const S = &mut LITERAL_STRUCT as *mut S; let mut ternary: core::ffi::c_int = if LITERAL_BOOL != 0 { @@ -119,9 +121,9 @@ pub unsafe extern "C" fn local_muts() { let mut builtin_0: core::ffi::c_int = (LITERAL_INT as core::ffi::c_uint).leading_zeros() as i32; let mut indexing_0: core::ffi::c_char = - NESTED_STR[LITERAL_FLOAT as core::ffi::c_int as usize]; + NESTED_STR[LITERAL_FLOAT as core::ffi::c_double as core::ffi::c_int as usize]; let mut mixed: core::ffi::c_float = (LITERAL_INT as core::ffi::c_double - + NESTED_FLOAT * LITERAL_CHAR as core::ffi::c_double + + NESTED_FLOAT as core::ffi::c_double * LITERAL_CHAR as core::ffi::c_double - true_0 as core::ffi::c_double) as core::ffi::c_float; let mut i: core::ffi::c_int = 0 as core::ffi::c_int; @@ -136,7 +138,7 @@ pub unsafe extern "C" fn local_muts() { pub unsafe extern "C" fn local_consts() { let literal_int: core::ffi::c_int = LITERAL_INT; let literal_bool: bool = LITERAL_BOOL != 0; - let literal_float: core::ffi::c_float = LITERAL_FLOAT as core::ffi::c_float; + let literal_float: core::ffi::c_float = LITERAL_FLOAT; let literal_char: core::ffi::c_char = LITERAL_CHAR as core::ffi::c_char; let literal_str_ptr: *const core::ffi::c_char = LITERAL_STR.as_ptr(); let literal_str: [core::ffi::c_char; 6] = LITERAL_STR; @@ -148,7 +150,7 @@ pub unsafe extern "C" fn local_consts() { let literal_struct: S = LITERAL_STRUCT; let nested_int: core::ffi::c_int = NESTED_INT; let nested_bool: bool = NESTED_BOOL != 0; - let nested_float: core::ffi::c_float = NESTED_FLOAT as core::ffi::c_float; + let nested_float: core::ffi::c_float = NESTED_FLOAT; let nested_char: core::ffi::c_char = NESTED_CHAR as core::ffi::c_char; let nested_str_ptr: *const core::ffi::c_char = NESTED_STR.as_ptr(); let nested_str: [core::ffi::c_char; 6] = NESTED_STR; @@ -159,15 +161,17 @@ pub unsafe extern "C" fn local_consts() { ]; let nested_struct: S = NESTED_STRUCT; let int_arithmetic: core::ffi::c_int = NESTED_INT + LITERAL_INT + 1 as core::ffi::c_int; - let mixed_arithmetic: core::ffi::c_float = - (LITERAL_INT as core::ffi::c_double + NESTED_FLOAT * LITERAL_CHAR as core::ffi::c_double - - true_0 as core::ffi::c_double) as core::ffi::c_float; + let mixed_arithmetic: core::ffi::c_float = (LITERAL_INT as core::ffi::c_double + + NESTED_FLOAT as core::ffi::c_double * LITERAL_CHAR as core::ffi::c_double + - true_0 as core::ffi::c_double) + as core::ffi::c_float; let parens: core::ffi::c_int = PARENS; let ptr_arithmetic: *const core::ffi::c_char = PTR_ARITHMETIC; let widening_cast: core::ffi::c_ulonglong = WIDENING_CAST; let narrowing_cast: core::ffi::c_char = LITERAL_INT as core::ffi::c_char; let conversion_cast: core::ffi::c_double = CONVERSION_CAST; - let indexing: core::ffi::c_char = NESTED_STR[LITERAL_FLOAT as core::ffi::c_int as usize]; + let indexing: core::ffi::c_char = + NESTED_STR[LITERAL_FLOAT as core::ffi::c_double as core::ffi::c_int as usize]; let str_concatenation_ptr: *const core::ffi::c_char = b"hello hello world\0" as *const u8 as *const core::ffi::c_char; let str_concatenation: [core::ffi::c_char; 18] = @@ -175,7 +179,7 @@ pub unsafe extern "C" fn local_consts() { let builtin: core::ffi::c_int = (LITERAL_INT as core::ffi::c_uint).leading_zeros() as i32; let ref_indexing: *const core::ffi::c_char = &*NESTED_STR .as_ptr() - .offset(LITERAL_FLOAT as core::ffi::c_int as isize) + .offset(LITERAL_FLOAT as core::ffi::c_double as core::ffi::c_int as isize) as *const core::ffi::c_char; let ref_struct: *const S = &mut LITERAL_STRUCT as *mut S; let ternary: core::ffi::c_int = if LITERAL_BOOL != 0 { @@ -188,9 +192,9 @@ pub unsafe extern "C" fn local_consts() { let mut builtin_0: core::ffi::c_int = (LITERAL_INT as core::ffi::c_uint).leading_zeros() as i32; let mut indexing_0: core::ffi::c_char = - NESTED_STR[LITERAL_FLOAT as core::ffi::c_int as usize]; + NESTED_STR[LITERAL_FLOAT as core::ffi::c_double as core::ffi::c_int as usize]; let mut mixed: core::ffi::c_float = (LITERAL_INT as core::ffi::c_double - + NESTED_FLOAT * LITERAL_CHAR as core::ffi::c_double + + NESTED_FLOAT as core::ffi::c_double * LITERAL_CHAR as core::ffi::c_double - true_0 as core::ffi::c_double) as core::ffi::c_float; let mut i: core::ffi::c_int = 0 as core::ffi::c_int; @@ -203,8 +207,7 @@ pub unsafe extern "C" fn local_consts() { } static mut global_static_const_literal_int: core::ffi::c_int = LITERAL_INT; static mut global_static_const_literal_bool: bool = LITERAL_BOOL != 0; -static mut global_static_const_literal_float: core::ffi::c_float = - LITERAL_FLOAT as core::ffi::c_float; +static mut global_static_const_literal_float: core::ffi::c_float = LITERAL_FLOAT; static mut global_static_const_literal_char: core::ffi::c_char = LITERAL_CHAR as core::ffi::c_char; static mut global_static_const_literal_str_ptr: *const core::ffi::c_char = LITERAL_STR.as_ptr(); static mut global_static_const_literal_str: [core::ffi::c_char; 6] = LITERAL_STR; @@ -216,8 +219,7 @@ static mut global_static_const_literal_array: [core::ffi::c_int; 3] = [ static mut global_static_const_literal_struct: S = LITERAL_STRUCT; static mut global_static_const_nested_int: core::ffi::c_int = NESTED_INT; static mut global_static_const_nested_bool: bool = NESTED_BOOL != 0; -static mut global_static_const_nested_float: core::ffi::c_float = - NESTED_FLOAT as core::ffi::c_float; +static mut global_static_const_nested_float: core::ffi::c_float = NESTED_FLOAT; static mut global_static_const_nested_char: core::ffi::c_char = NESTED_CHAR as core::ffi::c_char; static mut global_static_const_nested_str_ptr: *const core::ffi::c_char = NESTED_STR.as_ptr(); static mut global_static_const_nested_str: [core::ffi::c_char; 6] = NESTED_STR; @@ -230,7 +232,8 @@ static mut global_static_const_nested_struct: S = NESTED_STRUCT; static mut global_static_const_int_arithmetic: core::ffi::c_int = NESTED_INT + LITERAL_INT + 1 as core::ffi::c_int; static mut global_static_const_mixed_arithmetic: core::ffi::c_float = - (LITERAL_INT as core::ffi::c_double + NESTED_FLOAT * LITERAL_CHAR as core::ffi::c_double + (LITERAL_INT as core::ffi::c_double + + NESTED_FLOAT as core::ffi::c_double * LITERAL_CHAR as core::ffi::c_double - true_0 as core::ffi::c_double) as core::ffi::c_float; static mut global_static_const_parens: core::ffi::c_int = PARENS; static mut global_static_const_ptr_arithmetic: *const core::ffi::c_char = @@ -257,7 +260,7 @@ pub static mut global_const_literal_int: core::ffi::c_int = LITERAL_INT; #[no_mangle] pub static mut global_const_literal_bool: bool = LITERAL_BOOL != 0; #[no_mangle] -pub static mut global_const_literal_float: core::ffi::c_float = LITERAL_FLOAT as core::ffi::c_float; +pub static mut global_const_literal_float: core::ffi::c_float = LITERAL_FLOAT; #[no_mangle] pub static mut global_const_literal_char: core::ffi::c_char = LITERAL_CHAR as core::ffi::c_char; #[no_mangle] @@ -277,7 +280,7 @@ pub static mut global_const_nested_int: core::ffi::c_int = NESTED_INT; #[no_mangle] pub static mut global_const_nested_bool: bool = NESTED_BOOL != 0; #[no_mangle] -pub static mut global_const_nested_float: core::ffi::c_float = NESTED_FLOAT as core::ffi::c_float; +pub static mut global_const_nested_float: core::ffi::c_float = NESTED_FLOAT; #[no_mangle] pub static mut global_const_nested_char: core::ffi::c_char = NESTED_CHAR as core::ffi::c_char; #[no_mangle] @@ -297,7 +300,8 @@ pub static mut global_const_int_arithmetic: core::ffi::c_int = NESTED_INT + LITERAL_INT + 1 as core::ffi::c_int; #[no_mangle] pub static mut global_const_mixed_arithmetic: core::ffi::c_float = - (LITERAL_INT as core::ffi::c_double + NESTED_FLOAT * LITERAL_CHAR as core::ffi::c_double + (LITERAL_INT as core::ffi::c_double + + NESTED_FLOAT as core::ffi::c_double * LITERAL_CHAR as core::ffi::c_double - true_0 as core::ffi::c_double) as core::ffi::c_float; #[no_mangle] pub static mut global_const_parens: core::ffi::c_int = PARENS; @@ -413,7 +417,7 @@ pub unsafe extern "C" fn use_local_value() -> core::ffi::c_int { } #[no_mangle] pub unsafe extern "C" fn use_portable_type(mut len: uintptr_t) -> bool { - return len <= (UINTPTR_MAX as uintptr_t).wrapping_div(2 as uintptr_t); + return len <= UINTPTR_MAX.wrapping_div(2 as uintptr_t); } #[no_mangle] pub unsafe extern "C" fn ntlm_v2_blob_len(mut ntlm: *mut ntlmdata) -> core::ffi::c_uint { @@ -431,10 +435,11 @@ pub unsafe extern "C" fn late_init_var() -> core::ffi::c_int { } unsafe extern "C" fn run_static_initializers() { global_static_const_ptr_arithmetic = PTR_ARITHMETIC; - global_static_const_indexing = NESTED_STR[LITERAL_FLOAT as core::ffi::c_int as usize]; + global_static_const_indexing = + NESTED_STR[LITERAL_FLOAT as core::ffi::c_double as core::ffi::c_int as usize]; global_static_const_ref_indexing = &*NESTED_STR .as_ptr() - .offset(LITERAL_FLOAT as core::ffi::c_int as isize) + .offset(LITERAL_FLOAT as core::ffi::c_double as core::ffi::c_int as isize) as *const core::ffi::c_char; global_static_const_ternary = if LITERAL_BOOL != 0 { 1 as core::ffi::c_int @@ -443,10 +448,11 @@ unsafe extern "C" fn run_static_initializers() { }; global_static_const_member = LITERAL_STRUCT.i; global_const_ptr_arithmetic = PTR_ARITHMETIC; - global_const_indexing = NESTED_STR[LITERAL_FLOAT as core::ffi::c_int as usize]; + global_const_indexing = + NESTED_STR[LITERAL_FLOAT as core::ffi::c_double as core::ffi::c_int as usize]; global_const_ref_indexing = &*NESTED_STR .as_ptr() - .offset(LITERAL_FLOAT as core::ffi::c_int as isize) + .offset(LITERAL_FLOAT as core::ffi::c_double as core::ffi::c_int as isize) as *const core::ffi::c_char; global_const_ternary = if LITERAL_BOOL != 0 { 1 as core::ffi::c_int