@@ -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+
26072612std::string
26082613ConverterRefCount::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+
26262670void 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}
0 commit comments