Skip to content

Commit 1f254c6

Browse files
committed
Convert late instantiated methods
1 parent 839405d commit 1f254c6

4 files changed

Lines changed: 66 additions & 38 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,15 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
855855
AddByteReprTrait(decl);
856856
}
857857

858+
void Converter::ConvertLateInstantiatedMethods(clang::CXXRecordDecl *decl) {
859+
ConvertCXXMethodDecls(
860+
decl, std::format("{} {}", keyword::kImpl, GetRecordName(decl)),
861+
[](auto *method) {
862+
return IsEmittableMethod(method) && method->hasBody() &&
863+
!decl_ids_.contains(GetMethodID(method));
864+
});
865+
}
866+
858867
void Converter::ConvertCXXRecordMethods(clang::CXXRecordDecl *decl) {
859868
ConvertCXXMethodDecls(
860869
decl, std::format("{} {}", keyword::kImpl, GetRecordName(decl)),
@@ -941,12 +950,7 @@ bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
941950
if (!record_decls_.MarkDefined(GetRecordName(decl))) {
942951
// Other translation units may instantiate members this one did not.
943952
if (clang::isa<clang::ClassTemplateSpecializationDecl>(decl)) {
944-
ConvertCXXMethodDecls(
945-
decl, std::format("{} {}", keyword::kImpl, GetRecordName(decl)),
946-
[](auto *method) {
947-
return IsEmittableMethod(method) && method->hasBody() &&
948-
!decl_ids_.contains(GetMethodID(method));
949-
});
953+
ConvertLateInstantiatedMethods(decl);
950954
}
951955
return false;
952956
}

‎cpp2rust/converter/converter.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
133133
std::string GetMethodName(const clang::CXXMethodDecl *decl);
134134
virtual std::string GetSelfMaybeWithMut(const clang::CXXMethodDecl *decl);
135135
virtual void ConvertCXXRecordMethods(clang::CXXRecordDecl *decl);
136+
virtual void ConvertLateInstantiatedMethods(clang::CXXRecordDecl *decl);
136137
virtual std::string DestroyMembers(const clang::CXXRecordDecl *decl);
137138
virtual void EmitScopedDestructor(const clang::VarDecl *decl);
138139
void EmitDeallocation(clang::CXXDeleteExpr *expr,

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 50 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -2604,6 +2604,11 @@ ConverterRefCount::TraitName(const clang::CXXRecordDecl *decl) const {
26042604
return GetRecordName(decl) + "Impl";
26052605
}
26062606

2607+
std::string
2608+
ConverterRefCount::TraitHeader(const clang::CXXRecordDecl *decl) const {
2609+
return std::format("pub trait {}", TraitName(decl));
2610+
}
2611+
26072612
std::string
26082613
ConverterRefCount::ImplHeader(const clang::CXXRecordDecl *decl) const {
26092614
return std::format("impl {} for Ptr<{}>", TraitName(decl),
@@ -2623,6 +2628,45 @@ bool ConverterRefCount::ConvertOutOfLineMethod(clang::CXXMethodDecl *decl) {
26232628
return false;
26242629
}
26252630

2631+
void ConverterRefCount::ConvertMethodOnPtr(clang::CXXMethodDecl *method) {
2632+
auto *record = method->getParent();
2633+
{
2634+
Buffer buf(*this);
2635+
{
2636+
PushCurrFunction push_fn(*this, method);
2637+
PushMethodTarget push(*this, MethodTarget::TraitDecl);
2638+
ConvertCXXMethodDecl(method);
2639+
}
2640+
deferred_impls_[TraitHeader(record)] += std::move(buf).str();
2641+
}
2642+
if (!method->isThisDeclarationADefinition()) {
2643+
return;
2644+
}
2645+
Buffer buf(*this);
2646+
{
2647+
PushMethodTarget push(*this, MethodTarget::PtrImpl);
2648+
VisitCXXMethodDecl(method);
2649+
}
2650+
deferred_impls_[ImplHeader(record)] += std::move(buf).str();
2651+
}
2652+
2653+
void ConverterRefCount::ConvertLateInstantiatedMethods(
2654+
clang::CXXRecordDecl *decl) {
2655+
Converter::ConvertCXXMethodDecls(
2656+
decl, std::format("{} {}", keyword::kImpl, GetRecordName(decl)),
2657+
[](auto *method) {
2658+
return IsEmittableMethod(method) && method->hasBody() &&
2659+
!IsMethodOnPtr(method) &&
2660+
!decl_ids_.contains(GetMethodID(method));
2661+
});
2662+
for (auto *method : decl->methods()) {
2663+
if (IsEmittableMethod(method) && method->hasBody() &&
2664+
IsMethodOnPtr(method) && !decl_ids_.contains(GetMethodID(method))) {
2665+
ConvertMethodOnPtr(method);
2666+
}
2667+
}
2668+
}
2669+
26262670
void ConverterRefCount::ConvertCXXRecordMethods(clang::CXXRecordDecl *decl) {
26272671
auto struct_name = GetRecordName(decl);
26282672

@@ -2632,42 +2676,16 @@ void ConverterRefCount::ConvertCXXRecordMethods(clang::CXXRecordDecl *decl) {
26322676
!IsMethodOnPtr(method);
26332677
});
26342678

2635-
bool synthesize_dtor =
2636-
!GetUserDefinedDestructor(decl) && HasFieldsNeedingDestruction(decl);
2637-
if (!synthesize_dtor &&
2638-
!std::ranges::any_of(decl->methods(), [](auto *method) {
2639-
return IsMethodOnPtr(method) && method->getDefinition();
2640-
})) {
2641-
return;
2642-
}
2643-
2644-
auto header = ImplHeader(decl);
2645-
StrCat(keyword::kPub, keyword::kTrait, TraitName(decl));
2646-
PushBrace trait_brace(*this);
2647-
26482679
for (auto *method : decl->methods()) {
2649-
if (!IsMethodOnPtr(method) || !method->getDefinition()) {
2650-
continue;
2651-
}
2652-
{
2653-
PushCurrFunction push_fn(*this, method);
2654-
PushMethodTarget push(*this, MethodTarget::TraitDecl);
2655-
ConvertCXXMethodDecl(method);
2656-
}
2657-
if (!method->isThisDeclarationADefinition()) {
2658-
continue;
2659-
}
2660-
Buffer buf(*this);
2661-
{
2662-
PushMethodTarget push(*this, MethodTarget::PtrImpl);
2663-
VisitCXXMethodDecl(method);
2680+
if (IsMethodOnPtr(method) && method->getDefinition()) {
2681+
ConvertMethodOnPtr(method);
26642682
}
2665-
deferred_impls_[header] += std::move(buf).str();
26662683
}
26672684

2668-
if (synthesize_dtor) {
2669-
StrCat(std::format("fn {}(&self)", kDestructorName), token::kSemiColon);
2670-
deferred_impls_[header] += std::format(
2685+
if (!GetUserDefinedDestructor(decl) && HasFieldsNeedingDestruction(decl)) {
2686+
deferred_impls_[TraitHeader(decl)] +=
2687+
std::format("fn {}(&self);\n", kDestructorName);
2688+
deferred_impls_[ImplHeader(decl)] += std::format(
26712689
"fn {}(&self) {{ {} }}\n", kDestructorName, DestroyMembers(decl));
26722690
}
26732691
}

‎cpp2rust/converter/models/converter_refcount.h‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ class ConverterRefCount final : public Converter {
6060

6161
void ConvertCXXRecordMethods(clang::CXXRecordDecl *decl) override;
6262

63+
void ConvertLateInstantiatedMethods(clang::CXXRecordDecl *decl) override;
64+
65+
void ConvertMethodOnPtr(clang::CXXMethodDecl *method);
66+
6367
bool VisitCXXThisExpr(clang::CXXThisExpr *expr) override;
6468

6569
bool ThisIsRustPtr() const override;
@@ -215,6 +219,7 @@ class ConverterRefCount final : public Converter {
215219

216220
private:
217221
std::string TraitName(const clang::CXXRecordDecl *decl) const;
222+
std::string TraitHeader(const clang::CXXRecordDecl *decl) const;
218223
std::string ImplHeader(const clang::CXXRecordDecl *decl) const;
219224
std::string DestroyMembers(const clang::CXXRecordDecl *decl) override;
220225
void EmitScopedDestructor(const clang::VarDecl *decl) override;

0 commit comments

Comments
 (0)