From e03fac190d369dfc0cc4252995b2854c3102355c Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Apr 2026 11:18:18 +0100 Subject: [PATCH 1/4] Traverse the typedef/adjust chain to check va_list --- cpp2rust/converter/converter.cpp | 17 ++++++++-- cpp2rust/converter/converter_lib.cpp | 34 +++++++++---------- cpp2rust/converter/converter_lib.h | 2 +- .../converter/models/converter_refcount.cpp | 14 ++++++-- 4 files changed, 44 insertions(+), 23 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 5fe0269a..20950068 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -69,6 +69,12 @@ bool Converter::Convert(clang::QualType qual_type) { return false; } + // Catch va_list before desugaring + if (IsVaListType(qual_type)) { + StrCat("VaList"); + return false; + } + qual_type = qual_type.getUnqualifiedType().getDesugaredType(ctx_); return TraverseType(qual_type); } @@ -243,7 +249,7 @@ bool Converter::VisitPointerType(clang::PointerType *type) { return false; } - if (IsVaListType(ctx_, clang::QualType(type, 0))) { + if (IsVaListType(clang::QualType(type, 0))) { StrCat("VaList"); return false; } @@ -371,7 +377,7 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) { auto qual_type = decl->getType(); auto name = GetNamedDeclAsString(decl); - if (IsVaListType(ctx_, qual_type) && decl->isLocalVarDecl()) { + if (IsVaListType(qual_type) && decl->isLocalVarDecl()) { ConvertVaListVarDecl(decl); return true; } @@ -1641,7 +1647,7 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) { return Convert(sub_expr); } // __va_list_tag [1] decays to __va_list_tag *. Just pass through by value - if (IsVaListType(ctx_, sub_expr->getType())) { + if (IsVaListType(sub_expr->getType())) { Convert(sub_expr); break; } @@ -2650,6 +2656,11 @@ Converter::GetFunctionPointerDefaultAsString(clang::QualType qual_type) { } std::string Converter::GetDefaultAsString(clang::QualType qual_type) { + if (IsVaListType(qual_type)) { + computed_expr_type_ = ComputedExprType::FreshValue; + return "VaList::default()"; + } + if (qual_type->isPointerType()) { if (qual_type->getPointeeType()->isFunctionType()) { return GetFunctionPointerDefaultAsString(qual_type); diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 3f515788..7ab5e8e6 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -600,24 +600,24 @@ bool IsRedundantCopyInConversion(clang::ASTContext &ctx, return parent && parent->getConstructor()->isConvertingConstructor(false); } -// va_list is implemented as __va_list_tag[1] and decays to __va_list_tag *. -// That's because va_list must have pointer semantics, but still be passed as -// value by user code. -bool IsVaListType(clang::ASTContext &ctx, clang::QualType type) { - auto canonical = type.getCanonicalType(); - auto va_list = ctx.getBuiltinVaListType().getCanonicalType(); - - // Direct match: va_list itself - if (canonical == va_list) { - return true; - } - - // Decayed match: __va_list_tag[1] decays to __va_list_tag * - if (auto *arr = clang::dyn_cast(va_list)) { - return canonical == - ctx.getPointerType(arr->getElementType()).getCanonicalType(); +bool IsVaListType(clang::QualType type) { + for (auto t = type; !t.isNull();) { + if (auto *adjusted = t->getAs()) { + // Possibly decayed va_list + t = adjusted->getOriginalType(); + continue; + } else if (auto *typedef_type = t->getAs()) { + // Typedef'ed va_list + if (auto decl = typedef_type->getDecl()) { + if (decl->getName().contains("va_list")) { + return true; + } + t = decl->getUnderlyingType(); + continue; + } + } + break; } - return false; } diff --git a/cpp2rust/converter/converter_lib.h b/cpp2rust/converter/converter_lib.h index 3696d680..9834a0c6 100644 --- a/cpp2rust/converter/converter_lib.h +++ b/cpp2rust/converter/converter_lib.h @@ -142,7 +142,7 @@ std::string GetClassName(clang::QualType type); bool IsRedundantCopyInConversion(clang::ASTContext &ctx, const clang::CXXConstructExpr *expr); -bool IsVaListType(clang::ASTContext &ctx, clang::QualType type); +bool IsVaListType(clang::QualType type); bool IsBuiltinVaStart(const clang::CallExpr *expr); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index e9f397ca..642daf28 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -133,6 +133,12 @@ std::string ConverterRefCount::BoxValue(std::string &&str) const { } bool ConverterRefCount::Convert(clang::QualType qual_type) { + // Detect va_list before desugaring strips the typedef. + if (IsVaListType(qual_type)) { + StrCat(BoxType("VaList")); + return false; + } + if (!Mapper::Contains(qual_type)) qual_type = qual_type.getUnqualifiedType().getDesugaredType(ctx_); @@ -172,7 +178,7 @@ bool ConverterRefCount::VisitPointerType(clang::PointerType *type) { return false; } - if (IsVaListType(ctx_, clang::QualType(type, 0))) { + if (IsVaListType(clang::QualType(type, 0))) { StrCat("VaList"); return false; } @@ -933,7 +939,7 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) { } if (expr->getCastKind() == clang::CastKind::CK_ArrayToPointerDecay) { - if (IsVaListType(ctx_, sub_expr->getType())) { + if (IsVaListType(sub_expr->getType())) { Convert(sub_expr); return false; } @@ -1408,6 +1414,10 @@ bool ConverterRefCount::VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr *expr) { } std::string ConverterRefCount::GetDefaultAsString(clang::QualType qual_type) { + if (IsVaListType(qual_type)) { + return BoxValue("VaList::default()"); + } + std::string ret; if (qual_type->isPointerType()) { auto pointee_type = qual_type->getPointeeType(); From b6dffc3a110f60b85aefec9e815b9a457c4717a9 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Apr 2026 11:18:41 +0100 Subject: [PATCH 2/4] Update tests --- tests/unit/out/refcount/va_arg_chain.rs | 2 +- tests/unit/out/refcount/va_arg_concat.rs | 2 +- tests/unit/out/refcount/va_arg_conditional.rs | 2 +- tests/unit/out/refcount/va_arg_copy.rs | 4 ++-- tests/unit/out/refcount/va_arg_forward.rs | 2 +- tests/unit/out/refcount/va_arg_mixed_int_ptr.rs | 2 +- tests/unit/out/refcount/va_arg_mixed_types.rs | 2 +- tests/unit/out/refcount/va_arg_printf.rs | 2 +- tests/unit/out/refcount/va_arg_promotion.rs | 2 +- tests/unit/out/refcount/va_arg_snprintf.rs | 2 +- tests/unit/out/refcount/va_arg_struct_ctx.rs | 2 +- tests/unit/out/refcount/va_arg_two_passes.rs | 2 +- tests/unit/out/unsafe/va_arg_chain.rs | 2 +- tests/unit/out/unsafe/va_arg_concat.rs | 2 +- tests/unit/out/unsafe/va_arg_conditional.rs | 2 +- tests/unit/out/unsafe/va_arg_copy.rs | 4 ++-- tests/unit/out/unsafe/va_arg_forward.rs | 2 +- tests/unit/out/unsafe/va_arg_mixed_int_ptr.rs | 2 +- tests/unit/out/unsafe/va_arg_mixed_types.rs | 2 +- tests/unit/out/unsafe/va_arg_printf.rs | 2 +- tests/unit/out/unsafe/va_arg_promotion.rs | 2 +- tests/unit/out/unsafe/va_arg_snprintf.rs | 2 +- tests/unit/out/unsafe/va_arg_struct_ctx.rs | 2 +- tests/unit/out/unsafe/va_arg_two_passes.rs | 2 +- 24 files changed, 26 insertions(+), 26 deletions(-) diff --git a/tests/unit/out/refcount/va_arg_chain.rs b/tests/unit/out/refcount/va_arg_chain.rs index a08b1106..6c3cc40c 100644 --- a/tests/unit/out/refcount/va_arg_chain.rs +++ b/tests/unit/out/refcount/va_arg_chain.rs @@ -28,7 +28,7 @@ pub fn middle_layer_1(n: i32, ap: VaList) -> i32 { } pub fn top_level_2(n: i32, args: &[VaArg]) -> i32 { let n: Value = Rc::new(RefCell::new(n)); - let ap: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); (*ap.borrow_mut()) = VaList::new(args); let result: Value = Rc::new(RefCell::new( ({ diff --git a/tests/unit/out/refcount/va_arg_concat.rs b/tests/unit/out/refcount/va_arg_concat.rs index e59f12a2..6341aafe 100644 --- a/tests/unit/out/refcount/va_arg_concat.rs +++ b/tests/unit/out/refcount/va_arg_concat.rs @@ -9,7 +9,7 @@ use std::os::fd::AsFd; use std::rc::{Rc, Weak}; pub fn sum_ints_0(first: i32, args: &[VaArg]) -> i32 { let first: Value = Rc::new(RefCell::new(first)); - let ap: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); let total: Value = Rc::new(RefCell::new((*first.borrow()))); (*ap.borrow_mut()) = VaList::new(args); let val: Value = >::default(); diff --git a/tests/unit/out/refcount/va_arg_conditional.rs b/tests/unit/out/refcount/va_arg_conditional.rs index f2bdf8ab..dd75ca05 100644 --- a/tests/unit/out/refcount/va_arg_conditional.rs +++ b/tests/unit/out/refcount/va_arg_conditional.rs @@ -11,7 +11,7 @@ pub fn conditional_log_0(verbose: i32, fmt: Ptr, args: &[VaArg]) -> i32 { let verbose: Value = Rc::new(RefCell::new(verbose)); let fmt: Value> = Rc::new(RefCell::new(fmt)); if ((*verbose.borrow()) != 0) { - let ap: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); (*ap.borrow_mut()) = VaList::new(args); let result: Value = Rc::new(RefCell::new(((*ap.borrow_mut()).arg::()).clone())); return (*result.borrow()); diff --git a/tests/unit/out/refcount/va_arg_copy.rs b/tests/unit/out/refcount/va_arg_copy.rs index 3cc524fe..a7c67703 100644 --- a/tests/unit/out/refcount/va_arg_copy.rs +++ b/tests/unit/out/refcount/va_arg_copy.rs @@ -9,8 +9,8 @@ use std::os::fd::AsFd; use std::rc::{Rc, Weak}; pub fn sum_with_copy_0(count: i32, args: &[VaArg]) -> i32 { let count: Value = Rc::new(RefCell::new(count)); - let ap: Value = >::default(); - let aq: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); + let aq: Value = Rc::new(RefCell::new(VaList::default())); (*ap.borrow_mut()) = VaList::new(args); (*aq.borrow_mut()) = (*ap.borrow_mut()).clone(); let sum1: Value = Rc::new(RefCell::new(0)); diff --git a/tests/unit/out/refcount/va_arg_forward.rs b/tests/unit/out/refcount/va_arg_forward.rs index 257e60d2..6fb679ed 100644 --- a/tests/unit/out/refcount/va_arg_forward.rs +++ b/tests/unit/out/refcount/va_arg_forward.rs @@ -20,7 +20,7 @@ pub fn inner_0(count: i32, ap: VaList) -> i32 { } pub fn outer_1(count: i32, args: &[VaArg]) -> i32 { let count: Value = Rc::new(RefCell::new(count)); - let ap: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); (*ap.borrow_mut()) = VaList::new(args); let result: Value = Rc::new(RefCell::new( ({ diff --git a/tests/unit/out/refcount/va_arg_mixed_int_ptr.rs b/tests/unit/out/refcount/va_arg_mixed_int_ptr.rs index a8a3aaca..f136e651 100644 --- a/tests/unit/out/refcount/va_arg_mixed_int_ptr.rs +++ b/tests/unit/out/refcount/va_arg_mixed_int_ptr.rs @@ -9,7 +9,7 @@ use std::os::fd::AsFd; use std::rc::{Rc, Weak}; pub fn mixed_args_0(count: i32, args: &[VaArg]) -> i32 { let count: Value = Rc::new(RefCell::new(count)); - let ap: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); (*ap.borrow_mut()) = VaList::new(args); let total: Value = Rc::new(RefCell::new(0)); let i: Value = Rc::new(RefCell::new(0)); diff --git a/tests/unit/out/refcount/va_arg_mixed_types.rs b/tests/unit/out/refcount/va_arg_mixed_types.rs index 2dbb4bd2..e03d0632 100644 --- a/tests/unit/out/refcount/va_arg_mixed_types.rs +++ b/tests/unit/out/refcount/va_arg_mixed_types.rs @@ -9,7 +9,7 @@ use std::os::fd::AsFd; use std::rc::{Rc, Weak}; pub fn sum_mixed_0(count: i32, args: &[VaArg]) -> i32 { let count: Value = Rc::new(RefCell::new(count)); - let ap: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); (*ap.borrow_mut()) = VaList::new(args); let total: Value = Rc::new(RefCell::new(0)); let i: Value = Rc::new(RefCell::new(0)); diff --git a/tests/unit/out/refcount/va_arg_printf.rs b/tests/unit/out/refcount/va_arg_printf.rs index 10078dc7..a6da869b 100644 --- a/tests/unit/out/refcount/va_arg_printf.rs +++ b/tests/unit/out/refcount/va_arg_printf.rs @@ -17,7 +17,7 @@ pub fn logf_impl_0(fmt: Ptr, ap: VaList) -> i32 { } pub fn logf_1(fmt: Ptr, args: &[VaArg]) -> i32 { let fmt: Value> = Rc::new(RefCell::new(fmt)); - let ap: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); (*ap.borrow_mut()) = VaList::new(args); let result: Value = Rc::new(RefCell::new( ({ diff --git a/tests/unit/out/refcount/va_arg_promotion.rs b/tests/unit/out/refcount/va_arg_promotion.rs index 7b7f0620..152a9306 100644 --- a/tests/unit/out/refcount/va_arg_promotion.rs +++ b/tests/unit/out/refcount/va_arg_promotion.rs @@ -9,7 +9,7 @@ use std::os::fd::AsFd; use std::rc::{Rc, Weak}; pub fn test_promotions_0(count: i32, args: &[VaArg]) -> i32 { let count: Value = Rc::new(RefCell::new(count)); - let ap: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); (*ap.borrow_mut()) = VaList::new(args); let a: Value = Rc::new(RefCell::new(((*ap.borrow_mut()).arg::()).clone())); let b: Value = Rc::new(RefCell::new(((*ap.borrow_mut()).arg::()).clone())); diff --git a/tests/unit/out/refcount/va_arg_snprintf.rs b/tests/unit/out/refcount/va_arg_snprintf.rs index 2d5ee15f..5779fa64 100644 --- a/tests/unit/out/refcount/va_arg_snprintf.rs +++ b/tests/unit/out/refcount/va_arg_snprintf.rs @@ -11,7 +11,7 @@ pub fn extract_first_0(buf: Ptr, size: i32, fmt: Ptr, args: &[VaArg]) -> let buf: Value> = Rc::new(RefCell::new(buf)); let size: Value = Rc::new(RefCell::new(size)); let fmt: Value> = Rc::new(RefCell::new(fmt)); - let ap: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); (*ap.borrow_mut()) = VaList::new(args); let n: Value = Rc::new(RefCell::new(((*ap.borrow_mut()).arg::()).clone())); let __rhs = ((*n.borrow()) as u8); diff --git a/tests/unit/out/refcount/va_arg_struct_ctx.rs b/tests/unit/out/refcount/va_arg_struct_ctx.rs index d8218acf..1540e40f 100644 --- a/tests/unit/out/refcount/va_arg_struct_ctx.rs +++ b/tests/unit/out/refcount/va_arg_struct_ctx.rs @@ -26,7 +26,7 @@ pub fn set_error_0(ctx: Ptr, fmt: Ptr, args: &[VaArg]) { let ctx: Value> = Rc::new(RefCell::new(ctx)); let fmt: Value> = Rc::new(RefCell::new(fmt)); if ((*(*(*ctx.borrow()).upgrade().deref()).verbose.borrow()) != 0) { - let ap: Value = Rc::new(RefCell::new(::default())); + let ap: Value = Rc::new(RefCell::new(VaList::default())); (*ap.borrow_mut()) = VaList::new(args); (*(*(*ctx.borrow()).upgrade().deref()).last_error.borrow_mut()) = ((*ap.borrow_mut()).arg::()).clone(); diff --git a/tests/unit/out/refcount/va_arg_two_passes.rs b/tests/unit/out/refcount/va_arg_two_passes.rs index 4f6a25a4..7444471b 100644 --- a/tests/unit/out/refcount/va_arg_two_passes.rs +++ b/tests/unit/out/refcount/va_arg_two_passes.rs @@ -9,7 +9,7 @@ use std::os::fd::AsFd; use std::rc::{Rc, Weak}; pub fn sum_then_product_0(first: i32, args: &[VaArg]) -> i32 { let first: Value = Rc::new(RefCell::new(first)); - let ap: Value = >::default(); + let ap: Value = Rc::new(RefCell::new(VaList::default())); let sum: Value = Rc::new(RefCell::new((*first.borrow()))); let product: Value = Rc::new(RefCell::new((*first.borrow()))); (*ap.borrow_mut()) = VaList::new(args); diff --git a/tests/unit/out/unsafe/va_arg_chain.rs b/tests/unit/out/unsafe/va_arg_chain.rs index cdba8506..0fba180c 100644 --- a/tests/unit/out/unsafe/va_arg_chain.rs +++ b/tests/unit/out/unsafe/va_arg_chain.rs @@ -23,7 +23,7 @@ pub unsafe fn middle_layer_1(mut n: i32, mut ap: VaList) -> i32 { }); } pub unsafe fn top_level_2(mut n: i32, args: &[VaArg]) -> i32 { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); ap = VaList::new(args); let mut result: i32 = (unsafe { let _n: i32 = n; diff --git a/tests/unit/out/unsafe/va_arg_concat.rs b/tests/unit/out/unsafe/va_arg_concat.rs index ebd9cdb7..f5198549 100644 --- a/tests/unit/out/unsafe/va_arg_concat.rs +++ b/tests/unit/out/unsafe/va_arg_concat.rs @@ -8,7 +8,7 @@ use std::io::{Read, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn sum_ints_0(mut first: i32, args: &[VaArg]) -> i32 { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); let mut total: i32 = first; ap = VaList::new(args); let mut val: i32 = 0_i32; diff --git a/tests/unit/out/unsafe/va_arg_conditional.rs b/tests/unit/out/unsafe/va_arg_conditional.rs index f757e71f..431f249f 100644 --- a/tests/unit/out/unsafe/va_arg_conditional.rs +++ b/tests/unit/out/unsafe/va_arg_conditional.rs @@ -9,7 +9,7 @@ use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn conditional_log_0(mut verbose: i32, mut fmt: *const u8, args: &[VaArg]) -> i32 { if (verbose != 0) { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); ap = VaList::new(args); let mut result: i32 = ap.arg::(); return result; diff --git a/tests/unit/out/unsafe/va_arg_copy.rs b/tests/unit/out/unsafe/va_arg_copy.rs index ce342ee5..68e78b19 100644 --- a/tests/unit/out/unsafe/va_arg_copy.rs +++ b/tests/unit/out/unsafe/va_arg_copy.rs @@ -8,8 +8,8 @@ use std::io::{Read, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn sum_with_copy_0(mut count: i32, args: &[VaArg]) -> i32 { - let mut ap: VaList = ::default(); - let mut aq: VaList = ::default(); + let mut ap: VaList = VaList::default(); + let mut aq: VaList = VaList::default(); ap = VaList::new(args); aq = ap.clone(); let mut sum1: i32 = 0; diff --git a/tests/unit/out/unsafe/va_arg_forward.rs b/tests/unit/out/unsafe/va_arg_forward.rs index 475fef73..202563ad 100644 --- a/tests/unit/out/unsafe/va_arg_forward.rs +++ b/tests/unit/out/unsafe/va_arg_forward.rs @@ -17,7 +17,7 @@ pub unsafe fn inner_0(mut count: i32, mut ap: VaList) -> i32 { return total; } pub unsafe fn outer_1(mut count: i32, args: &[VaArg]) -> i32 { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); ap = VaList::new(args); let mut result: i32 = (unsafe { let _count: i32 = count; diff --git a/tests/unit/out/unsafe/va_arg_mixed_int_ptr.rs b/tests/unit/out/unsafe/va_arg_mixed_int_ptr.rs index 9460298e..c77d8fc6 100644 --- a/tests/unit/out/unsafe/va_arg_mixed_int_ptr.rs +++ b/tests/unit/out/unsafe/va_arg_mixed_int_ptr.rs @@ -8,7 +8,7 @@ use std::io::{Read, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn mixed_args_0(mut count: i32, args: &[VaArg]) -> i32 { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); ap = VaList::new(args); let mut total: i32 = 0; let mut i: i32 = 0; diff --git a/tests/unit/out/unsafe/va_arg_mixed_types.rs b/tests/unit/out/unsafe/va_arg_mixed_types.rs index 0a8411e5..56bcd7e0 100644 --- a/tests/unit/out/unsafe/va_arg_mixed_types.rs +++ b/tests/unit/out/unsafe/va_arg_mixed_types.rs @@ -8,7 +8,7 @@ use std::io::{Read, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn sum_mixed_0(mut count: i32, args: &[VaArg]) -> i32 { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); ap = VaList::new(args); let mut total: i32 = 0; let mut i: i32 = 0; diff --git a/tests/unit/out/unsafe/va_arg_printf.rs b/tests/unit/out/unsafe/va_arg_printf.rs index a0adbac1..b141b912 100644 --- a/tests/unit/out/unsafe/va_arg_printf.rs +++ b/tests/unit/out/unsafe/va_arg_printf.rs @@ -11,7 +11,7 @@ pub unsafe fn logf_impl_0(mut fmt: *const u8, mut ap: VaList) -> i32 { return ((ap.arg::()) + (ap.arg::())); } pub unsafe fn logf_1(mut fmt: *const u8, args: &[VaArg]) -> i32 { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); ap = VaList::new(args); let mut result: i32 = (unsafe { let _fmt: *const u8 = fmt; diff --git a/tests/unit/out/unsafe/va_arg_promotion.rs b/tests/unit/out/unsafe/va_arg_promotion.rs index 7500a36c..6683f3e9 100644 --- a/tests/unit/out/unsafe/va_arg_promotion.rs +++ b/tests/unit/out/unsafe/va_arg_promotion.rs @@ -8,7 +8,7 @@ use std::io::{Read, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn test_promotions_0(mut count: i32, args: &[VaArg]) -> i32 { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); ap = VaList::new(args); let mut a: i32 = ap.arg::(); let mut b: i32 = ap.arg::(); diff --git a/tests/unit/out/unsafe/va_arg_snprintf.rs b/tests/unit/out/unsafe/va_arg_snprintf.rs index 40d91d60..cc433306 100644 --- a/tests/unit/out/unsafe/va_arg_snprintf.rs +++ b/tests/unit/out/unsafe/va_arg_snprintf.rs @@ -13,7 +13,7 @@ pub unsafe fn extract_first_0( mut fmt: *const u8, args: &[VaArg], ) -> i32 { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); ap = VaList::new(args); let mut n: i32 = ap.arg::(); (*buf.offset((0) as isize)) = (n as u8); diff --git a/tests/unit/out/unsafe/va_arg_struct_ctx.rs b/tests/unit/out/unsafe/va_arg_struct_ctx.rs index 8ce93a92..9a28db86 100644 --- a/tests/unit/out/unsafe/va_arg_struct_ctx.rs +++ b/tests/unit/out/unsafe/va_arg_struct_ctx.rs @@ -14,7 +14,7 @@ pub struct context { } pub unsafe fn set_error_0(mut ctx: *mut context, mut fmt: *const u8, args: &[VaArg]) { if ((*ctx).verbose != 0) { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); ap = VaList::new(args); (*ctx).last_error = (ap.arg::()).clone(); } diff --git a/tests/unit/out/unsafe/va_arg_two_passes.rs b/tests/unit/out/unsafe/va_arg_two_passes.rs index 93f2df7c..2e280643 100644 --- a/tests/unit/out/unsafe/va_arg_two_passes.rs +++ b/tests/unit/out/unsafe/va_arg_two_passes.rs @@ -8,7 +8,7 @@ use std::io::{Read, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; pub unsafe fn sum_then_product_0(mut first: i32, args: &[VaArg]) -> i32 { - let mut ap: VaList = ::default(); + let mut ap: VaList = VaList::default(); let mut sum: i32 = first; let mut product: i32 = first; ap = VaList::new(args); From 3fddb9f8f09bb39518decff83a18961bf707ae46 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Apr 2026 11:22:03 +0100 Subject: [PATCH 3/4] Use uniform comments --- cpp2rust/converter/models/converter_refcount.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 642daf28..9bc5da7a 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -133,7 +133,7 @@ std::string ConverterRefCount::BoxValue(std::string &&str) const { } bool ConverterRefCount::Convert(clang::QualType qual_type) { - // Detect va_list before desugaring strips the typedef. + // Catch va_list before desugaring if (IsVaListType(qual_type)) { StrCat(BoxType("VaList")); return false; From c65b95a57537b253e88453dfd1b5411d53856008 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 20 Apr 2026 13:32:59 +0100 Subject: [PATCH 4/4] VaList check has higher priority --- cpp2rust/converter/converter.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 20950068..d5116cfe 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -63,18 +63,18 @@ bool Converter::VisitRecoveryExpr(clang::RecoveryExpr *expr) { } bool Converter::Convert(clang::QualType qual_type) { - if (Mapper::Contains(qual_type) && - Mapper::Map(qual_type) != ignore_rule_type_) { - StrCat(Mapper::Map(qual_type)); - return false; - } - // Catch va_list before desugaring if (IsVaListType(qual_type)) { StrCat("VaList"); return false; } + if (Mapper::Contains(qual_type) && + Mapper::Map(qual_type) != ignore_rule_type_) { + StrCat(Mapper::Map(qual_type)); + return false; + } + qual_type = qual_type.getUnqualifiedType().getDesugaredType(ctx_); return TraverseType(qual_type); }