diff --git a/c2rust-transpile/src/cfg/inc_cleanup.rs b/c2rust-transpile/src/cfg/inc_cleanup.rs index cf4b937d5..aabf5f871 100644 --- a/c2rust-transpile/src/cfg/inc_cleanup.rs +++ b/c2rust-transpile/src/cfg/inc_cleanup.rs @@ -127,21 +127,34 @@ fn cleanup_if(stmt: Stmt) -> Stmt { if let Stmt::Expr(Expr::If(ExprIf { cond, then_branch, - else_branch: Some((_token, else_)), + else_branch: Some((token, else_)), .. })) = &stmt { match &**else_ { Expr::Block(ExprBlock { block, label: None, .. - }) if block.stmts.is_empty() => { - return Stmt::Expr(Expr::If(ExprIf { - cond: cond.clone(), - then_branch: then_branch.clone(), - else_branch: Default::default(), - attrs: Default::default(), - if_token: Default::default(), - })); + }) => { + if block.stmts.is_empty() { + return Stmt::Expr(Expr::If(ExprIf { + cond: cond.clone(), + then_branch: then_branch.clone(), + else_branch: Default::default(), + attrs: Default::default(), + if_token: Default::default(), + })); + } else if block.stmts.len() == 1 { + // flatten nested if expression to else if chain + if let Stmt::Expr(Expr::If(nested_if_expr)) = &block.stmts[0] { + return Stmt::Expr(Expr::If(ExprIf { + cond: cond.clone(), + then_branch: then_branch.clone(), + else_branch: Some((*token, Box::new(Expr::If(nested_if_expr.clone())))), + attrs: Default::default(), + if_token: Default::default(), + })); + } + } } _ => {} } diff --git a/tests/conditionals/src/else_if_chain.c b/tests/conditionals/src/else_if_chain.c new file mode 100644 index 000000000..5f4868671 --- /dev/null +++ b/tests/conditionals/src/else_if_chain.c @@ -0,0 +1,13 @@ +// should produce else if chain +int entry4(int i) +{ + if (i == 0){ + return 0; + }else if (i == 10){ + return 10; + }else if (i == 20){ + return 20; + } + + return -1; +} diff --git a/tests/conditionals/src/test_conditionals.rs b/tests/conditionals/src/test_conditionals.rs index 54fac8ac0..3a0764254 100644 --- a/tests/conditionals/src/test_conditionals.rs +++ b/tests/conditionals/src/test_conditionals.rs @@ -4,6 +4,7 @@ use crate::conditionals::{rust_entry2, rust_ternaries}; use crate::unused_conditionals::{ rust_unused_conditional1, rust_unused_conditional2, rust_unused_conditional3, }; +use crate::else_if_chain::rust_entry4; use libc::{c_int, c_uint}; #[link(name = "test")] @@ -13,6 +14,8 @@ extern "C" { fn entry2(_: c_uint, _: *mut c_int); fn entry3(_: c_uint, _: *mut c_int); + + fn entry4(_: c_int) -> c_int; fn unused_conditional1() -> c_int; fn unused_conditional2() -> c_int; @@ -74,3 +77,12 @@ pub fn test_unused_conditional() { assert_eq!(unused_conditional3(), rust_unused_conditional3()); } } + +pub fn test_else_if_chain(){ + unsafe { + assert_eq!(entry4(0) , rust_entry4(0)); + assert_eq!(entry4(10) , rust_entry4(10)); + assert_eq!(entry4(20) , rust_entry4(20)); + assert_eq!(entry4(30) , rust_entry4(30)); + } +} \ No newline at end of file