Liming,
We performed the initial exploration of CLANGPDB toolchain issue on our end and believe we can suggest a solid solution.
In addition to all the issues I mentioned in the BZ[1] there are several more.
1. CLANGPDB uses -target x86_64-unknown-windows, and this basically means different behaviour for Windows and other operating systems:
- On Windows it will "attach" to installed Visual Studio and will gather the parameters from this installation, i.e. it will define _MSC_VER to installed Visual Studio version. For example, for me it is implicitly passing -fms-compatibility-version=19.16.27026 and setting full triple to x86_64-unknown-windows-msvc19.16.27026.
- On Mac and Linux it will obviously not find Visual Studio, and as a result the full triple will be x86_64-unknown-windows-msvc with _MSC_VER macro not being defined.
There basically is no control to it except -U_MSC_VER, which is ugly, as different include directories, other defines will still happen between installations.
2. EDK II relies on UINT32_MAX being a valid value for enum. This is not the case in the specification, as it requires enum to be either INT32 or UINT32:
Element of a standard ANSI C enum type declaration. Type INT32.or UINT32. ANSI C does not define the size of sign of an enum so they should never be used in structures. ANSI C integer promotion rules make INT32 or UINT32 interchangeable when passed as an argument to a function.
However, since I am not positive that no existing code relies on this, it is best to preserve the current behaviour. Supporting this is valid for GNU flavour or as a Microsoft Extension. Disabling -fms-compatibility will result in a compile error for enums having 0xFFFFFFFF values, like in Base.h.
All in all, we believe that CLANGPDB simply has an overlook in the -target argument due to a misconsideration of the clang triple implementation. Normally for target only 3 words are provided, but for Windows it is crucial to have 4, as there are different drivers with different automatics. To resolve the problem, we should use GNU targets i686-unknown-windows-gnu and x86_64-unknown-windows-gnu. This is basically the only and the least hurtful solution, as using MSVC mode will define _MSC_EXTENSIONS, which already breaks many places and will require a heavy codebase refactoring, and randomly define _MSC_VER and use Visual Studio headers and configuration, which makes reproducible builds on different operating systems questionable if not impossible.
I will submit another patch that will replace this one later this week. In addition to GNU targets I additionally pass -nostdlib and -nostdlibinc so that a freestanding target is used and only builtin headers are accessible (like stdint.h, stddef.h, and stdbool.h). This is not required but an extra safety measure. Our initial validation of the changes found no issues with our projects. We also performed building of most common EDK II packages like CryptoPkg, MdePkg, and MdeModulePkg. While the change is fairly minor, I will still request others to perform a brief check of their packages in case they want to use CLANGPDB. For a quick test I include the diff of the patch beforehand.
Best wishes,
Vitaly