Skip to content

Commit 6b10a29

Browse files
committed
work
1 parent 3f30d90 commit 6b10a29

5 files changed

Lines changed: 90 additions & 8 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,14 +1206,29 @@ void Converter::EmitFunctionPreamble(clang::FunctionDecl *decl) {
12061206
auto params = decl->getDefinition() ? decl->getDefinition()->parameters()
12071207
: decl->parameters();
12081208
for (auto *param : params) {
1209-
if (HasUsableDefaultArg(param)) {
1210-
auto name = GetNamedDeclAsString(param);
1211-
auto type = ToString(param->getType());
1212-
auto init = std::format("{}.unwrap_or({})", name,
1213-
ToString(param->getDefaultArg()));
1214-
StrCat(std::format("let mut {} : {} = {}", name, type, init),
1209+
if (!HasUsableDefaultArg(param)) {
1210+
continue;
1211+
}
1212+
auto name = GetNamedDeclAsString(param);
1213+
auto type = ToString(param->getType());
1214+
std::string value;
1215+
if (auto *temp = GetDefaultArgTemporary(param)) {
1216+
auto storage = std::format("__{}_default", name);
1217+
StrCat(std::format("let mut {} : Option<{}> = None", storage,
1218+
ToString(temp->getType().getUnqualifiedType())),
12151219
token::kSemiColon);
1220+
value = std::format("{}.insert({}) as {}", storage,
1221+
ToString(temp->getSubExpr()), type);
1222+
} else if (param->getType()->isReferenceType()) {
1223+
Buffer buf(*this);
1224+
ConvertVarInit(param->getType(), param->getDefaultArg());
1225+
value = std::move(buf).str();
1226+
} else {
1227+
value = ToString(param->getDefaultArg());
12161228
}
1229+
StrCat(std::format("let mut {} : {} = {}.unwrap_or_else(|| {} {{ {} }})",
1230+
name, type, name, keyword_unsafe_, value),
1231+
token::kSemiColon);
12171232
}
12181233
}
12191234

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -636,7 +636,8 @@ unsigned GetCtorIndex(clang::CXXConstructorDecl *ctor) {
636636
clang::CXXConstructorDecl *
637637
GetUserDefinedDefaultConstructor(const clang::CXXRecordDecl *decl) {
638638
for (auto c : decl->ctors()) {
639-
if (c->isUserProvided() && c->isDefaultConstructor() && c->hasBody()) {
639+
if (c->isUserProvided() && c->isDefaultConstructor() && c->hasBody() &&
640+
std::ranges::all_of(c->parameters(), HasUsableDefaultArg)) {
640641
return c;
641642
}
642643
}
@@ -647,6 +648,15 @@ bool HasUsableDefaultArg(const clang::ParmVarDecl *param) {
647648
return param->hasDefaultArg() && !param->hasUninstantiatedDefaultArg();
648649
}
649650

651+
const clang::MaterializeTemporaryExpr *
652+
GetDefaultArgTemporary(const clang::ParmVarDecl *param) {
653+
if (!param->getType()->isReferenceType()) {
654+
return nullptr;
655+
}
656+
return clang::dyn_cast<clang::MaterializeTemporaryExpr>(
657+
param->getDefaultArg()->IgnoreParens());
658+
}
659+
650660
std::string GetMainFileName(const clang::ASTContext &ctx) {
651661
const auto &src_mgr = ctx.getSourceManager();
652662
auto file_id = src_mgr.getMainFileID();

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ GetUserDefinedDefaultConstructor(const clang::CXXRecordDecl *decl);
154154

155155
bool HasUsableDefaultArg(const clang::ParmVarDecl *param);
156156

157+
const clang::MaterializeTemporaryExpr *
158+
GetDefaultArgTemporary(const clang::ParmVarDecl *param);
159+
157160
std::string GetMainFileName(const clang::ASTContext &ctx);
158161

159162
std::string GetFileName(const clang::Decl *decl);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -778,6 +778,30 @@ void ConverterRefCount::EmitFunctionPreamble(clang::FunctionDecl *decl) {
778778
auto params = decl->getDefinition() ? decl->getDefinition()->parameters()
779779
: decl->parameters();
780780
for (auto *param : params) {
781+
if (param->getType()->isReferenceType()) {
782+
auto name = GetNamedDeclAsString(param);
783+
if (name == "_" || !HasUsableDefaultArg(param)) {
784+
continue;
785+
}
786+
auto type = ToString(param->getType());
787+
std::string value;
788+
if (auto *temp = GetDefaultArgTemporary(param)) {
789+
auto storage = std::format("__{}_default", name);
790+
StrCat(std::format("let mut {} : Option<{}> = None", storage,
791+
ToString(temp->getType().getUnqualifiedType())),
792+
token::kSemiColon);
793+
value = std::format("{}.insert(Rc::new(RefCell::new({}))).as_pointer()",
794+
storage, ToString(temp->getSubExpr()));
795+
} else {
796+
Buffer buf(*this);
797+
ConvertVarInit(param->getType(), param->getDefaultArg());
798+
value = std::move(buf).str();
799+
}
800+
StrCat(std::format("let {} : {} = {}.unwrap_or_else(|| {})", name, type,
801+
name, value),
802+
token::kSemiColon);
803+
continue;
804+
}
781805
if (!param->getType()->isReferenceType()) {
782806
auto name = GetNamedDeclAsString(param);
783807
// Skip emitting the preamble for unnamed parameters
@@ -788,7 +812,7 @@ void ConverterRefCount::EmitFunctionPreamble(clang::FunctionDecl *decl) {
788812
auto init = name;
789813

790814
if (HasUsableDefaultArg(param)) {
791-
init = std::format("{}.unwrap_or({})", name,
815+
init = std::format("{}.unwrap_or_else(|| {})", name,
792816
ToString(param->getDefaultArg()));
793817
}
794818

‎tests/unit/default_function_arguments.cpp‎

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@ struct Bar {
99
Bar(int v = 1) : v(v) {}
1010
};
1111

12+
int counter = 0;
13+
14+
int next() { return ++counter; }
15+
16+
int lazy(int x = next()) { return x; }
17+
18+
int by_ref(const Bar &b = Bar(7)) { return b.v; }
19+
20+
Bar global_bar(9);
21+
22+
int by_global_ref(const Bar &b = global_bar) { return b.v; }
23+
24+
template <typename T> struct Holder {
25+
T v;
26+
explicit Holder(T v = 0) : v(v) {}
27+
};
28+
1229
int main() {
1330
assert(foo(1) == 11);
1431
assert(foo(1, 2) == 3);
@@ -25,5 +42,18 @@ int main() {
2542
assert(arr[0].v == 1);
2643
assert(arr[2].v == 1);
2744

45+
assert(lazy(5) == 5);
46+
assert(counter == 0);
47+
assert(lazy() == 1);
48+
assert(counter == 1);
49+
50+
assert(by_ref() == 7);
51+
assert(by_ref(Bar(3)) == 3);
52+
assert(by_global_ref() == 9);
53+
assert(by_global_ref(Bar(4)) == 4);
54+
55+
Holder<int> h(4);
56+
assert(h.v == 4);
57+
2858
return 0;
2959
}

0 commit comments

Comments
 (0)