Skip to content
Merged
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
8 changes: 4 additions & 4 deletions c2rust-transpile/src/cfg/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1491,7 +1491,7 @@ impl CfgBuilder {

// Condition
let (stmts, val) = translator
.convert_condition(ctx.used(), true, scrutinee)?
.convert_scalar_to_bool_cast(ctx.used(), scrutinee, true)?
.discard_unsafe();
wip.extend(stmts);

Expand Down Expand Up @@ -1564,7 +1564,7 @@ impl CfgBuilder {

// Condition
let (stmts, val) = translator
.convert_condition(ctx.used(), true, condition)?
.convert_scalar_to_bool_cast(ctx.used(), condition, true)?
.discard_unsafe();
let cond_val = translator
.ast_context
Expand Down Expand Up @@ -1643,7 +1643,7 @@ impl CfgBuilder {

// Condition
let (stmts, val) = translator
.convert_condition(ctx.used(), true, condition)?
.convert_scalar_to_bool_cast(ctx.used(), condition, true)?
.discard_unsafe();
let cond_val = translator
.ast_context
Expand Down Expand Up @@ -1698,7 +1698,7 @@ impl CfgBuilder {
// Condition
if let Some(cond) = condition {
let (stmts, val) = translator
.convert_condition(ctx.used(), true, cond)?
.convert_scalar_to_bool_cast(ctx.used(), cond, true)?
.discard_unsafe();
let cond_val = translator
.ast_context
Expand Down
334 changes: 181 additions & 153 deletions c2rust-transpile/src/translator/mod.rs

Large diffs are not rendered by default.

26 changes: 5 additions & 21 deletions c2rust-transpile/src/translator/operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ impl<'c> Translation<'c> {
}

op if op.is_logical() => {
let lhs = self.convert_condition(ctx.used(), true, lhs)?;
let rhs = self.convert_condition(ctx.used(), true, rhs)?;
let lhs = self.convert_scalar_to_bool_cast(ctx.used(), lhs, true)?;
let rhs = self.convert_scalar_to_bool_cast(ctx.used(), rhs, true)?;
Ok(lhs
.map(|x| bool_to_int(mk().binary_expr(BinOp::from(op), x, rhs.to_expr())))
.and_then(|out| {
Expand Down Expand Up @@ -138,26 +138,10 @@ impl<'c> Translation<'c> {
let is_null = op == CBinOp::EqualEqual;

if self.ast_context.is_null_expr(lhs) {
let val = self.convert_expr(rhs_ctx, rhs, Some(rhs_type_id))?;
let val = val.try_map(|rhs_rs| {
self.convert_pointer_is_null(
ctx,
rhs_type_id.ctype,
rhs_rs,
is_null,
)
})?;
let val = self.convert_pointer_is_null(rhs_ctx, rhs, is_null)?;
return Ok(val.map(bool_to_int));
} else if self.ast_context.is_null_expr(rhs) {
let val = self.convert_expr(ctx, lhs, Some(lhs_type_id))?;
let val = val.try_map(|lhs_rs| {
self.convert_pointer_is_null(
ctx,
lhs_type_id.ctype,
lhs_rs,
is_null,
)
})?;
let val = self.convert_pointer_is_null(ctx, lhs, is_null)?;
return Ok(val.map(bool_to_int));
}
}
Expand Down Expand Up @@ -594,7 +578,7 @@ impl<'c> Translation<'c> {
.map(|a| mk().unary_expr(UnOp::Not(Default::default()), a))),

CUnOp::Not => {
let val = self.convert_condition(ctx, false, arg)?;
let val = self.convert_scalar_to_bool_cast(ctx, arg, false)?;
Ok(val.map(|x| mk().cast_expr(x, mk().abs_path_ty(vec!["core", "ffi", "c_int"]))))
}
CUnOp::Extension => self.convert_expr(ctx, arg, expected_type_id),
Expand Down
36 changes: 23 additions & 13 deletions c2rust-transpile/src/translator/pointers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use failure::{err_msg, format_err};
use syn::{BinOp, Expr, Type, UnOp};

use crate::c_ast::CUnOp;
use crate::translator::IdOrExpr;
use crate::{
diagnostics::{TranslationError, TranslationErrorKind, TranslationResult},
format_translation_err,
Expand Down Expand Up @@ -681,16 +682,21 @@ impl<'c> Translation<'c> {
}
}

pub fn convert_pointer_is_null(
pub(crate) fn convert_pointer_is_null(
&self,
ctx: ExprContext,
ptr_type: CTypeId,
val: Box<Expr>,
expr: impl Into<IdOrExpr>,
is_null: bool,
) -> TranslationResult<Box<Expr>> {
Ok(if self.ast_context.is_function_pointer(ptr_type) {
) -> TranslationResult<WithStmts<Box<Expr>>> {
let expr = expr.into();
let expr_type_id = expr
.type_id(&self.ast_context)
.ok_or_else(|| format_err!("Invalid expression type"))?;
let expr_rs = self.convert_expr(ctx.decay_ref(), expr, None)?;

if self.ast_context.is_function_pointer(expr_type_id.ctype) {
let method = if is_null { "is_none" } else { "is_some" };
mk().method_call_expr(val, method, vec![])
Ok(expr_rs.map(|expr_rs| mk().method_call_expr(expr_rs, method, vec![])))
} else {
// TODO: `pointer::is_null` becomes stably const in Rust 1.84.
if ctx.is_const {
Expand All @@ -699,12 +705,16 @@ impl<'c> Translation<'c> {
"cannot check nullity of pointer in `const` context",
));
}
let val = mk().method_call_expr(val, "is_null", vec![]);
if !is_null {
mk().unary_expr(UnOp::Not(Default::default()), val)
} else {
val
}
})

Ok(expr_rs.map(|mut expr_rs| {
expr_rs = mk().method_call_expr(expr_rs, "is_null", vec![]);

if !is_null {
expr_rs = mk().unary_expr(UnOp::Not(Default::default()), expr_rs);
}

expr_rs
}))
}
}
}
6 changes: 6 additions & 0 deletions c2rust-transpile/src/with_stmts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ impl WithStmts<Box<Expr>> {
}
}

impl<T> From<T> for WithStmts<T> {
Comment thread
ahomescu marked this conversation as resolved.
Resolved
fn from(val: T) -> Self {
WithStmts::new_val(val)
}
}

impl<T> FromIterator<WithStmts<T>> for WithStmts<Vec<T>> {
fn from_iter<I: IntoIterator<Item = WithStmts<T>>>(value: I) -> Self {
let mut stmts = vec![];
Expand Down
14 changes: 14 additions & 0 deletions c2rust-transpile/tests/snapshots/bool.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,17 @@ void test_bool() {
int1 *= 2.0;
double d = int1;
}

#define STR "ab"
#define WSTR L"ab"

void test_ptr(int arg) {
int not_wstr = !&L"ab";
int conditional_wstr = &L"ab" ? 1 : 2;
int and_wstr = &L"ab" && arg;
int cast_wstr = (_Bool) &L"ab";

int not_macro_str = !&STR;
int not_macro_wstr = !&WSTR;
int conditional_macro_str = &STR ? 1 : 2;
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ expression: cat tests/snapshots/bool.2021.clang15.rs
unused_assignments,
unused_mut
)]
#![feature(inline_const)]
pub const r#true: ::core::ffi::c_int = 1 as ::core::ffi::c_int;
pub const r#false: ::core::ffi::c_int = 0 as ::core::ffi::c_int;
pub const MACRO_INT0: ::core::ffi::c_int = 0 as ::core::ffi::c_int;
Expand Down Expand Up @@ -56,3 +57,51 @@ pub unsafe extern "C" fn test_bool() {
int1 = int1 as u8 as ::core::ffi::c_double * 2.0f64 != 0.;
let mut d: ::core::ffi::c_double = int1 as u8 as ::core::ffi::c_double;
}
pub const STR: [::core::ffi::c_char; 3] =
unsafe { ::core::mem::transmute::<[u8; 3], [::core::ffi::c_char; 3]>(*b"ab\0") };
pub const WSTR: [::core::ffi::c_int; 3] = unsafe {
::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0")
};
#[no_mangle]
pub unsafe extern "C" fn test_ptr(mut arg: ::core::ffi::c_int) {
let mut not_wstr: ::core::ffi::c_int = (&const {
unsafe {
::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0")
}
} as *const [::core::ffi::c_int; 3])
.is_null() as ::core::ffi::c_int;
let mut conditional_wstr: ::core::ffi::c_int = if !(&const {
unsafe {
::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0")
}
} as *const [::core::ffi::c_int; 3])
.is_null()
{
1 as ::core::ffi::c_int
} else {
2 as ::core::ffi::c_int
};
let mut and_wstr: ::core::ffi::c_int = (!(&const {
unsafe {
::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0")
}
} as *const [::core::ffi::c_int; 3])
.is_null()
&& arg != 0) as ::core::ffi::c_int;
let mut cast_wstr: ::core::ffi::c_int = !(&const {
unsafe {
::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0")
}
} as *const [::core::ffi::c_int; 3])
.is_null() as ::core::ffi::c_int;
let mut not_macro_str: ::core::ffi::c_int =
(&STR as *const [::core::ffi::c_char; 3]).is_null() as ::core::ffi::c_int;
let mut not_macro_wstr: ::core::ffi::c_int =
(&WSTR as *const [::core::ffi::c_int; 3]).is_null() as ::core::ffi::c_int;
let mut conditional_macro_str: ::core::ffi::c_int =
if !(&STR as *const [::core::ffi::c_char; 3]).is_null() {
1 as ::core::ffi::c_int
} else {
2 as ::core::ffi::c_int
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,51 @@ pub unsafe extern "C" fn test_bool() {
int1 = int1 as u8 as ::core::ffi::c_double * 2.0f64 != 0.;
let mut d: ::core::ffi::c_double = int1 as u8 as ::core::ffi::c_double;
}
pub const STR: [::core::ffi::c_char; 3] =
unsafe { ::core::mem::transmute::<[u8; 3], [::core::ffi::c_char; 3]>(*b"ab\0") };
pub const WSTR: [::core::ffi::c_int; 3] = unsafe {
::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0")
};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn test_ptr(mut arg: ::core::ffi::c_int) {
let mut not_wstr: ::core::ffi::c_int = (&const {
unsafe {
::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0")
}
} as *const [::core::ffi::c_int; 3])
.is_null() as ::core::ffi::c_int;
let mut conditional_wstr: ::core::ffi::c_int = if !(&const {
unsafe {
::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0")
}
} as *const [::core::ffi::c_int; 3])
.is_null()
{
1 as ::core::ffi::c_int
} else {
2 as ::core::ffi::c_int
};
let mut and_wstr: ::core::ffi::c_int = (!(&const {
unsafe {
::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0")
}
} as *const [::core::ffi::c_int; 3])
.is_null()
&& arg != 0) as ::core::ffi::c_int;
let mut cast_wstr: ::core::ffi::c_int = !(&const {
unsafe {
::core::mem::transmute::<[u8; 12], [::core::ffi::c_int; 3]>(*b"a\0\0\0b\0\0\0\0\0\0\0")
}
} as *const [::core::ffi::c_int; 3])
.is_null() as ::core::ffi::c_int;
let mut not_macro_str: ::core::ffi::c_int =
(&STR as *const [::core::ffi::c_char; 3]).is_null() as ::core::ffi::c_int;
let mut not_macro_wstr: ::core::ffi::c_int =
(&WSTR as *const [::core::ffi::c_int; 3]).is_null() as ::core::ffi::c_int;
let mut conditional_macro_str: ::core::ffi::c_int =
if !(&STR as *const [::core::ffi::c_char; 3]).is_null() {
1 as ::core::ffi::c_int
} else {
2 as ::core::ffi::c_int
};
}
Loading