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 <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go
index 2f59137..a6de999 100644
--- a/misc/cgo/test/cgo_test.go
+++ b/misc/cgo/test/cgo_test.go
@@ -75,5 +75,6 @@
 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 0000000..ac94a66
--- /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 <stdlib.h>
+
+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 f6ddfbe..670a73f 100644
--- a/src/cmd/cgo/gcc.go
+++ b/src/cmd/cgo/gcc.go
@@ -713,15 +713,7 @@
 			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 @@
 			},
 		}
 	}
+
+	// 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 @@
 	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
 }