// Copyright 2010 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. // Test cases for cgo. // Both the import "C" prologue and the main file are sorted by issue number. // This file contains C definitions (not just declarations) // and so it must NOT contain any //export directives on Go functions. // See testx.go for exports. package cgotest /* #include #include #include #include #include #include #include #include #include #include #include #include #cgo !darwin LDFLAGS: -lm #ifndef WIN32 #include #include #endif // alignment tests typedef unsigned char Uint8; typedef unsigned short Uint16; typedef enum { MOD1 = 0x0000, MODX = 0x8000 } SDLMod; typedef enum { A1 = 1, B1 = 322, SDLK_LAST } SDLKey; typedef struct SDL_keysym { Uint8 scancode; SDLKey sym; SDLMod mod; Uint16 unicode; } SDL_keysym; typedef struct SDL_KeyboardEvent { Uint8 typ; Uint8 which; Uint8 state; SDL_keysym keysym; } SDL_KeyboardEvent; void makeEvent(SDL_KeyboardEvent *event) { unsigned char *p; int i; p = (unsigned char*)event; for (i=0; ityp == typ && e->which == which && e->state == state && e->keysym.scancode == scan && e->keysym.sym == sym && e->keysym.mod == mod && e->keysym.unicode == uni; } void cTest(SDL_KeyboardEvent *event) { printf("C: %#x %#x %#x %#x %#x %#x %#x\n", event->typ, event->which, event->state, event->keysym.scancode, event->keysym.sym, event->keysym.mod, event->keysym.unicode); fflush(stdout); } // api const char *greeting = "hello, world"; // basic test cases #define SHIFT(x, y) ((x)<<(y)) #define KILO SHIFT(1, 10) #define UINT32VAL 0xc008427bU enum E { Enum1 = 1, Enum2 = 2, }; typedef unsigned char cgo_uuid_t[20]; void uuid_generate(cgo_uuid_t x) { x[0] = 0; } struct S { int x; }; const char *cstr = "abcefghijklmnopqrstuvwxyzABCEFGHIJKLMNOPQRSTUVWXYZ1234567890"; extern enum E myConstFunc(struct S* const ctx, int const id, struct S **const filter); enum E myConstFunc(struct S *const ctx, int const id, struct S **const filter) { return 0; } int add(int x, int y) { return x+y; }; // escape vs noescape // TODO(#56378): enable in Go 1.23: // #cgo noescape handleGoStringPointerNoescape void handleGoStringPointerNoescape(void *s) {} void handleGoStringPointerEscape(void *s) {} // Following mimics vulkan complex definitions for benchmarking cgocheck overhead. typedef uint32_t VkFlags; typedef VkFlags VkDeviceQueueCreateFlags; typedef uint32_t VkStructureType; typedef struct VkDeviceQueueCreateInfo { VkStructureType sType; const void* pNext; VkDeviceQueueCreateFlags flags; uint32_t queueFamilyIndex; uint32_t queueCount; const float* pQueuePriorities; } VkDeviceQueueCreateInfo; typedef struct VkPhysicalDeviceFeatures { uint32_t bools[56]; } VkPhysicalDeviceFeatures; typedef struct VkDeviceCreateInfo { VkStructureType sType; const void* pNext; VkFlags flags; uint32_t queueCreateInfoCount; const VkDeviceQueueCreateInfo* pQueueCreateInfos; uint32_t enabledLayerCount; const char* const* ppEnabledLayerNames; uint32_t enabledExtensionCount; const char* const* ppEnabledExtensionNames; const VkPhysicalDeviceFeatures* pEnabledFeatures; } VkDeviceCreateInfo; void handleComplexPointer(VkDeviceCreateInfo *a0) {} void handleComplexPointer8( VkDeviceCreateInfo *a0, VkDeviceCreateInfo *a1, VkDeviceCreateInfo *a2, VkDeviceCreateInfo *a3, VkDeviceCreateInfo *a4, VkDeviceCreateInfo *a5, VkDeviceCreateInfo *a6, VkDeviceCreateInfo *a7 ) {} // complex alignment struct { float x; _Complex float y; } cplxAlign = { 3.14, 2.17 }; // constants and pointer checking #define CheckConstVal 0 typedef struct { int *p; } CheckConstStruct; static void CheckConstFunc(CheckConstStruct *p, int e) {} // duplicate symbol int base_symbol = 0; #define alias_one base_symbol #define alias_two base_symbol // function pointer variables typedef int (*intFunc) (); int bridge_int_func(intFunc f) { return f(); } int fortytwo() { return 42; } // issue 1222 typedef union { long align; } xxpthread_mutex_t; struct ibv_async_event { union { int x; } element; }; struct ibv_context { xxpthread_mutex_t mutex; }; // issue 1635 // Mac OS X's gcc will generate scattered relocation 2/1 for // this function on Darwin/386, and 8l couldn't handle it. // this example is in issue 1635 void scatter() { void *p = scatter; printf("scatter = %p\n", p); } // Adding this explicit extern declaration makes this a test for // https://gcc.gnu.org/PR68072 aka https://golang.org/issue/13344 . // It used to cause a cgo error when building with GCC 6. extern int hola; // this example is in issue 3253 int hola = 0; int testHola() { return hola; } // issue 3250 #ifdef WIN32 void testSendSIG() {} #else static void *thread(void *p) { const int M = 100; int i; (void)p; for (i = 0; i < M; i++) { pthread_kill(pthread_self(), SIGCHLD); usleep(rand() % 20 + 5); } return NULL; } void testSendSIG() { const int N = 20; int i; pthread_t tid[N]; for (i = 0; i < N; i++) { usleep(rand() % 200 + 100); pthread_create(&tid[i], 0, thread, NULL); } for (i = 0; i < N; i++) pthread_join(tid[i], 0); } #endif // issue 3261 // libgcc on ARM might be compiled as thumb code, but our 5l // can't handle that, so we have to disable this test on arm. #ifdef __ARMEL__ int vabs(int x) { puts("testLibgcc is disabled on ARM because 5l cannot handle thumb library."); return (x < 0) ? -x : x; } #elif defined(__arm64__) && defined(__clang__) int vabs(int x) { puts("testLibgcc is disabled on ARM64 with clang due to lack of libgcc."); return (x < 0) ? -x : x; } #else int __absvsi2(int); // dummy prototype for libgcc function // we shouldn't name the function abs, as gcc might use // the builtin one. int vabs(int x) { return __absvsi2(x); } #endif // issue 3729 // access errno from void C function const char _expA = 0x42; const float _expB = 3.14159; const short _expC = 0x55aa; const int _expD = 0xdeadbeef; #ifdef WIN32 void g(void) {} void g2(int x, char a, float b, short c, int d) {} #else void g(void) { errno = E2BIG; } // try to pass some non-trivial arguments to function g2 void g2(int x, char a, float b, short c, int d) { if (a == _expA && b == _expB && c == _expC && d == _expD) errno = x; else errno = -1; } #endif // issue 3945 // Test that cgo reserves enough stack space during cgo call. // See https://golang.org/issue/3945 for details. void say() { printf("%s from C\n", "hello"); } // issue 4054 part 1 - other half in testx.go typedef enum { A = 0, B, C, D, E, F, G, H, II, J, } issue4054a; // issue 4339 // We've historically permitted #include <>, so test it here. Issue 29333. // Also see issue 41059. #include // issue 4417 // cmd/cgo: bool alignment/padding issue. // bool alignment is wrong and causing wrong arguments when calling functions. static int c_bool(bool a, bool b, int c, bool d, bool e) { return c; } // issue 4857 #cgo CFLAGS: -Werror const struct { int a; } *issue4857() { return (void *)0; } // issue 5224 // Test that the #cgo CFLAGS directive works, // with and without platform filters. #cgo CFLAGS: -DCOMMON_VALUE=123 #cgo windows CFLAGS: -DIS_WINDOWS=1 #cgo !windows CFLAGS: -DIS_WINDOWS=0 int common = COMMON_VALUE; int is_windows = IS_WINDOWS; // issue 5227 // linker incorrectly treats common symbols and // leaves them undefined. typedef struct { int Count; } Fontinfo; Fontinfo SansTypeface; extern void init(); Fontinfo loadfont() { Fontinfo f = {0}; return f; } void init() { SansTypeface = loadfont(); } // issue 5242 // Cgo incorrectly computed the alignment of structs // with no Go accessible fields as 0, and then panicked on // modulo-by-zero computations. // issue 50987 // disable arm64 GCC warnings #cgo CFLAGS: -Wno-psabi -Wno-unknown-warning-option typedef struct { } foo; typedef struct { int x : 1; } bar; int issue5242(foo f, bar b) { return 5242; } // issue 5337 // Verify that we can withstand SIGPROF received on foreign threads #ifdef WIN32 void test5337() {} #else static void *thread1(void *p) { (void)p; pthread_kill(pthread_self(), SIGPROF); return NULL; } void test5337() { pthread_t tid; pthread_create(&tid, 0, thread1, NULL); pthread_join(tid, 0); } #endif // issue 5603 const long long issue5603exp = 0x12345678; long long issue5603foo0() { return issue5603exp; } long long issue5603foo1(void *p) { return issue5603exp; } long long issue5603foo2(void *p, void *q) { return issue5603exp; } long long issue5603foo3(void *p, void *q, void *r) { return issue5603exp; } long long issue5603foo4(void *p, void *q, void *r, void *s) { return issue5603exp; } // issue 5740 int test5740a(void), test5740b(void); // issue 5986 static void output5986() { int current_row = 0, row_count = 0; double sum_squares = 0; double d; do { if (current_row == 10) { current_row = 0; } ++row_count; } while (current_row++ != 1); d = sqrt(sum_squares / row_count); printf("sqrt is: %g\n", d); } // issue 6128 // Test handling of #defined names in clang. // NOTE: Must use hex, or else a shortcut for decimals // in cgo avoids trying to pass this to clang. #define X 0x1 // issue 6472 typedef struct { struct { int x; } y[16]; } z; // issue 6612 // Test new scheme for deciding whether C.name is an expression, type, constant. // Clang silences some warnings when the name is a #defined macro, so test those too // (even though we now use errors exclusively, not warnings). void myfunc(void) {} int myvar = 5; const char *mytext = "abcdef"; typedef int mytype; enum { myenum = 1234, }; #define myfunc_def myfunc #define myvar_def myvar #define mytext_def mytext #define mytype_def mytype #define myenum_def myenum #define myint_def 12345 #define myfloat_def 1.5 #define mystring_def "hello" // issue 6907 char* Issue6907CopyString(_GoString_ s) { size_t n; const char *p; char *r; n = _GoStringLen(s); p = _GoStringPtr(s); r = malloc(n + 1); memmove(r, p, n); r[n] = '\0'; return r; } // issue 7560 typedef struct { char x; long y; } __attribute__((__packed__)) misaligned; int offset7560(void) { return (uintptr_t)&((misaligned*)0)->y; } // issue 7786 // No runtime test, just make sure that typedef and struct/union/class are interchangeable at compile time. struct test7786; typedef struct test7786 typedef_test7786; void f7786(struct test7786 *ctx) {} void g7786(typedef_test7786 *ctx) {} typedef struct body7786 typedef_body7786; struct body7786 { int x; }; void b7786(struct body7786 *ctx) {} void c7786(typedef_body7786 *ctx) {} typedef union union7786 typedef_union7786; void u7786(union union7786 *ctx) {} void v7786(typedef_union7786 *ctx) {} // issue 8092 // Test that linker defined symbols (e.g., text, data) don't // conflict with C symbols. char text[] = "text"; char data[] = "data"; char *ctext(void) { return text; } char *cdata(void) { return data; } // issue 8428 // Cgo inconsistently translated zero size arrays. struct issue8428one { char b; char rest[]; }; struct issue8428two { void *p; char b; char rest[0]; char pad; }; 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]; }; // issue 8331 part 1 - part 2 in testx.go // A typedef of an unnamed struct is the same struct when // #include'd twice. No runtime test; just make sure it compiles. #include "issue8331.h" // issue 8368 and 8441 // Recursive struct definitions didn't work. // No runtime test; just make sure it compiles. typedef struct one one; typedef struct two two; struct one { two *x; }; struct two { one *x; }; // issue 8811 extern int issue8811Initialized; extern void issue8811Init(); void issue8811Execute() { if(!issue8811Initialized) issue8811Init(); } // issue 8945 typedef void (*PFunc8945)(); PFunc8945 func8945; // issue 9557 struct issue9557_t { int a; } test9557bar = { 42 }; struct issue9557_t *issue9557foo = &test9557bar; // issue 10303 // Pointers passed to C were not marked as escaping (bug in cgo). typedef int *intptr; void setintstar(int *x) { *x = 1; } void setintptr(intptr x) { *x = 1; } void setvoidptr(void *x) { *(int*)x = 1; } typedef struct Struct Struct; struct Struct { int *P; }; void setstruct(Struct s) { *s.P = 1; } // issue 11925 // Structs with zero-length trailing fields are now padded by the Go compiler. struct a11925 { int i; char a[0]; char b[0]; }; struct b11925 { int i; char a[0]; char b[]; }; // issue 12030 void issue12030conv(char *buf, double x) { sprintf(buf, "d=%g", x); } // issue 14838 int check_cbytes(char *b, size_t l) { int i; for (i = 0; i < l; i++) { if (b[i] != i) { return 0; } } return 1; } // issue 17065 // Test that C symbols larger than a page play nicely with the race detector. int ii[65537]; // issue 17537 // The void* cast introduced by cgo to avoid problems // with const/volatile qualifiers breaks C preprocessor macros that // emulate functions. typedef struct { int i; } S17537; int I17537(S17537 *p); #define I17537(p) ((p)->i) // Calling this function used to fail without the cast. const int F17537(const char **p) { return **p; } // issue 17723 // API compatibility checks typedef char *cstring_pointer; static void cstring_pointer_fun(cstring_pointer dummy) { } const char *api_hello = "hello!"; // Calling this function used to trigger an error from the C compiler // (issue 18298). void F18298(const void *const *p) { } // Test that conversions between typedefs work as they used to. typedef const void *T18298_1; struct S18298 { int i; }; typedef const struct S18298 *T18298_2; void G18298(T18298_1 t) { } // issue 18126 // cgo check of void function returning errno. void Issue18126C(void **p) {} // issue 18720 #define HELLO "hello" #define WORLD "world" #define HELLO_WORLD HELLO "\000" WORLD struct foo { char c; }; #define SIZE_OF(x) sizeof(x) #define SIZE_OF_FOO SIZE_OF(struct foo) #define VAR1 VAR #define VAR var int var = 5; #define ADDR &var #define CALL fn() int fn(void) { return ++var; } // issue 20129 int issue20129 = 0; typedef void issue20129Void; issue20129Void issue20129Foo() { issue20129 = 1; } typedef issue20129Void issue20129Void2; issue20129Void2 issue20129Bar() { issue20129 = 2; } // issue 20369 #define XUINT64_MAX 18446744073709551615ULL // issue 21668 // Fail to guess the kind of the constant "x". // No runtime test; just make sure it compiles. const int x21668 = 42; // issue 21708 #define CAST_TO_INT64 (int64_t)(-1) // issue 21809 // Compile C `typedef` to go type aliases. typedef long MySigned_t; // tests alias-to-alias typedef MySigned_t MySigned2_t; long takes_long(long x) { return x * x; } MySigned_t takes_typedef(MySigned_t x) { return x * x; } // issue 22906 // It's going to be hard to include a whole real JVM to test this. // So we'll simulate a really easy JVM using just the parts we need. // This is the relevant part of jni.h. struct _jobject; typedef struct _jobject *jobject; typedef jobject jclass; typedef jobject jthrowable; typedef jobject jstring; typedef jobject jarray; typedef jarray jbooleanArray; typedef jarray jbyteArray; typedef jarray jcharArray; typedef jarray jshortArray; typedef jarray jintArray; typedef jarray jlongArray; typedef jarray jfloatArray; typedef jarray jdoubleArray; typedef jarray jobjectArray; typedef jobject jweak; // Note: jvalue is already a non-pointer type due to it being a C union. // issue 22958 typedef struct { unsigned long long f8 : 8; unsigned long long f16 : 16; unsigned long long f24 : 24; unsigned long long f32 : 32; unsigned long long f40 : 40; unsigned long long f48 : 48; unsigned long long f56 : 56; unsigned long long f64 : 64; } issue22958Type; // issue 23356 int a(void) { return 5; }; int r(void) { return 3; }; // issue 23720 typedef int *issue23720A; typedef const int *issue23720B; void issue23720F(issue23720B a) {} // issue 24206 #if defined(__linux__) && defined(__x86_64__) #include // Returns string with null byte at the last valid address char* dangerousString1() { int pageSize = 4096; char *data = mmap(0, 2 * pageSize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0); mprotect(data + pageSize,pageSize,PROT_NONE); int start = pageSize - 123 - 1; // last 123 bytes of first page + 1 null byte int i = start; for (; i < pageSize; i++) { data[i] = 'x'; } data[pageSize -1 ] = 0; return data+start; } char* dangerousString2() { int pageSize = 4096; char *data = mmap(0, 3 * pageSize, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, 0, 0); mprotect(data + 2 * pageSize,pageSize,PROT_NONE); int start = pageSize - 123 - 1; // last 123 bytes of first page + 1 null byte int i = start; for (; i < 2 * pageSize; i++) { data[i] = 'x'; } data[2*pageSize -1 ] = 0; return data+start; } #else char *dangerousString1() { return NULL; } char *dangerousString2() { return NULL; } #endif // issue 26066 const unsigned long long int issue26066 = (const unsigned long long) -1; // issue 26517 // Introduce two pointer types which are distinct, but have the same // base type. Make sure that both of those pointer types get resolved // correctly. Before the fix for 26517 if one of these pointer types // was resolved before the other one was processed, the second one // would never be resolved. // Before this issue was fixed this test failed on Windows, // where va_list expands to a named char* type. typedef va_list TypeOne; typedef char *TypeTwo; // issue 28540 static void twoargs1(void *p, int n) {} static void *twoargs2() { return 0; } static int twoargs3(void * p) { return 0; } // issue 28545 // Failed to add type conversion for negative constant. static void issue28545F(char **p, int n, complex double a) {} // issue 28772 part 1 - part 2 in testx.go // Failed to add type conversion for Go constant set to C constant. // No runtime test; just make sure it compiles. #define issue28772Constant 1 // issue 28896 // cgo was incorrectly adding padding after a packed struct. typedef struct { void *f1; uint32_t f2; } __attribute__((__packed__)) innerPacked; typedef struct { innerPacked g1; uint64_t g2; } outerPacked; typedef struct { void *f1; uint32_t f2; } innerUnpacked; typedef struct { innerUnpacked g1; uint64_t g2; } outerUnpacked; size_t offset(int x) { switch (x) { case 0: return offsetof(innerPacked, f2); case 1: return offsetof(outerPacked, g2); case 2: return offsetof(innerUnpacked, f2); case 3: return offsetof(outerUnpacked, g2); default: abort(); } } // issue 29748 typedef struct { char **p; } S29748; static int f29748(S29748 *p) { return 0; } // issue 29781 // Error with newline inserted into constant expression. // Compilation test only, nothing to run. static void issue29781F(char **p, int n) {} #define ISSUE29781C 0 // issue 31093 static uint16_t issue31093F(uint16_t v) { return v; } // issue 32579 typedef struct S32579 { unsigned char data[1]; } S32579; // issue 37033, cgo.Handle extern void GoFunc37033(uintptr_t handle); void cFunc37033(uintptr_t handle) { GoFunc37033(handle); } // issue 38649 // Test that #define'd type aliases work. #define netbsd_gid unsigned int // issue 40494 // Inconsistent handling of tagged enum and union types. enum Enum40494 { X_40494 }; union Union40494 { int x; }; void issue40494(enum Enum40494 e, union Union40494* up) {} // Issue 45451, bad handling of go:notinheap types. typedef struct issue45451Undefined issue45451; // Issue 49633, example of cgo.Handle with void*. extern void GoFunc49633(void*); void cfunc49633(void *context) { GoFunc49633(context); } */ import "C" import ( "context" "fmt" "math" "math/rand" "os" "os/signal" "reflect" "runtime" "runtime/cgo" "sync" "syscall" "testing" "time" "unsafe" ) // alignment func testAlign(t *testing.T) { var evt C.SDL_KeyboardEvent C.makeEvent(&evt) if C.same(&evt, evt.typ, evt.which, evt.state, evt.keysym.scancode, evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode) == 0 { t.Error("*** bad alignment") C.cTest(&evt) t.Errorf("Go: %#x %#x %#x %#x %#x %#x %#x\n", evt.typ, evt.which, evt.state, evt.keysym.scancode, evt.keysym.sym, evt.keysym.mod, evt.keysym.unicode) t.Error(evt) } } // api const greeting = "hello, world" type testPair struct { Name string Got, Want interface{} } var testPairs = []testPair{ {"GoString", C.GoString(C.greeting), greeting}, {"GoStringN", C.GoStringN(C.greeting, 5), greeting[:5]}, {"GoBytes", C.GoBytes(unsafe.Pointer(C.greeting), 5), []byte(greeting[:5])}, } func testHelpers(t *testing.T) { for _, pair := range testPairs { if !reflect.DeepEqual(pair.Got, pair.Want) { t.Errorf("%s: got %#v, want %#v", pair.Name, pair.Got, pair.Want) } } } // basic test cases const EINVAL = C.EINVAL /* test #define */ var KILO = C.KILO func uuidgen() { var uuid C.cgo_uuid_t C.uuid_generate(&uuid[0]) } func Strtol(s string, base int) (int, error) { p := C.CString(s) n, err := C.strtol(p, nil, C.int(base)) C.free(unsafe.Pointer(p)) return int(n), err } func Atol(s string) int { p := C.CString(s) n := C.atol(p) C.free(unsafe.Pointer(p)) return int(n) } func testConst(t *testing.T) { C.myConstFunc(nil, 0, nil) } func testEnum(t *testing.T) { if C.Enum1 != 1 || C.Enum2 != 2 { t.Error("bad enum", C.Enum1, C.Enum2) } } func testNamedEnum(t *testing.T) { e := new(C.enum_E) *e = C.Enum1 if *e != 1 { t.Error("bad enum", C.Enum1) } *e = C.Enum2 if *e != 2 { t.Error("bad enum", C.Enum2) } } func testCastToEnum(t *testing.T) { e := C.enum_E(C.Enum1) if e != 1 { t.Error("bad enum", C.Enum1) } e = C.enum_E(C.Enum2) if e != 2 { t.Error("bad enum", C.Enum2) } } func testAtol(t *testing.T) { l := Atol("123") if l != 123 { t.Error("Atol 123: ", l) } } func testErrno(t *testing.T) { p := C.CString("no-such-file") m := C.CString("r") f, err := C.fopen(p, m) C.free(unsafe.Pointer(p)) C.free(unsafe.Pointer(m)) if err == nil { C.fclose(f) t.Fatalf("C.fopen: should fail") } if err != syscall.ENOENT { t.Fatalf("C.fopen: unexpected error: %v", err) } } func testMultipleAssign(t *testing.T) { p := C.CString("234") n, m := C.strtol(p, nil, 345), C.strtol(p, nil, 10) if runtime.GOOS == "openbsd" { // Bug in OpenBSD strtol(3) - base > 36 succeeds. if (n != 0 && n != 239089) || m != 234 { t.Fatal("Strtol x2: ", n, m) } } else if n != 0 || m != 234 { t.Fatal("Strtol x2: ", n, m) } C.free(unsafe.Pointer(p)) } var ( cuint = (C.uint)(0) culong C.ulong cchar C.char ) type Context struct { ctx *C.struct_ibv_context } func benchCgoCall(b *testing.B) { b.Run("add-int", func(b *testing.B) { const x = C.int(2) const y = C.int(3) for i := 0; i < b.N; i++ { C.add(x, y) } }) b.Run("one-pointer", func(b *testing.B) { var a0 C.VkDeviceCreateInfo for i := 0; i < b.N; i++ { C.handleComplexPointer(&a0) } }) b.Run("string-pointer-escape", func(b *testing.B) { for i := 0; i < b.N; i++ { var s string C.handleGoStringPointerEscape(unsafe.Pointer(&s)) } }) b.Run("string-pointer-noescape", func(b *testing.B) { for i := 0; i < b.N; i++ { var s string C.handleGoStringPointerNoescape(unsafe.Pointer(&s)) } }) b.Run("eight-pointers", func(b *testing.B) { var a0, a1, a2, a3, a4, a5, a6, a7 C.VkDeviceCreateInfo for i := 0; i < b.N; i++ { C.handleComplexPointer8(&a0, &a1, &a2, &a3, &a4, &a5, &a6, &a7) } }) b.Run("eight-pointers-nil", func(b *testing.B) { var a0, a1, a2, a3, a4, a5, a6, a7 *C.VkDeviceCreateInfo for i := 0; i < b.N; i++ { C.handleComplexPointer8(a0, a1, a2, a3, a4, a5, a6, a7) } }) b.Run("eight-pointers-array", func(b *testing.B) { var a [8]C.VkDeviceCreateInfo for i := 0; i < b.N; i++ { C.handleComplexPointer8(&a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7]) } }) b.Run("eight-pointers-slice", func(b *testing.B) { a := make([]C.VkDeviceCreateInfo, 8) for i := 0; i < b.N; i++ { C.handleComplexPointer8(&a[0], &a[1], &a[2], &a[3], &a[4], &a[5], &a[6], &a[7]) } }) } // Benchmark measuring overhead from Go to C and back to Go (via a callback) func benchCallback(b *testing.B) { var x = false for i := 0; i < b.N; i++ { nestedCall(func() { x = true }) } if !x { b.Fatal("nestedCall was not invoked") } } var sinkString string func benchGoString(b *testing.B) { for i := 0; i < b.N; i++ { sinkString = C.GoString(C.cstr) } const want = "abcefghijklmnopqrstuvwxyzABCEFGHIJKLMNOPQRSTUVWXYZ1234567890" if sinkString != want { b.Fatalf("%q != %q", sinkString, want) } } // 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 } // set in cgo_thread_lock.go init var testThreadLockFunc = func(*testing.T) {} // complex alignment func TestComplexAlign(t *testing.T) { if C.cplxAlign.x != 3.14 { t.Errorf("got %v, expected 3.14", C.cplxAlign.x) } if C.cplxAlign.y != 2.17 { t.Errorf("got %v, expected 2.17", C.cplxAlign.y) } } // constants and pointer checking func testCheckConst(t *testing.T) { // The test is that this compiles successfully. p := C.malloc(C.size_t(unsafe.Sizeof(C.int(0)))) defer C.free(p) C.CheckConstFunc(&C.CheckConstStruct{(*C.int)(p)}, C.CheckConstVal) } // duplicate symbol func duplicateSymbols() { fmt.Printf("%v %v %v\n", C.base_symbol, C.alias_one, C.alias_two) } // environment // This is really an os package test but here for convenience. func testSetEnv(t *testing.T) { if runtime.GOOS == "windows" { // Go uses SetEnvironmentVariable on windows. However, // C runtime takes a *copy* at process startup of the // OS environment, and stores it in environ/envp. // It is this copy that getenv/putenv manipulate. t.Logf("skipping test") return } const key = "CGO_OS_TEST_KEY" const val = "CGO_OS_TEST_VALUE" os.Setenv(key, val) keyc := C.CString(key) defer C.free(unsafe.Pointer(keyc)) v := C.getenv(keyc) if uintptr(unsafe.Pointer(v)) == 0 { t.Fatal("getenv returned NULL") } vs := C.GoString(v) if vs != val { t.Fatalf("getenv() = %q; want %q", vs, val) } } // function pointer variables func callBridge(f C.intFunc) int { return int(C.bridge_int_func(f)) } func callCBridge(f C.intFunc) C.int { return C.bridge_int_func(f) } func testFpVar(t *testing.T) { const expected = 42 f := C.intFunc(C.fortytwo) res1 := C.bridge_int_func(f) if r1 := int(res1); r1 != expected { t.Errorf("got %d, want %d", r1, expected) } res2 := callCBridge(f) if r2 := int(res2); r2 != expected { t.Errorf("got %d, want %d", r2, expected) } r3 := callBridge(f) if r3 != expected { t.Errorf("got %d, want %d", r3, expected) } } // issue 1222 type AsyncEvent struct { event C.struct_ibv_async_event } // issue 1635 func test1635(t *testing.T) { C.scatter() if v := C.hola; v != 0 { t.Fatalf("C.hola is %d, should be 0", v) } if v := C.testHola(); v != 0 { t.Fatalf("C.testHola() is %d, should be 0", v) } } // issue 2470 func testUnsignedInt(t *testing.T) { a := (int64)(C.UINT32VAL) b := (int64)(0xc008427b) if a != b { t.Errorf("Incorrect unsigned int - got %x, want %x", a, b) } } // issue 3250 func test3250(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("not applicable on windows") } t.Skip("skipped, see golang.org/issue/5885") var ( thres = 1 sig = syscall_dot_SIGCHLD ) type result struct { n int sig os.Signal } var ( sigCh = make(chan os.Signal, 10) waitStart = make(chan struct{}) waitDone = make(chan result) ) signal.Notify(sigCh, sig) go func() { n := 0 alarm := time.After(time.Second * 3) for { select { case <-waitStart: waitStart = nil case v := <-sigCh: n++ if v != sig || n > thres { waitDone <- result{n, v} return } case <-alarm: waitDone <- result{n, sig} return } } }() waitStart <- struct{}{} C.testSendSIG() r := <-waitDone if r.sig != sig { t.Fatalf("received signal %v, but want %v", r.sig, sig) } t.Logf("got %d signals\n", r.n) if r.n <= thres { t.Fatalf("expected more than %d", thres) } } // issue 3261 func testLibgcc(t *testing.T) { var table = []struct { in, out C.int }{ {0, 0}, {1, 1}, {-42, 42}, {1000300, 1000300}, {1 - 1<<31, 1<<31 - 1}, } for _, v := range table { if o := C.vabs(v.in); o != v.out { t.Fatalf("abs(%d) got %d, should be %d", v.in, o, v.out) return } } } // issue 3729 func test3729(t *testing.T) { if runtime.GOOS == "windows" { t.Skip("skipping on windows") } _, e := C.g() if e != syscall.E2BIG { t.Errorf("got %q, expect %q", e, syscall.E2BIG) } _, e = C.g2(C.EINVAL, C._expA, C._expB, C._expC, C._expD) if e != syscall.EINVAL { t.Errorf("got %q, expect %q", e, syscall.EINVAL) } } // issue 3945 func testPrintf(t *testing.T) { C.say() } // issue 4054 var issue4054a = []int{C.A, C.B, C.C, C.D, C.E, C.F, C.G, C.H, C.I, C.J} // issue 4339 func test4339(t *testing.T) { C.handle4339(&C.exported4339) } // issue 4417 func testBoolAlign(t *testing.T) { b := C.c_bool(true, true, 10, true, false) if b != 10 { t.Fatalf("found %d expected 10\n", b) } b = C.c_bool(true, true, 5, true, true) if b != 5 { t.Fatalf("found %d expected 5\n", b) } b = C.c_bool(true, true, 3, true, false) if b != 3 { t.Fatalf("found %d expected 3\n", b) } b = C.c_bool(false, false, 1, true, false) if b != 1 { t.Fatalf("found %d expected 1\n", b) } b = C.c_bool(false, true, 200, true, false) if b != 200 { t.Fatalf("found %d expected 200\n", b) } } // issue 4857 func test4857() { _ = C.issue4857() } // issue 5224 func testCflags(t *testing.T) { is_windows := C.is_windows == 1 if is_windows != (runtime.GOOS == "windows") { t.Errorf("is_windows: %v, runtime.GOOS: %s", is_windows, runtime.GOOS) } if C.common != 123 { t.Errorf("common: %v (expected 123)", C.common) } } // issue 5227 func test5227(t *testing.T) { C.init() } func selectfont() C.Fontinfo { return C.SansTypeface } // issue 5242 func test5242(t *testing.T) { if got := C.issue5242(C.foo{}, C.bar{}); got != 5242 { t.Errorf("got %v", got) } } func test5603(t *testing.T) { var x [5]int64 exp := int64(C.issue5603exp) x[0] = int64(C.issue5603foo0()) x[1] = int64(C.issue5603foo1(nil)) x[2] = int64(C.issue5603foo2(nil, nil)) x[3] = int64(C.issue5603foo3(nil, nil, nil)) x[4] = int64(C.issue5603foo4(nil, nil, nil, nil)) for i, v := range x { if v != exp { t.Errorf("issue5603foo%d() returns %v, expected %v", i, v, exp) } } } // issue 5337 func test5337(t *testing.T) { C.test5337() } // issue 5740 func test5740(t *testing.T) { if v := C.test5740a() + C.test5740b(); v != 5 { t.Errorf("expected 5, got %v", v) } } // issue 5986 func test5986(t *testing.T) { C.output5986() } // issue 6128 func test6128() { // nothing to run, just make sure this compiles. _ = C.X } // issue 6390 func test6390(t *testing.T) { p1 := C.malloc(1024) if p1 == nil { t.Fatalf("C.malloc(1024) returned nil") } p2 := C.malloc(0) if p2 == nil { t.Fatalf("C.malloc(0) returned nil") } C.free(p1) C.free(p2) } func test6472() { // nothing to run, just make sure this compiles s := new(C.z) println(s.y[0].x) } // issue 6506 func test6506() { // nothing to run, just make sure this compiles var x C.size_t C.calloc(x, x) C.malloc(x) C.realloc(nil, x) C.memcpy(nil, nil, x) C.memcmp(nil, nil, x) C.memmove(nil, nil, x) C.strncpy(nil, nil, x) C.strncmp(nil, nil, x) C.strncat(nil, nil, x) x = C.strxfrm(nil, nil, x) C.memchr(nil, 0, x) x = C.strcspn(nil, nil) x = C.strspn(nil, nil) C.memset(nil, 0, x) x = C.strlen(nil) _ = x } // issue 6612 func testNaming(t *testing.T) { C.myfunc() C.myfunc_def() if v := C.myvar; v != 5 { t.Errorf("C.myvar = %d, want 5", v) } if v := C.myvar_def; v != 5 { t.Errorf("C.myvar_def = %d, want 5", v) } if s := C.GoString(C.mytext); s != "abcdef" { t.Errorf("C.mytext = %q, want %q", s, "abcdef") } if s := C.GoString(C.mytext_def); s != "abcdef" { t.Errorf("C.mytext_def = %q, want %q", s, "abcdef") } if c := C.myenum; c != 1234 { t.Errorf("C.myenum = %v, want 1234", c) } if c := C.myenum_def; c != 1234 { t.Errorf("C.myenum_def = %v, want 1234", c) } { const c = C.myenum if c != 1234 { t.Errorf("C.myenum as const = %v, want 1234", c) } } { const c = C.myenum_def if c != 1234 { t.Errorf("C.myenum as const = %v, want 1234", c) } } if c := C.myint_def; c != 12345 { t.Errorf("C.myint_def = %v, want 12345", c) } { const c = C.myint_def if c != 12345 { t.Errorf("C.myint as const = %v, want 12345", c) } } if c := C.myfloat_def; c != 1.5 { t.Errorf("C.myint_def = %v, want 1.5", c) } { const c = C.myfloat_def if c != 1.5 { t.Errorf("C.myint as const = %v, want 1.5", c) } } if s := C.mystring_def; s != "hello" { t.Errorf("C.mystring_def = %q, want %q", s, "hello") } } // issue 6907 func test6907(t *testing.T) { want := "yarn" if got := C.GoString(C.Issue6907CopyString(want)); got != want { t.Errorf("C.GoString(C.Issue6907CopyString(%q)) == %q, want %q", want, got, want) } } // issue 7560 func test7560(t *testing.T) { // some mingw don't implement __packed__ correctly. if C.offset7560() != 1 { t.Skip("C compiler did not pack struct") } // C.misaligned should have x but then a padding field to get to the end of the struct. // There should not be a field named 'y'. var v C.misaligned rt := reflect.TypeOf(&v).Elem() if rt.NumField() != 2 || rt.Field(0).Name != "x" || rt.Field(1).Name != "_" { t.Errorf("unexpected fields in C.misaligned:\n") for i := 0; i < rt.NumField(); i++ { t.Logf("%+v\n", rt.Field(i)) } } } // issue 7786 func f() { var x1 *C.typedef_test7786 var x2 *C.struct_test7786 x1 = x2 x2 = x1 C.f7786(x1) C.f7786(x2) C.g7786(x1) C.g7786(x2) var b1 *C.typedef_body7786 var b2 *C.struct_body7786 b1 = b2 b2 = b1 C.b7786(b1) C.b7786(b2) C.c7786(b1) C.c7786(b2) var u1 *C.typedef_union7786 var u2 *C.union_union7786 u1 = u2 u2 = u1 C.u7786(u1) C.u7786(u2) C.v7786(u1) C.v7786(u2) } // issue 8092 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) } } } // issues 8368 and 8441 func issue8368(one *C.struct_one, two *C.struct_two) { } func issue8441(one *C.one, two *C.two) { issue8441(two.x, one.x) } // issue 8428 var _ = C.struct_issue8428one{ b: C.char(0), // The trailing rest field is not available in cgo. // See issue 11925. // 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{}, } // issue 8811 func test8811(t *testing.T) { C.issue8811Execute() } // issue 9557 func test9557(t *testing.T) { // implicitly dereference a Go variable foo := C.issue9557foo if v := foo.a; v != 42 { t.Fatalf("foo.a expected 42, but got %d", v) } // explicitly dereference a C variable if v := (*C.issue9557foo).a; v != 42 { t.Fatalf("(*C.issue9557foo).a expected 42, but is %d", v) } // implicitly dereference a C variable if v := C.issue9557foo.a; v != 42 { t.Fatalf("C.issue9557foo.a expected 42, but is %d", v) } } // issue 8331 part 1 func issue8331a() C.issue8331 { return issue8331Var } // issue 10303 func test10303(t *testing.T, n int) { if runtime.Compiler == "gccgo" { t.Skip("gccgo permits C pointers on the stack") } // Run at a few different stack depths just to avoid an unlucky pass // due to variables ending up on different pages. if n > 0 { test10303(t, n-1) } if t.Failed() { return } var x, y, z, v, si C.int var s C.Struct C.setintstar(&x) C.setintptr(&y) C.setvoidptr(unsafe.Pointer(&v)) s.P = &si C.setstruct(s) if uintptr(unsafe.Pointer(&x))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { t.Error("C int* argument on stack") } if uintptr(unsafe.Pointer(&y))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { t.Error("C intptr argument on stack") } if uintptr(unsafe.Pointer(&v))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { t.Error("C void* argument on stack") } if uintptr(unsafe.Pointer(&si))&^0xfff == uintptr(unsafe.Pointer(&z))&^0xfff { t.Error("C struct field pointer on stack") } } // issue 11925 func test11925(t *testing.T) { if C.sizeof_struct_a11925 != unsafe.Sizeof(C.struct_a11925{}) { t.Errorf("size of a changed: C %d, Go %d", C.sizeof_struct_a11925, unsafe.Sizeof(C.struct_a11925{})) } if C.sizeof_struct_b11925 != unsafe.Sizeof(C.struct_b11925{}) { t.Errorf("size of b changed: C %d, Go %d", C.sizeof_struct_b11925, unsafe.Sizeof(C.struct_b11925{})) } } // issue 12030 func test12030(t *testing.T) { buf := (*C.char)(C.malloc(256)) defer C.free(unsafe.Pointer(buf)) for _, f := range []float64{1.0, 2.0, 3.14} { C.issue12030conv(buf, C.double(f)) got := C.GoString(buf) if want := fmt.Sprintf("d=%g", f); got != want { t.Fatalf("C.sprintf failed for %g: %q != %q", f, got, want) } } } // issue 13402 var _ C.complexfloat var _ C.complexdouble // issue 13930 // Test that cgo's multiple-value special form for // C function calls works in variable declaration statements. var _, _ = C.abs(0) // issue 14838 func test14838(t *testing.T) { data := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} cData := C.CBytes(data) defer C.free(cData) if C.check_cbytes((*C.char)(cData), C.size_t(len(data))) == 0 { t.Fatalf("mismatched data: expected %v, got %v", data, (*(*[10]byte)(unsafe.Pointer(cData)))[:]) } } // issue 17065 var sink C.int func test17065(t *testing.T) { if runtime.GOOS == "darwin" || runtime.GOOS == "ios" { t.Skip("broken on darwin; issue 17065") } for i := range C.ii { sink = C.ii[i] } } // issue 17537 func test17537(t *testing.T) { v := C.S17537{i: 17537} if got, want := C.I17537(&v), C.int(17537); got != want { t.Errorf("got %d, want %d", got, want) } p := (*C.char)(C.malloc(1)) *p = 17 if got, want := C.F17537(&p), C.int(17); got != want { t.Errorf("got %d, want %d", got, want) } C.F18298(nil) var v18298 C.T18298_2 C.G18298(C.T18298_1(v18298)) } // issue 17723 func testAPI() { var cs *C.char cs = C.CString("hello") defer C.free(unsafe.Pointer(cs)) var s string s = C.GoString((*C.char)(C.api_hello)) s = C.GoStringN((*C.char)(C.api_hello), C.int(6)) var b []byte b = C.GoBytes(unsafe.Pointer(C.api_hello), C.int(6)) _, _ = s, b C.cstring_pointer_fun(nil) } // issue 18126 func test18126(t *testing.T) { p := C.malloc(1) _, err := C.Issue18126C(&p) C.free(p) _ = err } // issue 18720 func test18720(t *testing.T) { if got, want := C.HELLO_WORLD, "hello\000world"; got != want { t.Errorf("C.HELLO_WORLD == %q, expected %q", got, want) } if got, want := C.VAR1, C.int(5); got != want { t.Errorf("C.VAR1 == %v, expected %v", got, want) } if got, want := *C.ADDR, C.int(5); got != want { t.Errorf("*C.ADDR == %v, expected %v", got, want) } if got, want := C.CALL, C.int(6); got != want { t.Errorf("C.CALL == %v, expected %v", got, want) } if got, want := C.CALL, C.int(7); got != want { t.Errorf("C.CALL == %v, expected %v", got, want) } // Issue 20125. if got, want := C.SIZE_OF_FOO, 1; got != want { t.Errorf("C.SIZE_OF_FOO == %v, expected %v", got, want) } } // issue 20129 func test20129(t *testing.T) { if C.issue20129 != 0 { t.Fatal("test is broken") } C.issue20129Foo() if C.issue20129 != 1 { t.Errorf("got %v but expected %v", C.issue20129, 1) } C.issue20129Bar() if C.issue20129 != 2 { t.Errorf("got %v but expected %v", C.issue20129, 2) } } // issue 20369 func test20369(t *testing.T) { if C.XUINT64_MAX != math.MaxUint64 { t.Fatalf("got %v, want %v", uint64(C.XUINT64_MAX), uint64(math.MaxUint64)) } } // issue 21668 var issue21668_X = C.x21668 // issue 21708 func test21708(t *testing.T) { if got, want := C.CAST_TO_INT64, -1; got != want { t.Errorf("C.CAST_TO_INT64 == %v, expected %v", got, want) } } // issue 21809 func test21809(t *testing.T) { longVar := C.long(3) typedefVar := C.MySigned_t(4) typedefTypedefVar := C.MySigned2_t(5) // all three should be considered identical to `long` if ret := C.takes_long(longVar); ret != 9 { t.Errorf("got %v but expected %v", ret, 9) } if ret := C.takes_long(typedefVar); ret != 16 { t.Errorf("got %v but expected %v", ret, 16) } if ret := C.takes_long(typedefTypedefVar); ret != 25 { t.Errorf("got %v but expected %v", ret, 25) } // They should also be identical to the typedef'd type if ret := C.takes_typedef(longVar); ret != 9 { t.Errorf("got %v but expected %v", ret, 9) } if ret := C.takes_typedef(typedefVar); ret != 16 { t.Errorf("got %v but expected %v", ret, 16) } if ret := C.takes_typedef(typedefTypedefVar); ret != 25 { t.Errorf("got %v but expected %v", ret, 25) } } // issue 22906 func test22906(t *testing.T) { var x1 C.jobject = 0 // Note: 0, not nil. That makes sure we use uintptr for these types. _ = x1 var x2 C.jclass = 0 _ = x2 var x3 C.jthrowable = 0 _ = x3 var x4 C.jstring = 0 _ = x4 var x5 C.jarray = 0 _ = x5 var x6 C.jbooleanArray = 0 _ = x6 var x7 C.jbyteArray = 0 _ = x7 var x8 C.jcharArray = 0 _ = x8 var x9 C.jshortArray = 0 _ = x9 var x10 C.jintArray = 0 _ = x10 var x11 C.jlongArray = 0 _ = x11 var x12 C.jfloatArray = 0 _ = x12 var x13 C.jdoubleArray = 0 _ = x13 var x14 C.jobjectArray = 0 _ = x14 var x15 C.jweak = 0 _ = x15 } // issue 22958 // Nothing to run, just make sure this compiles. var Vissue22958 C.issue22958Type func test23356(t *testing.T) { if got, want := C.a(), C.int(5); got != want { t.Errorf("C.a() == %v, expected %v", got, want) } if got, want := C.r(), C.int(3); got != want { t.Errorf("C.r() == %v, expected %v", got, want) } } // issue 23720 func Issue23720F() { var x C.issue23720A C.issue23720F(x) } // issue 24206 func test24206(t *testing.T) { if runtime.GOOS != "linux" || runtime.GOARCH != "amd64" { t.Skipf("skipping on %s/%s", runtime.GOOS, runtime.GOARCH) } if l := len(C.GoString(C.dangerousString1())); l != 123 { t.Errorf("Incorrect string length - got %d, want 123", l) } if l := len(C.GoString(C.dangerousString2())); l != 4096+123 { t.Errorf("Incorrect string length - got %d, want %d", l, 4096+123) } } // issue 25143 func issue25143sum(ns ...C.int) C.int { total := C.int(0) for _, n := range ns { total += n } return total } func test25143(t *testing.T) { if got, want := issue25143sum(1, 2, 3), C.int(6); got != want { t.Errorf("issue25143sum(1, 2, 3) == %v, expected %v", got, want) } } // issue 26066 // Wrong type of constant with GCC 8 and newer. func test26066(t *testing.T) { var i = int64(C.issue26066) if i != -1 { t.Errorf("got %d, want -1", i) } } // issue 26517 var a C.TypeOne var b C.TypeTwo // issue 27660 // Stress the interaction between the race detector and cgo in an // attempt to reproduce the memory corruption described in #27660. // The bug was very timing sensitive; at the time of writing this // test would only trigger the bug about once out of every five runs. func test27660(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() ints := make([]int, 100) locks := make([]sync.Mutex, 100) // Slowly create threads so that ThreadSanitizer is forced to // frequently resize its SyncClocks. for i := 0; i < 100; i++ { go func() { for ctx.Err() == nil { // Sleep in C for long enough that it is likely that the runtime // will retake this goroutine's currently wired P. C.usleep(1000 /* 1ms */) runtime.Gosched() // avoid starvation (see #28701) } }() go func() { // Trigger lots of synchronization and memory reads/writes to // increase the likelihood that the race described in #27660 // results in corruption of ThreadSanitizer's internal state // and thus an assertion failure or segfault. i := 0 for ctx.Err() == nil { j := rand.Intn(100) locks[j].Lock() ints[j]++ locks[j].Unlock() // needed for gccgo, to avoid creation of an // unpreemptible "fast path" in this loop. Choice // of (1<<24) is somewhat arbitrary. if i%(1<<24) == 0 { runtime.Gosched() } i++ } }() time.Sleep(time.Millisecond) } } // issue 28540 func twoargsF() { var v struct{ p *byte } C.twoargs1(C.twoargs2(), C.twoargs3(unsafe.Pointer(&v))) } // issue 28545 func issue28545G(p **C.char) { C.issue28545F(p, -1, (0)) C.issue28545F(p, 2+3, complex(1, 1)) C.issue28545F(p, issue28772Constant, issue28772Constant2) } // issue 28772 part 1 - part 2 in testx.go const issue28772Constant = C.issue28772Constant // issue 28896 func offset(i int) uintptr { var pi C.innerPacked var po C.outerPacked var ui C.innerUnpacked var uo C.outerUnpacked switch i { case 0: return unsafe.Offsetof(pi.f2) case 1: return unsafe.Offsetof(po.g2) case 2: return unsafe.Offsetof(ui.f2) case 3: return unsafe.Offsetof(uo.g2) default: panic("can't happen") } } func test28896(t *testing.T) { for i := 0; i < 4; i++ { c := uintptr(C.offset(C.int(i))) g := offset(i) if c != g { t.Errorf("%d: C: %d != Go %d", i, c, g) } } } // issue 29383 // cgo's /*line*/ comments failed when inserted after '/', // because the result looked like a "//" comment. // No runtime test; just make sure it compiles. func Issue29383(n, size uint) int { if ^C.size_t(0)/C.size_t(n) < C.size_t(size) { return 0 } return 0 } // issue 29748 // Error handling a struct initializer that requires pointer checking. // Compilation test only, nothing to run. var Vissue29748 = C.f29748(&C.S29748{ nil, }) func Fissue299748() { C.f29748(&C.S29748{ nil, }) } // issue 29781 var issue29781X struct{ X int } func issue29781F(...int) int { return 0 } func issue29781G() { var p *C.char C.issue29781F(&p, C.ISSUE29781C+1) C.issue29781F(nil, (C.int)( 0)) C.issue29781F(&p, (C.int)(0)) C.issue29781F(&p, (C.int)( 0)) C.issue29781F(&p, (C.int)(issue29781X. X)) } // issue 30065 func test30065(t *testing.T) { var a [256]byte b := []byte("a") C.memcpy(unsafe.Pointer(&a), unsafe.Pointer(&b[0]), 1) if a[0] != 'a' { t.Errorf("&a failed: got %c, want %c", a[0], 'a') } b = []byte("b") C.memcpy(unsafe.Pointer(&a[0]), unsafe.Pointer(&b[0]), 1) if a[0] != 'b' { t.Errorf("&a[0] failed: got %c, want %c", a[0], 'b') } d := make([]byte, 256) b = []byte("c") C.memcpy(unsafe.Pointer(&d[0]), unsafe.Pointer(&b[0]), 1) if d[0] != 'c' { t.Errorf("&d[0] failed: got %c, want %c", d[0], 'c') } } // issue 31093 // No runtime test; just make sure it compiles. func Issue31093() { C.issue31093F(C.ushort(0)) } // issue 32579 func test32579(t *testing.T) { var s [1]C.struct_S32579 C.memset(unsafe.Pointer(&s[0].data[0]), 1, 1) if s[0].data[0] != 1 { t.Errorf("&s[0].data[0] failed: got %d, want %d", s[0].data[0], 1) } } // issue 37033, check if cgo.Handle works properly func testHandle(t *testing.T) { ch := make(chan int) for i := 0; i < 42; i++ { h := cgo.NewHandle(ch) go func() { C.cFunc37033(C.uintptr_t(h)) }() if v := <-ch; issue37033 != v { t.Fatalf("unexpected receiving value: got %d, want %d", v, issue37033) } h.Delete() } } // issue 38649 var issue38649 C.netbsd_gid = 42 // issue 39877 var issue39877 *C.void = nil // issue 40494 // No runtime test; just make sure it compiles. func Issue40494() { C.issue40494(C.enum_Enum40494(C.X_40494), (*C.union_Union40494)(nil)) } // Issue 45451. func test45451(t *testing.T) { var u *C.issue45451 typ := reflect.ValueOf(u).Type().Elem() // The type is undefined in C so allocating it should panic. defer func() { if r := recover(); r == nil { t.Error("expected panic") } }() _ = reflect.New(typ) t.Errorf("reflect.New(%v) should have panicked", typ) } // issue 52542 func func52542[T ~[]C.int]() {} type type52542[T ~*C.float] struct{}