1
0
mirror of https://github.com/golang/go synced 2024-11-16 22:34:45 -07:00

cmd/compile: do branch/label checks only once

The previous change implemented the missing fallthrough checking
in the parser. Therefore we can now disable the duplicate check
in the type checker:

- rename (types2.Config.)IngoreLabels to IgnoreBranches to more
  accurately reflect its functionality

- now also ignore break/continue/fallthroughs, not just labels

The IgnoreBranches flag only exists for types2, for use with
the compiler. There's no need to port this code to go/types.

Note: An alternative (and perhaps better) approach would be
to not use the the parser's CheckBranches mode and instead
enable (i.e. not disable) the branch/label checking in the
type checker. However, this requires a bit more work because
the type checker's error messages about goto's jumping over
variables don't have access to the variable names, which are
desired in the error messages.

Fixes #51456.

Change-Id: Ib2e71e811d4e84e4895b729646e879fd43b12dcd
Reviewed-on: https://go-review.googlesource.com/c/go/+/414135
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
Robert Griesemer 2022-06-24 19:11:52 -07:00
parent 6b309be7ab
commit 666d736ecb
4 changed files with 10 additions and 18 deletions

View File

@ -41,7 +41,7 @@ func checkFiles(noders []*noder) (posMap, *types2.Package, *types2.Info) {
conf := types2.Config{ conf := types2.Config{
Context: ctxt, Context: ctxt,
GoVersion: base.Flag.Lang, GoVersion: base.Flag.Lang,
IgnoreLabels: true, // parser already checked via syntax.CheckBranches mode IgnoreBranchErrors: true, // parser already checked via syntax.CheckBranches mode
CompilerErrorMessages: true, // use error strings matching existing compiler errors CompilerErrorMessages: true, // use error strings matching existing compiler errors
Error: func(err error) { Error: func(err error) {
terr := err.(types2.Error) terr := err.(types2.Error)

View File

@ -27,8 +27,6 @@ import (
func LoadPackage(filenames []string) { func LoadPackage(filenames []string) {
base.Timer.Start("fe", "parse") base.Timer.Start("fe", "parse")
mode := syntax.CheckBranches
// Limit the number of simultaneously open files. // Limit the number of simultaneously open files.
sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10) sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
@ -58,7 +56,7 @@ func LoadPackage(filenames []string) {
} }
defer f.Close() defer f.Close()
p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, syntax.CheckBranches) // errors are tracked via p.error
}() }()
} }
}() }()

View File

@ -128,9 +128,8 @@ type Config struct {
// Do not use casually! // Do not use casually!
FakeImportC bool FakeImportC bool
// If IgnoreLabels is set, correct label use is not checked. // If IgnoreBranchErrors is set, branch/label errors are ignored.
// TODO(gri) Consolidate label checking and remove this flag. IgnoreBranchErrors bool
IgnoreLabels bool
// If CompilerErrorMessages is set, errors are reported using // If CompilerErrorMessages is set, errors are reported using
// cmd/compile error strings to match $GOROOT/test errors. // cmd/compile error strings to match $GOROOT/test errors.

View File

@ -41,7 +41,7 @@ func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body
check.stmtList(0, body.List) check.stmtList(0, body.List)
if check.hasLabel && !check.conf.IgnoreLabels { if check.hasLabel && !check.conf.IgnoreBranchErrors {
check.labels(body) check.labels(body)
} }
@ -504,23 +504,18 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
check.hasLabel = true check.hasLabel = true
break // checked in 2nd pass (check.labels) break // checked in 2nd pass (check.labels)
} }
if check.conf.IgnoreBranchErrors {
break
}
switch s.Tok { switch s.Tok {
case syntax.Break: case syntax.Break:
if ctxt&breakOk == 0 { if ctxt&breakOk == 0 {
if check.conf.CompilerErrorMessages {
check.error(s, "break is not in a loop, switch, or select statement")
} else {
check.error(s, "break not in for, switch, or select statement") check.error(s, "break not in for, switch, or select statement")
} }
}
case syntax.Continue: case syntax.Continue:
if ctxt&continueOk == 0 { if ctxt&continueOk == 0 {
if check.conf.CompilerErrorMessages {
check.error(s, "continue is not in a loop")
} else {
check.error(s, "continue not in for statement") check.error(s, "continue not in for statement")
} }
}
case syntax.Fallthrough: case syntax.Fallthrough:
if ctxt&fallthroughOk == 0 { if ctxt&fallthroughOk == 0 {
var msg string var msg string