1
0
forked from boostorg/core

Compare commits

...

6 Commits

Author SHA1 Message Date
jzmaddock
06efc5bbb5 Apply workaround for Intel-16
Without this I see:
```
/boost/core/noncopyable.hpp(42): error: defaulted default constructor cannot be constexpr because the corresponding implicitly declared default constructor would not be constexpr
        BOOST_CONSTEXPR noncopyable() = default;
```
See: https://travis-ci.org/boostorg/type_traits/jobs/4722892817
Not sure if later Intel versions also require this... still working on that.
2018-12-30 18:29:54 +00:00
Andrey Semashev
83ea633d09 Use multiple jobs to checkout submodules in CI. 2018-12-18 22:19:50 +03:00
Andrey Semashev
2b60d044ac Added tools/boost_install and libs/headers manual init to CI jobs. 2018-12-18 21:53:49 +03:00
Andrey Semashev
3cd1885209 Reorganized code and made __cxa_get_globals signature closer to the original.
This should resolve gcc errors caused by mismatch of the return types of
aur declaration of __cxa_get_globals and the original in cxxabi.h.

Fixes https://github.com/boostorg/core/issues/45.
2018-12-18 20:49:24 +03:00
Andrey Semashev
9d123dc9a3 Added missing include guards. 2018-11-11 13:43:04 +03:00
Andrey Semashev
82957de970 Extracted uncaught_exceptions function from Boost.Log.
The uncaught_exceptions function is functionally equivalent to
unhandled_exceptions_count in Boost.Log and implements functionality
similar to the same named C++17 standard function. Tests and docs are
also included.

One notable difference from std::uncaught_exceptions is that the return
type is unsigned rather than signed. This is deliberate as uncaught_exceptions
must never return a negative value and unsigned int better documents that.
Theoretically, as a counter, it may also overflow.
2018-11-10 17:44:13 +03:00
9 changed files with 320 additions and 3 deletions

View File

@@ -258,13 +258,15 @@ install:
- cd ..
- git clone -b $BOOST_BRANCH https://github.com/boostorg/boost.git boost-root
- cd boost-root
- git submodule init libs/headers
- git submodule init libs/assert
- git submodule init libs/config
- git submodule init libs/predef
- git submodule init libs/static_assert
- git submodule init libs/type_traits
- git submodule init tools/build
- git submodule update
- git submodule init tools/boost_install
- git submodule update --jobs 4
- cp -r $TRAVIS_BUILD_DIR/* libs/core
- ./bootstrap.sh
- ./b2 headers

View File

@@ -55,13 +55,15 @@ install:
- cd ..
- git clone -b %BOOST_BRANCH% https://github.com/boostorg/boost.git boost-root
- cd boost-root
- git submodule init libs/headers
- git submodule init libs/assert
- git submodule init libs/config
- git submodule init libs/predef
- git submodule init libs/static_assert
- git submodule init libs/type_traits
- git submodule init tools/build
- git submodule update
- git submodule init tools/boost_install
- git submodule update --jobs 4
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\core
- cmd /c bootstrap
- b2 headers

View File

@@ -57,3 +57,4 @@ criteria for inclusion is that the utility component be:
[include scoped_enum.qbk]
[include swap.qbk]
[include typeinfo.qbk]
[include uncaught_exceptions.qbk]

View File

@@ -0,0 +1,52 @@
[/
/ Copyright (c) 2018 Andrey Semashev
/
/ 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)
/]
[section:uncaught_exceptions uncaught_exceptions]
[simplesect Authors]
* Andrey Semashev
[endsimplesect]
[section Header <boost/core/uncaught_exceptions.hpp>]
The header `<boost/core/uncaught_exceptions.hpp>` defines the `boost::core::uncaught_exceptions` function,
which is a more portable implementation of the same named function introduced in C++17. The function
returns the number of the currently pending exceptions. When that function returns a value greater than 0,
throwing an exception from a destructor can terminate the program.
Unfortunately, the function cannot be implemented on every pre-C++17 compiler, although the most commonly
used compilers are supported. When the compiler does not provide the necessary functionality,
`boost::core::uncaught_exceptions` returns a non-zero value if at least one exception is pending (i.e. not
necessarily the number of pending exceptions), and `BOOST_CORE_UNCAUGHT_EXCEPTIONS_EMULATED` macro
is defined.
[section Example]
``
class my_class
{
private:
const unsigned int m_exception_count;
public:
my_class() : m_exception_count(boost::core::uncaught_exceptions())
{
}
~my_class() noexcept(false)
{
if (m_exception_count == boost::core::uncaught_exceptions())
do_something_potentially_throwing();
}
};
``
[endsect]
[endsect]
[endsect]

View File

@@ -38,7 +38,8 @@ namespace noncopyable_ // protection from unintended ADL
class noncopyable: base_token
{
protected:
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)
#if !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) && !defined(BOOST_NO_CXX11_NON_PUBLIC_DEFAULTED_FUNCTIONS)\
&& !BOOST_WORKAROUND(__ICC, <= 1600)
BOOST_CONSTEXPR noncopyable() = default;
~noncopyable() = default;
#else

View File

@@ -0,0 +1,111 @@
/*
* Copyright Andrey Semashev 2018.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file uncaught_exceptions.hpp
* \author Andrey Semashev
* \date 2018-11-10
*
* \brief This header provides an `uncaught_exception` function implementation, which was introduced in C++17.
*
* The code in this file is based on the implementation by Evgeny Panasyuk:
*
* https://github.com/panaseleus/stack_unwinding/blob/master/boost/exception/uncaught_exception_count.hpp
*/
#ifndef BOOST_CORE_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED_
#define BOOST_CORE_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED_
#include <exception>
#include <boost/config.hpp>
#if defined(BOOST_HAS_PRAGMA_ONCE)
#pragma once
#endif
// Visual Studio 14 supports N4152 std::uncaught_exceptions()
#if (defined(__cpp_lib_uncaught_exceptions) && __cpp_lib_uncaught_exceptions >= 201411) || \
(defined(_MSC_VER) && _MSC_VER >= 1900)
#define BOOST_CORE_HAS_UNCAUGHT_EXCEPTIONS
#endif
#if !defined(BOOST_CORE_HAS_UNCAUGHT_EXCEPTIONS)
// cxxabi.h availability macro
#if defined(__has_include) && (!defined(BOOST_GCC) || (__GNUC__ >= 5))
# if __has_include(<cxxabi.h>)
# define BOOST_CORE_HAS_CXXABI_H
# endif
#elif defined(__GLIBCXX__) || defined(__GLIBCPP__)
# define BOOST_CORE_HAS_CXXABI_H
#endif
#if defined(BOOST_CORE_HAS_CXXABI_H)
// MinGW GCC 4.4 seem to not work the same way the newer GCC versions do. As a result, __cxa_get_globals based implementation will always return 0.
// Just disable it for now and fall back to std::uncaught_exception().
#if !defined(__MINGW32__) || (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)))
#define BOOST_CORE_HAS_CXA_GET_GLOBALS
#include <cxxabi.h>
// Only GCC 4.7 declares __cxa_get_globals() in cxxabi.h, older compilers do not expose this function but it's there
#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407
namespace __cxxabiv1 {
struct __cxa_eh_globals;
extern "C" __cxa_eh_globals* __cxa_get_globals() BOOST_NOEXCEPT_OR_NOTHROW __attribute__((__const__));
} // namespace __cxxabiv1
#endif // defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407
#endif
#endif // defined(BOOST_CORE_HAS_CXXABI_H)
#if defined(_MSC_VER) && _MSC_VER >= 1400
#define BOOST_CORE_HAS_GETPTD
namespace boost {
namespace core {
namespace detail {
extern "C" void* _getptd();
} // namespace detail
} // namespace core
} // namespace boost
#endif // defined(_MSC_VER) && _MSC_VER >= 1400
#endif // !defined(BOOST_CORE_HAS_UNCAUGHT_EXCEPTIONS)
#if !defined(BOOST_CORE_HAS_UNCAUGHT_EXCEPTIONS) && !defined(BOOST_CORE_HAS_CXA_GET_GLOBALS) && !defined(BOOST_CORE_HAS_GETPTD)
//! This macro is defined when `uncaught_exceptions` is not guaranteed to return values greater than 1 if multiple exceptions are pending
#define BOOST_CORE_UNCAUGHT_EXCEPTIONS_EMULATED
#endif
namespace boost {
namespace core {
//! Returns the number of currently pending exceptions
inline unsigned int uncaught_exceptions() BOOST_NOEXCEPT
{
#if defined(BOOST_CORE_HAS_UNCAUGHT_EXCEPTIONS)
// C++17 implementation
return static_cast< unsigned int >(std::uncaught_exceptions());
#elif defined(BOOST_CORE_HAS_CXA_GET_GLOBALS)
// Tested on {clang 3.2,GCC 3.5.6,GCC 4.1.2,GCC 4.4.6,GCC 4.4.7}x{x32,x64}
return *(reinterpret_cast< const unsigned int* >(reinterpret_cast< const char* >(::abi::__cxa_get_globals()) + sizeof(void*))); // __cxa_eh_globals::uncaughtExceptions, x32 offset - 0x4, x64 - 0x8
#elif defined(BOOST_CORE_HAS_GETPTD)
// MSVC specific. Tested on {MSVC2005SP1,MSVC2008SP1,MSVC2010SP1,MSVC2012}x{x32,x64}.
return *(reinterpret_cast< const unsigned int* >(static_cast< const char* >(boost::core::detail::_getptd()) + (sizeof(void*) == 8 ? 0x100 : 0x90))); // _tiddata::_ProcessingThrow, x32 offset - 0x90, x64 - 0x100
#else
// Portable C++03 implementation. Does not allow to detect multiple nested exceptions.
return static_cast< unsigned int >(std::uncaught_exception());
#endif
}
} // namespace core
} // namespace boost
#undef BOOST_CORE_HAS_CXXABI_H
#undef BOOST_CORE_HAS_CXA_GET_GLOBALS
#undef BOOST_CORE_HAS_UNCAUGHT_EXCEPTIONS
#undef BOOST_CORE_HAS_GETPTD
#endif // BOOST_CORE_UNCAUGHT_EXCEPTIONS_HPP_INCLUDED_

View File

@@ -138,5 +138,8 @@ run test_lib_typeid.cpp lib_typeid : : : <link>static : test_lib_typeid_static ;
run test_lib_typeid.cpp lib_typeid : : : <link>shared <rtti>off : test_lib_typeid_shared_no_rtti ;
run test_lib_typeid.cpp lib_typeid : : : <link>static <rtti>off : test_lib_typeid_static_no_rtti ;
run uncaught_exceptions.cpp : : : <exception-handling>on ;
run uncaught_exceptions_np.cpp : : : <exception-handling>on ;
use-project /boost/core/swap : ./swap ;
build-project ./swap ;

View File

@@ -0,0 +1,55 @@
/*
* Copyright Andrey Semashev 2018.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file uncaught_exceptions.cpp
* \author Andrey Semashev
* \date 2018-11-10
*
* \brief This file contains tests for the uncaught_exceptions function.
*
* This file only contains the very basic checks of functionality that can be portably achieved
* through C++03 std::uncaught_exception.
*/
#include <boost/core/uncaught_exceptions.hpp>
#include <boost/core/lightweight_test.hpp>
struct my_exception {};
class exception_watcher
{
unsigned int& m_count;
public:
explicit exception_watcher(unsigned int& count) : m_count(count) {}
~exception_watcher() { m_count = boost::core::uncaught_exceptions(); }
};
// Tests for uncaught_exceptions when used in a destructor while an exception propagates
void test_in_destructor()
{
const unsigned int root_count = boost::core::uncaught_exceptions();
unsigned int level1_count = root_count;
try
{
exception_watcher watcher(level1_count);
throw my_exception();
}
catch (...)
{
}
BOOST_TEST_NE(root_count, level1_count);
}
int main()
{
test_in_destructor();
return boost::report_errors();
}

View File

@@ -0,0 +1,90 @@
/*
* Copyright Andrey Semashev 2018.
* Distributed under the Boost Software License, Version 1.0.
* (See accompanying file LICENSE_1_0.txt or copy at
* https://www.boost.org/LICENSE_1_0.txt)
*/
/*!
* \file uncaught_exceptions_np.cpp
* \author Andrey Semashev
* \date 2018-11-10
*
* \brief This file contains tests for the uncaught_exceptions function.
*
* This file contains checks that are compiler specific and not quite portable or require C++17.
*/
#include <boost/core/uncaught_exceptions.hpp>
#if !defined(BOOST_CORE_UNCAUGHT_EXCEPTIONS_EMULATED)
#include <boost/core/lightweight_test.hpp>
struct my_exception1 {};
struct my_exception2 {};
class exception_watcher2
{
unsigned int& m_count;
public:
explicit exception_watcher2(unsigned int& count) : m_count(count) {}
~exception_watcher2() { m_count = boost::core::uncaught_exceptions(); }
};
class exception_watcher1
{
unsigned int& m_count1;
unsigned int& m_count2;
public:
exception_watcher1(unsigned int& count1, unsigned int& count2) : m_count1(count1), m_count2(count2) {}
~exception_watcher1()
{
m_count1 = boost::core::uncaught_exceptions();
try
{
exception_watcher2 watcher2(m_count2);
throw my_exception2();
}
catch (...)
{
}
}
};
// Tests for uncaught_exceptions when used in nested destructors while an exception propagates
void test_in_nested_destructors()
{
const unsigned int root_count = boost::core::uncaught_exceptions();
unsigned int level1_count = root_count, level2_count = root_count;
try
{
exception_watcher1 watcher1(level1_count, level2_count);
throw my_exception1();
}
catch (...)
{
}
BOOST_TEST_NE(root_count, level1_count);
BOOST_TEST_NE(root_count, level2_count);
BOOST_TEST_NE(level1_count, level2_count);
}
int main()
{
test_in_nested_destructors();
return boost::report_errors();
}
#else
int main()
{
return 0;
}
#endif