1
0
forked from boostorg/core

Compare commits

..

17 Commits

Author SHA1 Message Date
Peter Dimov
8ea2ac50fe Document BOOST_TEST_TRAIT_SAME 2019-02-06 18:12:25 +02:00
Peter Dimov
7f96d56eff Simplify implementation of BOOST_TEST_TRAIT_SAME 2019-02-06 04:38:27 +02:00
Peter Dimov
dcbe62c6bf Add BOOST_TEST_TRAIT_SAME 2019-02-06 02:02:40 +02:00
Peter Dimov
a8ef600c30 Remove duplicate Travis job 2019-01-28 23:16:52 +02:00
Peter Dimov
d8895bab46 Mark checked_delete as noexcept 2019-01-28 19:15:24 +02:00
Andrey Semashev
a8c870e2e7 Merge branch 'develop' 2019-01-15 13:34:33 +03:00
Peter Dimov
9db11ce554 Add more xcode configurations to Travis 2019-01-13 04:26:10 +02:00
Peter Dimov
3f3bba7869 Add test/cmake_subdir_test 2019-01-12 21:25:10 +02:00
Andrey Semashev
61b4e1a45d Use multiple jobs to checkout submodules in CI. 2019-01-12 21:24:45 +02:00
Andrey Semashev
b1949c0509 Added tools/boost_install and libs/headers manual init to CI jobs. 2019-01-12 21:24:28 +02:00
Andrey Semashev
7d70451b49 Updated the comment about __cxa_uncaught_exceptions. 2019-01-08 04:47:51 +03:00
Andrey Semashev
bf932b4908 Removed the use of __cxa_uncaught_exceptions.
Travis CI shows linking errors on Linux and OS X when __cxa_uncaught_exceptions
is used to implement uncaught_exceptions. There's probably some library missing,
which should be linked in implicitly by the compiler, or the library indeed
does not export the symbol. In any case, __cxa_get_globals-based implementation
should provide the same effect.
2019-01-08 04:17:24 +03:00
Andrey Semashev
e3629dd1c1 Added libc++abi-dev package installation, changed OS X image to xcode10.1.
This is in attempt to debug/work around strange issues in CI with cxxabi.h
provided by libc++abi-dev. The header declares __cxa_uncaught_exceptions
function, but on linking stage the function is missing. The current theory
is that the header and the libc++abi library do not match on CI machines for
some reason, and this commit tries to mitigate or verify that.
2019-01-08 00:29:53 +03:00
Andrey Semashev
dea6b04157 Added workarounds for gcc < 4.7 on Linux and OpenBSD.
Apparently, gcc < 4.7 on Linux also don't have __cxa_get_globals
declaration in cxxabi.h. Declare the function ourselves.

Also, on OpenBSD it seems there is no declaration either, and
on that platform the function implementation has no exception
specification, like on FreeBSD. Add a declaration of that platform.

Lastly, changed __cxa_get_globals and _getptd-based implementations
to avoid violating strict aliasing rules. This is still formally UB
to access structure fields like we do, but this is one less reason to
cause miscompilation or compiler warnings.
2019-01-08 00:23:09 +03:00
Andrey Semashev
9f9da9dc9b Limit __cxa_uncaught_exceptions to only since libc++abi 1002 and later. 2019-01-07 13:34:52 +03:00
Andrey Semashev
cdcc50a455 Added an implementation for uncaught_exceptions for libc++abi.
This should fix compilation errors due to missing declaration of
__cxa_get_globals when compiled against libc++ on Linux.
2019-01-07 02:14:31 +03:00
Andrey Semashev
6f3e6254e7 Only declare __cxa_get_globals on MinGW gcc < 4.7, where it's needed.
This should work around differences between the function signatures on other
platforms, like FreeBSD, for example.
2019-01-06 21:29:15 +03:00
8 changed files with 173 additions and 14 deletions

View File

@@ -240,6 +240,7 @@ matrix:
apt:
packages:
- libc++-dev
- libc++abi-dev
- os: linux
compiler: clang++-libc++
@@ -248,10 +249,27 @@ matrix:
apt:
packages:
- libc++-dev
- libc++abi-dev
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
osx_image: xcode7.3
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
osx_image: xcode8.3
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
osx_image: xcode9.4
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=03,11,14,1z
osx_image: xcode10.1
- os: linux
compiler: g++

View File

