Hello,
I have updated to a recent build of mingw-w64 (see below for version string) and now receive the following errors:
error: unknown field 'itemex' specified in initializer
error: unknown field 'mask' specified in initializer
The code in question is:
TVINSERTSTRUCT tvis = {
.hParent = TVI_ROOT,
.hInsertAfter = TVI_ROOT,
.itemex = { .mask = TVIF_TEXT | TVIF_PARAM }
};
Again, I have not changed the code, only updated mingw-w64. Altering the struct definition in commctrl.h gives a workaround, but not any seriously reasonable solution.
Using built-in specs.
COLLECT_GCC=i686-w64-mingw32-gcc
COLLECT_LTO_WRAPPER=d:/programs/mingw-w32/bin/../libexec/gcc/i686-w64-mingw32/4.5.2/lto-wrapper.exe
Target: i686-w64-mingw32
Configured with: ../../../build/gcc/src/configure --target=i686-w64-mingw32 --prefix=/c/bb/vista64-mingw32/mingw-x86-x86
/build/build/root --with-sysroot=/c/bb/vista64-mingw32/mingw-x86-x86/build/build/root --enable-languages=all,obj-c++ --e
nable-fully-dynamic-string --disable-multilib
Thread model: win32
gcc version 4.5.2 20100917 (prerelease) (GCC)
3115 typedef struct tagTVINSERTSTRUCTA {
3116 HTREEITEM hParent;
3117 HTREEITEM hInsertAfter;
3118 __MINGW_EXTENSION union {
3119 TVITEMEXA itemex;
3120 TV_ITEMA item;
3121 } DUMMYUNIONNAME;
3122 } TVINSERTSTRUCTA,*LPTVINSERTSTRUCTA;
It looks like DUMMYUNIONNAME should be removed, try that.
Yep I know, that's the workaround. But as as noted before, editing compiler headers isn't a reasonable solution. I'm hoping someone can fix this in head now, since the problem is clear.
AFAICS, a DUMMYUNIONNAME was not added or removed from any members of the TVINSERTSTRUCT structure, the existing one was already there from the beginning. Which version of mingw-w64 used to work for you?
Are you sure that you did not add NONAMELESSUNION to your CFLAGS or not defining it somewhere in your code?
I haven't changed the makefile, build process or code. My other machine builds the same project fine using this version of mingw-w64:
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=c:/msys/mingw32/bin/../libexec/gcc/i686-w64-mingw32/4.5.0/lto-wrapper.exe
Target: i686-w64-mingw32
Configured with: ../../../build/gcc/gcc/configure --target=i686-w64-mingw32 --prefix=/g/buildbot/vista64-mingw32/mingw-x
86-x86/build/build/root --with-sysroot=/g/buildbot/vista64-mingw32/mingw-x86-x86/build/build/root --enable-languages=all
,obj-c++ --enable-fully-dynamic-string --disable-multilib
Thread model: win32
gcc version 4.5.0 20091117 (experimental) (GCC)
Well, does the commctrl.h from that older toolchain have the dummy name in that structure? (It normally should...)
It appears to be identical. And that the compiler doesn't like struct initialization for member itemex. Do we now have a compiler bug on our hands?
(also, my CFLAGS are effectively: "-Wall -Wextra -std=c99 -pedantic -O3", and haven't changed for some time)
Tested with 4.4.5 using sezero 20100711 and 20101003 builds, failure is there with it, too:
unknown field 'itemex' specified in initializer
error: unknown field 'mask' specified in initializer
warning: missing braces around initializer
warning: (near initialization for 'tvis.<anonymous>.itemex')
warning: missing initializer
warning: (near initialization for 'tvis.<anonymous>.itemex.hItem')
(line numbers stripped manually.)
Changing initializer from .itemex= to .u.itemex= and adding -DNONAMELESSUNION makes it succeed. Anonymous union is the problem. This may be a compiler bug.
Paging Kai for help.
Here is a minimal testcase, hopefully correct, that doesn't
require a mingw compiler or any headers:
$ cat foo.c
typedef struct _TVINSERTSTRUCT {
int dummy;
__extension__ union {
unsigned mask;
};
} TVINSERTSTRUCT;
TVINSERTSTRUCT tvis = {
.dummy = 1,
.mask = 0x1 /* this fails */
};
void foo ()
{
tvis.mask = 0x1; /* this is fine */
}
typedef struct _TVINSERTSTRUCT2 {
int dummy;
__extension__ union {
unsigned mask;
} u;
} TVINSERTSTRUCT2;
TVINSERTSTRUCT2 tvis2 = {
.dummy = 1,
.u.mask = 0x1 /* this is fine too */
};
$ gcc44 -Wall -Wextra -std=c99 -c foo.c
foo.c:10: error: unknown field 'mask' specified in initializer
foo.c:11: warning: missing braces around initializer
foo.c:11: warning: (near initialization for 'tvis.<anonymous>')
fails with gcc34 too.
ISO 9899:TC2
6.7.2.1, 9:
Except where explicitly stated otherwise, for the purposes of this subclause unnamed
members of objects of structure and union type do not participate in initialization.
Unnamed members of structure objects have indeterminate value even after initialization.
I might interpret from this that the compiler has reason to complain (although using "do not" instead of "cannot" leaves room for doubt). If someone can offer their interpretation. However, nameless unions are not mentioned as part of the standard (microsoft specific; extension). On one hand, I'd expect a compiler that supports them to also support them during initialization... on the other, there is that clause above...
In any case, it worked before so that is cause for concern.
> ISO 9899:TC2
> 6.7.2.1, 9:
[snip]
> mentioned as part of the standard (microsoft specific; extension).
> On one hand, I'd expect a compiler that supports them to also
> support them during initialization... on the other, there is that
> clause above...
Fully agree with all of these
> In any case, it worked before so that is cause for concern.
This is my concern too, because I have no idea as to how it
really worked before...
So is this going to be moved to bugs and fixed, or ignored? I need to know before I start adding kludges/workarounds to the code.
Well, this should be among support requests IMO, because there is no mingw-w64 bug here. The problem is with gcc and I notified Kai about it in case he missed this support request. He didn't answer yet, probably he is busy, or on vacation, don't really know.
I don't think that this will be ignored, but it may have to go through gcc bugzilla, IMO, and might take some time.
Well, I tried this testcase on current 4.6 gcc and it was able to build successful. So question here is, if the issue is more a latent missing feature, or really a bug.