From d4b704e110dea8395d107f5fd3be9f3cf2e8d161 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 30 Nov 2016 15:46:37 -0800 Subject: [PATCH] cmd/cgo: fix cgo checking when fetching errno value Fixes #18126. Change-Id: I7ae090945ef203673b06eb94817cc5c894b5eadc Reviewed-on: https://go-review.googlesource.com/33752 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick --- misc/cgo/test/cgo_test.go | 1 + misc/cgo/test/issue18126.go | 26 +++++++++++++++ src/cmd/cgo/gcc.go | 65 +++++++++++++++++++++++-------------- 3 files changed, 67 insertions(+), 25 deletions(-) create mode 100644 misc/cgo/test/issue18126.go diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go index 2f591377ae..a6de999752 100644 --- a/misc/cgo/test/cgo_test.go +++ b/misc/cgo/test/cgo_test.go @@ -75,5 +75,6 @@ func Test17065(t *testing.T) { test17065(t) } func TestThreadLock(t *testing.T) { testThreadLockFunc(t) } func TestCheckConst(t *testing.T) { testCheckConst(t) } func Test17537(t *testing.T) { test17537(t) } +func Test18126(t *testing.T) { test18126(t) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } diff --git a/misc/cgo/test/issue18126.go b/misc/cgo/test/issue18126.go new file mode 100644 index 0000000000..ac94a66aab --- /dev/null +++ b/misc/cgo/test/issue18126.go @@ -0,0 +1,26 @@ +// Copyright 2016 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. + +// Issue 18126: cgo check of void function returning errno. + +package cgotest + +/* +#include + +void Issue18126C(void **p) { +} +*/ +import "C" + +import ( + "testing" +) + +func test18126(t *testing.T) { + p := C.malloc(1) + _, err := C.Issue18126C(&p) + C.free(p) + _ = err +} diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index f6ddfbeceb..670a73f546 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -713,15 +713,7 @@ func (p *Package) rewriteCall(f *File, call *Call, name *Name) bool { List: params, }, } - var fbody ast.Stmt - if name.FuncType.Result == nil { - fbody = &ast.ExprStmt{ - X: fcall, - } - } else { - fbody = &ast.ReturnStmt{ - Results: []ast.Expr{fcall}, - } + if name.FuncType.Result != nil { rtype := p.rewriteUnsafe(name.FuncType.Result.Go) if rtype != name.FuncType.Result.Go { needsUnsafe = true @@ -734,6 +726,45 @@ func (p *Package) rewriteCall(f *File, call *Call, name *Name) bool { }, } } + + // There is a Ref pointing to the old call.Call.Fun. + for _, ref := range f.Ref { + if ref.Expr == &call.Call.Fun { + ref.Expr = &fcall.Fun + + // If this call expects two results, we have to + // adjust the results of the function we generated. + if ref.Context == "call2" { + if ftype.Results == nil { + // An explicit void argument + // looks odd but it seems to + // be how cgo has worked historically. + ftype.Results = &ast.FieldList{ + List: []*ast.Field{ + &ast.Field{ + Type: ast.NewIdent("_Ctype_void"), + }, + }, + } + } + ftype.Results.List = append(ftype.Results.List, + &ast.Field{ + Type: ast.NewIdent("error"), + }) + } + } + } + + var fbody ast.Stmt + if ftype.Results == nil { + fbody = &ast.ExprStmt{ + X: fcall, + } + } else { + fbody = &ast.ReturnStmt{ + Results: []ast.Expr{fcall}, + } + } call.Call.Fun = &ast.FuncLit{ Type: ftype, Body: &ast.BlockStmt{ @@ -743,22 +774,6 @@ func (p *Package) rewriteCall(f *File, call *Call, name *Name) bool { call.Call.Lparen = token.NoPos call.Call.Rparen = token.NoPos - // There is a Ref pointing to the old call.Call.Fun. - for _, ref := range f.Ref { - if ref.Expr == &call.Call.Fun { - ref.Expr = &fcall.Fun - - // If this call expects two results, we have to - // adjust the results of the function we generated. - if ref.Context == "call2" { - ftype.Results.List = append(ftype.Results.List, - &ast.Field{ - Type: ast.NewIdent("error"), - }) - } - } - } - return needsUnsafe }