// @HEADER
// ***********************************************************************
//
// Teuchos: Common Tools Package
// Copyright (2004) Sandia Corporation
//
// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
// license for use of this work by or on behalf of the U.S. Government.
//
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA
// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
//
// ***********************************************************************
// @HEADER
#ifndef TEUCHOS_TEST_FOR_EXCEPTION_H
#define TEUCHOS_TEST_FOR_EXCEPTION_H
/*! \file Teuchos_TestForException.hpp
\brief Macro for throwing an exception with breakpointing to ease debugging.
*/
#include "Teuchos_TypeNameTraits.hpp"
/*! \defgroup TestForException_grp Utility code for throwing exceptions and setting breakpoints.
\ingroup teuchos_language_support_grp
*/
//@{
/** \brief Increment the throw number. */
void TestForException_incrThrowNumber();
/** \brief Increment the throw number. */
int TestForException_getThrowNumber();
/** \brief The only purpose for this function is to set a breakpoint. */
void TestForException_break( const std::string &msg );
/** \brief Macro for throwing an exception with breakpointing to ease debugging
*
* @param throw_exception_test
* [in] Test for when to throw the exception. This can and
* should be an expression that may mean something to the user.
* The text verbatim of this expression is included in the
* formed error string.
* @param Exception
* [in] This should be the name of an exception class. The
* only requirement for this class is that it have a constructor
* that accepts an std::string object (as all of the standard
* exception classes do).
* @param msg [in] This is any expression that can be included in an
* output stream operation. This is useful when buinding
* error messages on the fly. Note that the code in this
* argument only gets evaluated if throw_exception_test
* evaluates to true when an exception is throw.
*
* The way that this macro is intended to be used is to
* call it in the source code like a function. For example,
* suppose that in a piece of code in the file my_source_file.cpp
* that the exception std::out_of_range is thrown if n > 100.
* To use the macro, the source code would contain (at line 225
* for instance):
\verbatim
TEST_FOR_EXCEPTION( n > 100, std::out_of_range
, "Error, n = " << n << is bad" );
\endverbatim
* When the program runs and with n = 125 > 100 for instance,
* the std::out_of_range exception would be thrown with the
* error message:
\verbatim
/home/bob/project/src/my_source_file.cpp:225: n > 100: Error, n = 125 is bad
\endverbatim
*
* In order to debug this, simply open your debugger (gdb for instance),
* set a break point at my_soure_file.cpp:225 and then set the condition
* to break for n > 100 (e.g. in gdb the command
* is cond break_point_number n > 100 and then run the
* program. The program should stop a the point in the source file
* right where the exception will be thrown at but before the exception
* is thrown. Try not to use expression for throw_exception_test that
* includes virtual function calls, etc. as most debuggers will not be able to check
* these types of conditions in order to stop at a breakpoint. For example,
* instead of:
\verbatim
TEST_FOR_EXCEPTION( obj1->val() > obj2->val(), std::logic_error, "Oh no!" );
\endverbatim
* try:
\verbatim
double obj1_val = obj1->val(), obj2_val = obj2->val();
TEST_FOR_EXCEPTION( obj1_val > obj2_val, std::logic_error, "Oh no!" );
\endverbatim
* If the developer goes to the line in the source file that is contained
* in the error message of the exception thrown, he/she will see the
* underlying condition.
*
* As an alternative, you can set a breakpoint for any exception thrown
* by setting a breakpoint in the function ThrowException_break().
*/
#define TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg) \
{ \
const bool throw_exception = (throw_exception_test); \
if(throw_exception) { \
TestForException_incrThrowNumber(); \
std::ostringstream omsg; \
omsg \
<< __FILE__ << ":" << __LINE__ << ":\n\n" \
<< "Throw number = " << TestForException_getThrowNumber() << "\n\n" \
<< "Throw test that evaluated to true: "#throw_exception_test << "\n\n" \
<< msg; \
const std::string &omsgstr = omsg.str(); \
TestForException_break(omsgstr); \
throw Exception(omsgstr); \
} \
}
/** \brief Macro for throwing an exception with breakpointing to ease debugging
*
* This macro is equivalent to the TEST_FOR_EXCEPTION() macro except
* the file name, line number, and test condition are not printed.
*/
#define TEST_FOR_EXCEPTION_PURE_MSG(throw_exception_test,Exception,msg) \
{ \
const bool throw_exception = (throw_exception_test); \
if(throw_exception) { \
TestForException_incrThrowNumber(); \
std::ostringstream omsg; \
omsg << msg; \
omsg << "\n\nThrow number = " << TestForException_getThrowNumber() << "\n\n"; \
const std::string &omsgstr = omsg.str(); \
TestForException_break(omsgstr); \
throw Exception(omsgstr); \
} \
}
/** \brief This macro is designed to be a short version of
* TEST_FOR_EXCEPTION() that is easier to call.
*
* @param throw_exception_test
* [in] Test for when to throw the exception. This can and
* should be an expression that may mean something to the user.
* The text verbatim of this expression is included in the
* formed error string.
*
* \note The exception thrown is std::logic_error.
*/
#define TEST_FOR_EXCEPT(throw_exception_test) \
TEST_FOR_EXCEPTION(throw_exception_test,std::logic_error,"Error!")
/** \brief This macro is the same as TEST_FOR_EXCEPTION() except that the
* exception will be caught, the message printed, and then rethrown.
*
* @param throw_exception_test
* [in] See TEST_FOR_EXCEPTION().
* @param Exception
* [in] See TEST_FOR_EXCEPTION().
* @param msg [in] See TEST_FOR_EXCEPTION().
* @param out_ptr
* [in] If out_ptr!=NULL then *out_ptr will receive
* a printout of a line of output that gives the exception type and
* the error message that is generated.
*/
#define TEST_FOR_EXCEPTION_PRINT(throw_exception_test,Exception,msg,out_ptr) \
try { \
TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg); \
} \
catch(const std::exception &except) { \
std::ostream *l_out_ptr = (out_ptr); \
if(l_out_ptr) { \
*l_out_ptr \
<< "\nThorwing an std::exception of type \'"<TEST_FOR_EXCEPT() except that the
* exception will be caught, the message printed, and then rethrown.
*
* @param throw_exception_test
* [in] See TEST_FOR_EXCEPT().
* @param out_ptr
* [in] If out_ptr!=NULL then *out_ptr will receive
* a printout of a line of output that gives the exception type and
* the error message that is generated.
*/
#define TEST_FOR_EXCEPT_PRINT(throw_exception_test,out_ptr) \
TEST_FOR_EXCEPTION_PRINT(throw_exception_test,std::logic_error,"Error!",out_ptr)
/** \brief This macro intercepts an exception, prints a standardized message including
* the current filename and line number, and then throws the exception up the stack
* @param exc [in] the exception that has been caught
*/
#define TEUCHOS_TRACE(exc)\
{ \
std::ostringstream omsg; \
omsg << exc.what() << std::endl \
<< "caught in " << __FILE__ << ":" << __LINE__ << std::endl ; \
throw std::runtime_error(omsg.str()); \
}
//@}
#endif // TEUCHOS_TEST_FOR_EXCEPTION_H