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 8, 2024
1 parent 2c12197 commit e941dd8
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 55 deletions.
107 changes: 59 additions & 48 deletions include/boost/leaf/detail/demangle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,66 +119,77 @@ 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); \
}
// C++11 compile-time parsing of __PRETTY_FUNCTION__/__FUNCSIG__. The sizeof hacks are a
// workaround for older GCC versions, where __PRETTY_FUNCTION__ is not constexpr, which triggers
// compile errors when used in constexpr expressinos, yet evaluating a sizeof exrpession works.

// We don't try to recognize the compiler based on compiler-specific macros. Any compiler/version
// is supported as long as it uses one of the formats we recognize.

// Unrecognized __PRETTY_FUNCTION__/__FUNCSIG__ formats will result in compiler diagnostics.
// In that case, please file an issue on https://github.com/boostorg/leaf.

#define BOOST_LEAF_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_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_P("boost::leaf::leaf_detail::parsed_name boost::leaf::leaf_detail::parse_name() [Name = ");
; // gcc style:
int const p03 = BOOST_LEAF_P("boost::leaf::leaf_detail::parsed_name boost::leaf::leaf_detail::parse_name() [with Name = ");
// msvc style, struct
int const p04 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<struct ");
int const p05 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<struct ");
int const p06 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<struct ");
// msvc style, class
int const p07 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<class ");
int const p08 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<class ");
int const p09 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<class ");
// msvc style, enum
int const p10 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<enum ");
int const p11 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<enum ");
int const p12 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<enum ");
// msvc style, built-in type
int const p13 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __cdecl boost::leaf::leaf_detail::parse_name<");
int const p14 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __stdcall boost::leaf::leaf_detail::parse_name<");
int const p15 = BOOST_LEAF_P("struct boost::leaf::leaf_detail::parsed_name __fastcall boost::leaf::leaf_detail::parse_name<");
#undef BOOST_LEAF_P

#define BOOST_LEAF_S(S) (sizeof(char[1 + leaf_detail::check_suffix(BOOST_LEAF_PRETTY_FUNCTION, S)]) - 1)
// clang/gcc style
int const s01 = BOOST_LEAF_S("]");
// msvc style
int const s02 = BOOST_LEAF_S(">(void)");
#undef BOOST_LEAF_S

char unrecognized_pretty_function_format_please_file_github_issue[
(!!s01 * (1 == (!!p01 + !!p02 + !!p03)))
+
(!!s02 * (1 == (!!p04 + !!p05 + !!p06 + !!p07 + !!p08 + !!p09 + !!p10 + !!p11 + !!p12)))
+
(!!s02 * (1 == (!!p13 + !!p14 + !!p15)))
];
static_assert(sizeof(unrecognized_pretty_function_format_please_file_github_issue) == 1,
"Unrecognized __PRETTY_FUNCTION__/__FUNCSIG__ format, please file an issue on https://github.com/boostorg/leaf");

if( int const p = sizeof(char[1 + !!s01 * (p01 + p02 + p03)]) - 1 )
return { BOOST_LEAF_PRETTY_FUNCTION + p, s01 - p };
else if( int const p = sizeof(char[1 + !!s02 * (p04 + p05 + p06 + p07 + p08 + p09 + p10 + p11 + p12)]) - 1 )
return { BOOST_LEAF_PRETTY_FUNCTION + p, s02 - p };
else
{
int const q = sizeof(char[1 + !!s02 * (p13 + p14 + p15)]) - 1; // q is not zero, we static asserted the hell out of it
return { BOOST_LEAF_PRETTY_FUNCTION + q, s02 - q };
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion include/boost/leaf/exception.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ namespace leaf_detail

bool is_current_exception() const noexcept
{
return tls::read_uint<leaf_detail::tls_tag_id_factory_current_id>() == error_id::value();
return tls::read_uint<leaf_detail::tls_tag_id_factory_current_id>() == unsigned(error_id::value());
}

error_id get_error_id() const noexcept final override
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 e941dd8

Please sign in to comment.