diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3061c0f0..7bd8c542 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,6 +66,12 @@ jobs: os: ubuntu-22.04 install: g++-12-multilib address-model: 32,64 + - toolset: gcc-13 + cxxstd: "11,14,17,20,2b" + os: ubuntu-latest + container: ubuntu:23.04 + install: g++-13-multilib + address-model: 32,64 - toolset: clang compiler: clang++-3.9 cxxstd: "11,14" @@ -126,9 +132,26 @@ jobs: cxxstd: "11,14,17,20,2b" os: ubuntu-22.04 install: clang-14 + - toolset: clang + compiler: clang++-15 + cxxstd: "11,14,17,20,2b" + os: ubuntu-22.04 + install: clang-15 + - toolset: clang + compiler: clang++-16 + cxxstd: "11,14,17,20,2b" + os: ubuntu-latest + container: ubuntu:23.04 + install: clang-16 - toolset: clang cxxstd: "11,14,17,2a" os: macos-11 + - toolset: clang + cxxstd: "11,14,17,20,2b" + os: macos-12 + - toolset: clang + cxxstd: "11,14,17,20,2b" + os: macos-13 runs-on: ${{matrix.os}} container: ${{matrix.container}} @@ -144,11 +167,13 @@ jobs: if: matrix.container run: | apt-get update - apt-get -y install sudo python git g++ + apt-get -y install sudo python3 git g++ - name: Install packages if: matrix.install - run: sudo apt-get -y install ${{matrix.install}} + run: | + sudo apt-get update + sudo apt-get -y install ${{matrix.install}} - name: Setup Boost run: | @@ -168,7 +193,7 @@ jobs: cd boost-root cp -r $GITHUB_WORKSPACE/* libs/$LIBRARY git submodule update --init tools/boostdep - python tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY + python3 tools/boostdep/depinst/depinst.py --git_args "--jobs 3" $LIBRARY ./bootstrap.sh ./b2 -d0 headers @@ -180,7 +205,7 @@ jobs: - name: Generate headers run: | cd ../boost-root/libs/leaf - python gen/generate_single_header.py -i include/boost/leaf/detail/all.hpp -p include -o test/leaf.hpp boost/leaf + python3 gen/generate_single_header.py -i include/boost/leaf/detail/all.hpp -p include -o test/leaf.hpp boost/leaf - name: Run tests run: | @@ -204,7 +229,6 @@ jobs: cxxstd: "14,17,latest" addrmd: 64 os: windows-2022 - embedmanifest: embed-manifest-via=linker - toolset: gcc cxxstd: "11,14,17,2a" addrmd: 64 @@ -240,7 +264,7 @@ jobs: - name: Generate headers run: | cd ../boost-root/libs/leaf - python gen/generate_single_header.py -i include/boost/leaf/detail/all.hpp -p include -o test/leaf.hpp boost/leaf + python3 gen/generate_single_header.py -i include/boost/leaf/detail/all.hpp -p include -o test/leaf.hpp boost/leaf - name: Run tests shell: cmd diff --git a/.gitignore b/.gitignore index c589ffad..fd1a40a2 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ *.opensdf *.db *.opendb -bld/* +_bld/* doc/html/* snippets/* subprojects/*/ diff --git a/.vscode/launch.json b/.vscode/launch.json index 5f995048..0b2700e1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,7 +8,7 @@ "name": "(lldb) Launch", "type": "cppdbg", "request": "launch", - "program": "${workspaceFolder}/bld/debug/capture_exception_async_test", + "program": "${workspaceFolder}/_bld/debug/capture_exception_async_test", "args": [ ], "cwd": "${workspaceFolder}", "stopAtEntry": false, diff --git a/.vscode/tasks.json b/.vscode/tasks.json index d844b069..7a705ffe 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -6,13 +6,13 @@ { "label": "Configure Meson build directories", "type": "shell", - "command": "cd ${workspaceRoot} && meson -D leaf_boost_examples=true -D leaf_lua_examples=true bld/debug && meson -D leaf_boost_examples=true -D leaf_lua_examples=true -D leaf_hpp=true bld/debug_leaf_hpp && meson -D leaf_boost_examples=true -D leaf_lua_examples=true bld/release --buildtype release && meson -D leaf_boost_examples=true -D leaf_lua_examples=true -D leaf_hpp=true bld/release_leaf_hpp --buildtype release && meson -D leaf_diagnostics=0 -D cpp_eh=none -D b_ndebug=true -D b_lto=true -D leaf_enable_benchmarks=true bld/benchmark --buildtype release", + "command": "cd ${workspaceRoot} && meson -D leaf_boost_examples=true -D leaf_lua_examples=true _bld/debug && meson -D leaf_boost_examples=true -D leaf_lua_examples=true -D leaf_hpp=true _bld/debug_leaf_hpp && meson -D leaf_boost_examples=true -D leaf_lua_examples=true _bld/release --buildtype release && meson -D leaf_boost_examples=true -D leaf_lua_examples=true -D leaf_hpp=true _bld/release_leaf_hpp --buildtype release && meson -D leaf_diagnostics=0 -D cpp_eh=none -D b_ndebug=true -D b_lto=true -D leaf_enable_benchmarks=true _bld/benchmark --buildtype release", "problemMatcher": [] }, { "label": "Configure Meson build directories (no Boost)", "type": "shell", - "command": "cd ${workspaceRoot} && meson -D leaf_lua_examples=true bld/debug && meson -D leaf_lua_examples=true -D leaf_hpp=true bld/debug_leaf_hpp && meson -D leaf_lua_examples=true bld/release --buildtype release && meson -D leaf_lua_examples=true -D leaf_hpp=true bld/release_leaf_hpp --buildtype release", + "command": "cd ${workspaceRoot} && meson -D leaf_lua_examples=true _bld/debug && meson -D leaf_lua_examples=true -D leaf_hpp=true _bld/debug_leaf_hpp && meson -D leaf_lua_examples=true _bld/release --buildtype release && meson -D leaf_lua_examples=true -D leaf_hpp=true _bld/release_leaf_hpp --buildtype release", "problemMatcher": [] }, { @@ -28,12 +28,12 @@ }, "label": "Build all unit tests and examples (debug)", "type": "shell", - "command": "cd ${workspaceRoot}/bld/debug && ninja", + "command": "cd ${workspaceRoot}/_bld/debug && ninja", "problemMatcher": { "base": "$gcc", "fileLocation": [ "relative", - "${workspaceRoot}/bld/debug" + "${workspaceRoot}/_bld/debug" ] } }, @@ -44,12 +44,12 @@ "dependsOn": [ "Generate leaf.hpp" ], - "command": "cd ${workspaceRoot}/bld/debug_leaf_hpp && ninja && meson test && cd ${workspaceRoot}/bld/debug && ninja && meson test", + "command": "cd ${workspaceRoot}/_bld/debug_leaf_hpp && ninja && meson test && cd ${workspaceRoot}/_bld/debug && ninja && meson test", "problemMatcher": { "base": "$gcc", "fileLocation": [ "relative", - "${workspaceRoot}/bld/debug" + "${workspaceRoot}/_bld/debug" ] } }, @@ -60,12 +60,12 @@ "dependsOn": [ "Generate leaf.hpp" ], - "command": "cd ${workspaceRoot}/bld/release && ninja && meson test && cd ${workspaceRoot}/bld/release_leaf_hpp && ninja && meson test", + "command": "cd ${workspaceRoot}/_bld/release && ninja && meson test && cd ${workspaceRoot}/_bld/release_leaf_hpp && ninja && meson test", "problemMatcher": { "base": "$gcc", "fileLocation": [ "relative", - "${workspaceRoot}/bld/release" + "${workspaceRoot}/_bld/release" ] } }, @@ -73,9 +73,6 @@ "group": "test", "label": "Run all unit tests (b2, all configurations)", "type": "shell", - "dependsOn": [ - "Generate leaf.hpp" - ], "command": "../../b2 test link=shared,static variant=debug,release,leaf_debug_diag0,leaf_release_diag0,leaf_debug_leaf_hpp,leaf_release_leaf_hpp exception-handling=on,off cxxstd=11,14,1z,17 && ../../b2 test link=shared,static variant=debug,release,leaf_debug_diag0,leaf_release_diag0,leaf_debug_leaf_hpp,leaf_release_leaf_hpp,leaf_debug_embedded,leaf_release_embedded exception-handling=off rtti=off cxxstd=11,14,1z,17", "windows": { "command": "..\\..\\b2 test link=shared,static variant=debug,release,leaf_debug_diag0,leaf_release_diag0,leaf_debug_leaf_hpp,leaf_release_leaf_hpp exception-handling=on,off cxxstd=14,17,latest && ..\\..\\b2 test link=shared,static variant=debug,release,leaf_debug_diag0,leaf_release_diag0,leaf_debug_leaf_hpp,leaf_release_leaf_hpp,leaf_debug_embedded,leaf_release_embedded exception-handling=off rtti=off cxxstd=14,17,latest", @@ -84,7 +81,7 @@ "base": "$gcc", "fileLocation": [ "relative", - "${workspaceRoot}/bld/release" + "${workspaceRoot}/_bld/release" ] } }, @@ -95,12 +92,12 @@ }, "label": "Test current editor file", "type": "shell", - "command": "cd ${workspaceRoot}/bld/debug && ninja && { meson test ${fileBasenameNoExtension} || cat ./meson-logs/testlog.txt }", + "command": "cd ${workspaceRoot}/_bld/debug && ninja && { meson test ${fileBasenameNoExtension} || cat ./meson-logs/testlog.txt }", "problemMatcher": { "base": "$gcc", "fileLocation": [ "relative", - "${workspaceRoot}/bld/debug" + "${workspaceRoot}/_bld/debug" ] } } diff --git a/include/boost/leaf/context.hpp b/include/boost/leaf/context.hpp index 4fe1775b..dc0796a1 100644 --- a/include/boost/leaf/context.hpp +++ b/include/boost/leaf/context.hpp @@ -177,7 +177,7 @@ namespace leaf_detail BOOST_LEAF_ASSERT(err_id != 0); auto & sl = std::get(tup); if( sl.has_value(err_id) ) - load_slot(err_id, std::move(sl).value(err_id)); + (void) load_slot(err_id, std::move(sl).value(err_id)); tuple_for_each::propagate_captured(tup, err_id); } diff --git a/include/boost/leaf/detail/optional.hpp b/include/boost/leaf/detail/optional.hpp index 0a2cdb2d..93def2fc 100644 --- a/include/boost/leaf/detail/optional.hpp +++ b/include/boost/leaf/detail/optional.hpp @@ -107,6 +107,15 @@ namespace leaf_detail } } + BOOST_LEAF_CONSTEXPR T & put( int key ) + { + BOOST_LEAF_ASSERT(key); + reset(); + (void) new(&value_) T; + key_=key; + return value_; + } + BOOST_LEAF_CONSTEXPR T & put( int key, T const & v ) { BOOST_LEAF_ASSERT(key); diff --git a/include/boost/leaf/error.hpp b/include/boost/leaf/error.hpp index dac84a73..e718a923 100644 --- a/include/boost/leaf/error.hpp +++ b/include/boost/leaf/error.hpp @@ -18,7 +18,7 @@ #if BOOST_LEAF_CFG_DIAGNOSTICS # include # include -# include +# include #endif #if BOOST_LEAF_CFG_STD_SYSTEM_ERROR @@ -141,33 +141,120 @@ namespace leaf_detail BOOST_LEAF_CONSTEXPR static void print( std::basic_ostream &, e_unexpected_count const &) noexcept { } }; + template + class BOOST_LEAF_SYMBOL_VISIBLE slot; + class BOOST_LEAF_SYMBOL_VISIBLE e_unexpected_info { - std::string s_; - std::set already_; + e_unexpected_info( e_unexpected_info const & ) = delete; + e_unexpected_info & operator=( e_unexpected_info const & ) = delete; + + struct slot_base + { + public: + slot_base * next_; + virtual void deactivate() noexcept = 0; + virtual void propagate( int err_id ) noexcept = 0; + virtual std::string print( int key_to_print ) const = 0; + virtual ~slot_base() noexcept { }; + protected: + BOOST_LEAF_CONSTEXPR slot_base(): + next_(nullptr) + { + } + }; + + template + class slot_store: public slot_base, public slot + { + slot_store( slot_store const & ) = delete; + slot_store & operator=( slot_store const & ) = delete; + using sl = slot; + void deactivate() noexcept final override + { + sl::deactivate(); + } + void propagate( int err_id ) noexcept final override + { + sl::propagate(err_id); + } + std::string print( int key_to_print ) const final override + { + std::stringstream st; + sl::print(st, key_to_print); + return st.str(); + } + public: + template + BOOST_LEAF_CONSTEXPR slot_store( int err_id, T && e ) + { + sl::put(err_id, std::forward(e)); + } + }; + + slot_base * first_; + slot_base * * last_; public: - e_unexpected_info() noexcept + BOOST_LEAF_CONSTEXPR e_unexpected_info() noexcept: + first_(nullptr), + last_(&first_) { } - template - void add(E && e) + BOOST_LEAF_CONSTEXPR e_unexpected_info( e_unexpected_info && other ) noexcept: + first_(other.first_), + last_(other.last_ == &other.first_? &first_ : other.last_) + { + BOOST_LEAF_ASSERT(last_ != nullptr); + BOOST_LEAF_ASSERT(*last_ == nullptr); + other.first_ = nullptr; + other.last_ = nullptr; + } + + ~e_unexpected_info() noexcept { - if( !diagnostic::is_invisible && already_.insert(&type).second ) + for( slot_base const * p = first_; p; ) { - std::stringstream s; - diagnostic::print(s,e); - (s << '\n').flush(); - s_ += s.str(); + slot_base const * n = p -> next_; + delete p; + p = n; } } + template + BOOST_LEAF_CONSTEXPR typename std::decay::type & put(int err_id, E && e) + { + using T = typename std::decay::type; + BOOST_LEAF_ASSERT(last_ != nullptr); + BOOST_LEAF_ASSERT(*last_ == nullptr); + BOOST_LEAF_ASSERT(tls::read_ptr>() == nullptr); + slot_store * ss = new slot_store(err_id, std::forward(e)); + *last_ = ss; + last_ = &ss->next_; + ss->activate(); + return ss->value(err_id); + } + + void deactivate() noexcept + { + for( slot_base * p=first_; p; p=p->next_ ) + p->deactivate(); + } + + void propagate( int err_id ) noexcept + { + for( slot_base * p=first_; p; p=p->next_ ) + p->propagate(err_id); + } + template - void print( std::basic_ostream & os ) const + void print( std::basic_ostream & os, int key_to_print ) const { - os << "Unhandled error objects:\n" << s_; + os << "Unhandled error objects:\n"; + for( slot_base const * p=first_; p; p=p->next_ ) + os << p->print(key_to_print); } }; @@ -231,18 +318,18 @@ namespace leaf_detail BOOST_LEAF_ASSERT(x.prev_==nullptr); } - BOOST_LEAF_CONSTEXPR void activate() noexcept + void activate() noexcept { prev_ = tls::read_ptr>(); tls::write_ptr>(this); } - BOOST_LEAF_CONSTEXPR void deactivate() noexcept + void deactivate() noexcept { tls::write_ptr>(prev_); } - BOOST_LEAF_CONSTEXPR void propagate( int err_id ) noexcept; + void propagate( int err_id ) noexcept(!BOOST_LEAF_CFG_DIAGNOSTICS); template void print( std::basic_ostream & os, int key_to_print ) const @@ -274,6 +361,22 @@ namespace leaf_detail #if BOOST_LEAF_CFG_DIAGNOSTICS + template <> + inline void slot::deactivate() noexcept + { + if( int const err_id = this->key() ) + if( e_unexpected_info * info = this->has_value(err_id) ) + info->deactivate(); + tls::write_ptr>(prev_); + } + + template <> + inline void slot::propagate( int err_id ) noexcept(!BOOST_LEAF_CFG_DIAGNOSTICS) + { + if( e_unexpected_info * info = this->has_value(err_id) ) + info->propagate(err_id); + } + template BOOST_LEAF_CONSTEXPR inline void load_unexpected_count( int err_id ) noexcept { @@ -292,23 +395,42 @@ namespace leaf_detail if( slot * sl = tls::read_ptr>() ) { if( e_unexpected_info * unx = sl->has_value(err_id) ) - unx->add(std::forward(e)); + (void) unx->put(err_id, std::forward(e)); + else + (void) sl->put(err_id).put(err_id, std::forward(e)); + } + } + + template + BOOST_LEAF_CONSTEXPR inline void accumulate_unexpected_info( int err_id, F && f ) noexcept + { + if( slot * sl = tls::read_ptr>() ) + { + if( e_unexpected_info * unx = sl->has_value(err_id) ) + (void) std::forward(f)(unx->put(err_id, E{})); else - sl->put(err_id, e_unexpected_info()).add(std::forward(e)); + (void) std::forward(f)(sl->put(err_id).put(err_id, E{})); } } template - BOOST_LEAF_CONSTEXPR inline void load_unexpected( int err_id, E && e ) noexcept + BOOST_LEAF_CONSTEXPR inline void load_unexpected( int err_id, E && e ) { load_unexpected_count(err_id); load_unexpected_info(err_id, std::forward(e)); } + template + BOOST_LEAF_CONSTEXPR inline void accumulate_unexpected( int err_id, F && f ) + { + load_unexpected_count(err_id); + accumulate_unexpected_info(err_id, std::forward(f)); + } + #endif template - BOOST_LEAF_CONSTEXPR inline void slot::propagate( int err_id ) noexcept + inline void slot::propagate( int err_id ) noexcept(!BOOST_LEAF_CFG_DIAGNOSTICS) { if( this->key()!=err_id && err_id!=0 ) return; @@ -325,15 +447,18 @@ namespace leaf_detail #endif } - template - BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept + template + BOOST_LEAF_CONSTEXPR inline int load_slot( int err_id, E && e ) noexcept(!BOOST_LEAF_CFG_DIAGNOSTICS) { static_assert(!std::is_pointer::value, "Error objects of pointer types are not allowed"); static_assert(!std::is_same::type, error_id>::value, "Error objects of type error_id are not allowed"); using T = typename std::decay::type; BOOST_LEAF_ASSERT((err_id&3)==1); if( slot * p = tls::read_ptr>() ) - (void) p->put(err_id, std::forward(e)); + { + if( OverwriteAllowed || !p->has_value(err_id) ) + (void) p->put(err_id, std::forward(e)); + } #if BOOST_LEAF_CFG_DIAGNOSTICS else { @@ -347,7 +472,7 @@ namespace leaf_detail } template - BOOST_LEAF_CONSTEXPR inline int accumulate_slot( int err_id, F && f ) noexcept + BOOST_LEAF_CONSTEXPR inline int accumulate_slot( int err_id, F && f ) { static_assert(function_traits::arity==1, "Lambdas passed to accumulate must take a single e-type argument by reference"); using E = typename std::decay>::type; @@ -360,6 +485,15 @@ namespace leaf_detail else (void) std::forward(f)(sl->put(err_id,E())); } +#if BOOST_LEAF_CFG_DIAGNOSTICS + else + { + int c = int(tls::read_uint()); + BOOST_LEAF_ASSERT(c>=0); + if( c ) + accumulate_unexpected(err_id, std::forward(f)); + } +#endif return 0; } } @@ -414,7 +548,7 @@ namespace leaf_detail { BOOST_LEAF_CONSTEXPR static int load_( int err_id, E && e ) noexcept { - return load_slot(err_id, std::forward(e)); + return load_slot(err_id, std::forward(e)); } }; @@ -423,7 +557,7 @@ namespace leaf_detail { BOOST_LEAF_CONSTEXPR static int load_( int err_id, F && f ) noexcept { - return load_slot(err_id, std::forward(f)()); + return load_slot(err_id, std::forward(f)()); } }; @@ -474,7 +608,7 @@ namespace leaf_detail else { err_id = new_id(); - (void) load_slot(err_id, ec); + (void) load_slot(err_id, ec); return (err_id&~3)|1; } } diff --git a/include/boost/leaf/handle_errors.hpp b/include/boost/leaf/handle_errors.hpp index 0da2b376..8517e7c2 100644 --- a/include/boost/leaf/handle_errors.hpp +++ b/include/boost/leaf/handle_errors.hpp @@ -235,11 +235,12 @@ class BOOST_LEAF_SYMBOL_VISIBLE verbose_diagnostic_info: public error_info friend std::basic_ostream & operator<<( std::basic_ostream & os, verbose_diagnostic_info const & x ) { os << "leaf::verbose_diagnostic_info for "; + int const err_id = x.error().value(); x.print(os); os << ":\n"; - x.print_(os, x.tup_, x.error().value()); + x.print_(os, x.tup_, err_id); if( x.e_ui_ ) - x.e_ui_->print(os); + x.e_ui_->print(os, err_id); return os; } }; diff --git a/include/boost/leaf/on_error.hpp b/include/boost/leaf/on_error.hpp index cd471829..f9250565 100644 --- a/include/boost/leaf/on_error.hpp +++ b/include/boost/leaf/on_error.hpp @@ -92,34 +92,18 @@ namespace leaf_detail class preloaded_item { using decay_E = typename std::decay::type; - slot * s_; decay_E e_; public: BOOST_LEAF_CONSTEXPR preloaded_item( E && e ): - s_(tls::read_ptr>()), e_(std::forward(e)) { } BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept { - BOOST_LEAF_ASSERT((err_id&3)==1); - if( s_ ) - { - if( !s_->has_value(err_id) ) - s_->put(err_id, std::move(e_)); - } -#if BOOST_LEAF_CFG_DIAGNOSTICS - else - { - int c = int(tls::read_uint()); - BOOST_LEAF_ASSERT(c>=0); - if( c ) - load_unexpected(err_id, std::move(e_)); - } -#endif + (void) load_slot(err_id, std::move(e_)); } }; @@ -127,34 +111,18 @@ namespace leaf_detail class deferred_item { using E = decltype(std::declval()()); - slot * s_; F f_; public: BOOST_LEAF_CONSTEXPR deferred_item( F && f ) noexcept: - s_(tls::read_ptr>()), f_(std::forward(f)) { } BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept { - BOOST_LEAF_ASSERT((err_id&3)==1); - if( s_ ) - { - if( !s_->has_value(err_id) ) - s_->put(err_id, f_()); - } -#if BOOST_LEAF_CFG_DIAGNOSTICS - else - { - int c = int(tls::read_uint()); - BOOST_LEAF_ASSERT(c>=0); - if( c ) - load_unexpected(err_id, std::forward(f_())); - } -#endif + (void) load_slot(err_id, f_()); } }; @@ -165,27 +133,18 @@ namespace leaf_detail class accumulating_item { using E = A0; - slot * s_; F f_; public: BOOST_LEAF_CONSTEXPR accumulating_item( F && f ) noexcept: - s_(tls::read_ptr>()), f_(std::forward(f)) { } BOOST_LEAF_CONSTEXPR void trigger( int err_id ) noexcept { - BOOST_LEAF_ASSERT((err_id&3)==1); - if( s_ ) - { - if( E * e = s_->has_value(err_id) ) - (void) f_(*e); - else - (void) f_(s_->put(err_id, E())); - } + accumulate_slot(err_id, std::move(f_)); } }; diff --git a/meson.build b/meson.build index a6b55868..f351e97c 100644 --- a/meson.build +++ b/meson.build @@ -134,8 +134,11 @@ if option_enable_unit_tests 'defer_nested_new_error_result_test', 'defer_nested_success_exception_test', 'defer_nested_success_result_test', - 'diagnostic_info_test', + 'diagnostic_info_test1', 'diagnostic_info_test2', + 'diagnostic_info_test3', + 'diagnostic_info_test4', + 'diagnostic_info_test5', 'e_errno_test', 'e_LastError_test', 'error_code_test', diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index e8c02ac0..30a87d55 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -25,8 +25,8 @@ project BOOST_LEAF_BOOST_AVAILABLE single:BOOST_LEAF_NO_THREADS gcc:"-Wno-delete-non-virtual-dtor -Wno-parentheses" - clang:"-Wno-dangling-else" - darwin:"-Wno-unused-variable -Wno-delete-non-virtual-dtor -Wno-non-virtual-dtor -Wno-dangling-else" + clang:"-Wno-unused-variable -Wno-delete-non-virtual-dtor -Wno-non-virtual-dtor -Wno-delete-non-abstract-non-virtual-dtor -Wno-dangling-else" + darwin:"-Wno-unused-variable -Wno-delete-non-virtual-dtor -Wno-non-virtual-dtor -Wno-delete-non-abstract-non-virtual-dtor -Wno-dangling-else" msvc:"-wd 4267 -wd 4996 -wd 4244" ../../.. ; @@ -73,8 +73,11 @@ run defer_nested_new_error_exception_test.cpp ; run defer_nested_new_error_result_test.cpp ; run defer_nested_success_exception_test.cpp ; run defer_nested_success_result_test.cpp ; -run diagnostic_info_test.cpp ; +run diagnostic_info_test1.cpp ; run diagnostic_info_test2.cpp ; +run diagnostic_info_test3.cpp ; +run diagnostic_info_test4.cpp ; +run diagnostic_info_test5.cpp ; run e_errno_test.cpp ; run e_LastError_test.cpp ; run error_code_test.cpp ; diff --git a/test/accumulate_basic_test.cpp b/test/accumulate_basic_test.cpp index 928d7025..b32c97a4 100644 --- a/test/accumulate_basic_test.cpp +++ b/test/accumulate_basic_test.cpp @@ -18,7 +18,7 @@ namespace leaf = boost::leaf; template struct info { - int value; + int value = 0; }; leaf::error_id g() diff --git a/test/accumulate_nested_error_result_test.cpp b/test/accumulate_nested_error_result_test.cpp index f5896b44..67092d69 100644 --- a/test/accumulate_nested_error_result_test.cpp +++ b/test/accumulate_nested_error_result_test.cpp @@ -15,27 +15,35 @@ namespace leaf = boost::leaf; -template +template struct info { int value; + info(): + value(0) + { + } + explicit info(int value): + value(value) + { + } }; leaf::error_id f0() { auto load = leaf::on_error( []( info<0> & ) { } ); - return leaf::new_error( info<2>{2} ); + return leaf::new_error( info<2>(2) ); } leaf::error_id f1() { - auto load = leaf::on_error( info<0>{-1}, info<2>{-1}, []( info<1> & x ) {++x.value;} ); + auto load = leaf::on_error( info<0>(-1), info<2>(-1), []( info<1> & x ) {++x.value;} ); return f0(); } leaf::error_id f2() { - return f1().load( info<3>{3} ); + return f1().load( info<3>(3) ); } int main() diff --git a/test/accumulate_nested_new_error_exception_test.cpp b/test/accumulate_nested_new_error_exception_test.cpp index 322e9b08..57381580 100644 --- a/test/accumulate_nested_new_error_exception_test.cpp +++ b/test/accumulate_nested_new_error_exception_test.cpp @@ -33,12 +33,20 @@ template struct info { int value; + info(): + value(0) + { + } + explicit info(int value): + value(value) + { + } }; void f0() { - auto load = leaf::on_error( info<0>{-1} ); - leaf::throw_exception(info<1>{-1}); + auto load = leaf::on_error( info<0>(-1) ); + leaf::throw_exception(info<1>(-1)); } void f1() @@ -57,7 +65,7 @@ leaf::error_id f2() } catch( leaf::error_id const & err ) { - err.load( info<3>{3} ); + err.load( info<3>(3) ); throw; } catch(...) diff --git a/test/accumulate_nested_new_error_result_test.cpp b/test/accumulate_nested_new_error_result_test.cpp index a13a9a94..433dc90f 100644 --- a/test/accumulate_nested_new_error_result_test.cpp +++ b/test/accumulate_nested_new_error_result_test.cpp @@ -19,12 +19,20 @@ template struct info { int value; + info(): + value(0) + { + } + explicit info(int value): + value(value) + { + } }; leaf::error_id f0() { - auto load = leaf::on_error( info<0>{-1} ); - return leaf::new_error( info<1>{-1} ); + auto load = leaf::on_error( info<0>(-1) ); + return leaf::new_error( info<1>(-1) ); } leaf::error_id f1() @@ -36,7 +44,7 @@ leaf::error_id f1() leaf::error_id f2() { - return f1().load( info<3>{3} ); + return f1().load( info<3>(3) ); } int main() diff --git a/test/diagnostic_info_test.cpp b/test/diagnostic_info_test1.cpp similarity index 99% rename from test/diagnostic_info_test.cpp rename to test/diagnostic_info_test1.cpp index 29ccd922..b57e7b80 100644 --- a/test/diagnostic_info_test.cpp +++ b/test/diagnostic_info_test1.cpp @@ -12,8 +12,12 @@ # include #endif +#if BOOST_LEAF_CFG_STD_STRING +# include +#endif +#include + #include "lightweight_test.hpp" -#include namespace leaf = boost::leaf; diff --git a/test/diagnostic_info_test2.cpp b/test/diagnostic_info_test2.cpp index 7f36b87a..805b6a10 100644 --- a/test/diagnostic_info_test2.cpp +++ b/test/diagnostic_info_test2.cpp @@ -11,8 +11,12 @@ # include #endif +#if BOOST_LEAF_CFG_STD_STRING +# include +#endif +#include + #include "lightweight_test.hpp" -#include namespace leaf = boost::leaf; diff --git a/test/diagnostic_info_test3.cpp b/test/diagnostic_info_test3.cpp new file mode 100644 index 00000000..7a19401c --- /dev/null +++ b/test/diagnostic_info_test3.cpp @@ -0,0 +1,58 @@ +// Copyright 2018-2022 Emil Dotchevski and Reverge Studios, Inc. + +// 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) + +#ifdef BOOST_LEAF_TEST_SINGLE_HEADER +# include "leaf.hpp" +#else +# include +# include +# include +#endif + +#if BOOST_LEAF_CFG_STD_STRING +# include +#endif +#include + +#include "lightweight_test.hpp" + +namespace leaf = boost::leaf; + +struct info { int value; }; + +leaf::result f1() +{ + return leaf::new_error(info{41}); +} + +leaf::result f2() +{ + auto load = leaf::on_error(info{42}); + return f1(); +} + +int main() +{ + leaf::try_handle_all( + []() -> leaf::result + { + return f2(); + }, + []( leaf::verbose_diagnostic_info const & di ) + { +#if BOOST_LEAF_CFG_STD_STRING + std::ostringstream st; + st << di; + std::string s = st.str(); +#if BOOST_LEAF_CFG_DIAGNOSTICS + BOOST_TEST_NE(s.find("41"), s.npos); + BOOST_TEST_EQ(s.find("42"), s.npos); +#endif + std::cout << s; +#endif + } ); + + return boost::report_errors(); +} diff --git a/test/diagnostic_info_test4.cpp b/test/diagnostic_info_test4.cpp new file mode 100644 index 00000000..2e21070d --- /dev/null +++ b/test/diagnostic_info_test4.cpp @@ -0,0 +1,73 @@ +// Copyright 2018-2022 Emil Dotchevski and Reverge Studios, Inc. + +// 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) + +#ifdef BOOST_LEAF_TEST_SINGLE_HEADER +# include "leaf.hpp" +#else +# include +# include +# include +#endif + +#if BOOST_LEAF_CFG_STD_STRING +# include +#endif +#include +#include + +#include "lightweight_test.hpp" + +namespace leaf = boost::leaf; + +struct my_error +{ + std::vector vec; + void append(int x) + { + vec.push_back(x); + } + friend std::ostream & operator<<( std::ostream & os, my_error const & x ) + { + for( auto const & e : x.vec ) + os << "appended: " << e << std::endl; + return os; + } +}; + +leaf::result f1() +{ + auto ctx_ = leaf::on_error([](my_error & e) {e.append(42);}); + return leaf::new_error("new_error"); +} + +leaf::result f2() +{ + auto ctx_ = leaf::on_error([](my_error & e) {e.append(43);}); + return f1(); +} + +int main() +{ + leaf::try_handle_all([]() -> leaf::result + { + return f2(); + }, + [](leaf::verbose_diagnostic_info const & e) + { +#if BOOST_LEAF_CFG_STD_STRING + std::ostringstream st; + st << e; + std::string s = st.str(); +#if BOOST_LEAF_CFG_DIAGNOSTICS + BOOST_TEST_NE(s.find("new_error"), s.npos); + BOOST_TEST_NE(s.find("appended: 42"), s.npos); + BOOST_TEST_NE(s.find("appended: 43"), s.npos); +#endif + std::cout << s; +#endif + } ); + + return boost::report_errors(); +} diff --git a/test/diagnostic_info_test5.cpp b/test/diagnostic_info_test5.cpp new file mode 100644 index 00000000..6dff6aea --- /dev/null +++ b/test/diagnostic_info_test5.cpp @@ -0,0 +1,134 @@ +// Copyright 2018-2022 Emil Dotchevski and Reverge Studios, Inc. + +// 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) + +#ifdef BOOST_LEAF_TEST_SINGLE_HEADER +# include "leaf.hpp" +#else +# include +# include +# include +#endif + +#if BOOST_LEAF_CFG_STD_STRING +# include +#endif +#include + +#include "lightweight_test.hpp" + +namespace leaf = boost::leaf; + +namespace +{ + int counter = 0; +} + +template +struct info +{ + info(info const &) = delete; + info & operator=(info const &) = delete; + int acc = 0; + info() + { + ++counter; + } + info( info && x ): + acc(x.acc) + { + ++counter; + } + ~info() + { + --counter; + } + void accumulate() + { + ++acc; + } + friend std::ostream & operator<<( std::ostream & os, info const & x ) + { + return os << "info<" << N << ">: acc=" << x.acc; + } +}; + +leaf::result f1() +{ + return leaf::new_error(info<1>(), [](info<4> & x){ x.accumulate(); }); +} + +leaf::result f2() +{ + auto load = leaf::on_error(info<2>{}, [](){ return info<3>(); }, [](info<4> & x){ x.accumulate(); }); + return f1(); +} + +leaf::result f3() +{ + return leaf::try_handle_some( + []() -> leaf::result + { + return f2(); + }, + []( leaf::verbose_diagnostic_info const & e ) + { + return e.error(); + } ); +} + +int main() +{ + BOOST_TEST_EQ(counter, 0); + leaf::try_handle_all( + []() -> leaf::result + { + return f3(); + }, + []( info<1> const &, leaf::verbose_diagnostic_info const & di ) + { +#if BOOST_LEAF_CFG_STD_STRING + std::ostringstream st; + st << di; + std::string s = st.str(); +# if BOOST_LEAF_CFG_DIAGNOSTICS + auto const n1 = s.find("info<1>: acc=0"); + auto const n2 = s.find("info<2>: acc=0"); + auto const n3 = s.find("info<3>: acc=0"); + auto const n4 = s.find("info<4>: acc=2"); + auto const nd = s.find("Unhandled"); + BOOST_TEST_NE(n1, s.npos); + BOOST_TEST_NE(n2, s.npos); + BOOST_TEST_NE(n3, s.npos); + BOOST_TEST_NE(n4, s.npos); + BOOST_TEST_NE(nd, s.npos); + BOOST_TEST_LT(n1, nd); + BOOST_TEST_GT(n2, nd); + BOOST_TEST_GT(n3, nd); + BOOST_TEST_GT(n4, nd); + BOOST_TEST_EQ(counter, 4); +# else + BOOST_TEST_EQ(counter, 1); +# endif + std::cout << s; +#endif + }, + [] + { + std::abort(); + } ); + BOOST_TEST_EQ(counter, 0); + + leaf::try_handle_all( + []() -> leaf::result + { + return f2(); + }, + [] + { + BOOST_TEST_EQ(counter, 0); + } ); + + return boost::report_errors(); +}