--- /dev/null
+// 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
+}
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
},
}
}
- call.Call.Fun = &ast.FuncLit{
- Type: ftype,
- Body: &ast.BlockStmt{
- List: append(stmts, fbody),
- },
- }
- 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 {
ref.Expr = &fcall.Fun
// If this call expects two results, we have to
- // adjust the results of the function we generated.
+ // 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{
+ List: append(stmts, fbody),
+ },
+ }
+ call.Call.Lparen = token.NoPos
+ call.Call.Rparen = token.NoPos
+
return needsUnsafe
}