fn.Pragma = r.pragmaFlag()
r.linkname(name)
+ typecheck.Func(fn)
+
if r.bool() {
fn.ABI = obj.ABI(r.uint64())
// TODO(mdempsky): Use method.Pos instead?
pos := base.AutogeneratedPos
- fn := r.newWrapperFunc(pos, sym, wrapper, method, target)
+ fn := r.newWrapperFunc(pos, sym, wrapper, method)
var recv ir.Node = fn.Nname.Type().Recv().Nname.(*ir.Name)
}
addTailCall(pos, fn, recv, method)
+
+ r.finishWrapperFunc(fn, target)
}
func (r *reader) methodValueWrapper(tbase *types.Type, method *types.Field, target *ir.Package) {
// TODO(mdempsky): Use method.Pos instead?
pos := base.AutogeneratedPos
- fn := r.newWrapperFunc(pos, sym, nil, method, target)
+ fn := r.newWrapperFunc(pos, sym, nil, method)
fn.SetNeedctxt(true)
sym.Def = fn
fn.ClosureVars = append(fn.ClosureVars, recv)
addTailCall(pos, fn, recv, method)
+
+ r.finishWrapperFunc(fn, target)
}
-func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field, target *ir.Package) *ir.Func {
+func (r *reader) newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
fn := ir.NewFunc(pos)
fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers?
defParams(ir.PPARAM, sig.Params())
defParams(ir.PPARAMOUT, sig.Results())
- target.Decls = append(target.Decls, fn)
-
return fn
}
+func (r *reader) finishWrapperFunc(fn *ir.Func, target *ir.Package) {
+ typecheck.Func(fn)
+
+ ir.WithFunc(fn, func() {
+ typecheck.Stmts(fn.Body)
+ })
+
+ target.Decls = append(target.Decls, fn)
+}
+
// newWrapperType returns a copy of the given signature type, but with
// the receiver parameter type substituted with recvType.
// If recvType is nil, newWrapperType returns a signature
r.ext = r
r.pkgInit(types.LocalPkg, target)
+ // Type-check any top-level assignments. We ignore non-assignments
+ // here because other declarations are typechecked as they're
+ // constructed.
+ for i, ndecls := 0, len(target.Decls); i < ndecls; i++ {
+ switch n := target.Decls[i]; n.Op() {
+ case ir.OAS, ir.OAS2:
+ target.Decls[i] = typecheck.Stmt(n)
+ }
+ }
+
// Don't use range--bodyIdx can add closures to todoBodies.
for len(todoBodies) > 0 {
// The order we expand bodies doesn't matter, so pop from the end
// Instantiated generic function: add to Decls for typechecking
// and compilation.
- if pri.dict != nil && len(pri.dict.targs) != 0 && fn.OClosure == nil {
+ if fn.OClosure == nil && len(pri.dict.targs) != 0 {
target.Decls = append(target.Decls, fn)
}
}
todoBodies = nil
- if !quirksMode() {
- // TODO(mdempsky): Investigate generating wrappers in quirks mode too.
- r.wrapTypes(target)
- }
-
- // Don't use range--typecheck can add closures to Target.Decls.
- for i := 0; i < len(target.Decls); i++ {
- target.Decls[i] = typecheck.Stmt(target.Decls[i])
- }
-
// Don't use range--typecheck can add closures to Target.Decls.
for i := 0; i < len(target.Decls); i++ {
if fn, ok := target.Decls[i].(*ir.Func); ok {
s := fmt.Sprintf("\nbefore typecheck %v", fn)
ir.Dump(s, fn)
}
- ir.CurFunc = fn
- typecheck.Stmts(fn.Body)
+ ir.WithFunc(fn, func() {
+ typecheck.Stmts(fn.Body)
+ })
if base.Flag.W > 1 {
s := fmt.Sprintf("\nafter typecheck %v", fn)
ir.Dump(s, fn)
}
}
+ if !quirksMode() {
+ // TODO(mdempsky): Investigate generating wrappers in quirks mode too.
+ r.wrapTypes(target)
+ }
+
+ // Check that nothing snuck past typechecking.
+ for _, n := range target.Decls {
+ if n.Typecheck() == 0 {
+ base.FatalfAt(n.Pos(), "missed typecheck: %v", n)
+ }
+
+ // For functions, check that at least their first statement (if
+ // any) was typechecked too.
+ if fn, ok := n.(*ir.Func); ok && len(fn.Body) != 0 {
+ if stmt := fn.Body[0]; stmt.Typecheck() == 0 {
+ base.FatalfAt(stmt.Pos(), "missed typecheck: %v", stmt)
+ }
+ }
+ }
+
base.ExitIfErrors() // just in case
}