Fix all tests that fail with -sanitize=return.
[official-gcc.git] / gcc / testsuite / g++.dg / tree-ssa / pr78687.C
blob698458f0e9a5f1f9a92601027075bc5b330a2699
1 /* { dg-do compile } */
2 /* { dg-options "-O2 -std=gnu++14 -fdump-tree-sra" } */
4 #include <utility>
6 #define EGGS_CXX11_CONSTEXPR constexpr
7 #define EGGS_CXX11_STATIC_CONSTEXPR static constexpr
8 #define EGGS_CXX14_CONSTEXPR constexpr
9 #define EGGS_CXX11_NOEXCEPT noexcept
11 namespace eggs { namespace variants { namespace detail
13     struct empty
14     {
15         EGGS_CXX11_CONSTEXPR bool operator==(empty) const { return true; }
16         EGGS_CXX11_CONSTEXPR bool operator<(empty) const { return false; }
17     };
19     template <typename T>
20     struct identity
21     {
22         using type = T;
23     };
25     template <std::size_t I>
26     struct index
27     {
28         EGGS_CXX11_STATIC_CONSTEXPR std::size_t value = I;
29     };
31     template <typename ...Ts>
32     struct pack
33     {
34         using type = pack;
35         EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = sizeof...(Ts);
36     };
38     template <typename T, T ...Vs>
39     struct pack_c
40     {
41         using type = pack_c;
42         EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = sizeof...(Vs);
43     };
45     ///////////////////////////////////////////////////////////////////////////
46     template <typename Is, bool Odd>
47     struct _make_index_pack_twice;
49     template <std::size_t ...Is>
50     struct _make_index_pack_twice<
51         pack_c<std::size_t, Is...>
52       , false
53     > : pack_c<std::size_t, Is..., (sizeof...(Is) + Is)...>
54     {};
56     template <std::size_t ...Is>
57     struct _make_index_pack_twice<
58         pack_c<std::size_t, Is...>
59       , true
60     > : pack_c<std::size_t, Is..., (sizeof...(Is) + Is)..., sizeof...(Is) * 2>
61     {};
63     template <std::size_t N>
64     struct _make_index_pack
65       : _make_index_pack_twice<
66             typename _make_index_pack<N / 2>::type
67           , N % 2 != 0
68         >
69     {};
71     template <>
72     struct _make_index_pack<1>
73       : pack_c<std::size_t, 0>
74     {};
76     template <>
77     struct _make_index_pack<0>
78       : pack_c<std::size_t>
79     {};
81     template <std::size_t N>
82     using make_index_pack = typename _make_index_pack<N>::type;
84     template <typename Ts>
85     struct _index_pack;
87     template <typename ...Ts>
88     struct _index_pack<pack<Ts...>>
89       : _make_index_pack<sizeof...(Ts)>
90     {};
92     template <typename Ts>
93     using index_pack = typename _index_pack<Ts>::type;
95     ///////////////////////////////////////////////////////////////////////////
96     template <typename Vs>
97     struct all_of;
99     template <bool ...Vs>
100     struct all_of<pack_c<bool, Vs...>>
101       : std::integral_constant<
102             bool
103           , std::is_same<
104                 pack_c<bool, Vs...>
105               , pack_c<bool, (Vs || true)...> // true...
106             >::value
107         >
108     {};
110     template <typename ...Ts>
111     struct all_of<pack<Ts...>>
112       : all_of<pack_c<bool, (Ts::value)...>>
113     {};
115     template <typename ...Vs>
116     struct any_of;
118     template <bool ...Vs>
119     struct any_of<pack_c<bool, Vs...>>
120       : std::integral_constant<
121             bool
122           , !all_of<pack_c<bool, !Vs...>>::value
123         >
124     {};
126     template <typename ...Ts>
127     struct any_of<pack<Ts...>>
128       : any_of<pack_c<bool, (Ts::value)...>>
129     {};
131     ///////////////////////////////////////////////////////////////////////////
132     template <std::size_t I, typename T>
133     struct _indexed {};
135     template <typename Ts, typename Is = index_pack<Ts>>
136     struct _indexer;
138     template <typename ...Ts, std::size_t ...Is>
139     struct _indexer<pack<Ts...>, pack_c<std::size_t, Is...>>
140       : _indexed<Is, Ts>...
141     {};
143     empty _at_index(...);
145     template <std::size_t I, typename T>
146     identity<T> _at_index(_indexed<I, T> const&);
148     template <std::size_t I, typename Ts>
149     struct at_index
150       : decltype(_at_index<I>(_indexer<Ts>{}))
151     {};
153     empty _index_of(...);
155     template <typename T, std::size_t I>
156     index<I> _index_of(_indexed<I, T> const&);
158     template <typename T, typename Ts>
159     struct index_of
160       : decltype(_index_of<T>(_indexer<Ts>{}))
161     {};
164 namespace eggs { namespace variants { namespace detail
166     template <typename Ts, bool IsTriviallyDestructible>
167     struct _union;
169     ///////////////////////////////////////////////////////////////////////////
170     template <bool IsTriviallyDestructible>
171     struct _union<pack<>, IsTriviallyDestructible>
172     {};
174     template <typename T, typename ...Ts>
175     struct _union<pack<T, Ts...>, true>
176     {
177         EGGS_CXX11_STATIC_CONSTEXPR std::size_t size = 1 + sizeof...(Ts);
179         template <typename ...Args>
180         EGGS_CXX11_CONSTEXPR _union(index<0>, Args&&... args)
181           : _head(std::forward<Args>(args)...)
182         {}
184         template <std::size_t I, typename ...Args>
185         EGGS_CXX11_CONSTEXPR _union(index<I>, Args&&... args)
186           : _tail(index<I - 1>{}, std::forward<Args>(args)...)
187         {}
189         EGGS_CXX14_CONSTEXPR void* target() EGGS_CXX11_NOEXCEPT
190         {
191             return &_target;
192         }
194         EGGS_CXX11_CONSTEXPR void const* target() const EGGS_CXX11_NOEXCEPT
195         {
196             return &_target;
197         }
199         EGGS_CXX14_CONSTEXPR T& get(index<0>) EGGS_CXX11_NOEXCEPT
200         {
201             return this->_head;
202         }
204         EGGS_CXX11_CONSTEXPR T const& get(index<0>) const EGGS_CXX11_NOEXCEPT
205         {
206             return this->_head;
207         }
209         template <
210             std::size_t I
211           , typename U = typename at_index<I, pack<T, Ts...>>::type
212         >
213         EGGS_CXX14_CONSTEXPR U& get(index<I>) EGGS_CXX11_NOEXCEPT
214         {
215             return this->_tail.get(index<I - 1>{});
216         }
218         template <
219             std::size_t I
220           , typename U = typename at_index<I, pack<T, Ts...>>::type
221         >
222         EGGS_CXX11_CONSTEXPR U const& get(index<I>) const EGGS_CXX11_NOEXCEPT
223         {
224             return this->_tail.get(index<I - 1>{});
225         }
227     private:
228         union
229         {
230             char _target;
231             T _head;
232             _union<pack<Ts...>, true> _tail;
233         };
234     };
236     ///////////////////////////////////////////////////////////////////////////
237     template <typename Ts, bool TriviallyCopyable, bool TriviallyDestructible>
238     struct _storage;
240     template <typename ...Ts>
241     struct _storage<pack<Ts...>, true, true>
242       : _union<
243             pack<Ts...>
244           , all_of<pack<std::is_trivially_destructible<Ts>...>>::value
245         >
246     {
247         using base_type = _union<
248             pack<Ts...>
249           , all_of<pack<std::is_trivially_destructible<Ts>...>>::value
250         >;
252         EGGS_CXX11_CONSTEXPR _storage() EGGS_CXX11_NOEXCEPT
253           : base_type{index<0>{}}
254           , _which{0}
255         {}
257         _storage(_storage const& rhs) = default;
258         _storage(_storage&& rhs) = default;
260         template <std::size_t I, typename ...Args>
261         EGGS_CXX11_CONSTEXPR _storage(index<I> which, Args&&... args)
262           : base_type{which, std::forward<Args>(args)...}
263           , _which{I}
264         {}
266         _storage& operator=(_storage const& rhs) = default;
267         _storage& operator=(_storage&& rhs) = default;
269         EGGS_CXX11_CONSTEXPR std::size_t which() const
270         {
271             return _which;
272         }
274         using base_type::target;
275         using base_type::get;
277     protected:
278         std::size_t _which;
279     };
281     template <typename ...Ts>
282     using storage = _storage<
283         pack<empty, Ts...>
284       , all_of<pack<std::is_trivially_copyable<Ts>...>>::value
285       , all_of<pack<std::is_trivially_destructible<Ts>...>>::value
286     >;
289 namespace eggs { namespace variants
291     template <typename ...Ts>
292     class variant;
294     namespace detail
295     {
296         ///////////////////////////////////////////////////////////////////////
297         namespace _best_match
298         {
299             template <typename Ts, std::size_t I = 0>
300             struct overloads
301             {};
303             template <typename T, typename ...Ts, std::size_t I>
304             struct overloads<pack<T, Ts...>, I>
305               : overloads<pack<Ts...>, I + 1>
306             {
307                 using fun_ptr = index<I>(*)(T);
308                 operator fun_ptr();
309             };
311             template <typename F, typename T>
312             auto _invoke(F&&, T&&)
313              -> decltype(std::declval<F>()(std::declval<T>()));
315             struct _fallback {};
317             _fallback _invoke(...);
319             template <
320                 typename T, typename U
321               , typename R = decltype(_best_match::_invoke(
322                     std::declval<T>(), std::declval<U>()))
323             >
324             struct result_of : R
325             {};
327             template <typename T, typename U>
328             struct result_of<T, U, _fallback>
329             {};
330         }
332         template <typename U, typename ...Ts>
333         struct index_of_best_match
334           : _best_match::result_of<_best_match::overloads<Ts...>, U>
335         {};
337     }
339     template <typename ...Ts>
340     class variant
341     {
343     public:
344         EGGS_CXX11_CONSTEXPR variant() EGGS_CXX11_NOEXCEPT = delete;
346         variant(variant const& rhs) = default;
348         variant(variant&& rhs) = default;
350         template <
351             typename U
352           , typename Enable = typename std::enable_if<!std::is_same<
353                 typename std::decay<U>::type, variant
354             >::value>::type
355           , std::size_t I = detail::index_of_best_match<
356                 U&&, detail::pack<Ts...>>::value
357           , typename T = typename detail::at_index<
358                 I, detail::pack<Ts...>>::type
359         >
360         EGGS_CXX11_CONSTEXPR variant(U&& v)
361             noexcept(
362                 std::is_nothrow_constructible<T, U&&>::value)
363           : _storage{detail::index<I + 1>{}, std::forward<U>(v)}
364         {}
366         ~variant() = default;
367         variant& operator=(variant const& rhs) = delete;
369     private:
370         detail::storage<Ts...> _storage;
371     };
374 template <class T, class Base>
375 struct ref_proxy : Base
377     using Base::Base;
379     ref_proxy()
380         : Base()
381     {
382     }
384     ref_proxy(Base ptr)
385         : Base(std::move(ptr))
386     {
387     }
390 template <class T>
391 struct inplace_ref
393     explicit inplace_ref(T inner)
394         : inner_(inner)
395     {
396     }
398     T inner_;
401 template <class ...Variants>
402 struct variant_ref
404     variant_ref() = delete;
406     explicit variant_ref(eggs::variants::variant<Variants...> t)
407         : inner_storage_(t)
408     {
409     }
411     template <class Source>
412     variant_ref(ref_proxy<Source, variant_ref> ptr)
413         : inner_storage_(ptr.inner_storage_)
414     {}
416 private:
417     eggs::variants::variant<Variants...> inner_storage_;
420 struct option_1
422     void *a, *b, *c, *d, *e;
425 struct option_2
429 using option_ref = variant_ref<option_1, option_2>;
432 struct qual_option
434     qual_option(ref_proxy<void, option_ref > type, int quals)
435         : type_(type)
436         , quals_(quals)
437     {
438     }
440     explicit qual_option(ref_proxy<void, option_ref > type)
441         : qual_option(type, 0)
442     {
443     }
445     ref_proxy<void, option_ref > type_;
446     int quals_;
449 inline ref_proxy<option_2, option_ref > make_object_1()
451     return ref_proxy<option_2, option_ref >(option_2());
454 inline ref_proxy<option_2, option_ref > make_object_2()
456     return make_object_1();
459 inline inplace_ref<qual_option> make_object_3(ref_proxy<option_2, option_ref>&& a0)
461     return inplace_ref<qual_option>(qual_option(a0));
464 inline ref_proxy<qual_option, inplace_ref<qual_option> > make_object_4(ref_proxy<option_2, option_ref>&& a0)
466     return make_object_3(std::move(a0));
470 ref_proxy<qual_option, inplace_ref<qual_option> > f() __attribute__((noinline));
472 ref_proxy<qual_option, inplace_ref<qual_option> > f()
474     return make_object_4(make_object_2());
477 int main(int argc, char* argv[])
479     for (;;)
480         f();
483 /* { dg-final { scan-tree-dump "Removing load:.*ptr;" "sra" } } */