From: Ville Voutilainen Date: Wed, 6 Jul 2016 22:33:20 +0000 (+0300) Subject: Implement std::any. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=52e862219926fb800c55cdf36cb2e18ac4555dac;p=gcc.git Implement std::any. * include/Makefile.am: Add any and c++17_warning.h to exported headers. * include/Makefile.in: Likewise. * include/std/any: New. * testsuite/20_util/any/assign/1.cc: Likewise. * testsuite/20_util/any/assign/2.cc: Likewise. * testsuite/20_util/any/assign/self.cc: Likewise. * testsuite/20_util/any/cons/1.cc: Likewise. * testsuite/20_util/any/cons/2.cc: Likewise. * testsuite/20_util/any/cons/aligned.cc: Likewise. * testsuite/20_util/any/cons/nontrivial.cc: Likewise. * testsuite/20_util/any/misc/any_cast.cc: Likewise. * testsuite/20_util/any/misc/any_cast_neg.cc: Likewise. * testsuite/20_util/any/misc/any_cast_no_rtti.cc: Likewise. * testsuite/20_util/any/misc/swap.cc: Likewise. * testsuite/20_util/any/modifiers/1.cc: Likewise. * testsuite/20_util/any/observers/type.cc: Likewise. * testsuite/20_util/any/typedefs.cc: Likewise. From-SVN: r238061 --- diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index edbe06a6e21..c7050e32a04 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,24 @@ +2016-07-07 Ville Voutilainen + + Implement std::any. + * include/Makefile.am: Add any and c++17_warning.h to exported headers. + * include/Makefile.in: Likewise. + * include/std/any: New. + * testsuite/20_util/any/assign/1.cc: Likewise. + * testsuite/20_util/any/assign/2.cc: Likewise. + * testsuite/20_util/any/assign/self.cc: Likewise. + * testsuite/20_util/any/cons/1.cc: Likewise. + * testsuite/20_util/any/cons/2.cc: Likewise. + * testsuite/20_util/any/cons/aligned.cc: Likewise. + * testsuite/20_util/any/cons/nontrivial.cc: Likewise. + * testsuite/20_util/any/misc/any_cast.cc: Likewise. + * testsuite/20_util/any/misc/any_cast_neg.cc: Likewise. + * testsuite/20_util/any/misc/any_cast_no_rtti.cc: Likewise. + * testsuite/20_util/any/misc/swap.cc: Likewise. + * testsuite/20_util/any/modifiers/1.cc: Likewise. + * testsuite/20_util/any/observers/type.cc: Likewise. + * testsuite/20_util/any/typedefs.cc: Likewise. + 2016-07-06 Ville Voutilainen Add a new header for diagnosing the use of C++17 facilities diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index 9cd6a85b9a2..4c9cb06e095 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -27,6 +27,7 @@ std_srcdir = ${glibcxx_srcdir}/include/std std_builddir = . std_headers = \ ${std_srcdir}/algorithm \ + ${std_srcdir}/any \ ${std_srcdir}/array \ ${std_srcdir}/atomic \ ${std_srcdir}/bitset \ @@ -92,6 +93,7 @@ bits_headers = \ ${bits_srcdir}/boost_concept_check.h \ ${bits_srcdir}/c++0x_warning.h \ ${bits_srcdir}/c++14_warning.h \ + ${bits_srcdir}/c++17_warning.h \ ${bits_srcdir}/char_traits.h \ ${bits_srcdir}/codecvt.h \ ${bits_srcdir}/concept_check.h \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index 43735f9174c..bddeb885c10 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -317,6 +317,7 @@ std_srcdir = ${glibcxx_srcdir}/include/std std_builddir = . std_headers = \ ${std_srcdir}/algorithm \ + ${std_srcdir}/any \ ${std_srcdir}/array \ ${std_srcdir}/atomic \ ${std_srcdir}/bitset \ @@ -382,6 +383,7 @@ bits_headers = \ ${bits_srcdir}/boost_concept_check.h \ ${bits_srcdir}/c++0x_warning.h \ ${bits_srcdir}/c++14_warning.h \ + ${bits_srcdir}/c++17_warning.h \ ${bits_srcdir}/char_traits.h \ ${bits_srcdir}/codecvt.h \ ${bits_srcdir}/concept_check.h \ diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any new file mode 100644 index 00000000000..2e8baa6f8dd --- /dev/null +++ b/libstdc++-v3/include/std/any @@ -0,0 +1,523 @@ +// -*- C++ -*- + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/any + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ANY +#define _GLIBCXX_ANY 1 + +#pragma GCC system_header + +#if __cplusplus <= 201402L +# include +#else + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + /** + * @brief Exception class thrown by a failed @c any_cast + * @ingroup exceptions + */ + class bad_any_cast : public bad_cast + { + public: + virtual const char* what() const noexcept { return "bad any_cast"; } + }; + + [[gnu::noreturn]] inline void __throw_bad_any_cast() + { +#if __cpp_exceptions + throw bad_any_cast{}; +#else + __builtin_abort(); +#endif + } + + /** + * @brief A type-safe container of any type. + * + * An @c any object's state is either empty or it stores a contained object + * of CopyConstructible type. + */ + class any + { + // Holds either pointer to a heap object or the contained object itself. + union _Storage + { + // This constructor intentionally doesn't initialize anything. + _Storage() = default; + + // Prevent trivial copies of this type, buffer might hold a non-POD. + _Storage(const _Storage&) = delete; + _Storage& operator=(const _Storage&) = delete; + + void* _M_ptr; + aligned_storage::type _M_buffer; + }; + + template, + bool _Fits = (sizeof(_Tp) <= sizeof(_Storage)) + && (alignof(_Tp) <= alignof(_Storage))> + using _Internal = std::integral_constant; + + template + struct _Manager_internal; // uses small-object optimization + + template + struct _Manager_external; // creates contained object on the heap + + template + using _Manager = conditional_t<_Internal<_Tp>::value, + _Manager_internal<_Tp>, + _Manager_external<_Tp>>; + + template> + using _Decay = enable_if_t::value, _Decayed>; + + public: + // construct/destruct + + /// Default constructor, creates an empty object. + any() noexcept : _M_manager(nullptr) { } + + /// Copy constructor, copies the state of @p __other + any(const any& __other) + { + if (__other.empty()) + _M_manager = nullptr; + else + { + _Arg __arg; + __arg._M_any = this; + __other._M_manager(_Op_clone, &__other, &__arg); + } + } + + /** + * @brief Move constructor, transfer the state from @p __other + * + * @post @c __other.empty() (this postcondition is a GNU extension) + */ + any(any&& __other) noexcept + { + if (__other.empty()) + _M_manager = nullptr; + else + { + _Arg __arg; + __arg._M_any = this; + __other._M_manager(_Op_xfer, &__other, &__arg); + } + } + + /// Construct with a copy of @p __value as the contained object. + template , + typename _Mgr = _Manager<_Tp>, + typename enable_if::value, + bool>::type = true> + any(_ValueType&& __value) + : _M_manager(&_Mgr::_S_manage) + { + _Mgr::_S_create(_M_storage, std::forward<_ValueType>(__value)); + static_assert(is_copy_constructible<_Tp>::value, + "The contained object must be CopyConstructible"); + } + + /// Construct with a copy of @p __value as the contained object. + template , + typename _Mgr = _Manager<_Tp>, + typename enable_if::value, + bool>::type = false> + any(_ValueType&& __value) + : _M_manager(&_Mgr::_S_manage) + { + _Mgr::_S_create(_M_storage, __value); + static_assert(is_copy_constructible<_Tp>::value, + "The contained object must be CopyConstructible"); + } + + /// Destructor, calls @c clear() + ~any() { clear(); } + + // assignments + + /// Copy the state of another object. + any& operator=(const any& __rhs) + { + if (__rhs.empty()) + clear(); + else if (this != &__rhs) + { + if (!empty()) + _M_manager(_Op_destroy, this, nullptr); + _Arg __arg; + __arg._M_any = this; + __rhs._M_manager(_Op_clone, &__rhs, &__arg); + } + return *this; + } + + /** + * @brief Move assignment operator + * + * @post @c __rhs.empty() (not guaranteed for other implementations) + */ + any& operator=(any&& __rhs) noexcept + { + if (__rhs.empty()) + clear(); + else if (this != &__rhs) + { + if (!empty()) + _M_manager(_Op_destroy, this, nullptr); + _Arg __arg; + __arg._M_any = this; + __rhs._M_manager(_Op_xfer, &__rhs, &__arg); + } + return *this; + } + + /// Store a copy of @p __rhs as the contained object. + template + enable_if_t>::value, any&> + operator=(_ValueType&& __rhs) + { + *this = any(std::forward<_ValueType>(__rhs)); + return *this; + } + + // modifiers + + /// If not empty, destroy the contained object. + void clear() noexcept + { + if (!empty()) + { + _M_manager(_Op_destroy, this, nullptr); + _M_manager = nullptr; + } + } + + /// Exchange state with another object. + void swap(any& __rhs) noexcept + { + if (empty() && __rhs.empty()) + return; + + if (!empty() && !__rhs.empty()) + { + if (this == &__rhs) + return; + + any __tmp; + _Arg __arg; + __arg._M_any = &__tmp; + __rhs._M_manager(_Op_xfer, &__rhs, &__arg); + __arg._M_any = &__rhs; + _M_manager(_Op_xfer, this, &__arg); + __arg._M_any = this; + __tmp._M_manager(_Op_xfer, &__tmp, &__arg); + } + else + { + any* __empty = empty() ? this : &__rhs; + any* __full = empty() ? &__rhs : this; + _Arg __arg; + __arg._M_any = __empty; + __full->_M_manager(_Op_xfer, __full, &__arg); + } + } + + // observers + + /// Reports whether there is a contained object or not. + bool empty() const noexcept { return _M_manager == nullptr; } + +#if __cpp_rtti + /// The @c typeid of the contained object, or @c typeid(void) if empty. + const type_info& type() const noexcept + { + if (empty()) + return typeid(void); + _Arg __arg; + _M_manager(_Op_get_type_info, this, &__arg); + return *__arg._M_typeinfo; + } +#endif + + template + static constexpr bool __is_valid_cast() + { return __or_, is_copy_constructible<_Tp>>::value; } + + private: + enum _Op { + _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer + }; + + union _Arg + { + void* _M_obj; + const std::type_info* _M_typeinfo; + any* _M_any; + }; + + void (*_M_manager)(_Op, const any*, _Arg*); + _Storage _M_storage; + + template + friend void* __any_caster(const any* __any); + + // Manage in-place contained object. + template + struct _Manager_internal + { + static void + _S_manage(_Op __which, const any* __anyp, _Arg* __arg); + + template + static void + _S_create(_Storage& __storage, _Up&& __value) + { + void* __addr = &__storage._M_buffer; + ::new (__addr) _Tp(std::forward<_Up>(__value)); + } + }; + + // Manage external contained object. + template + struct _Manager_external + { + static void + _S_manage(_Op __which, const any* __anyp, _Arg* __arg); + + template + static void + _S_create(_Storage& __storage, _Up&& __value) + { + __storage._M_ptr = new _Tp(std::forward<_Up>(__value)); + } + }; + }; + + /// Exchange the states of two @c any objects. + inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); } + + /** + * @brief Access the contained object. + * + * @tparam _ValueType A const-reference or CopyConstructible type. + * @param __any The object to access. + * @return The contained object. + * @throw bad_any_cast If + * __any.type() != typeid(remove_reference_t<_ValueType>) + * + */ + template + inline _ValueType any_cast(const any& __any) + { + static_assert(any::__is_valid_cast<_ValueType>(), + "Template argument must be a reference or CopyConstructible type"); + auto __p = any_cast>>(&__any); + if (__p) + return *__p; + __throw_bad_any_cast(); + } + + /** + * @brief Access the contained object. + * + * @tparam _ValueType A reference or CopyConstructible type. + * @param __any The object to access. + * @return The contained object. + * @throw bad_any_cast If + * __any.type() != typeid(remove_reference_t<_ValueType>) + * + * + * @{ + */ + template + inline _ValueType any_cast(any& __any) + { + static_assert(any::__is_valid_cast<_ValueType>(), + "Template argument must be a reference or CopyConstructible type"); + auto __p = any_cast>(&__any); + if (__p) + return *__p; + __throw_bad_any_cast(); + } + + template::value + || is_lvalue_reference<_ValueType>::value, + bool>::type = true> + inline _ValueType any_cast(any&& __any) + { + static_assert(any::__is_valid_cast<_ValueType>(), + "Template argument must be a reference or CopyConstructible type"); + auto __p = any_cast>(&__any); + if (__p) + return *__p; + __throw_bad_any_cast(); + } + + template::value + && !is_lvalue_reference<_ValueType>::value, + bool>::type = false> + inline _ValueType any_cast(any&& __any) + { + static_assert(any::__is_valid_cast<_ValueType>(), + "Template argument must be a reference or CopyConstructible type"); + auto __p = any_cast>(&__any); + if (__p) + return std::move(*__p); + __throw_bad_any_cast(); + } + // @} + + template + void* __any_caster(const any* __any) + { + if (__any->_M_manager != &any::_Manager>::_S_manage) + return nullptr; + any::_Arg __arg; + __any->_M_manager(any::_Op_access, __any, &__arg); + return __arg._M_obj; + } + + /** + * @brief Access the contained object. + * + * @tparam _ValueType The type of the contained object. + * @param __any A pointer to the object to access. + * @return The address of the contained object if + * __any != nullptr && __any.type() == typeid(_ValueType) + * , otherwise a null pointer. + * + * @{ + */ + template + inline const _ValueType* any_cast(const any* __any) noexcept + { + if (__any) + return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); + return nullptr; + } + + template + inline _ValueType* any_cast(any* __any) noexcept + { + if (__any) + return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); + return nullptr; + } + // @} + + template + void + any::_Manager_internal<_Tp>:: + _S_manage(_Op __which, const any* __any, _Arg* __arg) + { + // The contained object is in _M_storage._M_buffer + auto __ptr = reinterpret_cast(&__any->_M_storage._M_buffer); + switch (__which) + { + case _Op_access: + __arg->_M_obj = const_cast<_Tp*>(__ptr); + break; + case _Op_get_type_info: +#if __cpp_rtti + __arg->_M_typeinfo = &typeid(_Tp); +#endif + break; + case _Op_clone: + ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr); + __arg->_M_any->_M_manager = __any->_M_manager; + break; + case _Op_destroy: + __ptr->~_Tp(); + break; + case _Op_xfer: + ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr); + __ptr->~_Tp(); + __arg->_M_any->_M_manager = __any->_M_manager; + const_cast(__any)->_M_manager = nullptr; + break; + } + } + + template + void + any::_Manager_external<_Tp>:: + _S_manage(_Op __which, const any* __any, _Arg* __arg) + { + // The contained object is *_M_storage._M_ptr + auto __ptr = static_cast(__any->_M_storage._M_ptr); + switch (__which) + { + case _Op_access: + __arg->_M_obj = const_cast<_Tp*>(__ptr); + break; + case _Op_get_type_info: +#if __cpp_rtti + __arg->_M_typeinfo = &typeid(_Tp); +#endif + break; + case _Op_clone: + __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr); + __arg->_M_any->_M_manager = __any->_M_manager; + break; + case _Op_destroy: + delete __ptr; + break; + case _Op_xfer: + __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr; + __arg->_M_any->_M_manager = __any->_M_manager; + const_cast(__any)->_M_manager = nullptr; + break; + } + } + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 + +#endif // _GLIBCXX_ANY diff --git a/libstdc++-v3/testsuite/20_util/any/assign/1.cc b/libstdc++-v3/testsuite/20_util/any/assign/1.cc new file mode 100644 index 00000000000..582a92d2f07 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/assign/1.cc @@ -0,0 +1,60 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +using std::any; + +void test01() +{ + any x; + any y; + y = x; + VERIFY( x.empty() ); + VERIFY( y.empty() ); + + y = std::move(x); + VERIFY( x.empty() ); + VERIFY( y.empty() ); +} + +void test02() +{ + any x(1); + any y; + y = x; + VERIFY( !x.empty() ); + VERIFY( !y.empty() ); + + x = std::move(y); + VERIFY( !x.empty() ); + VERIFY( y.empty() ); + + x = y; + VERIFY( x.empty() ); + VERIFY( y.empty() ); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/assign/2.cc b/libstdc++-v3/testsuite/20_util/any/assign/2.cc new file mode 100644 index 00000000000..b333e5df796 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/assign/2.cc @@ -0,0 +1,51 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +using std::any; +using std::any_cast; + +struct X +{ + bool moved = false; + bool moved_from = false; + X() = default; + X(const X&) = default; + X(X&& x) : moved(true) { x.moved_from = true; } +}; + +void test01() +{ + X x; + any a1; + a1 = x; + VERIFY(x.moved_from == false); + any a2; + a2 = std::move(x); + VERIFY(x.moved_from == true); + VERIFY(any_cast(a2).moved == true ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/assign/self.cc b/libstdc++-v3/testsuite/20_util/any/assign/self.cc new file mode 100644 index 00000000000..e773efad11c --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/assign/self.cc @@ -0,0 +1,93 @@ +// Copyright (C) 2015-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } + +#include +#include +#include + +std::set live_objects; + +struct A { + A() { live_objects.insert(this); } + ~A() { live_objects.erase(this); } + A(const A& a) { VERIFY(live_objects.count(&a)); live_objects.insert(this); } +}; + +void +test01() +{ + using std::any; + + any a; + a = a; + VERIFY( a.empty() ); + + a = A{}; + a = a; + VERIFY( !a.empty() ); + + a.clear(); + VERIFY( live_objects.empty() ); +} + +void +test02() +{ + using std::any; + + struct X { + any a; + }; + + X x; + std::swap(x, x); // results in "self-move-assignment" of X::a + VERIFY( x.a.empty() ); + + x.a = A{}; + std::swap(x, x); // results in "self-move-assignment" of X::a + VERIFY( !x.a.empty() ); + + x.a.clear(); + VERIFY( live_objects.empty() ); +} + +void +test03() +{ + using std::any; + + any a; + a.swap(a); + VERIFY( a.empty() ); + + a = A{}; + a.swap(a); + VERIFY( !a.empty() ); + + a.clear(); + VERIFY( live_objects.empty() ); +} + +int +main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/cons/1.cc b/libstdc++-v3/testsuite/20_util/any/cons/1.cc new file mode 100644 index 00000000000..d66320413d4 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/cons/1.cc @@ -0,0 +1,58 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +using std::any; + +void test01() +{ + any x; + VERIFY( x.empty() ); + + any y(x); + VERIFY( x.empty() ); + VERIFY( y.empty() ); + + any z(std::move(y)); + VERIFY( y.empty() ); + VERIFY( z.empty() ); +} + +void test02() +{ + any x(1); + VERIFY( !x.empty() ); + + any y(x); + VERIFY( !x.empty() ); + VERIFY( !y.empty() ); + + any z(std::move(y)); + VERIFY( y.empty() ); + VERIFY( !z.empty() ); +} + +int main() +{ + test01(); + test02(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/cons/2.cc b/libstdc++-v3/testsuite/20_util/any/cons/2.cc new file mode 100644 index 00000000000..613fa626d06 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/cons/2.cc @@ -0,0 +1,49 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +using std::any; +using std::any_cast; + +struct X +{ + bool moved = false; + bool moved_from = false; + X() = default; + X(const X&) = default; + X(X&& x) : moved(true) { x.moved_from = true; } +}; + +void test01() +{ + X x; + any a1(x); + VERIFY(x.moved_from == false); + any a2(std::move(x)); + VERIFY(x.moved_from == true); + VERIFY(any_cast(a2).moved == true ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/cons/aligned.cc b/libstdc++-v3/testsuite/20_util/any/cons/aligned.cc new file mode 100644 index 00000000000..9b23d8ac0f4 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/cons/aligned.cc @@ -0,0 +1,52 @@ +// Copyright (C) 2015-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } + +#include +#include +#include + +// Alignment requiremnts of this type prevent it being stored in 'any' +struct alignas(2 * alignof(void*)) X { }; + +bool +stored_internally(void* obj, const std::any& a) +{ + std::uintptr_t a_addr = reinterpret_cast(&a); + std::uintptr_t a_end = a_addr + sizeof(a); + std::uintptr_t obj_addr = reinterpret_cast(obj); + return (a_addr <= obj_addr) && (obj_addr < a_end); +} + +void +test01() +{ + std::any a = X{}; + X& x = std::any_cast(a); + VERIFY( !stored_internally(&x, a) ); + + a = 'X'; + char& c = std::any_cast(a); + VERIFY( stored_internally(&c, a) ); +} + +int +main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/cons/nontrivial.cc b/libstdc++-v3/testsuite/20_util/any/cons/nontrivial.cc new file mode 100644 index 00000000000..bb46452c619 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/cons/nontrivial.cc @@ -0,0 +1,75 @@ +// Copyright (C) 2015-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++17" } + +#include +#include + +struct LocationAware +{ + LocationAware() { } + ~LocationAware() { VERIFY(self == this); } + LocationAware(const LocationAware&) { } + LocationAware& operator=(const LocationAware&) { return *this; } + LocationAware(LocationAware&&) noexcept { } + LocationAware& operator=(LocationAware&&) noexcept { return *this; } + + void* const self = this; +}; +static_assert(std::is_nothrow_move_constructible::value, ""); +static_assert(!std::is_trivially_copyable::value, ""); + +using std::any; + +void +test01() +{ + + LocationAware l; + any a = l; +} + +void +test02() +{ + LocationAware l; + any a = l; + any b = a; + { + any tmp = std::move(a); + a = std::move(b); + b = std::move(tmp); + } +} + +void +test03() +{ + LocationAware l; + any a = l; + any b = a; + swap(a, b); +} + +int +main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc new file mode 100644 index 00000000000..96f9419e070 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast.cc @@ -0,0 +1,114 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include +#include + +using std::any; +using std::any_cast; + +void test01() +{ + using std::string; + using std::strcmp; + + // taken from example in N3804 proposal + + any x(5); // x holds int + VERIFY(any_cast(x) == 5); // cast to value + any_cast(x) = 10; // cast to reference + VERIFY(any_cast(x) == 10); + + x = "Meow"; // x holds const char* + VERIFY(strcmp(any_cast(x), "Meow") == 0); + any_cast(x) = "Harry"; + VERIFY(strcmp(any_cast(x), "Harry") == 0); + + x = string("Meow"); // x holds string + string s, s2("Jane"); + s = move(any_cast(x)); // move from any + VERIFY(s == "Meow"); + any_cast(x) = move(s2); // move to any + VERIFY(any_cast(x) == "Jane"); + + string cat("Meow"); + const any y(cat); // const y holds string + VERIFY(any_cast(y) == cat); +} + +void test02() +{ + using std::bad_any_cast; + any x(1); + auto p = any_cast(&x); + VERIFY(p == nullptr); + + x = 1.0; + p = any_cast(&x); + VERIFY(p != nullptr); + + x = any(); + p = any_cast(&x); + VERIFY(p == nullptr); + + try { + any_cast(x); + VERIFY(false); + } catch (const bad_any_cast&) { + } +} + +static int move_count = 0; + +void test03() +{ + struct MoveEnabled + { + MoveEnabled(MoveEnabled&&) + { + ++move_count; + } + MoveEnabled() = default; + MoveEnabled(const MoveEnabled&) = default; + }; + MoveEnabled m; + MoveEnabled m2 = any_cast(any(m)); + VERIFY(move_count == 1); + MoveEnabled&& m3 = any_cast(any(m)); + VERIFY(move_count == 1); + struct MoveDeleted + { + MoveDeleted(MoveDeleted&&) = delete; + MoveDeleted() = default; + MoveDeleted(const MoveDeleted&) = default; + }; + MoveDeleted md; + MoveDeleted&& md2 = any_cast(any(std::move(md))); + MoveDeleted&& md3 = any_cast(any(std::move(md))); +} + +int main() +{ + test01(); + test02(); + test03(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc new file mode 100644 index 00000000000..43c6c6b4a26 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc @@ -0,0 +1,30 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +void test01() +{ + using std::any; + using std::any_cast; + + const any y(1); + any_cast(y); // { dg-error "qualifiers" "" { target { *-*-* } } 357 } +} diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_no_rtti.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_no_rtti.cc new file mode 100644 index 00000000000..fa16f2371be --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_no_rtti.cc @@ -0,0 +1,54 @@ +// { dg-options "-std=gnu++17 -fno-rtti" } +// { dg-do run } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include +#include + +using std::any; +using std::any_cast; + +void test01() +{ + using std::bad_any_cast; + any x(1); + auto p = any_cast(&x); + VERIFY(p == nullptr); + + x = 1.0; + p = any_cast(&x); + VERIFY(p != nullptr); + + x = any(); + p = any_cast(&x); + VERIFY(p == nullptr); + + try { + any_cast(x); + VERIFY(false); + } catch (const bad_any_cast&) { + } +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/misc/swap.cc b/libstdc++-v3/testsuite/20_util/any/misc/swap.cc new file mode 100644 index 00000000000..0b3e1eb26de --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/misc/swap.cc @@ -0,0 +1,38 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +using std::any; + +void test01() +{ + any x(1); + any y; + swap(x, y); + VERIFY( x.empty() ); + VERIFY( !y.empty() ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/modifiers/1.cc b/libstdc++-v3/testsuite/20_util/any/modifiers/1.cc new file mode 100644 index 00000000000..36b9c247843 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/modifiers/1.cc @@ -0,0 +1,44 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +using std::any; + +void test01() +{ + any x(1); + any y; + x.swap(y); + VERIFY( x.empty() ); + VERIFY( !y.empty() ); + x.swap(y); + VERIFY( !x.empty() ); + VERIFY( y.empty() ); + + x.clear(); + VERIFY( x.empty() ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/observers/type.cc b/libstdc++-v3/testsuite/20_util/any/observers/type.cc new file mode 100644 index 00000000000..af4dc30c766 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/observers/type.cc @@ -0,0 +1,39 @@ +// { dg-options "-std=gnu++17" } +// { dg-do run } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include + +using std::any; + +void test01() +{ + any x; + VERIFY( x.type() == typeid(void) ); + x = 1; + VERIFY( x.type() == typeid(int) ); + x = any(); + VERIFY( x.type() == typeid(void) ); +} + +int main() +{ + test01(); +} diff --git a/libstdc++-v3/testsuite/20_util/any/typedefs.cc b/libstdc++-v3/testsuite/20_util/any/typedefs.cc new file mode 100644 index 00000000000..11a57924b25 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/any/typedefs.cc @@ -0,0 +1,30 @@ +// { dg-options "-std=gnu++17" } +// { dg-do compile } + +// Copyright (C) 2014-2016 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a moved_to of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include +#include +#include + +using check1_t = std::any; +using check2_t = std::bad_any_cast; + +static_assert(std::is_base_of::value, + "bad_any_cast must derive from bad_cast"); +