Compare commits

..

7 Commits

Author SHA1 Message Date
Peter Dimov
fe26439f39 Update bases_test.cpp 2021-03-13 21:45:24 +02:00
Peter Dimov
a876e619b7 Use detail/compute_base_modifiers.hpp in detail/bases.hpp 2021-03-13 21:39:53 +02:00
Peter Dimov
19bb4254bc Add a final class test to test/compute_base_modifiers 2021-03-13 21:29:49 +02:00
Peter Dimov
109bb07163 Add detail/compute_base_modifiers.hpp 2021-03-13 21:23:27 +02:00
Peter Dimov
39c438eb08 Enable UBSan for clang++-libc++, Apple Clang 2021-03-13 19:44:55 +02:00
Peter Dimov
ae31a5142f Disable Boost.JSON warnings 2021-03-13 19:34:28 +02:00
Peter Dimov
bcb70cea2c Switch newer clangs to bionic 2021-03-13 19:09:11 +02:00
6 changed files with 304 additions and 51 deletions

View File

@@ -143,6 +143,7 @@ matrix:
- ubuntu-toolchain-r-test
- os: linux
dist: bionic
compiler: clang++-5.0
env: TOOLSET=clang CXXSTD=14,1z
addons:
@@ -153,6 +154,7 @@ matrix:
- ubuntu-toolchain-r-test
- os: linux
dist: bionic
compiler: clang++-6.0
env: TOOLSET=clang CXXSTD=14,17
addons:
@@ -163,6 +165,7 @@ matrix:
- ubuntu-toolchain-r-test
- os: linux
dist: bionic
compiler: clang++-7
env: TOOLSET=clang CXXSTD=14,17,2a
addons:
@@ -171,9 +174,10 @@ matrix:
- clang-7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-7
- llvm-toolchain-bionic-7
- os: linux
dist: bionic
compiler: clang++-8
env: TOOLSET=clang CXXSTD=14,17,2a
addons:
@@ -182,10 +186,10 @@ matrix:
- clang-8
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
- llvm-toolchain-bionic-8
- os: linux
dist: xenial
dist: bionic
compiler: clang++-9
env: TOOLSET=clang CXXSTD=14,17,2a
addons:
@@ -194,11 +198,11 @@ matrix:
- clang-9
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
- sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
dist: xenial
dist: bionic
compiler: clang++-10
env: TOOLSET=clang CXXSTD=14,17,2a
addons:
@@ -207,13 +211,39 @@ matrix:
- clang-10
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-10 main'
- sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
dist: trusty
dist: bionic
compiler: clang++-11
env: TOOLSET=clang CXXSTD=14,17,2a
addons:
apt:
packages:
- clang-11
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-11 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
dist: bionic
compiler: clang++-12
env: UBSAN=1 TOOLSET=clang CXXSTD=14,17,2a UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
- clang-12
sources:
- ubuntu-toolchain-r-test
- sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-12 main'
key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
- os: linux
dist: bionic
compiler: clang++-libc++
env: TOOLSET=clang CXXSTD=14,1z
env: UBSAN=1 TOOLSET=clang CXXSTD=14,17,2a UBSAN_OPTIONS=print_stacktrace=1
addons:
apt:
packages:
@@ -221,7 +251,7 @@ matrix:
- os: osx
compiler: clang++
env: TOOLSET=clang COMPILER=clang++ CXXSTD=14,1z
env: UBSAN=1 TOOLSET=clang COMPILER=clang++ CXXSTD=14,1z UBSAN_OPTIONS=print_stacktrace=1
install:

View File

