New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/cgo: doesn't properly recognize a typedef'd C array type when it's a const C function argument #7270

Open
gopherbot opened this Issue Feb 5, 2014 · 7 comments

Comments

Projects
None yet
5 participants
@gopherbot

gopherbot commented Feb 5, 2014

by krzysiek@dajerade.pl:

I ran into an issue with cgo, when integrating Go with some C code. The attached tarball
contains a minimal example that reproduces the problem. Basicaly, passing a variable of
a typedef'd array type to a function accepting a const argument results in a "type
mismatch" compilation error.

C:

typedef unsigned char Bar[12];

void foo(Bar* f); // this works
void foo2(const Bar* f); // this confuses cgo

Go:

func main() {
  var v C.Bar
  C.foo(&bar) // this works
  C.foo2(&bar) // error, pasted below
}

This doesn't happen on Mac OS, go version go1.2 darwin/amd64, I don't know about Windows
builds.

What steps will reproduce the problem?
1. tar zxf const-bug.tar.gz && cd const-bug && make

What is the expected output?
Program should compile.

What do you see instead?
src/kg/constbug/main.go:12: cannot use &bar (type *_Ctype_Bar) as type
*[12]_Ctype_unsignedchar in function argument

Which compiler are you using (5g, 6g, 8g, gccgo)?
6g

Which operating system are you using?
Ubuntu 12.04

Which version are you using?  (run 'go version')
go version go1.2 linux/amd64
Installed from https://go.googlecode.com/files/go1.2.linux-amd64.tar.gz

Attachments:

  1. const-bug.tar.gz (1144 bytes)
@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Feb 5, 2014

Comment 1:

Labels changed: added repo-main, release-go1.3maybe.

@gopherbot

This comment has been minimized.

gopherbot commented Feb 6, 2014

Comment 2 by krzysiek@dajerade.pl:

Another important thing is that at the moment it's impossible to bypass this by casting
to *[12]C.uchar and have the program compile both on Linux and Mac OS. After changing
the problematic line to:
    C.fooconst((*[12]C.uchar)(&bar))
the program compiles and runs fine on Linux, but Mac OS go fails:
src/kg/constbug/main.go:12: cannot use (*[12]_Ctype_unsignedchar)(&bar) (type
*[12]_Ctype_unsignedchar) as type *_Ctype_Bar in function argument
@gopherbot

This comment has been minimized.

gopherbot commented Mar 14, 2014

Comment 3 by krzysiek@dajerade.pl:

It seems that this is a GCC bug: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60524
@rsc

This comment has been minimized.

Contributor

rsc commented May 9, 2014

Comment 4:

The usual workaround for all cgo problems is to write little wrappers in the /* */import
"C" comment that have simpler type definitions that don't provoke bugs in gcc (or in
cgo).

Labels changed: added release-none, suggested, removed release-go1.3maybe.

Status changed to Accepted.

@rsc rsc added this to the Unplanned milestone Apr 10, 2015

@rsc rsc removed release-none labels Apr 10, 2015

@paultag

This comment has been minimized.

paultag commented May 7, 2015

Similarly:

typedef void something();
something here;

And some Go:

C.here()

Results in some stuff like:

file/path.go:NN:YY: call of non-function C.here

(since it thinks it's of type something)

I didn't spend much time into digging into the root cause, but it looks similar enough. If this is another bug, let me know and I'll file this as a new issue.

Workaround is to define a new function in the C block -

void _here() {
   return here();
}

And invoke it as

C._here()
@silkeh

This comment has been minimized.

silkeh commented Jun 7, 2017

This doesn't happen on Mac OS

The reason for this is that clang (which is used by default on macOS) doesn't have this issue.
Building the following with CC=clang works:

package main

/*
typedef unsigned char Bar[12];

void foo(Bar* f){}        // this works
void foo2(const Bar* f){} // this confuses cgo
*/
import "C"

func main() {
  var v C.Bar
  
  C.foo(&v)  // this works
  C.foo2(&v) // error, pasted below
}

The behaviour experienced by @paultag doesn't work with either Clang or GCC. It seems like a separate issue to me.

@ianlancetaylor

This comment has been minimized.

Contributor

ianlancetaylor commented Jun 7, 2017

Thanks for the small test case. I believe the underlying cause is a bug in GCC. I filed https://gcc.gnu.org/PR81001.

silkeh added a commit to silkeh/libsodium-go that referenced this issue Jul 16, 2017

Fix pointer to AEAD context
The crypto_aead functions with precomputation take a pointer to a
`crypto_aead_aes256gcm_state` object as argument, not a char array.

The compiler is changed to clang because the code with the correct pointer does
not compile with GCC, see golang/go#7270.

silkeh added a commit to silkeh/libsodium-go that referenced this issue Jul 16, 2017

Fix pointer to AEAD context
The crypto_aead functions with precomputation take a pointer to a
`crypto_aead_aes256gcm_state` object as argument, not a char array.

The compiler is changed to clang because the code with the correct pointer does
not compile with GCC, see golang/go#7270.

silkeh added a commit to silkeh/libsodium-go that referenced this issue Aug 24, 2017

Fix pointer to AEAD context
The crypto_aead functions with precomputation take a pointer to a
`crypto_aead_aes256gcm_state` object as argument, not a char array.

The compiler is changed to clang because the code with the correct pointer does
not compile with GCC, see golang/go#7270.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment