Skip to content

Commit e03fac1

Browse files
committed
Traverse the typedef/adjust chain to check va_list
1 parent 2498fbc commit e03fac1

4 files changed

Lines changed: 44 additions & 23 deletions

File tree

cpp2rust/converter/converter.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ bool Converter::Convert(clang::QualType qual_type) {
6969
return false;
7070
}
7171

72+
// Catch va_list before desugaring
73+
if (IsVaListType(qual_type)) {
74+
StrCat("VaList");
75+
return false;
76+
}
77+
7278
qual_type = qual_type.getUnqualifiedType().getDesugaredType(ctx_);
7379
return TraverseType(qual_type);
7480
}
@@ -243,7 +249,7 @@ bool Converter::VisitPointerType(clang::PointerType *type) {
243249
return false;
244250
}
245251

246-
if (IsVaListType(ctx_, clang::QualType(type, 0))) {
252+
if (IsVaListType(clang::QualType(type, 0))) {
247253
StrCat("VaList");
248254
return false;
249255
}
@@ -371,7 +377,7 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) {
371377
auto qual_type = decl->getType();
372378
auto name = GetNamedDeclAsString(decl);
373379

374-
if (IsVaListType(ctx_, qual_type) && decl->isLocalVarDecl()) {
380+
if (IsVaListType(qual_type) && decl->isLocalVarDecl()) {
375381
ConvertVaListVarDecl(decl);
376382
return true;
377383
}
@@ -1641,7 +1647,7 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
16411647
return Convert(sub_expr);
16421648
}
16431649
// __va_list_tag [1] decays to __va_list_tag *. Just pass through by value
1644-
if (IsVaListType(ctx_, sub_expr->getType())) {
1650+
if (IsVaListType(sub_expr->getType())) {
16451651
Convert(sub_expr);
16461652
break;
16471653
}
@@ -2650,6 +2656,11 @@ Converter::GetFunctionPointerDefaultAsString(clang::QualType qual_type) {
26502656
}
26512657

26522658
std::string Converter::GetDefaultAsString(clang::QualType qual_type) {
2659+
if (IsVaListType(qual_type)) {
2660+
computed_expr_type_ = ComputedExprType::FreshValue;
2661+
return "VaList::default()";
2662+
}
2663+
26532664
if (qual_type->isPointerType()) {
26542665
if (qual_type->getPointeeType()->isFunctionType()) {
26552666
return GetFunctionPointerDefaultAsString(qual_type);

cpp2rust/converter/converter_lib.cpp

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -600,24 +600,24 @@ bool IsRedundantCopyInConversion(clang::ASTContext &ctx,
600600
return parent && parent->getConstructor()->isConvertingConstructor(false);
601601
}
602602

603-
// va_list is implemented as __va_list_tag[1] and decays to __va_list_tag *.
604-
// That's because va_list must have pointer semantics, but still be passed as
605-
// value by user code.
606-
bool IsVaListType(clang::ASTContext &ctx, clang::QualType type) {
607-
auto canonical = type.getCanonicalType();
608-
auto va_list = ctx.getBuiltinVaListType().getCanonicalType();
609-
610-
// Direct match: va_list itself
611-
if (canonical == va_list) {
612-
return true;
613-
}
614-
615-
// Decayed match: __va_list_tag[1] decays to __va_list_tag *
616-
if (auto *arr = clang::dyn_cast<clang::ConstantArrayType>(va_list)) {
617-
return canonical ==
618-
ctx.getPointerType(arr->getElementType()).getCanonicalType();
603+
bool IsVaListType(clang::QualType type) {
604+
for (auto t = type; !t.isNull();) {
605+
if (auto *adjusted = t->getAs<clang::AdjustedType>()) {
606+
// Possibly decayed va_list
607+
t = adjusted->getOriginalType();
608+
continue;
609+
} else if (auto *typedef_type = t->getAs<clang::TypedefType>()) {
610+
// Typedef'ed va_list
611+
if (auto decl = typedef_type->getDecl()) {
612+
if (decl->getName().contains("va_list")) {
613+
return true;
614+
}
615+
t = decl->getUnderlyingType();
616+
continue;
617+
}
618+
}
619+
break;
619620
}
620-
621621
return false;
622622
}
623623

cpp2rust/converter/converter_lib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ std::string GetClassName(clang::QualType type);
142142
bool IsRedundantCopyInConversion(clang::ASTContext &ctx,
143143
const clang::CXXConstructExpr *expr);
144144

145-
bool IsVaListType(clang::ASTContext &ctx, clang::QualType type);
145+
bool IsVaListType(clang::QualType type);
146146

147147
bool IsBuiltinVaStart(const clang::CallExpr *expr);
148148

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,12 @@ std::string ConverterRefCount::BoxValue(std::string &&str) const {
133133
}
134134

135135
bool ConverterRefCount::Convert(clang::QualType qual_type) {
136+
// Detect va_list before desugaring strips the typedef.
137+
if (IsVaListType(qual_type)) {
138+
StrCat(BoxType("VaList"));
139+
return false;
140+
}
141+
136142
if (!Mapper::Contains(qual_type))
137143
qual_type = qual_type.getUnqualifiedType().getDesugaredType(ctx_);
138144

@@ -172,7 +178,7 @@ bool ConverterRefCount::VisitPointerType(clang::PointerType *type) {
172178
return false;
173179
}
174180

175-
if (IsVaListType(ctx_, clang::QualType(type, 0))) {
181+
if (IsVaListType(clang::QualType(type, 0))) {
176182
StrCat("VaList");
177183
return false;
178184
}
@@ -933,7 +939,7 @@ bool ConverterRefCount::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
933939
}
934940

935941
if (expr->getCastKind() == clang::CastKind::CK_ArrayToPointerDecay) {
936-
if (IsVaListType(ctx_, sub_expr->getType())) {
942+
if (IsVaListType(sub_expr->getType())) {
937943
Convert(sub_expr);
938944
return false;
939945
}
@@ -1408,6 +1414,10 @@ bool ConverterRefCount::VisitCXXDefaultArgExpr(clang::CXXDefaultArgExpr *expr) {
14081414
}
14091415

14101416
std::string ConverterRefCount::GetDefaultAsString(clang::QualType qual_type) {
1417+
if (IsVaListType(qual_type)) {
1418+
return BoxValue("VaList::default()");
1419+
}
1420+
14111421
std::string ret;
14121422
if (qual_type->isPointerType()) {
14131423
auto pointee_type = qual_type->getPointeeType();

0 commit comments

Comments
 (0)