diff --git a/ssa/builder.go b/ssa/builder.go index cf7dd07e..8b0019f1 100644 --- a/ssa/builder.go +++ b/ssa/builder.go @@ -438,8 +438,6 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue { return &address{addr: fn.emit(v), expr: e} case *ast.StarExpr: - // TODO(adonovan): fix: implement nil-check if e.X - // evaluates to nil, per http://golang.org/s/go12nil. return &address{addr: b.expr(fn, e.X), starPos: e.Star, expr: e} } @@ -562,7 +560,14 @@ func (b *builder) expr(fn *Function, e ast.Expr) (result Value) { case *ast.UnaryExpr: switch e.Op { case token.AND: // &X --- potentially escaping. - return b.addr(fn, e.X, true).address(fn) + addr := b.addr(fn, e.X, true) + if _, ok := unparen(e.X).(*ast.StarExpr); ok { + // &*p must panic if p is nil (http://golang.org/s/go12nil). + // For simplicity, we'll just (suboptimally) rely + // on the side effects of a load. + addr.load(fn) + } + return addr.address(fn) case token.ADD: return b.expr(fn, e.X) case token.NOT, token.ARROW, token.SUB, token.XOR: // ! <- - ^ diff --git a/ssa/interp/external.go b/ssa/interp/external.go index 391e909c..cd02be40 100644 --- a/ssa/interp/external.go +++ b/ssa/interp/external.go @@ -152,7 +152,6 @@ func ext۰runtime۰getgoroot(fn *ssa.Function, args []value) value { } func ext۰sync۰runtime_Syncsemcheck(fn *ssa.Function, args []value) value { - // TODO(adonovan): do equivalent of calling runtime_Syncsemcheck(size uintptr) here return nil } diff --git a/ssa/interp/interp_test.go b/ssa/interp/interp_test.go index 49233cdd..12c14ffd 100644 --- a/ssa/interp/interp_test.go +++ b/ssa/interp/interp_test.go @@ -59,6 +59,7 @@ var gorootTestTests = []string{ "gc.go", "simassign.go", "iota.go", + "nilptr2.go", "goprint.go", // doesn't actually assert anything "utf.go", "method.go",