mirror of
https://github.com/golang/go
synced 2024-09-30 02:24:43 -06:00
go/parser, go/types: report invalid else branch in if statements
- Only accept valid if statement syntax in go/parser. - Check AST again in go/types since it may have been modified and the AST doesn't preclude other statements in the else branch of an if statement. - Removed a test from gofmt which verified that old-style if statements permitting any statement in the else branch were correctly reformatted. It's been years since we switched to the current syntax; no need to support this anymore. - Added a comment to go/printer. Fixes #13475. Change-Id: Id2c8fbcc68b719cd511027d0412a37266cceed6b Reviewed-on: https://go-review.googlesource.com/17408 Reviewed-by: Russ Cox <rsc@golang.org>
This commit is contained in:
parent
c5aa53c8c5
commit
670642d389
9
src/cmd/gofmt/testdata/old.golden
vendored
9
src/cmd/gofmt/testdata/old.golden
vendored
@ -1,9 +0,0 @@
|
|||||||
package P
|
|
||||||
|
|
||||||
func f() {
|
|
||||||
if x {
|
|
||||||
y
|
|
||||||
} else {
|
|
||||||
z
|
|
||||||
}
|
|
||||||
}
|
|
8
src/cmd/gofmt/testdata/old.input
vendored
8
src/cmd/gofmt/testdata/old.input
vendored
@ -1,8 +0,0 @@
|
|||||||
package P
|
|
||||||
|
|
||||||
func f() {
|
|
||||||
if x {
|
|
||||||
y
|
|
||||||
} else
|
|
||||||
z
|
|
||||||
}
|
|
@ -1857,7 +1857,16 @@ func (p *parser) parseIfStmt() *ast.IfStmt {
|
|||||||
var else_ ast.Stmt
|
var else_ ast.Stmt
|
||||||
if p.tok == token.ELSE {
|
if p.tok == token.ELSE {
|
||||||
p.next()
|
p.next()
|
||||||
else_ = p.parseStmt()
|
switch p.tok {
|
||||||
|
case token.IF:
|
||||||
|
else_ = p.parseIfStmt()
|
||||||
|
case token.LBRACE:
|
||||||
|
else_ = p.parseBlockStmt()
|
||||||
|
p.expectSemi()
|
||||||
|
default:
|
||||||
|
p.errorExpected(p.pos, "if statement or block")
|
||||||
|
else_ = &ast.BadStmt{From: p.pos, To: p.pos}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
p.expectSemi()
|
p.expectSemi()
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,10 @@ var invalids = []string{
|
|||||||
`package p; type _ struct { ( /* ERROR "expected anonymous field" */ int) };`,
|
`package p; type _ struct { ( /* ERROR "expected anonymous field" */ int) };`,
|
||||||
`package p; func _()(x, y, z ... /* ERROR "expected '\)', found '...'" */ int){}`,
|
`package p; func _()(x, y, z ... /* ERROR "expected '\)', found '...'" */ int){}`,
|
||||||
`package p; func _()(... /* ERROR "expected type, found '...'" */ int){}`,
|
`package p; func _()(... /* ERROR "expected type, found '...'" */ int){}`,
|
||||||
|
|
||||||
|
// issue 13475
|
||||||
|
`package p; func f() { if true {} else ; /* ERROR "expected if statement or block" */ }`,
|
||||||
|
`package p; func f() { if true {} else defer /* ERROR "expected if statement or block" */ f() }`,
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestInvalid(t *testing.T) {
|
func TestInvalid(t *testing.T) {
|
||||||
|
@ -1185,6 +1185,9 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool) {
|
|||||||
case *ast.BlockStmt, *ast.IfStmt:
|
case *ast.BlockStmt, *ast.IfStmt:
|
||||||
p.stmt(s.Else, nextIsRBrace)
|
p.stmt(s.Else, nextIsRBrace)
|
||||||
default:
|
default:
|
||||||
|
// This can only happen with an incorrectly
|
||||||
|
// constructed AST. Permit it but print so
|
||||||
|
// that it can be parsed without errors.
|
||||||
p.print(token.LBRACE, indent, formfeed)
|
p.print(token.LBRACE, indent, formfeed)
|
||||||
p.stmt(s.Else, true)
|
p.stmt(s.Else, true)
|
||||||
p.print(unindent, formfeed, token.RBRACE)
|
p.print(unindent, formfeed, token.RBRACE)
|
||||||
|
@ -457,8 +457,15 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
|
|||||||
check.error(s.Cond.Pos(), "non-boolean condition in if statement")
|
check.error(s.Cond.Pos(), "non-boolean condition in if statement")
|
||||||
}
|
}
|
||||||
check.stmt(inner, s.Body)
|
check.stmt(inner, s.Body)
|
||||||
if s.Else != nil {
|
// The parser produces a correct AST but if it was modified
|
||||||
|
// elsewhere the else branch may be invalid. Check again.
|
||||||
|
switch s.Else.(type) {
|
||||||
|
case nil, *ast.BadStmt:
|
||||||
|
// valid or error already reported
|
||||||
|
case *ast.IfStmt, *ast.BlockStmt:
|
||||||
check.stmt(inner, s.Else)
|
check.stmt(inner, s.Else)
|
||||||
|
default:
|
||||||
|
check.error(s.Else.Pos(), "invalid else branch in if statement")
|
||||||
}
|
}
|
||||||
|
|
||||||
case *ast.SwitchStmt:
|
case *ast.SwitchStmt:
|
||||||
|
Loading…
Reference in New Issue
Block a user