When building a testdir with C++ tests on MSVC 14, I see this error: source='../../gltests/test-wchar-c++3.cc' object='test-wchar-c++3.obj' libtool=no \ DEPDIR=.deps depmode=msvc7 /bin/sh ../../build-aux/depcomp \ /home/bruno/msvc/compile cl -nologo -DHAVE_CONFIG_H -DEXEEXT=\".exe\" -I. -I../../gltests -I.. -DGNULIB_STRICT_CHECKING=1 -DIN_GNULIB_TESTS=1 -I. -I../../gltests -I.. -I../../gltests/.. -I../gllib -I../../gltests/../gllib -D_WIN32_WINNT=_WIN32_WINNT_WINXP -I/usr/local/msvc64/include -MD -c -o test-wchar-c++3.obj `cygpath -w '../../gltests/test-wchar-c++3.cc'` test-wchar-c++3.cc ... C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xlocinfo(127): error C2440: 'return': cannot convert from 'lconv *' to 'const rpl_lconv *' C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xlocinfo(127): note: Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast ... make[4]: *** [Makefile:9886: test-wchar-c++3.obj] Error 2
The cause is a use of 'struct lconv' deep inside the C++ header files. The fix is to not override 'struct lconv' and 'localeconv' on this platform. What the override would do (see lib/localeconv.c lines 53..58) is to map the missing struct members to those without 'int_' prefix. We can do the same thing through C macros. This is not as good as the original override, because - it will also affect other uses of the identifiers int_p_cs_precedes, int_p_sign_posn, int_p_sep_by_space, int_n_cs_precedes, int_n_sign_posn, int_n_sep_by_space, - it will not work in code that uses 'struct lconv' for its own purposes (other than for localeconv() invocations). But it should be good enough. 2019-12-11 Bruno Haible <br...@clisp.org> locale: Fix compilation error in C++ mode on MSVC. * m4/locale_h.m4 (gl_LOCALE_H): Don't set REPLACE_STRUCT_LCONV on MSVC. * lib/locale.in.h (int_p_cs_precedes, int_p_sign_posn, int_p_sep_by_space, int_n_cs_precedes, int_n_sign_posn, int_n_sep_by_space): Define as macros on MSVC. diff --git a/m4/locale_h.m4 b/m4/locale_h.m4 index 380e40b..c0ec3fc 100644 --- a/m4/locale_h.m4 +++ b/m4/locale_h.m4 @@ -1,4 +1,4 @@ -# locale_h.m4 serial 22 +# locale_h.m4 serial 23 dnl Copyright (C) 2007, 2009-2019 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -56,7 +56,20 @@ AC_DEFUN([gl_LOCALE_H], [gl_cv_sys_struct_lconv_ok=no]) ]) if test $gl_cv_sys_struct_lconv_ok = no; then - REPLACE_STRUCT_LCONV=1 + dnl On native Windows with MSVC, merely define these member names as macros. + dnl This avoids trouble in C++ mode. + case "$host_os" in + mingw*) + AC_EGREP_CPP([Special], [ +#ifdef _MSC_VER + Special +#endif + ], + [], + [REPLACE_STRUCT_LCONV=1]) + ;; + *) REPLACE_STRUCT_LCONV=1 ;; + esac fi dnl <locale.h> is always overridden, because of GNULIB_POSIXCHECK. diff --git a/lib/locale.in.h b/lib/locale.in.h index 918d4dd..77b8b3b 100644 --- a/lib/locale.in.h +++ b/lib/locale.in.h @@ -64,6 +64,18 @@ # define LC_MESSAGES 1729 #endif +/* On native Windows with MSVC, 'struct lconv' lacks the members int_p_* and + int_n_*. Instead of overriding 'struct lconv', merely define these member + names as macros. This avoids trouble in C++ mode. */ +#if defined _MSC_VER +# define int_p_cs_precedes p_cs_precedes +# define int_p_sign_posn p_sign_posn +# define int_p_sep_by_space p_sep_by_space +# define int_n_cs_precedes n_cs_precedes +# define int_n_sign_posn n_sign_posn +# define int_n_sep_by_space n_sep_by_space +#endif + /* Bionic libc's 'struct lconv' is just a dummy. */ #if @REPLACE_STRUCT_LCONV@ # define lconv rpl_lconv