Compilers and Conformance

As the compiler vendors ramp up investment in C++ features and improved conformance, there is a bit of an arms race with library developers trying to keep up, while maintaining some degree of compatibility with current compilers. Two recent issues highlight this quite well. As of Visual C++ 15.8 Preview 3, Microsoft’s C++ compiler provides dramatically improved conformance. This has had the effect of detecting long-standing bugs in various libraries that previously compiled without issue.

Take for example the version of C++/WinRT that shipped with the 17134 (RS4) build of the Windows SDK. C++/WinRT builds fine without /permissive-, but with the added conformance that this flag provides it now produces the following error:

C:\Program Files (x86)\Windows Kits\10\Include\10.0.17134.0\cppwinrt\winrt/base.h(2185): error C3861: ‘from_abi’: identifier not found

That’s because the from_abi function was used before it was declared. This all happens inside various templates and the Visual C++ compiler has traditionally been rather lazy about resolving such names and so it previously worked and went undetected. Now that the Visual C++ compiler provides two-phase name lookup via /permissive- it can and does detect such bugs. I have been testing with daily builds of the Visual C++ compiler and thus fixed this bug months ago. The fix is thus already available in preview builds of the Windows SDK. Of course, this is not unique to C++/WinRT. I have fixed numerous such bugs in a variety of libraries over the last year as we’ve been getting ready to ship Visual C++ 15.8. I also now do a much better job of leveraging Clang for added validation.

If you are however stuck using Visual C++ 15.8 with the 17134 SDK then you can work around this problem by removing the /permissive- flag (aka Comformance mode) from the C++ compiler options.

Another example is one that’s plagued C++/WinRT from the early days but was actually a compiler bug rather than an undetected library bug. Consider this example:

struct Type {};

template <typename T>
void Use()

namespace Sample
    struct Type {};

using namespace Sample;

int main()

The global Type is being used in a function that happens to be a template. Later, Type is defined in the Sample namespace. That’s obviously a different Type and there’s no ambiguity. Indeed, even if the using namespace directive is used to introduce the names from the Sample namespace for unqualified name lookup there should still be no ambiguity unless the code actually refers to an unqualified Type following the using namespace directive. And yet, Visual C++ has historically complained about this:

app.cpp(6): error C2872: ‘Type’: ambiguous symbol

Visual C++ was being lazy, not necessarily a bad thing, and didn’t bother to resolve the Type in the context of the function template’s definition. Instead, it chose to resolve it in the context of its instantiation. That’s definitely a bad thing. Thankfully, using /permissive- forces two-phase name lookup and this error goes away and this correct code finally compiles!

Improved conformance helps everyone. Library developers just happen to be on the front line and work very hard to deal with these issues as quickly as possible. Sometimes delays in the various distribution channels or uncoordinated releases of compilers and libraries can also cause headaches for app developers. Hopefully this helps to shed some light on these issues.

8 thoughts on “Compilers and Conformance

  1. Thibault Jochem

    Hi Kenny,
    Kind of unrelated to this article… did you delete your twitter account ? I was looking for some anwer you gave me in past interactions, and cannot find your twitter account anymore.

  2. Jeff

    Hi Kenny, I’ve tried recompiling without the permissive flag but I get an error in combaseapi.h: error C2872: ‘IUnknown’: ambiguous symbol.
    The offending code is below.
    extern “C++”
    template _Post_equal_to_(pp) _Post_satisfies_(return == pp) void** IID_PPV_ARGS_Helper(T** pp)
    #pragma prefast(suppress: 6269, “Tool issue with unused static_cast”)
    static_cast(*pp); // make sure everyone derives from IUnknown
    return reinterpret_cast(pp);


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s