@@ -600,12 +600,12 @@ bool Converter::VisitRecordDecl(clang::RecordDecl *decl) {
600600 }
601601
602602 Mapper::AddRuleForUserDefinedType (decl);
603- EmitRustStruct (decl);
603+ EmitRustStructOrUnion (decl);
604604
605605 return false ;
606606}
607607
608- void Converter::EmitRustStruct (clang::RecordDecl *decl) {
608+ void Converter::EmitRustStructOrUnion (clang::RecordDecl *decl) {
609609 // Enums and static variables. In rust they live outside the record
610610 for (auto *d : decl->decls ()) {
611611 if (auto *enum_decl = llvm::dyn_cast<clang::EnumDecl>(d)) {
@@ -631,6 +631,9 @@ void Converter::EmitRustStruct(clang::RecordDecl *decl) {
631631 }
632632
633633 // Derived traits
634+ if (EmitsReprCForRecords ()) {
635+ StrCat (" #[repr(C)]" );
636+ }
634637 StrCat (" #[derive(" );
635638 for (auto *attr : GetStructAttributes (decl)) {
636639 StrCat (attr, " ," );
@@ -641,7 +644,8 @@ void Converter::EmitRustStruct(clang::RecordDecl *decl) {
641644 auto access = clang::dyn_cast<clang::CXXRecordDecl>(decl)
642645 ? AccessSpecifierAsString (decl->getAccess ())
643646 : keyword::kPub ;
644- StrCat (access, keyword::kStruct , GetRecordName (decl));
647+ StrCat (access, decl->isUnion () ? keyword::kUnion : keyword::kStruct ,
648+ GetRecordName (decl));
645649 {
646650 PushBrace brace (*this );
647651 for (auto *field : decl->fields ()) {
@@ -682,8 +686,8 @@ void Converter::EmitRustStruct(clang::RecordDecl *decl) {
682686 AddOrdTrait (cxx);
683687 AddCloneTrait (cxx);
684688 AddDropTrait (cxx);
685- AddDefaultTrait (cxx);
686689 }
690+ AddDefaultTrait (decl);
687691 AddByteReprTrait (decl);
688692}
689693
@@ -729,10 +733,10 @@ bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) {
729733 }
730734 }
731735
732- EmitRustStruct (decl);
736+ EmitRustStructOrUnion (decl);
733737 } else {
734738 // FIXME: improve error handling
735- assert (0 && " unsupported union " );
739+ assert (0 && " unsupported record kind " );
736740 }
737741
738742 return false ;
@@ -2889,6 +2893,10 @@ std::string Converter::GetRecordName(const clang::NamedDecl *decl) const {
28892893
28902894std::vector<const char *>
28912895Converter::GetStructAttributes (const clang::RecordDecl *decl) {
2896+ if (decl->isUnion ()) {
2897+ return {" Copy" , " Clone" };
2898+ }
2899+
28922900 std::vector<const char *> struct_attrs = {};
28932901
28942902 if (recordDerivesCopy (decl)) {
@@ -3208,7 +3216,21 @@ void Converter::AddCloneTrait(const clang::CXXRecordDecl *decl) {}
32083216
32093217void Converter::AddDropTrait (const clang::CXXRecordDecl *decl) {}
32103218
3211- void Converter::AddDefaultTrait (const clang::CXXRecordDecl *decl) {
3219+ void Converter::AddDefaultTraitForUnion (const clang::RecordDecl *decl) {
3220+ StrCat (std::format (" impl Default for {}" , GetRecordName (decl)));
3221+ PushBrace impl_brace (*this );
3222+ StrCat (" fn default() -> Self" );
3223+ PushBrace fn_brace (*this );
3224+ StrCat (" unsafe" );
3225+ PushBrace unsafe_brace (*this );
3226+ StrCat (" std::mem::zeroed()" );
3227+ }
3228+
3229+ void Converter::AddDefaultTrait (const clang::RecordDecl *decl) {
3230+ if (decl->isUnion ()) {
3231+ AddDefaultTraitForUnion (decl);
3232+ return ;
3233+ }
32123234 if (RecordDerivesDefault (decl)) {
32133235 return ;
32143236 }
@@ -3217,20 +3239,26 @@ void Converter::AddDefaultTrait(const clang::CXXRecordDecl *decl) {
32173239 PushBrace impl_brace (*this );
32183240 StrCat (" fn default() -> Self" );
32193241 PushBrace fn_brace (*this );
3220- if (auto *default_ctor = GetUserDefinedDefaultConstructor (decl)) {
3221- StrCat (keyword_unsafe_);
3222- PushBrace unsafe_brace (*this );
3223- Convert (clang::CXXConstructExpr::Create (
3224- ctx_, ctx_.getCanonicalTagType (decl), clang::SourceLocation (),
3225- default_ctor,
3226- /* Elidable=*/ false , llvm::ArrayRef<clang::Expr *>(),
3227- /* HadMultipleCandidates=*/ false ,
3228- /* ListInitialization=*/ false ,
3229- /* StdInitListInitialization=*/ false ,
3230- /* ZeroInitialization=*/ false , clang::CXXConstructionKind::Complete,
3231- clang::SourceRange ()));
3232- } else {
3233- StrCat (struct_name);
3242+
3243+ if (auto *cxx = clang::dyn_cast<clang::CXXRecordDecl>(decl)) {
3244+ if (auto *default_ctor = GetUserDefinedDefaultConstructor (cxx)) {
3245+ StrCat (keyword_unsafe_);
3246+ PushBrace unsafe_brace (*this );
3247+ Convert (clang::CXXConstructExpr::Create (
3248+ ctx_, ctx_.getCanonicalTagType (decl), clang::SourceLocation (),
3249+ default_ctor,
3250+ /* Elidable=*/ false , llvm::ArrayRef<clang::Expr *>(),
3251+ /* HadMultipleCandidates=*/ false ,
3252+ /* ListInitialization=*/ false ,
3253+ /* StdInitListInitialization=*/ false ,
3254+ /* ZeroInitialization=*/ false , clang::CXXConstructionKind::Complete,
3255+ clang::SourceRange ()));
3256+ return ;
3257+ }
3258+ }
3259+
3260+ StrCat (struct_name);
3261+ {
32343262 PushBrace struct_brace (*this );
32353263 for (auto *field : decl->fields ()) {
32363264 StrCat (GetNamedDeclAsString (field), token::kColon ,
0 commit comments