Windows headers that are troublesome for clang

ok. new topic is being started here...

Your question isn't actually that clear. What kind of brokenness do you care about? Are you looking for C++ that clang can't parse, or standard library features that behave incompatibly on Windows? I think you mean the former.

The answer to that question is complicated. It depends on what you want to parse. I'd say there's several classes of stuff in order of increasing difficulty to parse:
- Plain C Windows SDK headers: windows.h
- MSVC C++ STL headers: vector, string
- Templateless COM headers: DirectX etc
- Template libraries: ATL, WRL

The first three classes aren't that hard to parse. When they use standard language features, they are mostly well-formed. The difficulty in parsing them is that they use lots and lots of language extensions. The basic stuff is dllexport and __stdcall, but it gets harder. There are weird IDL attributes involving square brackets, for example.

The final category is really something all on its own. MSVC's template model is drastically different from ours. You could hypothetically hack these headers in probably 20 or so places to get them to parse with Clang without any compatibility hacks, but you end up fighting an uphill battle. This is the category that native GUI apps tend to have, while batch processing apps like LLVM can get by with the first three sets.

thanks for the response!

I’m aware of difficulties in macro processing. that was mentioned by the boost fellow some time back.

you are adding in a few more. Here is the list as I understand it. Please correct it if I am wrong.

1) problems with template definitions and instantiation
2) calling convention and export/import attributes.
3) IDL support
4) difficulties with macro definition and expansion.

Have any of these been fully or partially addressed yet?

a related question:

as I understand it, if you run clang directly on windows (assuming a win32 host environment verses as posix one (cygwin etc)), it compiles as it does on every other platform but the symbols will be gcc-style…not ms-style. If you run it with the clang-cl wrapper, it uses an alternative preprocessor that matches that of cl.exe. Is that understanding correct? can one detect at compile time what processor he is going to get? Is there a switch to pick the desired preprocessor to override what clang-cl might choose by default?

-James

ok. new topic is being started here...

> Your question isn't actually that clear. What kind of brokenness do you
care about? Are you looking for C++ that clang can't parse, or standard
library features that behave incompatibly on Windows? I think you mean the
former.
>
> The answer to that question is complicated. It depends on what you want
to parse. I'd say there's several classes of stuff in order of increasing
difficulty to parse:
> - Plain C Windows SDK headers: windows.h
> - MSVC C++ STL headers: vector, string
> - Templateless COM headers: DirectX etc
> - Template libraries: ATL, WRL
>
> The first three classes aren't that hard to parse. When they use
standard language features, they are mostly well-formed. The difficulty in
parsing them is that they use lots and lots of language extensions. The
basic stuff is dllexport and __stdcall, but it gets harder. There are weird
IDL attributes involving square brackets, for example.
>
> The final category is really something all on its own. MSVC's template
model is drastically different from ours. You could hypothetically hack
these headers in probably 20 or so places to get them to parse with Clang
without any compatibility hacks, but you end up fighting an uphill battle.
This is the category that native GUI apps tend to have, while batch
processing apps like LLVM can get by with the first three sets.

thanks for the response!

I’m aware of difficulties in macro processing. that was mentioned by the
boost fellow some time back.

you are adding in a few more. Here is the list as I understand it. Please
correct it if I am wrong.

1) problems with template definitions and instantiation
2) calling convention and export/import attributes.
3) IDL support
4) difficulties with macro definition and expansion.

Have any of these been fully or partially addressed yet?

See http://llvm.org/bugs/show_bug.cgi?id=13707 and blockers, in particular
http://llvm.org/bugs/show_bug.cgi?id=12477 and blockers. Many of these
mention that they're for system headers, but not all the changes that were
necessary for system headers do say that. There's also a ton of work that
was done not tracked by bugs, search the commit logs for "ms abi" etc to
find that.

a related question:

as I understand it, if you run clang directly on windows (assuming a win32
host environment verses as posix one (cygwin etc)), it compiles as it does
on every other platform but the symbols will be gcc-style…not ms-style. If
you run it with the clang-cl wrapper, it uses an alternative preprocessor
that matches that of cl.exe. Is that understanding correct?

The clang-cl wrapper only sets different defaults. You can get the same
behavior with both the cl-compatible driver and the gcc-compatible driver
if you pass the right flags. You can pass -### to both drivers to see the
actual frontend flags they pass. The ABI is determined by the triple (the
driver's -target flag

can one detect at compile time what processor he is going to get? Is there
a switch to pick the desired preprocessor to override what clang-cl might
choose by default?

Yes, see http://clang.llvm.org/docs/MSVCCompatibility.html

I’m not sure if this has changed since clang-cl was introduced but resulting clang depends on what you build it with. I’m sure this will go away at some point if it hasn’t already. Compiling clang with mingw produces a mingw compatible clang that uses libstd++ and ld. Compiling it with Visual Studio would produce msvc compatible clang that uses msvc stl and link.exe. I think the main difference comes from the triple where something like i586-win32-pc defines a different abi from i586-pc-mingw and passes -fms-extensions -fms-compatibility and some other stuff to indicate msvc compatibility. Have a look at http://clang.llvm.org/docs/MSVCCompatibility.html

clang-cl is supposed to be a drop in replacement for cl.exe and as such accepts same command line options and enables language extensions and/or bugs :). The same way clang/clang++ are a drop in replacement for gcc/g++. But there’s nothing preventing you from using the compliant version of clang on windows, it’s just a matter of what flags are being passed to the driver.

Then there’s also the idea of the complete clang toolchain on windows (libc++, lld, lldb) that many people would like to use. But the question of default ABI for this toolchain still remains. I can’t find the thread but I remember someone pointing out that just because Microsoft owns the platform it doesn’t mean that their compiler’s abi should be seen as the default one. But if Herb’s proposal for C++ ABI is accepted it will mean exactly that, the platform defines the abi…

thank you for taking the time to summarize all that. I’ll go through it all and educate myself.

What I would hope is possible is to be able to specify on a per-translation-unit basis to compile the unit in a completely normal fashion, but get microsoft symbols in the .o files OR compile the unit with with the microsoft-spcific adaptations. That way, some units could depend on Windows.h and Win32 and others could depend on libc++ and behave as I would expect on every other platform. If I can do that then I can contrive a shim layer to adapt insulated Win32 code to work with any standard c++ code that I want.

I always structure my projects so that most of it is standard c++ with an insulated platform-specific later…even if I don’t immediately need to have the code cross-platform.

-James

The main culprits are -fms-compatibility and -fdelayed-template-parsing
(and to a lesser extent -fms-extensions). If you tuck all uses of
Windows SDK headers away then it's enough to compile just these with the
additional flags. Depending on what headers you need, -fms-extensions
and a forward-declared "struct IUnknown;" are often sufficient (I've
used it for lean windows.h, D3D/D2D, multimedia).

-Nico