Clang inconsistency with gcc on Windows

Compiling some Boost library code the latest clang has produced an inconsistency with gcc on Windows that is making it impossible to build Boost libraries successfully.

The code in question, where clang is given an error:

clang-linux.compile.c++.without-pth ..\..\..\bin.v2\libs\context\build\clang-linux-3.7.0\debug\threading-multi\windows\stack_traits.obj
In file included from ..\..\..\libs\context\src\windows\stack_traits.cpp:24:
In file included from ..\..\..\boost/thread.hpp:13:
In file included from ..\..\..\boost/thread/thread.hpp:12:
In file included from ..\..\..\boost/thread/thread_only.hpp:15:
In file included from ..\..\..\boost/thread/win32/thread_data.hpp:10:
In file included from ..\..\..\boost/thread/thread_time.hpp:10:
In file included from ..\..\..\boost/date_time/microsec_time_clock.hpp:23:
..\..\..\boost/date_time/filetime_functions.hpp:57:46: error: conflicting types for 'GetSystemTimeAsFileTime'
        __declspec(dllimport) void __stdcall GetSystemTimeAsFileTime(FILETIME* lpFileTime);
                                             ^
/mingw/include\winbase.h:1397:24: note: previous declaration is here
WINBASEAPI void WINAPI GetSystemTimeAsFileTime(LPFILETIME);

                          ^

and more of the same in many places building Boost libraries with clang.

This is with the latest clang, which I build with mingw/gcc-4.8.1 on Windows.

With gcc-4.8.1:

gcc.compile.c++ ..\..\..\bin.v2\libs\context\build\gcc-mingw-4.8.1\debug\threading-multi\windows\stack_traits.o

With gcc-4.9.2

gcc.compile.c++ ..\..\..\bin.v2\libs\context\build\gcc-mingw-4.9.2\debug\threading-multi\windows\stack_traits.o

This is happening extensively in Boost code which uses the Windows API when compiling under Windows.

I do not know what WINBASEAPI is supposed to resove to under mingw, but clearly it should not be different for gcc and clang under Windows and gcc has no problems with this.

Boost tries to supplies its own version of the Windows API to avoid including WIndows.h
Boost version of the API is not strictly identical to Windows.h, so if Windows.h do get included somehow such errors happen. I always -DBOOST_USE_WINDOWS_H to force Boost to use Windows.h instead of its own.

I have added the compiler command lines to my original message.

Compiling some Boost library code the latest clang has produced an
inconsistency with gcc on Windows that is making it impossible to build
Boost libraries successfully.

The code in question, where clang is given an error:

clang-linux.compile.c++.without-pth
..\..\..\bin.v2\libs\context\build\clang-linux-3.7.0\debug\threading-multi\windows\stack_traits.obj

In file included from
..\..\..\libs\context\src\windows\stack_traits.cpp:24:
In file included from ..\..\..\boost/thread.hpp:13:
In file included from ..\..\..\boost/thread/thread.hpp:12:
In file included from ..\..\..\boost/thread/thread_only.hpp:15:
In file included from ..\..\..\boost/thread/win32/thread_data.hpp:10:
In file included from ..\..\..\boost/thread/thread_time.hpp:10:
In file included from
..\..\..\boost/date_time/microsec_time_clock.hpp:23:
..\..\..\boost/date_time/filetime_functions.hpp:57:46: error:
conflicting types for 'GetSystemTimeAsFileTime'
        __declspec(dllimport) void __stdcall
GetSystemTimeAsFileTime(FILETIME* lpFileTime);
                                             ^
/mingw/include\winbase.h:1397:24: note: previous declaration is here
WINBASEAPI void WINAPI GetSystemTimeAsFileTime(LPFILETIME);

                          ^

and more of the same in many places building Boost libraries with clang.

The clang command line is:

"C:/Programming/VersionControl/bninja_installed_clang/bin/clang++.exe" -c -x c++ -O0 -g -fno-inline -Wall -g -march=i686 -pthread -m32 -DBOOST_ALL_NO_LIB=1 -DBOOST_CHRONO_DYN_LINK=1 -DBOOST_CONTEXT_DYN_LINK=1 -DBOOST_CONTEXT_SOURCE -DBOOST_SYSTEM_DYN_LINK=1 -DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_THREAD_BUILD_DLL=1 -DBOOST_THREAD_USE_DLL=1 -I"..\..\.." -o "..\..\..\bin.v2\libs\context\build\clang-linux-3.7.0\debug\threading-multi\windows\stack_traits.obj" "..\..\..\libs\context\src\windows\stack_traits.cpp"

