diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /misc/cgo | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'misc/cgo')
40 files changed, 863 insertions, 127 deletions
diff --git a/misc/cgo/test/backdoor/backdoor_gccgo.go b/misc/cgo/errors/issue7757.go index 514f76ec5..5eafd22e8 100644 --- a/misc/cgo/test/backdoor/backdoor_gccgo.go +++ b/misc/cgo/errors/issue7757.go @@ -2,10 +2,13 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This is the gccgo version of the stub in runtime.c. +package main -// +build gccgo +/* +void foo() {} +*/ +import "C" -package backdoor - -func Issue7695(x1, x2, x3, x4, x5, x6, x7, x8 uintptr) {} +func main() { + C.foo = C.foo // ERROR HERE +} diff --git a/misc/cgo/errors/issue8442.go b/misc/cgo/errors/issue8442.go new file mode 100644 index 000000000..45daf8e59 --- /dev/null +++ b/misc/cgo/errors/issue8442.go @@ -0,0 +1,17 @@ +// Copyright 2014 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. + +package main + +// Issue 8442. Cgo output unhelpful error messages for +// invalid C preambles. + +/* +void issue8442foo(UNDEF*); // ERROR HERE +*/ +import "C" + +func main() { + C.issue8442foo(nil) +} diff --git a/misc/cgo/errors/test.bash b/misc/cgo/errors/test.bash index f0f60c844..c96264389 100755 --- a/misc/cgo/errors/test.bash +++ b/misc/cgo/errors/test.bash @@ -27,6 +27,8 @@ check() { check err1.go check err2.go check err3.go +check issue7757.go +check issue8442.go rm -rf errs _obj exit 0 diff --git a/misc/cgo/test/backdoor/backdoor.go b/misc/cgo/test/backdoor/backdoor.go index 7398772bd..3a973494b 100644 --- a/misc/cgo/test/backdoor/backdoor.go +++ b/misc/cgo/test/backdoor/backdoor.go @@ -4,5 +4,4 @@ package backdoor -func LockedOSThread() bool // in runtime.c -func Issue7695(x1, x2, x3, x4, x5, x6, x7, x8 uintptr) +func LockedOSThread() bool // in thunk.s diff --git a/misc/cgo/test/backdoor/runtime.c b/misc/cgo/test/backdoor/runtime.c deleted file mode 100644 index 7e6b44872..000000000 --- a/misc/cgo/test/backdoor/runtime.c +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2011 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. - -// Expose some runtime functions for testing. -// Must be in a non-cgo-using package so that -// the go command compiles this file with 6c, not gcc. - -// +build gc - -typedef char bool; - -bool runtime·lockedOSThread(void); - -static void -FLUSH(void*) -{ -} - -void -·LockedOSThread(bool b) -{ - b = runtime·lockedOSThread(); - FLUSH(&b); -} - -// This is what a cgo-compiled stub declaration looks like. -void -·Issue7695(struct{void *y[8*sizeof(void*)];}p) -{ - USED(p); -} diff --git a/misc/cgo/test/backdoor/thunk.s b/misc/cgo/test/backdoor/thunk.s new file mode 100644 index 000000000..ae735c8a3 --- /dev/null +++ b/misc/cgo/test/backdoor/thunk.s @@ -0,0 +1,16 @@ +// Copyright 2014 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. + +// Assembly to get into package runtime without using exported symbols. + +// +build amd64 amd64p32 arm 386 + +#include "textflag.h" + +#ifdef GOARCH_arm +#define JMP B +#endif + +TEXT ·LockedOSThread(SB),NOSPLIT,$0-0 + JMP runtime·lockedOSThread(SB) diff --git a/misc/cgo/test/basic.go b/misc/cgo/test/basic.go index 79cbf2b9c..019139d01 100644 --- a/misc/cgo/test/basic.go +++ b/misc/cgo/test/basic.go @@ -157,3 +157,8 @@ func testUnsignedInt(t *testing.T) { t.Errorf("Incorrect unsigned int - got %x, want %x", a, b) } } + +// Static (build-time) test that syntax traversal visits all operands of s[i:j:k]. +func sliceOperands(array [2000]int) { + _ = array[C.KILO:C.KILO:C.KILO] // no type error +} diff --git a/misc/cgo/test/buildid_linux.go b/misc/cgo/test/buildid_linux.go new file mode 100644 index 000000000..a3a86edfc --- /dev/null +++ b/misc/cgo/test/buildid_linux.go @@ -0,0 +1,77 @@ +// Copyright 2014 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. + +package cgotest + +// Test that we have no more than one build ID. In the past we used +// to generate a separate build ID for each package using cgo, and the +// linker concatenated them all. We don't want that--we only want +// one. + +import ( + "bytes" + "debug/elf" + "os" + "testing" +) + +func testBuildID(t *testing.T) { + f, err := elf.Open("/proc/self/exe") + if err != nil { + if os.IsNotExist(err) { + t.Skip("no /proc/self/exe") + } + t.Fatalf("opening /proc/self/exe: ", err) + } + defer f.Close() + + c := 0 + for i, s := range f.Sections { + if s.Type != elf.SHT_NOTE { + continue + } + + d, err := s.Data() + if err != nil { + t.Logf("reading data of note section %d: %v", i, err) + continue + } + + for len(d) > 0 { + + // ELF standards differ as to the sizes in + // note sections. Both the GNU linker and + // gold always generate 32-bit sizes, so that + // is what we assume here. + + if len(d) < 12 { + t.Logf("note section %d too short (%d < 12)", i, len(d)) + continue + } + + namesz := f.ByteOrder.Uint32(d) + descsz := f.ByteOrder.Uint32(d[4:]) + typ := f.ByteOrder.Uint32(d[8:]) + + an := (namesz + 3) &^ 3 + ad := (descsz + 3) &^ 3 + + if int(12+an+ad) > len(d) { + t.Logf("note section %d too short for header (%d < 12 + align(%d,4) + align(%d,4))", i, len(d), namesz, descsz) + continue + } + + // 3 == NT_GNU_BUILD_ID + if typ == 3 && namesz == 4 && bytes.Equal(d[12:16], []byte("GNU\000")) { + c++ + } + + d = d[12+an+ad:] + } + } + + if c > 1 { + t.Errorf("found %d build ID notes", c) + } +} diff --git a/misc/cgo/test/callback.go b/misc/cgo/test/callback.go index 82ed015bd..44167e6e9 100644 --- a/misc/cgo/test/callback.go +++ b/misc/cgo/test/callback.go @@ -9,16 +9,21 @@ void callback(void *f); void callGoFoo(void); void callGoStackCheck(void); void callPanic(void); +void callCgoAllocate(void); +int callGoReturnVal(void); +int returnAfterGrow(void); +int returnAfterGrowFromGo(void); */ import "C" import ( - "./backdoor" "path" "runtime" "strings" "testing" "unsafe" + + "./backdoor" ) // nestedCall calls into C, back into Go, and finally to f. @@ -152,11 +157,13 @@ func testCallbackCallers(t *testing.T) { n := 0 name := []string{ "test.goCallback", + "runtime.call16", "runtime.cgocallbackg1", "runtime.cgocallbackg", "runtime.cgocallback_gofunc", - "runtime.asmcgocall", - "runtime.cgocall", + "asmcgocall", + "runtime.asmcgocall_errno", + "runtime.cgocall_errno", "test._Cfunc_callback", "test.nestedCall", "test.testCallbackCallers", @@ -181,8 +188,12 @@ func testCallbackCallers(t *testing.T) { if strings.HasPrefix(fname, "_") { fname = path.Base(f.Name()[1:]) } - if fname != name[i] { - t.Errorf("expected function name %s, got %s", name[i], fname) + namei := "" + if i < len(name) { + namei = name[i] + } + if fname != namei { + t.Errorf("stk[%d] = %q, want %q", i, fname, namei) } } } @@ -200,6 +211,52 @@ func testPanicFromC(t *testing.T) { C.callPanic() } +func testAllocateFromC(t *testing.T) { + C.callCgoAllocate() // crashes or exits on failure +} + +// Test that C code can return a value if it calls a Go function that +// causes a stack copy. +func testReturnAfterGrow(t *testing.T) { + // Use a new goroutine so that we get a small stack. + c := make(chan int) + go func() { + c <- int(C.returnAfterGrow()) + }() + if got, want := <-c, 123456; got != want { + t.Errorf("got %d want %d", got, want) + } +} + +// Test that we can return a value from Go->C->Go if the Go code +// causes a stack copy. +func testReturnAfterGrowFromGo(t *testing.T) { + // Use a new goroutine so that we get a small stack. + c := make(chan int) + go func() { + c <- int(C.returnAfterGrowFromGo()) + }() + if got, want := <-c, 129*128/2; got != want { + t.Errorf("got %d want %d", got, want) + } +} + +//export goReturnVal +func goReturnVal() (r C.int) { + // Force a stack copy. + var f func(int) int + f = func(i int) int { + var buf [256]byte + use(buf[:]) + if i == 0 { + return 0 + } + return i + f(i-1) + } + r = C.int(f(128)) + return +} + func testCallbackStack(t *testing.T) { // Make cgo call and callback with different amount of stack stack available. // We do not do any explicit checks, just ensure that it does not crash. diff --git a/misc/cgo/test/callback_c.c b/misc/cgo/test/callback_c.c index dcd4ddd4e..5bb642534 100644 --- a/misc/cgo/test/callback_c.c +++ b/misc/cgo/test/callback_c.c @@ -64,3 +64,19 @@ callGoStackCheck(void) extern void goStackCheck(void); goStackCheck(); } + +int +returnAfterGrow(void) +{ + extern int goReturnVal(void); + goReturnVal(); + return 123456; +} + +int +returnAfterGrowFromGo(void) +{ + extern int goReturnVal(void); + return goReturnVal(); +} + diff --git a/misc/cgo/test/callback_c_gc.c b/misc/cgo/test/callback_c_gc.c index 8953b74a6..28a62c6db 100644 --- a/misc/cgo/test/callback_c_gc.c +++ b/misc/cgo/test/callback_c_gc.c @@ -5,11 +5,15 @@ // +build gc #include "_cgo_export.h" +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> /* Test calling panic from C. This is what SWIG does. */ extern void crosscall2(void (*fn)(void *, int), void *, int); extern void _cgo_panic(void *, int); +extern void _cgo_allocate(void *, int); void callPanic(void) @@ -19,3 +23,58 @@ callPanic(void) crosscall2(_cgo_panic, &a, sizeof a); *(int*)1 = 1; } + +/* Test calling cgo_allocate from C. This is what SWIG does. */ + +typedef struct List List; +struct List +{ + List *next; + int x; +}; + +void +callCgoAllocate(void) +{ + int i; + struct { size_t n; void *ret; } a; + List *l, *head, **tail; + + // Make sure this doesn't crash. + // And make sure it returns non-nil. + a.n = 0; + a.ret = 0; + crosscall2(_cgo_allocate, &a, sizeof a); + if(a.ret == 0) { + fprintf(stderr, "callCgoAllocate: alloc 0 returned nil\n"); + exit(2); + } + + head = 0; + tail = &head; + for(i=0; i<100; i++) { + a.n = sizeof *l; + crosscall2(_cgo_allocate, &a, sizeof a); + l = a.ret; + l->x = i; + l->next = 0; + *tail = l; + tail = &l->next; + } + + gc(); + + l = head; + for(i=0; i<100; i++) { + if(l->x != i) { + fprintf(stderr, "callCgoAllocate: lost memory\n"); + exit(2); + } + l = l->next; + } + if(l != 0) { + fprintf(stderr, "callCgoAllocate: lost memory\n"); + exit(2); + } +} + diff --git a/misc/cgo/test/callback_c_gccgo.c b/misc/cgo/test/callback_c_gccgo.c index 0ea7296c6..d367b7b68 100644 --- a/misc/cgo/test/callback_c_gccgo.c +++ b/misc/cgo/test/callback_c_gccgo.c @@ -5,13 +5,66 @@ // +build gccgo #include "_cgo_export.h" +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> /* Test calling panic from C. This is what SWIG does. */ extern void _cgo_panic(const char *); +extern void *_cgo_allocate(size_t); void callPanic(void) { _cgo_panic("panic from C"); } + +/* Test calling cgo_allocate from C. This is what SWIG does. */ + +typedef struct List List; +struct List +{ + List *next; + int x; +}; + +void +callCgoAllocate(void) +{ + int i; + List *l, *head, **tail; + + // Make sure this doesn't crash. + // And make sure it returns non-nil. + if(_cgo_allocate(0) == 0) { + fprintf(stderr, "callCgoAllocate: alloc 0 returned nil\n"); + exit(2); + } + + head = 0; + tail = &head; + for(i=0; i<100; i++) { + l = _cgo_allocate(sizeof *l); + l->x = i; + l->next = 0; + *tail = l; + tail = &l->next; + } + + gc(); + + l = head; + for(i=0; i<100; i++) { + if(l->x != i) { + fprintf(stderr, "callCgoAllocate: lost memory\n"); + exit(2); + } + l = l->next; + } + if(l != 0) { + fprintf(stderr, "callCgoAllocate: lost memory\n"); + exit(2); + } +} + diff --git a/misc/cgo/test/cgo_linux_test.go b/misc/cgo/test/cgo_linux_test.go index 0a405c7a3..4fe0db1b2 100644 --- a/misc/cgo/test/cgo_linux_test.go +++ b/misc/cgo/test/cgo_linux_test.go @@ -6,5 +6,6 @@ package cgotest import "testing" -func TestSetgid(t *testing.T) { testSetgid(t) } -func Test6997(t *testing.T) { test6997(t) } +func TestSetgid(t *testing.T) { testSetgid(t) } +func Test6997(t *testing.T) { test6997(t) } +func TestBuildID(t *testing.T) { testBuildID(t) } diff --git a/misc/cgo/test/cgo_test.go b/misc/cgo/test/cgo_test.go index e2e5a2bc1..fbdfac87a 100644 --- a/misc/cgo/test/cgo_test.go +++ b/misc/cgo/test/cgo_test.go @@ -10,49 +10,58 @@ import "testing" // so that they can use cgo (import "C"). // These wrappers are here for gotest to find. -func TestAlign(t *testing.T) { testAlign(t) } -func TestConst(t *testing.T) { testConst(t) } -func TestEnum(t *testing.T) { testEnum(t) } -func TestAtol(t *testing.T) { testAtol(t) } -func TestErrno(t *testing.T) { testErrno(t) } -func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) } -func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) } -func TestCallback(t *testing.T) { testCallback(t) } -func TestCallbackGC(t *testing.T) { testCallbackGC(t) } -func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) } -func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) } -func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) } -func TestPanicFromC(t *testing.T) { testPanicFromC(t) } -func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) } -func TestBlocking(t *testing.T) { testBlocking(t) } -func Test1328(t *testing.T) { test1328(t) } -func TestParallelSleep(t *testing.T) { testParallelSleep(t) } -func TestSetEnv(t *testing.T) { testSetEnv(t) } -func TestHelpers(t *testing.T) { testHelpers(t) } -func TestLibgcc(t *testing.T) { testLibgcc(t) } -func Test1635(t *testing.T) { test1635(t) } -func TestPrintf(t *testing.T) { testPrintf(t) } -func Test4029(t *testing.T) { test4029(t) } -func TestBoolAlign(t *testing.T) { testBoolAlign(t) } -func Test3729(t *testing.T) { test3729(t) } -func Test3775(t *testing.T) { test3775(t) } -func TestCthread(t *testing.T) { testCthread(t) } -func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) } -func Test5227(t *testing.T) { test5227(t) } -func TestCflags(t *testing.T) { testCflags(t) } -func Test5337(t *testing.T) { test5337(t) } -func Test5548(t *testing.T) { test5548(t) } -func Test5603(t *testing.T) { test5603(t) } -func Test6833(t *testing.T) { test6833(t) } -func Test3250(t *testing.T) { test3250(t) } -func TestCallbackStack(t *testing.T) { testCallbackStack(t) } -func TestFpVar(t *testing.T) { testFpVar(t) } -func Test4339(t *testing.T) { test4339(t) } -func Test6390(t *testing.T) { test6390(t) } -func Test5986(t *testing.T) { test5986(t) } -func Test7665(t *testing.T) { test7665(t) } -func TestNaming(t *testing.T) { testNaming(t) } -func Test7560(t *testing.T) { test7560(t) } -func Test7978(t *testing.T) { test7978(t) } +func TestAlign(t *testing.T) { testAlign(t) } +func TestConst(t *testing.T) { testConst(t) } +func TestEnum(t *testing.T) { testEnum(t) } +func TestAtol(t *testing.T) { testAtol(t) } +func TestErrno(t *testing.T) { testErrno(t) } +func TestMultipleAssign(t *testing.T) { testMultipleAssign(t) } +func TestUnsignedInt(t *testing.T) { testUnsignedInt(t) } +func TestCallback(t *testing.T) { testCallback(t) } +func TestCallbackGC(t *testing.T) { testCallbackGC(t) } +func TestCallbackPanic(t *testing.T) { testCallbackPanic(t) } +func TestCallbackPanicLoop(t *testing.T) { testCallbackPanicLoop(t) } +func TestCallbackPanicLocked(t *testing.T) { testCallbackPanicLocked(t) } +func TestPanicFromC(t *testing.T) { testPanicFromC(t) } +func TestAllocateFromC(t *testing.T) { testAllocateFromC(t) } +func TestZeroArgCallback(t *testing.T) { testZeroArgCallback(t) } +func TestBlocking(t *testing.T) { testBlocking(t) } +func Test1328(t *testing.T) { test1328(t) } +func TestParallelSleep(t *testing.T) { testParallelSleep(t) } +func TestSetEnv(t *testing.T) { testSetEnv(t) } +func TestHelpers(t *testing.T) { testHelpers(t) } +func TestLibgcc(t *testing.T) { testLibgcc(t) } +func Test1635(t *testing.T) { test1635(t) } +func TestPrintf(t *testing.T) { testPrintf(t) } +func Test4029(t *testing.T) { test4029(t) } +func TestBoolAlign(t *testing.T) { testBoolAlign(t) } +func Test3729(t *testing.T) { test3729(t) } +func Test3775(t *testing.T) { test3775(t) } +func TestCthread(t *testing.T) { testCthread(t) } +func TestCallbackCallers(t *testing.T) { testCallbackCallers(t) } +func Test5227(t *testing.T) { test5227(t) } +func TestCflags(t *testing.T) { testCflags(t) } +func Test5337(t *testing.T) { test5337(t) } +func Test5548(t *testing.T) { test5548(t) } +func Test5603(t *testing.T) { test5603(t) } +func Test6833(t *testing.T) { test6833(t) } +func Test3250(t *testing.T) { test3250(t) } +func TestCallbackStack(t *testing.T) { testCallbackStack(t) } +func TestFpVar(t *testing.T) { testFpVar(t) } +func Test4339(t *testing.T) { test4339(t) } +func Test6390(t *testing.T) { test6390(t) } +func Test5986(t *testing.T) { test5986(t) } +func Test7665(t *testing.T) { test7665(t) } +func TestNaming(t *testing.T) { testNaming(t) } +func Test7560(t *testing.T) { test7560(t) } +func Test5242(t *testing.T) { test5242(t) } +func Test8092(t *testing.T) { test8092(t) } +func Test7978(t *testing.T) { test7978(t) } +func Test8694(t *testing.T) { test8694(t) } +func Test8517(t *testing.T) { test8517(t) } +func Test8811(t *testing.T) { test8811(t) } +func TestReturnAfterGrow(t *testing.T) { testReturnAfterGrow(t) } +func TestReturnAfterGrowFromGo(t *testing.T) { testReturnAfterGrowFromGo(t) } +func Test9026(t *testing.T) { test9026(t) } func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) } diff --git a/misc/cgo/test/exports.go b/misc/cgo/test/exports.go index f96c60b00..4fe1703a6 100644 --- a/misc/cgo/test/exports.go +++ b/misc/cgo/test/exports.go @@ -5,8 +5,14 @@ package cgotest import "C" +import "runtime" //export ReturnIntLong func ReturnIntLong() (int, C.long) { return 1, 2 } + +//export gc +func gc() { + runtime.GC() +} diff --git a/misc/cgo/test/issue5242.go b/misc/cgo/test/issue5242.go new file mode 100644 index 000000000..fe0a6321c --- /dev/null +++ b/misc/cgo/test/issue5242.go @@ -0,0 +1,31 @@ +// Copyright 2014 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 5242. Cgo incorrectly computed the alignment of structs +// with no Go accessible fields as 0, and then panicked on +// modulo-by-zero computations. + +package cgotest + +/* +typedef struct { +} foo; + +typedef struct { + int x : 1; +} bar; + +int issue5242(foo f, bar b) { + return 5242; +} +*/ +import "C" + +import "testing" + +func test5242(t *testing.T) { + if got := C.issue5242(C.foo{}, C.bar{}); got != 5242 { + t.Errorf("got %v", got) + } +} diff --git a/misc/cgo/test/issue5548.go b/misc/cgo/test/issue5548.go index b41f46562..c879f2ae9 100644 --- a/misc/cgo/test/issue5548.go +++ b/misc/cgo/test/issue5548.go @@ -14,13 +14,14 @@ import "C" //export issue5548FromC func issue5548FromC(s string, i int) int { if len(s) == 4 && s == "test" && i == 42 { - return 1 + return 12345 } - return 0 + println("got", len(s), i) + return 9876 } func test5548(t *testing.T) { - if C.issue5548_in_c() == 0 { - t.Fail() + if x := C.issue5548_in_c(); x != 12345 { + t.Errorf("issue5548_in_c = %d, want %d", x, 12345) } } diff --git a/misc/cgo/test/issue6997_linux.go b/misc/cgo/test/issue6997_linux.go index 871bd517a..5455f0c53 100644 --- a/misc/cgo/test/issue6997_linux.go +++ b/misc/cgo/test/issue6997_linux.go @@ -34,7 +34,7 @@ func test6997(t *testing.T) { if r == 0 { t.Error("pthread finished but wasn't cancelled??") } - case <-time.After(5 * time.Second): + case <-time.After(30 * time.Second): t.Error("hung in pthread_cancel/pthread_join") } } diff --git a/misc/cgo/test/issue7695_test.go b/misc/cgo/test/issue7695_test.go deleted file mode 100644 index 4bd6f8e73..000000000 --- a/misc/cgo/test/issue7695_test.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 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. - -// Demo of deferred C function with untrue prototype -// breaking stack copying. See golang.org/issue/7695. - -package cgotest - -import ( - "testing" - - "./backdoor" -) - -func TestIssue7695(t *testing.T) { - defer backdoor.Issue7695(1, 0, 2, 0, 0, 3, 0, 4) - recurse(100) -} - -func recurse(n int) { - var x [128]int - n += x[0] - if n > 0 { - recurse(n - 1) - } -} diff --git a/misc/cgo/test/issue7978.go b/misc/cgo/test/issue7978.go index 432e006eb..5feed07b9 100644 --- a/misc/cgo/test/issue7978.go +++ b/misc/cgo/test/issue7978.go @@ -83,21 +83,21 @@ func issue7978go() { func test7978(t *testing.T) { if os.Getenv("GOTRACEBACK") != "2" { - t.Fatal("GOTRACEBACK must be 2") + t.Fatalf("GOTRACEBACK must be 2") } issue7978sync = 0 go issue7978go() // test in c code, before callback issue7978wait(0, 1) - issue7978check(t, "runtime.cgocall(", "", 1) + issue7978check(t, "runtime.cgocall_errno(", "", 1) // test in go code, during callback issue7978wait(2, 3) - issue7978check(t, "test.issue7978cb(", "test.issue7978go", 4) + issue7978check(t, "test.issue7978cb(", "test.issue7978go", 3) // test in c code, after callback issue7978wait(4, 5) - issue7978check(t, "runtime.cgocall(", "runtime.cgocallback", 1) + issue7978check(t, "runtime.cgocall_errno(", "runtime.cgocallback", 1) // test in go code, after return from cgo issue7978wait(6, 7) - issue7978check(t, "test.issue7978go(", "", 4) + issue7978check(t, "test.issue7978go(", "", 3) atomic.StoreUint32(&issue7978sync, 8) } diff --git a/misc/cgo/test/issue8092.go b/misc/cgo/test/issue8092.go new file mode 100644 index 000000000..8a14ce6d7 --- /dev/null +++ b/misc/cgo/test/issue8092.go @@ -0,0 +1,36 @@ +// Copyright 2014 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 8092. Test that linker defined symbols (e.g., text, data) don't +// conflict with C symbols. + +package cgotest + +/* +char text[] = "text"; +char data[] = "data"; +char *ctext(void) { return text; } +char *cdata(void) { return data; } +*/ +import "C" + +import "testing" + +func test8092(t *testing.T) { + tests := []struct { + s string + a, b *C.char + }{ + {"text", &C.text[0], C.ctext()}, + {"data", &C.data[0], C.cdata()}, + } + for _, test := range tests { + if test.a != test.b { + t.Errorf("%s: pointer mismatch: %v != %v", test.s, test.a, test.b) + } + if got := C.GoString(test.a); got != test.s { + t.Errorf("%s: points at %#v, want %#v", test.s, got, test.s) + } + } +} diff --git a/misc/cgo/test/issue8428.go b/misc/cgo/test/issue8428.go new file mode 100644 index 000000000..a3dc5755c --- /dev/null +++ b/misc/cgo/test/issue8428.go @@ -0,0 +1,52 @@ +// Copyright 2014 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. + +// This test fails on older versions of OS X because they use older buggy +// versions of Clang that emit ambiguous DWARF info. See issue 8611. +// +build !darwin + +package cgotest + +// Issue 8428. Cgo inconsistently translated zero size arrays. + +/* +struct issue8428one { + char b; + char rest[]; +}; + +struct issue8428two { + void *p; + char b; + char rest[0]; +}; + +struct issue8428three { + char w[1][2][3][0]; + char x[2][3][0][1]; + char y[3][0][1][2]; + char z[0][1][2][3]; +}; +*/ +import "C" + +import "unsafe" + +var _ = C.struct_issue8428one{ + b: C.char(0), + rest: [0]C.char{}, +} + +var _ = C.struct_issue8428two{ + p: unsafe.Pointer(nil), + b: C.char(0), + rest: [0]C.char{}, +} + +var _ = C.struct_issue8428three{ + w: [1][2][3][0]C.char{}, + x: [2][3][0][1]C.char{}, + y: [3][0][1][2]C.char{}, + z: [0][1][2][3]C.char{}, +} diff --git a/misc/cgo/test/issue8517.go b/misc/cgo/test/issue8517.go new file mode 100644 index 000000000..4e431df92 --- /dev/null +++ b/misc/cgo/test/issue8517.go @@ -0,0 +1,13 @@ +// Copyright 2014 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. + +// +build !windows + +package cgotest + +import "testing" + +func test8517(t *testing.T) { + t.Skip("skipping windows only test") +} diff --git a/misc/cgo/test/issue8517_windows.c b/misc/cgo/test/issue8517_windows.c new file mode 100644 index 000000000..a0b94c126 --- /dev/null +++ b/misc/cgo/test/issue8517_windows.c @@ -0,0 +1,24 @@ +// Copyright 2014 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. + +#include "windows.h" + +extern void testHandleLeaksCallback(); + +DWORD WINAPI testHandleLeaksFunc(LPVOID lpThreadParameter) +{ + int i; + for(i = 0; i < 100; i++) { + testHandleLeaksCallback(); + } + return 0; +} + +void testHandleLeaks() +{ + HANDLE h; + h = CreateThread(NULL, 0, &testHandleLeaksFunc, 0, 0, NULL); + WaitForSingleObject(h, INFINITE); + CloseHandle(h); +} diff --git a/misc/cgo/test/issue8517_windows.go b/misc/cgo/test/issue8517_windows.go new file mode 100644 index 000000000..3782631e9 --- /dev/null +++ b/misc/cgo/test/issue8517_windows.go @@ -0,0 +1,45 @@ +// Copyright 2014 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. + +package cgotest + +//void testHandleLeaks(); +import "C" + +import ( + "syscall" + "testing" + "unsafe" +) + +var issue8517counter int + +var ( + kernel32 = syscall.MustLoadDLL("kernel32.dll") + getProcessHandleCount = kernel32.MustFindProc("GetProcessHandleCount") +) + +func processHandleCount(t *testing.T) int { + const current_process = ^uintptr(0) + var c uint32 + r, _, err := getProcessHandleCount.Call(current_process, uintptr(unsafe.Pointer(&c))) + if r == 0 { + t.Fatal(err) + } + return int(c) +} + +func test8517(t *testing.T) { + c1 := processHandleCount(t) + C.testHandleLeaks() + c2 := processHandleCount(t) + if c1+issue8517counter <= c2 { + t.Fatalf("too many handles leaked: issue8517counter=%v c1=%v c2=%v", issue8517counter, c1, c2) + } +} + +//export testHandleLeaksCallback +func testHandleLeaksCallback() { + issue8517counter++ +} diff --git a/misc/cgo/test/issue8694.go b/misc/cgo/test/issue8694.go new file mode 100644 index 000000000..1876f782d --- /dev/null +++ b/misc/cgo/test/issue8694.go @@ -0,0 +1,38 @@ +// Copyright 2014 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. + +package cgotest + +/* +#include <complex.h> + +complex float complexFloatSquared(complex float a) { return a*a; } +complex double complexDoubleSquared(complex double a) { return a*a; } +*/ +import "C" + +import ( + "runtime" + "testing" +) + +func test8694(t *testing.T) { + if runtime.GOARCH == "arm" { + t.Skip("test8694 is disabled on ARM because 5l cannot handle thumb library.") + } + // Really just testing that this compiles, but check answer anyway. + x := complex64(2 + 3i) + x2 := x * x + cx2 := C.complexFloatSquared(x) + if cx2 != x2 { + t.Errorf("C.complexFloatSquared(%v) = %v, want %v", x, cx2, x2) + } + + y := complex128(2 + 3i) + y2 := y * y + cy2 := C.complexDoubleSquared(y) + if cy2 != y2 { + t.Errorf("C.complexDoubleSquared(%v) = %v, want %v", y, cy2, y2) + } +} diff --git a/misc/cgo/test/issue8811.c b/misc/cgo/test/issue8811.c new file mode 100644 index 000000000..584bb3934 --- /dev/null +++ b/misc/cgo/test/issue8811.c @@ -0,0 +1,8 @@ +// Copyright 2014 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. + +int issue8811Initialized = 0; + +void issue8811Init() { +} diff --git a/misc/cgo/test/issue8811.go b/misc/cgo/test/issue8811.go new file mode 100644 index 000000000..2e217d935 --- /dev/null +++ b/misc/cgo/test/issue8811.go @@ -0,0 +1,22 @@ +// Copyright 2014 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. + +package cgotest + +/* +extern int issue8811Initialized; +extern void issue8811Init(); + +void issue8811Execute() { + if(!issue8811Initialized) + issue8811Init(); +} +*/ +import "C" + +import "testing" + +func test8811(t *testing.T) { + C.issue8811Execute() +} diff --git a/misc/cgo/test/issue8828.go b/misc/cgo/test/issue8828.go new file mode 100644 index 000000000..304797c92 --- /dev/null +++ b/misc/cgo/test/issue8828.go @@ -0,0 +1,16 @@ +// compile + +// Copyright 2014 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 8828: compiling a file with -compiler=gccgo fails if a .c file +// has the same name as compiled directory. + +package cgotest + +import "./issue8828" + +func p() { + issue8828.Bar() +} diff --git a/misc/cgo/test/issue8828/issue8828.c b/misc/cgo/test/issue8828/issue8828.c new file mode 100644 index 000000000..2950f87cf --- /dev/null +++ b/misc/cgo/test/issue8828/issue8828.c @@ -0,0 +1,7 @@ +// Copyright 2014 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. + +void foo() +{ +} diff --git a/misc/cgo/test/issue8828/trivial.go b/misc/cgo/test/issue8828/trivial.go new file mode 100644 index 000000000..e7b9a4e57 --- /dev/null +++ b/misc/cgo/test/issue8828/trivial.go @@ -0,0 +1,8 @@ +package issue8828 + +//void foo(); +import "C" + +func Bar() { + C.foo() +} diff --git a/misc/cgo/test/issue9026.go b/misc/cgo/test/issue9026.go new file mode 100644 index 000000000..8848d0e81 --- /dev/null +++ b/misc/cgo/test/issue9026.go @@ -0,0 +1,9 @@ +package cgotest + +import ( + "testing" + + "./issue9026" +) + +func test9026(t *testing.T) { issue9026.Test(t) } diff --git a/misc/cgo/test/issue9026/issue9026.go b/misc/cgo/test/issue9026/issue9026.go new file mode 100644 index 000000000..0af86e64d --- /dev/null +++ b/misc/cgo/test/issue9026/issue9026.go @@ -0,0 +1,36 @@ +package issue9026 + +// This file appears in its own package since the assertion tests the +// per-package counter used to create fresh identifiers. + +/* +typedef struct {} git_merge_file_input; + +typedef struct {} git_merge_file_options; + +void git_merge_file( + git_merge_file_input *in, + git_merge_file_options *opts) {} +*/ +import "C" +import ( + "fmt" + "testing" +) + +func Test(t *testing.T) { + var in C.git_merge_file_input + var opts *C.git_merge_file_options + C.git_merge_file(&in, opts) + + // Test that the generated type names are deterministic. + // (Previously this would fail about 10% of the time.) + // + // Brittle: the assertion may fail spuriously when the algorithm + // changes, but should remain stable otherwise. + got := fmt.Sprintf("%T %T", in, opts) + want := "issue9026._Ctype_struct___0 *issue9026._Ctype_struct___1" + if got != want { + t.Errorf("Non-deterministic type names: got %s, want %s", got, want) + } +} diff --git a/misc/cgo/testcdefs/cdefstest.c b/misc/cgo/testcdefs/cdefstest.c index 10cdd66b6..ce670e729 100644 --- a/misc/cgo/testcdefs/cdefstest.c +++ b/misc/cgo/testcdefs/cdefstest.c @@ -6,3 +6,4 @@ #include "cdefstest.h" struct CdefsTest test; +struct PackedTest packed; diff --git a/misc/cgo/testcdefs/cdefstest.go b/misc/cgo/testcdefs/cdefstest.go index e6305b77d..5e613c79e 100644 --- a/misc/cgo/testcdefs/cdefstest.go +++ b/misc/cgo/testcdefs/cdefstest.go @@ -35,7 +35,26 @@ struct cdefsTest { // Correct: -> Array [20][20]**int8 -> int8 **array[20][20] char **array5[20][20]; }; + +// Test that packed structures can be translated to C correctly too. +// See issue 8477. + +struct packedTest { + char first; + int second; + long long third; +} __attribute__((packed)); + +// Test that conflicting type definitions don't cause problems with cgo. +// See issue 8477. + +typedef struct timespec { + double bogus; +} pid_t; + */ import "C" type CdefsTest C.struct_cdefsTest + +//type PackedTest C.struct_packedTest diff --git a/misc/cgo/testcdefs/main.c b/misc/cgo/testcdefs/main.c index 2d3ee4dbe..594a43167 100644 --- a/misc/cgo/testcdefs/main.c +++ b/misc/cgo/testcdefs/main.c @@ -17,11 +17,25 @@ struct CdefsOrig { int8 **array5[20][20]; }; +// Packed structs are no longer supported for -cdefs. +/* +typedef struct PackedOrig PackedOrig; +#pragma pack on +struct PackedOrig { + int8 first; + int32 second; + int64 third; +}; +#pragma pack off +*/ + void main·test(int32 ret) { CdefsOrig o; CdefsTest t; + // PackedOrig po; + // PackedTest pt; ret = 0; if(sizeof(t.array1) != sizeof(o.array1) || offsetof(CdefsTest, array1[0]) != offsetof(CdefsOrig, array1[0])) { @@ -44,5 +58,19 @@ main·test(int32 ret) runtime·printf("array5: size, offset = %d, %d, want %d, %d\n", sizeof(t.array5), offsetof(CdefsTest, array5[0][0]), sizeof(o.array5), offsetof(CdefsOrig, array5[0][0])); ret = 1; } +/* + if(sizeof(pt.first) != sizeof(po.first) || offsetof(PackedTest, first) != offsetof(PackedOrig, first)) { + runtime·printf("first: size, offset = %d, %d, want %d, %d\n", sizeof(pt.first), offsetof(PackedTest, first), sizeof(po.first), offsetof(PackedOrig, first)); + ret = 1; + } + if(sizeof(pt.second) != sizeof(po.second) || offsetof(PackedTest, second) != offsetof(PackedOrig, second)) { + runtime·printf("second: size, offset = %d, %d, want %d, %d\n", sizeof(pt.second), offsetof(PackedTest, second), sizeof(po.second), offsetof(PackedOrig, second)); + ret = 1; + } + if(sizeof(pt.third) != sizeof(po.third) || offsetof(PackedTest, third) != offsetof(PackedOrig, third)) { + runtime·printf("third: size, offset = %d, %d, want %d, %d\n", sizeof(pt.third), offsetof(PackedTest, third), sizeof(po.third), offsetof(PackedOrig, third)); + ret = 1; + } +*/ FLUSH(&ret); // flush return value } diff --git a/misc/cgo/testgodefs/anonunion.go b/misc/cgo/testgodefs/anonunion.go new file mode 100644 index 000000000..7bc736b9d --- /dev/null +++ b/misc/cgo/testgodefs/anonunion.go @@ -0,0 +1,26 @@ +// Copyright 2014 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. +// +// +build ignore + +package main + +// This file tests that when cgo -godefs sees a struct with a field +// that is an anonymous union, the first field in the union is +// promoted to become a field of the struct. See issue 6677 for +// background. + +/* +typedef struct { + union { + long l; + int c; + }; +} t; +*/ +import "C" + +// Input for cgo -godefs. + +type T C.t diff --git a/misc/cgo/testgodefs/issue8478.go b/misc/cgo/testgodefs/issue8478.go new file mode 100644 index 000000000..92258fde7 --- /dev/null +++ b/misc/cgo/testgodefs/issue8478.go @@ -0,0 +1,20 @@ +// Copyright 2014 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. +// +// +build ignore + +package main + +// Issue 8478. Test that void* is consistently mapped to *byte. + +/* +typedef struct { + void *p; + void **q; + void ***r; +} s; +*/ +import "C" + +type Issue8478 C.s diff --git a/misc/cgo/testgodefs/main.go b/misc/cgo/testgodefs/main.go new file mode 100644 index 000000000..7faccf265 --- /dev/null +++ b/misc/cgo/testgodefs/main.go @@ -0,0 +1,15 @@ +// Copyright 2014 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. + +package main + +// Test that the struct field in anonunion.go was promoted. +var v1 T +var v2 = v1.L + +// Test that P, Q, and R all point to byte. +var v3 = Issue8478{P: (*byte)(nil), Q: (**byte)(nil), R: (***byte)(nil)} + +func main() { +} diff --git a/misc/cgo/testgodefs/test.bash b/misc/cgo/testgodefs/test.bash new file mode 100755 index 000000000..5281b1056 --- /dev/null +++ b/misc/cgo/testgodefs/test.bash @@ -0,0 +1,20 @@ +# Copyright 2014 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. + +# We are testing cgo -godefs, which translates Go files that use +# import "C" into Go files with Go definitions of types defined in the +# import "C" block. Add more tests here. +FILE_PREFIXES="anonunion issue8478" + +RM= +for FP in $FILE_PREFIXES +do + go tool cgo -godefs ${FP}.go > ${FP}_defs.go + RM="${RM} ${FP}_defs.go" +done + +go build . && ./testgodefs +EXIT=$? +rm -rf _obj testgodefs ${RM} +exit $EXIT |