diff --git a/c2rust-transpile/src/convert_type.rs b/c2rust-transpile/src/convert_type.rs index ec11b14059..970e92ab42 100644 --- a/c2rust-transpile/src/convert_type.rs +++ b/c2rust-transpile/src/convert_type.rs @@ -268,44 +268,49 @@ impl TypeConverter { Ok(mk().unsafe_().extern_("C").barefn_ty(fn_ty)) } + /// Converts the qualified type of a pointer. pub fn convert_pointer( &mut self, ctxt: &TypedAstContext, qtype: CQualTypeId, ) -> TranslationResult> { - let mutbl = if qtype.qualifiers.is_const { - Mutability::Immutable + let pointee_ty = self.convert_pointee(ctxt, qtype.ctype)?; + + if let CTypeKind::Function(..) = ctxt.resolve_type(qtype.ctype).kind { + // Function pointers are translated to Option applied to the function type + // in order to support NULL function pointers natively + let param = mk().angle_bracketed_args(vec![pointee_ty]); + Ok(mk().path_ty(vec![mk().path_segment_with_args("Option", param)])) } else { - Mutability::Mutable - }; + let mutbl = if qtype.qualifiers.is_const { + Mutability::Immutable + } else { + Mutability::Mutable + }; - match ctxt.resolve_type(qtype.ctype).kind { + Ok(mk().set_mutbl(mutbl).ptr_ty(pointee_ty)) + } + } + + /// Converts the pointee type of a pointer. + pub fn convert_pointee( + &mut self, + ctxt: &TypedAstContext, + ctype: CTypeId, + ) -> TranslationResult> { + match ctxt.resolve_type(ctype).kind { // While void converts to () in function returns, it converts to c_void // in the case of pointers. - CTypeKind::Void => Ok(mk() - .set_mutbl(mutbl) - .ptr_ty(mk().abs_path_ty(vec!["core", "ffi", "c_void"]))), + CTypeKind::Void => Ok(mk().abs_path_ty(vec!["core", "ffi", "c_void"])), CTypeKind::VariableArray(mut elt, _len) => { while let CTypeKind::VariableArray(elt_, _) = ctxt.resolve_type(elt).kind { elt = elt_ } - let child_ty = self.convert(ctxt, elt)?; - Ok(mk().set_mutbl(mutbl).ptr_ty(child_ty)) - } - - // Function pointers are translated to Option applied to the function type - // in order to support NULL function pointers natively - CTypeKind::Function(..) => { - let fn_ty = self.convert(ctxt, qtype.ctype)?; - let param = mk().angle_bracketed_args(vec![fn_ty]); - Ok(mk().path_ty(vec![mk().path_segment_with_args("Option", param)])) + self.convert(ctxt, elt) } - _ => { - let child_ty = self.convert(ctxt, qtype.ctype)?; - Ok(mk().set_mutbl(mutbl).ptr_ty(child_ty)) - } + _ => self.convert(ctxt, ctype), } } diff --git a/c2rust-transpile/src/translator/mod.rs b/c2rust-transpile/src/translator/mod.rs index 1ffbb889ff..9054b08681 100644 --- a/c2rust-transpile/src/translator/mod.rs +++ b/c2rust-transpile/src/translator/mod.rs @@ -3071,6 +3071,14 @@ impl<'c> Translation<'c> { .convert(&self.ast_context, type_id) } + fn convert_pointee_type(&self, type_id: CTypeId) -> TranslationResult> { + self.import_type(type_id); + + self.type_converter + .borrow_mut() + .convert_pointee(&self.ast_context, type_id) + } + /// Construct an expression for a NULL at any type, including forward declarations, /// function pointers, and normal pointers. fn null_ptr(&self, type_id: CTypeId, is_static: bool) -> TranslationResult> { @@ -3085,13 +3093,8 @@ impl<'c> Translation<'c> { let ty = self.convert_type(type_id)?; let mut zero = mk().lit_expr(mk().int_unsuffixed_lit(0)); if is_static && !pointee.qualifiers.is_const { - let mut qtype = pointee; - qtype.qualifiers.is_const = true; - let ty_ = self - .type_converter - .borrow_mut() - .convert_pointer(&self.ast_context, qtype)?; - zero = mk().cast_expr(zero, ty_); + let ty_ = self.convert_pointee_type(pointee.ctype)?; + zero = mk().cast_expr(zero, mk().ptr_ty(ty_)); } Ok(mk().cast_expr(zero, ty)) } diff --git a/c2rust-transpile/src/translator/operators.rs b/c2rust-transpile/src/translator/operators.rs index 180baf5017..9afc31c400 100644 --- a/c2rust-transpile/src/translator/operators.rs +++ b/c2rust-transpile/src/translator/operators.rs @@ -1009,13 +1009,8 @@ impl<'c> Translation<'c> { // through & to *const to *mut addr_of_arg = mk().addr_of_expr(a); if let Mutability::Mutable = mutbl { - let mut qtype = pointee_ty; - qtype.qualifiers.is_const = true; - let ty_ = self - .type_converter - .borrow_mut() - .convert_pointer(&self.ast_context, qtype)?; - addr_of_arg = mk().cast_expr(addr_of_arg, ty_); + let ty_ = self.convert_pointee_type(pointee_ty.ctype)?; + addr_of_arg = mk().cast_expr(addr_of_arg, mk().ptr_ty(ty_)); } } else { // Normal case is allowed to use &mut if needed