Skip to content

Commit

Permalink
static_assert in parse_name
Browse files Browse the repository at this point in the history
  • Loading branch information
zajo committed Sep 7, 2024
1 parent 2c12197 commit 1640fd2
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 50 deletions.
100 changes: 56 additions & 44 deletions include/boost/leaf/detail/demangle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,66 +119,78 @@ namespace leaf_detail
len(len)
{
}
template <int S>
parsed_name(char const(&name)[S]) noexcept:
name(name),
len(S-1)
{
}
bool parse_success() const noexcept
{
return name[len] != 0;
}
template <class CharT, class Traits>
friend std::ostream & operator<<(std::basic_ostream<CharT, Traits> & os, parsed_name const & pn)
{
return os.write(pn.name, pn.len);
}
};

// Workaround - we only use this function if parse_name (below) fails to parse __PRETTY_FUNCTION__ / __FUNCSIG__.
// In this case parse_name should be fixed to support the newly encountered (note, parsing is done at compile-time).
template <class Name>
parsed_name please_update_parse_name()
{
return parsed_name(BOOST_LEAF_PRETTY_FUNCTION);
}

template <class Name>
parsed_name parse_name()
{
// Workaround for older gcc compilers where __PRETTY_FUNCTION__ is not constexpr.
// Instead of evaluating constexpr int x = f(__PRETTY_FUNCTION__), which fails,
// we evaluate int const x = f(__PRETTY_FUNCTION__). Then we enforce compile-time
// execution by evaluating sizeof(char[1 + x]) -1.
#define BOOST_LEAF_PARSE_PF(prefix, suffix) \
{ \
if( int const s = leaf_detail::check_suffix(BOOST_LEAF_PRETTY_FUNCTION, suffix) ) \
if( int const p = leaf_detail::check_prefix(BOOST_LEAF_PRETTY_FUNCTION, prefix) ) \
return parsed_name(BOOST_LEAF_PRETTY_FUNCTION + sizeof(char[1 + p]) - 1, sizeof(char[1 + s - p]) - 1); \
}
#define BOOST_LEAF_CHECK_P(P) (sizeof(char[1 + leaf_detail::check_prefix(BOOST_LEAF_PRETTY_FUNCTION, P)]) - 1)
// clang style:
BOOST_LEAF_PARSE_PF( "parsed_name boost::leaf::leaf_detail::parse_name() [Name = ", "]");
int const p01 = BOOST_LEAF_CHECK_P("parsed_name boost::leaf::leaf_detail::parse_name() [Name = ");
// old clang style:
BOOST_LEAF_PARSE_PF( "boost::leaf::leaf_detail::parsed_name boost::leaf::leaf_detail::parse_name() [Name = ", "]");
// gcc style:
BOOST_LEAF_PARSE_PF( "boost::leaf::leaf_detail::parsed_name boost::leaf::leaf_detail::parse_name() [with Name = ", "]");
// msvc style, __cdecl, struct/class/enum:
BOOST_LEAF_PARSE_PF( "struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<struct ", ">(void)");
BOOST_LEAF_PARSE_PF( "struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<class ", ">(void)");
BOOST_LEAF_PARSE_PF( "struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<enum ", ">(void)");
// msvc style, __stdcall, struct/class/enum:
BOOST_LEAF_PARSE_PF( "struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<struct ", ">(void)");
BOOST_LEAF_PARSE_PF( "struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<class ", ">(void)");
BOOST_LEAF_PARSE_PF( "struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<enum ", ">(void)");
// msvc style, __fastcall, struct/class/enum:
BOOST_LEAF_PARSE_PF( "struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<struct ", ">(void)");
BOOST_LEAF_PARSE_PF( "struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<class ", ">(void)");
BOOST_LEAF_PARSE_PF( "struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<enum ", ">(void)");
#undef BOOST_LEAF_PARSE_PF

// Unrecognized __PRETTY_FUNCTION__ / __FUNCSIG__ format, return as-is. Note, parsing is done at compile-time.
return please_update_parse_name<Name>();
int const p02 = BOOST_LEAF_CHECK_P("boost::leaf::leaf_detail::parsed_name boost::leaf::leaf_detail::parse_name() [Name = ");
; // gcc style:
int const p03 = BOOST_LEAF_CHECK_P("boost::leaf::leaf_detail::parsed_name boost::leaf::leaf_detail::parse_name() [with Name = ");
// msvc, struct, __cdecs/__stdcall/__fastcall
int const p04 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<struct ");
int const p05 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<struct ");
int const p06 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<struct ");
// msvc, class, __cdecs/__stdcall/__fastcall
int const p07 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<class ");
int const p08 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<class ");
int const p09 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<class ");
// msvc, enum, __cdecs/__stdcall/__fastcall
int const p10 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<enum ");
int const p11 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<enum ");
int const p12 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<enum ");
// msvc, built-in type, __cdecs/__stdcall/__fastcall
int const p13 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<");
int const p14 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<");
int const p15 = BOOST_LEAF_CHECK_P("struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<");
#undef BOOST_LEAF_CHECK_P
static_assert(p01||p02||p03||p04||p05||p06||p07||p08||p09||p10||p11||p12||p13||p14||p15,
"Unsupported type name parsing format");

#define BOOST_LEAF_CHECK_S(S) (sizeof(char[1 + leaf_detail::check_suffix(BOOST_LEAF_PRETTY_FUNCTION, S)]) - 1)
// clang/gcc style
int const s01 = BOOST_LEAF_CHECK_S("]");
// msvc style
int const s02 = BOOST_LEAF_CHECK_S(">(void)");
#undef BOOST_LEAF_CHECK_S
static_assert(s01||s02,
"Unsupported type name parsing format");

if( (p01||p02||p03) && s01 )
return {
BOOST_LEAF_PRETTY_FUNCTION
+p01+p02+p03,
s01
-p01-p02-p03};

if( (p04||p05||p06||p07||p08||p09||p10||p11||p12) && s02 )
return {
BOOST_LEAF_PRETTY_FUNCTION
+p04+p05+p06+p07+p08+p09+p10+p11+p12,
s02
-p04-p05-p06-p07-p08-p09-p10-p11-p12};

if( (p13||p14||p15) && s02 )
return {
BOOST_LEAF_PRETTY_FUNCTION
+p13+p14+p15,
s02
-p13-p14-p15};

return {nullptr, 0};
}
}

Expand Down
36 changes: 31 additions & 5 deletions test/diagnostics_test1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ int main()
[]() -> leaf::result<void>
{
return BOOST_LEAF_NEW_ERROR(
42,
printable_info_printable_value(),
printable_info_non_printable_value(),
non_printable_info_printable_value(),
Expand All @@ -172,6 +173,7 @@ int main()
leaf::e_errno{ENOENT} );
},
[](
int,
printable_info_printable_value,
printable_info_non_printable_value,
non_printable_info_printable_value,
Expand Down Expand Up @@ -204,6 +206,7 @@ int main()
[]() -> leaf::result<void>
{
return BOOST_LEAF_NEW_ERROR(
42,
printable_info_printable_value(),
printable_info_non_printable_value(),
non_printable_info_printable_value(),
Expand All @@ -214,6 +217,7 @@ int main()
leaf::e_errno{ENOENT} );
},
[](
int,
leaf::e_source_location,
printable_info_printable_value,
printable_info_non_printable_value,
Expand Down Expand Up @@ -247,6 +251,7 @@ int main()
[]() -> leaf::result<void>
{
return BOOST_LEAF_NEW_ERROR(
42,
printable_info_printable_value(),
printable_info_non_printable_value(),
non_printable_info_printable_value(),
Expand All @@ -257,6 +262,7 @@ int main()
leaf::e_errno{ENOENT} );
},
[](
int,
leaf::e_source_location,
printable_info_printable_value,
printable_info_non_printable_value,
Expand All @@ -277,7 +283,8 @@ int main()
BOOST_TEST(cmp(s,
"Error with serial #3 reported at <removed variance>"
"\nCaught:"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "int: 42"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_non_printable_value: *** printable_info non_printable_value ***"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_non_printable_value"
Expand All @@ -303,6 +310,7 @@ int main()
[]() -> leaf::result<void>
{
return BOOST_LEAF_NEW_ERROR(
42,
printable_info_printable_value(),
printable_info_non_printable_value(),
non_printable_info_printable_value(),
Expand All @@ -315,6 +323,7 @@ int main()
leaf::e_errno{ENOENT} );
},
[](
int,
leaf::e_source_location,
printable_info_printable_value,
printable_info_non_printable_value,
Expand All @@ -336,7 +345,8 @@ int main()
BOOST_TEST(cmp(s,
"Error with serial #4 reported at <removed variance>"
"\nCaught:"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "int: 42"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_non_printable_value: *** printable_info non_printable_value ***"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_non_printable_value"
Expand All @@ -351,7 +361,8 @@ int main()
BOOST_TEST(cmp(s,
"Error with serial #4 reported at <removed variance>"
"\nCaught:"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "int: 42"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_non_printable_value: *** printable_info non_printable_value ***"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_non_printable_value"
Expand All @@ -378,6 +389,7 @@ int main()
[]() -> leaf::result<void>
{
return BOOST_LEAF_NEW_ERROR(
42,
printable_info_printable_value(),
printable_info_non_printable_value(),
non_printable_info_printable_value(),
Expand All @@ -401,7 +413,8 @@ int main()
BOOST_TEST(cmp(s,
"Error with serial #5 reported at <removed variance>"
"\nDiagnostic details:"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "int: 42"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_non_printable_value: *** printable_info non_printable_value ***"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_non_printable_value"
Expand Down Expand Up @@ -439,6 +452,7 @@ int main()
[]
{
BOOST_LEAF_THROW_EXCEPTION( my_exception(),
42,
printable_info_printable_value(),
printable_info_non_printable_value(),
non_printable_info_printable_value(),
Expand All @@ -449,6 +463,7 @@ int main()
leaf::e_errno{ENOENT} );
},
[](
int,
printable_info_printable_value,
printable_info_non_printable_value,
non_printable_info_printable_value,
Expand Down Expand Up @@ -478,6 +493,7 @@ int main()
[]
{
BOOST_LEAF_THROW_EXCEPTION( my_exception(),
42,
printable_info_printable_value(),
printable_info_non_printable_value(),
non_printable_info_printable_value(),
Expand All @@ -488,6 +504,7 @@ int main()
leaf::e_errno{ENOENT} );
},
[](
int,
leaf::e_source_location,
printable_info_printable_value,
printable_info_non_printable_value,
Expand Down Expand Up @@ -518,6 +535,7 @@ int main()
[]
{
BOOST_LEAF_THROW_EXCEPTION( my_exception(),
42,
printable_info_printable_value(),
printable_info_non_printable_value(),
non_printable_info_printable_value(),
Expand All @@ -528,6 +546,7 @@ int main()
leaf::e_errno{ENOENT} );
},
[](
int,
leaf::e_source_location,
printable_info_printable_value,
printable_info_non_printable_value,
Expand All @@ -549,6 +568,7 @@ int main()
"Error with serial #8 reported at <removed variance>"
"\nCaught:"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "<removed variance>: \"my_exception what\""
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "int: 42"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_non_printable_value: *** printable_info non_printable_value ***"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_printable_value: printed printable_value"
Expand All @@ -573,6 +593,7 @@ int main()
[]
{
BOOST_LEAF_THROW_EXCEPTION( my_exception(),
42,
printable_info_printable_value(),
printable_info_non_printable_value(),
non_printable_info_printable_value(),
Expand All @@ -585,6 +606,7 @@ int main()
leaf::e_errno{ENOENT} );
},
[](
int,
leaf::e_source_location,
printable_info_printable_value,
printable_info_non_printable_value,
Expand All @@ -607,6 +629,7 @@ int main()
"Error with serial #9 reported at <removed variance>"
"\nCaught:"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "<removed variance>: \"my_exception what\""
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "int: 42"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_non_printable_value: *** printable_info non_printable_value ***"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_printable_value: printed printable_value"
Expand All @@ -623,6 +646,7 @@ int main()
"Error with serial #9 reported at <removed variance>"
"\nCaught:"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "<removed variance>: \"my_exception what\""
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "int: 42"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_non_printable_value: *** printable_info non_printable_value ***"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_printable_value: printed printable_value"
Expand All @@ -648,6 +672,7 @@ int main()
[]
{
BOOST_LEAF_THROW_EXCEPTION( my_exception(),
42,
printable_info_printable_value(),
printable_info_non_printable_value(),
non_printable_info_printable_value(),
Expand All @@ -673,7 +698,8 @@ int main()
"\nCaught:"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "<removed variance>: \"my_exception what\""
"\nDiagnostic details:"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_FIRST_DELIMITER "int: 42"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "printable_info_non_printable_value: *** printable_info non_printable_value ***"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_printable_value: printed printable_value"
BOOST_LEAF_CFG_DIAGNOSTICS_DELIMITER "non_printable_info_non_printable_value"
Expand Down
1 change: 0 additions & 1 deletion test/parse_name_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ namespace
void test_name(std::string const & correct)
{
auto pn = leaf::leaf_detail::parse_name<Name>();
BOOST_TEST(pn.parse_success());
BOOST_TEST_EQ(std::string(pn.name, pn.len), correct);
}
}
Expand Down

0 comments on commit 1640fd2

Please sign in to comment.