summaryrefslogtreecommitdiffstats
path: root/misc/cgo/test/test.go
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:23:18 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-16 19:23:18 +0000
commit43a123c1ae6613b3efeed291fa552ecd909d3acf (patch)
treefd92518b7024bc74031f78a1cf9e454b65e73665 /misc/cgo/test/test.go
parentInitial commit. (diff)
downloadgolang-1.20-43a123c1ae6613b3efeed291fa552ecd909d3acf.tar.xz
golang-1.20-43a123c1ae6613b3efeed291fa552ecd909d3acf.zip
Adding upstream version 1.20.14.upstream/1.20.14upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'misc/cgo/test/test.go')
-rw-r--r--misc/cgo/test/test.go2303
1 files changed, 2303 insertions, 0 deletions
diff --git a/misc/cgo/test/test.go b/misc/cgo/test/test.go
new file mode 100644
index 0000000..9d9b14e
--- /dev/null
+++ b/misc/cgo/test/test.go
@@ -0,0 +1,2303 @@
+// 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 <complex.h>
+#include <math.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+#cgo LDFLAGS: -lm
+
+#ifndef WIN32
+#include <pthread.h>
+#include <signal.h>
+#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; i<sizeof *event; i++) {
+ p[i] = i;
+ }
+}
+
+int same(SDL_KeyboardEvent* e, Uint8 typ, Uint8 which, Uint8 state, Uint8 scan, SDLKey sym, SDLMod mod, Uint16 uni) {
+ return e->typ == 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;
+};
+
+// Following mimicks 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 <issue4339.h>
+
+// 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 <sys/mman.h>
+// 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("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() {
+ v := []string{}
+ 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{}