@@ -30,6 +30,7 @@ std::vector<std::string> Converter::global_inits_;
3030std::unordered_set<std::string> Converter::abstract_structs_;
3131Converter::RecordIndex Converter::record_decls_;
3232std::map<std::string, Converter::MethodsOnPtr> Converter::methods_on_ptr_;
33+ std::map<std::string, Converter::DeferredBlock> Converter::vtable_impls_;
3334
3435void Converter::ConvertUniquePtrDeref (clang::CXXOperatorCallExpr *expr) {
3536 bool is_star = expr->getOperator () == clang::OverloadedOperatorKind::OO_Star;
@@ -60,16 +61,24 @@ use std::rc::Rc;
6061)" );
6162}
6263
64+ void Converter::EmitDeferredBlock (const DeferredBlock &block,
65+ std::string &out) {
66+ out += block.header ;
67+ out += " {\n " ;
68+ out += block.body ;
69+ out += " }\n " ;
70+ }
71+
72+ void Converter::EmitVTableImpls (std::string &out) {
73+ for (const auto &[name, impl] : vtable_impls_) {
74+ EmitDeferredBlock (impl, out);
75+ }
76+ }
77+
6378void Converter::EmitMethodsOnPtr (std::string &out) {
6479 for (const auto &[name, methods] : methods_on_ptr_) {
65- out += methods.trait_header ;
66- out += " {\n " ;
67- out += methods.trait_body ;
68- out += " }\n " ;
69- out += methods.impl_header ;
70- out += " {\n " ;
71- out += methods.impl_body ;
72- out += " }\n " ;
80+ EmitDeferredBlock (methods.trait , out);
81+ EmitDeferredBlock (methods.impl , out);
7382 }
7483}
7584
@@ -866,20 +875,8 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) {
866875
867876 // C++ method decls
868877 if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
869- auto struct_name = GetRecordName (cxx);
870-
871878 ConvertCXXRecordMethods (cxx);
872-
873- if (cxx->bases_begin () != cxx->bases_end ()) {
874- ConvertCXXMethodDecls (
875- cxx,
876- std::format (" {} impl {} for {}" , keyword_unsafe_,
877- GetUnsafeTypeAsString (cxx->bases_begin ()->getType ()),
878- struct_name),
879- [](auto *method) {
880- return !method->isImplicit () && method->isVirtual ();
881- });
882- }
879+ ConvertVTableMethods (cxx);
883880 }
884881
885882 // Traits
@@ -1076,7 +1073,7 @@ bool Converter::VisitCXXMethodDecl(clang::CXXMethodDecl *decl) {
10761073 PushCurrFunction push_fn (*this , decl);
10771074
10781075 if (decl->isOutOfLine () && !decl->overridden_methods ().empty ()) {
1079- return false ;
1076+ return ConvertVTableMethod (decl) ;
10801077 }
10811078 if (decl->isOutOfLine () && !decl->isTemplateInstantiation ()) {
10821079 return ConvertOutOfLineMethod (decl);
@@ -4475,6 +4472,48 @@ void Converter::ConvertCXXMethodDecls(
44754472 }
44764473}
44774474
4475+ Converter::DeferredBlock &
4476+ Converter::VTableImplFor (const clang::CXXRecordDecl *decl) {
4477+ auto name = GetRecordName (decl);
4478+ auto [it, inserted] = vtable_impls_.try_emplace (name);
4479+ if (inserted) {
4480+ it->second .header = std::format (
4481+ " {} impl {} for {}" , keyword_unsafe_,
4482+ GetUnsafeTypeAsString (decl->bases_begin ()->getType ()), name);
4483+ }
4484+ return it->second ;
4485+ }
4486+
4487+ void Converter::ConvertVTableMethods (clang::CXXRecordDecl *decl) {
4488+ if (decl->bases_begin () == decl->bases_end ()) {
4489+ return ;
4490+ }
4491+ bool any = false ;
4492+ Buffer buf (*this );
4493+ for (auto *method : decl->methods ()) {
4494+ if (!method->isImplicit () && method->isVirtual ()) {
4495+ any = true ;
4496+ VisitCXXMethodDecl (method);
4497+ }
4498+ }
4499+ auto body = std::move (buf).str ();
4500+ if (!any) {
4501+ return ;
4502+ }
4503+ VTableImplFor (decl).body += body;
4504+ }
4505+
4506+ bool Converter::ConvertVTableMethod (clang::CXXMethodDecl *decl) {
4507+ auto *record = decl->getParent ();
4508+ if (record->bases_begin () == record->bases_end ()) {
4509+ return false ;
4510+ }
4511+ Buffer buf (*this );
4512+ auto emitted = ConvertCXXMethodDecl (decl);
4513+ VTableImplFor (record).body += std::move (buf).str ();
4514+ return emitted;
4515+ }
4516+
44784517void Converter::ConvertOrdAndPartialOrdTraitsBase (
44794518 std::string_view cmp_body, std::string_view eq_body,
44804519 std::string_view record_name) {
0 commit comments