Skip to content

Commit 56925e6

Browse files
authored
fix: correct branch control flow graph for parenthesis expressions (#583)
1 parent c580dfd commit 56925e6

File tree

4 files changed

+60
-25
lines changed

4 files changed

+60
-25
lines changed

_test/not0.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package main
2+
3+
func main() {
4+
a := 0
5+
b := true
6+
c := false
7+
if (b && c) {
8+
a = 1
9+
} else {
10+
a = -1
11+
}
12+
println(a)
13+
}
14+
15+
// Output:
16+
// -1

_test/not1.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package main
2+
3+
func main() {
4+
a := 0
5+
b := true
6+
if (!b) {
7+
a = 1
8+
} else {
9+
a = -1
10+
}
11+
println(a)
12+
}
13+
14+
// Output:
15+
// -1

interp/ast.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ const (
196196
aAndNot
197197
aAndNotAssign
198198
aBitNot
199+
aBranch
199200
aCall
200201
aCase
201202
aCompositeLit
@@ -253,6 +254,7 @@ var actions = [...]string{
253254
aAndNot: "&^",
254255
aAndNotAssign: "&^=",
255256
aBitNot: "^",
257+
aBranch: "branch",
256258
aCall: "call",
257259
aCase: "case",
258260
aCompositeLit: "compositeLit",

interp/cfg.go

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -881,7 +881,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
881881
cond.tnext = body.start
882882
body.tnext = cond.start
883883
}
884-
cond.fnext = n
884+
setFNext(cond, n)
885885
sc = sc.pop()
886886

887887
case forStmt2: // for init; cond; {}
@@ -903,7 +903,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
903903
body.tnext = cond.start
904904
}
905905
cond.tnext = body.start
906-
cond.fnext = n
906+
setFNext(cond, n)
907907
sc = sc.pop()
908908

909909
case forStmt3: // for ; cond; post {}
@@ -922,7 +922,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
922922
post.tnext = cond.start
923923
}
924924
cond.tnext = body.start
925-
cond.fnext = n
925+
setFNext(cond, n)
926926
body.tnext = post.start
927927
sc = sc.pop()
928928

@@ -953,13 +953,13 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
953953
post.tnext = cond.start
954954
}
955955
cond.tnext = body.start
956-
cond.fnext = n
956+
setFNext(cond, n)
957957
body.tnext = post.start
958958
sc = sc.pop()
959959

960960
case forRangeStmt:
961961
n.start = n.child[0].start
962-
n.child[0].fnext = n
962+
setFNext(n.child[0], n)
963963
sc = sc.pop()
964964

965965
case funcDecl:
@@ -1010,9 +1010,6 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
10101010
err = n.cfgErrorf("use of builtin %s not in function call", n.ident)
10111011
}
10121012
}
1013-
if sym.kind == varSym && sym.typ != nil && sym.typ.TypeOf().Kind() == reflect.Bool {
1014-
fixBranch(n)
1015-
}
10161013
}
10171014
if n.sym != nil {
10181015
n.recv = n.sym.recv
@@ -1035,7 +1032,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
10351032
n.start = cond.start
10361033
cond.tnext = tbody.start
10371034
}
1038-
cond.fnext = n
1035+
setFNext(cond, n)
10391036
tbody.tnext = n
10401037
sc = sc.pop()
10411038

@@ -1054,7 +1051,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
10541051
} else {
10551052
n.start = cond.start
10561053
cond.tnext = tbody.start
1057-
cond.fnext = fbody.start
1054+
setFNext(cond, fbody.start)
10581055
}
10591056
tbody.tnext = n
10601057
fbody.tnext = n
@@ -1078,7 +1075,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
10781075
cond.tnext = tbody.start
10791076
}
10801077
tbody.tnext = n
1081-
cond.fnext = n
1078+
setFNext(cond, n)
10821079
sc = sc.pop()
10831080

10841081
case ifStmt3: // if init; cond {} else {}
@@ -1097,7 +1094,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
10971094
} else {
10981095
init.tnext = cond.start
10991096
cond.tnext = tbody.start
1100-
cond.fnext = fbody.start
1097+
setFNext(cond, fbody.start)
11011098
}
11021099
tbody.tnext = n
11031100
fbody.tnext = n
@@ -1109,7 +1106,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
11091106
case landExpr:
11101107
n.start = n.child[0].start
11111108
n.child[0].tnext = n.child[1].start
1112-
n.child[0].fnext = n
1109+
setFNext(n.child[0], n)
11131110
n.child[1].tnext = n
11141111
n.typ = n.child[0].typ
11151112
n.findex = sc.add(n.typ)
@@ -1120,7 +1117,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
11201117
case lorExpr:
11211118
n.start = n.child[0].start
11221119
n.child[0].tnext = n
1123-
n.child[0].fnext = n.child[1].start
1120+
setFNext(n.child[0], n.child[1].start)
11241121
n.child[1].tnext = n
11251122
n.typ = n.child[0].typ
11261123
n.findex = sc.add(n.typ)
@@ -1423,7 +1420,8 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
14231420
}
14241421
// Chain case clauses.
14251422
for i, c := range clauses[:l-1] {
1426-
c.fnext = clauses[i+1] // Chain to next clause.
1423+
// Chain to next clause.
1424+
setFNext(c, clauses[i+1])
14271425
if len(c.child) == 0 {
14281426
c.tnext = n // Clause body is empty, exit.
14291427
} else {
@@ -1472,9 +1470,9 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
14721470
cond := c.child[0]
14731471
cond.tnext = body.start
14741472
if i == l-1 {
1475-
cond.fnext = n
1473+
setFNext(cond, n)
14761474
} else {
1477-
cond.fnext = clauses[i+1].start
1475+
setFNext(cond, clauses[i+1].start)
14781476
}
14791477
c.start = cond.start
14801478
} else {
@@ -1703,15 +1701,19 @@ func genRun(nod *node) error {
17031701
return err
17041702
}
17051703

1706-
// FixBranch sets the branch action to the identExpr node if it is a bool
1707-
// used in a conditional expression.
1708-
func fixBranch(n *node) {
1709-
switch n.anc.kind {
1710-
case ifStmt0, ifStmt1, ifStmt2, ifStmt3, forStmt1, forStmt2, forStmt3, forStmt4:
1711-
n.gen = branch
1712-
case parenExpr:
1713-
fixBranch(n.anc)
1704+
// setFnext sets the cond fnext field to next, propagates it for parenthesis blocks
1705+
// and sets the action to branch.
1706+
func setFNext(cond, next *node) {
1707+
if cond.action == aNop {
1708+
cond.action = aBranch
1709+
cond.gen = branch
1710+
cond.fnext = next
1711+
}
1712+
if cond.kind == parenExpr {
1713+
setFNext(cond.lastChild(), next)
1714+
return
17141715
}
1716+
cond.fnext = next
17151717
}
17161718

17171719
// GetDefault return the index of default case clause in a switch statement, or -1.

0 commit comments

Comments
 (0)