Skip to content

Conversation

@oldnewthing
Copy link
Member

The existing mismatch detection catches the case where a single *.cpp file includes headers from different versions of the C++/WinRT headers. However, the error message isn't very helpful in tracking down the two versions that didn't match.

Move the #define of CPPWINRT_VERSION outside the header guard and repeat the definition after the static_assert. This makes mismatches easier to diagnose because the compiler will tell you

apple\base.h(3) warning: CPPWINRT_VERSION: macro redefinition
banana\base.h(3) note: see previous definition of CPPWINRT_VERSION

in the case where you #include two incompatible versions of base.h, or

apple\Windows.UI.h(6) error: Mismatched C++/WinRT headers.
apple\Windows.UI.h(7) warning: CPPWINRT_VERSION: macro redefinition
banana\base.h(3) note: see previous definition of CPPWINRT_VERSION

in the case where you use a projection header file that is not compatible with the base.h you used.

In both cases, the compiler will give you the path to the conflicting header files, making it easier to diagnose. In this case, you can see that you are mixing headers between apple and banana.

This takes advantage of the fact that it is legal to redefine a macro provided you redefine it to something that exactly matches its existing definition. We have everybody define the CPPWINRT_VERSION macro to be the version they expect, and the compiler will call out any discrepancy within a single translation unit.

A more insidious error that had previous gone undetected is the case where you link together *.cpp files that disagree on the C++/WinRT version.

We address this by using MSVC's detect_mismatch pragma to stamp each object file with the version of C++/WinRT it was compiled with, and the linker will complain if object files with different stamps are linked together:

file1.obj: error: mismatch detected for 'C++/WinRT version':
value '1.2.3.4' doesn't match value '2.3.4.5' in file2.obj

The existing mismatch detection catches only
the case where a single *.cpp file includes headers
from different versions of the C++/WinRT headers.
However, the error message isn't very helpful in
tracking down the two versions that didn't match.

Move the `#define` of `CPPWINRT_VERSION` outside
the header guard and repeat the definition after the
`static_assert`.  This makes mismatches easier to diagnose
because the compiler will tell you

```
apple\base.h(3) warning: CPPWINRT_VERSION: macro redefinition
banana\base.h(3) note: see previous definition of CPPWINRT_VERSION
```
in the case where you `#include` two incompatible versions
of `base.h`, or

```
apple\Windows.UI.h(6) error: Mismatched C++/WinRT headers.
apple\Windows.UI.h(7) warning: CPPWINRT_VERSION: macro redefinition
banana\base.h(3) note: see previous definition of CPPWINRT_VERSION
```

in the case where you use a projection header file that
is not compatible with the `base.h` you used.

In both cases, the compiler will give you the path to
the conflicting header files, making it easier to diagnose.
In this case, you can see that you are mixing headers
between apple and banana.

This takes advantage of the fact that it is legal to
redefine a macro provided you redefine it to something
that exactly matches its existing definition. We have
everybody define the `CPPWINRT_VERSION` macro to be
the version they expect, and the compiler will call out
any discrepancy within a single translation unit.

A more insidious error that had previous gone undetected is
the case where you link together *.cpp files that disagree
on the C++/WinRT version.

We address this by using MSVC's detect_mismatch pragma
to stamp each object file with the version of C++/WinRT
it was compiled with, and the linker will complain if
object files with different stamps are linked together:

```
file1.obj: error: mismatch detected for 'C++/WinRT version':
value '1.2.3.4' doesn't match value '2.3.4.5' in file2.obj
```
@kennykerr
Copy link
Collaborator

/azp run

@azure-pipelines
Copy link

No pipelines are associated with this pull request.

Copy link
Collaborator

@kennykerr kennykerr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice!

@kennykerr kennykerr merged commit 2e05e58 into microsoft:master Jul 9, 2020
@oldnewthing oldnewthing deleted the version-mismatch branch July 9, 2020 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants