Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 91 additions & 75 deletions strings/base_error.h

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions strings/base_includes.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
#include <format>
#endif

#ifdef __cpp_lib_source_location
#include <source_location>
#endif

#ifdef __cpp_lib_coroutine

#include <coroutine>
Expand Down
24 changes: 24 additions & 0 deletions strings/base_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,27 @@
struct IUnknown;
typedef struct _GUID GUID;
#endif

// std::source_location is a C++20 feature, which is above the C++17 feature floor for cppwinrt. The source location needs
// to be the calling code, not cppwinrt itself, so that it is useful to developers building on top of this library. As a
// result any public-facing method that can result in an error needs a default-constructed source_location argument. Because
// this type does not exist in C++17 we need to use a macro to optionally add parameters and forwarding wherever appropriate.
#ifdef __cpp_lib_source_location
#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , std::source_location const& sourceInformation
#define WINRT_IMPL_SOURCE_LOCATION_ARGS , std::source_location const& sourceInformation = std::source_location::current()
#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM std::source_location const& sourceInformation = std::source_location::current()

#define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation
#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation

#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "true")
#else
#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT
#define WINRT_IMPL_SOURCE_LOCATION_ARGS
#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM

#define WINRT_IMPL_SOURCE_LOCATION_FORWARD
#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM

#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "false")
#endif
2 changes: 1 addition & 1 deletion strings/base_meta.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

WINRT_EXPORT namespace winrt
{
hresult check_hresult(hresult const result);
hresult check_hresult(hresult const result WINRT_IMPL_SOURCE_LOCATION_ARGS);
hresult to_hresult() noexcept;

template <typename D, typename I>
Expand Down
6 changes: 5 additions & 1 deletion test/test/custom_error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,11 @@ namespace

void __stdcall logger(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept
{
lineNumber; fileName; functionName;
// In C++17 these fields cannot be filled in so they are expected to be empty.
REQUIRE(lineNumber == 0);
REQUIRE(fileName == nullptr);
REQUIRE(functionName == nullptr);

REQUIRE(returnAddress);
REQUIRE(result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT)
s_loggerCalled = true;
Expand Down
48 changes: 48 additions & 0 deletions test/test_cpp20/custom_error.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#include "pch.h"

using namespace winrt;
using namespace Windows::Foundation;

namespace
{
static bool s_loggerCalled = false;

// Note that we are checking that the source line number matches expectations. If lines above this are changed
// then this value needs to change as well.
void FailOnLine15()
{
// Validate that handler translated exception
REQUIRE_THROWS_AS(check_hresult(0x80000018), hresult_illegal_delegate_assignment);
}

void __stdcall logger(uint32_t lineNumber, char const* fileName, char const* functionName, void* returnAddress, winrt::hresult const result) noexcept
{
// In C++20 these fields should be filled in by std::source_location
REQUIRE(lineNumber == 15);
const auto fileNameSv = std::string_view(fileName);
REQUIRE(!fileNameSv.empty());
REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos);
const auto functionNameSv = std::string_view(functionName);
REQUIRE(!functionNameSv.empty());
REQUIRE(functionNameSv == "FailOnLine15");

REQUIRE(returnAddress);
REQUIRE(result == 0x80000018); // E_ILLEGAL_DELEGATE_ASSIGNMENT)
s_loggerCalled = true;
}
}

TEST_CASE("custom_error_logger")
{
// Set up global handler
REQUIRE(!s_loggerCalled);
REQUIRE(!winrt_throw_hresult_handler);
winrt_throw_hresult_handler = logger;

FailOnLine15();
REQUIRE(s_loggerCalled);

// Remove global handler
winrt_throw_hresult_handler = nullptr;
s_loggerCalled = false;
}
2 changes: 2 additions & 0 deletions test/test_cpp20/pch.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@
#include <winstring.h>
#include "catch.hpp"

#include <string_view>

using namespace std::literals;
1 change: 1 addition & 0 deletions test/test_cpp20/test_cpp20.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="await_completed.cpp" />
<ClCompile Include="custom_error.cpp" />
<ClCompile Include="format.cpp" />
<ClCompile Include="hstring.cpp" />
<ClCompile Include="main.cpp">
Expand Down