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
49 changes: 36 additions & 13 deletions c2rust-transpile/src/translator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2990,7 +2990,7 @@ impl<'c> Translation<'c> {
}
_ => {
// Non function null ptrs provide enough information to skip
// type annotations; ie `= 0 as *const MyStruct;`
// type annotations; ie `= ::core::ptr::null::<MyStruct>();`
if initializer.is_none() {
return false;
}
Expand Down Expand Up @@ -3071,29 +3071,52 @@ 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>> {
if self.ast_context.is_function_pointer(type_id) {
return Ok(mk().path_expr(vec!["None"]));
}

let pointee = self
let pointer_qty = self
.ast_context
.get_pointee_qual_type(type_id)
.ok_or_else(|| TranslationError::generic("null_ptr requires a pointer"))?;
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 func = if pointer_qty.qualifiers.is_const
// static variable initializers aren't able to use null_mut
// TODO: Rust 1.83: Allowed, so this can be removed.
|| is_static
{
"null"
} else {
"null_mut"
};
let pointee_ty = self.convert_pointee_type(pointer_qty.ctype)?;
let type_args = mk().angle_bracketed_args(vec![pointee_ty.clone()]);
let mut val = mk().call_expr(
mk().abs_path_expr(vec![
mk().path_segment("core"),
mk().path_segment("ptr"),
mk().path_segment_with_args(func, type_args),
]),
vec![],
);

// TODO: Rust 1.83: Remove.
if is_static && !pointer_qty.qualifiers.is_const {
val = mk().cast_expr(val, mk().mutbl().ptr_ty(pointee_ty));
}
Ok(mk().cast_expr(zero, ty))

Ok(val)
}

fn addr_lhs(
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ pub unsafe extern "C" fn VM_CallCompiled(
mut args: *mut ::core::ffi::c_int,
) -> ::core::ffi::c_int {
let mut stack: [byte; 271] = [0; 271];
let mut entryPoint: *mut ::core::ffi::c_void = 0 as *mut ::core::ffi::c_void;
let mut entryPoint: *mut ::core::ffi::c_void = ::core::ptr::null_mut::<::core::ffi::c_void>();
let mut programStack: ::core::ffi::c_int = 0;
let mut stackOnEntry: ::core::ffi::c_int = 0;
let mut image: *mut byte = 0 as *mut byte;
let mut opStack: *mut ::core::ffi::c_int = 0 as *mut ::core::ffi::c_int;
let mut image: *mut byte = ::core::ptr::null_mut::<byte>();
let mut opStack: *mut ::core::ffi::c_int = ::core::ptr::null_mut::<::core::ffi::c_int>();
let mut opStackOfs: ::core::ffi::c_int = 0;
let mut arg: ::core::ffi::c_int = 0;
let mut currentVM: *mut vm_t = vm;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ pub unsafe extern "C" fn VM_CallCompiled(
mut args: *mut ::core::ffi::c_int,
) -> ::core::ffi::c_int {
let mut stack: [byte; 271] = [0; 271];
let mut entryPoint: *mut ::core::ffi::c_void = 0 as *mut ::core::ffi::c_void;
let mut entryPoint: *mut ::core::ffi::c_void = ::core::ptr::null_mut::<::core::ffi::c_void>();
let mut programStack: ::core::ffi::c_int = 0;
let mut stackOnEntry: ::core::ffi::c_int = 0;
let mut image: *mut byte = 0 as *mut byte;
let mut opStack: *mut ::core::ffi::c_int = 0 as *mut ::core::ffi::c_int;
let mut image: *mut byte = ::core::ptr::null_mut::<byte>();
let mut opStack: *mut ::core::ffi::c_int = ::core::ptr::null_mut::<::core::ffi::c_int>();
let mut opStackOfs: ::core::ffi::c_int = 0;
let mut arg: ::core::ffi::c_int = 0;
let mut currentVM: *mut vm_t = vm;
Expand Down
4 changes: 2 additions & 2 deletions c2rust-transpile/tests/snapshots/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ pub unsafe extern "C" fn alloca_sum(
mut val2: ::core::ffi::c_int,
) -> ::core::ffi::c_int {
let mut alloca_allocations: Vec<Vec<u8>> = Vec::new();
let mut alloca1: *mut ::core::ffi::c_int = 0 as *mut ::core::ffi::c_int;
let mut alloca2: *mut ::core::ffi::c_int = 0 as *mut ::core::ffi::c_int;
let mut alloca1: *mut ::core::ffi::c_int = ::core::ptr::null_mut::<::core::ffi::c_int>();
let mut alloca2: *mut ::core::ffi::c_int = ::core::ptr::null_mut::<::core::ffi::c_int>();
if TRUE != 0 {
alloca_allocations.push(::std::vec::from_elem(
0,
Expand Down
2 changes: 1 addition & 1 deletion c2rust-transpile/tests/snapshots/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub unsafe extern "C" fn entry() {
let mut int_too_short: [::core::ffi::c_int; 16] = [0 as ::core::ffi::c_int; 16];
int_too_short[15 as ::core::ffi::c_int as usize] += 9 as ::core::ffi::c_int;
let mut struct_init_too_short: [C2RustUnnamed_0; 1] = [C2RustUnnamed_0 {
x: 0 as *mut ::core::ffi::c_char,
x: ::core::ptr::null_mut::<::core::ffi::c_char>(),
y: 0,
}; 1];
struct_init_too_short[0 as ::core::ffi::c_int as usize].y += 9 as ::core::ffi::c_int;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pub struct Scope {
#[no_mangle]
pub static mut scope: *mut Scope = &{
let mut init = Scope {
next: 0 as *const Scope as *mut Scope,
next: ::core::ptr::null::<Scope>() as *mut Scope,
};
init
} as *const Scope as *mut Scope;
2 changes: 1 addition & 1 deletion c2rust-transpile/tests/snapshots/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub unsafe extern "C" fn unary_without_side_effect() {
}
#[no_mangle]
pub unsafe extern "C" fn unary_with_side_effect() {
let mut arr: [*mut ::core::ffi::c_char; 1] = [0 as *mut ::core::ffi::c_char];
let mut arr: [*mut ::core::ffi::c_char; 1] = [::core::ptr::null_mut::<::core::ffi::c_char>()];
-side_effect();
side_effect();
!side_effect();
Expand Down
10 changes: 5 additions & 5 deletions c2rust-transpile/tests/snapshots/[email protected]
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ static mut global_static_const_mixed_arithmetic: ::core::ffi::c_float =
- 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 =
0 as *const ::core::ffi::c_char;
::core::ptr::null::<::core::ffi::c_char>();
static mut global_static_const_widening_cast: ::core::ffi::c_ulonglong = WIDENING_CAST;
static mut global_static_const_narrowing_cast: ::core::ffi::c_char =
LITERAL_INT as ::core::ffi::c_char;
Expand All @@ -254,7 +254,7 @@ static mut global_static_const_str_concatenation: [::core::ffi::c_char; 18] = un
static mut global_static_const_builtin: ::core::ffi::c_int =
(LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32;
static mut global_static_const_ref_indexing: *const ::core::ffi::c_char =
0 as *const ::core::ffi::c_char;
::core::ptr::null::<::core::ffi::c_char>();
static mut global_static_const_ref_struct: *const S = &LITERAL_STRUCT as *const S as *mut S;
static mut global_static_const_ternary: ::core::ffi::c_int = 0;
static mut global_static_const_member: ::core::ffi::c_int = 0;
Expand Down Expand Up @@ -313,7 +313,7 @@ pub static mut global_const_mixed_arithmetic: ::core::ffi::c_float =
pub static mut global_const_parens: ::core::ffi::c_int = PARENS;
#[no_mangle]
pub static mut global_const_ptr_arithmetic: *const ::core::ffi::c_char =
0 as *const ::core::ffi::c_char;
::core::ptr::null::<::core::ffi::c_char>();
#[no_mangle]
pub static mut global_const_widening_cast: ::core::ffi::c_ulonglong = WIDENING_CAST;
#[no_mangle]
Expand All @@ -335,7 +335,7 @@ pub static mut global_const_builtin: ::core::ffi::c_int =
(LITERAL_INT as ::core::ffi::c_uint).leading_zeros() as i32;
#[no_mangle]
pub static mut global_const_ref_indexing: *const ::core::ffi::c_char =
0 as *const ::core::ffi::c_char;
::core::ptr::null::<::core::ffi::c_char>();
#[no_mangle]
pub static mut global_const_ref_struct: *const S = &LITERAL_STRUCT as *const S as *mut S;
#[no_mangle]
Expand Down Expand Up @@ -363,7 +363,7 @@ pub unsafe extern "C" fn reference_define() -> ::core::ffi::c_int {
#[no_mangle]
pub static mut fns: fn_ptrs = {
let mut init = fn_ptrs {
v: 0 as *const ::core::ffi::c_void as *mut ::core::ffi::c_void,
v: ::core::ptr::null::<::core::ffi::c_void>() as *mut ::core::ffi::c_void,
fn1: None,
fn2: None,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ pub unsafe extern "C" fn array_extra_braces() {
pub unsafe extern "C" fn array_of_ptrs() {
let mut _s: [*const ::core::ffi::c_char; 3] = [
b"hello\0" as *const u8 as *const ::core::ffi::c_char,
0 as *const ::core::ffi::c_char,
0 as *const ::core::ffi::c_char,
::core::ptr::null::<::core::ffi::c_char>(),
::core::ptr::null::<::core::ffi::c_char>(),
];
}
#[no_mangle]
Expand Down
Loading