Boost logo

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>&lt;boost/assert.hpp&gt;</STRONG> defines the macro <b>BOOST_ASSERT</b>,
                         which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG>&lt;cassert&gt;</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>&lt;boost/assert.hpp&gt;</STRONG>
+ <P>If the macro <STRONG>BOOST_DISABLE_ASSERTS</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</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>&lt;boost/assert.hpp&gt;</STRONG>
+ <P>If the macro <STRONG>BOOST_ENABLE_ASSERT_HANDLER</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</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>&lt;boost/assert.hpp&gt;</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>&lt;cassert&gt;</STRONG>, <STRONG>&lt;boost/assert.hpp&gt;</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>&lt;boost/assert.hpp&gt;</STRONG> defines the macro <b>BOOST_ASSERT_MSG</b>,
+ which is similar to the standard <STRONG>assert</STRONG> macro defined in <STRONG>&lt;cassert&gt;</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>&lt;boost/assert.hpp&gt;</STRONG>
+ to specify a different output stream.&nbsp; </P>
+ <P>If the macro <STRONG>BOOST_ENABLE_ASSERT_MSG_HANDLER</STRONG> is defined when <STRONG>&lt;boost/assert.hpp&gt;</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>&lt;boost/assert.hpp&gt;</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>&lt;cassert&gt;</STRONG>, <STRONG>&lt;boost/assert.hpp&gt;</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>&lt;boost/assert.hpp&gt;</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.&nbsp; 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