Skip to content

transpile: return is stripped from end of statement expressions #1506

@Rua

Description

@Rua

Transpiling the following:

#include <stdio.h>

void foo() {
    int var = 9001;

    ({
        var = 42;
        return;
    });

    printf("I should be unreachable!");
}

results in

#![allow(
    dead_code,
    non_camel_case_types,
    non_snake_case,
    non_upper_case_globals,
    unused_assignments,
    unused_mut
)]
#![feature(label_break_value)]
extern "C" {
    fn printf(__format: *const ::core::ffi::c_char, ...) -> ::core::ffi::c_int;
}
#[no_mangle]
pub unsafe extern "C" fn foo() {
    let mut var: ::core::ffi::c_int = 9001 as ::core::ffi::c_int;
    var = 42 as ::core::ffi::c_int;
    printf(b"I should be unreachable!\0" as *const u8 as *const ::core::ffi::c_char);
}

The Rust code is missing the return, causing the code below to be executed when it shouldn't be. I've tracked down the cause of this to the code here:

let mut stmts = match self.ast_context[result_id].kind {
CStmtKind::Expr(expr_id) => {
let ret = cfg::ImplicitReturnType::StmtExpr(ctx, expr_id, lbl.clone());
self.convert_function_body(ctx, &name, &substmt_ids[0..(n - 1)], None, ret)?
}
_ => self.convert_function_body(
ctx,
&name,
substmt_ids,
None,
cfg::ImplicitReturnType::Void,
)?,
};

convert_function_body calls convert_cfg with true passed for the cut_out_trailing_ret argument. But it should be passing false for statement expressions, only true for actual functions.

Metadata

Metadata

Assignees

No one assigned

    Labels

    mistranslationTranslating a well-behaved program changes its behavior

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions