From 2a6d03869a621d12ae8f10964088cdb96c71b2cc Mon Sep 17 00:00:00 2001 From: Wolfgang Bangerth Date: Thu, 25 Jan 2024 14:01:05 -0700 Subject: [PATCH] Introduce DEAL_II_NOT_IMPLEMENTED() and associated machinery. --- include/deal.II/base/exceptions.h | 27 ++++++++++++++++++++++++ source/base/exceptions.cc | 34 ++++++++++++++++++++++--------- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/include/deal.II/base/exceptions.h b/include/deal.II/base/exceptions.h index 740bf3c3a2..b158e50558 100644 --- a/include/deal.II/base/exceptions.h +++ b/include/deal.II/base/exceptions.h @@ -1762,6 +1762,33 @@ namespace deal_II_exceptions #endif /*ifdef DEAL_II_HAVE_BUILTIN_EXPECT*/ +/** + * `DEAL_II_NOT_IMPLEMENTED` is a macro (that looks like a function call + * when used as in `DEAL_II_NOT_IMPLEMENTED();`) that is used to raise an + * error in places where a piece of code is not yet implemented. If a code + * runs into such a place, it will be aborted with an error message that + * explains the situation, along with a backtrace of how the code ended + * up in this place. + * + * Alternatively, if + * deal_II_exceptions::internals::ExceptionHandling::abort_or_throw_on_exception + * is set to ExceptionHandling::throw_on_exception, then the corresponding + * error is thrown as a C++ exception that can be caught (though in + * many cases codes will then find it difficult to do what they wanted + * to do). + */ +#define DEAL_II_NOT_IMPLEMENTED() \ + ::dealii::deal_II_exceptions::internals::issue_error_noreturn( \ + ::dealii::deal_II_exceptions::internals::ExceptionHandling:: \ + abort_or_throw_on_exception, \ + __FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__, \ + nullptr, \ + nullptr, \ + ExcNotImplemented()) + + namespace deal_II_exceptions { namespace internals diff --git a/source/base/exceptions.cc b/source/base/exceptions.cc index cbf2200ac3..a7832a8262 100644 --- a/source/base/exceptions.cc +++ b/source/base/exceptions.cc @@ -183,14 +183,21 @@ ExceptionBase::print_exc_data(std::ostream &out) const // print a header for the exception out << "An error occurred in line <" << line << "> of file <" << file << "> in function" << std::endl - << " " << function << std::endl - << "The violated condition was: " << std::endl - << " " << cond << std::endl; - - // print the way the additional information message was generated. - // this is useful if the names of local variables appear in the - // generation of the error message, because it allows the identification - // of parts of the error text with what variables may have cause this + << " " << function << std::endl; + + // If the exception stores a string representation of the violated + // condition, then output it. Not all exceptions do (e.g., when + // creating an exception inside DEAL_II_NOT_IMPLEMENTED()), so + // we have to check whether there is anything to print. + if (cond != nullptr) + out << "The violated condition was: " << std::endl + << " " << cond << std::endl; + + // If a string representation of the exception itself is available, + // consider printing it as well. This is useful if the names of + // local variables appear in the generation of the error message, + // because it allows the identification of parts of the error text + // with what variables may have cause this. // // On the other hand, this is almost never the case for ExcMessage // exceptions which would simply print the same text twice: once for @@ -198,8 +205,15 @@ ExceptionBase::print_exc_data(std::ostream &out) const // information. Furthermore, the former of these two is often spread // between numerous "..."-enclosed strings that the preprocessor // collates into a single string, making it awkward to read. Consequently, - // elide this text if the message was generated via an ExcMessage object - if (std::strstr(cond, "dealii::ExcMessage") != nullptr) + // elide this text if the message was generated via an ExcMessage object. + // + // There are cases where the exception generation mechanism suppresses + // the string representation of the exception because it does not add + // anything -- e.g., DEAL_II_NOT_IMPLEMENTED does this. In those cases, + // also suppress the output. + if ((exc != nullptr) && + ((cond == nullptr) || + (std::strstr(cond, "dealii::ExcMessage") != nullptr))) out << "The name and call sequence of the exception was:" << std::endl << " " << exc << std::endl; -- 2.39.5