// This test comes from upstream bug // https://sourceware.org/bugzilla/show_bug.cgi?id=21296 // // It has to be compiled once with clang++ and once with g++, like // this: // // clang++ -std=c++14 -o test40-PR21296-libclang.so -shared -fPIC test40-PR21296-clanggcc.cc -g // // g++ -o test40-PR21296-libgcc.so -shared -fPIC test40-PR21296-clanggcc.cc -g // extern "C" void free(void*) throw (); extern "C" char* strdup(const char*); struct STR { STR(const char* S): C(strdup(S)) {} ~STR() { free(C); } STR(STR&& O): C(O.C) { O.C = 0; } char* C; }; extern "C" int printf(const char*,...); namespace std { typedef unsigned long size_t; struct true_type { static constexpr bool value = true; }; struct false_type { static constexpr bool value = false; }; // Reference transformations. /// remove_reference template struct remove_reference { typedef _Tp type; }; template struct remove_reference<_Tp&> { typedef _Tp type; }; template struct remove_reference<_Tp&&> { typedef _Tp type; }; /** * @brief Forward an lvalue. * @return The parameter cast to the specified type. * * This function is used to implement "perfect forwarding". */ template constexpr _Tp&& forward(typename std::remove_reference<_Tp>::type& __t) noexcept { return static_cast<_Tp&&>(__t); } /** * @brief Forward an rvalue. * @return The parameter cast to the specified type. * * This function is used to implement "perfect forwarding". */ template constexpr _Tp&& forward(typename std::remove_reference<_Tp>::type&& __t) noexcept { return static_cast<_Tp&&>(__t); } /** * @brief Convert a value to an rvalue. * @param __t A thing of arbitrary type. * @return The parameter cast to an rvalue-reference to allow moving it. */ template constexpr typename std::remove_reference<_Tp>::type&& move(_Tp&& __t) noexcept { return static_cast::type&&>(__t); } // Adds a const reference to a non-reference type. template struct __add_c_ref { typedef const _Tp& type; }; template struct __add_c_ref<_Tp&> { typedef _Tp& type; }; template struct _Head_base; template struct _Head_base<_Idx, _Head, false> { constexpr _Head_base() : _M_head_impl() { } constexpr _Head_base(const _Head& __h) : _M_head_impl(__h) { } template constexpr _Head_base(_UHead&& __h) : _M_head_impl(std::forward<_UHead>(__h)) { } static constexpr const _Head& _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } _Head _M_head_impl; }; template struct _Tuple_impl; template struct _Tuple_impl<_Idx> { template friend class _Tuple_impl; _Tuple_impl() = default; }; template class tuple; template struct _Tuple_impl<_Idx, _Head, _Tail...> : public _Tuple_impl<_Idx + 1, _Tail...>, private _Head_base<_Idx, _Head, /*__empty_not_final<_Head>::value*/ 0> { template friend class _Tuple_impl; typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; typedef _Head_base<_Idx, _Head, /*__empty_not_final<_Head>::value*/ 0> _Base; static constexpr const _Head& _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } static constexpr const _Inherited& _M_tail(const _Tuple_impl& __t) noexcept { return __t; } template explicit constexpr _Tuple_impl(_UHead&& __head, _UTail&&... __tail) : _Inherited(std::forward<_UTail>(__tail)...), _Base(std::forward<_UHead>(__head)) { } constexpr _Tuple_impl(_Tuple_impl&& __in) noexcept(false) : _Inherited(std::move(_M_tail(__in))), _Base(std::forward<_Head>(_M_head(__in))) { } }; /// Primary class template, tuple template class tuple : public _Tuple_impl<0, _Elements...> { typedef _Tuple_impl<0, _Elements...> _Inherited; public: template explicit constexpr tuple(_UElements&&... __elements) : _Inherited(std::forward<_UElements>(__elements)...) { } }; /// Gives the type of the ith element of a given tuple type. template struct tuple_element; /** * Recursive case for tuple_element: strip off the first element in * the tuple and retrieve the (i-1)th element of the remaining tuple. */ template struct tuple_element<__i, tuple<_Head, _Tail...> > : tuple_element<__i - 1, tuple<_Tail...> > { }; /** * Basis case for tuple_element: The first element is the one we're seeking. */ template struct tuple_element<0, tuple<_Head, _Tail...> > { typedef _Head type; }; template struct tuple_element<__i, const _Tp> { typedef const typename tuple_element<__i, _Tp>::type type; }; template constexpr typename __add_c_ref<_Head>::type __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } // Return a reference (const reference, rvalue reference) to the ith element // of a tuple. Any const or non-const ref elements are returned with their // original type. template constexpr typename __add_c_ref< typename tuple_element<__i, tuple<_Elements...>>::type >::type get(const tuple<_Elements...>& __t) noexcept { return __get_helper<__i>(__t); } template tuple<_Elements&&...> forward_as_tuple(_Elements&&... __args) noexcept { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } } // namespace std using namespace std; template void tpl(T x) { printf("tpl: &C=%p\n", get<0>(x).C); printf("tpl: C=%s\n", get<0>(x).C); }; template tuple<_Elements&&...> my_forward_as_tuple(_Elements&&... __args) noexcept { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } namespace { void call(const char* pass, STR&& __k) { printf("%s: &rval=%p\n", pass, &__k); printf("%s: &C=%p\n", pass, __k.C); tpl(my_forward_as_tuple(std::move(__k))); } } void clang() { call("clang", "a"); }