/* { dg-do compile } */ /* { dg-options "-O2 -std=gnu++14 -fdump-tree-sra" } */ #include #define EGGS_CXX11_CONSTEXPR constexpr #define EGGS_CXX11_STATIC_CONSTEXPR static constexpr #define EGGS_CXX14_CONSTEXPR constexpr #define EGGS_CXX11_NOEXCEPT noexcept namespace eggs { namespace variants { namespace detail { struct empty { EGGS_CXX11_CONSTEXPR bool operator==(empty) const { return true; } EGGS_CXX11_CONSTEXPR bool operator<(empty) const { return false; } }; template struct identity { using type = T; }; template struct index { EGGS_CXX11_STATIC_CONSTEXPR std::size_t value = I; }; template struct pack { using type = pack; EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = sizeof...(Ts); }; template struct pack_c { using type = pack_c; EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = sizeof...(Vs); }; /////////////////////////////////////////////////////////////////////////// template struct _make_index_pack_twice; template struct _make_index_pack_twice< pack_c , false > : pack_c {}; template struct _make_index_pack_twice< pack_c , true > : pack_c {}; template struct _make_index_pack : _make_index_pack_twice< typename _make_index_pack::type , N % 2 != 0 > {}; template <> struct _make_index_pack<1> : pack_c {}; template <> struct _make_index_pack<0> : pack_c {}; template using make_index_pack = typename _make_index_pack::type; template struct _index_pack; template struct _index_pack> : _make_index_pack {}; template using index_pack = typename _index_pack::type; /////////////////////////////////////////////////////////////////////////// template struct all_of; template struct all_of> : std::integral_constant< bool , std::is_same< pack_c , pack_c // true... >::value > {}; template struct all_of> : all_of> {}; template struct any_of; template struct any_of> : std::integral_constant< bool , !all_of>::value > {}; template struct any_of> : any_of> {}; /////////////////////////////////////////////////////////////////////////// template struct _indexed {}; template > struct _indexer; template struct _indexer, pack_c> : _indexed... {}; empty _at_index(...); template identity _at_index(_indexed const&); template struct at_index : decltype(_at_index(_indexer{})) {}; empty _index_of(...); template index _index_of(_indexed const&); template struct index_of : decltype(_index_of(_indexer{})) {}; }}} namespace eggs { namespace variants { namespace detail { template struct _union; /////////////////////////////////////////////////////////////////////////// template struct _union, IsTriviallyDestructible> {}; template struct _union, true> { EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = 1 + sizeof...(Ts); template EGGS_CXX11_CONSTEXPR _union(index<0>, Args&&... args) : _head(std::forward(args)...) {} template EGGS_CXX11_CONSTEXPR _union(index, Args&&... args) : _tail(index{}, std::forward(args)...) {} EGGS_CXX14_CONSTEXPR void* target() EGGS_CXX11_NOEXCEPT { return &_target; } EGGS_CXX11_CONSTEXPR void const* target() const EGGS_CXX11_NOEXCEPT { return &_target; } EGGS_CXX14_CONSTEXPR T& get(index<0>) EGGS_CXX11_NOEXCEPT { return this->_head; } EGGS_CXX11_CONSTEXPR T const& get(index<0>) const EGGS_CXX11_NOEXCEPT { return this->_head; } template < std::size_t I , typename U = typename at_index>::type > EGGS_CXX14_CONSTEXPR U& get(index) EGGS_CXX11_NOEXCEPT { return this->_tail.get(index{}); } template < std::size_t I , typename U = typename at_index>::type > EGGS_CXX11_CONSTEXPR U const& get(index) const EGGS_CXX11_NOEXCEPT { return this->_tail.get(index{}); } private: union { char _target; T _head; _union, true> _tail; }; }; /////////////////////////////////////////////////////////////////////////// template struct _storage; template struct _storage, true, true> : _union< pack , all_of...>>::value > { using base_type = _union< pack , all_of...>>::value >; EGGS_CXX11_CONSTEXPR _storage() EGGS_CXX11_NOEXCEPT : base_type{index<0>{}} , _which{0} {} _storage(_storage const& rhs) = default; _storage(_storage&& rhs) = default; template EGGS_CXX11_CONSTEXPR _storage(index which, Args&&... args) : base_type{which, std::forward(args)...} , _which{I} {} _storage& operator=(_storage const& rhs) = default; _storage& operator=(_storage&& rhs) = default; EGGS_CXX11_CONSTEXPR std::size_t which() const { return _which; } using base_type::target; using base_type::get; protected: std::size_t _which; }; template using storage = _storage< pack , all_of...>>::value , all_of...>>::value >; }}} namespace eggs { namespace variants { template class variant; namespace detail { /////////////////////////////////////////////////////////////////////// namespace _best_match { template struct overloads {}; template struct overloads, I> : overloads, I + 1> { using fun_ptr = index(*)(T); operator fun_ptr(); }; template auto _invoke(F&&, T&&) -> decltype(std::declval()(std::declval())); struct _fallback {}; _fallback _invoke(...); template < typename T, typename U , typename R = decltype(_best_match::_invoke( std::declval(), std::declval())) > struct result_of : R {}; template struct result_of {}; } template struct index_of_best_match : _best_match::result_of<_best_match::overloads, U> {}; } template class variant { public: EGGS_CXX11_CONSTEXPR variant() EGGS_CXX11_NOEXCEPT = delete; variant(variant const& rhs) = default; variant(variant&& rhs) = default; template < typename U , typename Enable = typename std::enable_if::type, variant >::value>::type , std::size_t I = detail::index_of_best_match< U&&, detail::pack>::value , typename T = typename detail::at_index< I, detail::pack>::type > EGGS_CXX11_CONSTEXPR variant(U&& v) noexcept( std::is_nothrow_constructible::value) : _storage{detail::index{}, std::forward(v)} {} ~variant() = default; variant& operator=(variant const& rhs) = delete; private: detail::storage _storage; }; }} template struct ref_proxy : Base { using Base::Base; ref_proxy() : Base() { } ref_proxy(Base ptr) : Base(std::move(ptr)) { } }; template struct inplace_ref { explicit inplace_ref(T inner) : inner_(inner) { } T inner_; }; template struct variant_ref { variant_ref() = delete; explicit variant_ref(eggs::variants::variant t) : inner_storage_(t) { } template variant_ref(ref_proxy ptr) : inner_storage_(ptr.inner_storage_) {} private: eggs::variants::variant inner_storage_; }; struct option_1 { void *a, *b, *c, *d, *e; }; struct option_2 { }; using option_ref = variant_ref; struct qual_option { qual_option(ref_proxy type, int quals) : type_(type) , quals_(quals) { } explicit qual_option(ref_proxy type) : qual_option(type, 0) { } ref_proxy type_; int quals_; }; inline ref_proxy make_object_1() { return ref_proxy(option_2()); } inline ref_proxy make_object_2() { return make_object_1(); } inline inplace_ref make_object_3(ref_proxy&& a0) { return inplace_ref(qual_option(a0)); } inline ref_proxy > make_object_4(ref_proxy&& a0) { return make_object_3(std::move(a0)); } ref_proxy > f() __attribute__((noinline)); ref_proxy > f() { return make_object_4(make_object_2()); } int main(int argc, char* argv[]) { for (;;) f(); } // XFAILed due to PR116416 /* { dg-final { scan-tree-dump "Removing load:.*ptr;" "sra" { xfail { *-*-* } } } } */