diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 59943ad2..e5a85037 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -2058,6 +2058,9 @@ bool Converter::VisitUnaryOperator(clang::UnaryOperator *expr) { return false; } switch (opcode) { + case clang::UO_Extension: + Convert(sub_expr); + break; case clang::UO_AddrOf: { PushParen paren(*this); ConvertAddrOf(sub_expr, expr->getType()); @@ -2091,6 +2094,27 @@ bool Converter::VisitUnaryOperator(clang::UnaryOperator *expr) { return false; } +bool Converter::VisitStmtExpr(clang::StmtExpr *expr) { + auto *body = expr->getSubStmt(); + PushBrace brace(*this); + auto stmts = body->body(); + size_t n = static_cast(stmts.end() - stmts.begin()); + size_t i = 0; + for (auto *s : stmts) { + ++i; + if (i == n) { + if (auto *tail = clang::dyn_cast(s)) { + EmitStmtExprTail(tail); + continue; + } + } + Convert(s); + } + return false; +} + +void Converter::EmitStmtExprTail(clang::Expr *tail) { Convert(tail); } + bool Converter::VisitConditionalOperator(clang::ConditionalOperator *expr) { StrCat(keyword::kIf); Convert(expr->getCond()); diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 8e2fda4c..b652afd6 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -248,6 +248,10 @@ class Converter : public clang::RecursiveASTVisitor { virtual bool VisitUnaryOperator(clang::UnaryOperator *expr); + virtual bool VisitStmtExpr(clang::StmtExpr *expr); + + virtual void EmitStmtExprTail(clang::Expr *tail); + virtual bool VisitConditionalOperator(clang::ConditionalOperator *expr); virtual bool VisitDeclRefExpr(clang::DeclRefExpr *expr); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index eedb1606..f47f9aa0 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -1141,6 +1141,18 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) { } } +bool ConverterRefCount::VisitStmtExpr(clang::StmtExpr *expr) { + PushConversionKind push(*this, ConversionKind::FullRefCount); + return Converter::VisitStmtExpr(expr); +} + +void ConverterRefCount::EmitStmtExprTail(clang::Expr *tail) { + StrCat("let __result = "); + Convert(tail); + StrCat(token::kSemiColon); + StrCat("__result"); +} + bool ConverterRefCount::VisitBinaryOperator(clang::BinaryOperator *expr) { auto *lhs = expr->getLHS(); auto *rhs = expr->getRHS(); @@ -1654,12 +1666,10 @@ void ConverterRefCount::ConvertVarInit(clang::QualType qual_type, } bool is_ref = qual_type->isReferenceType(); - in_function_formals_ = true; PushConversionKind push(*this, ConversionKind::Unboxed, is_ref); StrCat(BoxValue((is_ref || qual_type->isFunctionPointerType()) ? ConvertFreshPointer(expr) : ConvertFreshRValue(expr))); - in_function_formals_ = false; } static std::unordered_set diff --git a/cpp2rust/converter/models/converter_refcount.h b/cpp2rust/converter/models/converter_refcount.h index 0ea89e68..890583e9 100644 --- a/cpp2rust/converter/models/converter_refcount.h +++ b/cpp2rust/converter/models/converter_refcount.h @@ -84,6 +84,10 @@ class ConverterRefCount final : public Converter { bool VisitBinaryOperator(clang::BinaryOperator *expr) override; + bool VisitStmtExpr(clang::StmtExpr *expr) override; + + void EmitStmtExprTail(clang::Expr *tail) override; + bool VisitInitListExpr(clang::InitListExpr *expr) override; bool VisitArraySubscriptExpr(clang::ArraySubscriptExpr *expr) override; diff --git a/tests/unit/out/refcount/stmt_expr.rs b/tests/unit/out/refcount/stmt_expr.rs new file mode 100644 index 00000000..c7a3bda5 --- /dev/null +++ b/tests/unit/out/refcount/stmt_expr.rs @@ -0,0 +1,50 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let x: Value = Rc::new(RefCell::new({ + let a: Value = Rc::new(RefCell::new(1)); + let b: Value = Rc::new(RefCell::new(2)); + let __result = ((*a.borrow()) + (*b.borrow())); + __result + })); + assert!(((*x.borrow()) == 3)); + let counter: Value = Rc::new(RefCell::new(0)); + let y: Value = Rc::new(RefCell::new({ + (*counter.borrow_mut()).postfix_inc(); + let __result = ((*counter.borrow()) * 10); + __result + })); + assert!(((*y.borrow()) == 10)); + assert!(((*counter.borrow()) == 1)); + let z: Value = Rc::new(RefCell::new({ + let v: Value = Rc::new(RefCell::new(5)); + if ((*v.borrow()) > 0) { + let __rhs = ((*v.borrow()) * 2); + (*v.borrow_mut()) = __rhs; + } + let __result = (*v.borrow()); + __result + })); + assert!(((*z.borrow()) == 10)); + assert!( + ({ + let inner: Value = Rc::new(RefCell::new({ + let a: Value = Rc::new(RefCell::new(100)); + let __result = (*a.borrow()); + __result + })); + let __result = (*inner.borrow()); + __result + } == 100) + ); + return 0; +} diff --git a/tests/unit/out/unsafe/stmt_expr.rs b/tests/unit/out/unsafe/stmt_expr.rs new file mode 100644 index 00000000..9a205d88 --- /dev/null +++ b/tests/unit/out/unsafe/stmt_expr.rs @@ -0,0 +1,46 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut x: i32 = { + let mut a: i32 = 1; + let mut b: i32 = 2; + ((a) + (b)) + }; + assert!(((x) == (3))); + let mut counter: i32 = 0; + let mut y: i32 = { + counter.postfix_inc(); + ((counter) * (10)) + }; + assert!(((y) == (10))); + assert!(((counter) == (1))); + let mut z: i32 = { + let mut v: i32 = 5; + if ((v) > (0)) { + v = ((v) * (2)); + } + v + }; + assert!(((z) == (10))); + assert!( + (({ + let mut inner: i32 = { + let mut a: i32 = 100; + a + }; + inner + }) == (100)) + ); + return 0; +} diff --git a/tests/unit/stmt_expr.cpp b/tests/unit/stmt_expr.cpp new file mode 100644 index 00000000..bae4c3d0 --- /dev/null +++ b/tests/unit/stmt_expr.cpp @@ -0,0 +1,36 @@ +#include + +int main() { + int x = __extension__({ + int a = 1; + int b = 2; + a + b; + }); + assert(x == 3); + + int counter = 0; + int y = ({ + counter++; + counter * 10; + }); + assert(y == 10); + assert(counter == 1); + + int z = ({ + int v = 5; + if (v > 0) { + v = v * 2; + } + v; + }); + assert(z == 10); + + assert(({ + int inner = ({ + int a = 100; + a; + }); + inner; + }) == 100); + return 0; +}