Skip to content

Commit

Permalink
<source_location>: Light up detailed function_name() for Clang 17…
Browse files Browse the repository at this point in the history
…, add escape hatch (#4055)
  • Loading branch information
StephanTLavavej committed Oct 4, 2023
1 parent f3f753d commit 94d9fdd
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 62 deletions.
18 changes: 14 additions & 4 deletions stl/inc/source_location
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,25 @@ _STL_DISABLE_CLANG_WARNINGS
#pragma push_macro("new")
#undef new

#ifndef _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
#ifdef __EDG__ // TRANSITION, DevCom-10199227
#define _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION 0
#elif defined(__clang__) // TRANSITION, Clang 17 has this builtin
#define _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION __has_builtin(__builtin_FUNCSIG)
#else // ^^^ Clang / MSVC vvv
#define _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION 1
#endif // ^^^ MSVC ^^^
#endif // ^^^ !defined(_USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION) ^^^

_STD_BEGIN
_EXPORT_STD struct source_location {
_NODISCARD static consteval source_location current(const uint_least32_t _Line_ = __builtin_LINE(),
const uint_least32_t _Column_ = __builtin_COLUMN(), const char* const _File_ = __builtin_FILE(),
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
const char* const _Function_ = __builtin_FUNCTION()
#else // ^^^ workaround / no workaround vvv
#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
const char* const _Function_ = __builtin_FUNCSIG()
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#else // ^^^ detailed / basic vvv
const char* const _Function_ = __builtin_FUNCTION()
#endif // ^^^ basic ^^^
) noexcept {
source_location _Result{};
_Result._Line = _Line_;
Expand Down
18 changes: 14 additions & 4 deletions tests/std/include/test_header_units_and_modules.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -679,11 +679,21 @@ constexpr bool impl_test_source_location() {
const auto sl = source_location::current();
assert(sl.line() == __LINE__ - 1);
assert(sl.column() == 38);
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
assert(sl.function_name() == "impl_test_source_location"sv);
#else // ^^^ workaround / no workaround vvv

#ifdef __EDG__ // TRANSITION, DevCom-10199227
#define TEST_DETAILED_FUNCTION_NAME 0
#elif defined(__clang__) // TRANSITION, Clang 17 has this builtin
#define TEST_DETAILED_FUNCTION_NAME __has_builtin(__builtin_FUNCSIG)
#else // ^^^ Clang / MSVC vvv
#define TEST_DETAILED_FUNCTION_NAME 1
#endif // ^^^ MSVC ^^^

#if TEST_DETAILED_FUNCTION_NAME
assert(sl.function_name() == "bool __cdecl impl_test_source_location(void)"sv);
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#else // ^^^ detailed / basic vvv
assert(sl.function_name() == "impl_test_source_location"sv);
#endif // ^^^ basic ^^^

assert(string_view{sl.file_name()}.ends_with("test_header_units_and_modules.hpp"sv));
return true;
}
Expand Down
8 changes: 4 additions & 4 deletions tests/std/tests/P1208R6_source_location/header.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ constexpr void header_test() {
#else // ^^^ EDG / C1XX vvv
assert(x.column() == 37);
#endif // ^^^ C1XX ^^^
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
assert(x.function_name() == "header_test"sv);
#else // ^^^ workaround / no workaround vvv
#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
assert(x.function_name() == "void __cdecl header_test(void)"sv);
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#else // ^^^ detailed / basic vvv
assert(x.function_name() == "header_test"sv);
#endif // ^^^ basic ^^^
assert(string_view{x.file_name()}.ends_with("header.h"sv));
}
113 changes: 63 additions & 50 deletions tests/std/tests/P1208R6_source_location/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@
#include <type_traits>
using namespace std;

#ifdef _M_IX86
#define THISCALL_OR_CDECL "__thiscall"
#else
#define THISCALL_OR_CDECL "__cdecl"
#endif

static_assert(is_nothrow_default_constructible_v<source_location>);
static_assert(is_nothrow_move_constructible_v<source_location>);
static_assert(is_nothrow_move_assignable_v<source_location>);
Expand Down Expand Up @@ -61,23 +67,23 @@ constexpr void local_test() {
#else // ^^^ EDG / C1XX vvv
assert(x.column() == 37);
#endif // ^^^ C1XX ^^^
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
assert(x.function_name() == "local_test"sv);
#else // ^^^ workaround / no workaround vvv
#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
assert(x.function_name() == "void __cdecl local_test(void)"sv);
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#else // ^^^ detailed / basic vvv
assert(x.function_name() == "local_test"sv);
#endif // ^^^ basic ^^^
assert(string_view{x.file_name()}.ends_with(test_cpp));
}

constexpr void argument_test(
const unsigned int line, const unsigned int column, const source_location x = source_location::current()) {
assert(x.line() == line);
assert(x.column() == column);
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
assert(x.function_name() == "test"sv);
#else // ^^^ workaround / no workaround vvv
#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
assert(x.function_name() == "bool __cdecl test(void)"sv);
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#else // ^^^ detailed / basic vvv
assert(x.function_name() == "test"sv);
#endif // ^^^ basic ^^^
assert(string_view{x.file_name()}.ends_with(test_cpp));
}

Expand All @@ -89,15 +95,18 @@ constexpr void sloc_constructor_test() {
#else // ^^^ defined(__EDG__) / !defined(__EDG__) vvv
assert(x.loc.column() == 13);
#endif // ^^^ !defined(__EDG__) ^^^
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
assert(x.loc.function_name() == "sloc_constructor_test"sv);
#else // ^^^ workaround / no workaround vvv
#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-1285783
if (is_constant_evaluated()) {
assert(x.loc.function_name() == "int __cdecl main(void)"sv); // TRANSITION, VSO-1285783
} else {
assert(x.loc.function_name() == "int __cdecl main(void)"sv);
} else
#endif // ^^^ workaround ^^^
{
assert(x.loc.function_name() == "void __cdecl sloc_constructor_test(void)"sv);
}
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#else // ^^^ detailed / basic vvv
assert(x.loc.function_name() == "sloc_constructor_test"sv);
#endif // ^^^ basic ^^^
assert(string_view{x.loc.file_name()}.ends_with(test_cpp));
}

Expand All @@ -111,13 +120,11 @@ constexpr void different_constructor_test() {
#else // ^^^ EDG / C1XX vvv
assert(x.loc.column() == 5);
#endif // ^^^ C1XX ^^^
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
assert(x.loc.function_name() == THISCALL_OR_CDECL " s::s(int)"sv);
#else // ^^^ detailed / basic vvv
assert(x.loc.function_name() == "s"sv);
#elif defined(_M_IX86) // ^^^ workaround / no workaround vvv
assert(x.loc.function_name() == "__thiscall s::s(int)"sv);
#else // ^^^ _M_IX86 / !_M_IX86 vvv
assert(x.loc.function_name() == "__cdecl s::s(int)"sv);
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#endif // ^^^ basic ^^^
assert(string_view{x.loc.file_name()}.ends_with(test_cpp));
}

Expand All @@ -129,15 +136,18 @@ constexpr void sub_member_test() {
#else // ^^^ defined(__EDG__) / !defined(__EDG__) vvv
assert(s.x.loc.column() == 14);
#endif // ^^^ !defined(__EDG__) ^^^
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
assert(s.x.loc.function_name() == "sub_member_test"sv);
#else // ^^^ workaround / no workaround vvv
#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
#if !defined(__clang__) && !defined(__EDG__) // TRANSITION, VSO-1285783
if (is_constant_evaluated()) {
assert(s.x.loc.function_name() == "int __cdecl main(void)"sv); // TRANSITION, VSO-1285783
} else {
assert(s.x.loc.function_name() == "int __cdecl main(void)"sv);
} else
#endif // ^^^ workaround ^^^
{
assert(s.x.loc.function_name() == "void __cdecl sub_member_test(void)"sv);
}
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#else // ^^^ detailed / basic vvv
assert(s.x.loc.function_name() == "sub_member_test"sv);
#endif // ^^^ basic ^^^
assert(string_view{s.x.loc.file_name()}.ends_with(test_cpp));

const s2 s_i{1};
Expand All @@ -149,13 +159,11 @@ constexpr void sub_member_test() {
#else // ^^^ EDG / C1XX vvv
assert(s_i.x.loc.column() == 5);
#endif // ^^^ C1XX ^^^
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
assert(s_i.x.loc.function_name() == THISCALL_OR_CDECL " s2::s2(int)"sv);
#else // ^^^ detailed / basic vvv
assert(s_i.x.loc.function_name() == "s2"sv);
#elif defined(_M_IX86) // ^^^ workaround / no workaround vvv
assert(s_i.x.loc.function_name() == "__thiscall s2::s2(int)"sv);
#else // ^^^ _M_IX86 / !_M_IX86 vvv
assert(s_i.x.loc.function_name() == "__cdecl s2::s2(int)"sv);
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#endif // ^^^ basic ^^^
assert(string_view{s_i.x.loc.file_name()}.ends_with(test_cpp));
}

Expand All @@ -176,19 +184,20 @@ constexpr void lambda_test() {
assert(x1.column() == 52);
assert(x2.column() == 50);
#endif // ^^^ C1XX ^^^
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
assert(x1.function_name() == "lambda_test"sv);
assert(x2.function_name() == "operator()"sv);
#elif defined(_M_IX86) // ^^^ workaround / no workaround vvv
assert(x1.function_name() == "void __cdecl lambda_test(void)"sv);
assert(
string_view{x2.function_name()}.starts_with("struct std::source_location __thiscall lambda_test::<lambda_"sv));
assert(string_view{x2.function_name()}.ends_with("::operator ()(void) const"sv));
#else // ^^^ _M_IX86 / !_M_IX86 vvv
#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
assert(x1.function_name() == "void __cdecl lambda_test(void)"sv);
assert(string_view{x2.function_name()}.starts_with("struct std::source_location __cdecl lambda_test::<lambda_"sv));
assert(string_view{x2.function_name()}.ends_with("::operator ()(void) const"sv));
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#else // ^^^ detailed / basic vvv
assert(x1.function_name() == "lambda_test"sv);
#endif // ^^^ basic ^^^
const string_view fun2{x2.function_name()};
#if !_USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
assert(fun2 == "operator()"sv);
#elif defined(__clang__) // ^^^ basic / detailed Clang vvv
assert(fun2 == "auto " THISCALL_OR_CDECL " lambda_test()::(anonymous class)::operator()(void) const"sv);
#else // ^^^ detailed Clang / detailed non-Clang vvv
assert(fun2.starts_with("struct std::source_location " THISCALL_OR_CDECL " lambda_test::<lambda_"sv));
assert(fun2.ends_with("::operator ()(void) const"sv));
#endif // ^^^ detailed non-Clang ^^^
assert(string_view{x1.file_name()}.ends_with(test_cpp));
assert(string_view{x2.file_name()}.ends_with(test_cpp));
}
Expand All @@ -208,21 +217,25 @@ constexpr void function_template_test() {
#else // ^^^ EDG / C1XX vvv
assert(x1.column() == 29);
#endif // ^^^ C1XX ^^^
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
#if !_USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
assert(x1.function_name() == "function_template"sv);
#else // ^^^ workaround / no workaround vvv
#elif defined(__clang__) // ^^^ basic / detailed Clang vvv
assert(x1.function_name() == "source_location __cdecl function_template(void) [T = void]"sv);
#else // ^^^ detailed Clang / detailed non-Clang vvv
assert(x1.function_name() == "struct std::source_location __cdecl function_template<void>(void)"sv);
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#endif // ^^^ detailed non-Clang ^^^
assert(string_view{x1.file_name()}.ends_with(test_cpp));

const auto x2 = function_template<int>();
assert(x1.line() == x2.line());
assert(x1.column() == x2.column());
#if defined(__clang__) || defined(__EDG__) // TRANSITION, DevCom-10199227 and LLVM-58951
#if !_USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION
assert(x2.function_name() == "function_template"sv);
#else // ^^^ workaround / no workaround vvv
#elif defined(__clang__) // ^^^ basic / detailed Clang vvv
assert(x2.function_name() == "source_location __cdecl function_template(void) [T = int]"sv);
#else // ^^^ detailed Clang / detailed non-Clang vvv
assert(x2.function_name() == "struct std::source_location __cdecl function_template<int>(void)"sv);
#endif // TRANSITION, DevCom-10199227 and LLVM-58951
#endif // ^^^ detailed non-Clang ^^^
assert(string_view{x1.file_name()} == string_view{x2.file_name()});
}

Expand Down

0 comments on commit 94d9fdd

Please sign in to comment.