debug: make panic and friends constexpr

This commit is contained in:
Danny Robson 2015-10-29 10:43:41 +11:00
parent ba9a8f8b35
commit 2702c53df4
3 changed files with 148 additions and 47 deletions

View File

@ -22,33 +22,31 @@
#include <cstdlib>
#include <iostream>
using namespace std;
using namespace util::debug;
//------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
void
panic (const std::string& what) {
cerr << "PANIC: " << what << "\n" << debug::backtrace () << endl;
detail::panic (const char *msg)
{
std::cerr << "PANIC: " << msg << "\n" << ::debug::backtrace () << std::endl;
breakpoint ();
abort ();
}
void
panic (void)
{ panic ("NFI"); }
//------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
#if defined(PLATFORM_WIN32)
#include <windows.h>
void
breakpoint (void) {
breakpoint (void)
{
DebugBreak ();
}
#else
void
breakpoint (void) {
breakpoint (void)
{
#if defined (__x86_64) || defined (__i386)
__asm__ ("int $3;");
#else
@ -58,39 +56,31 @@ breakpoint (void) {
#endif
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void
not_implemented (void) {
not_implemented ("Function not implemented");
detail::not_implemented (const char *msg)
{
panic (msg);
}
//-----------------------------------------------------------------------------
void
not_implemented (const char *msg)
{ panic (msg); }
//------------------------------------------------------------------------------
void
unreachable (void) {
panic ("Unreachable code executed");
detail::unreachable (const char *msg)
{
panic (msg);
}
////////////////////////////////////////////////////////////////////////////////
void
unreachable (const std::string& what) {
panic (" Unreachable code executed: " + what);
}
//------------------------------------------------------------------------------
void
unusual (void) {
unusual (void)
{
panic ("Unusual code path found.");
}
//------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
#if defined(PLATFORM_LINUX)
#include <fenv.h>
void
@ -100,6 +90,7 @@ enable_fpe (void)
}
//-----------------------------------------------------------------------------
void
disable_fpe (void)
{
@ -108,8 +99,11 @@ disable_fpe (void)
#else
// contropfp is not defined supposedly due to a regression in GCC include behaviours.
//-----------------------------------------------------------------------------
void
enable_fpe (void) {
enable_fpe (void)
{
LOG_WARN ("Non-Linux exception code is broken under current GCC.");
// _clearfp();
// unsigned int ignored;
@ -117,8 +111,10 @@ enable_fpe (void) {
}
//-----------------------------------------------------------------------------
void
disable_fpe (void) {
disable_fpe (void)
{
LOG_WARN ("Non-Linux exception code is broken under current GCC.");
// _clearfp();
// unsigned int ignored;
@ -127,13 +123,14 @@ disable_fpe (void) {
#endif
//------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
#if defined(PLATFORM_WIN32)
#include <io.h>
#include <fcntl.h>
void
force_console (void) {
force_console (void)
{
if (!AttachConsole (ATTACH_PARENT_PROCESS))
return;
@ -169,9 +166,10 @@ force_console (void) {
#endif
//------------------------------------------------------------------------------
////////////////////////////////////////////////////////////////////////////////
void
debug::init (void) {
util::debug::init (void)
{
#if defined(PLATFORM_WIN32)
force_console ();

View File

@ -11,7 +11,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2010-2012 Danny Robson <danny@nerdcruft.net>
* Copyright 2010-2015 Danny Robson <danny@nerdcruft.net>
*/
#ifndef __DEBUG_HPP
@ -289,18 +289,21 @@ class panic_error {
};
///////////////////////////////////////////////////////////////////////////////
void panic [[noreturn]] (const std::string&);
void panic [[noreturn]] (void);
constexpr void panic [[noreturn]] (const char*);
constexpr void panic [[noreturn]] (void);
///////////////////////////////////////////////////////////////////////////////
void not_implemented [[noreturn]] (void);
void not_implemented [[noreturn]] (const char*);
constexpr void not_implemented [[noreturn]] (void);
constexpr void not_implemented [[noreturn]] (const char *msg);
///////////////////////////////////////////////////////////////////////////////
void unreachable [[noreturn]] (void);
void unreachable [[noreturn]] (const std::string&);
constexpr void unreachable [[noreturn]] (void);
constexpr void unreachable [[noreturn]] (const char*);
void unusual (void);
@ -314,7 +317,7 @@ void disable_fpe (void);
///////////////////////////////////////////////////////////////////////////////
namespace debug {
namespace util { namespace debug {
void init (void);
@ -358,13 +361,15 @@ namespace debug {
(void)t;
CHECK (valid (t));
}
}
} }
///////////////////////////////////////////////////////////////////////////////
// XXX: maths needs to be included so that CHECK_EQ/NEQ can call almost_equal,
// but maths.hpp might be using CHECK_ macros so we must include maths.hpp
// after we define the CHECK_ macros so the preprocessor can resolve them.
#include "maths.hpp"
#include "./maths.hpp"
#include "./debug.ipp"
#endif // __DEBUG_HPP

98
debug.ipp Normal file
View File

@ -0,0 +1,98 @@
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
*/
#ifdef __UTIL_DEBUG_IPP
#error
#endif
#define __UTIL_DEBUG_IPP
#include <limits>
///////////////////////////////////////////////////////////////////////////////
namespace util { namespace debug { namespace detail {
void panic [[noreturn]] (const char *msg);
void not_implemented [[noreturn]] (const char *msg);
void unreachable [[noreturn]] (const char *msg);
} } }
// 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]] (void)
{
not_implemented ("operation not implemented");
}
//-----------------------------------------------------------------------------
constexpr void not_implemented [[noreturn]] (const char *msg)
{
! msg
? not_implemented (msg)
: util::debug::detail::not_implemented (msg);
}
///////////////////////////////////////////////////////////////////////////////
constexpr void unreachable [[noreturn]] (void)
{
unreachable ("unreachable code executed");
}
//-----------------------------------------------------------------------------
constexpr void unreachable [[noreturn]] (const char *msg)
{
! msg
? unreachable (msg)
: util::debug::detail::unreachable (msg);
}
///////////////////////////////////////////////////////////////////////////////
inline void panic [[noreturn]] (const std::string &msg)
{
util::debug::detail::panic (msg.c_str ());
}
//-----------------------------------------------------------------------------
constexpr void panic [[noreturn]] (void)
{
panic ("nfi");
}
//-----------------------------------------------------------------------------
constexpr void panic [[noreturn]] (const char *msg)
{
! msg
? panic (msg)
: util::debug::detail::panic (msg);
}