Skip to content

Commit 6ac40b5

Browse files
committed
Translate va_list references and pointers in fields
1 parent 2bb3063 commit 6ac40b5

3 files changed

Lines changed: 69 additions & 14 deletions

File tree

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ bool ConverterRefCount::VisitReferenceType(clang::ReferenceType *type) {
291291
PushConversionKind push(*this, ConversionKind::Unboxed);
292292
return Convert(ctx_.getPointerType(pointee_type));
293293
}
294-
if (pointee_type->isArrayType()) {
294+
if (pointee_type->isArrayType() && !IsVaListType(pointee_type)) {
295295
// A reference to an array decays straight to a pointer to its first
296296
// element, the same way a by-value array parameter would, instead of
297297
// going through a pointer to the whole boxed array.
@@ -335,10 +335,11 @@ bool ConverterRefCount::VisitPointerType(clang::PointerType *type) {
335335
}
336336

337337
auto pointee_type = type->getPointeeType();
338-
PushConversionKind push1(*this, ConversionKind::Ptr,
339-
!pointee_type->isArrayType());
338+
bool pointee_is_array =
339+
pointee_type->isArrayType() && !IsVaListType(pointee_type);
340+
PushConversionKind push1(*this, ConversionKind::Ptr, !pointee_is_array);
340341
PushConversionKind push2(*this, ConversionKind::FullRefCount,
341-
pointee_type->isArrayType());
342+
pointee_is_array);
342343
if (pointee_type->isRecordType() &&
343344
abstract_structs_.contains(GetID(pointee_type->getAsRecordDecl()))) {
344345
StrCat("PtrDyn<dyn");
@@ -2462,13 +2463,18 @@ bool ConverterRefCount::VisitVAArgExpr(clang::VAArgExpr *expr) {
24622463
if (auto *cast = clang::dyn_cast<clang::ImplicitCastExpr>(va_list_expr)) {
24632464
va_list_expr = cast->getSubExpr();
24642465
}
2465-
StrCat(ConvertLValue(va_list_expr));
2466-
StrCat(".arg::<");
2466+
auto str = ConvertLValue(va_list_expr);
2467+
std::string arg_type;
24672468
{
24682469
PushConversionKind push(*this, ConversionKind::Unboxed);
2469-
StrCat(ToString(expr->getType()));
2470+
arg_type = ToString(expr->getType());
2471+
}
2472+
if (!pending_deref_.empty()) {
2473+
StrCat(pending_deref_.take(), ".with_mut(|__v| __v.arg::<", arg_type,
2474+
">())");
2475+
} else {
2476+
StrCat(str, ".arg::<", arg_type, ">()");
24702477
}
2471-
StrCat(">()");
24722478
SetFreshType(expr->getType());
24732479
return false;
24742480
}

‎libcc2rs/src/va_args.rs‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,20 @@ impl<T: crate::reinterpret::ByteRepr + 'static> From<crate::rc::Ptr<T>> for VaAr
5252
}
5353
}
5454

55-
#[derive(Clone, Copy, Default)]
56-
pub struct VaList<'a> {
57-
args: &'a [VaArg],
55+
#[derive(Clone, Default)]
56+
pub struct VaList {
57+
args: Rc<[VaArg]>,
5858
pos: usize,
5959
}
6060

61-
impl<'a> VaList<'a> {
62-
pub fn new(args: &'a [VaArg]) -> Self {
63-
VaList { args, pos: 0 }
61+
impl crate::reinterpret::ByteRepr for VaList {}
62+
63+
impl VaList {
64+
pub fn new(args: &[VaArg]) -> Self {
65+
VaList {
66+
args: Rc::from(args),
67+
pos: 0,
68+
}
6469
}
6570

6671
pub fn arg<T: VaArgGet>(&mut self) -> T {

‎tests/unit/va_list_field.cpp‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <cassert>
2+
#include <cstdarg>
3+
4+
static int sum(int n, ...) {
5+
struct Guard {
6+
va_list &ap;
7+
bool active;
8+
Guard(va_list &val) : ap(val), active(true) {}
9+
~Guard() {
10+
if (active) {
11+
va_end(ap);
12+
}
13+
}
14+
};
15+
va_list ap;
16+
va_start(ap, n);
17+
Guard guard(ap);
18+
int total = 0;
19+
for (int i = 0; i < n; ++i) {
20+
total += va_arg(guard.ap, int);
21+
}
22+
return total;
23+
}
24+
25+
static int sum_ptr(int n, ...) {
26+
struct Cursor {
27+
va_list *ap;
28+
};
29+
va_list ap;
30+
va_start(ap, n);
31+
Cursor cursor{&ap};
32+
int total = 0;
33+
for (int i = 0; i < n; ++i) {
34+
total += va_arg(*cursor.ap, int);
35+
}
36+
va_end(ap);
37+
return total;
38+
}
39+
40+
int main() {
41+
assert(sum(3, 1, 2, 3) == 6);
42+
assert(sum_ptr(2, 4, 5) == 9);
43+
return 0;
44+
}

0 commit comments

Comments
 (0)