@@ -1,7 +1,7 @@
[/
Copyright 2010, 2011 Beman Dawes
Copyright 2013 Ion Gaztanaga
Copyright 2014, 2017 Peter Dimov
Copyright 2014-2019 Peter Dimov
Copyright 2017 Kohei Takahashi
Distributed under the Boost Software License, Version 1.0.
@@ -253,6 +253,7 @@ return a boolean value.
``
#define BOOST_TEST_TRAIT_TRUE((Trait)) /*unspecified*/
#define BOOST_TEST_TRAIT_FALSE((Trait)) /*unspecified*/
#define BOOST_TEST_TRAIT_SAME(Type1, Type2) /*unspecified*/
``
[endsect]
@@ -280,6 +281,20 @@ message containing `Trait`. Note the double set of parentheses.
[endsect]
[section BOOST_TEST_TRAIT_SAME]
``
BOOST_TEST_TRAIT_SAME(Type1, Type2)
``
If the two types are not the same, increases the error count and outputs a
message containing them. This macro requires that the compiler supports
variadic macros and `__VA_ARGS__`. (Note that unlike `BOOST_TEST_TRAIT_TRUE`
and `BOOST_TEST_TRAIT_FALSE`, this macro only requires a single set of
parentheses.)
[endsect]
[section Example]
``
@@ -297,6 +312,8 @@ int main()
{
BOOST_TEST_TRAIT_TRUE(( is_same<X<int, long>::type, int> ));
BOOST_TEST_TRAIT_SAME( X<int, long>::type, int );
return boost::report_errors();
}
``

View File

@@ -7,6 +7,8 @@
# pragma once
#endif
#include <boost/config.hpp>
//
// boost/checked_delete.hpp
//
@@ -26,7 +28,7 @@ namespace boost
// verify that types are complete for increased safety
template<class T> inline void checked_delete(T * x)
template<class T> inline void checked_delete(T * x) BOOST_NOEXCEPT
{
// intentionally complex - simplification causes regressions
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
@@ -34,7 +36,7 @@ template<class T> inline void checked_delete(T * x)
delete x;
}
template<class T> inline void checked_array_delete(T * x)
template<class T> inline void checked_array_delete(T * x) BOOST_NOEXCEPT
{
typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
(void) sizeof(type_must_be_complete);
@@ -46,7 +48,7 @@ template<class T> struct checked_deleter
typedef void result_type;
typedef T * argument_type;
void operator()(T * x) const
void operator()(T * x) const BOOST_NOEXCEPT
{
// boost:: disables ADL
boost::checked_delete(x);
@@ -58,7 +60,7 @@ template<class T> struct checked_array_deleter
typedef void result_type;
typedef T * argument_type;
void operator()(T * x) const
void operator()(T * x) const BOOST_NOEXCEPT
{
boost::checked_array_delete(x);
}

View File

@@ -9,7 +9,7 @@
// boost/core/lightweight_test_trait.hpp
//
// BOOST_TEST_TRAIT_TRUE, BOOST_TEST_TRAIT_FALSE
// BOOST_TEST_TRAIT_TRUE, BOOST_TEST_TRAIT_FALSE, BOOST_TEST_TRAIT_SAME
//
// Copyright 2014 Peter Dimov
//
@@ -19,6 +19,7 @@
#include <boost/core/lightweight_test.hpp>
#include <boost/core/typeinfo.hpp>
#include <boost/core/is_same.hpp>
namespace boost
{
@@ -46,11 +47,37 @@ template< class T > inline void test_trait_impl( char const * trait, void (*)( T
}
}
template<class T> inline bool test_trait_same_impl_( T )
{
return T::value;
}
template<class T1, class T2> inline void test_trait_same_impl( char const * types,
boost::core::is_same<T1, T2> same, char const * file, int line, char const * function )
{
if( test_trait_same_impl_( same ) )
{
test_results();
}
else
{
BOOST_LIGHTWEIGHT_TEST_OSTREAM
<< file << "(" << line << "): test 'is_same<" << types << ">'"
<< " failed in function '" << function
<< "' ('" << boost::core::demangled_name( BOOST_CORE_TYPEID(T1) )
<< "' != '" << boost::core::demangled_name( BOOST_CORE_TYPEID(T2) ) << "')"
<< std::endl;
++test_results().errors();
}
}
} // namespace detail
} // namespace boost
#define BOOST_TEST_TRAIT_TRUE(type) ( ::boost::detail::test_trait_impl(#type, (void(*)type)0, true, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
#define BOOST_TEST_TRAIT_FALSE(type) ( ::boost::detail::test_trait_impl(#type, (void(*)type)0, false, __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
#define BOOST_TEST_TRAIT_SAME(...) ( ::boost::detail::test_trait_same_impl(#__VA_ARGS__, ::boost::core::is_same<__VA_ARGS__>(), __FILE__, __LINE__, BOOST_CURRENT_FUNCTION) )
#endif // #ifndef BOOST_CORE_LIGHTWEIGHT_TEST_TRAIT_HPP

View File

@@ -46,20 +46,36 @@
#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
#if !(defined(__MINGW32__) && (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 405))
#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
#include <cstring>
#define BOOST_CORE_HAS_CXA_GET_GLOBALS
// At least on MinGW and Linux, only GCC since 4.7 declares __cxa_get_globals() in cxxabi.h. Older versions of GCC do not expose this function but it's there.
// On OpenBSD, it seems, the declaration is also missing.
// Note that at least on FreeBSD 11, cxxabi.h declares __cxa_get_globals with a different exception specification, so we can't declare the function unconditionally.
// On Linux with clang and libc++ and on OS X, there is a version of cxxabi.h from libc++abi that doesn't declare __cxa_get_globals, but provides __cxa_uncaught_exceptions.
// The function only appeared in version _LIBCPPABI_VERSION >= 1002 of the library. Unfortunately, there are linking errors about undefined reference to __cxa_uncaught_exceptions
// on Ubuntu Trusty and OS X, so we avoid using it and forward-declare __cxa_get_globals instead.
#if !defined(__FreeBSD__) && \
( \
(defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 407) || \
defined(__OpenBSD__) || \
defined(_LIBCPPABI_VERSION) \
)
namespace __cxxabiv1 {
struct __cxa_eh_globals;
#if defined(__OpenBSD__)
extern "C" __cxa_eh_globals* __cxa_get_globals();
#else
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
} // namespace __cxxabiv1
#endif
#endif // !(defined(__MINGW32__) && (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) < 405))
#endif // defined(BOOST_CORE_HAS_CXXABI_H)
#if defined(_MSC_VER) && _MSC_VER >= 1400
#include <cstring>
#define BOOST_CORE_HAS_GETPTD
namespace boost {
namespace core {
@@ -89,10 +105,14 @@ inline unsigned int uncaught_exceptions() BOOST_NOEXCEPT
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
unsigned int count;
std::memcpy(&count, reinterpret_cast< const unsigned char* >(::abi::__cxa_get_globals()) + sizeof(void*), sizeof(count)); // __cxa_eh_globals::uncaughtExceptions, x32 offset - 0x4, x64 - 0x8
return count;
#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
unsigned int count;
std::memcpy(&count, static_cast< const unsigned char* >(boost::core::detail::_getptd()) + (sizeof(void*) == 8u ? 0x100 : 0x90), sizeof(count)); // _tiddata::_ProcessingThrow, x32 offset - 0x90, x64 - 0x100
return count;
#else
// Portable C++03 implementation. Does not allow to detect multiple nested exceptions.
return static_cast< unsigned int >(std::uncaught_exception());

View File

@@ -76,6 +76,8 @@ run lightweight_test_lt_le_test.cpp ;
run lightweight_test_gt_ge_test.cpp ;
run lightweight_test_eq_nullptr.cpp ;
run lightweight_test_test3.cpp ;
run lightweight_test_test4.cpp ;
run lightweight_test_test5.cpp ;
run-fail lightweight_test_fail.cpp ;
run-fail lightweight_test_fail2.cpp ;

View File

@@ -0,0 +1,36 @@
//
// Test for BOOST_TEST_TRAIT_SAME
//
// Copyright 2014, 2019 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/core/lightweight_test_trait.hpp>
struct X
{
typedef int type;
};
template<class T1, class T2> struct Y
{
typedef T1 type;
};
int main()
{
BOOST_TEST_TRAIT_SAME(X, X);
BOOST_TEST_TRAIT_SAME(void, void);
BOOST_TEST_TRAIT_SAME(char[1], char[1]);
BOOST_TEST_TRAIT_SAME(char[], char[]);
BOOST_TEST_TRAIT_SAME(void(), void());
BOOST_TEST_TRAIT_SAME(X::type, X::type);
BOOST_TEST_TRAIT_SAME(X::type, Y<int, float>::type);
BOOST_TEST_TRAIT_SAME(Y<int, float>, Y<int, float>);
BOOST_TEST_TRAIT_SAME(Y<void, float>::type, void);
return boost::report_errors();
}

View File

@@ -0,0 +1,37 @@
//
// Negative test for BOOST_TEST_TRAIT_SAME
//
// Copyright 2014, 2019 Peter Dimov
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/core/lightweight_test_trait.hpp>
struct X
{
typedef int type;
};
template<class T1, class T2> struct Y
{
typedef T1 type;
};
int main()
{
BOOST_TEST_TRAIT_SAME(char[1], char[2]);
BOOST_TEST_TRAIT_SAME(char[1], char[]);
BOOST_TEST_TRAIT_SAME(char[1], char*);
BOOST_TEST_TRAIT_SAME(void(), void(int));
BOOST_TEST_TRAIT_SAME(void(), void(*)());
BOOST_TEST_TRAIT_SAME(X, void);
BOOST_TEST_TRAIT_SAME(X::type, void);
BOOST_TEST_TRAIT_SAME(X, Y<void, void>);
BOOST_TEST_TRAIT_SAME(X::type, Y<float, int>::type);
BOOST_TEST_TRAIT_SAME(Y<int, float>, Y<int, double>);
return boost::report_errors() == 10;
}