0
1
mirror of https://github.com/golang/go synced 2025-04-12 00:29:42 +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/check
test/fixedbugs

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

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

@ -6,4 +6,4 @@
// Line 9 must end in EOF for this test (no newline).
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()
}
func (check *Checker) suspendedCall(keyword string, call *syntax.CallExpr) {
func (check *Checker) suspendedCall(keyword string, call syntax.Expr) {
var x operand
var msg string
switch check.rawExpr(&x, call, nil, false) {

@ -229,7 +229,7 @@ func selects() {
}
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 gos()
var c chan int
@ -238,7 +238,7 @@ func gos() {
}
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 defers()
var c chan int

@ -10,4 +10,4 @@
// there yet, so put it here for now. See also #20800.)
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
// TODO(gri) The "not used" errors should not be reported.
import (
"fmt"
"math"
"fmt" // ERROR "imported and not used"
"math" // ERROR "imported and not used"
)
func f() {
var i int
var i int // ERROR "i declared but not used"
defer func() { fmt.Println() } // ERROR "must be function call"
go func() { _ = math.Sin(0) } // ERROR "must be function call"
go func() { _ = i} // ERROR "must be function call"