diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index 386420f26b..4fe8ba8836 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -1203,6 +1203,9 @@ func (s *state) expr(n *Node) *ssa.Value { s.stmtList(n.Ninit) switch n.Op { + case OCFUNC: + aux := &ssa.ExternSymbol{n.Type, n.Left.Sym} + return s.entryNewValue1A(ssa.OpAddr, n.Type, aux, s.sb) case ONAME: if n.Class == PFUNC { // "value" of a function is the address of the function's closure @@ -1296,16 +1299,17 @@ func (s *state) expr(n *Node) *ssa.Value { case OCONVNOP: to := n.Type from := n.Left.Type - if to.Etype == TFUNC { - s.Unimplementedf("CONVNOP closure") - return nil - } // Assume everything will work out, so set up our return value. // Anything interesting that happens from here is a fatal. x := s.expr(n.Left) v := s.newValue1(ssa.OpCopy, to, x) // ensure that v has the right type + // CONVNOP closure + if to.Etype == TFUNC && from.IsPtr() { + return v + } + // named <--> unnamed type or typed <--> untyped const if from.Etype == to.Etype { return v diff --git a/src/cmd/compile/internal/gc/ssa_test.go b/src/cmd/compile/internal/gc/ssa_test.go index 0bce902982..feaea8b463 100644 --- a/src/cmd/compile/internal/gc/ssa_test.go +++ b/src/cmd/compile/internal/gc/ssa_test.go @@ -78,3 +78,6 @@ func TestRegalloc(t *testing.T) { runTest(t, "regalloc_ssa.go") } func TestString(t *testing.T) { runTest(t, "string_ssa.go") } func TestDeferNoReturn(t *testing.T) { buildTest(t, "deferNoReturn_ssa.go") } + +// TestClosure tests closure related behavior. +func TestClosure(t *testing.T) { runTest(t, "closure_ssa.go") } diff --git a/src/cmd/compile/internal/gc/testdata/closure_ssa.go b/src/cmd/compile/internal/gc/testdata/closure_ssa.go new file mode 100644 index 0000000000..ac1e51a23e --- /dev/null +++ b/src/cmd/compile/internal/gc/testdata/closure_ssa.go @@ -0,0 +1,39 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// map_ssa.go tests map operations. +package main + +import "fmt" + +var failed = false + +func testCFunc_ssa() int { + switch { // prevent inlining + } + a := 0 + b := func() { + switch { + } + a++ + } + b() + b() + return a +} + +func testCFunc() { + if want, got := 2, testCFunc_ssa(); got != want { + fmt.Printf("expected %d, got %d", want, got) + failed = true + } +} + +func main() { + testCFunc() + + if failed { + panic("failed") + } +}