Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User/dmachaj/slim source location #1379

Merged
merged 3 commits into from
Dec 22, 2023
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
75 changes: 72 additions & 3 deletions strings/base_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,58 @@ typedef struct _GUID GUID;
// Some projects may decide to disable std::source_location support to prevent source code information from ending up in their
// release binaries, or to reduce binary size. Defining WINRT_NO_SOURCE_LOCATION will prevent this feature from activating.
#if defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION)

namespace winrt::impl
{
// This struct is intended to be highly similar to std::source_location. The key difference is
// that function_name is NOT included. Function names do not fold to identical strings and can
// have heavy binary size overhead when templates cause many permutations to exist.
struct slim_source_location
{
[[nodiscard]] static consteval slim_source_location current(
const std::uint_least32_t line = __builtin_LINE(),
const char* const file = __builtin_FILE()) noexcept
{
return slim_source_location{ line, file };
}

[[nodiscard]] constexpr slim_source_location() noexcept = default;

[[nodiscard]] constexpr slim_source_location(const std::uint_least32_t line,
const char* const file) noexcept :
m_line(line),
m_file(file)
{}

[[nodiscard]] constexpr std::uint_least32_t line() const noexcept
{
return m_line;
}

[[nodiscard]] constexpr const char* file_name() const noexcept
{
return m_file;
}

constexpr const char* function_name() const noexcept
{
// This is intentionally not included. See comment above.
return nullptr;
}

private:
const std::uint_least32_t m_line{};
const char* const m_file{};
};
}

// std::source_location includes function_name which can be helpful but creates a lot of binary size impact. Many consumers
// have defined WINRT_NO_SOURCE_LOCATION to prevent this impact, losing the value of source_location. We have defined a
// slim_source_location struct that is equivalent but excludes function_name. This should have the vast majority of the
// usefulness of source_location while having a much smaller binary impact.
//
// When building _DEBUG binary size is not usually much of a concern, so we can use the full source_location type.
#ifdef _DEBUG
#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()
Expand All @@ -96,7 +148,24 @@ typedef struct _GUID GUID;

#ifdef _MSC_VER
#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "true")
#endif
#endif // _MSC_VER

#else // !_DEBUG
#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT , winrt::impl::slim_source_location const& sourceInformation
#define WINRT_IMPL_SOURCE_LOCATION_ARGS , winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()
#define WINRT_IMPL_SOURCE_LOCATION_ARGS_SINGLE_PARAM winrt::impl::slim_source_location const& sourceInformation = winrt::impl::slim_source_location::current()

#define WINRT_IMPL_SOURCE_LOCATION_FORWARD , sourceInformation
#define WINRT_IMPL_SOURCE_LOCATION_FORWARD_SINGLE_PARAM sourceInformation

#define WINRT_SOURCE_LOCATION_ACTIVE

#ifdef _MSC_VER
#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "slim")
#endif // _MSC_VER

#endif // _DEBUG

#else
#define WINRT_IMPL_SOURCE_LOCATION_ARGS_NO_DEFAULT
#define WINRT_IMPL_SOURCE_LOCATION_ARGS
Expand All @@ -107,5 +176,5 @@ typedef struct _GUID GUID;

#ifdef _MSC_VER
#pragma detect_mismatch("WINRT_SOURCE_LOCATION", "false")
#endif
#endif
#endif // _MSC_VER
#endif // defined(__cpp_lib_source_location) && !defined(WINRT_NO_SOURCE_LOCATION)
4 changes: 4 additions & 0 deletions test/test_cpp20/custom_error.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,16 @@ TEST_CASE("custom_error_logger")
const auto fileNameSv = std::string_view(s_loggerArgs.fileName);
REQUIRE(!fileNameSv.empty());
REQUIRE(fileNameSv.find("custom_error.cpp") != std::string::npos);
#ifdef _DEBUG
const auto functionNameSv = std::string_view(s_loggerArgs.functionName);
REQUIRE(!functionNameSv.empty());
// Every compiler has a slightly different naming approach for this function, and even the same
// compiler can change its mind over time. Instead of matching the entire function name just
// match against the part we care about.
REQUIRE((functionNameSv.find("FailOnLine15") != std::string_view::npos));
#else
REQUIRE(s_loggerArgs.functionName == nullptr);
#endif // _DEBUG

REQUIRE(s_loggerArgs.returnAddress);
REQUIRE(s_loggerArgs.result == static_cast<int32_t>(0x80000018)); // E_ILLEGAL_DELEGATE_ASSIGNMENT)
Expand Down
Loading