]> Cypherpunks repositories - gostls13.git/commitdiff
go/parser: test and fix := scoping bug
authorRuss Cox <rsc@golang.org>
Thu, 27 Oct 2011 19:22:06 +0000 (12:22 -0700)
committerRuss Cox <rsc@golang.org>
Thu, 27 Oct 2011 19:22:06 +0000 (12:22 -0700)
R=iant
CC=golang-dev, gri
https://golang.org/cl/5327048

src/pkg/go/parser/parser.go
src/pkg/go/parser/parser_test.go

index c78c6b56ecb2cc5c7efcbf14d32b464a7fca649d..e2c944137217893adac3fe64d5b14f7d639c7e88 100644 (file)
@@ -434,7 +434,9 @@ func (p *parser) parseLhsList() []ast.Expr {
        switch p.tok {
        case token.DEFINE:
                // lhs of a short variable declaration
-               p.shortVarDecl(p.makeIdentList(list))
+               // but doesn't enter scope until later:
+               // caller must call p.shortVarDecl(p.makeIdentList(list))
+               // at appropriate time.
        case token.COLON:
                // lhs of a label declaration or a communication clause of a select
                // statement (parseLhsList is not called when parsing the case clause
@@ -1398,6 +1400,9 @@ func (p *parser) parseSimpleStmt(mode int) (ast.Stmt, bool) {
                } else {
                        y = p.parseRhsList()
                }
+               if tok == token.DEFINE {
+                       p.shortVarDecl(p.makeIdentList(x))
+               }
                return &ast.AssignStmt{x, pos, tok, y}, isRange
        }
 
@@ -1722,6 +1727,9 @@ func (p *parser) parseCommClause() *ast.CommClause {
                                }
                                p.next()
                                rhs = p.parseRhs()
+                               if tok == token.DEFINE && lhs != nil {
+                                       p.shortVarDecl(p.makeIdentList(lhs))
+                               }
                        } else {
                                // rhs must be single receive operation
                                if len(lhs) > 1 {
index 9705dcff250468d18d99fdea08e922fa909c63ee..dee90fbcf4c4a37adfa99e15ed170357413ce8d7 100644 (file)
@@ -5,6 +5,7 @@
 package parser
 
 import (
+       "go/ast"
        "go/token"
        "os"
        "testing"
@@ -134,3 +135,46 @@ func TestParse4(t *testing.T) {
                }
        }
 }
+
+func TestColonEqualsScope(t *testing.T) {
+       f, err := ParseFile(fset, "", `package p; func f() { x, y, z := x, y, z }`, 0)
+       if err != nil {
+               t.Errorf("parse: %s", err)
+       }
+
+       // RHS refers to undefined globals; LHS does not.
+       as := f.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.AssignStmt)
+       for _, v := range as.Rhs {
+               id := v.(*ast.Ident)
+               if id.Obj != nil {
+                       t.Errorf("rhs %s has Obj, should not", id.Name)
+               }
+       }
+       for _, v := range as.Lhs {
+               id := v.(*ast.Ident)
+               if id.Obj == nil {
+                       t.Errorf("lhs %s does not have Obj, should", id.Name)
+               }
+       }
+}
+
+func TestVarScope(t *testing.T) {
+       f, err := ParseFile(fset, "", `package p; func f() { var x, y, z = x, y, z }`, 0)
+       if err != nil {
+               t.Errorf("parse: %s", err)
+       }
+
+       // RHS refers to undefined globals; LHS does not.
+       as := f.Decls[0].(*ast.FuncDecl).Body.List[0].(*ast.DeclStmt).Decl.(*ast.GenDecl).Specs[0].(*ast.ValueSpec)
+       for _, v := range as.Values {
+               id := v.(*ast.Ident)
+               if id.Obj != nil {
+                       t.Errorf("rhs %s has Obj, should not", id.Name)
+               }
+       }
+       for _, id := range as.Names {
+               if id.Obj == nil {
+                       t.Errorf("lhs %s does not have Obj, should", id.Name)
+               }
+       }
+}