diff --git a/_xtool/internal/clang/clang.go b/_xtool/internal/clang/clang.go index 752462fa..667d3a9b 100644 --- a/_xtool/internal/clang/clang.go +++ b/_xtool/internal/clang/clang.go @@ -101,6 +101,25 @@ func BuildScopingParts(cursor clang.Cursor) []string { return parts } +func HasParent(cursor clang.Cursor) bool { + semanticParentsNum := 0 + node := cursor + for node.IsNull() != 1 && node.Kind != clang.CursorTranslationUnit { + semanticParentsNum++ + node = node.SemanticParent() + } + if semanticParentsNum > 1 { + return true + } + node = cursor + lexicalParentsNum := 0 + for node.IsNull() != 1 && node.Kind != clang.CursorTranslationUnit { + lexicalParentsNum++ + node = node.LexicalParent() + } + return lexicalParentsNum > 1 +} + func VisitChildren(cursor clang.Cursor, fn Visitor) c.Uint { return clang.VisitChildren(cursor, func(cursor, parent clang.Cursor, clientData unsafe.Pointer) clang.ChildVisitResult { cfn := *(*Visitor)(clientData) diff --git a/_xtool/internal/parser/parser.go b/_xtool/internal/parser/parser.go index f7331da1..86bdc60b 100644 --- a/_xtool/internal/parser/parser.go +++ b/_xtool/internal/parser/parser.go @@ -646,7 +646,7 @@ func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl { decl.Name = &ast.Ident{Name: cursorName} ct.logln("ProcessEnumDecl: has name", cursorName) } else { - ct.logln("ProcessRecordDecl: is anonymous") + ct.logln("ProcessEnumDecl: is anonymous") } return decl @@ -679,6 +679,7 @@ func (ct *Converter) createBaseField(cursor clang.Cursor) *ast.Field { fieldName := toStr(cursor.String()) typ := cursor.Type() + typeName, typeKind := getTypeDesc(typ) ct.logf("createBaseField: ProcessType %s TypeKind: %s", typeName, typeKind) @@ -760,23 +761,41 @@ func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) []ast.Decl { ct.logln("ProcessRecordDecl: CursorName:", cursorName, "CursorKind:", cursorKind) childs := PostOrderVisitChildren(cursor, func(child, parent clang.Cursor) bool { + // if we found a nested enum, handle it like nested struct + if child.Kind == clang.CursorEnumDecl { + return true + } return (child.Kind == clang.CursorStructDecl || child.Kind == clang.CursorUnionDecl) && child.IsAnonymous() == 0 }) for _, child := range childs { - // Check if this is a named nested struct/union - typ := ct.ProcessRecordType(child) - // note(zzy):use len(typ.Fields.List) to ensure it has fields not a forward declaration - // but maybe make the forward decl in to AST is also good. - if child.IsAnonymous() == 0 && typ.Fields != nil { + switch child.Kind { + case clang.CursorStructDecl, clang.CursorUnionDecl: + // note(zzy):use len(typ.Fields.List) to ensure it has fields not a forward declaration + // but maybe make the forward decl in to AST is also good. childName := clang.GoString(child.String()) ct.logln("ProcessRecordDecl: Found named nested struct:", childName) - decls = append(decls, &ast.TypeDecl{ - Object: ct.CreateObject(child, &ast.Ident{Name: childName}), - Type: ct.ProcessRecordType(child), - }) + // Check if this is a named nested struct/union + typ := ct.ProcessRecordType(child) + // note(zzy):use len(typ.Fields.List) to ensure it has fields not a forward declaration + // but maybe make the forward decl in to AST is also good. + if child.IsAnonymous() == 0 && typ.Fields != nil { + decls = append(decls, &ast.TypeDecl{ + Object: ct.CreateObject(child, &ast.Ident{Name: childName}), + Type: ct.ProcessRecordType(child), + }) + } + case clang.CursorEnumDecl: + childName := clang.GoString(child.String()) + + ct.logln("ProcessRecordDecl: Found named nested enum:", childName) + + ct.incIndent() + decls = append(decls, ct.ProcessEnumDecl(child)) + ct.decIndent() } } + ct.logln("ProcessRecordDecl: process record: ", cursorName) decl := &ast.TypeDecl{ Object: ct.CreateObject(cursor, nil), @@ -864,28 +883,44 @@ func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr { ct.logln("ProcessElaboratedType: TypeName:", typeName, "TypeKind:", typeKind) decl := t.TypeDeclaration() + isAnonymousDecl := decl.IsAnonymous() > 0 - if decl.IsAnonymous() != 0 { - // anonymous type refer (except anonymous RecordType&EnumType in TypedefDecl) - if decl.Kind == clang.CursorEnumDecl { + if isAnonymousDecl && decl.Kind != clang.CursorEnumDecl { + return ct.ProcessRecordType(decl) + } + parts := clangutils.BuildScopingParts(decl) + hasParent := clangutils.HasParent(decl) + // NOTE(MeteorsLiu): nested enum behaves different from nested struct, for example, we can find its semantic parent + // however, it will cause we misidentified it as a class method expr, so take it out + if isAnonymousDecl && decl.Kind == clang.CursorEnumDecl { + // case 1: anonymous enum, but not nested (anonymous enum decl variable case) + if !hasParent { + // this is not a nested enum, handle it normally return ct.ProcessEnumType(decl) } - return ct.ProcessRecordType(decl) + // case 2: anonymous enum, nested (normal nested struct reference) + // by default, the type of an anonymous enum is int + // NOTE(MeteorsLiu): see disscussion https://github.com/goplus/llcppg/pull/530 + return &ast.BuiltinType{Kind: ast.Int} + + // case 3: named enum, nested, fallback to process as a ElaboratedType (nornaml nested struct) + // case 4: named enum, non-nested, fallback to process as a ElaboratedType normally. (typedef enum case) } // for elaborated type, it could have a tag description // like struct A, union B, class C, enum D - parts := strings.SplitN(typeName, " ", 2) - if len(parts) == 2 { - if tagValue, ok := tagMap[parts[0]]; ok { + typeParts := strings.SplitN(typeName, " ", 2) + + if len(typeParts) == 2 { + if tagValue, ok := tagMap[typeParts[0]]; ok { return &ast.TagExpr{ Tag: tagValue, - Name: ct.BuildScopingExpr(decl), + Name: buildScopingFromParts(parts), } } } - return ct.BuildScopingExpr(decl) + return buildScopingFromParts(parts) } func (ct *Converter) ProcessTypeDefType(t clang.Type) ast.Expr { @@ -1031,7 +1066,6 @@ func buildScopingFromParts(parts []string) ast.Expr { if len(parts) == 0 { return nil } - var expr ast.Expr = &ast.Ident{Name: parts[0]} for _, part := range parts[1:] { expr = &ast.ScopingExpr{ diff --git a/_xtool/internal/parser/parser_test.go b/_xtool/internal/parser/parser_test.go index 2837baea..5cfc3ef9 100644 --- a/_xtool/internal/parser/parser_test.go +++ b/_xtool/internal/parser/parser_test.go @@ -20,7 +20,7 @@ import ( ) func TestParserCppMode(t *testing.T) { - cases := []string{"class", "comment", "enum", "func", "scope", "struct", "typedef", "union", "macro", "forwarddecl1", "forwarddecl2", "include", "typeof", "forward_vs_empty"} + cases := []string{"class", "comment", "enum", "func", "scope", "struct", "typedef", "union", "macro", "forwarddecl1", "forwarddecl2", "include", "typeof", "forward_vs_empty", "nestedenum_cpp"} // https://github.com/goplus/llgo/issues/1114 // todo(zzy):use os.ReadDir for _, folder := range cases { @@ -31,7 +31,7 @@ func TestParserCppMode(t *testing.T) { } func TestParserCMode(t *testing.T) { - cases := []string{"enum", "struct", "union", "macro", "include", "typeof", "named_nested_struct", "forward_vs_empty"} + cases := []string{"enum", "struct", "union", "macro", "include", "typeof", "named_nested_struct", "forward_vs_empty", "nestedenum"} for _, folder := range cases { t.Run(folder, func(t *testing.T) { testFrom(t, filepath.Join("testdata", folder), "temp.h", false, false) @@ -250,6 +250,15 @@ func TestNonBuiltinTypes(t *testing.T) { }, }, }, + { + TypeCode: `struct Foo { enum Bar {} k; }; + enum Bar`, + ExpectTypeStr: "enum Bar", + expr: &ast.TagExpr{ + Tag: ast.Enum, + Name: &ast.Ident{Name: "Bar"}, + }, + }, { TypeCode: `enum { x = 42 }`, ExpectTypeStr: "enum (unnamed enum at temp.h:1:1)", diff --git a/_xtool/internal/parser/testdata/nestedenum/expect.json b/_xtool/internal/parser/testdata/nestedenum/expect.json new file mode 100755 index 00000000..2fb0b3b4 --- /dev/null +++ b/_xtool/internal/parser/testdata/nestedenum/expect.json @@ -0,0 +1,494 @@ +{ + "_Type": "File", + "decls": [ + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": null, + "Parent": { + "Name": "NestedEnum", + "_Type": "Ident" + }, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA1", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA2", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": null, + "Parent": { + "Name": "a", + "_Type": "Ident" + }, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA_A1", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA_A2", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "a", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": [ + { + "Access": 1, + "Comment": null, + "Doc": null, + "IsStatic": false, + "Names": [ + { + "Name": "is_metadata1_t", + "_Type": "Ident" + } + ], + "Type": { + "Flags": 0, + "Kind": 6, + "_Type": "BuiltinType" + }, + "_Type": "Field" + } + ], + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "NestedEnum", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": [ + { + "Access": 1, + "Comment": null, + "Doc": null, + "IsStatic": false, + "Names": [ + { + "Name": "is_metadata1_t", + "_Type": "Ident" + } + ], + "Type": { + "Flags": 0, + "Kind": 6, + "_Type": "BuiltinType" + }, + "_Type": "Field" + }, + { + "Access": 1, + "Comment": null, + "Doc": null, + "IsStatic": false, + "Names": [ + { + "Name": "a_t", + "_Type": "Ident" + } + ], + "Type": { + "Name": { + "Name": "a", + "_Type": "Ident" + }, + "Tag": 0, + "_Type": "TagExpr" + }, + "_Type": "Field" + } + ], + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": null, + "Parent": { + "Name": "NestedEnum2", + "_Type": "Ident" + }, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA3", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA4", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "NestedEnum2", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": null, + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "is_metadata3", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA5", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA6", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "NestedEnum3", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": null, + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "is_metadata4", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA7", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA8", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "NestedEnum4", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": [ + { + "Access": 1, + "Comment": null, + "Doc": null, + "IsStatic": false, + "Names": [ + { + "Name": "key", + "_Type": "Ident" + } + ], + "Type": { + "Name": { + "Name": "is_metadata4", + "_Type": "Ident" + }, + "Tag": 2, + "_Type": "TagExpr" + }, + "_Type": "Field" + } + ], + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "OuterEnum", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA9", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA10", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "Enum", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": [ + { + "Access": 1, + "Comment": null, + "Doc": null, + "IsStatic": false, + "Names": [ + { + "Name": "k", + "_Type": "Ident" + } + ], + "Type": { + "Name": { + "Name": "OuterEnum", + "_Type": "Ident" + }, + "Tag": 2, + "_Type": "TagExpr" + }, + "_Type": "Field" + } + ], + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + } + ], + "includes": null, + "macros": null +} \ No newline at end of file diff --git a/_xtool/internal/parser/testdata/nestedenum/temp.h b/_xtool/internal/parser/testdata/nestedenum/temp.h new file mode 100644 index 00000000..4fbcce95 --- /dev/null +++ b/_xtool/internal/parser/testdata/nestedenum/temp.h @@ -0,0 +1,54 @@ +struct NestedEnum +{ + enum + { + APR_BUCKET_DATA1 = 0, + APR_BUCKET_METADATA2 = 1 + } is_metadata1_t; + + struct a + { + enum + { + APR_BUCKET_DATA_A1 = 0, + APR_BUCKET_METADATA_A2 = 1 + } is_metadata1_t; + } a_t; +}; + +struct NestedEnum2 +{ + enum + { + APR_BUCKET_DATA3 = 0, + APR_BUCKET_METADATA4 = 1 + }; +}; + +struct NestedEnum3 +{ + enum is_metadata3 + { + APR_BUCKET_DATA5 = 0, + APR_BUCKET_METADATA6 = 1 + }; +}; + +struct NestedEnum4 +{ + enum is_metadata4 + { + APR_BUCKET_DATA7 = 0, + APR_BUCKET_METADATA8 = 1 + } key; +}; + +enum OuterEnum +{ + APR_BUCKET_DATA9 = 0, + APR_BUCKET_METADATA10 = 1 +}; +struct Enum +{ + enum OuterEnum k; +}; diff --git a/_xtool/internal/parser/testdata/nestedenum_cpp/expect.json b/_xtool/internal/parser/testdata/nestedenum_cpp/expect.json new file mode 100755 index 00000000..60f865bc --- /dev/null +++ b/_xtool/internal/parser/testdata/nestedenum_cpp/expect.json @@ -0,0 +1,524 @@ +{ + "_Type": "File", + "decls": [ + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": null, + "Parent": { + "Name": "NestedEnum", + "_Type": "Ident" + }, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA1", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA2", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": null, + "Parent": { + "Parent": { + "Name": "NestedEnum", + "_Type": "Ident" + }, + "X": { + "Name": "a", + "_Type": "Ident" + }, + "_Type": "ScopingExpr" + }, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA_A1", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA_A2", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "a", + "_Type": "Ident" + }, + "Parent": { + "Name": "NestedEnum", + "_Type": "Ident" + }, + "Type": { + "Fields": { + "List": [ + { + "Access": 1, + "Comment": null, + "Doc": null, + "IsStatic": false, + "Names": [ + { + "Name": "is_metadata1_t", + "_Type": "Ident" + } + ], + "Type": { + "Flags": 0, + "Kind": 6, + "_Type": "BuiltinType" + }, + "_Type": "Field" + } + ], + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "NestedEnum", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": [ + { + "Access": 1, + "Comment": null, + "Doc": null, + "IsStatic": false, + "Names": [ + { + "Name": "is_metadata1_t", + "_Type": "Ident" + } + ], + "Type": { + "Flags": 0, + "Kind": 6, + "_Type": "BuiltinType" + }, + "_Type": "Field" + }, + { + "Access": 1, + "Comment": null, + "Doc": null, + "IsStatic": false, + "Names": [ + { + "Name": "a_t", + "_Type": "Ident" + } + ], + "Type": { + "Name": { + "Parent": { + "Name": "NestedEnum", + "_Type": "Ident" + }, + "X": { + "Name": "a", + "_Type": "Ident" + }, + "_Type": "ScopingExpr" + }, + "Tag": 0, + "_Type": "TagExpr" + }, + "_Type": "Field" + } + ], + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": null, + "Parent": { + "Name": "NestedEnum2", + "_Type": "Ident" + }, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA3", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA4", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "NestedEnum2", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": null, + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "is_metadata3", + "_Type": "Ident" + }, + "Parent": { + "Name": "NestedEnum3", + "_Type": "Ident" + }, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA5", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA6", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "NestedEnum3", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": null, + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "is_metadata4", + "_Type": "Ident" + }, + "Parent": { + "Name": "NestedEnum4", + "_Type": "Ident" + }, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA7", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA8", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "NestedEnum4", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": [ + { + "Access": 1, + "Comment": null, + "Doc": null, + "IsStatic": false, + "Names": [ + { + "Name": "key", + "_Type": "Ident" + } + ], + "Type": { + "Name": { + "Parent": { + "Name": "NestedEnum4", + "_Type": "Ident" + }, + "X": { + "Name": "is_metadata4", + "_Type": "Ident" + }, + "_Type": "ScopingExpr" + }, + "Tag": 2, + "_Type": "TagExpr" + }, + "_Type": "Field" + } + ], + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "OuterEnum", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Items": [ + { + "Name": { + "Name": "APR_BUCKET_DATA9", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "0", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + }, + { + "Name": { + "Name": "APR_BUCKET_METADATA10", + "_Type": "Ident" + }, + "Value": { + "Kind": 0, + "Value": "1", + "_Type": "BasicLit" + }, + "_Type": "EnumItem" + } + ], + "_Type": "EnumType" + }, + "_Type": "EnumTypeDecl" + }, + { + "Doc": null, + "Loc": { + "File": "testdata/nestedenum_cpp/temp.h", + "_Type": "Location" + }, + "Name": { + "Name": "Enum", + "_Type": "Ident" + }, + "Parent": null, + "Type": { + "Fields": { + "List": [ + { + "Access": 1, + "Comment": null, + "Doc": null, + "IsStatic": false, + "Names": [ + { + "Name": "k", + "_Type": "Ident" + } + ], + "Type": { + "Name": { + "Name": "OuterEnum", + "_Type": "Ident" + }, + "Tag": 2, + "_Type": "TagExpr" + }, + "_Type": "Field" + } + ], + "_Type": "FieldList" + }, + "Methods": null, + "Tag": 0, + "_Type": "RecordType" + }, + "_Type": "TypeDecl" + } + ], + "includes": null, + "macros": null +} \ No newline at end of file diff --git a/_xtool/internal/parser/testdata/nestedenum_cpp/temp.h b/_xtool/internal/parser/testdata/nestedenum_cpp/temp.h new file mode 100644 index 00000000..4fbcce95 --- /dev/null +++ b/_xtool/internal/parser/testdata/nestedenum_cpp/temp.h @@ -0,0 +1,54 @@ +struct NestedEnum +{ + enum + { + APR_BUCKET_DATA1 = 0, + APR_BUCKET_METADATA2 = 1 + } is_metadata1_t; + + struct a + { + enum + { + APR_BUCKET_DATA_A1 = 0, + APR_BUCKET_METADATA_A2 = 1 + } is_metadata1_t; + } a_t; +}; + +struct NestedEnum2 +{ + enum + { + APR_BUCKET_DATA3 = 0, + APR_BUCKET_METADATA4 = 1 + }; +}; + +struct NestedEnum3 +{ + enum is_metadata3 + { + APR_BUCKET_DATA5 = 0, + APR_BUCKET_METADATA6 = 1 + }; +}; + +struct NestedEnum4 +{ + enum is_metadata4 + { + APR_BUCKET_DATA7 = 0, + APR_BUCKET_METADATA8 = 1 + } key; +}; + +enum OuterEnum +{ + APR_BUCKET_DATA9 = 0, + APR_BUCKET_METADATA10 = 1 +}; +struct Enum +{ + enum OuterEnum k; +}; diff --git a/cl/internal/convert/_testdata/nestedenum/conf/llcppg.cfg b/cl/internal/convert/_testdata/nestedenum/conf/llcppg.cfg new file mode 100644 index 00000000..e54e679f --- /dev/null +++ b/cl/internal/convert/_testdata/nestedenum/conf/llcppg.cfg @@ -0,0 +1,7 @@ +{ + "name": "nestedenum", + "include": ["temp.h"], + "cplusplus":false, + "libs": "$(pkg-config --libs xxx)", + "trimPrefixes": [] +} diff --git a/cl/internal/convert/_testdata/nestedenum/gogensig.expect b/cl/internal/convert/_testdata/nestedenum/gogensig.expect new file mode 100644 index 00000000..872aae02 --- /dev/null +++ b/cl/internal/convert/_testdata/nestedenum/gogensig.expect @@ -0,0 +1,80 @@ +===== nestedenum_autogen_link.go ===== +package nestedenum + +import _ "github.com/goplus/lib/c" + +const LLGoPackage string = "link: $(pkg-config --libs xxx);" + +===== temp.go ===== +package nestedenum + +import ( + "github.com/goplus/lib/c" + _ "unsafe" +) + +const ( + APR_BUCKET_DATA1 c.Int = 0 + APR_BUCKET_METADATA2 c.Int = 1 +) +const ( + APR_BUCKET_DATA_A1 c.Int = 0 + APR_BUCKET_METADATA_A2 c.Int = 1 +) + +type A struct { + IsMetadata1T c.Int +} + +type NestedEnum struct { + IsMetadata1T c.Int + AT A +} + +const ( + APR_BUCKET_DATA3 c.Int = 0 + APR_BUCKET_METADATA4 c.Int = 1 +) + +type NestedEnum2 struct { +} +type IsMetadata3 c.Int + +const ( + APR_BUCKET_DATA5 IsMetadata3 = 0 + APR_BUCKET_METADATA6 IsMetadata3 = 1 +) + +type NestedEnum3 struct { +} +type IsMetadata4 c.Int + +const ( + APR_BUCKET_DATA7 IsMetadata4 = 0 + APR_BUCKET_METADATA8 IsMetadata4 = 1 +) + +type NestedEnum4 struct { + Key IsMetadata4 +} +type OuterEnum c.Int + +const ( + APR_BUCKET_DATA9 OuterEnum = 0 + APR_BUCKET_METADATA10 OuterEnum = 1 +) + +type Enum struct { + K OuterEnum +} + +===== llcppg.pub ===== +Enum +NestedEnum +NestedEnum2 +NestedEnum3 +NestedEnum4 +OuterEnum +a A +is_metadata3 IsMetadata3 +is_metadata4 IsMetadata4 \ No newline at end of file diff --git a/cl/internal/convert/_testdata/nestedenum/hfile/temp.h b/cl/internal/convert/_testdata/nestedenum/hfile/temp.h new file mode 100644 index 00000000..4fbcce95 --- /dev/null +++ b/cl/internal/convert/_testdata/nestedenum/hfile/temp.h @@ -0,0 +1,54 @@ +struct NestedEnum +{ + enum + { + APR_BUCKET_DATA1 = 0, + APR_BUCKET_METADATA2 = 1 + } is_metadata1_t; + + struct a + { + enum + { + APR_BUCKET_DATA_A1 = 0, + APR_BUCKET_METADATA_A2 = 1 + } is_metadata1_t; + } a_t; +}; + +struct NestedEnum2 +{ + enum + { + APR_BUCKET_DATA3 = 0, + APR_BUCKET_METADATA4 = 1 + }; +}; + +struct NestedEnum3 +{ + enum is_metadata3 + { + APR_BUCKET_DATA5 = 0, + APR_BUCKET_METADATA6 = 1 + }; +}; + +struct NestedEnum4 +{ + enum is_metadata4 + { + APR_BUCKET_DATA7 = 0, + APR_BUCKET_METADATA8 = 1 + } key; +}; + +enum OuterEnum +{ + APR_BUCKET_DATA9 = 0, + APR_BUCKET_METADATA10 = 1 +}; +struct Enum +{ + enum OuterEnum k; +}; diff --git a/cl/internal/convert/type.go b/cl/internal/convert/type.go index 08e1bb2e..1eed976b 100644 --- a/cl/internal/convert/type.go +++ b/cl/internal/convert/type.go @@ -159,15 +159,13 @@ func (p *TypeConv) handleIdentRefer(t ast.Expr) (types.Type, error) { case *ast.ScopingExpr: // todo(zzy) case *ast.TagExpr: - // todo(zzy):scoping - if ident, ok := t.Name.(*ast.Ident); ok { - typ, err := lookup(ident.Name) - if err != nil { - return nil, err - } - return typ, nil - } // todo(zzy):scoping expr + // FIXME(MeteorsLiu): when we support more tag type in the future, + // we need to split this logic into a function for readability + switch nameType := t.Name.(type) { + case *ast.Ident: + return lookup(nameType.Name) + } } return nil, fmt.Errorf("unsupported refer type %T", t) }