bind: accept null objects as nil pointers

Currently the generated bindings assume that any object
passed to Go as a method argument is actually a valid one
originating from Go. The `null` object is however a corner
case to this assumption, which should be accepted for Go
pointer types, since they can cleanly convert into `nil`.

This CL modifies the generated wrapper code so any `nil`
reference is permitted for Go pointer types, which until
now produced a nil pointer dereference error.

Fixes golang/go#20330

Change-Id: If1ab9cf9df7ac3808486d23ccf2db8d32fb89426
Reviewed-on: https://go-review.googlesource.com/43253
Reviewed-by: Elias Naur <elias.naur@gmail.com>
diff --git a/bind/gengo.go b/bind/gengo.go
index c56d3e3..1d0ff9f 100644
--- a/bind/gengo.go
+++ b/bind/gengo.go
@@ -413,8 +413,10 @@
 				return
 			}
 			g.Printf("// Must be a Go object\n")
-			g.Printf("%s_ref := _seq.FromRefNum(int32(%s))\n", toVar, fromVar)
-			g.Printf("%s := %s_ref.Get().(*%s%s)\n", toVar, toVar, g.pkgName(oPkg), o.Name())
+			g.Printf("var %s *%s%s\n", toVar, g.pkgName(oPkg), o.Name())
+			g.Printf("if %s_ref := _seq.FromRefNum(int32(%s)); %s_ref != nil {\n", toVar, fromVar, toVar)
+			g.Printf("  %s = %s_ref.Get().(*%s%s)\n", toVar, toVar, g.pkgName(oPkg), o.Name())
+			g.Printf("}\n")
 		default:
 			g.errorf("unsupported pointer type %s", t)
 		}
diff --git a/bind/java/SeqTest.java b/bind/java/SeqTest.java
index 2439c51..36f3169 100644
--- a/bind/java/SeqTest.java
+++ b/bind/java/SeqTest.java
@@ -448,8 +448,11 @@
         return null;
       }
     }));
-	assertEquals("Go nil interface is null", null, Testpkg.newNullInterface());
-	assertEquals("Go nil struct pointer is null", null, Testpkg.newNullStruct());
+    assertEquals("Go nil interface is null", null, Testpkg.newNullInterface());
+    assertEquals("Go nil struct pointer is null", null, Testpkg.newNullStruct());
+
+    Issue20330 nullArger = new Issue20330();
+    assertTrue(nullArger.callWithNull(null));
   }
 
   public void testPassByteArray() {
diff --git a/bind/objc/SeqTest.m b/bind/objc/SeqTest.m
index e6d0fe7..139a9f9 100644
--- a/bind/objc/SeqTest.m
+++ b/bind/objc/SeqTest.m
@@ -395,6 +395,8 @@
 	XCTAssertNil(i, @"NewNullInterface() returned %p; expected nil", i);
 	TestpkgS *s = TestpkgNewNullStruct();
 	XCTAssertNil(s, @"NewNullStruct() returned %p; expected nil", s);
+	TestpkgIssue20330 *nullArger = TestpkgNewIssue20330();
+	XCTAssertTrue([nullArger callWithNull:nil], @"Issue20330.CallWithNull failed");
 }
 
 - (void)testReturnsError {
diff --git a/bind/testdata/issue10788.go.golden b/bind/testdata/issue10788.go.golden
index a6ef182..f8d1145 100644
--- a/bind/testdata/issue10788.go.golden
+++ b/bind/testdata/issue10788.go.golden
@@ -46,8 +46,10 @@
 	ref := _seq.FromRefNum(int32(refnum))
 	v := ref.Get().(issue10788.TestInterface)
 	// Must be a Go object
-	_param_s_ref := _seq.FromRefNum(int32(param_s))
-	_param_s := _param_s_ref.Get().(*issue10788.TestStruct)
+	var _param_s *issue10788.TestStruct
+	if _param_s_ref := _seq.FromRefNum(int32(param_s)); _param_s_ref != nil {
+		_param_s = _param_s_ref.Get().(*issue10788.TestStruct)
+	}
 	v.DoSomeWork(_param_s)
 }
 
diff --git a/bind/testdata/structs.go.golden b/bind/testdata/structs.go.golden
index f989e4e..49e366f 100644
--- a/bind/testdata/structs.go.golden
+++ b/bind/testdata/structs.go.golden
@@ -120,8 +120,10 @@
 //export proxystructs__Identity
 func proxystructs__Identity(param_s C.int32_t) C.int32_t {
 	// Must be a Go object
-	_param_s_ref := _seq.FromRefNum(int32(param_s))
-	_param_s := _param_s_ref.Get().(*structs.S)
+	var _param_s *structs.S
+	if _param_s_ref := _seq.FromRefNum(int32(param_s)); _param_s_ref != nil {
+		_param_s = _param_s_ref.Get().(*structs.S)
+	}
 	res_0 := structs.Identity(_param_s)
 	var _res_0 C.int32_t = _seq.NullRefNum
 	if res_0 != nil {
@@ -133,8 +135,10 @@
 //export proxystructs__IdentityWithError
 func proxystructs__IdentityWithError(param_s C.int32_t) (C.int32_t, C.int32_t) {
 	// Must be a Go object
-	_param_s_ref := _seq.FromRefNum(int32(param_s))
-	_param_s := _param_s_ref.Get().(*structs.S)
+	var _param_s *structs.S
+	if _param_s_ref := _seq.FromRefNum(int32(param_s)); _param_s_ref != nil {
+		_param_s = _param_s_ref.Get().(*structs.S)
+	}
 	res_0, res_1 := structs.IdentityWithError(_param_s)
 	var _res_0 C.int32_t = _seq.NullRefNum
 	if res_0 != nil {
diff --git a/bind/testdata/vars.go.golden b/bind/testdata/vars.go.golden
index f3a1132..6158e20 100644
--- a/bind/testdata/vars.go.golden
+++ b/bind/testdata/vars.go.golden
@@ -101,8 +101,10 @@
 //export var_setvars_AStructPtr
 func var_setvars_AStructPtr(v C.int32_t) {
 	// Must be a Go object
-	_v_ref := _seq.FromRefNum(int32(v))
-	_v := _v_ref.Get().(*vars.S)
+	var _v *vars.S
+	if _v_ref := _seq.FromRefNum(int32(v)); _v_ref != nil {
+		_v = _v_ref.Get().(*vars.S)
+	}
 	vars.AStructPtr = _v
 }
 
diff --git a/bind/testpkg/testpkg.go b/bind/testpkg/testpkg.go
index 2e825c7..f0cda07 100644
--- a/bind/testpkg/testpkg.go
+++ b/bind/testpkg/testpkg.go
@@ -266,6 +266,16 @@
 	return _null == nil && nuller.Null() == nil
 }
 
+type Issue20330 struct{}
+
+func NewIssue20330() *Issue20330 {
+	return new(Issue20330)
+}
+
+func (i *Issue20330) CallWithNull(_null *Issue20330) bool {
+	return _null == nil
+}
+
 type Issue14168 interface {
 	F(seq int32)
 }