interp: fix a wrong control flow in switch

In switch case expressions, the condition on case clause was
not always properly evaluated. Reverse the order of case clause
evaluations (as already done for if-else-if fashion), and fix the
wiring to false-next and true-next nodes.

Fixes #1126.
This commit is contained in:
Marc Vertes
2021-06-14 12:18:07 +02:00
committed by GitHub
parent b1ef9251d4
commit 93e2db7085
5 changed files with 42 additions and 16 deletions

View File

@@ -57,7 +57,7 @@ func main() {
fmt.Println(err, vvv)
}
// Ouput:
// Output:
// <nil> {work bob@work.com}
// <nil> {work bob@work.com}
// <nil> {work bob@work.com}

View File

@@ -103,7 +103,7 @@ func main() {
intoMap()
}
// Ouput:
// Output:
// 0 : foo
// 1 : bar
// 0 : foo

View File

@@ -8,5 +8,5 @@ func main() {
fmt.Printf("%v %T\n", x, x)
}
// Ouput:
// Output:
// ab string

23
_test/issue-1126.go Normal file
View File

@@ -0,0 +1,23 @@
package main
import (
"errors"
"fmt"
"strings"
)
func main() {
err := errors.New("hello there")
switch true {
case err == nil:
break
case strings.Contains(err.Error(), "hello"):
fmt.Println("True!")
default:
fmt.Println("False!")
}
}
// Output:
// True!

View File

@@ -1737,15 +1737,17 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) {
break
}
// Chain case clauses.
for i, c := range clauses[:l-1] {
// Chain to next clause.
setFNext(c, clauses[i+1])
for i := l - 1; i >= 0; i-- {
c := clauses[i]
if len(c.child) == 0 {
c.tnext = n // Clause body is empty, exit.
} else {
body := c.lastChild()
c.tnext = body.start
if len(body.child) > 0 && body.lastChild().kind == fallthroughtStmt {
c.child[0].tnext = c
c.start = c.child[0].start
if i < l-1 && len(body.child) > 0 && body.lastChild().kind == fallthroughtStmt {
if n.kind == typeSwitch {
err = body.lastChild().cfgErrorf("cannot fallthrough in type switch")
}
@@ -1758,15 +1760,16 @@ func (interp *Interpreter) cfg(root *node, importPath string) ([]*node, error) {
body.tnext = n // Exit switch at end of clause body.
}
}
}
c := clauses[l-1] // Last clause.
c.fnext = n
if len(c.child) == 0 {
c.tnext = n // Clause body is empty, exit.
} else {
body := c.lastChild()
c.tnext = body.start
body.tnext = n
if i == l-1 {
setFNext(clauses[i], n)
continue
}
if len(clauses[i+1].child) > 1 {
setFNext(c, clauses[i+1].start)
} else {
setFNext(c, clauses[i+1])
}
}
n.start = n.child[0].start
n.child[0].tnext = sbn.start