@@ -5,7 +5,7 @@
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/modifiers.hpp>
#include <boost/describe/detail/compute_base_modifiers.hpp>
#include <boost/describe/detail/pp_for_each.hpp>
#include <boost/describe/detail/list.hpp>
#include <type_traits>
@@ -17,29 +17,13 @@ namespace describe
namespace detail
{
// is_public_base_of
template<class T, class U> using is_public_base_of = std::is_convertible<U*, T*>;
// is_virtual_base_of
template<class T, class U, class = void> struct can_cast: std::false_type {};
template<class T, class U> struct can_cast<T, U, decltype((void)(U*)(T*)0)>: std::true_type {};
template<class T, class U> using is_virtual_base_of =
std::integral_constant<bool, can_cast<U, T>::value && !can_cast<T, U>::value>;
// base_modifiers
template<class C, class B> constexpr unsigned base_modifiers() noexcept
{
return (is_public_base_of<B, C>::value? mod_public: mod_private) | (is_virtual_base_of<B, C>::value? mod_virtual: 0);
}
// base_descriptor
template<class C, class B> struct base_descriptor
{
static_assert( std::is_base_of<B, C>::value, "A type listed as a base is not one" );
using type = B;
static constexpr unsigned modifiers = base_modifiers<C, B>();
static constexpr unsigned modifiers = compute_base_modifiers<C, B>();
};
template<class C, class B> constexpr unsigned base_descriptor<C, B>::modifiers;

View File

@@ -0,0 +1,73 @@
#ifndef BOOST_DESCRIBE_DETAIL_COMPUTE_BASE_MODIFIERS_HPP_INCLUDED
#define BOOST_DESCRIBE_DETAIL_COMPUTE_BASE_MODIFIERS_HPP_INCLUDED
// Copyright 2020, 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/modifiers.hpp>
#include <type_traits>
namespace boost
{
namespace describe
{
namespace detail
{
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable: 4594) // can never be instantiated - indirect virtual base class is inaccessible
# pragma warning(disable: 4624) // destructor was implicitly defined as deleted
#endif
// is_public_base_of
template<class T, class U> using is_public_base_of = std::is_convertible<U*, T*>;
// is_protected_base_of
struct ipb_final
{
template<class T, class U> using fn = std::false_type;
};
struct ipb_non_final
{
template<class T, class U> struct fn: U
{
static std::true_type f( T* );
template<class X> static auto g( X x ) -> decltype( f(x) );
static std::false_type g( ... );
using type = decltype( g((U*)0) );
};
};
template<class T, class U> using is_protected_base_of =
typename std::conditional<std::is_final<U>::value || std::is_union<U>::value, ipb_final, ipb_non_final>::type::template fn<T, U>::type;
// is_virtual_base_of
template<class T, class U, class = void> struct can_cast: std::false_type {};
template<class T, class U> struct can_cast<T, U, decltype((void)(U*)(T*)0)>: std::true_type {};
template<class T, class U> using is_virtual_base_of =
std::integral_constant<bool, can_cast<U, T>::value && !can_cast<T, U>::value>;
// compute_base_modifiers
template<class C, class B> constexpr unsigned compute_base_modifiers() noexcept
{
return (is_public_base_of<B, C>::value? mod_public: (is_protected_base_of<B, C>::value? mod_protected: mod_private)) | (is_virtual_base_of<B, C>::value? mod_virtual: 0);
}
#if defined(_MSC_VER)
# pragma warning(pop)
#endif
} // namespace detail
} // namespace describe
} // namespace boost
#endif // #ifndef BOOST_DESCRIBE_DETAIL_COMPUTE_BASE_MODIFIERS_HPP_INCLUDED

View File

@@ -17,7 +17,10 @@ run quick.cpp ;
run pp_for_each_test.cpp ;
run enumerators_test.cpp ;
run compute_base_modifiers.cpp ;
run bases_test.cpp ;
run members_test.cpp ;
run members_test2.cpp ;
run members_test3.cpp ;
@@ -31,12 +34,15 @@ explicit describe_cxx14 ;
local CXX14 = [ check-target-builds describe_cxx14 describe_cxx14 : : <build>no ] ;
local JSON = <library>/boost//json/<warnings>off "<toolset>msvc-14.0:<build>no" ;
local SERIALIZATION = <library>/boost//serialization/<warnings>off "-<toolset>clang:<warnings-as-errors>on" ;
run ../example/printing_enums_ct.cpp : : : $(CXX14) ;
run ../example/printing_enums_rt.cpp : : : $(CXX14) ;
run ../example/enum_to_string.cpp : : : $(CXX14) ;
run ../example/string_to_enum.cpp : : : $(CXX14) ;
run ../example/print_function.cpp : : : $(CXX14) ;
run ../example/to_json.cpp /boost//json : : : $(CXX14) <toolset>msvc-14.0:<build>no ;
run ../example/from_json.cpp /boost//json : : : $(CXX14) <toolset>msvc-14.0:<build>no ;
run ../example/serialization.cpp /boost//serialization/<warnings>off : : : $(CXX14) "-<toolset>clang:<warnings-as-errors>on" ;
run ../example/json_rpc.cpp /boost//json : : : $(CXX14) <toolset>msvc-14.0:<build>no ;
run ../example/to_json.cpp : : : $(CXX14) $(JSON) ;
run ../example/from_json.cpp : : : $(CXX14) $(JSON) ;
run ../example/serialization.cpp : : : $(CXX14) $(SERIALIZATION) ;
run ../example/json_rpc.cpp : : : $(CXX14) $(JSON) ;

View File

@@ -25,15 +25,26 @@ struct X3
{
};
struct X4
struct V1
{
V1(int);
};
struct V2
{
V2(int);
};
struct V3
{
V3(int);
};
struct Y: public X1, protected X2, private X3, public virtual V1, protected virtual V2, private virtual V3
{
};
struct Y: public X1, private X2, public virtual X3, private virtual X4
{
};
BOOST_DESCRIBE_STRUCT(Y, (X1, X2, X3, X4), ())
BOOST_DESCRIBE_STRUCT(Y, (X1, X2, X3, V1, V2, V3), ())
#if !defined(BOOST_DESCRIBE_CXX14)
@@ -57,22 +68,46 @@ int main()
BOOST_TEST_EQ( mp_size<L>::value, 0 );
}
{
using L = describe_bases<X, mod_public>;
BOOST_TEST_EQ( mp_size<L>::value, 0 );
}
{
using L = describe_bases<X, mod_protected>;
BOOST_TEST_EQ( mp_size<L>::value, 0 );
}
{
using L = describe_bases<X, mod_private>;
BOOST_TEST_EQ( mp_size<L>::value, 0 );
}
{
using L = describe_bases<Y, mod_any_access>;
BOOST_TEST_EQ( mp_size<L>::value, 4 );
BOOST_TEST_EQ( mp_size<L>::value, 6 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X1 );
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_public );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, X2 );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_private );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_protected );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 2>::type, X3 );
BOOST_TEST_EQ( (mp_at_c<L, 2>::modifiers), mod_public | mod_virtual );
BOOST_TEST_EQ( (mp_at_c<L, 2>::modifiers), mod_private );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 3>::type, X4 );
BOOST_TEST_EQ( (mp_at_c<L, 3>::modifiers), mod_private | mod_virtual );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 3>::type, V1 );
BOOST_TEST_EQ( (mp_at_c<L, 3>::modifiers), mod_public | mod_virtual );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 4>::type, V2 );
BOOST_TEST_EQ( (mp_at_c<L, 4>::modifiers), mod_protected | mod_virtual );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 5>::type, V3 );
BOOST_TEST_EQ( (mp_at_c<L, 5>::modifiers), mod_private | mod_virtual );
}
{
@@ -83,28 +118,34 @@ int main()
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X1 );
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_public );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, X3 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, V1 );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_public | mod_virtual );
}
{
using L = describe_bases<Y, mod_protected>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X2 );
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_protected );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, V2 );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_protected | mod_virtual );
}
{
using L = describe_bases<Y, mod_private>;
BOOST_TEST_EQ( mp_size<L>::value, 2 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X2 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 0>::type, X3 );
BOOST_TEST_EQ( (mp_at_c<L, 0>::modifiers), mod_private );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, X4 );
BOOST_TEST_TRAIT_SAME( typename mp_at_c<L, 1>::type, V3 );
BOOST_TEST_EQ( (mp_at_c<L, 1>::modifiers), mod_private | mod_virtual );
}
{
using L = describe_bases<Y, mod_protected>;
BOOST_TEST_EQ( mp_size<L>::value, 0 );
}
return boost::report_errors();
}

