debug: move panic related calls to a distinct unit
This will allow us to reduce the required headers and avoid some circular dependencies in some client libraries.
This commit is contained in:
parent
644cae506f
commit
a4d963e00b
@ -278,6 +278,8 @@ list (
|
||||
cpuid.hpp
|
||||
debug.cpp
|
||||
debug.hpp
|
||||
debug/panic.cpp
|
||||
debug/panic.hpp
|
||||
encode/number.hpp
|
||||
encode/base.cpp
|
||||
encode/base.hpp
|
||||
|
133
debug.hpp
133
debug.hpp
@ -3,12 +3,13 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2010-2017 Danny Robson <danny@nerdcruft.net>
|
||||
* Copyright 2010-2019 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "platform.hpp"
|
||||
#include "debug/panic.hpp"
|
||||
|
||||
//#include "maths.hpp" // XXX: See notes at the end of file for maths.hpp inclusion
|
||||
#include <cmath>
|
||||
@ -435,136 +436,6 @@ namespace cruft::debug {
|
||||
void breakpoint (void);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// We define an identity macro for panic so that TCL and GCC don't decide to
|
||||
// fuck us over by redefine the symbol.
|
||||
//
|
||||
// Apparently this can't be taken care of via a '-Dpanic=panic' argument,
|
||||
// because it just ignores it for reasons I can't figure out.
|
||||
#ifdef panic
|
||||
#undef panic
|
||||
#endif
|
||||
|
||||
#define panic panic
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace cruft::debug::detail {
|
||||
void
|
||||
panic [[noreturn]] (const char *msg);
|
||||
|
||||
|
||||
void not_implemented [[noreturn]] (const char *msg);
|
||||
|
||||
|
||||
void unreachable [[noreturn]] (const char *msg);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
constexpr void
|
||||
panic [[noreturn]] (const char *msg)
|
||||
{
|
||||
! msg
|
||||
? panic (msg)
|
||||
: cruft::debug::detail::panic (msg);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void
|
||||
panic [[noreturn]] (const std::string &msg)
|
||||
{
|
||||
panic (msg.c_str ());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// not_implemented/unreachable/panic must be callable from constexpr contexts.
|
||||
// but they rely on functions that aren't constexpr to perform the controlled
|
||||
// abort.
|
||||
//
|
||||
// we can work around this in the same way assert does by using a conditional
|
||||
// that hides an extern function that actually does the work. as we can't
|
||||
// utilise external state this has to be the message variable which will
|
||||
// assume isn't ever null.
|
||||
//
|
||||
// to avoid warnings about a return from a noreturn function we recurse into
|
||||
// ourself in the alternate case. this branch shouldn't ever be taken, but if
|
||||
// it is we were planning on crashing anyway...
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
constexpr void
|
||||
not_implemented [[noreturn]] (const char *msg)
|
||||
{
|
||||
! msg
|
||||
? not_implemented (msg)
|
||||
: cruft::debug::detail::not_implemented (msg);
|
||||
}
|
||||
|
||||
|
||||
constexpr void
|
||||
not_implemented [[noreturn]] (void)
|
||||
{
|
||||
not_implemented ("operation not implemented");
|
||||
}
|
||||
|
||||
|
||||
constexpr void unimplemented [[noreturn]] (void) { not_implemented (); }
|
||||
|
||||
|
||||
constexpr void unimplemented [[noreturn]] (const char *msg) { not_implemented (msg); }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
constexpr void
|
||||
unreachable [[noreturn]] (const char *msg)
|
||||
{
|
||||
! msg
|
||||
? unreachable (msg)
|
||||
: cruft::debug::detail::unreachable (msg);
|
||||
}
|
||||
|
||||
|
||||
constexpr void
|
||||
unreachable [[noreturn]] (void)
|
||||
{
|
||||
unreachable ("unreachable code isn't");
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// report a fatal error induced by an unhandled value, especially in switch
|
||||
/// statements. will almost invariably abort the application.
|
||||
namespace cruft::debug::detail {
|
||||
template <typename T>
|
||||
T
|
||||
unhandled [[noreturn]] (T &&t) noexcept
|
||||
{
|
||||
// If we've been given an enum we should handle it like its underlying
|
||||
// type so that when we end up logging it we don't accidentally
|
||||
// trigger an infinite loop of calls to `unhandled` within the
|
||||
// ostream operator. It doesn't have to be pretty, just functional.
|
||||
using base_type = std::remove_reference_t<std::decay_t<T>>;
|
||||
if constexpr (std::is_enum_v<base_type>) {
|
||||
unhandled (static_cast<std::underlying_type_t<base_type>> (t));
|
||||
} else {
|
||||
std::ostringstream os;
|
||||
os << "unhandled value: " << t << '\n';
|
||||
::panic (os.str ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
constexpr T
|
||||
unhandled [[noreturn]] (T &&t) noexcept
|
||||
{
|
||||
cruft::debug::detail::unhandled (std::forward<T> (t));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
void warn (void);
|
||||
void warn (const std::string&);
|
||||
|
1
debug/panic.cpp
Normal file
1
debug/panic.cpp
Normal file
@ -0,0 +1 @@
|
||||
#include "panic.hpp"
|
143
debug/panic.hpp
Normal file
143
debug/panic.hpp
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* Copyright 2010-2019 Danny Robson <danny@nerdcruft.net>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// We define an identity macro for panic so that TCL and GCC don't decide to
|
||||
// fuck us over by redefine the symbol.
|
||||
//
|
||||
// Apparently this can't be taken care of via a '-Dpanic=panic' argument,
|
||||
// because it just ignores it for reasons I can't figure out.
|
||||
#ifdef panic
|
||||
#undef panic
|
||||
#endif
|
||||
|
||||
#define panic panic
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
namespace cruft::debug::detail {
|
||||
void
|
||||
panic [[noreturn]] (const char *msg);
|
||||
|
||||
|
||||
void not_implemented [[noreturn]] (const char *msg);
|
||||
|
||||
|
||||
void unreachable [[noreturn]] (const char *msg);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
constexpr void
|
||||
panic [[noreturn]] (const char *msg)
|
||||
{
|
||||
! msg
|
||||
? panic (msg)
|
||||
: cruft::debug::detail::panic (msg);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
inline void
|
||||
panic [[noreturn]] (const std::string &msg)
|
||||
{
|
||||
panic (msg.c_str ());
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// not_implemented/unreachable/panic must be callable from constexpr contexts.
|
||||
// but they rely on functions that aren't constexpr to perform the controlled
|
||||
// abort.
|
||||
//
|
||||
// we can work around this in the same way assert does by using a conditional
|
||||
// that hides an extern function that actually does the work. as we can't
|
||||
// utilise external state this has to be the message variable which will
|
||||
// assume isn't ever null.
|
||||
//
|
||||
// to avoid warnings about a return from a noreturn function we recurse into
|
||||
// ourself in the alternate case. this branch shouldn't ever be taken, but if
|
||||
// it is we were planning on crashing anyway...
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
constexpr void
|
||||
not_implemented [[noreturn]] (const char *msg)
|
||||
{
|
||||
! msg
|
||||
? not_implemented (msg)
|
||||
: cruft::debug::detail::not_implemented (msg);
|
||||
}
|
||||
|
||||
|
||||
constexpr void
|
||||
not_implemented [[noreturn]] (void)
|
||||
{
|
||||
not_implemented ("operation not implemented");
|
||||
}
|
||||
|
||||
|
||||
constexpr void unimplemented [[noreturn]] (void) { not_implemented (); }
|
||||
|
||||
|
||||
constexpr void unimplemented [[noreturn]] (const char *msg) { not_implemented (msg); }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
constexpr void
|
||||
unreachable [[noreturn]] (const char *msg)
|
||||
{
|
||||
! msg
|
||||
? unreachable (msg)
|
||||
: cruft::debug::detail::unreachable (msg);
|
||||
}
|
||||
|
||||
|
||||
constexpr void
|
||||
unreachable [[noreturn]] (void)
|
||||
{
|
||||
unreachable ("unreachable code isn't");
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// report a fatal error induced by an unhandled value, especially in switch
|
||||
/// statements. will almost invariably abort the application.
|
||||
namespace cruft::debug::detail {
|
||||
template <typename T>
|
||||
T
|
||||
unhandled [[noreturn]] (T &&t) noexcept
|
||||
{
|
||||
// If we've been given an enum we should handle it like its underlying
|
||||
// type so that when we end up logging it we don't accidentally
|
||||
// trigger an infinite loop of calls to `unhandled` within the
|
||||
// ostream operator. It doesn't have to be pretty, just functional.
|
||||
using base_type = std::remove_reference_t<std::decay_t<T>>;
|
||||
if constexpr (std::is_enum_v<base_type>) {
|
||||
unhandled (static_cast<std::underlying_type_t<base_type>> (t));
|
||||
} else {
|
||||
std::ostringstream os;
|
||||
os << "unhandled value: " << t << '\n';
|
||||
::panic (os.str ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
constexpr T
|
||||
unhandled [[noreturn]] (T &&t) noexcept
|
||||
{
|
||||
cruft::debug::detail::unhandled (std::forward<T> (t));
|
||||
}
|
Loading…
Reference in New Issue
Block a user