0
1
mirror of https://github.com/golang/go synced 2025-04-29 02:27:46 +00:00

cmd/compile/internal/syntax: use BadExpr instead of fake CallExpr in bad go/defer

If the go/defer syntax is bad, using a fake CallExpr may produce
a follow-on error in the type checker. Instead store a BadExpr
in the syntax tree (since an error has already been reported).

Adjust various tests.

For .

Change-Id: Ib2d25f8eab7d5745275188d83d11620cad6ef47c
Reviewed-on: https://go-review.googlesource.com/c/go/+/425675
Reviewed-by: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
Robert Griesemer
2022-08-25 16:14:43 -07:00
committed by Gopher Robot
parent 9b80d3d3db
commit c801e4b10f
7 changed files with 24 additions and 17 deletions
src/cmd/compile/internal
syntax
types2
stmt.go
testdata
test/fixedbugs

@ -385,7 +385,7 @@ type (
CallStmt struct { CallStmt struct {
Tok token // Go or Defer Tok token // Go or Defer
Call *CallExpr Call Expr
stmt stmt
} }

@ -951,16 +951,21 @@ func (p *parser) callStmt() *CallStmt {
x = t x = t
} }
cx, ok := x.(*CallExpr) // TODO(gri) Now that we don't store a CallExpr in a CallStmt anymore
if !ok { // we might as well leave this check to the type checker.
p.errorAt(x.Pos(), fmt.Sprintf("expression in %s must be function call", s.Tok)) // Adjust this here and in go/parser eventually.
// already progressed, no need to advance if _, ok := x.(*CallExpr); !ok {
cx = new(CallExpr) // only report an error if it's a new one
cx.pos = x.Pos() if bad, ok := x.(*BadExpr); !ok {
cx.Fun = x // assume common error of missing parentheses (function invocation) p.errorAt(x.Pos(), fmt.Sprintf("expression in %s must be function call", s.Tok))
// already progressed, no need to advance
bad = new(BadExpr)
bad.pos = x.Pos()
x = bad
}
} }
s.Call = cx s.Call = x
return s return s
} }

@ -6,4 +6,4 @@
// Line 9 must end in EOF for this test (no newline). // Line 9 must end in EOF for this test (no newline).
package e package e
func([<-chan<-[func /* ERROR unexpected u */ u){go /* ERROR must be function call */ func([<-chan<-[func /* ERROR unexpected u */ u){go

@ -165,7 +165,7 @@ func (check *Checker) closeScope() {
check.scope = check.scope.Parent() check.scope = check.scope.Parent()
} }
func (check *Checker) suspendedCall(keyword string, call *syntax.CallExpr) { func (check *Checker) suspendedCall(keyword string, call syntax.Expr) {
var x operand var x operand
var msg string var msg string
switch check.rawExpr(&x, call, nil, false) { switch check.rawExpr(&x, call, nil, false) {

@ -229,7 +229,7 @@ func selects() {
} }
func gos() { func gos() {
go 1 /* ERROR must be function call */ /* ERROR cannot call non-function */ go 1 /* ERROR must be function call */
go int /* ERROR "go requires function call, not conversion" */ (0) go int /* ERROR "go requires function call, not conversion" */ (0)
go gos() go gos()
var c chan int var c chan int
@ -238,7 +238,7 @@ func gos() {
} }
func defers() { func defers() {
defer 1 /* ERROR must be function call */ /* ERROR cannot call non-function */ defer 1 /* ERROR must be function call */
defer int /* ERROR "defer requires function call, not conversion" */ (0) defer int /* ERROR "defer requires function call, not conversion" */ (0)
defer defers() defer defers()
var c chan int var c chan int

@ -10,4 +10,4 @@
// there yet, so put it here for now. See also #20800.) // there yet, so put it here for now. See also #20800.)
package e package e
func([<-chan<-[func u){go // ERROR "unexpected u", ERROR "must be function call" func([<-chan<-[func u){go // ERROR "unexpected u"

@ -11,13 +11,15 @@
package p package p
// TODO(gri) The "not used" errors should not be reported.
import ( import (
"fmt" "fmt" // ERROR "imported and not used"
"math" "math" // ERROR "imported and not used"
) )
func f() { func f() {
var i int var i int // ERROR "i declared but not used"
defer func() { fmt.Println() } // ERROR "must be function call" defer func() { fmt.Println() } // ERROR "must be function call"
go func() { _ = math.Sin(0) } // ERROR "must be function call" go func() { _ = math.Sin(0) } // ERROR "must be function call"
go func() { _ = i} // ERROR "must be function call" go func() { _ = i} // ERROR "must be function call"