diff --git a/assert.html b/assert.html index 4381ae1..a970cef 100644 --- a/assert.html +++ b/assert.html @@ -47,9 +47,15 @@ void assertion_failed(char const * expr, char const * function, char const * fil

As is the case with <cassert>, <boost/assert.hpp> can be included multiple times in a single translation unit. BOOST_ASSERT will be redefined each time as specified above.

+

<boost/assert.hpp> also defines the macro BOOST_VERIFY. + It has exactly the same behavior as BOOST_ASSERT, except that + the expression that is passed to BOOST_VERIFY is always + evaluated. This is useful when the asserted expression has desirable side + effects; it can also help suppress warnings about unused variables when the + only use of the variable is inside an assertion.


- Copyright © 2002 by Peter Dimov. 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.

+ Copyright © 2002, 2007 by Peter Dimov. 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.

diff --git a/include/boost/assert.hpp b/include/boost/assert.hpp index 5619f29..c227f17 100644 --- a/include/boost/assert.hpp +++ b/include/boost/assert.hpp @@ -2,6 +2,7 @@ // boost/assert.hpp - BOOST_ASSERT(expr) // // Copyright (c) 2001, 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2007 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -35,3 +36,15 @@ void assertion_failed(char const * expr, char const * function, char const * fil # include // .h to support old libraries w/o - effect is the same # define BOOST_ASSERT(expr) assert(expr) #endif + +#undef BOOST_VERIFY + +#if defined(BOOST_DISABLE_ASSERTS) || ( !defined(BOOST_ENABLE_ASSERT_HANDLER) && defined(NDEBUG) ) + +# define BOOST_VERIFY(expr) ((void)(expr)) + +#else + +# define BOOST_VERIFY(expr) BOOST_ASSERT(expr) + +#endif diff --git a/include/boost/utility/typed_in_place_factory.hpp b/include/boost/utility/typed_in_place_factory.hpp index f5de755..347b7f4 100644 --- a/include/boost/utility/typed_in_place_factory.hpp +++ b/include/boost/utility/typed_in_place_factory.hpp @@ -54,8 +54,8 @@ public: void* apply (void* address, std::size_t n) const { - for(char* next = address = this->apply(address); !! --n;) - this->apply(next = next+sizeof(T)); + for(void* next = address = this->apply(address); !! --n;) + this->apply(next = static_cast(next) + sizeof(T)); return address; } diff --git a/include/boost/utility/value_init.hpp b/include/boost/utility/value_init.hpp index 65600e5..b6d1246 100644 --- a/include/boost/utility/value_init.hpp +++ b/include/boost/utility/value_init.hpp @@ -1,10 +1,11 @@ -// (C) 2002, Fernando Luis Cacciola Carballal. +// (C) Copyright 2002-2007, Fernando Luis Cacciola Carballal. // // 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) // // 21 Ago 2002 (Created) Fernando Cacciola +// 07 Set 2007 (Worked around MSVC++ bug) Fernando Cacciola, Niels Dekker // #ifndef BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP #define BOOST_UTILITY_VALUE_INIT_21AGO2002_HPP @@ -13,6 +14,98 @@ #include #include +#if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500) ) +// Microsoft Visual C++ does not correctly support value initialization, as reported by +// Pavel Kuznetsov (MetaCommunications Engineering), 7/28/2005, Feedback ID 100744, +// Feedback Title: Value-initialization in new-expression +// https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=100744 +// The report was closed at 11/14/2006, and its status was set to "Closed (Won't Fix)". +// Luckily, even in the presence of this compiler bug, boost::value_initialized will still +// do its job correctly, when using the following workaround: +#define BOOST_UTILITY_VALUE_INIT_WORKAROUND +#endif + +#ifdef BOOST_UTILITY_VALUE_INIT_WORKAROUND +#include +#include +#include +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#if _MSC_VER >= 1310 +// When using MSVC 7.1 or higher, placement new, "new (&x) T()", may trigger warning C4345: +// "behavior change: an object of POD type constructed with an initializer of the form () +// will be default-initialized". There is no need to worry about this, though. +#pragma warning(disable: 4345) +#endif +#endif + +namespace boost { + +namespace vinit_detail { + +template +class const_T_base +{ + protected : + + const_T_base() + { + std::memset(&x, 0, sizeof(x)); + new (&x) T(); + } + + ~const_T_base() + { + void const * ptr = &x; + static_cast(ptr)->T::~T(); + } + + T & get() const + { + void const * ptr = &x; + return *static_cast(ptr); + } + + private : + typename ::boost::aligned_storage::value>::type x; +} ; + +template +class non_const_T_base +{ + protected : + + non_const_T_base() + { + std::memset(&x, 0, sizeof(x)); + new (&x) T(); + } + + ~non_const_T_base() + { + void * ptr = &x; + static_cast(ptr)->T::~T(); + } + + T & get() const + { + void * ptr = &x; + return *static_cast(ptr); + } + + private : + mutable typename ::boost::aligned_storage::value>::type x; +} ; + +#ifdef BOOST_MSVC +// Restores the state of warning C4345. +#pragma warning(pop) +#endif + +#else + namespace boost { namespace vinit_detail { @@ -23,20 +116,26 @@ class const_T_base protected : const_T_base() : x() {} + T & get() const { return x; } + private : T x ; } ; template -struct non_const_T_base +class non_const_T_base { protected : non_const_T_base() : x() {} + T & get() const { return x; } + private : mutable T x ; } ; +#endif + template struct select_base { @@ -57,9 +156,9 @@ class value_initialized : private vinit_detail::select_base::type value_initialized() {} - operator T&() const { return this->x ; } + operator T&() const { return this->get(); } - T& data() const { return this->x ; } + T& data() const { return this->get(); } } ; diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index d5ecaa0..f30154c 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -33,4 +33,6 @@ test-suite utility [ compile-fail ../value_init_test_fail1.cpp ] [ compile-fail ../value_init_test_fail2.cpp ] [ compile-fail ../value_init_test_fail3.cpp ] + [ run ../verify_test.cpp ] ; + diff --git a/value_init_test.cpp b/value_init_test.cpp index fe73cc1..6bca270 100644 --- a/value_init_test.cpp +++ b/value_init_test.cpp @@ -60,6 +60,20 @@ struct NonPOD : NonPODBase std::string id ; } ; +// +// Sample aggregate POD struct type +// +struct AggregatePODStruct +{ + float f; + char c; + int i; +}; + +bool operator == ( AggregatePODStruct const& lhs, AggregatePODStruct const& rhs ) +{ return lhs.f == rhs.f && lhs.c == rhs.c && lhs.i == rhs.i ; } + + template void test ( T const& y, T const& z ) { @@ -95,6 +109,13 @@ int test_main(int, char **) test( POD(0,0,0.0), POD('a',1234,56.78) ) ; test( NonPOD( std::string() ), NonPOD( std::string("something") ) ) ; + NonPOD NonPOD_object( std::string("NonPOD_object") ); + test( 0, &NonPOD_object ) ; + + AggregatePODStruct zeroInitializedAggregatePODStruct = { 0.0f, '\0', 0 }; + AggregatePODStruct nonZeroInitializedAggregatePODStruct = { 1.25f, 'a', -1 }; + test(zeroInitializedAggregatePODStruct, nonZeroInitializedAggregatePODStruct); + return 0; } diff --git a/verify_test.cpp b/verify_test.cpp new file mode 100644 index 0000000..3481636 --- /dev/null +++ b/verify_test.cpp @@ -0,0 +1,126 @@ +// +// verify_test.cpp - a test for BOOST_VERIFY +// +// Copyright (c) 2002 Peter Dimov and Multi Media Ltd. +// Copyright (c) 2007 Peter Dimov +// +// 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) +// + +#include + +#include + +int f( int & x ) +{ + return ++x; +} + +void test_default() +{ + int x = 1; + + BOOST_VERIFY( 1 ); + BOOST_VERIFY( x == 1 ); + BOOST_VERIFY( ++x ); + BOOST_VERIFY( f(x) ); + BOOST_VERIFY( &x ); + + BOOST_TEST( x == 3 ); +} + +#define BOOST_DISABLE_ASSERTS +#include + +void test_disabled() +{ + int x = 1; + + BOOST_VERIFY( 1 ); + BOOST_VERIFY( x == 1 ); + BOOST_VERIFY( ++x ); + BOOST_VERIFY( f(x) ); + BOOST_VERIFY( &x ); + + BOOST_TEST( x == 3 ); + + BOOST_VERIFY( 0 ); + BOOST_VERIFY( !x ); + BOOST_VERIFY( x == 0 ); + BOOST_VERIFY( !++x ); + BOOST_VERIFY( !f(x) ); + + BOOST_TEST( x == 5 ); + + void * p = 0; + BOOST_VERIFY( p ); +} + +#undef BOOST_DISABLE_ASSERTS + +#define BOOST_ENABLE_ASSERT_HANDLER +#include +#include +#include + +int handler_invoked = 0; + +void boost::assertion_failed(char const * expr, char const * function, char const * file, long line) +{ +#if !defined(BOOST_NO_STDC_NAMESPACE) + using std::printf; +#endif + + printf("Expression: %s\nFunction: %s\nFile: %s\nLine: %ld\n\n", expr, function, file, line); + ++handler_invoked; +} + +struct X +{ + static bool f() + { + BOOST_VERIFY( 0 ); + return false; + } +}; + +void test_handler() +{ + int x = 1; + + BOOST_VERIFY( 1 ); + BOOST_VERIFY( x == 1 ); + BOOST_VERIFY( ++x ); + BOOST_VERIFY( f(x) ); + BOOST_VERIFY( &x ); + + BOOST_TEST( x == 3 ); + + BOOST_VERIFY( 0 ); + BOOST_VERIFY( !x ); + BOOST_VERIFY( x == 0 ); + BOOST_VERIFY( !++x ); + BOOST_VERIFY( !f(x) ); + + BOOST_TEST( x == 5 ); + + void * p = 0; + BOOST_VERIFY( p ); + + BOOST_VERIFY( X::f() ); + + BOOST_TEST( handler_invoked == 8 ); +} + +#undef BOOST_ENABLE_ASSERT_HANDLER + +int main() +{ + test_default(); + test_disabled(); + test_handler(); + + return boost::report_errors(); +}