Skip to content

Commit

Permalink
Improved diagnostics
Browse files Browse the repository at this point in the history
  • Loading branch information
zajo committed Sep 2, 2024
1 parent 907bd6c commit 42b85ca
Show file tree
Hide file tree
Showing 16 changed files with 558 additions and 447 deletions.
4 changes: 2 additions & 2 deletions include/boost/leaf/common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct BOOST_LEAF_SYMBOL_VISIBLE e_errno
template <class CharT, class Traits>
friend std::ostream & operator<<(std::basic_ostream<CharT, Traits> & os, e_errno const & err)
{
return os << parse_name<e_errno>() << ": " << err.value << ", \"" << std::strerror(err.value) << '"';
return os << err.value << ", \"" << std::strerror(err.value) << '"';
}
};

Expand Down Expand Up @@ -102,7 +102,7 @@ namespace windows
*--z = 0;
if( z[-1] == '\r' )
*--z = 0;
return os << parse_name<e_LastError>() << ": " << err.value << ", \"" << (LPCSTR)mb.p << '"';
return os << err.value << ", \"" << (LPCSTR)mb.p << '"';
}
return os;
}
Expand Down
49 changes: 25 additions & 24 deletions include/boost/leaf/context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,50 +136,56 @@ namespace leaf_detail

namespace leaf_detail
{
template <int I, class Tuple>
template <int I, class Tup>
struct tuple_for_each
{
BOOST_LEAF_CONSTEXPR static void activate( Tuple & tup ) noexcept
BOOST_LEAF_CONSTEXPR static void activate( Tup & tup ) noexcept
{
static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
tuple_for_each<I-1,Tuple>::activate(tup);
tuple_for_each<I-1,Tup>::activate(tup);
std::get<I-1>(tup).activate();
}

BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & tup ) noexcept
BOOST_LEAF_CONSTEXPR static void deactivate( Tup & tup ) noexcept
{
static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
std::get<I-1>(tup).deactivate();
tuple_for_each<I-1,Tuple>::deactivate(tup);
tuple_for_each<I-1,Tup>::deactivate(tup);
}

BOOST_LEAF_CONSTEXPR static void unload( Tuple & tup, int err_id ) noexcept
BOOST_LEAF_CONSTEXPR static void unload( Tup & tup, int err_id ) noexcept
{
static_assert(!std::is_same<error_info, typename std::decay<decltype(std::get<I-1>(tup))>::type>::value, "Bug in LEAF: context type deduction");
BOOST_LEAF_ASSERT(err_id != 0);
auto & sl = std::get<I-1>(tup);
sl.unload(err_id);
tuple_for_each<I-1,Tuple>::unload(tup, err_id);
tuple_for_each<I-1,Tup>::unload(tup, err_id);
}

template <class CharT, class Traits>
static void print( std::basic_ostream<CharT, Traits> & os, void const * tup, int err_id_to_print )
static void print(std::basic_ostream<CharT, Traits> & os, void const * tup, error_id to_print, char const * & prefix, char const * delimiter)
{
BOOST_LEAF_ASSERT(tup != nullptr);
tuple_for_each<I-1,Tuple>::print(os, tup, err_id_to_print);
std::get<I-1>(*static_cast<Tuple const *>(tup)).print(os, err_id_to_print);
tuple_for_each<I-1,Tup>::print(os, tup, to_print, prefix, delimiter);
std::get<I-1>(*static_cast<Tup const *>(tup)).print(os, to_print, prefix, delimiter);
}
};

template <class Tuple>
struct tuple_for_each<0, Tuple>
template <class Tup>
struct tuple_for_each<0, Tup>
{
BOOST_LEAF_CONSTEXPR static void activate( Tuple & ) noexcept { }
BOOST_LEAF_CONSTEXPR static void deactivate( Tuple & ) noexcept { }
BOOST_LEAF_CONSTEXPR static void unload( Tuple &, int ) noexcept { }
BOOST_LEAF_CONSTEXPR static void activate( Tup & ) noexcept { }
BOOST_LEAF_CONSTEXPR static void deactivate( Tup & ) noexcept { }
BOOST_LEAF_CONSTEXPR static void unload( Tup &, int ) noexcept { }
template <class CharT, class Traits>
BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream<CharT, Traits> &, void const *, int ) { }
BOOST_LEAF_CONSTEXPR static void print(std::basic_ostream<CharT, Traits> &, void const *, error_id, char const * &, char const *) { }
};

template <class Tup, class CharT, class Traits>
BOOST_LEAF_CONSTEXPR void print_tuple_contents(std::basic_ostream<CharT, Traits> & os, void const * tup, error_id to_print, char const * & prefix, char const * delimiter)
{
tuple_for_each<std::tuple_size<Tup>::value, Tup>::print(os, tup, to_print, prefix, delimiter);
}
}

////////////////////////////////////////////
Expand Down Expand Up @@ -297,17 +303,12 @@ class context
return is_active_;
}

template <class CharT, class Traits>
void print( std::basic_ostream<CharT, Traits> & os ) const
{
leaf_detail::tuple_for_each<std::tuple_size<Tup>::value,Tup>::print(os, &tup_, 0);
}

template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, context const & ctx )
{
ctx.print(os);
return os;
char const * prefix = "Contents:";
leaf_detail::print_tuple_contents<Tup>(os, &ctx.tup_, error_id(), prefix, "\n\t");
return os << '\n';
}

template <class R, class... H>
Expand Down
17 changes: 9 additions & 8 deletions include/boost/leaf/detail/capture_list.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,16 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#include <boost/leaf/config.hpp>
#include <boost/leaf/detail/print.hpp>

#if BOOST_LEAF_CFG_CAPTURE

#include <iosfwd>

namespace boost { namespace leaf {

class error_id;

namespace leaf_detail
{
struct BOOST_LEAF_SYMBOL_VISIBLE tls_tag_id_factory_current_id;
Expand All @@ -31,7 +34,7 @@ namespace leaf_detail

virtual void unload( int err_id ) = 0;
#if BOOST_LEAF_CFG_DIAGNOSTICS
virtual void print( std::ostream &, int err_id_to_print ) const = 0;
virtual void print(std::ostream &, error_id const & to_print, char const * & prefix, char const * delimiter) const = 0;
#endif

protected:
Expand Down Expand Up @@ -94,23 +97,21 @@ namespace leaf_detail
}

template <class CharT, class Traits>
void print(std::basic_ostream<CharT, Traits> & os, int const err_id_to_print, char const * title = nullptr) const
void print(std::basic_ostream<CharT, Traits> & os, error_id const & to_print, char const * & prefix, char const * delimiter) const
{
#if BOOST_LEAF_CFG_DIAGNOSTICS
if( first_ )
{
if( title )
os << title;
for_each(
[&os, err_id_to_print]( node const & n )
[&os, &to_print, &prefix, delimiter]( node const & n )
{
n.print(os, err_id_to_print);
n.print(os, to_print, prefix, delimiter);
} );
}
#else
(void) os;
(void) title;
(void) err_id_to_print;
(void) prefix;
(void) to_print;
#endif
}
};
Expand Down
79 changes: 42 additions & 37 deletions include/boost/leaf/detail/print.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,85 +47,90 @@ namespace leaf_detail

////////////////////////////////////////

template <class T, class PrintableInfo, class CharT, class Traits>
bool print_impl(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, char const * mid, PrintableInfo const & x)
{
static_assert(show_in_diagnostics<T>::value, "show_in_diagnostics violation");
BOOST_LEAF_ASSERT(delimiter);
if( prefix )
{
os << prefix;
prefix = nullptr;
}
os << delimiter << parse_name<T>();
if( mid )
os << mid << x;
return true;
}

////////////////////////////////////////

template <
class Wrapper,
bool ShowInDiagnostics = show_in_diagnostics<Wrapper>::value,
bool WrapperPrintable = is_printable<Wrapper>::value,
bool ValuePrintable = has_printable_member_value<Wrapper>::value,
bool IsException = std::is_base_of<std::exception,Wrapper>::value,
bool IsEnum = std::is_enum<Wrapper>::value>
struct diagnostic;

template <class Wrapper, bool ValuePrintable, bool IsException, bool IsEnum>
struct diagnostic<Wrapper, true, ValuePrintable, IsException, IsEnum>
template <class Wrapper, bool WrapperPrintable, bool ValuePrintable, bool IsException, bool IsEnum>
struct diagnostic<Wrapper, false, WrapperPrintable, ValuePrintable, IsException, IsEnum>
{
static constexpr bool is_invisible = false;

template <class CharT, class Traits>
static void print( std::basic_ostream<CharT, Traits> & os, Wrapper const & x )
static bool print(std::basic_ostream<CharT, Traits> &, char const * &, char const *, Wrapper const & x) noexcept
{
os << x;
return false;
}
};

template <class Wrapper, bool IsException, bool IsEnum>
struct diagnostic<Wrapper, false, true, IsException, IsEnum>
template <class Wrapper, bool ValuePrintable, bool IsEnum>
struct diagnostic<Wrapper, true, true, ValuePrintable, false, IsEnum>
{
static constexpr bool is_invisible = false;

template <class CharT, class Traits>
static void print( std::basic_ostream<CharT, Traits> & os, Wrapper const & x )
static bool print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, Wrapper const & x)
{
os << parse_name<Wrapper>() << ": " << x.value;
return print_impl<Wrapper>(os, prefix, delimiter, ": ", x);
}
};

