fix: dont allow calling init

This commit is contained in:
Nicholas Wiersma
2020-07-09 14:35:04 +02:00
committed by GitHub
parent 98eacf3610
commit 3c6df504df
4 changed files with 48 additions and 30 deletions

12
_test/init1.go Normal file
View File

@@ -0,0 +1,12 @@
package main
func init() {
println("here")
}
func main() {
init()
}
// Error:
// _test/init1.go:8:2: undefined: init

View File

@@ -1153,11 +1153,11 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
n.types = sc.types
sc = sc.pop()
funcName := n.child[1].ident
if !isMethod(n) {
interp.scopes[pkgID].sym[funcName].index = -1 // to force value to n.val
interp.scopes[pkgID].sym[funcName].typ = n.typ
interp.scopes[pkgID].sym[funcName].kind = funcSym
interp.scopes[pkgID].sym[funcName].node = n
if sym := sc.sym[funcName]; !isMethod(n) && sym != nil {
sym.index = -1 // to force value to n.val
sym.typ = n.typ
sym.kind = funcSym
sym.node = n
}
case funcLit:
@@ -1172,6 +1172,10 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
if isKey(n) || isNewDefine(n, sc) {
break
}
if n.anc.kind == funcDecl && n.anc.child[1] == n {
// Dont process a function name identExpr.
break
}
sym, level, found := sc.lookup(n.ident)
if !found {

View File

@@ -138,11 +138,13 @@ func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error)
if n.typ, err = nodeType(interp, sc, n.child[2]); err != nil {
return false
}
if isMethod(n) {
ident := n.child[1].ident
switch {
case isMethod(n):
// TODO(mpl): redeclaration detection
// Add a method symbol in the receiver type name space
var rcvrtype *itype
n.ident = n.child[1].ident
n.ident = ident
rcvr := n.child[0].child[0]
rtn := rcvr.lastChild()
typeName := rtn.ident
@@ -167,33 +169,32 @@ func (interp *Interpreter) gta(root *node, rpath, pkgID string) ([]*node, error)
}
rcvrtype.method = append(rcvrtype.method, n)
n.child[0].child[0].lastChild().typ = rcvrtype
} else {
ident := n.child[1].ident
case ident == "init":
// TODO(mpl): use constant instead of hardcoded string?
if ident != "init" {
asImportName := filepath.Join(ident, baseName)
if _, exists := sc.sym[asImportName]; exists {
// redeclaration error
// TODO(mpl): improve error with position of previous declaration.
err = n.cfgErrorf("%s redeclared in this block", ident)
return false
}
sym, exists := sc.sym[ident]
if exists {
// Make sure the symbol we found seems to be about another node, before calling
// it a redeclaration.
if sym.typ.isComplete() {
// TODO(mpl): this check might be too permissive?
if sym.kind != funcSym || sym.typ.cat != n.typ.cat || sym.node != n || sym.index != -1 {
// redeclaration error
// TODO(mpl): improve error with position of previous declaration.
err = n.cfgErrorf("%s redeclared in this block", ident)
return false
}
// init functions do not get declared as per the Go spec.
default:
asImportName := filepath.Join(ident, baseName)
if _, exists := sc.sym[asImportName]; exists {
// redeclaration error
// TODO(mpl): improve error with position of previous declaration.
err = n.cfgErrorf("%s redeclared in this block", ident)
return false
}
sym, exists := sc.sym[ident]
if exists {
// Make sure the symbol we found seems to be about another node, before calling
// it a redeclaration.
if sym.typ.isComplete() {
// TODO(mpl): this check might be too permissive?
if sym.kind != funcSym || sym.typ.cat != n.typ.cat || sym.node != n || sym.index != -1 {
// redeclaration error
// TODO(mpl): improve error with position of previous declaration.
err = n.cfgErrorf("%s redeclared in this block", ident)
return false
}
}
}
// Add a function symbol in the package name space
// Add a function symbol in the package name space except for init
sc.sym[n.child[1].ident] = &symbol{kind: funcSym, typ: n.typ, node: n, index: -1}
}
if !n.typ.isComplete() {

View File

@@ -45,6 +45,7 @@ func TestInterpConsistencyBuild(t *testing.T) {
file.Name() == "fun22.go" || // expect error
file.Name() == "if2.go" || // expect error
file.Name() == "import6.go" || // expect error
file.Name() == "init1.go" || // expect error
file.Name() == "io0.go" || // use random number
file.Name() == "op1.go" || // expect error
file.Name() == "op7.go" || // expect error