diff --git a/debug.cpp b/debug.cpp index ecfab2aa..e180be9a 100644 --- a/debug.cpp +++ b/debug.cpp @@ -22,33 +22,31 @@ #include #include -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 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 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 #include 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 (); diff --git a/debug.hpp b/debug.hpp index 9bca8b18..19ad5b4e 100644 --- a/debug.hpp +++ b/debug.hpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2010-2012 Danny Robson + * Copyright 2010-2015 Danny Robson */ #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 diff --git a/debug.ipp b/debug.ipp new file mode 100644 index 00000000..f54475e5 --- /dev/null +++ b/debug.ipp @@ -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 + */ + +#ifdef __UTIL_DEBUG_IPP +#error +#endif + +#define __UTIL_DEBUG_IPP + +#include + +/////////////////////////////////////////////////////////////////////////////// +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); +}