template <class Wrapper, bool IsEnum>
struct diagnostic<Wrapper, false, false, true, IsEnum>
template <class Wrapper>
struct diagnostic<Wrapper, true, false, true, false, false>
{
static constexpr bool is_invisible = false;

template <class CharT, class Traits>
static void print( std::basic_ostream<CharT, Traits> & os, Wrapper const & ex )
static bool print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, Wrapper const & x)
{
os << parse_name<Wrapper>() << ": std::exception::what(): " << ex.what();
return print_impl<Wrapper>(os, prefix, delimiter, ": ", x.value);
}
};

template <class Wrapper>
struct diagnostic<Wrapper, false, false, false, false>
template <class Exception, bool WrapperPrintable, bool ValuePrintable>
struct diagnostic<Exception, true, WrapperPrintable, ValuePrintable, true, false>
{
static constexpr bool is_invisible = false;

template <class CharT, class Traits>
static void print( std::basic_ostream<CharT, Traits> & os, Wrapper const & )
static bool print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, Exception const & ex)
{
os << parse_name<Wrapper>() <<
(show_in_diagnostics<Wrapper>::value ?
": {not printable}" :
": {hidden by show_in_diagnostics}");
return print_impl<Exception>(os, prefix, delimiter, ", std::exception::what(): ", static_cast<std::exception const &>(ex).what());
}
};

template <class Wrapper>
struct diagnostic<Wrapper, false, false, false, true>
struct diagnostic<Wrapper, true, false, false, false, false>
{
static constexpr bool is_invisible = false;

template <class CharT, class Traits>
static void print( std::basic_ostream<CharT, Traits> & os, Wrapper const & w )
static bool print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, Wrapper const &)
{
os << parse_name<Wrapper>() << ": " << static_cast<typename std::underlying_type<Wrapper>::type>(w);
return print_impl<Wrapper>(os, prefix, delimiter, nullptr, 0);
}
};

template <>
struct diagnostic<std::exception_ptr, false, false, false>
template <class Enum>
struct diagnostic<Enum, true, false, false, false, true>
{
static constexpr bool is_invisible = true;

template <class CharT, class Traits>
BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream<CharT, Traits> &, std::exception_ptr const & )
static bool print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter, Enum const & enum_)
{
return print_impl<Enum>(os, prefix, delimiter, ": ", static_cast<typename std::underlying_type<Enum>::type>(enum_));
}
};
}
Expand Down
28 changes: 19 additions & 9 deletions include/boost/leaf/diagnostics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace boost { namespace leaf {
class diagnostic_info: public error_info
{
void const * tup_;
void (*print_context_content_)( std::ostream &, void const * tup, int err_id_to_print );
void (*print_tuple_contents_)(std::ostream &, void const * tup, error_id to_print, char const * & prefix, char const * delimiter);

protected:

Expand All @@ -27,16 +27,23 @@ class diagnostic_info: public error_info
BOOST_LEAF_CONSTEXPR diagnostic_info( error_info const & ei, Tup const & tup ) noexcept:
error_info(ei),
tup_(&tup),
print_context_content_(&leaf_detail::tuple_for_each<std::tuple_size<Tup>::value, Tup>::print)
print_tuple_contents_(&leaf_detail::print_tuple_contents<Tup>)
{
}

template <class CharT, class Traits>
void print(std::basic_ostream<CharT, Traits> & os, char const * & prefix, char const * delimiter) const
{
print_tuple_contents_(os, tup_, error(), prefix, delimiter);
}

template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
{
os << static_cast<error_info const &>(x);
x.print_context_content_(os, x.tup_, x.error().value());
return os;
static_cast<error_info const &>(x).print(os);
char const * prefix = x.exception() ? nullptr : "\nCaught:";
x.print(os, prefix, "\n\t");
return os << '\n';
}
};

Expand Down Expand Up @@ -78,7 +85,7 @@ class diagnostic_info: public error_info
template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_info const & x )
{
return os << "diagnostic_info not available due to BOOST_LEAF_CFG_DIAGNOSTICS=0. Basic error_info follows.\n" << static_cast<error_info const &>(x);
return os << "diagnostic_info not available due to BOOST_LEAF_CFG_DIAGNOSTICS=0.\n" << static_cast<error_info const &>(x);
}
};

Expand Down Expand Up @@ -129,10 +136,13 @@ class diagnostic_details: public diagnostic_info
template <class CharT, class Traits>
friend std::ostream & operator<<( std::basic_ostream<CharT, Traits> & os, diagnostic_details const & x )
{
os << static_cast<diagnostic_info const &>(x);
static_cast<error_info const &>(x).print(os);
char const * prefix = x.exception() ? nullptr : "\nCaught:";
x.print(os, prefix, "\n\t");
prefix = "\nDiagnostic details:";
if( x.da_ )
x.da_->print(os, x.error().value());
return os;
x.da_->print(os, x.error(), prefix, "\n\t");
return os << '\n';
}
};

Expand Down
Loading

0 comments on commit 42b85ca

Please sign in to comment.