> Cc: bug-gnulib@gnu.org > From: Paul Eggert <egg...@cs.ucla.edu> > Date: Sun, 9 Oct 2016 10:35:14 -0700 > > Eli Zaretskii wrote: > > I'm not sure I understand how this is different from what > > e.g. Gnulib's wchar.h already does. Can you point out the crucial > > differences? > > Ah, I didn't look at lib/wchar.in.h. Yes, it's already doing that, with a > complicated ifdef that is supposed to work on MinGW. It isn't working for > you, I > suppose because MinGW's include-file internals have changed. So, what's > different about your MinGW's include-file internals? > > Maybe you're using a 64-bit MinGW, say? wchar.in.h seems to know only about > 32-bit.
No, I'm using 32-bit MinGW, just the latest release of their runtime and headers. What changed is that now MinGW string.h includes wchar.h, and wchar.h has a special treatment of that inclusion. Here are the important parts, indented 2 spaces: #ifndef _WCHAR_H #pragma GCC system_header /* This header declares prototypes for wchar_t string functions, as are * prescribed by ISO-C, but which MSVC also expects, (in contravention of * ISO-C prescriptions), to find in <string.h>. To accommodate this MSVC * anomaly, we make provision for <string.h> to include a selected subset * of <wchar.h>; thus, we do not immediately define _WCHAR_T... */ #ifndef __STRING_H_SOURCED__ /* ...but defer it until we have confirmed that this is NOT inclusion for * only this subset of <wchar.h> declarations. */ #define _WCHAR_H [...] #endif /* !__STRING_H_SOURCED__ */ /* This completes the set of declarations which are to be duplicated by * inclusion of <string.h>; revert the declarative condition, to make it * specific to <wchar.h> alone. */ #endif /* !(RC_INVOKED || (_WCHAR_H && _STRING_H)) */ #if defined _WCHAR_H && ! defined RC_INVOKED #ifndef __STRICT_ANSI__ typedef wchar_t _Wint_t; #endif typedef int mbstate_t; [...] As you see, when wchar.h is included from string.h, only part of it is processed, and that part doesn't include, for example, the definition of mbstate_t, and all the prototypes of wchar.h functions after that. What happens in many Gnulib files (for example, dirname-lgpl.c) is that Gnulib's string.h is included, it includes MinGW string.h, which includes Gnulib's wchar.h, and that in turn includes MinGW wchar.h. But because string.h was included, __STRING_H_SOURCED__ is defined, and MinGW's wchar.h doesn't define mbstate_t. Gnulib's wchar.h doesn't expect that, and uses mbstate_t after #include_next. Previously, MinGW string.h didn't include wchar.h, but instead duplicated the relevant parts. So this problem didn't happen.