Update to latest Clang AST spec.

This commit is contained in:
Greg 2021-06-11 11:24:25 -04:00
parent 0bc23404da
commit f4a9dae250
16 changed files with 345 additions and 6 deletions

View File

@ -5,6 +5,7 @@ type AsmLabelAttr struct {
Addr Address
Pos Position
Inherited bool
LiteralLabel bool
FunctionName string
ChildNodes []Node
}
@ -13,7 +14,8 @@ func parseAsmLabelAttr(line string) Node {
groups := groupsFromRegex(
`<(?P<position>.*)>
(?P<inherited> Inherited)?
"(?P<function>.+)"`,
"(?P<function>.+)"
(?P<isliterallabel> IsLiteralLabel)?`,
line,
)
if groups == nil {
@ -24,6 +26,7 @@ func parseAsmLabelAttr(line string) Node {
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Inherited: len(groups["inherited"]) > 0,
LiteralLabel: len(groups["isliterallabel"]) > 0,
FunctionName: groups["function"],
ChildNodes: []Node{},
}

View File

@ -10,6 +10,7 @@ func TestAsmLabelAttr(t *testing.T) {
Addr: 0x7ff26d8224e8,
Pos: NewPositionFromString("/usr/include/sys/cdefs.h:569:36"),
Inherited: false,
LiteralLabel: false,
FunctionName: "_fopen",
ChildNodes: []Node{},
},
@ -21,6 +22,7 @@ func TestAsmLabelAttr(t *testing.T) {
Addr: 0x7fd55a169318,
Pos: NewPositionFromString("/usr/include/stdio.h:325:47"),
Inherited: true,
LiteralLabel: false,
FunctionName: "_popen",
ChildNodes: []Node{},
},
@ -28,6 +30,18 @@ func TestAsmLabelAttr(t *testing.T) {
NewPositionFromString("/usr/include/stdio.h:325:47"),
[]Node{},
},
`0x7fd55a169318 </usr/include/stdio.h:325:47> "_kill" IsLiteralLabel`: testNode{&AsmLabelAttr{
Addr: 0x7fd55a169318,
Pos: NewPositionFromString("/usr/include/stdio.h:325:47"),
Inherited: false,
LiteralLabel: true,
FunctionName: "_kill",
ChildNodes: []Node{},
},
0x7fd55a169318,
NewPositionFromString("/usr/include/stdio.h:325:47"),
[]Node{},
},
}
runNodeTests(t, nodes)

View File

@ -93,6 +93,8 @@ func Parse(fullline string) Node {
return parseBuiltinType(line)
case "CallExpr":
return parseCallExpr(line)
case "ConstantExpr":
return parseConstantExpr(line)
case "ConvertVectorExpr":
return parseConvertVectorExpr(line)
case "CaseStmt":
@ -107,6 +109,8 @@ func Parse(fullline string) Node {
return parseCFReturnsNotRetainedAttr(line)
case "CharacterLiteral":
return parseCharacterLiteral(line)
case "ColdAttr":
return parseColdAttr(line)
case "CompoundLiteralExpr":
return parseCompoundLiteralExpr(line)
case "CompoundStmt":
@ -285,6 +289,8 @@ func Parse(fullline string) Node {
return parseObjCRootClassAttr(line)
case "ObjCPropertyDecl":
return parseObjCPropertyDecl(line)
case "ObjCTypeParam":
return parseObjCTypeParam(line)
case "ObjCTypeParamDecl":
return parseObjCTypeParamDecl(line)
case "OffsetOfExpr":

View File

@ -9,6 +9,7 @@ type AvailabilityAttr struct {
Version string
Unknown1 string
Unknown2 string
Unknown3 string
IsUnavailable bool
Message1 string
Message2 string
@ -26,7 +27,7 @@ func parseAvailabilityAttr(line string) Node {
(?P<unknown2>[\d_.]+)
(?P<unavalable> Unavailable)?
"(?P<message1>.*?)"
(?P<message2> ".*?")?`,
(?P<message2> ".*?")?( (?P<unknown3>[\d_.]+))?`,
line,
)
if groups == nil {
@ -40,6 +41,7 @@ func parseAvailabilityAttr(line string) Node {
Version: groups["version"],
Unknown1: groups["unknown1"],
Unknown2: groups["unknown2"],
Unknown3: groups["unknown3"],
IsUnavailable: len(groups["unavalable"]) > 0,
Message1: removeQuotes(groups["message1"]),
Message2: removeQuotes(groups["message2"]),

View File

@ -13,6 +13,7 @@ func TestAvailabilityAttr(t *testing.T) {
Version: "10.10",
Unknown1: "0",
Unknown2: "0",
Unknown3: "",
IsUnavailable: false,
Message1: "",
Message2: "",
@ -30,6 +31,7 @@ func TestAvailabilityAttr(t *testing.T) {
Version: "3.0",
Unknown1: "0",
Unknown2: "0",
Unknown3: "",
IsUnavailable: false,
Message1: "",
Message2: "",
@ -47,6 +49,7 @@ func TestAvailabilityAttr(t *testing.T) {
Version: "10.0",
Unknown1: "0",
Unknown2: "0",
Unknown3: "",
IsUnavailable: false,
Message1: "",
Message2: "",
@ -64,6 +67,7 @@ func TestAvailabilityAttr(t *testing.T) {
Version: "10.0",
Unknown1: "0",
Unknown2: "0",
Unknown3: "",
IsUnavailable: false,
Message1: "",
Message2: "",
@ -81,6 +85,7 @@ func TestAvailabilityAttr(t *testing.T) {
Version: "0",
Unknown1: "0",
Unknown2: "0",
Unknown3: "",
IsUnavailable: true,
Message1: "Use snprintf instead.",
Message2: "",
@ -98,6 +103,7 @@ func TestAvailabilityAttr(t *testing.T) {
Version: "0",
Unknown1: "0",
Unknown2: "0",
Unknown3: "",
IsUnavailable: true,
Message1: "Use mkstemp(3) instead.",
Message2: "",
@ -115,6 +121,7 @@ func TestAvailabilityAttr(t *testing.T) {
Version: "10.10",
Unknown1: "0",
Unknown2: "0",
Unknown3: "",
IsUnavailable: false,
Message1: "",
Message2: "",
@ -132,6 +139,25 @@ func TestAvailabilityAttr(t *testing.T) {
Version: "10.5",
Unknown1: "0",
Unknown2: "0",
Unknown3: "",
IsUnavailable: false,
Message1: "",
Message2: "",
IsInherited: true,
ChildNodes: []Node{},
},
0x7f9bd588b1a8,
NewPositionFromString("/usr/include/gethostuuid.h:39:65, col:100"),
[]Node{},
},
`0x7f9bd588b1a8 </usr/include/gethostuuid.h:39:65, col:100> Inherited macos 10.5 0 0 "" "" 1`: testNode{&AvailabilityAttr{
Addr: 0x7f9bd588b1a8,
Pos: NewPositionFromString("/usr/include/gethostuuid.h:39:65, col:100"),
OS: "macos",
Version: "10.5",
Unknown1: "0",
Unknown2: "0",
Unknown3: "1",
IsUnavailable: false,
Message1: "",
Message2: "",

48
ast/cold_attr.go Normal file
View File

@ -0,0 +1,48 @@
package ast
// ColdAttr is a type of attribute that is optionally attached to function
// declaration.
type ColdAttr struct {
Addr Address
Pos Position
ChildNodes []Node
}
func parseColdAttr(line string) Node {
groups := groupsFromRegex(
"<(?P<position>.*)>",
line,
)
if groups == nil {
return &Unknown{}
}
return &ColdAttr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ColdAttr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *ColdAttr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ColdAttr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ColdAttr) Position() Position {
return n.Pos
}

21
ast/cold_attr_test.go Normal file
View File

@ -0,0 +1,21 @@
package ast
import (
"testing"
)
func TestColdAttr(t *testing.T) {
nodes := map[string]testNode{
`0x7fc8fa094558 <col:107>`: testNode{&ColdAttr{
Addr: 0x7fc8fa094558,
Pos: NewPositionFromString("col:107"),
ChildNodes: []Node{},
},
0x7fc8fa094558,
NewPositionFromString("col:107"),
[]Node{},
},
}
runNodeTests(t, nodes)
}

53
ast/constant_expr.go Normal file
View File

@ -0,0 +1,53 @@
package ast
// ConstantExpr is expression.
type ConstantExpr struct {
Addr Address
Pos Position
Type string
Type2 string
Extra string
ChildNodes []Node
}
func parseConstantExpr(line string) Node {
groups := groupsFromRegex(
`<(?P<position>.*)> '(?P<type>[\w ]+)'(:'(?P<type2>[\w ]+)')?( .*)?`,
line,
)
if groups == nil {
return &Unknown{}
}
return &ConstantExpr{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
Type: groups["type"],
Type2: groups["type2"],
Extra: groups["extra"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ConstantExpr) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *ConstantExpr) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ConstantExpr) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ConstantExpr) Position() Position {
return n.Pos
}

64
ast/constant_expr_test.go Normal file
View File

@ -0,0 +1,64 @@
package ast
import (
"testing"
)
func TestConstantExpr(t *testing.T) {
nodes := map[string]testNode{
`0x7f9bf3033240 <col:11, col:25> 'int'`: testNode{&ConstantExpr{
Addr: 0x7f9bf3033240,
Pos: NewPositionFromString("col:11, col:25"),
Type: "int",
ChildNodes: []Node{},
},
0x7f9bf3033240,
NewPositionFromString("col:11, col:25"),
[]Node{},
},
`0x7f9bf3035c20 <line:7:4, col:64> 'int'`: testNode{&ConstantExpr{
Addr: 0x7f9bf3035c20,
Pos: NewPositionFromString("line:7:4, col:64"),
Type: "int",
ChildNodes: []Node{},
},
0x7f9bf3035c20,
NewPositionFromString("line:7:4, col:64"),
[]Node{},
},
`0x7f9bf3035c20 <line:7:4, col:64> 'unsigned int'`: testNode{&ConstantExpr{
Addr: 0x7f9bf3035c20,
Pos: NewPositionFromString("line:7:4, col:64"),
Type: "unsigned int",
ChildNodes: []Node{},
},
0x7f9bf3035c20,
NewPositionFromString("line:7:4, col:64"),
[]Node{},
},
`0x7f9bf3035c20 <line:7:4, col:64> 'NSModalResponse':'long' Int: 1`: testNode{&ConstantExpr{
Addr: 0x7f9bf3035c20,
Pos: NewPositionFromString("line:7:4, col:64"),
Type: "NSModalResponse",
Type2: "long",
ChildNodes: []Node{},
},
0x7f9bf3035c20,
NewPositionFromString("line:7:4, col:64"),
[]Node{},
},
`0x7f9bf3035c20 <line:7:4, col:64> 'NSModalResponse':'unsigned long' Int: 1`: testNode{&ConstantExpr{
Addr: 0x7f9bf3035c20,
Pos: NewPositionFromString("line:7:4, col:64"),
Type: "NSModalResponse",
Type2: "unsigned long",
ChildNodes: []Node{},
},
0x7f9bf3035c20,
NewPositionFromString("line:7:4, col:64"),
[]Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -4,12 +4,13 @@ package ast
type IfStmt struct {
Addr Address
Pos Position
HasElse bool
ChildNodes []Node
}
func parseIfStmt(line string) Node {
groups := groupsFromRegex(
"<(?P<position>.*)>",
"<(?P<position>.*)>(?P<has_else> has_else)?",
line,
)
if groups == nil {
@ -19,6 +20,7 @@ func parseIfStmt(line string) Node {
return &IfStmt{
Addr: ParseAddress(groups["address"]),
Pos: NewPositionFromString(groups["position"]),
HasElse: len(groups["has_else"]) > 0,
ChildNodes: []Node{},
}
}

View File

@ -8,6 +8,17 @@ func TestIfStmt(t *testing.T) {
nodes := map[string]testNode{
`0x7fc0a69091d0 <line:11:7, line:18:7>`: testNode{&IfStmt{
Addr: 0x7fc0a69091d0,
HasElse: false,
Pos: NewPositionFromString("line:11:7, line:18:7"),
ChildNodes: []Node{},
},
0x7fc0a69091d0,
NewPositionFromString("line:11:7, line:18:7"),
[]Node{},
},
`0x7fc0a69091d0 <line:11:7, line:18:7> has_else`: testNode{&IfStmt{
Addr: 0x7fc0a69091d0,
HasElse: true,
Pos: NewPositionFromString("line:11:7, line:18:7"),
ChildNodes: []Node{},
},

47
ast/objc_type_param.go Normal file
View File

@ -0,0 +1,47 @@
package ast
// ObjCTypeParam is expression.
type ObjCTypeParam struct {
Addr Address
Type string
ChildNodes []Node
}
func parseObjCTypeParam(line string) Node {
groups := groupsFromRegex(
"'(?P<type>.*?)'",
line,
)
if groups == nil {
return &Unknown{}
}
return &ObjCTypeParam{
Addr: ParseAddress(groups["address"]),
Type: groups["type"],
ChildNodes: []Node{},
}
}
// AddChild adds a new child node. Child nodes can then be accessed with the
// Children attribute.
func (n *ObjCTypeParam) AddChild(node Node) {
n.ChildNodes = append(n.ChildNodes, node)
}
// Address returns the numeric address of the node. See the documentation for
// the Address type for more information.
func (n *ObjCTypeParam) Address() Address {
return n.Addr
}
// Children returns the child nodes. If this node does not have any children or
// this node does not support children it will always return an empty slice.
func (n *ObjCTypeParam) Children() []Node {
return n.ChildNodes
}
// Position returns the position in the original source code.
func (n *ObjCTypeParam) Position() Position {
return Position{}
}

View File

@ -0,0 +1,30 @@
package ast
import (
"testing"
)
func TestObjCTypeParam(t *testing.T) {
nodes := map[string]testNode{
`0x7f9bf3033240 'int'`: testNode{&ObjCTypeParam{
Addr: 0x7f9bf3033240,
Type: "int",
ChildNodes: []Node{},
},
0x7f9bf3033240,
Position{},
[]Node{},
},
`0x7f9bf3035c20 'unsigned int'`: testNode{&ObjCTypeParam{
Addr: 0x7f9bf3035c20,
Type: "unsigned int",
ChildNodes: []Node{},
},
0x7f9bf3035c20,
Position{},
[]Node{},
},
}
runNodeTests(t, nodes)
}

View File

@ -5,11 +5,12 @@ package ast
type WarnUnusedResultAttr struct {
Addr Address
Pos Position
Text string
ChildNodes []Node
}
func parseWarnUnusedResultAttr(line string) Node {
groups := groupsFromRegex(`<(?P<position>.*)>( warn_unused_result)?`, line)
groups := groupsFromRegex(`<(?P<position>.*)>( warn_unused_result)?( ".*")?`, line)
if groups == nil {
return &Unknown{}
}

View File

@ -24,6 +24,15 @@ func TestWarnUnusedResultAttr(t *testing.T) {
NewPositionFromString("line:481:52"),
[]Node{},
},
`0x1fac810 <line:481:52> warn_unused_result ""`: testNode{&WarnUnusedResultAttr{
Addr: 0x1fac810,
Pos: NewPositionFromString("line:481:52"),
ChildNodes: []Node{},
},
0x1fac810,
NewPositionFromString("line:481:52"),
[]Node{},
},
}
runNodeTests(t, nodes)

View File

@ -716,7 +716,7 @@ func (w *Wrapper) addIntCat(name string, ns []ast.Node) {
}
case *ast.ObjCRootClassAttr, *ast.VisibilityAttr,
*ast.ObjCIvarDecl, *ast.ArcWeakrefUnavailableAttr,
*ast.ObjCExceptionAttr:
*ast.ObjCExceptionAttr, *ast.SwiftNameAttr:
default:
fmt.Printf("AST parse error: node type is %s\n", reflect.TypeOf(x).String())
}
@ -1388,7 +1388,9 @@ func (w *Wrapper) MethodFromSig(sig, class string) *Method {
}
sig = sig[1:]
rem, n := types.MethodSignature(sig, types.NewNode("AST"))
if Debug { fmt.Println(n.String()) }
if Debug {
fmt.Println(n.String())
}
if len(rem) > 0 {
fmt.Printf("Failed to parse method signature %s (%s)\n", sig, rem)
os.Exit(-1)