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
15 changes: 11 additions & 4 deletions cpp2rust/converter/converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,9 @@ Converter::ConvertFunctionPointerType(const clang::FunctionProtoType *proto) {
result += ToString(p_ty);
result += ',';
}
if (proto->isVariadic()) {
result += "Box<[VaArg]>,";
}
result += ')';
if (!proto->getReturnType()->isVoidType()) {
result += std::format(" -> {}", ToString(proto->getReturnType()));
Expand Down Expand Up @@ -2234,8 +2237,9 @@ void Converter::EmitArgList(const CallInfo &info) {

if (info.is_variadic) {
if (!info.is_libc_passthrough) {
StrCat(token::kRef);
StrCat("Box::new");
}
PushParen box(*this, !info.is_libc_passthrough);
PushBracket push(*this, !info.is_libc_passthrough);
for (auto *arg : info.variadic_args) {
{
Expand Down Expand Up @@ -4069,6 +4073,9 @@ void Converter::ConvertLambdaClosure(const clang::CXXRecordDecl *decl,
ConvertVarDeclSkipInit(p);
StrCat(token::kComma);
}
if (call_operator->isVariadic()) {
StrCat("__args: Box<[VaArg]>", token::kComma);
}
in_function_formals_ = false;
StrCat('|');
ConvertFunctionReturnType(call_operator);
Expand Down Expand Up @@ -4626,7 +4633,7 @@ void Converter::ConvertFunctionParameters(clang::FunctionDecl *decl) {
StrCat(token::kComma);
}
if (decl->isVariadic()) {
StrCat("__args: &[VaArg]", token::kComma);
StrCat("__args: Box<[VaArg]>", token::kComma);
}
in_function_formals_ = false;
}
Expand Down Expand Up @@ -5321,15 +5328,15 @@ Converter::ConvertVariadicTail(clang::Expr *expr,
unsigned fixed = tgt_ir ? tgt_ir->params.size() : 0;

Buffer buf(*this);
StrCat("&[");
StrCat("Box::<[VaArg]>::from([");
for (unsigned i = fixed; i < all_args.size(); ++i) {
{
PushParen p(*this);
ConvertVariadicArg(all_args[i]);
}
StrCat(".into()", token::kComma);
}
StrCat("]");
StrCat("])");
return std::move(buf).str();
}

Expand Down
2 changes: 1 addition & 1 deletion docs/src/rules/conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ fails the build; the notes below call out the ones that are not checked.
| Type rule | `t1`, `t2`, ... via `using`/`typedef` | `fn tN() -> RustType` with no arguments |
| Parameters | free-form (`o`, `it`, `key`, `dst`, `n`, ...) | must be `a0`, `a1`, ... consecutive from 0 |
| Generics | `T1`, `T2`, ... (type and non-type params) | `T1`, `T2`, ... consecutive from 1 |
| Variadic pack | `typename... Args` | trailing `va: &[VaArg]` |
| Variadic pack | `typename... Args` | trailing `va: Box<[VaArg]>` |
| Constructing pack | `Init<T, Args> &&...args` | trailing `init: RustType` |
| Locals in Rust bodies | | double-underscore prefix: `__v`, `__fd`, `__e`, ... |

Expand Down
4 changes: 2 additions & 2 deletions docs/src/rules/writing-rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ int f1(int a0, int a1, ...) { return fcntl(a0, a1, ...); }

is not expressible. A parameter pack can be forwarded (`args...`), which is
exactly what the rule body needs to do. The Rust side takes a trailing parameter
that must be typed `&[VaArg]` and named `va`:
that must be typed `Box<[VaArg]>` and named `va`:

```cpp
// rules/fcntl/src.cpp
Expand All @@ -279,7 +279,7 @@ int f1(int a0, int a1, Args... args) {

```rust
// rules/fcntl/tgt_refcount.rs
fn f1(a0: i32, a1: i32, va: &[VaArg]) -> i32 { ... }
fn f1(a0: i32, a1: i32, va: Box<[VaArg]>) -> i32 { ... }
```

Bodies read the arguments through the va-args API in `libcc2rs` (`VaArg`,
Expand Down
6 changes: 3 additions & 3 deletions docs/src/runtime/va-args.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ sum(3, 10, 20, 30);
```

```rust
pub fn sum_0(count: i32, __args: &[VaArg]) -> i32 {
pub fn sum_0(count: i32, __args: Box<[VaArg]>) -> i32 {
let ap: Value<VaList> = Rc::new(RefCell::new(VaList::default()));
(*ap.borrow_mut()) = VaList::new(__args);
let total: Value<i32> = Rc::new(RefCell::new(0));
Expand All @@ -48,7 +48,7 @@ pub fn sum_0(count: i32, __args: &[VaArg]) -> i32 {
// ...
}

sum_0(3, &[10.into(), 20.into(), 30.into()]);
sum_0(3, Box::new([10.into(), 20.into(), 30.into()]));
```

`arg::<T>()` goes through the `VaArgGet` trait, implemented for the integer and
Expand All @@ -59,5 +59,5 @@ panics, as does reading past the last argument.

Variadic libc functions such as `printf` and `fcntl` are handled by
[variadic rules](../rules/writing-rules.md#variadic-functions), whose bodies
receive the same `&[VaArg]` slice; `format_c` in the
receive the same `Box<[VaArg]>`; `format_c` in the
[format module](./io.md#formatting) consumes one to evaluate a format string.
11 changes: 11 additions & 0 deletions libcc2rs/src/fn_ptr_arg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::rc::Rc;

use crate::rc::Ptr;
use crate::reinterpret::ByteRepr;
use crate::va_args::VaArg;
use crate::void::{AnyPtr, ErasedPtr};

pub enum ArgRepr {
Expand Down Expand Up @@ -126,6 +127,16 @@ impl FnPtrArg for AnyPtr {
}
}

impl FnPtrArg for Box<[VaArg]> {
#[inline]
fn to_repr(self) -> ArgRepr {
ArgRepr::Record(Box::new(self))
}
fn from_repr(r: ArgRepr) -> Self {
record_from_repr(r)
}
}

impl<T: ?Sized + 'static> FnPtrArg for *mut T {
#[inline]
fn to_repr(self) -> ArgRepr {
Expand Down
11 changes: 8 additions & 3 deletions rule-preprocessor/src/syntactic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use cfg_expr::Expression;
use cfg_expr::expr::{Predicate, TargetPredicate};
use ra_ap_syntax::ast::{HasAttrs, HasGenericParams, HasName, HasTypeBounds};
use ra_ap_syntax::ast::{HasAttrs, HasGenericArgs, HasGenericParams, HasName, HasTypeBounds};
use ra_ap_syntax::{AstNode, SyntaxKind, ast, match_ast};
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
Expand Down Expand Up @@ -41,8 +41,13 @@ fn pointer_flags(ty: &ast::Type) -> (bool, bool) {
}

fn is_va_args_type(ty: &ast::Type) -> bool {
if let ast::Type::RefType(r) = ty
&& let Some(ast::Type::SliceType(slice)) = r.ty()
if let ast::Type::PathType(boxed) = ty
&& let Some(segment) = boxed.path().and_then(|p| p.segment())
&& segment.name_ref().is_some_and(|name| name.text() == "Box")
&& let Some(ast::GenericArg::TypeArg(arg)) = segment
.generic_arg_list()
.and_then(|args| args.generic_args().next())
&& let Some(ast::Type::SliceType(slice)) = arg.ty()
{
return matches!(slice.ty(), Some(ast::Type::PathType(path))
if path
Expand Down
4 changes: 2 additions & 2 deletions rules/fcntl/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use libcc2rs::*;

fn f1(a0: i32, a1: i32, va: &[VaArg]) -> i32 {
fn f1(a0: i32, a1: i32, va: Box<[VaArg]>) -> i32 {
let __res = match a1 {
::libc::F_GETFL => FdRegistry::with_fd(a0, |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFL)
Expand Down Expand Up @@ -34,7 +34,7 @@ fn f1(a0: i32, a1: i32, va: &[VaArg]) -> i32 {
}
}

fn f2(a0: Ptr<i8>, a1: i32, va: &[VaArg]) -> i32 {
fn f2(a0: Ptr<i8>, a1: i32, va: Box<[VaArg]>) -> i32 {
let __mode = match va.first() {
Some(__m) => nix::sys::stat::Mode::from_bits_truncate(i32::get(__m) as ::libc::mode_t),
None => nix::sys::stat::Mode::empty(),
Expand Down
2 changes: 1 addition & 1 deletion rules/ioctl/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use libcc2rs::*;

fn f1(a0: i32, a1: u64, va: &[VaArg]) -> i32 {
fn f1(a0: i32, a1: u64, va: Box<[VaArg]>) -> i32 {
panic!(
"ioctl is not supported in the refcount model (fd={}, request={}, varargs={})",
a0,
Expand Down
12 changes: 6 additions & 6 deletions rules/stdio/tgt_refcount.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@ fn f20(a0: i32, a1: Ptr<i8>) -> Ptr<CFile> {
Ptr::alloc(CFile::new(a0))
}

fn f21(a0: Ptr<i8>, a1: usize, a2: Ptr<i8>, va: &[VaArg]) -> i32 {
let __s = libcc2rs::format_c(&a2.to_rust_string(), va);
fn f21(a0: Ptr<i8>, a1: usize, a2: Ptr<i8>, va: Box<[VaArg]>) -> i32 {
let __s = libcc2rs::format_c(&a2.to_rust_string(), &va);
let __b = __s.as_bytes();
if a1 > 0 {
let __n = ::std::cmp::min(__b.len(), a1 - 1);
Expand Down Expand Up @@ -190,12 +190,12 @@ fn f24(a0: Ptr<CFile>, a1: Ptr<i8>, a2: i32, a3: usize) -> i32 {
0
}

fn f28(a0: Ptr<CFile>, a1: Ptr<i8>, va: &[VaArg]) -> i32 {
let __s = libcc2rs::format_c(&a1.to_rust_string(), va);
fn f28(a0: Ptr<CFile>, a1: Ptr<i8>, va: Box<[VaArg]>) -> i32 {
let __s = libcc2rs::format_c(&a1.to_rust_string(), &va);
a0.with_mut(|__f| __f.write(__s.as_bytes())) as i32
}

fn f29(a0: Ptr<i8>, va: &[VaArg]) -> i32 {
let __s = libcc2rs::format_c(&a0.to_rust_string(), va);
fn f29(a0: Ptr<i8>, va: Box<[VaArg]>) -> i32 {
let __s = libcc2rs::format_c(&a0.to_rust_string(), &va);
libcc2rs::c_stdout().with_mut(|__f| __f.write(__s.as_bytes())) as i32
}
2 changes: 1 addition & 1 deletion tests/ub/out/refcount/fd_double_close.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub fn main() {
}
fn main_0() -> i32 {
let mut fd: i32 = {
let __mode = match &[].first() {
let __mode = match Box::<[VaArg]>::from([]).first() {
Some(__m) => nix::sys::stat::Mode::from_bits_truncate(i32::get(__m) as ::libc::mode_t),
None => nix::sys::stat::Mode::empty(),
};
Expand Down
2 changes: 1 addition & 1 deletion tests/ub/out/refcount/fd_use_after_close.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ pub fn main() {
}
fn main_0() -> i32 {
let mut fd: i32 = {
let __mode = match &[].first() {
let __mode = match Box::<[VaArg]>::from([]).first() {
Some(__m) => nix::sys::stat::Mode::from_bits_truncate(i32::get(__m) as ::libc::mode_t),
None => nix::sys::stat::Mode::empty(),
};
Expand Down
44 changes: 32 additions & 12 deletions tests/unit/out/refcount/fcntl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ fn main_0() -> i32 {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFL)
}),
::libc::F_SETFL => {
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(&&[(0).into()][0]));
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(
&Box::<[VaArg]>::from([(0).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFL(__flags))
})
Expand All @@ -43,7 +45,9 @@ fn main_0() -> i32 {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFD)
}),
::libc::F_SETFD => {
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(&&[(0).into()][0]));
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(
&Box::<[VaArg]>::from([(0).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFD(__flags))
})
Expand All @@ -68,7 +72,7 @@ fn main_0() -> i32 {
}),
::libc::F_SETFL => {
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(
&&[(flags | ::libc::O_NONBLOCK).into()][0],
&Box::<[VaArg]>::from([(flags | ::libc::O_NONBLOCK).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFL(__flags))
Expand All @@ -79,7 +83,7 @@ fn main_0() -> i32 {
}),
::libc::F_SETFD => {
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(
&&[(flags | ::libc::O_NONBLOCK).into()][0],
&Box::<[VaArg]>::from([(flags | ::libc::O_NONBLOCK).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFD(__flags))
Expand All @@ -103,7 +107,9 @@ fn main_0() -> i32 {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFL)
}),
::libc::F_SETFL => {
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(&&[(0).into()][0]));
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(
&Box::<[VaArg]>::from([(0).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFL(__flags))
})
Expand All @@ -112,7 +118,9 @@ fn main_0() -> i32 {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFD)
}),
::libc::F_SETFD => {
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(&&[(0).into()][0]));
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(
&Box::<[VaArg]>::from([(0).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFD(__flags))
})
Expand Down Expand Up @@ -151,7 +159,9 @@ fn main_0() -> i32 {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFL)
}),
::libc::F_SETFL => {
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(&&[(0).into()][0]));
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(
&Box::<[VaArg]>::from([(0).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFL(__flags))
})
Expand All @@ -160,7 +170,9 @@ fn main_0() -> i32 {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFD)
}),
::libc::F_SETFD => {
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(&&[(0).into()][0]));
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(
&Box::<[VaArg]>::from([(0).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFD(__flags))
})
Expand All @@ -185,7 +197,9 @@ fn main_0() -> i32 {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFL)
}),
::libc::F_SETFL => {
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(&&[(1).into()][0]));
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(
&Box::<[VaArg]>::from([(1).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFL(__flags))
})
Expand All @@ -194,7 +208,9 @@ fn main_0() -> i32 {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFD)
}),
::libc::F_SETFD => {
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(&&[(1).into()][0]));
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(
&Box::<[VaArg]>::from([(1).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFD(__flags))
})
Expand All @@ -218,7 +234,9 @@ fn main_0() -> i32 {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFL)
}),
::libc::F_SETFL => {
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(&&[(0).into()][0]));
let __flags = nix::fcntl::OFlag::from_bits_retain(i32::get(
&Box::<[VaArg]>::from([(0).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFL(__flags))
})
Expand All @@ -227,7 +245,9 @@ fn main_0() -> i32 {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_GETFD)
}),
::libc::F_SETFD => {
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(&&[(0).into()][0]));
let __flags = nix::fcntl::FdFlag::from_bits_retain(i32::get(
&Box::<[VaArg]>::from([(0).into()])[0],
));
FdRegistry::with_fd((*fds.borrow())[(0) as usize], |__fd| {
nix::fcntl::fcntl(__fd, nix::fcntl::FcntlArg::F_SETFD(__flags))
})
Expand Down
4 changes: 2 additions & 2 deletions tests/unit/out/refcount/fd_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn main() {
fn main_0() -> i32 {
let mut path: Ptr<i8> = Ptr::<i8>::from_string_literal(b"cpp2rust_fd_io_test.tmp");
let mut fd: i32 = {
let __mode = match &[(420).into()].first() {
let __mode = match Box::<[VaArg]>::from([(420).into()]).first() {
Some(__m) => nix::sys::stat::Mode::from_bits_truncate(i32::get(__m) as ::libc::mode_t),
None => nix::sys::stat::Mode::empty(),
};
Expand Down Expand Up @@ -49,7 +49,7 @@ fn main_0() -> i32 {
);
assert!((((FdRegistry::close(fd) == 0) as i32) != 0));
fd = {
let __mode = match &[].first() {
let __mode = match Box::<[VaArg]>::from([]).first() {
Some(__m) => nix::sys::stat::Mode::from_bits_truncate(i32::get(__m) as ::libc::mode_t),
None => nix::sys::stat::Mode::empty(),
};
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/out/refcount/fstat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn main() {
fn main_0() -> i32 {
let mut path: Ptr<i8> = Ptr::<i8>::from_string_literal(b"cpp2rust_fstat_test.tmp");
let mut fd: i32 = {
let __mode = match &[(420).into()].first() {
let __mode = match Box::<[VaArg]>::from([(420).into()]).first() {
Some(__m) => nix::sys::stat::Mode::from_bits_truncate(i32::get(__m) as ::libc::mode_t),
None => nix::sys::stat::Mode::empty(),
};
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/out/refcount/isatty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ pub fn main() {
fn main_0() -> i32 {
let mut path: Ptr<i8> = Ptr::<i8>::from_string_literal(b"cpp2rust_isatty_test.tmp");
let mut fd: i32 = {
let __mode = match &[(420).into()].first() {
let __mode = match Box::<[VaArg]>::from([(420).into()]).first() {
Some(__m) => nix::sys::stat::Mode::from_bits_truncate(i32::get(__m) as ::libc::mode_t),
None => nix::sys::stat::Mode::empty(),
};
Expand Down
Loading
Loading