From f4c4e958b07d308767240c78b42e9c10a205ea13 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 27 Sep 2023 15:42:30 -0700 Subject: [PATCH 1/4] Light up for Clang 17, add escape hatch. --- stl/inc/source_location | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/stl/inc/source_location b/stl/inc/source_location index e4e724d652..8829dd9306 100644 --- a/stl/inc/source_location +++ b/stl/inc/source_location @@ -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 + const char* const _Function_ = __builtin_FUNCTION() +#endif ) noexcept { source_location _Result{}; _Result._Line = _Line_; From 3458d68b1f3686016ca2446ae58ccabe2e98c1d7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 28 Sep 2023 14:12:36 -0700 Subject: [PATCH 2/4] Update the tests for Clang 17. --- .../include/test_header_units_and_modules.hpp | 18 +++- .../tests/P1208R6_source_location/header.h | 8 +- .../tests/P1208R6_source_location/test.cpp | 94 +++++++++++-------- 3 files changed, 74 insertions(+), 46 deletions(-) diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index 828a3e9bbc..d05807b52a 100644 --- a/tests/std/include/test_header_units_and_modules.hpp +++ b/tests/std/include/test_header_units_and_modules.hpp @@ -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 + assert(sl.function_name() == "impl_test_source_location"sv); +#endif + assert(string_view{sl.file_name()}.ends_with("test_header_units_and_modules.hpp"sv)); return true; } diff --git a/tests/std/tests/P1208R6_source_location/header.h b/tests/std/tests/P1208R6_source_location/header.h index e9c8b48bbb..7dff0cbc17 100644 --- a/tests/std/tests/P1208R6_source_location/header.h +++ b/tests/std/tests/P1208R6_source_location/header.h @@ -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 + assert(x.function_name() == "header_test"sv); +#endif assert(string_view{x.file_name()}.ends_with("header.h"sv)); } diff --git a/tests/std/tests/P1208R6_source_location/test.cpp b/tests/std/tests/P1208R6_source_location/test.cpp index 4640ca5c13..b55bd00996 100644 --- a/tests/std/tests/P1208R6_source_location/test.cpp +++ b/tests/std/tests/P1208R6_source_location/test.cpp @@ -61,11 +61,11 @@ 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 + assert(x.function_name() == "local_test"sv); +#endif assert(string_view{x.file_name()}.ends_with(test_cpp)); } @@ -73,11 +73,11 @@ 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 + assert(x.function_name() == "test"sv); +#endif assert(string_view{x.file_name()}.ends_with(test_cpp)); } @@ -89,15 +89,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 + assert(x.loc.function_name() == "sloc_constructor_test"sv); +#endif assert(string_view{x.loc.file_name()}.ends_with(test_cpp)); } @@ -111,13 +114,13 @@ 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() == "s"sv); -#elif defined(_M_IX86) // ^^^ workaround / no workaround vvv +#elif defined(_M_IX86) // ^^^ basic / detailed x86 vvv assert(x.loc.function_name() == "__thiscall s::s(int)"sv); -#else // ^^^ _M_IX86 / !_M_IX86 vvv +#else // ^^^ detailed x86 / detailed non-x86 vvv assert(x.loc.function_name() == "__cdecl s::s(int)"sv); -#endif // TRANSITION, DevCom-10199227 and LLVM-58951 +#endif // ^^^ detailed non-x86 ^^^ assert(string_view{x.loc.file_name()}.ends_with(test_cpp)); } @@ -129,15 +132,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 + assert(s.x.loc.function_name() == "sub_member_test"sv); +#endif assert(string_view{s.x.loc.file_name()}.ends_with(test_cpp)); const s2 s_i{1}; @@ -149,13 +155,13 @@ 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() == "s2"sv); -#elif defined(_M_IX86) // ^^^ workaround / no workaround vvv +#elif defined(_M_IX86) // ^^^ basic / detailed x86 vvv assert(s_i.x.loc.function_name() == "__thiscall s2::s2(int)"sv); -#else // ^^^ _M_IX86 / !_M_IX86 vvv +#else // ^^^ detailed x86 / detailed non-x86 vvv assert(s_i.x.loc.function_name() == "__cdecl s2::s2(int)"sv); -#endif // TRANSITION, DevCom-10199227 and LLVM-58951 +#endif // ^^^ detailed non-x86 ^^^ assert(string_view{s_i.x.loc.file_name()}.ends_with(test_cpp)); } @@ -176,19 +182,27 @@ 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 +#if !_USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION assert(x1.function_name() == "lambda_test"sv); assert(x2.function_name() == "operator()"sv); -#elif defined(_M_IX86) // ^^^ workaround / no workaround vvv +#elif defined(_M_IX86) // ^^^ basic / detailed x86 vvv assert(x1.function_name() == "void __cdecl lambda_test(void)"sv); +#ifdef __clang__ + assert(x2.function_name() == "auto __thiscall lambda_test()::(anonymous class)::operator()(void) const"sv); +#else // ^^^ defined(__clang__) / !defined(__clang__) vvv assert( string_view{x2.function_name()}.starts_with("struct std::source_location __thiscall lambda_test::(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(); 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(void)"sv); -#endif // TRANSITION, DevCom-10199227 and LLVM-58951 +#endif // ^^^ detailed non-Clang ^^^ assert(string_view{x1.file_name()} == string_view{x2.file_name()}); } From 444c40d7485a1c63485985bab0838a611f42acbd Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Thu, 28 Sep 2023 16:16:50 -0700 Subject: [PATCH 3/4] Simplify x86/non-x86, add comments. --- stl/inc/source_location | 4 +- .../include/test_header_units_and_modules.hpp | 4 +- .../tests/P1208R6_source_location/header.h | 4 +- .../tests/P1208R6_source_location/test.cpp | 76 +++++++++---------- 4 files changed, 42 insertions(+), 46 deletions(-) diff --git a/stl/inc/source_location b/stl/inc/source_location index 8829dd9306..31d5fb34cb 100644 --- a/stl/inc/source_location +++ b/stl/inc/source_location @@ -36,9 +36,9 @@ _EXPORT_STD struct source_location { const uint_least32_t _Column_ = __builtin_COLUMN(), const char* const _File_ = __builtin_FILE(), #if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION const char* const _Function_ = __builtin_FUNCSIG() -#else +#else // ^^^ detailed / basic vvv const char* const _Function_ = __builtin_FUNCTION() -#endif +#endif // ^^^ basic ^^^ ) noexcept { source_location _Result{}; _Result._Line = _Line_; diff --git a/tests/std/include/test_header_units_and_modules.hpp b/tests/std/include/test_header_units_and_modules.hpp index d05807b52a..cdb5ce1446 100644 --- a/tests/std/include/test_header_units_and_modules.hpp +++ b/tests/std/include/test_header_units_and_modules.hpp @@ -690,9 +690,9 @@ constexpr bool impl_test_source_location() { #if TEST_DETAILED_FUNCTION_NAME assert(sl.function_name() == "bool __cdecl impl_test_source_location(void)"sv); -#else +#else // ^^^ detailed / basic vvv assert(sl.function_name() == "impl_test_source_location"sv); -#endif +#endif // ^^^ basic ^^^ assert(string_view{sl.file_name()}.ends_with("test_header_units_and_modules.hpp"sv)); return true; diff --git a/tests/std/tests/P1208R6_source_location/header.h b/tests/std/tests/P1208R6_source_location/header.h index 7dff0cbc17..3369da4d63 100644 --- a/tests/std/tests/P1208R6_source_location/header.h +++ b/tests/std/tests/P1208R6_source_location/header.h @@ -19,8 +19,8 @@ constexpr void header_test() { #endif // ^^^ C1XX ^^^ #if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION assert(x.function_name() == "void __cdecl header_test(void)"sv); -#else +#else // ^^^ detailed / basic vvv assert(x.function_name() == "header_test"sv); -#endif +#endif // ^^^ basic ^^^ assert(string_view{x.file_name()}.ends_with("header.h"sv)); } diff --git a/tests/std/tests/P1208R6_source_location/test.cpp b/tests/std/tests/P1208R6_source_location/test.cpp index b55bd00996..a241136e46 100644 --- a/tests/std/tests/P1208R6_source_location/test.cpp +++ b/tests/std/tests/P1208R6_source_location/test.cpp @@ -5,10 +5,17 @@ #include #include #include +#include #include #include using namespace std; +#ifdef _M_IX86 +#define THISCALL_OR_CDECL_STR "__thiscall"s +#else +#define THISCALL_OR_CDECL_STR "__cdecl"s +#endif + static_assert(is_nothrow_default_constructible_v); static_assert(is_nothrow_move_constructible_v); static_assert(is_nothrow_move_assignable_v); @@ -63,9 +70,9 @@ constexpr void local_test() { #endif // ^^^ C1XX ^^^ #if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION assert(x.function_name() == "void __cdecl local_test(void)"sv); -#else +#else // ^^^ detailed / basic vvv assert(x.function_name() == "local_test"sv); -#endif +#endif // ^^^ basic ^^^ assert(string_view{x.file_name()}.ends_with(test_cpp)); } @@ -75,9 +82,9 @@ constexpr void argument_test( assert(x.column() == column); #if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION assert(x.function_name() == "bool __cdecl test(void)"sv); -#else +#else // ^^^ detailed / basic vvv assert(x.function_name() == "test"sv); -#endif +#endif // ^^^ basic ^^^ assert(string_view{x.file_name()}.ends_with(test_cpp)); } @@ -98,9 +105,9 @@ constexpr void sloc_constructor_test() { { assert(x.loc.function_name() == "void __cdecl sloc_constructor_test(void)"sv); } -#else +#else // ^^^ detailed / basic vvv assert(x.loc.function_name() == "sloc_constructor_test"sv); -#endif +#endif // ^^^ basic ^^^ assert(string_view{x.loc.file_name()}.ends_with(test_cpp)); } @@ -114,13 +121,11 @@ constexpr void different_constructor_test() { #else // ^^^ EDG / C1XX vvv assert(x.loc.column() == 5); #endif // ^^^ C1XX ^^^ -#if !_USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION +#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION + assert(x.loc.function_name() == THISCALL_OR_CDECL_STR + " s::s(int)"); +#else // ^^^ detailed / basic vvv assert(x.loc.function_name() == "s"sv); -#elif defined(_M_IX86) // ^^^ basic / detailed x86 vvv - assert(x.loc.function_name() == "__thiscall s::s(int)"sv); -#else // ^^^ detailed x86 / detailed non-x86 vvv - assert(x.loc.function_name() == "__cdecl s::s(int)"sv); -#endif // ^^^ detailed non-x86 ^^^ +#endif // ^^^ basic ^^^ assert(string_view{x.loc.file_name()}.ends_with(test_cpp)); } @@ -141,9 +146,9 @@ constexpr void sub_member_test() { { assert(s.x.loc.function_name() == "void __cdecl sub_member_test(void)"sv); } -#else +#else // ^^^ detailed / basic vvv assert(s.x.loc.function_name() == "sub_member_test"sv); -#endif +#endif // ^^^ basic ^^^ assert(string_view{s.x.loc.file_name()}.ends_with(test_cpp)); const s2 s_i{1}; @@ -155,13 +160,11 @@ constexpr void sub_member_test() { #else // ^^^ EDG / C1XX vvv assert(s_i.x.loc.column() == 5); #endif // ^^^ C1XX ^^^ -#if !_USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION +#if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION + assert(s_i.x.loc.function_name() == THISCALL_OR_CDECL_STR + " s2::s2(int)"); +#else // ^^^ detailed / basic vvv assert(s_i.x.loc.function_name() == "s2"sv); -#elif defined(_M_IX86) // ^^^ basic / detailed x86 vvv - assert(s_i.x.loc.function_name() == "__thiscall s2::s2(int)"sv); -#else // ^^^ detailed x86 / detailed non-x86 vvv - assert(s_i.x.loc.function_name() == "__cdecl s2::s2(int)"sv); -#endif // ^^^ detailed non-x86 ^^^ +#endif // ^^^ basic ^^^ assert(string_view{s_i.x.loc.file_name()}.ends_with(test_cpp)); } @@ -182,27 +185,20 @@ constexpr void lambda_test() { assert(x1.column() == 52); assert(x2.column() == 50); #endif // ^^^ C1XX ^^^ -#if !_USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION - assert(x1.function_name() == "lambda_test"sv); - assert(x2.function_name() == "operator()"sv); -#elif defined(_M_IX86) // ^^^ basic / detailed x86 vvv - assert(x1.function_name() == "void __cdecl lambda_test(void)"sv); -#ifdef __clang__ - assert(x2.function_name() == "auto __thiscall lambda_test()::(anonymous class)::operator()(void) const"sv); -#else // ^^^ defined(__clang__) / !defined(__clang__) vvv - assert( - string_view{x2.function_name()}.starts_with("struct std::source_location __thiscall lambda_test:: Date: Thu, 28 Sep 2023 17:30:56 -0700 Subject: [PATCH 4/4] Rely on string literal concat. --- tests/std/tests/P1208R6_source_location/test.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/std/tests/P1208R6_source_location/test.cpp b/tests/std/tests/P1208R6_source_location/test.cpp index a241136e46..18b8f26f57 100644 --- a/tests/std/tests/P1208R6_source_location/test.cpp +++ b/tests/std/tests/P1208R6_source_location/test.cpp @@ -5,15 +5,14 @@ #include #include #include -#include #include #include using namespace std; #ifdef _M_IX86 -#define THISCALL_OR_CDECL_STR "__thiscall"s +#define THISCALL_OR_CDECL "__thiscall" #else -#define THISCALL_OR_CDECL_STR "__cdecl"s +#define THISCALL_OR_CDECL "__cdecl" #endif static_assert(is_nothrow_default_constructible_v); @@ -122,7 +121,7 @@ constexpr void different_constructor_test() { assert(x.loc.column() == 5); #endif // ^^^ C1XX ^^^ #if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION - assert(x.loc.function_name() == THISCALL_OR_CDECL_STR + " s::s(int)"); + assert(x.loc.function_name() == THISCALL_OR_CDECL " s::s(int)"sv); #else // ^^^ detailed / basic vvv assert(x.loc.function_name() == "s"sv); #endif // ^^^ basic ^^^ @@ -161,7 +160,7 @@ constexpr void sub_member_test() { assert(s_i.x.loc.column() == 5); #endif // ^^^ C1XX ^^^ #if _USE_DETAILED_FUNCTION_NAME_IN_SOURCE_LOCATION - assert(s_i.x.loc.function_name() == THISCALL_OR_CDECL_STR + " s2::s2(int)"); + 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); #endif // ^^^ basic ^^^ @@ -194,9 +193,9 @@ constexpr void lambda_test() { #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_STR + " lambda_test()::(anonymous class)::operator()(void) const"); + 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_STR + " lambda_test::