View File

@@ -0,0 +1,119 @@
// Copyright 2021 Peter Dimov
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt
#include <boost/describe/detail/config.hpp>
#if !defined(BOOST_DESCRIBE_CXX14)
#include <boost/config/pragma_message.hpp>
BOOST_PRAGMA_MESSAGE("Skipping test because C++14 is not available")
int main() {}
#else
#include <boost/describe/detail/compute_base_modifiers.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
struct X1
{
};
struct X2
{
};
struct X3
{
};
struct V1
{
V1(int);
};
struct V2
{
V2(int);
};
struct V3
{
V3(int);
};
struct Y: public X1, protected X2, private X3, public virtual V1, protected virtual V2, private virtual V3
{
};
struct Z final: public X1, protected X2, private X3, public virtual V1, protected virtual V2, private virtual V3
{
};
int main()
{
using namespace boost::describe::detail;
using namespace boost::describe;
BOOST_TEST( (is_public_base_of<X1, Y>::value) );
BOOST_TEST( (!is_virtual_base_of<X1, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, X1>()), mod_public );
BOOST_TEST( (!is_public_base_of<X2, Y>::value) );
BOOST_TEST( (is_protected_base_of<X2, Y>::value) );
BOOST_TEST( (!is_virtual_base_of<X2, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, X2>()), mod_protected );
BOOST_TEST( (!is_public_base_of<X3, Y>::value) );
BOOST_TEST( (!is_protected_base_of<X3, Y>::value) );
BOOST_TEST( (!is_virtual_base_of<X3, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, X3>()), mod_private );
BOOST_TEST( (is_public_base_of<V1, Y>::value) );
BOOST_TEST( (is_virtual_base_of<V1, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, V1>()), mod_public | mod_virtual );
BOOST_TEST( (!is_public_base_of<V2, Y>::value) );
BOOST_TEST( (is_protected_base_of<V2, Y>::value) );
BOOST_TEST( (is_virtual_base_of<V2, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, V2>()), mod_protected | mod_virtual );
BOOST_TEST( (!is_public_base_of<V3, Y>::value) );
BOOST_TEST( (!is_protected_base_of<V3, Y>::value) );
BOOST_TEST( (is_virtual_base_of<V3, Y>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Y, V3>()), mod_private | mod_virtual );
BOOST_TEST( (is_public_base_of<X1, Z>::value) );
BOOST_TEST( (!is_virtual_base_of<X1, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, X1>()), mod_public );
BOOST_TEST( (!is_public_base_of<X2, Z>::value) );
BOOST_TEST( (!is_protected_base_of<X2, Z>::value) );
BOOST_TEST( (!is_virtual_base_of<X2, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, X2>()), mod_private );
BOOST_TEST( (!is_public_base_of<X3, Z>::value) );
BOOST_TEST( (!is_protected_base_of<X3, Z>::value) );
BOOST_TEST( (!is_virtual_base_of<X3, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, X3>()), mod_private );
BOOST_TEST( (is_public_base_of<V1, Z>::value) );
BOOST_TEST( (is_virtual_base_of<V1, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, V1>()), mod_public | mod_virtual );
BOOST_TEST( (!is_public_base_of<V2, Z>::value) );
BOOST_TEST( (!is_protected_base_of<V2, Z>::value) );
BOOST_TEST( (is_virtual_base_of<V2, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, V2>()), mod_private | mod_virtual );
BOOST_TEST( (!is_public_base_of<V3, Z>::value) );
BOOST_TEST( (!is_protected_base_of<V3, Z>::value) );
BOOST_TEST( (is_virtual_base_of<V3, Z>::value) );
BOOST_TEST_EQ( (compute_base_modifiers<Z, V3>()), mod_private | mod_virtual );
return boost::report_errors();
}
#endif // !defined(BOOST_DESCRIBE_CXX14)