diff --git a/c2rust-transpile/src/convert_type.rs b/c2rust-transpile/src/convert_type.rs index 3a176d9b56..2c04237c45 100644 --- a/c2rust-transpile/src/convert_type.rs +++ b/c2rust-transpile/src/convert_type.rs @@ -21,6 +21,7 @@ pub struct TypeConverter { suffix_names: HashMap<(CDeclId, &'static str), String>, features: HashSet<&'static str>, emit_no_std: bool, + ctypes_prefix: String, } pub const RESERVED_NAMES: [&str; 103] = [ @@ -133,7 +134,7 @@ pub const RESERVED_NAMES: [&str; 103] = [ ]; impl TypeConverter { - pub fn new(emit_no_std: bool) -> TypeConverter { + pub fn new(emit_no_std: bool, ctypes_prefix: String) -> TypeConverter { TypeConverter { translate_valist: false, renamer: Renamer::new(&RESERVED_NAMES), @@ -141,6 +142,7 @@ impl TypeConverter { suffix_names: HashMap::new(), features: HashSet::new(), emit_no_std, + ctypes_prefix, } } @@ -275,7 +277,7 @@ impl TypeConverter { CTypeKind::Void => { Ok(mk() .set_mutbl(mutbl) - .ptr_ty(mk().path_ty(vec!["libc", "c_void"]))) + .ptr_ty(mk().path_ty(vec!["core", "ffi", "c_void"]))) } CTypeKind::VariableArray(mut elt, _len) => { @@ -301,6 +303,41 @@ impl TypeConverter { } } + /// Convert a primitive C type kind into the equivalent Rust type + pub fn convert_primitive_type_kind(&self, kind: &CTypeKind) -> Option
> {
+ let primitive_type = |ty: &str| {
+ let path = self
+ .ctypes_prefix
+ .split("::")
+ .chain(std::iter::once(ty))
+ .collect:: >)),
+ CTypeKind::Bool => Some(mk().path_ty(mk().path(vec!["bool"]))),
+ CTypeKind::Short => Some(primitive_type("c_short")),
+ CTypeKind::Int => Some(primitive_type("c_int")),
+ CTypeKind::Long => Some(primitive_type("c_long")),
+ CTypeKind::LongLong => Some(primitive_type("c_longlong")),
+ CTypeKind::UShort => Some(primitive_type("c_ushort")),
+ CTypeKind::UInt => Some(primitive_type("c_uint")),
+ CTypeKind::ULong => Some(primitive_type("c_ulong")),
+ CTypeKind::ULongLong => Some(primitive_type("c_ulonglong")),
+ CTypeKind::SChar => Some(primitive_type("c_schar")),
+ CTypeKind::UChar => Some(primitive_type("c_uchar")),
+ CTypeKind::Char => Some(primitive_type("c_char")),
+ CTypeKind::Float => Some(primitive_type("c_float")),
+ CTypeKind::Double => Some(primitive_type("c_double")),
+ CTypeKind::LongDouble => Some(mk().path_ty(mk().path(vec!["f128", "f128"]))),
+ CTypeKind::Int128 => Some(mk().path_ty(mk().path(vec!["i128"]))),
+ CTypeKind::UInt128 => Some(mk().path_ty(mk().path(vec!["u128"]))),
+
+ _ => None
+ }
+ }
+
/// Convert a `C` type to a `Rust` one. For the moment, these are expected to have compatible
/// memory layouts.
pub fn convert(
@@ -315,26 +352,12 @@ impl TypeConverter {
return Ok(ty);
}
- match ctxt.index(ctype).kind {
- CTypeKind::Void => Ok(mk().tuple_ty(vec![] as Vec >)),
- CTypeKind::Bool => Ok(mk().path_ty(mk().path(vec!["bool"]))),
- CTypeKind::Short => Ok(mk().path_ty(mk().path(vec!["libc", "c_short"]))),
- CTypeKind::Int => Ok(mk().path_ty(mk().path(vec!["libc", "c_int"]))),
- CTypeKind::Long => Ok(mk().path_ty(mk().path(vec!["libc", "c_long"]))),
- CTypeKind::LongLong => Ok(mk().path_ty(mk().path(vec!["libc", "c_longlong"]))),
- CTypeKind::UShort => Ok(mk().path_ty(mk().path(vec!["libc", "c_ushort"]))),
- CTypeKind::UInt => Ok(mk().path_ty(mk().path(vec!["libc", "c_uint"]))),
- CTypeKind::ULong => Ok(mk().path_ty(mk().path(vec!["libc", "c_ulong"]))),
- CTypeKind::ULongLong => Ok(mk().path_ty(mk().path(vec!["libc", "c_ulonglong"]))),
- CTypeKind::SChar => Ok(mk().path_ty(mk().path(vec!["libc", "c_schar"]))),
- CTypeKind::UChar => Ok(mk().path_ty(mk().path(vec!["libc", "c_uchar"]))),
- CTypeKind::Char => Ok(mk().path_ty(mk().path(vec!["libc", "c_char"]))),
- CTypeKind::Double => Ok(mk().path_ty(mk().path(vec!["libc", "c_double"]))),
- CTypeKind::LongDouble => Ok(mk().path_ty(mk().path(vec!["f128", "f128"]))),
- CTypeKind::Float => Ok(mk().path_ty(mk().path(vec!["libc", "c_float"]))),
- CTypeKind::Int128 => Ok(mk().path_ty(mk().path(vec!["i128"]))),
- CTypeKind::UInt128 => Ok(mk().path_ty(mk().path(vec!["u128"]))),
+ let kind = &ctxt.index(ctype).kind;
+ if let Some(ty) = self.convert_primitive_type_kind(kind) {
+ return Ok(ty);
+ }
+ match *kind {
CTypeKind::Pointer(qtype) => self.convert_pointer(ctxt, qtype),
CTypeKind::Elaborated(ref ctype) => self.convert(ctxt, *ctype),
diff --git a/c2rust-transpile/src/lib.rs b/c2rust-transpile/src/lib.rs
index 1872b6f4be..2d85c4fa05 100644
--- a/c2rust-transpile/src/lib.rs
+++ b/c2rust-transpile/src/lib.rs
@@ -105,6 +105,7 @@ pub struct TranspilerConfig {
pub reorganize_definitions: bool,
pub enabled_warnings: HashSet >);
- mk().cast_expr(val, mk().path_ty(vec!["libc", "c_int"]))
+ mk().cast_expr(val, self.convert_primitive_type_kind(&CTypeKind::Int))
}))
},
"__builtin_ffs" | "__builtin_ffsl" | "__builtin_ffsll" => {
@@ -246,6 +246,8 @@ impl<'c> Translation<'c> {
"__builtin_constant_p" => Ok(WithStmts::new_val(mk().lit_expr(mk().int_lit(0, "")))),
"__builtin_object_size" => {
+ self.use_crate(ExternCrate::Libc);
+
// We can't convert this to Rust, but it should be safe to always return -1/0
// (depending on the value of `type`), so we emit the following:
// `(if (type & 2) == 0 { -1isize } else { 0isize }) as libc::size_t`
@@ -670,6 +672,8 @@ impl<'c> Translation<'c> {
ctx: ExprContext,
args: &[CExprId],
) -> Result , TranslationError> {
@@ -3118,7 +3130,7 @@ impl<'c> Translation<'c> {
UnTypeOp::PreferredAlignOf => self.compute_align_of_type(arg_ty.ctype, true)?,
};
- Ok(result.map(|x| mk().cast_expr(x, mk().path_ty(vec!["libc", "c_ulong"]))))
+ Ok(result.map(|x| mk().cast_expr(x, self.convert_primitive_type_kind(&CTypeKind::ULong))))
}
CExprKind::ConstantExpr(_ty, child, value) => {
@@ -4033,10 +4045,10 @@ impl<'c> Translation<'c> {
}
let target_ty = self.convert_type(ty.ctype)?;
val.and_then(|x| {
- let intptr_t = mk().path_ty(vec!["libc", "intptr_t"]);
- let intptr = mk().cast_expr(x, intptr_t.clone());
+ let usize_ty = mk().ident_ty("usize");
+ let intptr = mk().cast_expr(x, usize_ty.clone());
Ok(WithStmts::new_unsafe_val(
- transmute_expr(intptr_t, target_ty, intptr, self.tcfg.emit_no_std)
+ transmute_expr(usize_ty, target_ty, intptr, self.tcfg.emit_no_std)
))
})
}
diff --git a/c2rust-transpile/src/translator/operators.rs b/c2rust-transpile/src/translator/operators.rs
index 4c840c3502..f9ff4cd671 100644
--- a/c2rust-transpile/src/translator/operators.rs
+++ b/c2rust-transpile/src/translator/operators.rs
@@ -68,7 +68,7 @@ impl<'c> Translation<'c> {
let lhs = self.convert_condition(ctx, true, lhs)?;
let rhs = self.convert_condition(ctx, true, rhs)?;
lhs
- .map(|x| bool_to_int(mk().binary_expr(BinOpKind::from(op), x, rhs.to_expr())))
+ .map(|x| self.convert_bool_to_int(mk().binary_expr(BinOpKind::from(op), x, rhs.to_expr())))
.and_then(|out| {
if ctx.is_unused() {
Ok(WithStmts::new(
@@ -655,7 +655,7 @@ impl<'c> Translation<'c> {
mk().binary_expr(BinOpKind::Eq, lhs, rhs)
};
- Ok(bool_to_int(expr))
+ Ok(self.convert_bool_to_int(expr))
}
c_ast::BinOp::NotEqual => {
// Using is_some method for null comparison means we don't have to
@@ -677,12 +677,12 @@ impl<'c> Translation<'c> {
mk().binary_expr(BinOpKind::Ne, lhs, rhs)
};
- Ok(bool_to_int(expr))
+ Ok(self.convert_bool_to_int(expr))
}
- c_ast::BinOp::Less => Ok(bool_to_int(mk().binary_expr(BinOpKind::Lt, lhs, rhs))),
- c_ast::BinOp::Greater => Ok(bool_to_int(mk().binary_expr(BinOpKind::Gt, lhs, rhs))),
- c_ast::BinOp::GreaterEqual => Ok(bool_to_int(mk().binary_expr(BinOpKind::Ge, lhs, rhs))),
- c_ast::BinOp::LessEqual => Ok(bool_to_int(mk().binary_expr(BinOpKind::Le, lhs, rhs))),
+ c_ast::BinOp::Less => Ok(self.convert_bool_to_int(mk().binary_expr(BinOpKind::Lt, lhs, rhs))),
+ c_ast::BinOp::Greater => Ok(self.convert_bool_to_int(mk().binary_expr(BinOpKind::Gt, lhs, rhs))),
+ c_ast::BinOp::GreaterEqual => Ok(self.convert_bool_to_int(mk().binary_expr(BinOpKind::Ge, lhs, rhs))),
+ c_ast::BinOp::LessEqual => Ok(self.convert_bool_to_int(mk().binary_expr(BinOpKind::Le, lhs, rhs))),
c_ast::BinOp::BitAnd => Ok(mk().binary_expr(BinOpKind::BitAnd, lhs, rhs)),
c_ast::BinOp::BitOr => Ok(mk().binary_expr(BinOpKind::BitOr, lhs, rhs)),
@@ -1031,7 +1031,7 @@ impl<'c> Translation<'c> {
c_ast::UnOp::Not => {
let val = self.convert_condition(ctx, false, arg)?;
- Ok(val.map(|x| mk().cast_expr(x, mk().path_ty(vec!["libc", "c_int"]))))
+ Ok(val.map(|x| mk().cast_expr(x, self.convert_primitive_type_kind(&c_ast::CTypeKind::Int))))
}
c_ast::UnOp::Extension => {
let arg = self.convert_expr(ctx, arg)?;
diff --git a/c2rust-transpile/src/translator/variadic.rs b/c2rust-transpile/src/translator/variadic.rs
index 3cffd8f0a5..c788dd775a 100644
--- a/c2rust-transpile/src/translator/variadic.rs
+++ b/c2rust-transpile/src/translator/variadic.rs
@@ -147,7 +147,7 @@ impl<'c> Translation<'c> {
.map_or(false, |ty| self.ast_context.is_forward_declared_type(ty.ctype))
{
real_arg_ty = Some(arg_ty.clone());
- arg_ty = mk().mutbl().ptr_ty(mk().path_ty(vec!["libc", "c_void"]));
+ arg_ty = mk().mutbl().ptr_ty(mk().path_ty(vec!["core", "ffi", "c_void"]));
}
val.and_then(|val| {
diff --git a/c2rust/src/bin/c2rust-transpile.rs b/c2rust/src/bin/c2rust-transpile.rs
index 0bed965f6d..24bd4449e6 100644
--- a/c2rust/src/bin/c2rust-transpile.rs
+++ b/c2rust/src/bin/c2rust-transpile.rs
@@ -112,6 +112,10 @@ fn main() {
},
replace_unsupported_decls: ReplaceMode::Extern,
emit_no_std: matches.is_present("emit-no-std"),
+ ctypes_prefix: matches
+ .value_of("ctypes-prefix")
+ .map(String::from)
+ .unwrap(),
enabled_warnings,
log_level,
};
diff --git a/c2rust/src/transpile.yaml b/c2rust/src/transpile.yaml
index a716b9b0bd..89822e59c1 100644
--- a/c2rust/src/transpile.yaml
+++ b/c2rust/src/transpile.yaml
@@ -168,6 +168,17 @@ args:
long: emit-no-std
help: Emit code using core rather than std
takes_value: false
+ requires: use-libc-types
+ - ctypes-prefix:
+ long: ctypes-prefix
+ help: Prefix to use for C types
+ takes_value: true
+ default_value: std::os::raw
+ # FIXME: clap has a bug parsing this which was fixed
+ # immediately after the release of 2.33.3; when 2.33.4
+ # comes out, this will work
+ #default_value_if:
+ # - ["emit-no-std", null, "libc"]
- disable-refactoring:
long: disable-refactoring
help: Disable running refactoring tool after translation
diff --git a/tests/statics/src/test_sections.rs b/tests/statics/src/test_sections.rs
index 49908fb735..706cf2fde0 100644
--- a/tests/statics/src/test_sections.rs
+++ b/tests/statics/src/test_sections.rs
@@ -43,14 +43,14 @@ pub fn test_sectioned_used_static() {
let pos = lines
.iter()
- .position(|&x| x == "static mut rust_used_static4: libc::c_int = 1 as libc::c_int;")
+ .position(|&x| x == "static mut rust_used_static4: std::os::raw::c_int = 1 as std::os::raw::c_int;")
.expect("Did not find expected static string in source");
// The ordering of these attributes is not stable between LLVM versions
assert!((lines[pos-1] == "#[used]" && lines[pos-2] == "#[link_section = \"barz\"]") ||
(lines[pos-2] == "#[used]" && lines[pos-1] == "#[link_section = \"barz\"]"));
// This static is pub, but we want to ensure it has attributes applied
- assert!(src.contains("#[link_section = \"fb\"]\npub static mut rust_initialized_extern: libc::c_int = 1 as libc::c_int;"));
- assert!(src.contains("#[no_mangle]\n #[link_name = \"no_attrs\"]\n static mut rust_aliased_static: libc::c_int;"))
+ assert!(src.contains("#[link_section = \"fb\"]\npub static mut rust_initialized_extern: std::os::raw::c_int =\n 1 as std::os::raw::c_int;"));
+ assert!(src.contains("#[no_mangle]\n #[link_name = \"no_attrs\"]\n static mut rust_aliased_static: std::os::raw::c_int;"))
}
}