diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index 290188fb..806e0616 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -1,4 +1,4 @@ -Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard' +Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value' CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 16cec927..8f6cb5ad 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -26,6 +26,7 @@ if(USE_PYTHON) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp + exception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 05766a14..30c1023c 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -7,13 +7,13 @@ #include // for function #include // for map #include // for shared_ptr -#include // for runtime_error #include // for string #include // for declval, enable_if, false_type, is_co... #include // for type_info #include // for move, swap, pair #include // for vector +#include "exception.hpp" // for UnreachableCodeException, Exception #include "logging.hpp" // for logger #include "ngcore_api.hpp" // for NGCORE_API, unlikely #include "type_traits.hpp" // for all_of_tmpl @@ -37,7 +37,7 @@ namespace ngcore // create new pointer of type T if it is default constructible, else throw template T* constructIfPossible_impl(Rest... /*unused*/) - { throw std::runtime_error(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } + { throw Exception(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } template::value>::type> T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT @@ -140,9 +140,9 @@ namespace ngcore #ifdef NETGEN_PYTHON virtual void ShallowOutPython(const pybind11::object& /*unused*/) - { throw std::runtime_error("Should not get in ShallowToPython base class implementation!"); } + { throw UnreachableCodeException{}; } virtual pybind11::object ShallowInPython() - { throw std::runtime_error("Should not get in ShallowFromPython base class implementation!"); } + { throw UnreachableCodeException{}; } #endif // NETGEN_PYTHON Archive& operator=(const Archive&) = delete; @@ -284,9 +284,9 @@ namespace ngcore NETGEN_DEBUG_LOG(logger, "Typids are different: " + Demangle(typeid(T).name()) + " vs. " + Demangle(typeid(*ptr).name())); if(!IsRegistered(Demangle(typeid(*ptr).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + Demangle(typeid(*ptr).name()) - + " not registered for archive"); + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*ptr).name()) + + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); // if there was a true downcast we have to store more information if(reg_ptr != static_cast(ptr.get())) @@ -404,9 +404,9 @@ namespace ngcore NETGEN_DEBUG_LOG(logger, "Typeids are different: " + Demangle(typeid(T).name()) + " vs. " + Demangle(typeid(*p).name())); if(!IsRegistered(Demangle(typeid(*p).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + Demangle(typeid(*p).name()) - + " not registered for archive"); + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*p).name()) + + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); if(reg_ptr != static_cast(p)) { @@ -427,8 +427,8 @@ namespace ngcore return (*this) << -1 & (*p); } else - throw std::runtime_error(std::string("Archive error: Class ") + - Demangle(typeid(*p).name()) + " does not provide a default constructor!"); + throw Exception(std::string("Archive error: Class ") + + Demangle(typeid(*p).name()) + " does not provide a default constructor!"); else { // if a pointer to a base class is archived, the class hierarchy must be registered @@ -436,9 +436,9 @@ namespace ngcore // implement a void DoArchive(Archive&) member function // To recreate the object we need to store the true type of it if(!IsRegistered(Demangle(typeid(*p).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + Demangle(typeid(*p).name()) - + " not registered for archive"); + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*p).name()) + + " not registered for archive"); NETGEN_DEBUG_LOG(logger, "Store a possibly more complicated pointer"); return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); } @@ -552,11 +552,11 @@ namespace ngcore { static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/) { - throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!"); + throw Exception("Upcast not successful, some classes are not registered properly for archiving!"); } static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/) { - throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!"); + throw Exception("Downcast not successful, some classes are not registered properly for archiving!"); } }; @@ -568,7 +568,7 @@ namespace ngcore try { return GetArchiveRegister(Demangle(typeid(B1).name())). upcaster(ti, static_cast(dynamic_cast(p))); } - catch(std::exception&) + catch(const Exception&) { return Caster::tryUpcast(ti, p); } } @@ -581,7 +581,7 @@ namespace ngcore return dynamic_cast(static_cast(GetArchiveRegister(Demangle(typeid(B1).name())). downcaster(ti, p))); } - catch(std::exception&) + catch(const Exception&) { return Caster::tryDowncast(ti, p); } diff --git a/libsrc/core/exception.hpp b/libsrc/core/exception.hpp new file mode 100644 index 00000000..248a180f --- /dev/null +++ b/libsrc/core/exception.hpp @@ -0,0 +1,68 @@ +#ifndef NETGEN_CORE_EXCEPTION_HPP +#define NETGEN_CORE_EXCEPTION_HPP + +#include // for stringstream +#include // for exception +#include // for string + +#include "ngcore_api.hpp" // for NGCORE_API + +namespace ngcore +{ + // Exception for code that shouldn't be executed + class NGCORE_API UnreachableCodeException : public std::exception + { + const char* what() const noexcept override + { + return "Shouldn't get here, something went wrong!"; + } + }; + + // Default exception class + class NGCORE_API Exception : public std::exception + { + /// a verbal description of the exception + std::string m_what; + public: + Exception() = default; + Exception(const Exception&) = default; + Exception(Exception&&) = default; + Exception(const std::string& s) : m_what(s) {} + Exception(const char* s) : m_what(s) {} + ~Exception() override = default; + + Exception& operator =(const Exception&) = default; + Exception& operator =(Exception&&) noexcept = default; + + /// append string to description + Exception & Append (const std::string & s) { m_what += s; return *this; } + /// append string to description + Exception & Append (const char * s) { m_what += s; return *this; } + + /// verbal description of exception + const std::string & What() const { return m_what; } + + /// implement virtual function of std::exception + const char* what() const noexcept override { return m_what.c_str(); } + }; + + // Out of Range exception + class NGCORE_API RangeException : public Exception + { + public: + /// where it occurs, index, minimal and maximal indices + RangeException (const std::string & where, + int ind, int imin, int imax) : Exception("") + { + std::stringstream str; + str << where << ": index " << ind << " out of range [" << imin << "," << imax << "]\n"; + Append (str.str()); + } + }; + + // Exception used if no simd implementation is available to fall back to standard evaluation + class NGCORE_API ExceptionNOSIMD : public Exception + { public: using Exception::Exception; }; +} // namespace ngcore + +#endif // NETGEN_CORE_EXCEPTION_HPP diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index ea7f8eab..b345a114 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -2,6 +2,7 @@ #define NETGEN_CORE_NGCORE_HPP #include "archive.hpp" +#include "exception.hpp" #include "logging.hpp" #include "version.hpp"