Skip to content

Commit 937fe84

Browse files
committed
Add translation-time snprintf generation
1 parent 9cfdb15 commit 937fe84

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,12 +1048,50 @@ void ConverterRefCount::ConvertPrintf(clang::CallExpr *expr) {
10481048
StrCat(')');
10491049
}
10501050

1051+
void ConverterRefCount::ConvertSnprintf(clang::CallExpr *expr) {
1052+
std::string format;
1053+
if (auto *str = clang::dyn_cast<clang::StringLiteral>(
1054+
expr->getArg(2)->IgnoreImplicit())) {
1055+
format = GetEscapedStringLiteral(str);
1056+
} else {
1057+
llvm::errs() << "Unknown snprintf format: ";
1058+
expr->getArg(2)->dump();
1059+
llvm::errs() << '\n';
1060+
exit(1);
1061+
}
1062+
auto types = printf2fmt(format);
1063+
1064+
StrCat("({ let __s = format!(", format);
1065+
unsigned j = 0;
1066+
for (unsigned i = 3, e = expr->getNumArgs(); i < e; ++i) {
1067+
StrCat(token::kComma);
1068+
Convert(expr->getArg(i));
1069+
if (types[j]) {
1070+
StrCat(keyword::kAs, types[j]);
1071+
}
1072+
++j;
1073+
}
1074+
StrCat("); let __b = __s.as_bytes(); let __size = (");
1075+
Convert(expr->getArg(1));
1076+
StrCat(") as usize; if __size > 0 {",
1077+
"let __n = ::std::cmp::min(__b.len(), __size - 1); (");
1078+
Convert(expr->getArg(0));
1079+
StrCat(").with_slice_mut(__n + 1, |__dst| {",
1080+
"__dst[..__n].copy_from_slice(&__b[..__n]); __dst[__n] = 0; }); }",
1081+
"__b.len() as i32 })");
1082+
}
1083+
10511084
bool ConverterRefCount::VisitCallExpr(clang::CallExpr *expr) {
10521085
if (IsBuiltinVaStart(expr) || IsBuiltinVaEnd(expr) || IsBuiltinVaCopy(expr)) {
10531086
ConvertVAArgCall(expr);
10541087
return false;
10551088
}
10561089

1090+
if (Mapper::ToString(expr->getCallee()).starts_with("int snprintf")) {
1091+
ConvertSnprintf(expr);
1092+
return false;
1093+
}
1094+
10571095
if (expr->isCallToStdMove()) {
10581096
if (IsUniquePtr(expr->getArg(0)->getType())) {
10591097
StrCat(std::format("{}.take()", ConvertLValue(expr->getArg(0))));

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ class ConverterRefCount final : public Converter {
8282

8383
void ConvertPrintf(clang::CallExpr *expr) override;
8484

85+
void ConvertSnprintf(clang::CallExpr *expr);
86+
8587
void EmitFnPtrCall(clang::Expr *callee) override;
8688

8789
void

0 commit comments

Comments
 (0)