Skip to content

Conversation

@oldnewthing
Copy link
Member

@oldnewthing oldnewthing commented Aug 26, 2020

Mismatching WINRT_NO_MAKE_DETECTION results in inconsistent vtables and very confusing runtime crashes. Detect the problem at link time.

pragma detect_mismatch must occur at global scope, so we float it to the top of base_implements.h even though it would more logically be placed at the point of declaration of the bonus virtual member.

This change uncovered the fact that test and test_win7 had portions built with and without WINRT_NO_MAKE_DETECTION, so it was already violating ODR. Moved the WINRT_NO_MAKE_DETECTION to the test component and make the entire test component enable WINRT_NO_MAKE_DETECTION.

The symbol WINRT_LEAN_AND_MEAN does not require ODR protection because it excludes entire functions and classes, rather than rewriting pieces of existing functions and classes.

Technically, WINRT_IMPL_IUNKNOWN_DEFINED and __IInspectable_INTERFACE_DEFINED__ are also subject to ODR due to how it changes the definition of some type traits classes some types in the winrt::impl namespace, and activates some member functions and specializations. In practice, this isn't a problem because the type traits classes are constexpr (and therefore follow the settings of the current translation unit), and the other issues, if conflicting, trigger linkage errors.

Mismatching `WINRT_NO_MAKE_DETECTION` results in inconsistent vtables
and very confusing runtime crashes. Detect the problem at link time.

`pragma detect_mismatch` must occur at global scope, so we float
it to the top of `base_implements.h` even though it would more logically
be placed at the point of declaration of the bonus virtual member.

This change uncovered the fact that `test` and `test_win7` had
portions built with and without `WINRT_NO_MAKE_DETECTION`, so it
was already violating ODR violation. Moved the `WINRT_NO_MAKE_DETECTION`
to the test component and make the entire test component enable
`WINRT_NO_MAKE_DETECTION`.

The symbol `WINRT_LEAN_AND_MEAN` does not require ODR protection
because it excludes entire functions and classes, rather than rewriting
pieces of existing functions and classes.

Technically, `WINRT_IMPL_IUNKNOWN_DEFINED` is also subject to ODR
due to how it changes the definition of some type traits classes
some types in the `winrt::impl` namespace, and activates some member
functions and specializations. In practice, this isn't a problem because
the type traits classes are constexpr (and therefore follow the settings
of the current translation unit), and the other issues, if conflicting,
trigger linkage errors.
@kennykerr kennykerr merged commit 84d2814 into microsoft:master Sep 1, 2020
@oldnewthing oldnewthing deleted the odr branch February 16, 2021 15:31
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.

3 participants