package cshared_test
import (
+ "bufio"
"bytes"
"debug/elf"
"debug/pe"
run(t, goenv, "go", "build", "-o", bin, "./go2c2go/m2")
runExe(t, runenv, bin)
}
+
+func TestIssue36233(t *testing.T) {
+ t.Parallel()
+
+ // Test that the export header uses GoComplex64 and GoComplex128
+ // for complex types.
+
+ tmpdir, err := os.MkdirTemp("", "cshared-TestIssue36233")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.RemoveAll(tmpdir)
+
+ const exportHeader = "issue36233.h"
+
+ run(t, nil, "go", "tool", "cgo", "-exportheader", exportHeader, "-objdir", tmpdir, "./issue36233/issue36233.go")
+ data, err := os.ReadFile(exportHeader)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ funcs := []struct{ name, signature string }{
+ {"exportComplex64", "GoComplex64 exportComplex64(GoComplex64 v)"},
+ {"exportComplex128", "GoComplex128 exportComplex128(GoComplex128 v)"},
+ {"exportComplexfloat", "GoComplex64 exportComplexfloat(GoComplex64 v)"},
+ {"exportComplexdouble", "GoComplex128 exportComplexdouble(GoComplex128 v)"},
+ }
+
+ scanner := bufio.NewScanner(bytes.NewReader(data))
+ var found int
+ for scanner.Scan() {
+ b := scanner.Bytes()
+ for _, fn := range funcs {
+ if bytes.Contains(b, []byte(fn.name)) {
+ found++
+ if !bytes.Contains(b, []byte(fn.signature)) {
+ t.Errorf("function signature mismatch; got %q, want %q", b, fn.signature)
+ }
+ }
+ }
+ }
+ if err = scanner.Err(); err != nil {
+ t.Errorf("scanner encountered error: %v", err)
+ }
+ if found != len(funcs) {
+ t.Error("missing functions")
+ }
+}
--- /dev/null
+// Copyright 2022 The Go Authors. All rights reserved.\r
+// Use of this source code is governed by a BSD-style\r
+// license that can be found in the LICENSE file.\r
+package main\r
+\r
+// #include <complex.h>\r
+import "C"\r
+\r
+//export exportComplex64\r
+func exportComplex64(v complex64) complex64 {\r
+ return v\r
+}\r
+\r
+//export exportComplex128\r
+func exportComplex128(v complex128) complex128 {\r
+ return v\r
+}\r
+\r
+//export exportComplexfloat\r
+func exportComplexfloat(v C.complexfloat) C.complexfloat {\r
+ return v\r
+}\r
+\r
+//export exportComplexdouble\r
+func exportComplexdouble(v C.complexdouble) C.complexdouble {\r
+ return v\r
+}\r
+\r
+func main() {}\r
case *ast.ChanType:
return &Type{Size: p.PtrSize, Align: p.PtrSize, C: c("GoChan")}
case *ast.Ident:
+ goTypesFixup := func(r *Type) *Type {
+ if r.Size == 0 { // int or uint
+ rr := new(Type)
+ *rr = *r
+ rr.Size = p.IntSize
+ rr.Align = p.IntSize
+ r = rr
+ }
+ if r.Align > p.PtrSize {
+ r.Align = p.PtrSize
+ }
+ return r
+ }
// Look up the type in the top level declarations.
// TODO: Handle types defined within a function.
for _, d := range p.Decl {
}
}
if def := typedef[t.Name]; def != nil {
+ if defgo, ok := def.Go.(*ast.Ident); ok {
+ switch defgo.Name {
+ case "complex64", "complex128":
+ // MSVC does not support the _Complex keyword
+ // nor the complex macro.
+ // Use GoComplex64 and GoComplex128 instead,
+ // which are typedef-ed to a compatible type.
+ // See go.dev/issues/36233.
+ return goTypesFixup(goTypes[defgo.Name])
+ }
+ }
return def
}
if t.Name == "uintptr" {
return &Type{Size: 2 * p.PtrSize, Align: p.PtrSize, C: c("GoInterface")}
}
if r, ok := goTypes[t.Name]; ok {
- if r.Size == 0 { // int or uint
- rr := new(Type)
- *rr = *r
- rr.Size = p.IntSize
- rr.Align = p.IntSize
- r = rr
- }
- if r.Align > p.PtrSize {
- r.Align = p.PtrSize
- }
- return r
+ return goTypesFixup(r)
}
error_(e.Pos(), "unrecognized Go type %s", t.Name)
return &Type{Size: 4, Align: 4, C: c("int")}
typedef size_t GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
+#ifdef _MSC_VER
+#include <complex.h>
+typedef _Fcomplex GoComplex64;
+typedef _Dcomplex GoComplex128;
+#else
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
+#endif
/*
static assertion to make sure the file is being used on architecture