@@ -646,7 +646,7 @@ func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl {
646646 decl .Name = & ast.Ident {Name : cursorName }
647647 ct .logln ("ProcessEnumDecl: has name" , cursorName )
648648 } else {
649- ct .logln ("ProcessRecordDecl : is anonymous" )
649+ ct .logln ("ProcessEnumDecl : is anonymous" )
650650 }
651651
652652 return decl
@@ -679,6 +679,7 @@ func (ct *Converter) createBaseField(cursor clang.Cursor) *ast.Field {
679679 fieldName := toStr (cursor .String ())
680680
681681 typ := cursor .Type ()
682+
682683 typeName , typeKind := getTypeDesc (typ )
683684
684685 ct .logf ("createBaseField: ProcessType %s TypeKind: %s" , typeName , typeKind )
@@ -760,23 +761,41 @@ func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) []ast.Decl {
760761 ct .logln ("ProcessRecordDecl: CursorName:" , cursorName , "CursorKind:" , cursorKind )
761762
762763 childs := PostOrderVisitChildren (cursor , func (child , parent clang.Cursor ) bool {
764+ // if we found a nested enum, handle it like nested struct
765+ if child .Kind == clang .CursorEnumDecl {
766+ return true
767+ }
763768 return (child .Kind == clang .CursorStructDecl || child .Kind == clang .CursorUnionDecl ) && child .IsAnonymous () == 0
764769 })
765770
766771 for _ , child := range childs {
767- // Check if this is a named nested struct/union
768- typ := ct .ProcessRecordType (child )
769- // note(zzy):use len(typ.Fields.List) to ensure it has fields not a forward declaration
770- // but maybe make the forward decl in to AST is also good.
771- if child .IsAnonymous () == 0 && typ .Fields != nil {
772+ switch child .Kind {
773+ case clang .CursorStructDecl , clang .CursorUnionDecl :
774+ // note(zzy):use len(typ.Fields.List) to ensure it has fields not a forward declaration
775+ // but maybe make the forward decl in to AST is also good.
772776 childName := clang .GoString (child .String ())
773777 ct .logln ("ProcessRecordDecl: Found named nested struct:" , childName )
774- decls = append (decls , & ast.TypeDecl {
775- Object : ct .CreateObject (child , & ast.Ident {Name : childName }),
776- Type : ct .ProcessRecordType (child ),
777- })
778+ // Check if this is a named nested struct/union
779+ typ := ct .ProcessRecordType (child )
780+ // note(zzy):use len(typ.Fields.List) to ensure it has fields not a forward declaration
781+ // but maybe make the forward decl in to AST is also good.
782+ if child .IsAnonymous () == 0 && typ .Fields != nil {
783+ decls = append (decls , & ast.TypeDecl {
784+ Object : ct .CreateObject (child , & ast.Ident {Name : childName }),
785+ Type : ct .ProcessRecordType (child ),
786+ })
787+ }
788+ case clang .CursorEnumDecl :
789+ childName := clang .GoString (child .String ())
790+
791+ ct .logln ("ProcessRecordDecl: Found named nested enum:" , childName )
792+
793+ ct .incIndent ()
794+ decls = append (decls , ct .ProcessEnumDecl (child ))
795+ ct .decIndent ()
778796 }
779797 }
798+ ct .logln ("ProcessRecordDecl: process record: " , cursorName )
780799
781800 decl := & ast.TypeDecl {
782801 Object : ct .CreateObject (cursor , nil ),
@@ -864,28 +883,44 @@ func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr {
864883 ct .logln ("ProcessElaboratedType: TypeName:" , typeName , "TypeKind:" , typeKind )
865884
866885 decl := t .TypeDeclaration ()
886+ isAnonymousDecl := decl .IsAnonymous () > 0
867887
868- if decl .IsAnonymous () != 0 {
869- // anonymous type refer (except anonymous RecordType&EnumType in TypedefDecl)
870- if decl .Kind == clang .CursorEnumDecl {
888+ if isAnonymousDecl && decl .Kind != clang .CursorEnumDecl {
889+ return ct .ProcessRecordType (decl )
890+ }
891+ parts := clangutils .BuildScopingParts (decl )
892+ hasParent := clangutils .HasParent (decl )
893+ // NOTE(MeteorsLiu): nested enum behaves different from nested struct, for example, we can find its semantic parent
894+ // however, it will cause we misidentified it as a class method expr, so take it out
895+ if isAnonymousDecl && decl .Kind == clang .CursorEnumDecl {
896+ // case 1: anonymous enum, but not nested (anonymous enum decl variable case)
897+ if ! hasParent {
898+ // this is not a nested enum, handle it normally
871899 return ct .ProcessEnumType (decl )
872900 }
873- return ct .ProcessRecordType (decl )
901+ // case 2: anonymous enum, nested (normal nested struct reference)
902+ // by default, the type of an anonymous enum is int
903+ // NOTE(MeteorsLiu): see disscussion https://github.com/goplus/llcppg/pull/530
904+ return & ast.BuiltinType {Kind : ast .Int }
905+
906+ // case 3: named enum, nested, fallback to process as a ElaboratedType (nornaml nested struct)
907+ // case 4: named enum, non-nested, fallback to process as a ElaboratedType normally. (typedef enum case)
874908 }
875909
876910 // for elaborated type, it could have a tag description
877911 // like struct A, union B, class C, enum D
878- parts := strings .SplitN (typeName , " " , 2 )
879- if len (parts ) == 2 {
880- if tagValue , ok := tagMap [parts [0 ]]; ok {
912+ typeParts := strings .SplitN (typeName , " " , 2 )
913+
914+ if len (typeParts ) == 2 {
915+ if tagValue , ok := tagMap [typeParts [0 ]]; ok {
881916 return & ast.TagExpr {
882917 Tag : tagValue ,
883- Name : ct . BuildScopingExpr ( decl ),
918+ Name : buildScopingFromParts ( parts ),
884919 }
885920 }
886921 }
887922
888- return ct . BuildScopingExpr ( decl )
923+ return buildScopingFromParts ( parts )
889924}
890925
891926func (ct * Converter ) ProcessTypeDefType (t clang.Type ) ast.Expr {
@@ -1031,7 +1066,6 @@ func buildScopingFromParts(parts []string) ast.Expr {
10311066 if len (parts ) == 0 {
10321067 return nil
10331068 }
1034-
10351069 var expr ast.Expr = & ast.Ident {Name : parts [0 ]}
10361070 for _ , part := range parts [1 :] {
10371071 expr = & ast.ScopingExpr {
0 commit comments