llcppsigfetch:unexpect typedef record type's named anonymous record decl resolve to normal anonymous record refer

This commit is contained in:
luoliwoshang
2024-09-06 17:27:00 +08:00
parent b9aaba7b16
commit b369321e2f
2 changed files with 268 additions and 174 deletions

View File

@@ -40,7 +40,7 @@ type Converter struct {
// //
// Example: // Example:
// typedef struct { int x; } MyStruct; // typedef struct { int x; } MyStruct;
anonyTypeMap map[string]string // cursorUsr -> anonyname anonyTypeMap map[string]bool // cursorUsr
} }
var tagMap = map[string]ast.Tag{ var tagMap = map[string]ast.Tag{
@@ -67,7 +67,7 @@ func NewConverter(config *Config) (*Converter, error) {
Files: make(map[string]*ast.File), Files: make(map[string]*ast.File),
index: index, index: index,
unit: unit, unit: unit,
anonyTypeMap: make(map[string]string), anonyTypeMap: make(map[string]bool),
typeDecls: make(map[string]ast.Decl), typeDecls: make(map[string]ast.Decl),
}, nil }, nil
} }
@@ -181,19 +181,19 @@ func (ct *Converter) GetCurFile() *ast.File {
return file return file
} }
func (ct *Converter) SetAnonyType(cursor clang.Cursor, anonyname string) { func (ct *Converter) SetAnonyType(cursor clang.Cursor) {
usr := cursor.USR() usr := cursor.USR()
usrStr := c.GoString(usr.CStr()) usrStr := c.GoString(usr.CStr())
defer usr.Dispose() defer usr.Dispose()
ct.anonyTypeMap[usrStr] = anonyname ct.anonyTypeMap[usrStr] = true
} }
func (ct *Converter) GetAnonyType(cursor clang.Cursor) (string, bool) { func (ct *Converter) GetAnonyType(cursor clang.Cursor) (bool, bool) {
usr := cursor.USR() usr := cursor.USR()
usrStr := c.GoString(usr.CStr()) usrStr := c.GoString(usr.CStr())
defer usr.Dispose() defer usr.Dispose()
anonyname, ok := ct.anonyTypeMap[usrStr] isAnony, ok := ct.anonyTypeMap[usrStr]
return anonyname, ok return isAnony, ok
} }
func (ct *Converter) SetTypeDecl(cursor clang.Cursor, decl ast.Decl) { func (ct *Converter) SetTypeDecl(cursor clang.Cursor, decl ast.Decl) {
@@ -379,7 +379,6 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr {
return ct.ProcessType(underlyingTyp) return ct.ProcessType(underlyingTyp)
} }
typ := ct.ProcessElaboratedType(underlyingTyp)
referTypeCursor := underlyingTyp.TypeDeclaration() referTypeCursor := underlyingTyp.TypeDeclaration()
// If the type decl for the reference already exists in anonyTypeMap // If the type decl for the reference already exists in anonyTypeMap
@@ -389,19 +388,17 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr {
// In this case, libclang incorrectly reports an anonymous struct as a named struct // In this case, libclang incorrectly reports an anonymous struct as a named struct
sourceCode := ct.GetTokens(referTypeCursor) sourceCode := ct.GetTokens(referTypeCursor)
if isAnonymousStructure(sourceCode) { if isAnonymousStructure(sourceCode) {
anonyName := ct.GenerateAnonymousName(referTypeCursor) ct.SetAnonyType(referTypeCursor)
// update reference's name
setInnerName(typ, anonyName)
ct.SetAnonyType(referTypeCursor, anonyName)
typ, isValidType := ct.GetTypeDecl(referTypeCursor) typ, isValidType := ct.GetTypeDecl(referTypeCursor)
if isValidType { if isValidType {
// There will be no anonymous classes,here will execute enum,union,struct // There will be no anonymous classes,here will execute enum,union,struct
// according to a normal anonymous decl
switch declType := typ.(type) { switch declType := typ.(type) {
case *ast.EnumTypeDecl: case *ast.EnumTypeDecl:
declType.Name.Name = anonyName declType.Name = nil
case *ast.TypeDecl: case *ast.TypeDecl:
if declType.Type.Tag != ast.Class { if declType.Type.Tag != ast.Class {
declType.Name.Name = anonyName declType.Name = nil
} else { } else {
// Unreachable: There should be no anonymous classes in this context // Unreachable: There should be no anonymous classes in this context
fmt.Fprintln(os.Stderr, "unexpect typedef anonymous class %s", declType.Name.Name) fmt.Fprintln(os.Stderr, "unexpect typedef anonymous class %s", declType.Name.Name)
@@ -414,12 +411,7 @@ func (ct *Converter) ProcessUnderlyingType(cursor clang.Cursor) ast.Expr {
} }
} }
return typ return ct.ProcessElaboratedType(underlyingTyp)
}
// generates a name for an anonymous structure like:__ANONY_A_B_MYSTRUCT
func (ct *Converter) GenerateAnonymousName(cursor clang.Cursor) string {
return fmt.Sprintf("__ANONY_%s", strings.Join(ct.BuildScopingParts(cursor), "_"))
} }
// converts functions, methods, constructors, destructors (including out-of-class decl) to ast.FuncDecl nodes. // converts functions, methods, constructors, destructors (including out-of-class decl) to ast.FuncDecl nodes.
@@ -730,7 +722,9 @@ func (ct *Converter) ProcessElaboratedType(t clang.Type) ast.Expr {
defer name.Dispose() defer name.Dispose()
decl := t.TypeDeclaration() decl := t.TypeDeclaration()
if decl.IsAnonymous() != 0 { isAnony, ok := ct.GetAnonyType(decl)
if decl.IsAnonymous() != 0 || isAnony && ok {
// 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)
@@ -836,17 +830,11 @@ func (ct *Converter) BuildScopingParts(cursor clang.Cursor) []string {
var parts []string var parts []string
// Traverse up the semantic parents // Traverse up the semantic parents
for cursor.IsNull() != 1 && cursor.Kind != clang.CursorTranslationUnit { for cursor.IsNull() != 1 && cursor.Kind != clang.CursorTranslationUnit {
var qualified string name := cursor.String()
// anonymous decl quote qualified := c.GoString(name.CStr())
if anonyName, ok := ct.GetAnonyType(cursor); ok {
qualified = anonyName
} else {
name := cursor.String()
qualified = c.GoString(name.CStr())
name.Dispose()
}
parts = append([]string{qualified}, parts...) parts = append([]string{qualified}, parts...)
cursor = cursor.SemanticParent() cursor = cursor.SemanticParent()
name.Dispose()
} }
return parts return parts
} }
@@ -911,18 +899,6 @@ func getOffset(location clang.SourceLocation) c.Uint {
return offset return offset
} }
// setTagName updates the name of the innermost Ident in a Name Expr
func setInnerName(expr ast.Expr, name string) {
switch e := expr.(type) {
case *ast.TagExpr:
setInnerName(e.Name, name)
case *ast.ScopingExpr:
setInnerName(e.X, name)
case *ast.Ident:
e.Name = name
}
}
// checks if the source code represents an actual anonymous structure // checks if the source code represents an actual anonymous structure
func isAnonymousStructure(sourceCode []*ast.Token) bool { func isAnonymousStructure(sourceCode []*ast.Token) bool {
_, isValidTag := tagMap[sourceCode[0].Lit] _, isValidTag := tagMap[sourceCode[0].Lit]

View File

@@ -484,10 +484,7 @@ TestTypeDefDecl Case 7:
}, },
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": null,
"_Type": "Ident",
"Name": "__ANONY_MyStruct"
},
"Type": { "Type": {
"_Type": "RecordType", "_Type": "RecordType",
"Tag": 0, "Tag": 0,
@@ -525,12 +522,28 @@ TestTypeDefDecl Case 7:
"Name": "MyStruct" "Name": "MyStruct"
}, },
"Type": { "Type": {
"_Type": "TagExpr", "_Type": "RecordType",
"Name": { "Tag": 0,
"_Type": "Ident", "Fields": {
"Name": "__ANONY_MyStruct" "_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"
}]
}]
}, },
"Tag": 0 "Methods": []
} }
}], }],
"includes": [], "includes": [],
@@ -550,10 +563,7 @@ TestTypeDefDecl Case 8:
}, },
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": null,
"_Type": "Ident",
"Name": "__ANONY_MyUnion"
},
"Type": { "Type": {
"_Type": "RecordType", "_Type": "RecordType",
"Tag": 1, "Tag": 1,
@@ -591,12 +601,28 @@ TestTypeDefDecl Case 8:
"Name": "MyUnion" "Name": "MyUnion"
}, },
"Type": { "Type": {
"_Type": "TagExpr", "_Type": "RecordType",
"Name": { "Tag": 1,
"_Type": "Ident", "Fields": {
"Name": "__ANONY_MyUnion" "_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"
}]
}]
}, },
"Tag": 1 "Methods": []
} }
}], }],
"includes": [], "includes": [],
@@ -616,10 +642,7 @@ TestTypeDefDecl Case 9:
}, },
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": null,
"_Type": "Ident",
"Name": "__ANONY_MyEnum"
},
"Type": { "Type": {
"_Type": "EnumType", "_Type": "EnumType",
"Items": [{ "Items": [{
@@ -670,12 +693,41 @@ TestTypeDefDecl Case 9:
"Name": "MyEnum" "Name": "MyEnum"
}, },
"Type": { "Type": {
"_Type": "TagExpr", "_Type": "EnumType",
"Name": { "Items": [{
"_Type": "Ident", "_Type": "EnumItem",
"Name": "__ANONY_MyEnum" "Name": {
}, "_Type": "Ident",
"Tag": 2 "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"
}
}]
} }
}], }],
"includes": [], "includes": [],
@@ -695,10 +747,7 @@ TestTypeDefDecl Case 10:
}, },
"Doc": null, "Doc": null,
"Parent": null, "Parent": null,
"Name": { "Name": null,
"_Type": "Ident",
"Name": "__ANONY_MyStruct"
},
"Type": { "Type": {
"_Type": "RecordType", "_Type": "RecordType",
"Tag": 0, "Tag": 0,
@@ -736,12 +785,28 @@ TestTypeDefDecl Case 10:
"Name": "MyStruct" "Name": "MyStruct"
}, },
"Type": { "Type": {
"_Type": "TagExpr", "_Type": "RecordType",
"Name": { "Tag": 0,
"_Type": "Ident", "Fields": {
"Name": "__ANONY_MyStruct" "_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"
}]
}]
}, },
"Tag": 0 "Methods": []
} }
}, { }, {
"_Type": "TypedefDecl", "_Type": "TypedefDecl",
@@ -756,12 +821,28 @@ TestTypeDefDecl Case 10:
"Name": "MyStruct2" "Name": "MyStruct2"
}, },
"Type": { "Type": {
"_Type": "TagExpr", "_Type": "RecordType",
"Name": { "Tag": 0,
"_Type": "Ident", "Fields": {
"Name": "__ANONY_MyStruct" "_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"
}]
}]
}, },
"Tag": 0 "Methods": []
} }
}, { }, {
"_Type": "TypedefDecl", "_Type": "TypedefDecl",
@@ -778,12 +859,28 @@ TestTypeDefDecl Case 10:
"Type": { "Type": {
"_Type": "PointerType", "_Type": "PointerType",
"X": { "X": {
"_Type": "TagExpr", "_Type": "RecordType",
"Name": { "Tag": 0,
"_Type": "Ident", "Fields": {
"Name": "__ANONY_MyStruct" "_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"
}]
}]
}, },
"Tag": 0 "Methods": []
} }
} }
}, { }, {
@@ -801,12 +898,28 @@ TestTypeDefDecl Case 10:
"Type": { "Type": {
"_Type": "ArrayType", "_Type": "ArrayType",
"Elt": { "Elt": {
"_Type": "TagExpr", "_Type": "RecordType",
"Name": { "Tag": 0,
"_Type": "Ident", "Fields": {
"Name": "__ANONY_MyStruct" "_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"
}]
}]
}, },
"Tag": 0 "Methods": []
}, },
"Len": null "Len": null
} }
@@ -838,10 +951,7 @@ TestTypeDefDecl Case 11:
"Name": "A" "Name": "A"
} }
}, },
"Name": { "Name": null,
"_Type": "Ident",
"Name": "__ANONY_A_B_MyStruct"
},
"Type": { "Type": {
"_Type": "RecordType", "_Type": "RecordType",
"Tag": 0, "Tag": 0,
@@ -889,26 +999,28 @@ TestTypeDefDecl Case 11:
"Name": "MyStruct" "Name": "MyStruct"
}, },
"Type": { "Type": {
"_Type": "TagExpr", "_Type": "RecordType",
"Name": { "Tag": 0,
"_Type": "ScopingExpr", "Fields": {
"X": { "_Type": "FieldList",
"_Type": "Ident", "List": [{
"Name": "__ANONY_A_B_MyStruct" "_Type": "Field",
}, "Type": {
"Parent": { "_Type": "BuiltinType",
"_Type": "ScopingExpr", "Kind": 6,
"X": { "Flags": 0
"_Type": "Ident", },
"Name": "B" "Doc": null,
}, "Comment": null,
"Parent": { "IsStatic": false,
"_Type": "Ident", "Access": 1,
"Name": "A" "Names": [{
} "_Type": "Ident",
} "Name": "x"
}]
}]
}, },
"Tag": 0 "Methods": []
} }
}, { }, {
"_Type": "TypedefDecl", "_Type": "TypedefDecl",
@@ -933,26 +1045,28 @@ TestTypeDefDecl Case 11:
"Name": "MyStruct2" "Name": "MyStruct2"
}, },
"Type": { "Type": {
"_Type": "TagExpr", "_Type": "RecordType",
"Name": { "Tag": 0,
"_Type": "ScopingExpr", "Fields": {
"X": { "_Type": "FieldList",
"_Type": "Ident", "List": [{
"Name": "__ANONY_A_B_MyStruct" "_Type": "Field",
}, "Type": {
"Parent": { "_Type": "BuiltinType",
"_Type": "ScopingExpr", "Kind": 6,
"X": { "Flags": 0
"_Type": "Ident", },
"Name": "B" "Doc": null,
}, "Comment": null,
"Parent": { "IsStatic": false,
"_Type": "Ident", "Access": 1,
"Name": "A" "Names": [{
} "_Type": "Ident",
} "Name": "x"
}]
}]
}, },
"Tag": 0 "Methods": []
} }
}, { }, {
"_Type": "TypedefDecl", "_Type": "TypedefDecl",
@@ -979,26 +1093,28 @@ TestTypeDefDecl Case 11:
"Type": { "Type": {
"_Type": "PointerType", "_Type": "PointerType",
"X": { "X": {
"_Type": "TagExpr", "_Type": "RecordType",
"Name": { "Tag": 0,
"_Type": "ScopingExpr", "Fields": {
"X": { "_Type": "FieldList",
"_Type": "Ident", "List": [{
"Name": "__ANONY_A_B_MyStruct" "_Type": "Field",
}, "Type": {
"Parent": { "_Type": "BuiltinType",
"_Type": "ScopingExpr", "Kind": 6,
"X": { "Flags": 0
"_Type": "Ident", },
"Name": "B" "Doc": null,
}, "Comment": null,
"Parent": { "IsStatic": false,
"_Type": "Ident", "Access": 1,
"Name": "A" "Names": [{
} "_Type": "Ident",
} "Name": "x"
}]
}]
}, },
"Tag": 0 "Methods": []
} }
} }
}, { }, {
@@ -1026,26 +1142,28 @@ TestTypeDefDecl Case 11:
"Type": { "Type": {
"_Type": "ArrayType", "_Type": "ArrayType",
"Elt": { "Elt": {
"_Type": "TagExpr", "_Type": "RecordType",
"Name": { "Tag": 0,
"_Type": "ScopingExpr", "Fields": {
"X": { "_Type": "FieldList",
"_Type": "Ident", "List": [{
"Name": "__ANONY_A_B_MyStruct" "_Type": "Field",
}, "Type": {
"Parent": { "_Type": "BuiltinType",
"_Type": "ScopingExpr", "Kind": 6,
"X": { "Flags": 0
"_Type": "Ident", },
"Name": "B" "Doc": null,
}, "Comment": null,
"Parent": { "IsStatic": false,
"_Type": "Ident", "Access": 1,
"Name": "A" "Names": [{
} "_Type": "Ident",
} "Name": "x"
}]
}]
}, },
"Tag": 0 "Methods": []
}, },
"Len": null "Len": null
} }