Merge pull request #870 from luoliwoshang/llcppsigfetch/otherdefinetype
llcppsigfetch:typedef refer same struct & remove tokenize check for underlying
This commit is contained in:
@@ -27,28 +27,7 @@ type Converter struct {
|
|||||||
index *clang.Index
|
index *clang.Index
|
||||||
unit *clang.TranslationUnit
|
unit *clang.TranslationUnit
|
||||||
|
|
||||||
typeDecls map[string]ast.Decl // cursorUsr -> ast.Decl
|
indent int // for verbose debug
|
||||||
|
|
||||||
// anonyTypeMap stores mappings for unexpected named declarations in typedefs
|
|
||||||
// that actually represent anonymous types.
|
|
||||||
//
|
|
||||||
// Key: The USR (Unified Symbol Resolution) of the declaration cursor.
|
|
||||||
// Value: The generated name for the anonymous type.
|
|
||||||
//
|
|
||||||
// This map is necessary due to a limitation in libclang where anonymous
|
|
||||||
// structs, unions, or enums within typedefs are incorrectly reported as
|
|
||||||
// named declarations. We use this map to keep track of these cases and
|
|
||||||
// generate appropriate names for them.
|
|
||||||
//
|
|
||||||
// Additionally, for all nodes referencing these anonymous types, their
|
|
||||||
// name references are updated to use the corresponding anonyname from
|
|
||||||
// this map. This ensures consistent naming across the entire AST for
|
|
||||||
// these anonymous types.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
// typedef struct { int x; } MyStruct;
|
|
||||||
anonyTypeMap map[string]bool // cursorUsr
|
|
||||||
indent int // for verbose debug
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var tagMap = map[string]ast.Tag{
|
var tagMap = map[string]ast.Tag{
|
||||||
@@ -80,11 +59,9 @@ func NewConverter(config *clangutils.Config) (*Converter, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &Converter{
|
return &Converter{
|
||||||
Files: make([]*FileEntry, 0),
|
Files: make([]*FileEntry, 0),
|
||||||
index: index,
|
index: index,
|
||||||
unit: unit,
|
unit: unit,
|
||||||
anonyTypeMap: make(map[string]bool),
|
|
||||||
typeDecls: make(map[string]ast.Decl),
|
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,28 +154,6 @@ func (ct *Converter) GetCurFile() *ast.File {
|
|||||||
return newDoc
|
return newDoc
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ct *Converter) SetAnonyType(cursor clang.Cursor) {
|
|
||||||
usr := toStr(cursor.USR())
|
|
||||||
ct.anonyTypeMap[usr] = true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ct *Converter) GetAnonyType(cursor clang.Cursor) (bool, bool) {
|
|
||||||
usr := toStr(cursor.USR())
|
|
||||||
isAnony, ok := ct.anonyTypeMap[usr]
|
|
||||||
return isAnony, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ct *Converter) SetTypeDecl(cursor clang.Cursor, decl ast.Decl) {
|
|
||||||
usr := toStr(cursor.USR())
|
|
||||||
ct.typeDecls[usr] = decl
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ct *Converter) GetTypeDecl(cursor clang.Cursor) (ast.Decl, bool) {
|
|
||||||
usr := toStr(cursor.USR())
|
|
||||||
decl, ok := ct.typeDecls[usr]
|
|
||||||
return decl, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ct *Converter) CreateDeclBase(cursor clang.Cursor) ast.DeclBase {
|
func (ct *Converter) CreateDeclBase(cursor clang.Cursor) ast.DeclBase {
|
||||||
base := ast.DeclBase{
|
base := ast.DeclBase{
|
||||||
Loc: &ct.curLoc,
|
Loc: &ct.curLoc,
|
||||||
@@ -315,6 +270,9 @@ func (ct *Converter) visitTop(cursor, parent clang.Cursor) clang.ChildVisitResul
|
|||||||
ct.logln("visitTop: ProcessFuncDecl END", funcDecl.Name.Name, funcDecl.MangledName, "isStatic:", funcDecl.IsStatic, "isInline:", funcDecl.IsInline)
|
ct.logln("visitTop: ProcessFuncDecl END", funcDecl.Name.Name, funcDecl.MangledName, "isStatic:", funcDecl.IsStatic, "isInline:", funcDecl.IsInline)
|
||||||
case clang.CursorTypedefDecl:
|
case clang.CursorTypedefDecl:
|
||||||
typedefDecl := ct.ProcessTypeDefDecl(cursor)
|
typedefDecl := ct.ProcessTypeDefDecl(cursor)
|
||||||
|
if typedefDecl == nil {
|
||||||
|
return clang.ChildVisit_Continue
|
||||||
|
}
|
||||||
curFile.Decls = append(curFile.Decls, typedefDecl)
|
curFile.Decls = append(curFile.Decls, typedefDecl)
|
||||||
ct.logln("visitTop: ProcessTypeDefDecl END", typedefDecl.Name.Name)
|
ct.logln("visitTop: ProcessTypeDefDecl END", typedefDecl.Name.Name)
|
||||||
case clang.CursorNamespace:
|
case clang.CursorNamespace:
|
||||||
@@ -444,15 +402,20 @@ func (ct *Converter) ProcessTypeDefDecl(cursor clang.Cursor) *ast.TypedefDecl {
|
|||||||
ct.logln("ProcessTypeDefDecl: CursorName:", name, "CursorKind:", kind, "CursorTypeKind:", toStr(cursor.Type().Kind.String()))
|
ct.logln("ProcessTypeDefDecl: CursorName:", name, "CursorKind:", kind, "CursorTypeKind:", toStr(cursor.Type().Kind.String()))
|
||||||
|
|
||||||
typ := ct.ProcessUnderlyingType(cursor)
|
typ := ct.ProcessUnderlyingType(cursor)
|
||||||
|
// For cases like: typedef struct { int x; } Name;
|
||||||
|
// libclang incorrectly reports the anonymous structure as a named structure
|
||||||
|
// with the same name as the typedef. Since the anonymous structure definition
|
||||||
|
// has already been collected when processing its declaration cursor,
|
||||||
|
// we skip this redundant typedef declaration by returning nil.
|
||||||
|
if typ == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
decl := &ast.TypedefDecl{
|
decl := &ast.TypedefDecl{
|
||||||
DeclBase: ct.CreateDeclBase(cursor),
|
DeclBase: ct.CreateDeclBase(cursor),
|
||||||
Name: &ast.Ident{Name: name},
|
Name: &ast.Ident{Name: name},
|
||||||
Type: typ,
|
Type: typ,
|
||||||
}
|
}
|
||||||
|
|
||||||
ct.SetTypeDecl(cursor, decl)
|
|
||||||
|
|
||||||
return decl
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,38 +428,9 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
referTypeCursor := underlyingTyp.TypeDeclaration()
|
referTypeCursor := underlyingTyp.TypeDeclaration()
|
||||||
|
if toStr(cursor.String()) == toStr(referTypeCursor.String()) && isCursorChildOf(referTypeCursor, cursor) {
|
||||||
// If the type decl for the reference already exists in anonyTypeMap
|
ct.logln("ProcessUnderlyingType: is self reference")
|
||||||
// then the refer has been processed in ProcessElaboratedType
|
return nil
|
||||||
if _, ok := ct.GetAnonyType(referTypeCursor); !ok && isCursorChildOf(referTypeCursor, cursor) {
|
|
||||||
// Handle unexpected named structures generated from anonymous RecordTypes in Typedefs
|
|
||||||
// In this case, libclang incorrectly reports an anonymous struct as a named struct
|
|
||||||
sourceCode := ct.GetTokens(referTypeCursor)
|
|
||||||
if isAnonymousStructure(sourceCode) {
|
|
||||||
ct.logln("ProcessUnderlyingType: is anonymous structure")
|
|
||||||
ct.SetAnonyType(referTypeCursor)
|
|
||||||
typ, isValidType := ct.GetTypeDecl(referTypeCursor)
|
|
||||||
if isValidType {
|
|
||||||
// There will be no anonymous classes,here will execute enum,union,struct
|
|
||||||
// according to a normal anonymous decl
|
|
||||||
switch declType := typ.(type) {
|
|
||||||
case *ast.EnumTypeDecl:
|
|
||||||
ct.logln("ProcessUnderlyingType: is actually anonymous enum,remove name")
|
|
||||||
declType.Name = nil
|
|
||||||
case *ast.TypeDecl:
|
|
||||||
if declType.Type.Tag != ast.Class {
|
|
||||||
ct.logln("ProcessUnderlyingType: is actually anonymous struct,remove name")
|
|
||||||
declType.Name = nil
|
|
||||||
} else {
|
|
||||||
// Unreachable: There should be no anonymous classes in this context
|
|
||||||
fmt.Fprintln(os.Stderr, "unexpect typedef anonymous class %s", declType.Name.Name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Unreachable:When referencing an anonymous node, its collection must have been completed beforehand
|
|
||||||
fmt.Fprintln(os.Stderr, "anonymous node not collected before reference")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ct.ProcessElaboratedType(underlyingTyp)
|
return ct.ProcessElaboratedType(underlyingTyp)
|
||||||
@@ -546,7 +480,6 @@ func (ct *Converter) ProcessFuncDecl(cursor clang.Cursor) *ast.FuncDecl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ct.SetTypeDecl(cursor, funcDecl)
|
|
||||||
return funcDecl
|
return funcDecl
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -631,7 +564,6 @@ func (ct *Converter) ProcessEnumDecl(cursor clang.Cursor) *ast.EnumTypeDecl {
|
|||||||
ct.logln("ProcessRecordDecl: is anonymous")
|
ct.logln("ProcessRecordDecl: is anonymous")
|
||||||
}
|
}
|
||||||
|
|
||||||
ct.SetTypeDecl(cursor, decl)
|
|
||||||
return decl
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -764,7 +696,6 @@ func (ct *Converter) ProcessRecordDecl(cursor clang.Cursor) *ast.TypeDecl {
|
|||||||
ct.logln("ProcessRecordDecl: is anonymous")
|
ct.logln("ProcessRecordDecl: is anonymous")
|
||||||
}
|
}
|
||||||
|
|
||||||
ct.SetTypeDecl(cursor, decl)
|
|
||||||
return decl
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -790,7 +721,6 @@ func (ct *Converter) ProcessClassDecl(cursor clang.Cursor) *ast.TypeDecl {
|
|||||||
Type: typ,
|
Type: typ,
|
||||||
}
|
}
|
||||||
|
|
||||||
ct.SetTypeDecl(cursor, decl)
|
|
||||||
return decl
|
return decl
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -833,9 +763,8 @@ func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr {
|
|||||||
ct.logln("ProcessElaboratedType: TypeName:", typeName, "TypeKind:", typeKind)
|
ct.logln("ProcessElaboratedType: TypeName:", typeName, "TypeKind:", typeKind)
|
||||||
|
|
||||||
decl := t.TypeDeclaration()
|
decl := t.TypeDeclaration()
|
||||||
isAnony, ok := ct.GetAnonyType(decl)
|
|
||||||
|
|
||||||
if decl.IsAnonymous() != 0 || isAnony && ok {
|
if decl.IsAnonymous() != 0 {
|
||||||
// anonymous type refer (except anonymous RecordType&EnumType in TypedefDecl)
|
// anonymous type refer (except anonymous RecordType&EnumType in TypedefDecl)
|
||||||
if decl.Kind == clang.CursorEnumDecl {
|
if decl.Kind == clang.CursorEnumDecl {
|
||||||
return ct.ProcessEnumType(decl)
|
return ct.ProcessEnumType(decl)
|
||||||
@@ -1026,15 +955,6 @@ func getOffset(location clang.SourceLocation) c.Uint {
|
|||||||
return offset
|
return offset
|
||||||
}
|
}
|
||||||
|
|
||||||
// checks if the source code represents an actual anonymous structure
|
|
||||||
func isAnonymousStructure(sourceCode []*ast.Token) bool {
|
|
||||||
_, isValidTag := tagMap[sourceCode[0].Lit]
|
|
||||||
return sourceCode[0].Token == token.KEYWORD &&
|
|
||||||
isValidTag &&
|
|
||||||
sourceCode[1].Token == token.PUNCT &&
|
|
||||||
sourceCode[1].Lit == "{"
|
|
||||||
}
|
|
||||||
|
|
||||||
func toStr(clangStr clang.String) (str string) {
|
func toStr(clangStr clang.String) (str string) {
|
||||||
defer clangStr.Dispose()
|
defer clangStr.Dispose()
|
||||||
if clangStr.CStr() != nil {
|
if clangStr.CStr() != nil {
|
||||||
|
|||||||
@@ -12,30 +12,35 @@ import (
|
|||||||
|
|
||||||
func RunTest(testName string, testCases []string) {
|
func RunTest(testName string, testCases []string) {
|
||||||
for i, content := range testCases {
|
for i, content := range testCases {
|
||||||
converter, err := parse.NewConverter(&clangutils.Config{
|
c.Printf(c.Str("%s Case %d:\n"), c.AllocaCStr(testName), c.Int(i+1))
|
||||||
|
RunTestWithConfig(&clangutils.Config{
|
||||||
File: content,
|
File: content,
|
||||||
Temp: true,
|
Temp: true,
|
||||||
IsCpp: true,
|
IsCpp: true,
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = converter.Convert()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
result := converter.MarshalASTFiles()
|
|
||||||
str := result.Print()
|
|
||||||
c.Printf(c.Str("%s Case %d:\n%s\n\n"), c.AllocaCStr(testName), c.Int(i+1), str)
|
|
||||||
|
|
||||||
cjson.FreeCStr(str)
|
|
||||||
result.Delete()
|
|
||||||
converter.Dispose()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func RunTestWithConfig(config *clangutils.Config) {
|
||||||
|
converter, err := parse.NewConverter(config)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = converter.Convert()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result := converter.MarshalASTFiles()
|
||||||
|
str := result.Print()
|
||||||
|
c.Printf(c.Str("%s\n\n"), str)
|
||||||
|
|
||||||
|
cjson.FreeCStr(str)
|
||||||
|
result.Delete()
|
||||||
|
converter.Dispose()
|
||||||
|
}
|
||||||
|
|
||||||
type GetTypeOptions struct {
|
type GetTypeOptions struct {
|
||||||
TypeCode string // e.g. "char*", "char**"
|
TypeCode string // e.g. "char*", "char**"
|
||||||
|
|
||||||
|
|||||||
@@ -484,39 +484,6 @@ TestTypeDefDecl Case 7:
|
|||||||
},
|
},
|
||||||
"Doc": null,
|
"Doc": null,
|
||||||
"Parent": null,
|
"Parent": null,
|
||||||
"Name": null,
|
|
||||||
"Type": {
|
|
||||||
"_Type": "RecordType",
|
|
||||||
"Tag": 0,
|
|
||||||
"Fields": {
|
|
||||||
"_Type": "FieldList",
|
|
||||||
"List": [{
|
|
||||||
"_Type": "Field",
|
|
||||||
"Type": {
|
|
||||||
"_Type": "BuiltinType",
|
|
||||||
"Kind": 6,
|
|
||||||
"Flags": 0
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Comment": null,
|
|
||||||
"IsStatic": false,
|
|
||||||
"Access": 1,
|
|
||||||
"Names": [{
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "x"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"Methods": []
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"_Type": "TypedefDecl",
|
|
||||||
"Loc": {
|
|
||||||
"_Type": "Location",
|
|
||||||
"File": "temp.h"
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Parent": null,
|
|
||||||
"Name": {
|
"Name": {
|
||||||
"_Type": "Ident",
|
"_Type": "Ident",
|
||||||
"Name": "MyStruct"
|
"Name": "MyStruct"
|
||||||
@@ -563,39 +530,6 @@ TestTypeDefDecl Case 8:
|
|||||||
},
|
},
|
||||||
"Doc": null,
|
"Doc": null,
|
||||||
"Parent": null,
|
"Parent": null,
|
||||||
"Name": null,
|
|
||||||
"Type": {
|
|
||||||
"_Type": "RecordType",
|
|
||||||
"Tag": 1,
|
|
||||||
"Fields": {
|
|
||||||
"_Type": "FieldList",
|
|
||||||
"List": [{
|
|
||||||
"_Type": "Field",
|
|
||||||
"Type": {
|
|
||||||
"_Type": "BuiltinType",
|
|
||||||
"Kind": 6,
|
|
||||||
"Flags": 0
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Comment": null,
|
|
||||||
"IsStatic": false,
|
|
||||||
"Access": 1,
|
|
||||||
"Names": [{
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "x"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"Methods": []
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"_Type": "TypedefDecl",
|
|
||||||
"Loc": {
|
|
||||||
"_Type": "Location",
|
|
||||||
"File": "temp.h"
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Parent": null,
|
|
||||||
"Name": {
|
"Name": {
|
||||||
"_Type": "Ident",
|
"_Type": "Ident",
|
||||||
"Name": "MyUnion"
|
"Name": "MyUnion"
|
||||||
@@ -642,52 +576,6 @@ TestTypeDefDecl Case 9:
|
|||||||
},
|
},
|
||||||
"Doc": null,
|
"Doc": null,
|
||||||
"Parent": null,
|
"Parent": null,
|
||||||
"Name": null,
|
|
||||||
"Type": {
|
|
||||||
"_Type": "EnumType",
|
|
||||||
"Items": [{
|
|
||||||
"_Type": "EnumItem",
|
|
||||||
"Name": {
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "RED"
|
|
||||||
},
|
|
||||||
"Value": {
|
|
||||||
"_Type": "BasicLit",
|
|
||||||
"Kind": 0,
|
|
||||||
"Value": "0"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"_Type": "EnumItem",
|
|
||||||
"Name": {
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "GREEN"
|
|
||||||
},
|
|
||||||
"Value": {
|
|
||||||
"_Type": "BasicLit",
|
|
||||||
"Kind": 0,
|
|
||||||
"Value": "1"
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"_Type": "EnumItem",
|
|
||||||
"Name": {
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "BLUE"
|
|
||||||
},
|
|
||||||
"Value": {
|
|
||||||
"_Type": "BasicLit",
|
|
||||||
"Kind": 0,
|
|
||||||
"Value": "2"
|
|
||||||
}
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"_Type": "TypedefDecl",
|
|
||||||
"Loc": {
|
|
||||||
"_Type": "Location",
|
|
||||||
"File": "temp.h"
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Parent": null,
|
|
||||||
"Name": {
|
"Name": {
|
||||||
"_Type": "Ident",
|
"_Type": "Ident",
|
||||||
"Name": "MyEnum"
|
"Name": "MyEnum"
|
||||||
@@ -747,39 +635,6 @@ TestTypeDefDecl Case 10:
|
|||||||
},
|
},
|
||||||
"Doc": null,
|
"Doc": null,
|
||||||
"Parent": null,
|
"Parent": null,
|
||||||
"Name": null,
|
|
||||||
"Type": {
|
|
||||||
"_Type": "RecordType",
|
|
||||||
"Tag": 0,
|
|
||||||
"Fields": {
|
|
||||||
"_Type": "FieldList",
|
|
||||||
"List": [{
|
|
||||||
"_Type": "Field",
|
|
||||||
"Type": {
|
|
||||||
"_Type": "BuiltinType",
|
|
||||||
"Kind": 6,
|
|
||||||
"Flags": 0
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Comment": null,
|
|
||||||
"IsStatic": false,
|
|
||||||
"Access": 1,
|
|
||||||
"Names": [{
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "x"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"Methods": []
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"_Type": "TypedefDecl",
|
|
||||||
"Loc": {
|
|
||||||
"_Type": "Location",
|
|
||||||
"File": "temp.h"
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Parent": null,
|
|
||||||
"Name": {
|
"Name": {
|
||||||
"_Type": "Ident",
|
"_Type": "Ident",
|
||||||
"Name": "MyStruct"
|
"Name": "MyStruct"
|
||||||
@@ -821,28 +676,12 @@ TestTypeDefDecl Case 10:
|
|||||||
"Name": "MyStruct2"
|
"Name": "MyStruct2"
|
||||||
},
|
},
|
||||||
"Type": {
|
"Type": {
|
||||||
"_Type": "RecordType",
|
"_Type": "TagExpr",
|
||||||
"Tag": 0,
|
"Name": {
|
||||||
"Fields": {
|
"_Type": "Ident",
|
||||||
"_Type": "FieldList",
|
"Name": "MyStruct"
|
||||||
"List": [{
|
|
||||||
"_Type": "Field",
|
|
||||||
"Type": {
|
|
||||||
"_Type": "BuiltinType",
|
|
||||||
"Kind": 6,
|
|
||||||
"Flags": 0
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Comment": null,
|
|
||||||
"IsStatic": false,
|
|
||||||
"Access": 1,
|
|
||||||
"Names": [{
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "x"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"Methods": []
|
"Tag": 0
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"_Type": "TypedefDecl",
|
"_Type": "TypedefDecl",
|
||||||
@@ -859,28 +698,12 @@ TestTypeDefDecl Case 10:
|
|||||||
"Type": {
|
"Type": {
|
||||||
"_Type": "PointerType",
|
"_Type": "PointerType",
|
||||||
"X": {
|
"X": {
|
||||||
"_Type": "RecordType",
|
"_Type": "TagExpr",
|
||||||
"Tag": 0,
|
"Name": {
|
||||||
"Fields": {
|
"_Type": "Ident",
|
||||||
"_Type": "FieldList",
|
"Name": "MyStruct"
|
||||||
"List": [{
|
|
||||||
"_Type": "Field",
|
|
||||||
"Type": {
|
|
||||||
"_Type": "BuiltinType",
|
|
||||||
"Kind": 6,
|
|
||||||
"Flags": 0
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Comment": null,
|
|
||||||
"IsStatic": false,
|
|
||||||
"Access": 1,
|
|
||||||
"Names": [{
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "x"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"Methods": []
|
"Tag": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@@ -898,28 +721,12 @@ TestTypeDefDecl Case 10:
|
|||||||
"Type": {
|
"Type": {
|
||||||
"_Type": "ArrayType",
|
"_Type": "ArrayType",
|
||||||
"Elt": {
|
"Elt": {
|
||||||
"_Type": "RecordType",
|
"_Type": "TagExpr",
|
||||||
"Tag": 0,
|
"Name": {
|
||||||
"Fields": {
|
"_Type": "Ident",
|
||||||
"_Type": "FieldList",
|
"Name": "MyStruct"
|
||||||
"List": [{
|
|
||||||
"_Type": "Field",
|
|
||||||
"Type": {
|
|
||||||
"_Type": "BuiltinType",
|
|
||||||
"Kind": 6,
|
|
||||||
"Flags": 0
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Comment": null,
|
|
||||||
"IsStatic": false,
|
|
||||||
"Access": 1,
|
|
||||||
"Names": [{
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "x"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"Methods": []
|
"Tag": 0
|
||||||
},
|
},
|
||||||
"Len": null
|
"Len": null
|
||||||
}
|
}
|
||||||
@@ -930,6 +737,132 @@ TestTypeDefDecl Case 10:
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestTypeDefDecl Case 11:
|
TestTypeDefDecl Case 11:
|
||||||
|
{
|
||||||
|
"temp.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "EnumTypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "MyEnum"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "EnumType",
|
||||||
|
"Items": [{
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "RED"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "0"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "GREEN"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "1"
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "EnumItem",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "BLUE"
|
||||||
|
},
|
||||||
|
"Value": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "2"
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "TypedefDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "MyEnum2"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "TagExpr",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "MyEnum"
|
||||||
|
},
|
||||||
|
"Tag": 2
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "TypedefDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "EnumPtr"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "PointerType",
|
||||||
|
"X": {
|
||||||
|
"_Type": "TagExpr",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "MyEnum"
|
||||||
|
},
|
||||||
|
"Tag": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, {
|
||||||
|
"_Type": "TypedefDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "temp.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "EnumArr"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "ArrayType",
|
||||||
|
"Elt": {
|
||||||
|
"_Type": "TagExpr",
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "MyEnum"
|
||||||
|
},
|
||||||
|
"Tag": 2
|
||||||
|
},
|
||||||
|
"Len": null
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [],
|
||||||
|
"macros": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TestTypeDefDecl Case 12:
|
||||||
{
|
{
|
||||||
"temp.h": {
|
"temp.h": {
|
||||||
"_Type": "File",
|
"_Type": "File",
|
||||||
@@ -951,49 +884,6 @@ TestTypeDefDecl Case 11:
|
|||||||
"Name": "A"
|
"Name": "A"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Name": null,
|
|
||||||
"Type": {
|
|
||||||
"_Type": "RecordType",
|
|
||||||
"Tag": 0,
|
|
||||||
"Fields": {
|
|
||||||
"_Type": "FieldList",
|
|
||||||
"List": [{
|
|
||||||
"_Type": "Field",
|
|
||||||
"Type": {
|
|
||||||
"_Type": "BuiltinType",
|
|
||||||
"Kind": 6,
|
|
||||||
"Flags": 0
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Comment": null,
|
|
||||||
"IsStatic": false,
|
|
||||||
"Access": 1,
|
|
||||||
"Names": [{
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "x"
|
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
"Methods": []
|
|
||||||
}
|
|
||||||
}, {
|
|
||||||
"_Type": "TypedefDecl",
|
|
||||||
"Loc": {
|
|
||||||
"_Type": "Location",
|
|
||||||
"File": "temp.h"
|
|
||||||
},
|
|
||||||
"Doc": null,
|
|
||||||
"Parent": {
|
|
||||||
"_Type": "ScopingExpr",
|
|
||||||
"X": {
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "B"
|
|
||||||
},
|
|
||||||
"Parent": {
|
|
||||||
"_Type": "Ident",
|
|
||||||
"Name": "A"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"Name": {
|
"Name": {
|
||||||
"_Type": "Ident",
|
"_Type": "Ident",
|
||||||
"Name": "MyStruct"
|
"Name": "MyStruct"
|
||||||
@@ -1045,28 +935,26 @@ TestTypeDefDecl Case 11:
|
|||||||
"Name": "MyStruct2"
|
"Name": "MyStruct2"
|
||||||
},
|
},
|
||||||
"Type": {
|
"Type": {
|
||||||
"_Type": "RecordType",
|
"_Type": "TagExpr",
|
||||||
"Tag": 0,
|
"Name": {
|
||||||
"Fields": {
|
"_Type": "ScopingExpr",
|
||||||
"_Type": "FieldList",
|
"X": {
|
||||||
"List": [{
|
"_Type": "Ident",
|
||||||
"_Type": "Field",
|
"Name": "MyStruct"
|
||||||
"Type": {
|
},
|
||||||
"_Type": "BuiltinType",
|
"Parent": {
|
||||||
"Kind": 6,
|
"_Type": "ScopingExpr",
|
||||||
"Flags": 0
|
"X": {
|
||||||
},
|
"_Type": "Ident",
|
||||||
"Doc": null,
|
"Name": "B"
|
||||||
"Comment": null,
|
},
|
||||||
"IsStatic": false,
|
"Parent": {
|
||||||
"Access": 1,
|
"_Type": "Ident",
|
||||||
"Names": [{
|
"Name": "A"
|
||||||
"_Type": "Ident",
|
}
|
||||||
"Name": "x"
|
}
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"Methods": []
|
"Tag": 0
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"_Type": "TypedefDecl",
|
"_Type": "TypedefDecl",
|
||||||
@@ -1093,28 +981,26 @@ TestTypeDefDecl Case 11:
|
|||||||
"Type": {
|
"Type": {
|
||||||
"_Type": "PointerType",
|
"_Type": "PointerType",
|
||||||
"X": {
|
"X": {
|
||||||
"_Type": "RecordType",
|
"_Type": "TagExpr",
|
||||||
"Tag": 0,
|
"Name": {
|
||||||
"Fields": {
|
"_Type": "ScopingExpr",
|
||||||
"_Type": "FieldList",
|
"X": {
|
||||||
"List": [{
|
"_Type": "Ident",
|
||||||
"_Type": "Field",
|
"Name": "MyStruct"
|
||||||
"Type": {
|
},
|
||||||
"_Type": "BuiltinType",
|
"Parent": {
|
||||||
"Kind": 6,
|
"_Type": "ScopingExpr",
|
||||||
"Flags": 0
|
"X": {
|
||||||
},
|
"_Type": "Ident",
|
||||||
"Doc": null,
|
"Name": "B"
|
||||||
"Comment": null,
|
},
|
||||||
"IsStatic": false,
|
"Parent": {
|
||||||
"Access": 1,
|
"_Type": "Ident",
|
||||||
"Names": [{
|
"Name": "A"
|
||||||
"_Type": "Ident",
|
}
|
||||||
"Name": "x"
|
}
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"Methods": []
|
"Tag": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
@@ -1142,28 +1028,26 @@ TestTypeDefDecl Case 11:
|
|||||||
"Type": {
|
"Type": {
|
||||||
"_Type": "ArrayType",
|
"_Type": "ArrayType",
|
||||||
"Elt": {
|
"Elt": {
|
||||||
"_Type": "RecordType",
|
"_Type": "TagExpr",
|
||||||
"Tag": 0,
|
"Name": {
|
||||||
"Fields": {
|
"_Type": "ScopingExpr",
|
||||||
"_Type": "FieldList",
|
"X": {
|
||||||
"List": [{
|
"_Type": "Ident",
|
||||||
"_Type": "Field",
|
"Name": "MyStruct"
|
||||||
"Type": {
|
},
|
||||||
"_Type": "BuiltinType",
|
"Parent": {
|
||||||
"Kind": 6,
|
"_Type": "ScopingExpr",
|
||||||
"Flags": 0
|
"X": {
|
||||||
},
|
"_Type": "Ident",
|
||||||
"Doc": null,
|
"Name": "B"
|
||||||
"Comment": null,
|
},
|
||||||
"IsStatic": false,
|
"Parent": {
|
||||||
"Access": 1,
|
"_Type": "Ident",
|
||||||
"Names": [{
|
"Name": "A"
|
||||||
"_Type": "Ident",
|
}
|
||||||
"Name": "x"
|
}
|
||||||
}]
|
|
||||||
}]
|
|
||||||
},
|
},
|
||||||
"Methods": []
|
"Tag": 0
|
||||||
},
|
},
|
||||||
"Len": null
|
"Len": null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,12 @@ func TestTypeDefDecl() {
|
|||||||
int x;
|
int x;
|
||||||
} MyStruct,MyStruct2,*StructPtr, StructArr[];`,
|
} MyStruct,MyStruct2,*StructPtr, StructArr[];`,
|
||||||
|
|
||||||
|
`typedef enum {
|
||||||
|
RED,
|
||||||
|
GREEN,
|
||||||
|
BLUE
|
||||||
|
} MyEnum,MyEnum2,*EnumPtr,EnumArr[];`,
|
||||||
|
|
||||||
`namespace A{
|
`namespace A{
|
||||||
namespace B{
|
namespace B{
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -118,6 +118,113 @@ TestInclude Case 1:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestMacroExpansionOtherFile:
|
||||||
|
{
|
||||||
|
"./testdata/macroexpan/ref.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [{
|
||||||
|
"_Type": "TypeDecl",
|
||||||
|
"Loc": {
|
||||||
|
"_Type": "Location",
|
||||||
|
"File": "./testdata/macroexpan/ref.h"
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Parent": null,
|
||||||
|
"Name": {
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "NewType"
|
||||||
|
},
|
||||||
|
"Type": {
|
||||||
|
"_Type": "RecordType",
|
||||||
|
"Tag": 0,
|
||||||
|
"Fields": {
|
||||||
|
"_Type": "FieldList",
|
||||||
|
"List": [{
|
||||||
|
"_Type": "Field",
|
||||||
|
"Type": {
|
||||||
|
"_Type": "ArrayType",
|
||||||
|
"Elt": {
|
||||||
|
"_Type": "BuiltinType",
|
||||||
|
"Kind": 6,
|
||||||
|
"Flags": 0
|
||||||
|
},
|
||||||
|
"Len": {
|
||||||
|
"_Type": "BasicLit",
|
||||||
|
"Kind": 0,
|
||||||
|
"Value": "2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Doc": null,
|
||||||
|
"Comment": null,
|
||||||
|
"IsStatic": false,
|
||||||
|
"Access": 1,
|
||||||
|
"Names": [{
|
||||||
|
"_Type": "Ident",
|
||||||
|
"Name": "__val"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
"Methods": []
|
||||||
|
}
|
||||||
|
}],
|
||||||
|
"includes": [{
|
||||||
|
"_Type": "Include",
|
||||||
|
"Path": "def.h"
|
||||||
|
}],
|
||||||
|
"macros": []
|
||||||
|
},
|
||||||
|
"./testdata/macroexpan/def.h": {
|
||||||
|
"_Type": "File",
|
||||||
|
"decls": [],
|
||||||
|
"includes": [],
|
||||||
|
"macros": [{
|
||||||
|
"_Type": "Macro",
|
||||||
|
"Name": "__FSID_T_TYPE",
|
||||||
|
"Tokens": [{
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 3,
|
||||||
|
"Lit": "__FSID_T_TYPE"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 2,
|
||||||
|
"Lit": "struct"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": "{"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 2,
|
||||||
|
"Lit": "int"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 3,
|
||||||
|
"Lit": "__val"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": "["
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 4,
|
||||||
|
"Lit": "2"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": "]"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": ";"
|
||||||
|
}, {
|
||||||
|
"_Type": "Token",
|
||||||
|
"Token": 1,
|
||||||
|
"Lit": "}"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#stderr
|
#stderr
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/goplus/llgo/c"
|
||||||
test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
test "github.com/goplus/llgo/chore/_xtool/llcppsigfetch/parse/cvt_test"
|
||||||
|
"github.com/goplus/llgo/chore/_xtool/llcppsymg/clangutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
TestDefine()
|
TestDefine()
|
||||||
TestInclude()
|
TestInclude()
|
||||||
|
TestMacroExpansionOtherFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefine() {
|
func TestDefine() {
|
||||||
@@ -25,3 +28,12 @@ func TestInclude() {
|
|||||||
}
|
}
|
||||||
test.RunTest("TestInclude", testCases)
|
test.RunTest("TestInclude", testCases)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMacroExpansionOtherFile() {
|
||||||
|
c.Printf(c.Str("TestMacroExpansionOtherFile:\n"))
|
||||||
|
test.RunTestWithConfig(&clangutils.Config{
|
||||||
|
File: "./testdata/macroexpan/ref.h",
|
||||||
|
Temp: false,
|
||||||
|
IsCpp: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
4
chore/_xtool/llcppsigfetch/parse/cvt_test/preprocess_test/testdata/macroexpan/def.h
vendored
Normal file
4
chore/_xtool/llcppsigfetch/parse/cvt_test/preprocess_test/testdata/macroexpan/def.h
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#define __FSID_T_TYPE \
|
||||||
|
struct { \
|
||||||
|
int __val[2]; \
|
||||||
|
}
|
||||||
2
chore/_xtool/llcppsigfetch/parse/cvt_test/preprocess_test/testdata/macroexpan/ref.h
vendored
Normal file
2
chore/_xtool/llcppsigfetch/parse/cvt_test/preprocess_test/testdata/macroexpan/ref.h
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#include "def.h"
|
||||||
|
typedef __FSID_T_TYPE NewType;
|
||||||
Reference in New Issue
Block a user