nested union declaration causes incorrect compile if imported from another file
application/x-zip-compressed
1445
Comments
Comment #0 by opantm2+dbugs — 2014-02-24T00:13:24Z
Sample:
import core.sys.posix.pthread;
void main() {
auto a = pthread_mutex_t.init;
}
Output:
rdmd test.d
test.o: In function `_Dmain':
test.d:(.text._Dmain+0xa): undefined reference to `_D4core3sys5posix3sys5types15pthread_mutex_t6__initZ'
collect2: error: ld returned 1 exit status
While this particular sample is Posix only (tested on Linux 64-bit and OSX 64-bit), I would assume that the actual bug is not OS related. The bug also occurs with -allinst.
I wasn't able to duplicate the bug when I replaced pthread_mutex_t (either in the same file as the test or in a different file) with:
union pthread_mutex_t {
byte __size[40];
ptrdiff_t __align;
}
Which should be essentially the same on my system.
Comment #1 by dbugz — 2014-08-14T05:10:13Z
Created attachment 1385
nested union declaration causes incorrect compile if imported from another file
I just ran into this bug when trying to port some Android system headers from C, except with nested unions in my case and with dmd-git-24e8347f1fa4 from a week ago. I can confirm that Kapps's testcase also doesn't work on linux/x86, when tried with the latest stock dmd 2.065.
I've attached a couple source files to demonstrate the problem. The structs defined are exactly the ones I'm trying to port from Android, ASensorVector and ASensorEvent shown here:
https://android.googlesource.com/platform/frameworks/native/+/jb-release/include/android/sensor.h
I build and run as so on linux/86 using stock dmd 2.065:
> clang -c foo.c
> dmd food.d foo.o
>./food
That works, since it's getting the struct declarations from the main source file. This doesn't:
> dmd -version=do_import food.d foo.o
food.o:food.d:function _Dmain: error: undefined reference to '_D4fooi5foogo6__initZ'
Looking at the symbols generated, it appears that dmd is generating the right symbols only if the union or nested union is declared in the local source file. Here's the symbols without do_import:
> dmd -c food.d
> nm -s food.o | grep foogo
00000000 V _D21TypeInfo_S4food5foogo6__initZ
00000000 T _D4food5foogo11__xopEqualsUKxS4food5foogoKxS4food5foogoZb
00000030 R _D4food5foogo6__initZ
With the do_import:
> dmd -version=do_import -c food.d
> nm -s food.o | grep foogo
U _D4fooi5foogo6__initZ
It's that undefined symbol that causes the linker to fail. Putting the ASensorVector/ASensorEvent declarations in the same file also gets it to work on Android/x86.
Comment #2 by genede — 2016-01-07T22:33:13Z
Workaround:
I ran into this today with the Windows COM VARIANT struct, which is a union that contains a struct that contains a union and a struct.
I ended up working around this with a separate initialization method:
export static tagVARIANT createVARIANT { return tagVARIANT(); }
This work around isn't elegant, but my guess is it can be broadly used for this issue, potentially blocking some people who are stumped.
Comment #3 by genede — 2016-01-07T23:02:12Z
(In reply to genede from comment #2)
> Workaround:
>
> I ran into this today with the Windows COM VARIANT struct, which is a union
> that contains a struct that contains a union and a struct.
>
> I ended up working around this with a separate initialization method:
>
> export static tagVARIANT createVARIANT { return tagVARIANT(); }
>
> This work around isn't elegant, but my guess is it can be broadly used for
> this issue, potentially blocking some people who are stumped.
or rather unblocking....
Comment #4 by robert.schadek — 2024-12-13T18:17:25Z