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
|
cpuid.hpp
|
||||||
debug.cpp
|
debug.cpp
|
||||||
debug.hpp
|
debug.hpp
|
||||||
|
debug/panic.cpp
|
||||||
|
debug/panic.hpp
|
||||||
encode/number.hpp
|
encode/number.hpp
|
||||||
encode/base.cpp
|
encode/base.cpp
|
||||||
encode/base.hpp
|
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
|
* 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/.
|
* 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
|
#pragma once
|
||||||
|
|
||||||
#include "platform.hpp"
|
#include "platform.hpp"
|
||||||
|
#include "debug/panic.hpp"
|
||||||
|
|
||||||
//#include "maths.hpp" // XXX: See notes at the end of file for maths.hpp inclusion
|
//#include "maths.hpp" // XXX: See notes at the end of file for maths.hpp inclusion
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -435,136 +436,6 @@ namespace cruft::debug {
|
|||||||
void breakpoint (void);
|
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 (void);
|
||||||
void warn (const std::string&);
|
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