Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 27 additions & 22 deletions c2rust-transpile/src/convert_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Box<Type>> {
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<Box<Type>> {
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),
}
}

Expand Down
17 changes: 10 additions & 7 deletions c2rust-transpile/src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3071,6 +3071,14 @@ impl<'c> Translation<'c> {
.convert(&self.ast_context, type_id)
}

fn convert_pointee_type(&self, type_id: CTypeId) -> TranslationResult<Box<Type>> {
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<Box<Expr>> {
Expand All @@ -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))
}
Expand Down
9 changes: 2 additions & 7 deletions c2rust-transpile/src/translator/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down