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

<source_location>: Light up detailed function_name() for Clang 17, add escape hatch #4055

Merged
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
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