You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
6.9 KiB

// 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<typename _Tp>
struct remove_reference
{ typedef _Tp type; };
template<typename _Tp>
struct remove_reference<_Tp&>
{ typedef _Tp type; };
template<typename _Tp>
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<typename _Tp>
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<typename _Tp>
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<typename _Tp>
constexpr typename std::remove_reference<_Tp>::type&&
move(_Tp&& __t) noexcept
{ return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
// Adds a const reference to a non-reference type.
template<typename _Tp>
struct __add_c_ref
{ typedef const _Tp& type; };
template<typename _Tp>
struct __add_c_ref<_Tp&>
{ typedef _Tp& type; };
template<std::size_t _Idx, typename _Head, bool _IsEmptyNotFinal>
struct _Head_base;
template<std::size_t _Idx, typename _Head>
struct _Head_base<_Idx, _Head, false>
{
constexpr _Head_base()
: _M_head_impl() { }
constexpr _Head_base(const _Head& __h)
: _M_head_impl(__h) { }
template<typename _UHead, typename = true_type>
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<std::size_t _Idx, typename... _Elements>
struct _Tuple_impl;
template<std::size_t _Idx>
struct _Tuple_impl<_Idx>
{
template<std::size_t, typename...> friend class _Tuple_impl;
_Tuple_impl() = default;
};
template<typename... _Elements>
class tuple;
template<std::size_t _Idx, typename _Head, typename... _Tail>
struct _Tuple_impl<_Idx, _Head, _Tail...>
: public _Tuple_impl<_Idx + 1, _Tail...>,
private _Head_base<_Idx, _Head, /*__empty_not_final<_Head>::value*/
0>
{
template<std::size_t, typename...> 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<typename _UHead, typename... _UTail, typename = false_type>
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<typename... _Elements>
class tuple : public _Tuple_impl<0, _Elements...>
{
typedef _Tuple_impl<0, _Elements...> _Inherited;
public:
template<typename... _UElements, typename = true_type>
explicit
constexpr tuple(_UElements&&... __elements)
: _Inherited(std::forward<_UElements>(__elements)...) { }
};
/// Gives the type of the ith element of a given tuple type.
template<std::size_t __i, typename _Tp>
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<std::size_t __i, typename _Head, typename... _Tail>
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<typename _Head, typename... _Tail>
struct tuple_element<0, tuple<_Head, _Tail...> >
{
typedef _Head type;
};
template<std::size_t __i, typename _Tp>
struct tuple_element<__i, const _Tp>
{
typedef const typename tuple_element<__i, _Tp>::type type;
};
template<std::size_t __i, typename _Head, typename... _Tail>
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<std::size_t __i, typename... _Elements>
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<typename... _Elements>
tuple<_Elements&&...>
forward_as_tuple(_Elements&&... __args) noexcept
{ return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); }
} // namespace std
using namespace std;
template <class T>
void tpl(T x) {
printf("tpl: &C=%p\n", get<0>(x).C);
printf("tpl: C=%s\n", get<0>(x).C);
};
template<typename... _Elements>
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");
}