1// { dg-do compile }
2// { dg-additional-options "-std=gnu++11" }
3namespace mpl {
4template <typename, typename = int> struct lambda;
5template <typename T3> struct if_ { typedef T3 type; };
6template <int> struct arg {
7  template <typename U1, typename> struct apply { typedef U1 type; };
8};
9template <typename> struct begin_impl;
10template <typename Sequence> struct begin {
11  typedef typename Sequence::tag tag_;
12  typedef typename begin_impl<tag_>::template apply<Sequence>::type type;
13};
14template <typename> struct O1_size_impl;
15}
16template <long N> struct long_ { static const long value = N; };
17namespace mpl {
18template <typename Sequence>
19struct O1_size
20    : O1_size_impl<typename Sequence::tag>::template apply<Sequence> {};
21typedef arg<1> _1;
22template <typename T> struct protect : T {};
23template <typename F> struct apply_wrap1 : F::template apply<int> {};
24template <typename F, typename T1, typename T2>
25struct apply_wrap2 : F::template apply<T1, T2> {};
26template <typename F> struct apply_wrap5 : F::template apply<int> {};
27template <typename, typename, typename, typename, typename, typename>
28struct resolve_bind_arg;
29template <typename T, typename> struct replace_unnamed_arg { typedef T type; };
30template <typename F, typename> struct bind1 {
31  template <typename> struct apply {
32    typedef typename apply_wrap1<F>::type type;
33  };
34};
35template <typename F, typename T1, typename U1, typename U2, typename U3,
36          typename U4, typename U5>
37struct resolve_bind_arg<bind1<F, T1>, U1, U2, U3, U4, U5> {
38  typedef typename apply_wrap5<bind1<F, T1>>::type type;
39};
40template <typename F, typename, typename T2> struct bind2 {
41  template <typename U1, typename U2> struct apply {
42    typedef resolve_bind_arg<typename replace_unnamed_arg<T2, arg<1>>::type, U1,
43                             U2, int, int, int> t2;
44    typedef typename apply_wrap2<F, typename U1::type, typename t2::type>::type
45        type;
46  };
47};
48template <typename T> struct quote_impl { typedef T type; };
49template <template <typename> class F> struct quote1 {
50  template <typename> struct apply : quote_impl<F<int>> {};
51};
52template <typename T, typename> struct lambda {
53  typedef T type;
54  typedef arg<1> result_;
55};
56template <typename, template <typename> class, typename> struct le_result1;
57template <template <typename> class F, typename L1>
58struct le_result1<int, F, L1> {
59  typedef protect<bind1<quote1<F>, typename L1::result_>> type;
60};
61template <template <typename> class F, typename T1, typename Tag>
62struct lambda<F<T1>, Tag> {
63  typedef typename le_result1<int, F, lambda<T1>>::type type;
64};
65template <int, typename, typename, typename> struct iter_fold_impl;
66template <typename First, typename State, typename ForwardOp>
67struct iter_fold_impl<1, First, State, ForwardOp> {
68  typedef typename apply_wrap2<ForwardOp, State, First>::type state;
69};
70template <typename Sequence, typename State, typename ForwardOp>
71struct iter_fold {
72  typedef typename iter_fold_impl<O1_size<Sequence>::value,
73                                  typename begin<Sequence>::type, State,
74                                  ForwardOp>::state type;
75};
76template <typename> struct deref;
77template <typename> struct push_front_impl;
78template <typename T> struct l_item {
79  typedef int tag;
80  typedef l_item type;
81  typedef long_<1> size;
82  typedef T item;
83};
84struct l_end {
85  typedef int tag;
86  typedef l_end type;
87};
88template <> struct push_front_impl<int> {
89  template <typename, typename T> struct apply { typedef l_item<T> type; };
90};
91template <> struct O1_size_impl<int> {
92  template <typename> struct apply : l_item<int>::size {};
93};
94template <typename> struct l_iter;
95template <typename Node> struct deref<l_iter<Node>> {
96  typedef typename Node::item type;
97};
98template <> struct begin_impl<int> {
99  template <typename List> struct apply {
100    typedef l_iter<typename List::type> type;
101  };
102};
103template <typename> struct list : l_item<int> {};
104}
105template <typename T> T &cast_storage(void *storage) {
106  return *static_cast<T *>(storage);
107}
108struct symbol;
109struct visitation_impl_step {
110  typedef symbol type;
111};
112template <typename Visitor, typename VoidPtrCV, typename T>
113void visitation_impl_invoke_impl(int, Visitor visitor, VoidPtrCV storage, T *) {
114  visitor.internal_visit(cast_storage<T>(storage), 1);
115}
116int visitation_impl_invoke_internal_which, visitation_impl_logical_which;
117template <typename Visitor, typename VoidPtrCV, typename T,
118          typename NoBackupFlag>
119void visitation_impl_invoke(Visitor visitor, VoidPtrCV storage, T t,
120                            NoBackupFlag, int) {
121  visitation_impl_invoke_impl(visitation_impl_invoke_internal_which, visitor,
122                              storage, t);
123}
124template <typename Which, typename step0, typename Visitor, typename VoidPtrCV,
125          typename NoBackupFlag>
126void visitation_impl(int, Visitor visitor, VoidPtrCV storage, int,
127                     NoBackupFlag no_backup_flag, Which, step0 *) {
128  switch (visitation_impl_logical_which)
129  case 0:
130  visitation_impl_invoke(visitor, storage,
131                         static_cast<typename step0::type *>(0), no_backup_flag,
132                         1);
133}
134template <long N> struct size_t { static const long value = N; };
135struct aligned_storage_imp {};
136template <long> class aligned_storage : aligned_storage_imp {
137public:
138  void *address() { return static_cast<aligned_storage_imp *>(this); }
139};
140namespace mpl {
141template <typename> struct less;
142template <typename> struct select_max {
143  template <typename OldIterator, typename> struct apply {
144    typedef OldIterator type;
145  };
146};
147template <typename Sequence, typename Predicate = less<arg<11>>>
148struct max_element : iter_fold<Sequence, typename begin<Sequence>::type,
149                               protect<select_max<Predicate>>> {};
150template <typename Sequence = int, typename T = int>
151struct push_front
152    : push_front_impl<typename Sequence::tag>::template apply<Sequence, T> {};
153template <> struct push_front<> {
154  template <typename T1, typename T2> struct apply : push_front<T1, T2> {};
155};
156template <typename> struct sizeof_ : size_t<sizeof(int)> {};
157template <long, typename, typename, typename, typename>
158struct reverse_fold_impl;
159template <typename First, typename State, typename BackwardOp,
160          typename ForwardOp>
161struct reverse_fold_impl<1, First, State, BackwardOp, ForwardOp> {
162  typedef First iter0;
163  typedef typename apply_wrap2<
164      BackwardOp,
165      typename apply_wrap2<ForwardOp, State, typename deref<iter0>::type>::type,
166      typename deref<iter0>::type>::type state;
167};
168template <typename Sequence, typename State, typename BackwardOp,
169          typename ForwardOp = arg<1>>
170struct reverse_fold {
171  typedef typename reverse_fold_impl<O1_size<Sequence>::value,
172                                     typename begin<Sequence>::type, State,
173                                     BackwardOp, ForwardOp>::state type;
174};
175template <typename> struct inserter {
176  typedef mpl::l_end state;
177  typedef mpl::push_front<> operation;
178};
179template <typename Seq, typename Op, typename In>
180struct reverse_transform1_impl
181    : reverse_fold<Seq, typename In::state,
182                   bind2<typename lambda<typename In::operation>::type, _1,
183                         bind1<typename lambda<Op>::type, arg<2>>>> {};
184template <typename P1, typename P2>
185struct transform1
186    : if_<reverse_transform1_impl<P1, P2, inserter<push_front<>>>>::type {};
187}
188template <typename, typename> struct max_value {
189  typedef mpl::transform1<mpl::list<symbol>, mpl::sizeof_<mpl::arg<1>>>::type
190      transformed_;
191  typedef mpl::max_element<transformed_>::type max_it;
192  typedef mpl::deref<max_it>::type type;
193};
194template <typename> struct make_storage {
195  typedef max_value<int, mpl::sizeof_<int>>::type max_size;
196  typedef aligned_storage<max_size::value> type;
197};
198struct destroyer {
199  template <typename T> void internal_visit(T &operand, int) { operand.~T(); }
200};
201template <typename, typename...> class variant {
202  typedef int internal_types;
203  int which_;
204  make_storage<internal_types>::type storage_;
205public:
206  ~variant() {
207    destroyer visitor;
208    internal_apply_visitor(visitor);
209  }
210  template <typename Visitor, typename VoidPtrCV>
211  void internal_apply_visitor_impl(int internal_which, int, Visitor visitor,
212                                   VoidPtrCV storage) {
213    visitation_impl(internal_which, visitor, storage, int(), int(),
214                    static_cast<int>(0),
215                    static_cast<visitation_impl_step *>(0));
216  }
217  int internal_apply_visitor___trans_tmp_1;
218  template <typename Visitor> void internal_apply_visitor(Visitor visitor) {
219    internal_apply_visitor_impl(which_, internal_apply_visitor___trans_tmp_1,
220                                visitor, storage_.address());
221  }
222};
223struct symbol {
224  virtual ~symbol();
225};
226using Identifier = variant<int>;
227struct Fragment {
228  virtual void foo() const = 0;
229  virtual ~Fragment();
230};
231struct ProcFrag : Fragment {
232  ~ProcFrag() {}
233  void foo() const;
234  Identifier id;
235};
236struct Fragments {
237  ~Fragments() { delete x; }
238  Fragment *x;
239} fragments;
240