diff --git a/ast/asm_label_attr.go b/ast/asm_label_attr.go index 26c599a..5ae8df8 100644 --- a/ast/asm_label_attr.go +++ b/ast/asm_label_attr.go @@ -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.*)> (?P Inherited)? - "(?P.+)"`, + "(?P.+)" + (?P 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{}, } diff --git a/ast/asm_label_attr_test.go b/ast/asm_label_attr_test.go index 306779f..3399074 100644 --- a/ast/asm_label_attr_test.go +++ b/ast/asm_label_attr_test.go @@ -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 "_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) diff --git a/ast/ast.go b/ast/ast.go index 7922ddb..9f428cf 100644 --- a/ast/ast.go +++ b/ast/ast.go @@ -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": diff --git a/ast/availability_attr.go b/ast/availability_attr.go index 961d78e..4c4b796 100644 --- a/ast/availability_attr.go +++ b/ast/availability_attr.go @@ -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[\d_.]+) (?P Unavailable)? "(?P.*?)" - (?P ".*?")?`, + (?P ".*?")?( (?P[\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"]), diff --git a/ast/availability_attr_test.go b/ast/availability_attr_test.go index 70a2940..0eea971 100644 --- a/ast/availability_attr_test.go +++ b/ast/availability_attr_test.go @@ -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 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: "", diff --git a/ast/cold_attr.go b/ast/cold_attr.go new file mode 100644 index 0000000..b488566 --- /dev/null +++ b/ast/cold_attr.go @@ -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.*)>", + 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 +} diff --git a/ast/cold_attr_test.go b/ast/cold_attr_test.go new file mode 100644 index 0000000..946558c --- /dev/null +++ b/ast/cold_attr_test.go @@ -0,0 +1,21 @@ +package ast + +import ( + "testing" +) + +func TestColdAttr(t *testing.T) { + nodes := map[string]testNode{ + `0x7fc8fa094558 `: testNode{&ColdAttr{ + Addr: 0x7fc8fa094558, + Pos: NewPositionFromString("col:107"), + ChildNodes: []Node{}, + }, + 0x7fc8fa094558, + NewPositionFromString("col:107"), + []Node{}, + }, + } + + runNodeTests(t, nodes) +} diff --git a/ast/constant_expr.go b/ast/constant_expr.go new file mode 100644 index 0000000..004f117 --- /dev/null +++ b/ast/constant_expr.go @@ -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.*)> '(?P[\w ]+)'(:'(?P[\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 +} diff --git a/ast/constant_expr_test.go b/ast/constant_expr_test.go new file mode 100644 index 0000000..c64780c --- /dev/null +++ b/ast/constant_expr_test.go @@ -0,0 +1,64 @@ +package ast + +import ( + "testing" +) + +func TestConstantExpr(t *testing.T) { + nodes := map[string]testNode{ + `0x7f9bf3033240 'int'`: testNode{&ConstantExpr{ + Addr: 0x7f9bf3033240, + Pos: NewPositionFromString("col:11, col:25"), + Type: "int", + ChildNodes: []Node{}, + }, + 0x7f9bf3033240, + NewPositionFromString("col:11, col:25"), + []Node{}, + }, + `0x7f9bf3035c20 '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 '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 '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 '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) +} diff --git a/ast/if_stmt.go b/ast/if_stmt.go index b38fb4f..20bbcde 100644 --- a/ast/if_stmt.go +++ b/ast/if_stmt.go @@ -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.*)>", + "<(?P.*)>(?P 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{}, } } diff --git a/ast/if_stmt_test.go b/ast/if_stmt_test.go index 57a8549..d54d897 100644 --- a/ast/if_stmt_test.go +++ b/ast/if_stmt_test.go @@ -8,6 +8,17 @@ func TestIfStmt(t *testing.T) { nodes := map[string]testNode{ `0x7fc0a69091d0 `: 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 has_else`: testNode{&IfStmt{ + Addr: 0x7fc0a69091d0, + HasElse: true, Pos: NewPositionFromString("line:11:7, line:18:7"), ChildNodes: []Node{}, }, diff --git a/ast/objc_type_param.go b/ast/objc_type_param.go new file mode 100644 index 0000000..bc2cb3e --- /dev/null +++ b/ast/objc_type_param.go @@ -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.*?)'", + 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{} +} diff --git a/ast/objc_type_param_test.go b/ast/objc_type_param_test.go new file mode 100644 index 0000000..d3fad73 --- /dev/null +++ b/ast/objc_type_param_test.go @@ -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) +} diff --git a/ast/warn_unused_result_attr.go b/ast/warn_unused_result_attr.go index 3e3bba8..5ea1dc6 100644 --- a/ast/warn_unused_result_attr.go +++ b/ast/warn_unused_result_attr.go @@ -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.*)>( warn_unused_result)?`, line) + groups := groupsFromRegex(`<(?P.*)>( warn_unused_result)?( ".*")?`, line) if groups == nil { return &Unknown{} } diff --git a/ast/warn_unused_result_attr_test.go b/ast/warn_unused_result_attr_test.go index 33d038d..66b6045 100644 --- a/ast/warn_unused_result_attr_test.go +++ b/ast/warn_unused_result_attr_test.go @@ -24,6 +24,15 @@ func TestWarnUnusedResultAttr(t *testing.T) { NewPositionFromString("line:481:52"), []Node{}, }, + `0x1fac810 warn_unused_result ""`: testNode{&WarnUnusedResultAttr{ + Addr: 0x1fac810, + Pos: NewPositionFromString("line:481:52"), + ChildNodes: []Node{}, + }, + 0x1fac810, + NewPositionFromString("line:481:52"), + []Node{}, + }, } runNodeTests(t, nodes) diff --git a/wrap/main.go b/wrap/main.go index af79d8f..085c761 100644 --- a/wrap/main.go +++ b/wrap/main.go @@ -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)