@@ -580,6 +580,113 @@ static bool recordDerivesCopy(const clang::CXXRecordDecl *decl) {
580580 return true ;
581581}
582582
583+ bool Converter::VisitRecordDecl (clang::RecordDecl *decl) {
584+ decl->dumpColor ();
585+
586+ // VisitCXXRecordDecl already visited the record
587+ if (clang::isa<clang::CXXRecordDecl>(decl)) {
588+ return true ;
589+ }
590+
591+ if (!decl->isCompleteDefinition ()) {
592+ return false ;
593+ }
594+
595+ if (!record_decls_.insert (GetID (decl)).second ) {
596+ return false ;
597+ }
598+
599+ Mapper::AddRuleForUserDefinedType (decl);
600+ EmitRustStruct (decl);
601+
602+ return false ;
603+ }
604+
605+ void Converter::EmitRustStruct (clang::RecordDecl *decl) {
606+ // Enums and static variables. In rust they live outside the record
607+ for (auto *d : decl->decls ()) {
608+ if (auto *enum_decl = llvm::dyn_cast<clang::EnumDecl>(d)) {
609+ VisitEnumDecl (enum_decl);
610+ }
611+ if (auto *var_decl = clang::dyn_cast<clang::VarDecl>(d)) {
612+ VisitVarDecl (var_decl);
613+ }
614+ }
615+
616+ // Inner records. In rust they live outside the record
617+ for (auto *d : decl->decls ()) {
618+ if (auto *nested = clang::dyn_cast<clang::RecordDecl>(d)) {
619+ if (!nested->isImplicit ()) {
620+ inner_structs_[GetID (nested)] = GetRecordName (nested);
621+ if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(nested)) {
622+ VisitCXXRecordDecl (cxx);
623+ } else {
624+ VisitRecordDecl (nested);
625+ }
626+ }
627+ }
628+ }
629+
630+ // Derived traits
631+ StrCat (" #[derive(" );
632+ if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
633+ for (auto *attr : GetStructAttributes (cxx)) {
634+ StrCat (attr, " ," );
635+ }
636+ } else {
637+ StrCat (" Clone, Default" );
638+ }
639+ StrCat (" )]" );
640+
641+ // Fields
642+ auto access = clang::dyn_cast<clang::CXXRecordDecl>(decl)
643+ ? AccessSpecifierAsString (decl->getAccess ())
644+ : keyword::kPub ;
645+ StrCat (access, keyword::kStruct , GetRecordName (decl),
646+ token::kOpenCurlyBracket );
647+ for (auto *field : decl->fields ()) {
648+ VisitFieldDecl (field);
649+ }
650+ StrCat (token::kCloseCurlyBracket );
651+
652+ // C++ method decls
653+ if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
654+ auto struct_name = GetRecordName (cxx);
655+
656+ ConvertCXXMethodDecls (
657+ cxx, std::string (keyword::kImpl ) + ' ' + struct_name,
658+ [](const auto *method) {
659+ return !method->isImplicit () &&
660+ !(method->getDefinition () &&
661+ method->getDefinition ()->isDefaulted ()) &&
662+ (method->isThisDeclarationADefinition () ||
663+ clang::isa<clang::CXXConstructorDecl>(method)) &&
664+ !method->isVirtual () &&
665+ !clang::isa<clang::CXXDestructorDecl>(method);
666+ });
667+
668+ if (cxx->bases_begin () != cxx->bases_end ()) {
669+ ConvertCXXMethodDecls (
670+ cxx,
671+ std::format (" {} impl {} for {}" , keyword_unsafe_,
672+ GetUnsafeTypeAsString (cxx->bases_begin ()->getType ()),
673+ struct_name),
674+ [](const auto *method) {
675+ return !method->isImplicit () && method->isVirtual ();
676+ });
677+ }
678+ }
679+
680+ // Traits
681+ if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
682+ AddOrdTrait (cxx);
683+ AddCloneTrait (cxx);
684+ AddDropTrait (cxx);
685+ AddDefaultTrait (cxx);
686+ }
687+ AddByteReprTrait (decl);
688+ }
689+
583690bool Converter::VisitCXXRecordDecl (clang::CXXRecordDecl *decl) {
584691 if (clang::isa<clang::ClassTemplateSpecializationDecl>(decl)) {
585692 materializeTemplateSpecialization (decl);
@@ -623,74 +730,7 @@ bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
623730 }
624731 }
625732
626- auto struct_name = GetRecordName (decl);
627-
628- // First visit the nested enums
629- for (auto d : decl->decls ()) {
630- if (auto enum_decl = llvm::dyn_cast<clang::EnumDecl>(d)) {
631- VisitEnumDecl (enum_decl);
632- }
633- }
634-
635- for (auto *decl : decl->decls ()) {
636- if (auto var_decl = clang::dyn_cast<clang::VarDecl>(decl)) {
637- VisitVarDecl (var_decl);
638- }
639- }
640-
641- auto nested = GetNestedStructs (decl);
642- for (auto *record_decl : nested) {
643- auto ID = GetID (record_decl);
644- inner_structs_[ID] = GetRecordName (record_decl);
645- VisitCXXRecordDecl (record_decl);
646- }
647-
648- StrCat (token::kHash , token::kOpenBracket , " derive" , token::kOpenParen );
649- bool derives_default = RecordDerivesDefault (decl);
650-
651- for (auto *struct_attr : GetStructAttributes (decl, derives_default)) {
652- StrCat (struct_attr, token::kComma );
653- }
654- StrCat (token::kCloseParen , token::kCloseBracket );
655-
656- auto access_specifier = decl->getAccess ();
657- StrCat (AccessSpecifierAsString (access_specifier), keyword::kStruct ,
658- struct_name, token::kOpenCurlyBracket );
659- for (auto *field : decl->fields ()) {
660- VisitFieldDecl (field);
661- }
662- StrCat (token::kCloseCurlyBracket );
663-
664- ConvertCXXMethodDecls (
665- decl, std::string (keyword::kImpl ) + ' ' + struct_name,
666- [](const auto *method) {
667- return !method->isImplicit () &&
668- !(method->getDefinition () &&
669- method->getDefinition ()->isDefaulted ()) &&
670- (method->isThisDeclarationADefinition () ||
671- clang::isa<clang::CXXConstructorDecl>(method)) &&
672- !method->isVirtual () &&
673- !clang::isa<clang::CXXDestructorDecl>(method);
674- });
675-
676- AddOrdTrait (decl);
677- AddCloneTrait (decl);
678- AddDropTrait (decl);
679- if (!derives_default) {
680- AddDefaultTrait (decl);
681- }
682- AddByteReprTrait (decl);
683-
684- if (decl->bases_begin () != decl->bases_end ()) {
685- ConvertCXXMethodDecls (
686- decl,
687- std::format (" {} impl {} for {}" , keyword_unsafe_,
688- GetUnsafeTypeAsString (decl->bases_begin ()->getType ()),
689- struct_name),
690- [](const auto *method) {
691- return !method->isImplicit () && method->isVirtual ();
692- });
693- }
733+ EmitRustStruct (decl);
694734 } else {
695735 // FIXME: improve error handling
696736 assert (0 && " unsupported union" );
@@ -2797,8 +2837,7 @@ std::string Converter::GetRecordName(const clang::NamedDecl *decl) const {
27972837}
27982838
27992839std::vector<const char *>
2800- Converter::GetStructAttributes (const clang::CXXRecordDecl *decl,
2801- bool &out_impl_default) {
2840+ Converter::GetStructAttributes (const clang::CXXRecordDecl *decl) {
28022841 std::vector<const char *> struct_attrs = {};
28032842
28042843 if (recordDerivesCopy (decl)) {
@@ -3106,11 +3145,14 @@ void Converter::AddCloneTrait(const clang::CXXRecordDecl *decl) {}
31063145void Converter::AddDropTrait (const clang::CXXRecordDecl *decl) {}
31073146
31083147void Converter::AddDefaultTrait (const clang::CXXRecordDecl *decl) {
3148+ if (RecordDerivesDefault (decl)) {
3149+ return ;
3150+ }
31093151 auto struct_name = GetRecordName (decl);
31103152 StrCat (std::format (" impl Default for {}" , struct_name),
31113153 token::kOpenCurlyBracket , " fn default() -> Self" ,
31123154 token::kOpenCurlyBracket );
3113- if (auto default_ctor = GetUserDefinedDefaultConstructor (decl)) {
3155+ if (auto * default_ctor = GetUserDefinedDefaultConstructor (decl)) {
31143156 StrCat (keyword_unsafe_, token::kOpenCurlyBracket );
31153157 Convert (clang::CXXConstructExpr::Create (
31163158 ctx_, ctx_.getCanonicalTagType (decl), clang::SourceLocation (),
@@ -3133,7 +3175,7 @@ void Converter::AddDefaultTrait(const clang::CXXRecordDecl *decl) {
31333175 StrCat (token::kCloseCurlyBracket , token::kCloseCurlyBracket );
31343176}
31353177
3136- void Converter::AddByteReprTrait (const clang::CXXRecordDecl *decl) {}
3178+ void Converter::AddByteReprTrait (const clang::RecordDecl *decl) {}
31373179
31383180void Converter::ConvertUnsignedArithBinaryOperator (clang::BinaryOperator *op,
31393181 clang::Expr *expr) {
0 commit comments