Skip to content

Conversation

@dmachaj
Copy link
Contributor

@dmachaj dmachaj commented Nov 1, 2024

Why is this change being made?

Someone is trying to upgrade the cppwinrt version used by a large project that has many static libraries using cppwinrt. Some binaries in that project are mixing static libs with different cpp language versions. (This seems like not a great idea generally but it is the state of the world so to some degree we have to live with it). In those binaries the ODR checks for cppwinrt source_location usage are breaking the build. For good reason, it is not safe to mix this functionality across language versions. This set of changes is aimed at making that upgrade process easier without losing any useful functionality.

Briefly summarize what changed

We already have winrt::impl::slim_source_location which is a lot like std::source_location, minus always containing the very impactful FUNCTION data. This type is powered by the same intrinsics as the STL version so it works as well as the STL library. The existence of this class means that we can avoid the ODR violations by always using winrt::impl::slim_source_location.

Some new macros are used to control what goes into the constructor. cpp20 code that does not suppress source_location will get valid source information passed in. Code that is cpp17, or suppresses this feature, will have zero's passed in. Furthermore, when compiling as _DEBUG this will also include the FUNCTION data, matching previous behavior.

The net result is that there is no more ODR violation because the function signatures are always the same.

For now I have elected not to clean up the WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT macro family. There is only one option so there is no more ODR violation. But removing that would churn a lot of code. I could be convinced to remove it now but only if there is agreement it is worth it and that we won't try to re-add variance later.

How was this change tested?

build_test_all.cmd for both release and debug. I also created a little project that mixes cpp17 and cpp20 libraries. With the latest public release of cppwinrt this project does not build because of the ODR violations. With these changes it builds and runs as expected.

build break with existing cppwinrt

3>Cpp17StaticLib.lib(Cpp17StaticLib.obj) : error LNK2038: mismatch detected for 'WINRT_SOURCE_LOCATION': value 'false' doesn't match value 'slim' in main.ob

cpp17 code

void Cpp17StaticLib()
{
    try
    {
        winrt::check_hresult(E_FAIL);
    }
    catch (const winrt::hresult_error& e)
    {
        wprintf(L"C++17 Static Lib: %ws\n", e.message().c_str());
    }
}

cpp20 code

void Cpp20StaticLib()
{
    try
    {
        winrt::check_hresult(E_FAIL);
    }
    catch (const winrt::hresult_error& e)
    {
        wprintf(L"C++20 Static Lib: %ws\n", e.message().c_str());
    }
}

console exe code

void __stdcall MY_winrt_throw_hresult_handler(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept
{
    wprintf(L"winrt::hresult_error thrown at line %u in %hs in %hs with error code 0x%08X\n", lineNumber, fileName, functionName, (uint32_t)result);
}

int main()
{
    winrt::init_apartment();

    winrt_throw_hresult_handler = MY_winrt_throw_hresult_handler;

    Cpp17StaticLib();
    Cpp20StaticLib();
}

Release output:

winrt::hresult_error thrown at line 0 in (null) in (null) with error code 0x80004005
winrt::hresult_error thrown at line 0 in (null) in (null) with error code 0x80004005
C++17 Static Lib: Unspecified error
winrt::hresult_error thrown at line 7 in %PATH%Cpp20StaticLib\Cpp20StaticLib.cpp in (null) with error code 0x80004005
winrt::hresult_error thrown at line 7 in %PATH%\Cpp20StaticLib\Cpp20StaticLib.cpp in (null) with error code 0x80004005
C++20 Static Lib: Unspecified error

Debug output:

winrt::hresult_error thrown at line 0 in (null) in (null) with error code 0x80004005
winrt::hresult_error thrown at line 0 in (null) in (null) with error code 0x80004005
C++17 Static Lib: Unspecified error
winrt::hresult_error thrown at line 7 in %PATH%\Cpp20StaticLib\Cpp20StaticLib.cpp in Cpp20StaticLib with error code 0x80004005
winrt::hresult_error thrown at line 7 in %PATH%\Cpp20StaticLib\Cpp20StaticLib.cpp in Cpp20StaticLib with error code 0x80004005
C++20 Static Lib: Unspecified error

jonwis
jonwis previously approved these changes Nov 1, 2024
ChrisGuzak
ChrisGuzak previously approved these changes Nov 2, 2024
Copy link
Member

@ChrisGuzak ChrisGuzak left a comment

Choose a reason for hiding this comment

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

I'm in favor of the macro cleanup too.

@dmachaj dmachaj dismissed stale reviews from ChrisGuzak and jonwis via f1c3241 November 3, 2024 19:55
@dmachaj dmachaj merged commit e53db0f into master Nov 4, 2024
75 checks passed
@dmachaj dmachaj deleted the user/dmachaj/slim-source-location-cpp17 branch November 4, 2024 22:53
@dikan-i
Copy link

dikan-i commented Jan 28, 2025

When new version with this fix will be released ?

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.

8 participants