diff --git a/example/cline90/stack.cpp b/example/cline90/stack.cpp index 69de81c..b4ca860 100644 --- a/example/cline90/stack.cpp +++ b/example/cline90/stack.cpp @@ -1,7 +1,6 @@ //[cline90_stack #include -#include #include template @@ -15,12 +14,10 @@ public: // NOTE: Incomplete contract assertions, addressing only `empty` and `full`. - static void stack_precondition(int const& capacity) { - BOOST_CONTRACT_ASSERT(capacity >= 0); - } explicit stack(int capacity) : - boost::contract::constructor_precondition(boost::bind( - &stack::stack_precondition, boost::cref(capacity))), + boost::contract::constructor_precondition([&] { + BOOST_CONTRACT_ASSERT(capacity >= 0); + }), data_(new T[capacity]), capacity_(capacity), size_(0) { auto c = boost::contract::constructor(this) diff --git a/example/cline90/vector.hpp b/example/cline90/vector.hpp index 409d21d..5d7d3c6 100644 --- a/example/cline90/vector.hpp +++ b/example/cline90/vector.hpp @@ -4,7 +4,6 @@ #define VECTOR_HPP_ #include -#include template class vector @@ -21,12 +20,10 @@ public: BOOST_CONTRACT_ASSERT(size() >= 0); } - static void vector_precondition(int const& count) { - BOOST_CONTRACT_ASSERT(count >= 0); - } explicit vector(int count = 10) : - boost::contract::constructor_precondition(boost::bind( - &vector::vector_precondition, boost::cref(count))), + boost::contract::constructor_precondition([&] { + BOOST_CONTRACT_ASSERT(count >= 0); + }), data_(new T[count]), size_(count) { diff --git a/example/cline90/vstack.cpp b/example/cline90/vstack.cpp index ad10af7..5589187 100644 --- a/example/cline90/vstack.cpp +++ b/example/cline90/vstack.cpp @@ -139,12 +139,10 @@ public: BOOST_CONTRACT_ASSERT(length() < capacity()); } - static void vstack_precondition(int const& count) { - BOOST_CONTRACT_ASSERT(count >= 0); - } explicit vstack(int count = 10) : - boost::contract::constructor_precondition(boost::bind( - &vstack::vstack_precondition, boost::cref(count))), + boost::contract::constructor_precondition([&] { + BOOST_CONTRACT_ASSERT(count >= 0); + }), vect_(count), // OK, executed after precondition so count >= 0. len_(0) { diff --git a/example/features/no_lambdas.cpp b/example/features/no_lambdas.cpp index a3d14d8..3c064cd 100644 --- a/example/features/no_lambdas.cpp +++ b/example/features/no_lambdas.cpp @@ -1,5 +1,6 @@ #include "separate_body.hpp" +#include //[no_lambdas_cpp template diff --git a/example/features/no_lambdas.hpp b/example/features/no_lambdas.hpp index 494171d..eb1c777 100644 --- a/example/features/no_lambdas.hpp +++ b/example/features/no_lambdas.hpp @@ -7,13 +7,14 @@ class array : private boost::contract::constructor_precondition > { public: - void invariant() const { - BOOST_CONTRACT_ASSERT(size() <= MaxSize); - } static void static_invariant() const { BOOST_CONTRACT_ASSERT(instances() >= 0); } + void invariant() const { + BOOST_CONTRACT_ASSERT(size() <= MaxSize); + } + explicit array(std::size_t count); static void constructor_precondition(std::size_t const& count) { BOOST_CONTRACT_ASSERT(count <= MaxSize) diff --git a/example/meyer97/stack4.hpp b/example/meyer97/stack4.hpp index 4ca7ada..a187fa5 100644 --- a/example/meyer97/stack4.hpp +++ b/example/meyer97/stack4.hpp @@ -5,7 +5,6 @@ #define STACK4_HPP_ #include -#include // Dispenser with LIFO access policy and fixed max capacity. template @@ -26,12 +25,11 @@ public: /* Initialization */ // Allocate static from a maximum of n items. - static void stack4_precondition(int const& n) { - // Its own func. for MSVC 2010 bug with lambdas in template init. list. - BOOST_CONTRACT_ASSERT(n >= 0); // Non-negative capacity. - } - explicit stack4(int n) : boost::contract::constructor_precondition( - boost::bind(&stack4::stack4_precondition, boost::cref(n))) { + explicit stack4(int n) : + boost::contract::constructor_precondition([&] { + BOOST_CONTRACT_ASSERT(n >= 0); // Non-negative capacity. + }) + { auto c = boost::contract::constructor(this) .postcondition([&] { BOOST_CONTRACT_ASSERT(capacity() == n); // Capacity set. diff --git a/example/mitchell02/courier.cpp b/example/mitchell02/courier.cpp index 01955d0..368e8d1 100644 --- a/example/mitchell02/courier.cpp +++ b/example/mitchell02/courier.cpp @@ -32,16 +32,16 @@ public: typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { - // Above min. insurance. - BOOST_CONTRACT_ASSERT(insurance_cover_usd() >= min_insurance_usd); - } - static void static_invariant() { // Positive min. insurance. BOOST_CONTRACT_ASSERT(min_insurance_usd >= 0.0); } + void invariant() const { + // Above min. insurance. + BOOST_CONTRACT_ASSERT(insurance_cover_usd() >= min_insurance_usd); + } + static double min_insurance_usd; /* Creation */ @@ -113,15 +113,15 @@ public: typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; // Subcontracting. #undef BASES - void invariant() const { - // Above different insurance value. - BOOST_CONTRACT_ASSERT(insurance_cover_usd() >= different_insurance_usd); - } - static void static_invariant() { BOOST_CONTRACT_ASSERT( // Better insurance amount. different_insurance_usd >= courier::min_insurance_usd); } + + void invariant() const { + // Above different insurance value. + BOOST_CONTRACT_ASSERT(insurance_cover_usd() >= different_insurance_usd); + } static double different_insurance_usd; diff --git a/example/mitchell02/simple_queue.cpp b/example/mitchell02/simple_queue.cpp index bbc649f..07cc4f6 100644 --- a/example/mitchell02/simple_queue.cpp +++ b/example/mitchell02/simple_queue.cpp @@ -1,7 +1,6 @@ //[mitchell02_simple_queue #include -#include #include #include #include @@ -28,15 +27,10 @@ public: /* Creation */ // Create empty queue. - static void simple_queue_precondition(int const& _capacity) { - BOOST_CONTRACT_ASSERT(_capacity > 0); // Positive capacity. - } explicit simple_queue(int _capacity) : - boost::contract::constructor_precondition( - boost::bind(&simple_queue::simple_queue_precondition, - boost::cref(_capacity) - ) - ) + boost::contract::constructor_precondition([&] { + BOOST_CONTRACT_ASSERT(_capacity > 0); // Positive capacity. + }) { auto c = boost::contract::constructor(this) .postcondition([&] { diff --git a/example/stroustrup97/string.cpp b/example/stroustrup97/string.cpp index 609e608..d8e720f 100644 --- a/example/stroustrup97/string.cpp +++ b/example/stroustrup97/string.cpp @@ -1,7 +1,6 @@ //[stroustrup97_string #include -#include #include #include #include @@ -37,13 +36,11 @@ public: if(chars_[size_] != '\0') throw invariant_error(); } - static void string_precondition(char const* const chars) { - if(!chars) throw string::null_error(); - if(strlen(chars) > too_large) throw too_large_error(); - } /* implicit */ string(char const* chars) : - boost::contract::constructor_precondition( - boost::bind(&string_precondition, chars)) + boost::contract::constructor_precondition([&] { + if(!chars) throw string::null_error(); + if(strlen(chars) > too_large) throw too_large_error(); + }) { auto c = boost::contract::constructor(this); // Check invariants. init(chars); diff --git a/include/boost/contract.hpp b/include/boost/contract.hpp index 073b1f1..2106fc4 100644 --- a/include/boost/contract.hpp +++ b/include/boost/contract.hpp @@ -20,7 +20,7 @@ // TODO: What shall I do with unions? Can/shall I contract them? Double check which members C++11 unions can have (ctor, dtor, etc?). -// TODO: Using MSVC 2013 (instead of MSVC 2010) I should be able to use lambdas also in ctor template member inits for all tests and examples. Also add a note a bout this MSVC 2010 bug in the docs. +// TODO: Document that there is a MSVC 2010 bug for which lambdas cannot be used in template constructor intialization list (this was fixed in MSVC 2013). Therefore, an external (static member) function must be used (possibly with bind and cref) to program constructor preconditions on MSVC 2010 instead of using lambdas. // TODO: Test failure handlers, throw on contract failure, and throw user-defined exceptions: (1) Add a test for throwing exception handlers (somewhat similar to stroustrup97/string.cpp but more comprehensive); (2) Test what happens if bodies throw (e.g., public function should still check inv, dtor too, but ctor should not, etc.)... test all contract types when bodies throw; (3) Test what happens if old expression copies throw (with OLDOF and with .old()). @@ -30,8 +30,6 @@ // TODO: Test overloading for all contract types. Also test subcontracting of overloaded virtual functions (overload both overridden and overriding functions). -// TODO: Test no static inv / const inv / volatile inv are checked when static_inv() / inv() const / inv() const volatile functions are not declared (for ctor, dtor, and public functions). - // TODO: Test what this lib does when derived public function overrides base's protected virtual function (substitution principle does not apply here because base's protected virtual functions cannot be called by users so it should not be subcontracted...). // TODO: Test with function and array argument types like `void f(int x[2][3], int (*g)(int))`. This should work... but it might require to specialize some of this lib's internal templates... diff --git a/include/boost/contract/aux_/condition/check_pre_post_inv.hpp b/include/boost/contract/aux_/condition/check_pre_post_inv.hpp index c18096b..1ddb639 100644 --- a/include/boost/contract/aux_/condition/check_pre_post_inv.hpp +++ b/include/boost/contract/aux_/condition/check_pre_post_inv.hpp @@ -7,8 +7,13 @@ #include #include /** @cond */ -#include -#include +#include +#include +#include +#include +#include +#include +#include /** @endcond */ namespace boost { namespace contract { namespace aux { @@ -16,6 +21,52 @@ namespace boost { namespace contract { namespace aux { template class check_pre_post_inv : public check_pre_post { // Copyable (as *). public: +#ifndef BOOST_CONTRACT_CONFIG_PERMISSIVE + BOOST_STATIC_ASSERT_MSG( + !boost::contract::access::has_static_invariant_f >::value, + "static invariant member function cannot be mutable " + "(it must be static instead)" + ); + BOOST_STATIC_ASSERT_MSG( + !boost::contract::access::has_static_invariant_f, boost::function_types::const_non_volatile>::value, + "static invariant member function cannot be const qualified " + "(it must be static instead)" + ); + BOOST_STATIC_ASSERT_MSG( + !boost::contract::access::has_static_invariant_f, boost::function_types::volatile_non_const>::value, + "static invariant member function cannot be volatile qualified " + "(it must be static instead)" + ); + BOOST_STATIC_ASSERT_MSG( + !boost::contract::access::has_static_invariant_f, boost::function_types::cv_qualified>::value, + "static invariant member function cannot be const volatile qualified " + "(it must be static instead)" + ); + + BOOST_STATIC_ASSERT_MSG( + !boost::contract::access::has_invariant_s >::value, + "non-static invariant member function cannot be static " + "(it must be either const or const volatile qualified instead)" + ); + BOOST_STATIC_ASSERT_MSG( + !boost::contract::access::has_invariant_f, boost::function_types::non_cv>::value, + "non-static invariant member function cannot be mutable " + "(it must be either const or const volatile qualified instead)" + ); + BOOST_STATIC_ASSERT_MSG( + !boost::contract::access::has_invariant_f, boost::function_types::volatile_non_const>::value, + "non-static invariant member function cannot be volatile qualified " + "(it must be const or const volatile qualified instead)" + ); +#endif + // obj can be 0 for static member functions. explicit check_pre_post_inv(boost::contract::from from, C* obj) : check_pre_post(from), obj_(obj) {} @@ -34,11 +85,13 @@ protected: private: void check_inv(bool on_entry, bool static_inv_only) { try { - check_static_inv(on_entry, boost::mpl::bool_::value>()); + // Static members only check static inv. + check_static_inv(); if(!static_inv_only) { - check_const_inv(on_entry, boost::mpl::bool_::value>()); + // Volatile (const or not) members check static and cv inv. + check_cv_inv(); + // Other members (const or not) check static, cv, and const. + check_const_inv(); } } catch(...) { if(on_entry) boost::contract::entry_invariant_failed(from()); @@ -46,17 +99,45 @@ private: } } - void check_static_inv(bool, boost::mpl::false_ const&) {} - void check_static_inv(bool on_entry, boost::mpl::true_ const&) { - boost::contract::access::static_invariant(); - } - - void check_const_inv(bool, boost::mpl::false_ const&) {} - void check_const_inv(bool on_entry, boost::mpl::true_ const&) { - boost::contract::access::const_invariant(obj_); - } - // TODO: Add support for volatile member functions and class invariants. + template + typename boost::enable_if< + boost::contract::access::has_static_invariant >::type + check_static_inv() { boost::contract::access::static_invariant(); } + + template + typename boost::disable_if< + boost::contract::access::has_static_invariant >::type + check_static_inv() {} + + + template + typename boost::enable_if< + boost::contract::access::has_cv_invariant >::type + check_cv_inv() { boost::contract::access::cv_invariant(obj_); } + + template + typename boost::disable_if< + boost::contract::access::has_cv_invariant >::type + check_cv_inv() {} + + template + struct call_const_inv : + boost::mpl::and_< + boost::contract::access::has_const_invariant, + // Volatile (like const) cannot be stripped so [const] volatile + // members only check cv invariant, and cannot check const inv. + boost::mpl::not_ > + > + {}; + + template + typename boost::enable_if >::type + check_const_inv() { boost::contract::access::const_invariant(obj_); } + + template + typename boost::disable_if >::type + check_const_inv() {} C* obj_; }; diff --git a/include/boost/contract/aux_/condition/check_subcontracted_pre_post_inv.hpp b/include/boost/contract/aux_/condition/check_subcontracted_pre_post_inv.hpp index d458cd2..cec583e 100644 --- a/include/boost/contract/aux_/condition/check_subcontracted_pre_post_inv.hpp +++ b/include/boost/contract/aux_/condition/check_subcontracted_pre_post_inv.hpp @@ -100,8 +100,11 @@ class check_subcontracted_pre_post_inv : // Copyable (as * and &). >::type overridden_bases; #ifndef BOOST_CONTRACT_CONFIG_PERMISSIVE - BOOST_STATIC_ASSERT_MSG(boost::mpl::or_, - boost::mpl::not_ > >::value, + BOOST_STATIC_ASSERT_MSG( + boost::mpl::or_< + boost::is_same, + boost::mpl::not_ > + >::value, "subcontracting function specified as 'override' but does not " "override any contracted member function" ); @@ -232,14 +235,12 @@ private: } template - typename boost::enable_if >::type check_post_r( - Result const& r) { - this->check_post(r); - } + typename boost::enable_if >::type + check_post_r(Result const& r) { this->check_post(r); } template - typename boost::disable_if >::type check_post_r( - Result const& r) { + typename boost::disable_if >::type + check_post_r(Result const& r) { BOOST_CONTRACT_AUX_DEBUG(r); this->check_post(*r); } diff --git a/include/boost/contract/core/access.hpp b/include/boost/contract/core/access.hpp index 7fa00f3..c3893be 100644 --- a/include/boost/contract/core/access.hpp +++ b/include/boost/contract/core/access.hpp @@ -45,53 +45,48 @@ class access { struct base_types_of { typedef typename C::BOOST_CONTRACT_CONFIG_BASE_TYPES type; }; - - BOOST_CONTRACT_AUX_INTROSPECTION_HAS_MEMBER_FUNCTION( - has_invariant_func, BOOST_CONTRACT_CONFIG_INVARIANT) BOOST_CONTRACT_AUX_INTROSPECTION_HAS_MEMBER_FUNCTION( - has_non_static_invariant_func, - BOOST_CONTRACT_CONFIG_STATIC_INVARIANT - ) - + has_static_invariant_f, BOOST_CONTRACT_CONFIG_STATIC_INVARIANT) + BOOST_CONTRACT_AUX_INTROSPECTION_HAS_STATIC_MEMBER_FUNCTION( - has_static_invariant_func, BOOST_CONTRACT_CONFIG_STATIC_INVARIANT) + has_static_invariant_s, BOOST_CONTRACT_CONFIG_STATIC_INVARIANT) - // TODO: Unless PERMISSIVE, enforce: !has_invariant || has_const_invariant || has_const_volatile_invariant - - template - struct has_const_invariant : has_invariant_func, boost::function_types::const_non_volatile> {}; - - template - struct has_const_volatile_invariant : has_invariant_func, boost::function_types::cv_qualified> {}; - - template - struct has_invariant : has_invariant_func + struct has_static_invariant : has_static_invariant_s > {}; - // TODO: Unless PERMISSIVE, enforce: !has_non_static_invariant - - template - struct has_static_invariant : has_static_invariant_func > {}; - - template - struct has_non_static_invariant : has_non_static_invariant_func > {}; - - template + template static void static_invariant() { C::BOOST_CONTRACT_CONFIG_STATIC_INVARIANT(); } - template + BOOST_CONTRACT_AUX_INTROSPECTION_HAS_MEMBER_FUNCTION( + has_invariant_f, BOOST_CONTRACT_CONFIG_INVARIANT) + + BOOST_CONTRACT_AUX_INTROSPECTION_HAS_STATIC_MEMBER_FUNCTION( + has_invariant_s, BOOST_CONTRACT_CONFIG_INVARIANT) + + template + struct has_cv_invariant : has_invariant_f, + boost::function_types::cv_qualified> {}; + + template + struct has_const_invariant : has_invariant_f, + boost::function_types::const_qualified> {}; + + template + static void cv_invariant(C const volatile* obj) { + BOOST_CONTRACT_AUX_DEBUG(obj); + obj->BOOST_CONTRACT_CONFIG_INVARIANT(); + } + + template static void const_invariant(C const* obj) { BOOST_CONTRACT_AUX_DEBUG(obj); obj->BOOST_CONTRACT_CONFIG_INVARIANT(); } - + // Friendship used to limit library's public API. template diff --git a/include/boost/contract/core/config.hpp b/include/boost/contract/core/config.hpp index afb04f0..b3ce293 100644 --- a/include/boost/contract/core/config.hpp +++ b/include/boost/contract/core/config.hpp @@ -35,7 +35,6 @@ #endif // BOOST_CONTRACT_CONFIG_PERMISSING (#undef by default). -// TODO: Implement following static errors (unless PERMISSIVE): (1) error if contracted class has `invariant` or `invariant volatile` without `const` qualifiers; (2) error if `invariant const` but not `invariant const volatile` and there are contracts for volatile members (mistake: assume `invariant const` will be called also for volatile members); (3) error if R != result_type& && R != optional>& (mistake: C++ should warn already if overriding func has different result type (but maybe not if it's a covariant type, in which case the lib's cast on v' void* result_ will probably segfault? test it...). #endif // #include guard diff --git a/include/boost/contract/core/virtual.hpp b/include/boost/contract/core/virtual.hpp index 3c2e2d0..25e6aa8 100644 --- a/include/boost/contract/core/virtual.hpp +++ b/include/boost/contract/core/virtual.hpp @@ -10,8 +10,6 @@ #include /** @endcond */ -// TODO: Always program static_inv before inv in tests, examples, etc (because that is the order they are checked). - namespace boost { namespace contract { namespace aux { diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 7be5eed..41159b0 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -3,13 +3,33 @@ test-suite constructor : [ subdir-run constructor : bases ] [ subdir-run constructor : body_throw ] [ subdir-run constructor : access ] - [ subdir-compile-fail constructor : no_pre_error ] + + [ subdir-compile-fail constructor : pre_error ] ; test-suite destructor : [ subdir-run destructor : bases ] [ subdir-run destructor : body_throw ] - [ subdir-compile-fail destructor : no_pre_error ] + [ subdir-run destructor : access ] + + [ subdir-compile-fail destructor : pre_error ] +; + +test-suite public_function : + [ subdir-run public_function : bases ] + [ subdir-run public_function : bases_pre ] + [ subdir-run public_function : bases_virtual ] + [ subdir-run public_function : bases_branch ] + [ subdir-run public_function : bases_sparse ] + + [ subdir-run public_function : body_throw ] + [ subdir-run public_function : access ] + + [ subdir-run public_function : static ] + [ subdir-run public_function : static_body_throw ] + + [ subdir-compile-fail public_function : override_error ] + [ subdir-run public_function : override_permissive ] ; test-suite function : @@ -17,32 +37,50 @@ test-suite function : [ subdir-run function : body_throw ] ; -test-suite public_function : - [ subdir-run public_function : bases ] - [ subdir-run public_function : bases_virtual ] - [ subdir-run public_function : bases_branch ] - [ subdir-run public_function : bases_sparse ] - [ subdir-run public_function : body_throw ] - [ subdir-run public_function : static ] - [ subdir-run public_function : static_body_throw ] - [ subdir-run public_function : access ] - [ subdir-compile-fail public_function : override_error ] - [ subdir-run public_function : override_permissive ] +test-suite invariant : + [ subdir-run invariant : all_static_cv_const ] + [ subdir-run invariant : both_static_cv ] + [ subdir-run invariant : both_cv_const ] + [ subdir-run invariant : both_static_const ] + [ subdir-run invariant : only_static ] + [ subdir-run invariant : only_cv ] + [ subdir-run invariant : only_const ] + [ subdir-run invariant : no_inv ] + + [ subdir-compile-fail invariant : static_inv_mutable_error ] + [ subdir-run invariant : static_inv_mutable_permissive ] + [ subdir-compile-fail invariant : static_inv_const_error ] + [ subdir-run invariant : static_inv_const_permissive ] + [ subdir-compile-fail invariant : static_inv_volatile_error ] + [ subdir-run invariant : static_inv_volatile_permissive ] + [ subdir-compile-fail invariant : static_inv_cv_error ] + [ subdir-run invariant : static_inv_cv_permissive ] + + [ subdir-compile-fail invariant : inv_static_error ] + [ subdir-run invariant : inv_static_permissive ] + [ subdir-compile-fail invariant : inv_mutable_error ] + [ subdir-run invariant : inv_mutable_permissive ] + [ subdir-compile-fail invariant : inv_volatile_error ] + [ subdir-run invariant : inv_volatile_permissive ] ; test-suite result : [ subdir-run result : mixed_optional ] [ subdir-run result : mixed_optional_ref ] + [ subdir-compile-fail result : type_mismatch_error ] ; test-suite old : - [ subdir-run old : no_macros ] [ subdir-run old : auto ] - [ subdir-run old : no_equal ] - [ subdir-run old : noncopyable ] + + [ subdir-run old : no_macros ] [ subdir-compile-fail old : no_make_old_error ] + + [ subdir-run old : noncopyable ] [ subdir-compile-fail old : noncopyable_error ] + + [ subdir-run old : no_equal ] [ subdir-compile-fail old : no_equal_error ] ; @@ -51,14 +89,15 @@ test-suite disable : ; test-suite set : - [ subdir-run set : nothing ] - [ subdir-run set : only_pre ] - [ subdir-run set : only_old ] - [ subdir-run set : only_post ] + [ subdir-run set : all_pre_old_post ] [ subdir-run set : both_pre_old ] [ subdir-run set : both_old_post ] [ subdir-run set : both_pre_post ] - [ subdir-run set : all_pre_old_post ] + [ subdir-run set : only_pre ] + [ subdir-run set : only_old ] + [ subdir-run set : only_post ] + [ subdir-run set : nothing ] + [ subdir-compile-fail set : old_pre_error ] [ subdir-compile-fail set : post_old_error ] [ subdir-compile-fail set : post_pre_error ] @@ -67,8 +106,10 @@ test-suite set : test-suite call_if : [ subdir-run call_if : true_ ] [ subdir-run call_if : false_ ] + [ subdir-run call_if : true_void ] [ subdir-run call_if : false_void ] + [ subdir-run call_if : equal_to ] ; diff --git a/test/constructor/bases.cpp b/test/constructor/bases.cpp index 0656806..02275da 100644 --- a/test/constructor/bases.cpp +++ b/test/constructor/bases.cpp @@ -23,14 +23,15 @@ struct t typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { - out << Id << "::inv" << std::endl; - BOOST_CONTRACT_ASSERT(k_ < 0); - } static void static_invariant() { out << Id << "::static_inv" << std::endl; BOOST_CONTRACT_ASSERT(l.value >= 0); } + + void invariant() const { + out << Id << "::inv" << std::endl; + BOOST_CONTRACT_ASSERT(k_ < 0); + } struct l_tag; typedef boost::contract::aux::test::counter l_type; @@ -84,15 +85,16 @@ struct c typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { - out << "c::inv" << std::endl; - BOOST_CONTRACT_ASSERT(j_ < 0); - } static void static_invariant() { out << "c::static_inv" << std::endl; BOOST_CONTRACT_ASSERT(m.value >= 0); } + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(j_ < 0); + } + struct m_tag; typedef boost::contract::aux::test::counter m_type; static m_type m; @@ -143,8 +145,8 @@ struct b typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "b::inv" << std::endl; } static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } explicit b() {} // No contract. virtual ~b() {} @@ -159,15 +161,16 @@ struct a typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { - out << "a::inv" << std::endl; - BOOST_CONTRACT_ASSERT(i_ < 0); - } static void static_invariant() { out << "a::static_inv" << std::endl; BOOST_CONTRACT_ASSERT(n.value >= 0); } + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } + struct n_tag; typedef boost::contract::aux::test::counter n_type; static n_type n; diff --git a/test/constructor/body_throw.cpp b/test/constructor/body_throw.cpp index 5ffced3..c86b1c4 100644 --- a/test/constructor/body_throw.cpp +++ b/test/constructor/body_throw.cpp @@ -17,8 +17,8 @@ struct c typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "c::inv" << std::endl; } static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } c() : boost::contract::constructor_precondition([&] { @@ -41,8 +41,8 @@ struct b typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "b::inv" << std::endl; } static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } struct e {}; @@ -67,8 +67,8 @@ struct a typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "a::inv" << std::endl; } static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } a() : boost::contract::constructor_precondition([&] { diff --git a/test/constructor/no_pre_error.cpp b/test/constructor/pre_error.cpp similarity index 100% rename from test/constructor/no_pre_error.cpp rename to test/constructor/pre_error.cpp diff --git a/test/destructor/access.cpp b/test/destructor/access.cpp new file mode 100644 index 0000000..0e99a38 --- /dev/null +++ b/test/destructor/access.cpp @@ -0,0 +1,93 @@ + +// Test making all contract extra declarations (base types, inv, etc.) private. + +#include "../aux_/oteststream.hpp" +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +class b { + friend class boost::contract::access; + + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + +public: + virtual ~b() { + boost::contract::guard c = boost::contract::destructor(this) + .old([] { out << "b::dtor::old" << std::endl; }) + .postcondition([] { out << "b::dtor::post" << std::endl; }) + ; + out << "b::dtor::body" << std::endl; + } +}; + +class a + #define BASES public b + : BASES +{ + friend class boost::contract::access; + + // Private base types (always OK because never used by dtors). + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + // Private invariants. + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + +public: + virtual ~a() { + boost::contract::guard c = boost::contract::destructor(this) + .old([] { out << "a::dtor::old" << std::endl; }) + .postcondition([] { out << "a::dtor::post" << std::endl; }) + ; + out << "a::dtor::body" << std::endl; + } +}; + +int main() { + std::ostringstream ok; + + { + a aa; + out.str(""); + } // Call aa's destructor. + ok.str(""); ok + << "a::static_inv" << std::endl + << "a::inv" << std::endl + << "a::dtor::old" << std::endl + << "a::dtor::body" << std::endl + << "a::static_inv" << std::endl + << "a::dtor::post" << std::endl + + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "b::dtor::old" << std::endl + << "b::dtor::body" << std::endl + << "b::static_inv" << std::endl + << "b::dtor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + { + b bb; + out.str(""); + } // Call bb's destructor. + ok.str(""); ok + << "b::static_inv" << std::endl + << "b::inv" << std::endl + << "b::dtor::old" << std::endl + << "b::dtor::body" << std::endl + << "b::static_inv" << std::endl + << "b::dtor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/destructor/bases.cpp b/test/destructor/bases.cpp index a93dae0..f57861a 100644 --- a/test/destructor/bases.cpp +++ b/test/destructor/bases.cpp @@ -15,14 +15,15 @@ boost::contract::aux::test::oteststream out; template struct t { - void invariant() const { - out << Id << "::inv" << std::endl; - BOOST_CONTRACT_ASSERT(k_ < 0); - } static void static_invariant() { out << Id << "::static_inv" << std::endl; BOOST_CONTRACT_ASSERT(l.value >= 0); } + + void invariant() const { + out << Id << "::inv" << std::endl; + BOOST_CONTRACT_ASSERT(k_ < 0); + } struct l_tag; typedef boost::contract::aux::test::counter l_type; @@ -62,15 +63,16 @@ struct c typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { - out << "c::inv" << std::endl; - BOOST_CONTRACT_ASSERT(j_ < 0); - } static void static_invariant() { out << "c::static_inv" << std::endl; BOOST_CONTRACT_ASSERT(m.value >= 0); } + void invariant() const { + out << "c::inv" << std::endl; + BOOST_CONTRACT_ASSERT(j_ < 0); + } + struct m_tag; typedef boost::contract::aux::test::counter m_type; static m_type m; @@ -101,8 +103,8 @@ c::m_type c::m; // Test not (fully) contracted base is not part of destructor subcontracting. struct b { - void invariant() const { out << "b::inv" << std::endl; } static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } explicit b() {} virtual ~b() {} // No contract. @@ -116,14 +118,15 @@ struct a typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { - out << "a::inv" << std::endl; - BOOST_CONTRACT_ASSERT(i_ < 0); - } static void static_invariant() { out << "a::static_inv" << std::endl; BOOST_CONTRACT_ASSERT(n.value >= 0); } + + void invariant() const { + out << "a::inv" << std::endl; + BOOST_CONTRACT_ASSERT(i_ < 0); + } struct n_tag; typedef boost::contract::aux::test::counter n_type; diff --git a/test/destructor/body_throw.cpp b/test/destructor/body_throw.cpp index 27ecdcb..c1afdba 100644 --- a/test/destructor/body_throw.cpp +++ b/test/destructor/body_throw.cpp @@ -14,8 +14,8 @@ boost::contract::aux::test::oteststream out; struct c { - void invariant() const { out << "c::inv" << std::endl; } static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } ~c() { boost::contract::guard c = boost::contract::destructor(this) @@ -34,8 +34,8 @@ struct b typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "b::inv" << std::endl; } static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } struct e {}; @@ -56,8 +56,8 @@ struct a typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "a::inv" << std::endl; } static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } ~a() { boost::contract::guard c = boost::contract::destructor(this) diff --git a/test/destructor/no_pre_error.cpp b/test/destructor/pre_error.cpp similarity index 100% rename from test/destructor/no_pre_error.cpp rename to test/destructor/pre_error.cpp diff --git a/test/disable/checking.cpp b/test/disable/checking.cpp index d58f9d6..b8548a7 100644 --- a/test/disable/checking.cpp +++ b/test/disable/checking.cpp @@ -13,8 +13,8 @@ boost::contract::aux::test::oteststream out; struct a { - void invariant() const { out << "a::inv" << std::endl; } static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } struct x_tag; typedef boost::contract::aux::test::counter x_type; @@ -46,8 +46,8 @@ bool call_f() { } struct b { - void invariant() const { out << "b::inv" << std::endl; } static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } void g() { boost::contract::guard c = boost::contract::public_function(this) diff --git a/test/invariant/all_static_cv_const.cpp b/test/invariant/all_static_cv_const.cpp new file mode 100644 index 0000000..188097b --- /dev/null +++ b/test/invariant/all_static_cv_const.cpp @@ -0,0 +1,8 @@ + +// Test all invariants (static, cv, and const-only). + +#define BOOST_CONTRACT_AUX_TEST_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_CV_INV +#define BOOST_CONTRACT_AUX_TEST_CONST_INV +#include "combinations.i" + diff --git a/test/invariant/both_cv_const.cpp b/test/invariant/both_cv_const.cpp new file mode 100644 index 0000000..a566dff --- /dev/null +++ b/test/invariant/both_cv_const.cpp @@ -0,0 +1,8 @@ + +// Test all invariants (static, cv, and const-only). + +#undef BOOST_CONTRACT_AUX_TEST_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_CV_INV +#define BOOST_CONTRACT_AUX_TEST_CONST_INV +#include "combinations.i" + diff --git a/test/invariant/both_static_const.cpp b/test/invariant/both_static_const.cpp new file mode 100644 index 0000000..043dfbd --- /dev/null +++ b/test/invariant/both_static_const.cpp @@ -0,0 +1,8 @@ + +// Test all invariants (static, cv, and const-only). + +#define BOOST_CONTRACT_AUX_TEST_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_CV_INV +#define BOOST_CONTRACT_AUX_TEST_CONST_INV +#include "combinations.i" + diff --git a/test/invariant/both_static_cv.cpp b/test/invariant/both_static_cv.cpp new file mode 100644 index 0000000..3458c78 --- /dev/null +++ b/test/invariant/both_static_cv.cpp @@ -0,0 +1,8 @@ + +// Test all invariants (static, cv, and const-only). + +#define BOOST_CONTRACT_AUX_TEST_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_CV_INV +#undef BOOST_CONTRACT_AUX_TEST_CONST_INV +#include "combinations.i" + diff --git a/test/invariant/combinations.i b/test/invariant/combinations.i new file mode 100644 index 0000000..ad97a3a --- /dev/null +++ b/test/invariant/combinations.i @@ -0,0 +1,655 @@ + +// Test all invariants combinations (static/cv/const-only) for all operations. + +#include "../aux_/oteststream.hpp" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +struct b : private boost::contract::constructor_precondition { + // Test also with no base_types. + +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + static void static_invariant() { out << "b::static_inv" << std::endl; } +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + void invariant() const volatile { out << "b::cv_inv" << std::endl; } +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + void invariant() const { out << "b::const_inv" << std::endl; } +#endif + + b() : boost::contract::constructor_precondition([] { + out << "b::ctor::pre" << std::endl; + }) { + boost::contract::guard c = boost::contract::constructor(this) + .old([] { out << "b::ctor::old" << std::endl; }) + .postcondition([] { out << "b::ctor::post" << std::endl; }) + ; + out << "b::ctor::body" << std::endl; + } + + virtual ~b() { + boost::contract::guard c = boost::contract::destructor(this) + .old([] { out << "b::dtor::old" << std::endl; }) + .postcondition([] { out << "b::dtor::post" << std::endl; }) + ; + out << "b::dtor::body" << std::endl; + } + + virtual void f(char x, boost::contract::virtual_* v = 0) volatile { + boost::contract::guard c = boost::contract::public_function(v, this) + .precondition([&] { + out << "b::f::volatile_pre" << std::endl; + BOOST_CONTRACT_ASSERT(x == 'b'); + }) + .old([] { out << "b::f::volatile_old" << std::endl; }) + .postcondition([] { out << "b::f::volatile_post" << std::endl; }) + ; + out << "b::f::volatile_body" << std::endl; + } + + virtual void f(char x, boost::contract::virtual_* v = 0) { + boost::contract::guard c = boost::contract::public_function(v, this) + .precondition([&] { + out << "b::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(x == 'b'); + }) + .old([] { out << "b::f::old" << std::endl; }) + .postcondition([] { out << "b::f::post" << std::endl; }) + ; + out << "b::f::body" << std::endl; + } +}; + +struct a + #define BASES private boost::contract::constructor_precondition, public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + static void static_invariant() { out << "a::static_inv" << std::endl; } +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + void invariant() const volatile { out << "a::cv_inv" << std::endl; } +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + void invariant() const { out << "a::const_inv" << std::endl; } +#endif + + a() : boost::contract::constructor_precondition([] { + out << "a::ctor::pre" << std::endl; + }) { + boost::contract::guard c = boost::contract::constructor(this) + .old([] { out << "a::ctor::old" << std::endl; }) + .postcondition([] { out << "a::ctor::post" << std::endl; }) + ; + out << "a::ctor::body" << std::endl; + } + + virtual ~a() { + boost::contract::guard c = boost::contract::destructor(this) + .old([] { out << "a::dtor::old" << std::endl; }) + .postcondition([] { out << "a::dtor::post" << std::endl; }) + ; + out << "a::dtor::body" << std::endl; + } + + virtual void f(char x, boost::contract::virtual_* v = 0) + volatile /* override */ { + boost::contract::guard c = boost::contract::public_function< + override_f>( + v, + static_cast(&a::f), + this, x + ) + .precondition([&] { + out << "a::f::volatile_pre" << std::endl; + BOOST_CONTRACT_ASSERT(x == 'a'); + }) + .old([] { out << "a::f::volatile_old" << std::endl; }) + .postcondition([] { out << "a::f::volatile_post" << std::endl; }) + ; + out << "a::f::volatile_body" << std::endl; + } + + virtual void f(char x, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::guard c = boost::contract::public_function< + override_f>( + v, + static_cast(&a::f), + this, x + ) + .precondition([&] { + out << "a::f::pre" << std::endl; + BOOST_CONTRACT_ASSERT(x == 'a'); + }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } + + static void s() { + boost::contract::guard c = boost::contract::public_function() + .precondition([] { out << "a::s::pre" << std::endl; }) + .old([] { out << "a::s::old" << std::endl; }) + .postcondition([] { out << "a::s::post" << std::endl; }) + ; + out << "a::s::body" << std::endl; + } + +protected: + void p() volatile { + boost::contract::guard c = boost::contract::function() + .precondition([] { out << "a::p::volatile_pre" << std::endl; }) + .old([] { out << "a::p::volatile_old" << std::endl; }) + .postcondition([] { out << "a::p::volatile_post" << std::endl; }) + ; + out << "a::p::volatile_body" << std::endl; + } + + void p() { + boost::contract::guard c = boost::contract::function() + .precondition([] { out << "a::p::pre" << std::endl; }) + .old([] { out << "a::p::old" << std::endl; }) + .postcondition([] { out << "a::p::post" << std::endl; }) + ; + out << "a::p::body" << std::endl; + } +public: + void call_p() volatile { p(); } + void call_p() { p(); } + +private: + void q() volatile { + boost::contract::guard c = boost::contract::function() + .precondition([] { out << "a::q::volatile_pre" << std::endl; }) + .old([] { out << "a::q::volatile_old" << std::endl; }) + .postcondition([] { out << "a::q::volatile_post" << std::endl; }) + ; + out << "a::q::volatile_body" << std::endl; + } + + void q() { + boost::contract::guard c = boost::contract::function() + .precondition([] { out << "a::q::pre" << std::endl; }) + .old([] { out << "a::q::old" << std::endl; }) + .postcondition([] { out << "a::q::post" << std::endl; }) + ; + out << "a::q::body" << std::endl; + } +public: + void call_q() volatile { q(); } + void call_q() { q(); } + + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + std::ostringstream ok; + + { // Test volatile call with bases. + out.str(""); + a volatile av; + ok.str(""); ok // Ctors always check const_inv (even if volatile). + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif + << "b::ctor::old" << std::endl + << "b::ctor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif + << "b::ctor::post" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif + << "a::ctor::old" << std::endl + << "a::ctor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "a::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "a::const_inv" << std::endl +#endif + << "a::ctor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + av.f('a'); + ok.str(""); ok // Volatile checks static and cv (but not const) inv. +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "a::cv_inv" << std::endl +#endif + << "b::f::volatile_pre" << std::endl + << "a::f::volatile_pre" << std::endl + << "b::f::volatile_old" << std::endl + << "a::f::volatile_old" << std::endl + << "a::f::volatile_body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "a::cv_inv" << std::endl +#endif + << "b::f::volatile_old" << std::endl + << "b::f::volatile_post" << std::endl + // No old call here because not a base object. + << "a::f::volatile_post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + av.s(); // Test static call. + ok.str(""); ok +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif + << "a::s::pre" << std::endl + << "a::s::old" << std::endl + << "a::s::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif + << "a::s::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + av.call_p(); // Test (indirect) protected call. + ok.str(""); ok + << "a::p::volatile_pre" << std::endl + << "a::p::volatile_old" << std::endl + << "a::p::volatile_body" << std::endl + << "a::p::volatile_post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + av.call_q(); // Test (indirect) private call. + ok.str(""); ok + << "a::q::volatile_pre" << std::endl + << "a::q::volatile_old" << std::endl + << "a::q::volatile_body" << std::endl + << "a::q::volatile_post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + } // Call a's destructor. + ok.str(""); ok // Dtors always check const_inv (even if volatile). +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "a::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "a::const_inv" << std::endl +#endif + << "a::dtor::old" << std::endl + << "a::dtor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif + << "a::dtor::post" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif + << "b::dtor::old" << std::endl + << "b::dtor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif + << "b::dtor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + { // Test non-volatile call with bases. + out.str(""); + a aa; + ok.str(""); ok + << "a::ctor::pre" << std::endl + << "b::ctor::pre" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif + << "b::ctor::old" << std::endl + << "b::ctor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif + << "b::ctor::post" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif + << "a::ctor::old" << std::endl + << "a::ctor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "a::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "a::const_inv" << std::endl +#endif + << "a::ctor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.f('a'); + ok.str(""); ok // Mutable checks static, cv, and const-only inv. +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "a::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "a::const_inv" << std::endl +#endif + << "b::f::pre" << std::endl + << "a::f::pre" << std::endl + << "b::f::old" << std::endl + << "a::f::old" << std::endl + << "a::f::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "a::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "a::const_inv" << std::endl +#endif + << "b::f::old" << std::endl + << "b::f::post" << std::endl + << "a::f::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.s(); // Test static call. + ok.str(""); ok +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif + << "a::s::pre" << std::endl + << "a::s::old" << std::endl + << "a::s::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif + << "a::s::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.call_p(); // Test (indirect) protected call. + ok.str(""); ok + << "a::p::pre" << std::endl + << "a::p::old" << std::endl + << "a::p::body" << std::endl + << "a::p::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + aa.call_q(); // Test (indirect) private call. + ok.str(""); ok + << "a::q::pre" << std::endl + << "a::q::old" << std::endl + << "a::q::body" << std::endl + << "a::q::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + } // Call a's destructor. + ok.str(""); ok +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "a::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "a::const_inv" << std::endl +#endif + << "a::dtor::old" << std::endl + << "a::dtor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "a::static_inv" << std::endl +#endif + << "a::dtor::post" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif + << "b::dtor::old" << std::endl + << "b::dtor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif + << "b::dtor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + + { // Test volatile call with no bases. + out.str(""); + b volatile bv; + ok.str(""); ok // Ctors always check const_inv (even if volatile). + << "b::ctor::pre" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif + << "b::ctor::old" << std::endl + << "b::ctor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif + << "b::ctor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + bv.f('b'); + ok.str(""); ok // Volatile checks static and cv (but not const) inv. +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif + << "b::f::volatile_pre" << std::endl + << "b::f::volatile_old" << std::endl + << "b::f::volatile_body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif + << "b::f::volatile_post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + } // Call b's destructor. + ok.str(""); ok // Dtors always check const_inv (even if volatile). +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif + << "b::dtor::old" << std::endl + << "b::dtor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif + << "b::dtor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + { // Test non-volatile call with no bases. + out.str(""); + b bb; + ok.str(""); ok + << "b::ctor::pre" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif + << "b::ctor::old" << std::endl + << "b::ctor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif + << "b::ctor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + bb.f('b'); + ok.str(""); ok // Mutable checks static, cv, and const-only inv. +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif + << "b::f::pre" << std::endl + << "b::f::old" << std::endl + << "b::f::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif + << "b::f::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + out.str(""); + } // Call b's destructor. + ok.str(""); ok +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CV_INV + << "b::cv_inv" << std::endl +#endif +#ifdef BOOST_CONTRACT_AUX_TEST_CONST_INV + << "b::const_inv" << std::endl +#endif + << "b::dtor::old" << std::endl + << "b::dtor::body" << std::endl +#ifdef BOOST_CONTRACT_AUX_TEST_STATIC_INV + << "b::static_inv" << std::endl +#endif + << "b::dtor::post" << std::endl + ; + BOOST_TEST(out.eq(ok.str())); + + return boost::report_errors(); +} + diff --git a/test/invariant/inv_mutable.i b/test/invariant/inv_mutable.i new file mode 100644 index 0000000..ff1d584 --- /dev/null +++ b/test/invariant/inv_mutable.i @@ -0,0 +1,21 @@ + +// Test error if non-static inv declared mutable (unless PERMISSIVE #defined). + +#include +#include + +struct a { + void invariant() {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::guard c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +}; + diff --git a/test/invariant/inv_mutable_error.cpp b/test/invariant/inv_mutable_error.cpp new file mode 100644 index 0000000..d488ccd --- /dev/null +++ b/test/invariant/inv_mutable_error.cpp @@ -0,0 +1,3 @@ + +#include "inv_mutable.i" + diff --git a/test/invariant/inv_mutable_permissive.cpp b/test/invariant/inv_mutable_permissive.cpp new file mode 100644 index 0000000..2473a7a --- /dev/null +++ b/test/invariant/inv_mutable_permissive.cpp @@ -0,0 +1,4 @@ + +#define BOOST_CONTRACT_CONFIG_PERMISSIVE +#include "inv_mutable.i" + diff --git a/test/invariant/inv_static.i b/test/invariant/inv_static.i new file mode 100644 index 0000000..0029683 --- /dev/null +++ b/test/invariant/inv_static.i @@ -0,0 +1,21 @@ + +// Test error if non-static inv declared static (unless PERMISSIVE #defined). + +#include +#include + +struct a { + static void invariant() {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::guard c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +}; + diff --git a/test/invariant/inv_static_error.cpp b/test/invariant/inv_static_error.cpp new file mode 100644 index 0000000..5374204 --- /dev/null +++ b/test/invariant/inv_static_error.cpp @@ -0,0 +1,3 @@ + +#include "inv_static.i" + diff --git a/test/invariant/inv_static_permissive.cpp b/test/invariant/inv_static_permissive.cpp new file mode 100644 index 0000000..75eb16e --- /dev/null +++ b/test/invariant/inv_static_permissive.cpp @@ -0,0 +1,4 @@ + +#define BOOST_CONTRACT_CONFIG_PERMISSIVE +#include "inv_static.i" + diff --git a/test/invariant/inv_volatile.i b/test/invariant/inv_volatile.i new file mode 100644 index 0000000..0c9330a --- /dev/null +++ b/test/invariant/inv_volatile.i @@ -0,0 +1,21 @@ + +// Test error if non-static inv declared volatile (unless PERMISSIVE #defined). + +#include +#include + +struct a { + void invariant() volatile {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::guard c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +}; + diff --git a/test/invariant/inv_volatile_error.cpp b/test/invariant/inv_volatile_error.cpp new file mode 100644 index 0000000..8229413 --- /dev/null +++ b/test/invariant/inv_volatile_error.cpp @@ -0,0 +1,3 @@ + +#include "inv_volatile.i" + diff --git a/test/invariant/inv_volatile_permissive.cpp b/test/invariant/inv_volatile_permissive.cpp new file mode 100644 index 0000000..611052f --- /dev/null +++ b/test/invariant/inv_volatile_permissive.cpp @@ -0,0 +1,4 @@ + +#define BOOST_CONTRACT_CONFIG_PERMISSIVE +#include "inv_volatile.i" + diff --git a/test/invariant/no_inv.cpp b/test/invariant/no_inv.cpp new file mode 100644 index 0000000..8359a9d --- /dev/null +++ b/test/invariant/no_inv.cpp @@ -0,0 +1,8 @@ + +// Test all invariants (static, cv, and const-only). + +#undef BOOST_CONTRACT_AUX_TEST_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_CV_INV +#undef BOOST_CONTRACT_AUX_TEST_CONST_INV +#include "combinations.i" + diff --git a/test/invariant/only_const.cpp b/test/invariant/only_const.cpp new file mode 100644 index 0000000..62c4144 --- /dev/null +++ b/test/invariant/only_const.cpp @@ -0,0 +1,8 @@ + +// Test all invariants (static, cv, and const-only). + +#undef BOOST_CONTRACT_AUX_TEST_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_CV_INV +#define BOOST_CONTRACT_AUX_TEST_CONST_INV +#include "combinations.i" + diff --git a/test/invariant/only_cv.cpp b/test/invariant/only_cv.cpp new file mode 100644 index 0000000..5b5b41d --- /dev/null +++ b/test/invariant/only_cv.cpp @@ -0,0 +1,8 @@ + +// Test all invariants (static, cv, and const-only). + +#undef BOOST_CONTRACT_AUX_TEST_STATIC_INV +#define BOOST_CONTRACT_AUX_TEST_CV_INV +#undef BOOST_CONTRACT_AUX_TEST_CONST_INV +#include "combinations.i" + diff --git a/test/invariant/only_static.cpp b/test/invariant/only_static.cpp new file mode 100644 index 0000000..0e6b319 --- /dev/null +++ b/test/invariant/only_static.cpp @@ -0,0 +1,8 @@ + +// Test all invariants (static, cv, and const-only). + +#define BOOST_CONTRACT_AUX_TEST_STATIC_INV +#undef BOOST_CONTRACT_AUX_TEST_CV_INV +#undef BOOST_CONTRACT_AUX_TEST_CONST_INV +#include "combinations.i" + diff --git a/test/invariant/static_inv_const.i b/test/invariant/static_inv_const.i new file mode 100644 index 0000000..6611d5d --- /dev/null +++ b/test/invariant/static_inv_const.i @@ -0,0 +1,21 @@ + +// Test error if static inv declared const (unless PERMISSIVE #defined). + +#include +#include + +struct a { + void static_invariant() const {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::guard c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +}; + diff --git a/test/invariant/static_inv_const_error.cpp b/test/invariant/static_inv_const_error.cpp new file mode 100644 index 0000000..523bca5 --- /dev/null +++ b/test/invariant/static_inv_const_error.cpp @@ -0,0 +1,3 @@ + +#include "static_inv_const.i" + diff --git a/test/invariant/static_inv_const_permissive.cpp b/test/invariant/static_inv_const_permissive.cpp new file mode 100644 index 0000000..a4631bd --- /dev/null +++ b/test/invariant/static_inv_const_permissive.cpp @@ -0,0 +1,4 @@ + +#define BOOST_CONTRACT_CONFIG_PERMISSIVE +#include "static_inv_const.i" + diff --git a/test/invariant/static_inv_cv.i b/test/invariant/static_inv_cv.i new file mode 100644 index 0000000..b05bf67 --- /dev/null +++ b/test/invariant/static_inv_cv.i @@ -0,0 +1,21 @@ + +// Test error if static inv declared cv (unless PERMISSIVE #defined). + +#include +#include + +struct a { + void static_invariant() const volatile {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::guard c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +}; + diff --git a/test/invariant/static_inv_cv_error.cpp b/test/invariant/static_inv_cv_error.cpp new file mode 100644 index 0000000..960a8e7 --- /dev/null +++ b/test/invariant/static_inv_cv_error.cpp @@ -0,0 +1,3 @@ + +#include "static_inv_cv.i" + diff --git a/test/invariant/static_inv_cv_permissive.cpp b/test/invariant/static_inv_cv_permissive.cpp new file mode 100644 index 0000000..1460f32 --- /dev/null +++ b/test/invariant/static_inv_cv_permissive.cpp @@ -0,0 +1,4 @@ + +#define BOOST_CONTRACT_CONFIG_PERMISSIVE +#include "static_inv_cv.i" + diff --git a/test/invariant/static_inv_mutable.i b/test/invariant/static_inv_mutable.i new file mode 100644 index 0000000..756a64d --- /dev/null +++ b/test/invariant/static_inv_mutable.i @@ -0,0 +1,21 @@ + +// Test error if static inv declared mutable (unless PERMISSIVE #defined). + +#include +#include + +struct a { + void static_invariant() {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::guard c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +}; + diff --git a/test/invariant/static_inv_mutable_error.cpp b/test/invariant/static_inv_mutable_error.cpp new file mode 100644 index 0000000..fe90b2e --- /dev/null +++ b/test/invariant/static_inv_mutable_error.cpp @@ -0,0 +1,3 @@ + +#include "static_inv_mutable.i" + diff --git a/test/invariant/static_inv_mutable_permissive.cpp b/test/invariant/static_inv_mutable_permissive.cpp new file mode 100644 index 0000000..46bd297 --- /dev/null +++ b/test/invariant/static_inv_mutable_permissive.cpp @@ -0,0 +1,4 @@ + +#define BOOST_CONTRACT_CONFIG_PERMISSIVE +#include "static_inv_mutable.i" + diff --git a/test/invariant/static_inv_volatile.i b/test/invariant/static_inv_volatile.i new file mode 100644 index 0000000..ba02fbb --- /dev/null +++ b/test/invariant/static_inv_volatile.i @@ -0,0 +1,21 @@ + +// Test error if static inv declared volatile (unless PERMISSIVE #defined). + +#include +#include + +struct a { + void static_invariant() volatile {} + + void f() { + // Same for ctor and dtor (because they all use check_pre_post_inv). + boost::contract::guard c = boost::contract::public_function(this); + } +}; + +int main() { + a aa; + aa.f(); + return 0; +}; + diff --git a/test/invariant/static_inv_volatile_error.cpp b/test/invariant/static_inv_volatile_error.cpp new file mode 100644 index 0000000..33ed96d --- /dev/null +++ b/test/invariant/static_inv_volatile_error.cpp @@ -0,0 +1,3 @@ + +#include "static_inv_volatile.i" + diff --git a/test/invariant/static_inv_volatile_permissive.cpp b/test/invariant/static_inv_volatile_permissive.cpp new file mode 100644 index 0000000..9806ffd --- /dev/null +++ b/test/invariant/static_inv_volatile_permissive.cpp @@ -0,0 +1,4 @@ + +#define BOOST_CONTRACT_CONFIG_PERMISSIVE +#include "static_inv_volatile.i" + diff --git a/test/public_function/bases.hpp b/test/public_function/bases.hpp index 2fdaea1..8d6e04c 100644 --- a/test/public_function/bases.hpp +++ b/test/public_function/bases.hpp @@ -32,11 +32,12 @@ private: // Test non-copyable and non-default-constructible result. // Test base without additional bases and pure virtual. template struct t { + static void static_invariant() { out << Id << "::static_inv" << std::endl; } + void invariant() const { out << Id << "::inv" << std::endl; BOOST_CONTRACT_ASSERT(z.value != ""); } - static void static_invariant() { out << Id << "::static_inv" << std::endl; } struct z_tag; typedef boost::contract::aux::test::counter z_type; @@ -84,11 +85,12 @@ struct c typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES + static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; BOOST_CONTRACT_ASSERT(y.value != ""); } - static void static_invariant() { out << "c::static_inv" << std::endl; } struct y_tag; typedef boost::contract::aux::test::counter y_type; @@ -144,8 +146,8 @@ struct c // Test no subcontracting from not (fully) contracted base. struct b { - void invariant() const { out << "b::inv" << std::endl; } static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } virtual ~b() {} @@ -165,11 +167,12 @@ struct a typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; BOOST_CONTRACT_ASSERT(x.value != ""); } - static void static_invariant() { out << "a::static_inv" << std::endl; } struct x_tag; typedef boost::contract::aux::test::counter x_type; diff --git a/test/public_function/bases_pre.cpp b/test/public_function/bases_pre.cpp new file mode 100644 index 0000000..7ec6f2d --- /dev/null +++ b/test/public_function/bases_pre.cpp @@ -0,0 +1,59 @@ + +// Test overriding func has no pre (but overridden pre still checked). + +#include "../aux_/oteststream.hpp" +#include +#include +#include +#include +#include +#include +#include + +boost::contract::aux::test::oteststream out; + +struct b { + static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } + + virtual void f(char ch, boost::contract::virtual_* v = 0) { + boost::contract::guard c = boost::contract::public_function(v, this) + .precondition([&] { + out << "b::pre" << std::endl; + BOOST_CONTRACT_ASSERT(ch == 'b'); + }) + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } +}; + +struct a + #define BASES public b + : BASES +{ + typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; + #undef BASES + + static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } + + virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ { + boost::contract::guard c = boost::contract::public_function( + v, &a::f, this, ch) + // Test no .precondition(...) here. + .old([] { out << "a::f::old" << std::endl; }) + .postcondition([] { out << "a::f::post" << std::endl; }) + ; + out << "a::f::body" << std::endl; + } + BOOST_CONTRACT_OVERRIDE(f) +}; + +int main() { + a aa; + aa.f('a'); + return boost::report_errors(); +} + diff --git a/test/public_function/bases_sparse.cpp b/test/public_function/bases_sparse.cpp index 5be6e2c..d1d2f51 100644 --- a/test/public_function/bases_sparse.cpp +++ b/test/public_function/bases_sparse.cpp @@ -13,8 +13,8 @@ boost::contract::aux::test::oteststream out; struct j { - void invariant() const { out << "j::inv" << std::endl; } static void static_invariant() { out << "j::static_inv" << std::endl; } + void invariant() const { out << "j::inv" << std::endl; } virtual void f(char ch, boost::contract::virtual_* v = 0) { boost::contract::guard c = boost::contract::public_function(v, this) @@ -30,8 +30,8 @@ struct j { }; struct i { - void invariant() const { out << "i::inv" << std::endl; } static void static_invariant() { out << "i::static_inv" << std::endl; } + void invariant() const { out << "i::inv" << std::endl; } virtual void f(char ch, boost::contract::virtual_* v = 0) { boost::contract::guard c = boost::contract::public_function(v, this) @@ -55,8 +55,8 @@ struct h typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "h::inv" << std::endl; } static void static_invariant() { out << "h::static_inv" << std::endl; } + void invariant() const { out << "h::inv" << std::endl; } virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ { boost::contract::guard c = boost::contract::public_function< @@ -80,8 +80,8 @@ struct e typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "e::inv" << std::endl; } static void static_invariant() { out << "e::static_inv" << std::endl; } + void invariant() const { out << "e::inv" << std::endl; } virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ { boost::contract::guard c = boost::contract::public_function< @@ -105,13 +105,13 @@ struct d typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "d::inv" << std::endl; } static void static_invariant() { out << "d::static_inv" << std::endl; } + void invariant() const { out << "d::inv" << std::endl; } }; struct c { - void invariant() const { out << "c::inv" << std::endl; } static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } virtual void f(char ch, boost::contract::virtual_* v = 0) { boost::contract::guard c = boost::contract::public_function(v, this) @@ -133,8 +133,8 @@ struct b typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "b::inv" << std::endl; } static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } }; struct x {}; @@ -149,8 +149,8 @@ struct a typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "a::inv" << std::endl; } static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } virtual void f(char ch, boost::contract::virtual_* v = 0) /* override */ { boost::contract::guard c = boost::contract::public_function< diff --git a/test/public_function/body_throw.cpp b/test/public_function/body_throw.cpp index 2454384..57e2888 100644 --- a/test/public_function/body_throw.cpp +++ b/test/public_function/body_throw.cpp @@ -13,8 +13,8 @@ boost::contract::aux::test::oteststream out; struct c { - void invariant() const { out << "c::inv" << std::endl; } static void static_invariant() { out << "c::static_inv" << std::endl; } + void invariant() const { out << "c::inv" << std::endl; } struct e {}; @@ -39,8 +39,8 @@ struct b typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "b::inv" << std::endl; } static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } struct e {}; @@ -67,8 +67,8 @@ struct a typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "a::inv" << std::endl; } static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } struct e {}; diff --git a/test/public_function/override.i b/test/public_function/override.i index 2831c32..394a061 100644 --- a/test/public_function/override.i +++ b/test/public_function/override.i @@ -1,5 +1,5 @@ -// Test a::f overrides, but base b does not have f (has g instead). +// Test error if override func does not actually override (unless PERMISSIVE). #include #include diff --git a/test/public_function/override_error.cpp b/test/public_function/override_error.cpp index b565b69..0bb1b8c 100644 --- a/test/public_function/override_error.cpp +++ b/test/public_function/override_error.cpp @@ -1,4 +1,3 @@ -// Test error when a::f marked override does not override any function. #include "override.i" diff --git a/test/public_function/override_permissive.cpp b/test/public_function/override_permissive.cpp index afc3dda..a639be5 100644 --- a/test/public_function/override_permissive.cpp +++ b/test/public_function/override_permissive.cpp @@ -1,5 +1,4 @@ -// Test error when a::f marked override does not override any function. #define BOOST_CONTRACT_CONFIG_PERMISSIVE #include "override.i" diff --git a/test/public_function/static.cpp b/test/public_function/static.cpp index 55e2675..2829df2 100644 --- a/test/public_function/static.cpp +++ b/test/public_function/static.cpp @@ -11,8 +11,8 @@ boost::contract::aux::test::oteststream out; struct b { - void invariant() const { out << "b::inv" << std::endl; } static void static_invariant() { out << "b::static_inv" << std::endl; } + void invariant() const { out << "b::inv" << std::endl; } static void f() { boost::contract::guard c = boost::contract::public_function() @@ -31,8 +31,8 @@ struct a typedef BOOST_CONTRACT_BASE_TYPES(BASES) base_types; #undef BASES - void invariant() const { out << "a::inv" << std::endl; } static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } static void f() { boost::contract::guard c = boost::contract::public_function() diff --git a/test/public_function/static_body_throw.cpp b/test/public_function/static_body_throw.cpp index e68f179..f4629c4 100644 --- a/test/public_function/static_body_throw.cpp +++ b/test/public_function/static_body_throw.cpp @@ -10,8 +10,8 @@ boost::contract::aux::test::oteststream out; struct a { - void invariant() const { out << "a::inv" << std::endl; } static void static_invariant() { out << "a::static_inv" << std::endl; } + void invariant() const { out << "a::inv" << std::endl; } struct e {};