|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r68414 - in trunk: boost boost/detail libs/utility
From: bdawes_at_[hidden]
Date: 2011-01-24 10:37:28
Author: bemandawes
Date: 2011-01-24 10:37:13 EST (Mon, 24 Jan 2011)
New Revision: 68414
URL: http://svn.boost.org/trac/boost/changeset/68414
Log:
Add BOOST_ASSERT_MSG. Add macros to configure output stream.
Text files modified:
trunk/boost/assert.hpp | 83 ++++++++++++++++++++++++++++++++++++++-
trunk/boost/detail/lightweight_test.hpp | 29 ++++++++++---
trunk/libs/utility/assert.html | 74 ++++++++++++++++++++++++++++++----
trunk/libs/utility/assert_test.cpp | 45 +++++++++++++++++++++
4 files changed, 210 insertions(+), 21 deletions(-)
Modified: trunk/boost/assert.hpp
==============================================================================
--- trunk/boost/assert.hpp (original)
+++ trunk/boost/assert.hpp 2011-01-24 10:37:13 EST (Mon, 24 Jan 2011)
@@ -1,8 +1,11 @@
//
// boost/assert.hpp - BOOST_ASSERT(expr)
+// BOOST_ASSERT_MSG(expr, msg)
+// BOOST_VERIFY(expr)
//
// Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd.
// Copyright (c) 2007 Peter Dimov
+// Copyright (c) Beman Dawes 2011
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -19,6 +22,10 @@
// boostinspect:naassert_macro
//
+//--------------------------------------------------------------------------------------//
+// BOOST_ASSERT //
+//--------------------------------------------------------------------------------------//
+
#undef BOOST_ASSERT
#if defined(BOOST_DISABLE_ASSERTS)
@@ -31,18 +38,86 @@
namespace boost
{
-
-void assertion_failed(char const * expr, char const * function, char const * file, long line); // user defined
-
+ void assertion_failed(char const * expr,
+ char const * function, char const * file, long line); // user defined
} // namespace boost
-#define BOOST_ASSERT(expr) ((expr)? ((void)0): ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
+#define BOOST_ASSERT(expr) ((expr) \
+ ? ((void)0) \
+ : ::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
#else
# include <assert.h> // .h to support old libraries w/o <cassert> - effect is the same
# define BOOST_ASSERT(expr) assert(expr)
#endif
+//--------------------------------------------------------------------------------------//
+// BOOST_ASSERT_MSG //
+//--------------------------------------------------------------------------------------//
+
+# undef BOOST_ASSERT_MSG
+
+#if defined(BOOST_DISABLE_ASSERTS) || defined(NDEBUG)
+
+ #define BOOST_ASSERT_MSG(expr, msg) ((void)0)
+
+#elif defined(BOOST_ENABLE_ASSERT_MSG_HANDLER)
+
+ #include <boost/current_function.hpp>
+
+ namespace boost
+ {
+ void assertion_failed_msg(char const * expr, char const * msg,
+ char const * function, char const * file, long line); // user defined
+ } // namespace boost
+
+ #define BOOST_ASSERT_MSG(expr, msg) ((expr) \
+ ? ((void)0) \
+ : ::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
+
+#else
+ #ifndef BOOST_ASSERT_HPP
+ #define BOOST_ASSERT_HPP
+ #include <cstdlib>
+ #include <iostream>
+ #include <boost/current_function.hpp>
+
+ // IDE's like Visual Studio perform better if output goes to std::cout or
+ // some other stream, so allow user to configure output stream:
+ #ifndef BOOST_ASSERT_MSG_OSTREAM
+ # define BOOST_ASSERT_MSG_OSTREAM std::cerr
+ #endif
+
+ namespace boost
+ {
+ namespace assertion
+ {
+ namespace detail
+ {
+ inline void assertion_failed_msg(char const * expr, char const * msg, char const * function,
+ char const * file, long line)
+ {
+ BOOST_ASSERT_MSG_OSTREAM
+ << "***** Internal Program Error - assertion (" << expr << ") failed in "
+ << function << ":\n"
+ << file << '(' << line << "): " << msg << std::endl;
+ std::abort();
+ }
+ } // detail
+ } // assertion
+ } // detail
+ #endif
+
+ #define BOOST_ASSERT_MSG(expr, msg) ((expr) \
+ ? ((void)0) \
+ : ::boost::assertion::detail::assertion_failed_msg(#expr, msg, \
+ BOOST_CURRENT_FUNCTION, __FILE__, __LINE__))
+#endif
+
+//--------------------------------------------------------------------------------------//
+// BOOST_VERIFY //
+//--------------------------------------------------------------------------------------//
+
#undef BOOST_VERIFY
#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) )
Modified: trunk/boost/detail/lightweight_test.hpp
==============================================================================
--- trunk/boost/detail/lightweight_test.hpp (original)
+++ trunk/boost/detail/lightweight_test.hpp 2011-01-24 10:37:13 EST (Mon, 24 Jan 2011)
@@ -11,6 +11,7 @@
// boost/detail/lightweight_test.hpp - lightweight test library
//
// Copyright (c) 2002, 2009 Peter Dimov
+// Copyright (2) Beman Dawes 2010, 2011
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
@@ -23,9 +24,15 @@
// int boost::report_errors()
//
+#include <iostream>
#include <boost/current_function.hpp>
#include <boost/assert.hpp>
-#include <iostream>
+
+// IDE's like Visual Studio perform better if output goes to std::cout or
+// some other stream, so allow user to configure output stream:
+#ifndef BOOST_LIGHTWEIGHT_TEST_OSTREAM
+# define BOOST_LIGHTWEIGHT_TEST_OSTREAM std::cerr
+#endif
namespace boost
{
@@ -58,24 +65,30 @@
inline void test_failed_impl(char const * expr, char const * file, int line, char const * function)
{
- std::cerr << file << "(" << line << "): test '" << expr << "' failed in function '" << function << "'" << std::endl;
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << file << "(" << line << "): test '" << expr << "' failed in function '"
+ << function << "'" << std::endl;
++test_errors();
}
inline void error_impl(char const * msg, char const * file, int line, char const * function)
{
- std::cerr << file << "(" << line << "): " << msg << " in function '" << function << "'" << std::endl;
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << file << "(" << line << "): " << msg << " in function '"
+ << function << "'" << std::endl;
++test_errors();
}
-template<class T, class U> inline void test_eq_impl( char const * expr1, char const * expr2, char const * file, int line, char const * function, T const & t, U const & u )
+template<class T, class U> inline void test_eq_impl( char const * expr1, char const * expr2,
+ char const * file, int line, char const * function, T const & t, U const & u )
{
if( t == u )
{
}
else
{
- std::cerr << file << "(" << line << "): test '" << expr1 << " == " << expr2
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << file << "(" << line << "): test '" << expr1 << " == " << expr2
<< "' failed in function '" << function << "': "
<< "'" << t << "' != '" << u << "'" << std::endl;
++test_errors();
@@ -92,12 +105,14 @@
if( errors == 0 )
{
- std::cerr << "No errors detected." << std::endl;
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << "No errors detected." << std::endl;
return 0;
}
else
{
- std::cerr << errors << " error" << (errors == 1? "": "s") << " detected." << std::endl;
+ BOOST_LIGHTWEIGHT_TEST_OSTREAM
+ << errors << " error" << (errors == 1? "": "s") << " detected." << std::endl;
return 1;
}
}
Modified: trunk/libs/utility/assert.html
==============================================================================
--- trunk/libs/utility/assert.html (original)
+++ trunk/libs/utility/assert.html 2011-01-24 10:37:13 EST (Mon, 24 Jan 2011)
@@ -18,35 +18,88 @@
</tr>
</table>
<p>
+ BOOST_ASSERT<br>
+ BOOST_ASSERT_MSG<br>
+ BOOST_VERIFY</p>
+
+<h2><a name="BOOST_ASSERT">BOOST_ASSERT</a></h2>
+ <p>
The header <STRONG><boost/assert.hpp></STRONG> defines the macro <b>BOOST_ASSERT</b>,
which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG><cassert></STRONG>.
- The macro is intended to be used in Boost libraries.
+ The macro is intended to be used in both Boost libraries and user
+ code.
</p>
<P>By default, <tt>BOOST_ASSERT(expr)</tt> is equivalent to <tt>assert(expr)</tt>.</P>
- <P>When the macro <STRONG>BOOST_DISABLE_ASSERTS</STRONG> is defined when <STRONG><boost/assert.hpp></STRONG>
+ <P>If the macro <STRONG>BOOST_DISABLE_ASSERTS</STRONG> is defined when <STRONG><boost/assert.hpp></STRONG>
is included, <tt>BOOST_ASSERT(expr)</tt> is defined as <tt>((void)0)</tt>. This
allows users to selectively disable <STRONG>BOOST_ASSERT</STRONG> without
affecting the definition of the standard <STRONG>assert</STRONG>.</P>
- <P>When the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG><boost/assert.hpp></STRONG>
+ <P>If the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG><boost/assert.hpp></STRONG>
is included, <tt>BOOST_ASSERT(expr)</tt> evaluates <b>expr</b> and, if the
result is false, evaluates the expression</P>
+ <blockquote>
<P><tt>::boost::assertion_failed(#expr, BOOST_CURRENT_FUNCTION,
__FILE__, __LINE__)</tt></P>
+ </blockquote>
<P><STRONG>assertion_failed</STRONG> is declared in <STRONG><boost/assert.hpp></STRONG>
as</P>
- <pre>
-namespace boost
+ <blockquote>
+ <pre>namespace boost
{
-
-void assertion_failed(char const * expr, char const * function, char const * file, long line);
-
+ void assertion_failed(char const * expr, char const * function, char const * file, long line);
}
</pre>
+ </blockquote>
<p>but it is never defined. The user is expected to supply an appropriate
definition.</p>
<P>As is the case with <STRONG><cassert></STRONG>, <STRONG><boost/assert.hpp></STRONG>
can be included multiple times in a single translation unit. <STRONG>BOOST_ASSERT</STRONG>
will be redefined each time as specified above.</P>
+
+<h2><a name="BOOST_ASSERT_MSG">BOOST_ASSERT_MSG</a></h2>
+ <p>
+ The header <STRONG><boost/assert.hpp></STRONG> defines the macro <b>BOOST_ASSERT_MSG</b>,
+ which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG><cassert></STRONG>,
+ but with an additional macro parameter supplying an error message. The macro is intended to be used in both Boost libraries
+ and user code.
+ </p>
+ <P> <tt>BOOST_ASSERT_MSG(expr, msg)</tt> is equivalent to <code>
+ ((void)0)</code> if <b>BOOST_DISABLE_ASSERTS</b> or <b>NDEBUG</b> are
+ defined or <code>expr</code> evaluates to <code>true</code>. If those
+ macros and <STRONG>BOOST_ENABLE_ASSERT_MSG_HANDLER</STRONG> are not
+ defined, and <code>expr</code> evaluates to <code>false</code>, an error
+ message that includes <tt>#expr</tt>, <tt>msg</tt>, <tt> BOOST_CURRENT_FUNCTION</tt>, <tt>
+ __FILE__</tt>, and <tt>__LINE__</tt> is sent to output stream <b>
+ BOOST_ASSERT_MSG_OSTREAM</b>
+ and <code>std::abort()</code> is called.</P>
+ <P> <b>BOOST_ASSERT_MSG_OSTREAM</b> defines the output stream. It defaults to <code>std::cerr</code>.
+ Integrated development environments (IDE's) like Microsoft Visual Studio
+ may produce easier to understand output if messages go to a different
+ stream, such as <code>std::cout</code>. Users may define <b>BOOST_ASSERT_MSG_OSTREAM</b> before including <STRONG><boost/assert.hpp></STRONG>
+ to specify a different output stream. </P>
+ <P>If the macro <STRONG>BOOST_ENABLE_ASSERT_MSG_HANDLER</STRONG> is defined when <STRONG><boost/assert.hpp></STRONG>
+ is included, instead of sending a error message to an output
+ stream, this expression is evaluated</P>
+ <blockquote>
+ <P><tt>::boost::assertion_failed_msg(#expr, msg, BOOST_CURRENT_FUNCTION,
+ __FILE__, __LINE__)</tt></P>
+ </blockquote>
+ <P><STRONG>assertion_failed_msg</STRONG> is declared in <STRONG><boost/assert.hpp></STRONG>
+ as</P>
+ <blockquote>
+ <pre>namespace boost
+{
+ void assertion_failed_msg(char const * expr, char const * msg, char const * function, char const * file, long line);
+}
+</pre>
+ </blockquote>
+ <p>but it is never defined. The user is expected to supply an appropriate
+ definition.</p>
+ <P>As is the case with <STRONG><cassert></STRONG>, <STRONG><boost/assert.hpp></STRONG>
+ can be included multiple times in a single translation unit. <STRONG>BOOST_ASSERT_MSG</STRONG>
+ will be redefined each time as specified above.</P>
+
+<h2><a name="BOOST_VERIFY">BOOST_VERIFY</a></h2>
<p><STRONG><boost/assert.hpp></STRONG> also defines the macro <STRONG>BOOST_VERIFY</STRONG>.
It has exactly the same behavior as <STRONG>BOOST_ASSERT</STRONG>, except that
the expression that is passed to <STRONG>BOOST_VERIFY</STRONG> is always
@@ -54,8 +107,9 @@
effects; it can also help suppress warnings about unused variables when the
only use of the variable is inside an assertion.</p>
<p><br>
- <small>Copyright © 2002, 2007 by Peter Dimov. Distributed under the Boost Software
+ <small>Copyright © 2002, 2007 by Peter Dimov. Copyright © 2011
+ by Beman Dawes. Distributed under the Boost Software
License, Version 1.0. See accompanying file LICENSE_1_0.txt
or copy at http://www.boost.org/LICENSE_1_0.txt.</small></p>
</body>
-</html>
+</html>
\ No newline at end of file
Modified: trunk/libs/utility/assert_test.cpp
==============================================================================
--- trunk/libs/utility/assert_test.cpp (original)
+++ trunk/libs/utility/assert_test.cpp 2011-01-24 10:37:13 EST (Mon, 24 Jan 2011)
@@ -2,6 +2,7 @@
// assert_test.cpp - a test for boost/assert.hpp
//
// Copyright (c) 2002 Peter Dimov and Multi Media Ltd.
+// Copyright (2) Beman Dawes 2011
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
@@ -20,6 +21,11 @@
BOOST_ASSERT(x);
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
+
+ BOOST_ASSERT_MSG(1, "msg");
+ BOOST_ASSERT_MSG(x, "msg");
+ BOOST_ASSERT_MSG(x == 1, "msg");
+ BOOST_ASSERT_MSG(&x, "msg");
}
#define BOOST_DISABLE_ASSERTS
@@ -34,13 +40,23 @@
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
+ BOOST_ASSERT_MSG(1, "msg");
+ BOOST_ASSERT_MSG(x, "msg");
+ BOOST_ASSERT_MSG(x == 1, "msg");
+ BOOST_ASSERT_MSG(&x, "msg");
+
BOOST_ASSERT(0);
BOOST_ASSERT(!x);
BOOST_ASSERT(x == 0);
+ BOOST_ASSERT_MSG(0, "msg");
+ BOOST_ASSERT_MSG(!x, "msg");
+ BOOST_ASSERT_MSG(x == 0, "msg");
+
void * p = 0;
BOOST_ASSERT(p);
+ BOOST_ASSERT_MSG(p, "msg");
// supress warnings
p = &x;
@@ -50,11 +66,13 @@
#undef BOOST_DISABLE_ASSERTS
#define BOOST_ENABLE_ASSERT_HANDLER
+#define BOOST_ENABLE_ASSERT_MSG_HANDLER
#include <boost/assert.hpp>
#include <boost/config.hpp>
#include <cstdio>
int handler_invoked = 0;
+int msg_handler_invoked = 0;
void boost::assertion_failed(char const * expr, char const * function, char const * file, long line)
{
@@ -66,11 +84,24 @@
++handler_invoked;
}
+void boost::assertion_failed_msg(char const * expr, char const * msg, char const * function,
+ char const * file, long line)
+{
+#if !defined(BOOST_NO_STDC_NAMESPACE)
+ using std::printf;
+#endif
+
+ printf("Expression: %s Message: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n",
+ expr, msg, function, file, line);
+ ++msg_handler_invoked;
+}
+
struct X
{
static void f()
{
BOOST_ASSERT(0);
+ BOOST_ASSERT_MSG(0, "msg f()");
}
};
@@ -83,21 +114,35 @@
BOOST_ASSERT(x == 1);
BOOST_ASSERT(&x);
+ BOOST_ASSERT_MSG(1, "msg2");
+ BOOST_ASSERT_MSG(x, "msg3");
+ BOOST_ASSERT_MSG(x == 1, "msg4");
+ BOOST_ASSERT_MSG(&x, "msg5");
+
BOOST_ASSERT(0);
BOOST_ASSERT(!x);
BOOST_ASSERT(x == 0);
+ BOOST_ASSERT_MSG(0,"msg 0");
+ BOOST_ASSERT_MSG(!x, "msg !x");
+ BOOST_ASSERT_MSG(x == 0, "msg x == 0");
+
void * p = 0;
BOOST_ASSERT(p);
+ BOOST_ASSERT_MSG(p, "msg p");
X::f();
BOOST_ASSERT(handler_invoked == 5);
BOOST_TEST(handler_invoked == 5);
+
+ BOOST_ASSERT_MSG(msg_handler_invoked == 5, "msg_handler_invoked count is wrong");
+ BOOST_TEST(msg_handler_invoked == 5);
}
#undef BOOST_ENABLE_ASSERT_HANDLER
+#undef BOOST_ENABLE_ASSERT_MSG_HANDLER
int main()
{
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk