]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/syntax: use BadExpr instead of fake CallExpr in bad go/defer
authorRobert Griesemer <gri@golang.org>
Thu, 25 Aug 2022 23:14:43 +0000 (16:14 -0700)
committerGopher Robot <gobot@golang.org>
Thu, 1 Sep 2022 22:37:03 +0000 (22:37 +0000)
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 #54511.

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>
src/cmd/compile/internal/syntax/nodes.go
src/cmd/compile/internal/syntax/parser.go
src/cmd/compile/internal/syntax/testdata/issue20789.go
src/cmd/compile/internal/types2/stmt.go
src/cmd/compile/internal/types2/testdata/check/stmt0.go
test/fixedbugs/issue20789.go
test/fixedbugs/issue23586.go

index b0a0918e77b8a7270250e26ecf8d1c781d3c4873..10af3c597b03e24945b3568cb787201e9b6a098f 100644 (file)
@@ -385,7 +385,7 @@ type (
 
        CallStmt struct {
                Tok  token // Go or Defer
-               Call *CallExpr
+               Call Expr
                stmt
        }
 
index 3bf9a5cb3b1799bccb0697378bf3f607017f7aa1..8ae2ebbe7656dd30ceb4f08cf14bf9e1238c1cdc 100644 (file)
@@ -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
 }
 
index 5f150db7e6b8427766a50e51a89b682aa6daa988..0d5988b9a608c21316be48ba481f5f81a4994985 100644 (file)
@@ -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 */
\ No newline at end of file
+func([<-chan<-[func /* ERROR unexpected u */ u){go
\ No newline at end of file
index 74d4164ba9d1ba3d0e669336b97a39b9bb1e493e..92aa6b6f76827ed4331cac19f76e1f836e91135a 100644 (file)
@@ -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) {
index e5b6f5dff740be386cc69ec26b4bd32a1b67a0b4..7aaa83e4ff484d75e7f1a2e375d381152ec74773 100644 (file)
@@ -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
index 82aec965ede64dff77ff04718b78495e0a32c262..4e4eed42a7ff4bdcdf25f3118b5217b4d7547ed5 100644 (file)
@@ -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"
\ No newline at end of file
+func([<-chan<-[func u){go // ERROR "unexpected u"
\ No newline at end of file
index c2d4c9ffb59351996488f966f4ecf7dd51547f8f..31d39d83894c7251559f3d454f110ef9a2da2320 100644 (file)
 
 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"