This is with the latest clang, which I build with mingw/gcc-4.8.1 on
Windows.

With gcc-4.8.1:

gcc.compile.c++
..\..\..\bin.v2\libs\context\build\gcc-mingw-4.8.1\debug\threading-multi\windows\stack_traits.o

The gcc-4.8.1 command line is:

"g++" -ftemplate-depth-128 -O0 -fno-inline -Wall -g -march=i686 -mthreads -m32 -DBOOST_ALL_NO_LIB=1 -DBOOST_CHRONO_DYN_LINK=1 -DBOOST_CONTEXT_DYN_LINK=1 -DBOOST_CONTEXT_SOURCE -DBOOST_SYSTEM_DYN_LINK=1 -DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_THREAD_BUILD_DLL=1 -DBOOST_THREAD_USE_DLL=1 -I"..\..\.." -c -o "..\..\..\bin.v2\libs\context\build\gcc-mingw-4.8.1\debug\threading-multi\windows\stack_traits.o" "..\..\..\libs\context\src\windows\stack_traits.cpp"

With gcc-4.9.2

gcc.compile.c++
..\..\..\bin.v2\libs\context\build\gcc-mingw-4.9.2\debug\threading-multi\windows\stack_traits.o

The gcc-4.9.2 command line is:

"g++" -ftemplate-depth-128 -O0 -fno-inline -Wall -g -march=i686 -mthreads -m32 -DBOOST_ALL_NO_LIB=1 -DBOOST_CHRONO_DYN_LINK=1 -DBOOST_CONTEXT_DYN_LINK=1 -DBOOST_CONTEXT_SOURCE -DBOOST_SYSTEM_DYN_LINK=1 -DBOOST_SYSTEM_NO_DEPRECATED -DBOOST_THREAD_BUILD_DLL=1 -DBOOST_THREAD_USE_DLL=1 -I"..\..\.." -c -o "..\..\..\bin.v2\libs\context\build\gcc-mingw-4.9.2\debug\threading-multi\windows\stack_traits.o" "..\..\..\libs\context\src\windows\stack_traits.cpp"

Boost tries to supplies its own version of the Windows API to avoid
including WIndows.h
Boost version of the API is not strictly identical to Windows.h, so if
Windows.h do get included somehow such errors happen. I always
-DBOOST_USE_WINDOWS_H to force Boost to use Windows.h instead of its own.

Thanks, that does work.

I still would like to know why clang is giving errors in the situation I describe in my OP and gcc is not. I am not saying that clang is wrong to do so but clearly it is not being compatible with gcc in this area.

Maybe gcc is more fogiving with checking redeclarations or some compiler predefine is not the same. You can check this in depth by looking at preprocess output (-E) and comparing how both compilers expand the GetSystemTimeAsFileTime declaration.

Maybe gcc is more fogiving with checking redeclarations or some compiler
predefine is not the same. You can check this in depth by looking at
preprocess output (-E) and comparing how both compilers expand the
GetSystemTimeAsFileTime declaration.

Both compilers expand the different GetSystemTimeAsFileTime declaration in the internal Boost winapi headers and the mingw headers in exactly the same way.

The preprocessed expansion in the internal Boost winapi header is:

      __attribute__((dllimport)) void __attribute__((__stdcall__))
          GetSystemTimeAsFileTime(FILETIME_* lpFileTime);

and the preprocessed expansion in the mingw headers is:

      void __attribute__((__stdcall__)) GetSystemTimeAsFileTime(LPFILETIME);

where FILETIME_ and LPFILETIME are the same structure.

The gcc compiler sees these declarations as the same but the clang compiler sees them as different and therefore an error.

I’ts a good question wether attribute((dllimport)) should really be ignored here but we’ll probably want to in order to keep compatibility with mingw. Could you file a bug report on this?

I'ts a good question wether __attribute__((dllimport)) should really be
ignored here but we'll probably want to in order to keep compatibility
with mingw. Could you file a bug report on this?

Bug report at https://llvm.org/bugs/show_bug.cgi?id=23722.