1 // { dg-do compile }
2 // { dg-additional-options "-Wno-return-type" }
3 
4 template <typename> class A;
5 template <typename _Tp> using __allocator_base = _Tp;
6 template <class T, class = T, class = int, class = __allocator_base<int>>
7 class B;
8 template <class T, class H, class P, class A>
9 bool operator==(B<T, H, P, A> const &, B<T, H, P, A> const &);
10 template <class T, class H, class P, class A>
11 bool operator!=(B<T, H, P, A> const &, B<T, H, P, A> const &);
12 typedef B<int> int_multiset;
13 int a;
14 template <typename> struct C {
CC15     C(int) {}
16 };
17 template <typename> struct D;
18 template <typename> struct K;
19 struct L : C<A<D<int>>>, C<A<K<int>>> {
20     template <typename First, typename Second>
LL21 	L(First, Second)
22 	: C<A<D<int>>>(0), C<A<K<int>>>(0) {}
23 };
24 template <typename Node> struct F {
25     typedef typename Node::node_pointer node_pointer;
26     node_pointer node_;
27     F();
FF28     F(typename Node::link_pointer p1) : node_(static_cast<node_pointer>(p1)) {}
29     void operator++() { node_ = 0; }
30     int operator!=(F p1) { return node_ != p1.node_; }
31 };
32 struct G {
33     typedef G *link_pointer;
34 };
35 struct H {
new_bucket_countH36     static int new_bucket_count(int) {
37 	int b;
38 	int *c = 0;
39 	if (a)
40 	  b = *c;
41 	return b;
42     }
43 };
44 class functions {
45 public:
functions(int,int)46     functions(int, int) {}
47     ~functions();
48 };
49 template <typename Types> struct table : functions {
50     typedef typename Types::policy policy;
51     typedef Types node_allocator;
52     typedef F<typename Types::node> iterator;
53     L allocators_;
54     int bucket_count_;
55     int size_;
56     typename Types::link_pointer get_previous_start() const;
begintable57     iterator begin() const { return size_ ? get_previous_start() : 0; }
tabletable58     table(int, typename Types::hasher, typename Types::key_equal, node_allocator)
59 	: functions(0, 0), allocators_(0, 0),
60 	bucket_count_(policy::new_bucket_count(0)), size_() {}
61 };
62 template <typename> struct K : G { typedef K *node_pointer; };
63 struct I {
64     typedef G *link_pointer;
65 };
66 struct J {
67     typedef I::link_pointer link_pointer;
68 };
69 template <typename> struct D {
70     typedef int hasher;
71     typedef int key_equal;
72     typedef K<int> node;
73     typedef J::link_pointer link_pointer;
74     typedef H policy;
75 };
76 struct M : table<D<int>> {
77     node_allocator grouped_table_impl_a;
MM78     M(int, int) : table(0, 0, 0, grouped_table_impl_a) {}
equalsM79     void equals(M const &) const {
80 	for (iterator d = begin(); d.node_;) {
81 	    iterator e;
82 	    group_equals(e);
83 	}
84     }
group_equalsM85     static int group_equals(iterator p1) {
86 	int f;
87 	iterator g;
88 	for (; g != p1; ++g)
89 	  if (find())
90 	    if (f)
91 	      return 0;
92     }
93     static int find();
94 };
95 template <class, class, class, class> class B {
96     M table_;
97 
98 public:
99     B(unsigned long = 0);
100     friend bool operator==<>(B const &, B const &);
101     friend bool operator!=<>(B const &, B const &);
102 };
103 template <class T, class H, class P, class A>
B(unsigned long)104 B<T, H, P, A>::B(unsigned long)
105      : table_(0, 0) {}
106      template <class T, class H, class P, class A>
107      bool operator==(B<T, H, P, A> const &p1, B<T, H, P, A> const &p2) {
108 	 p1.table_.equals(p2.table_);
109      }
110 template <class T, class H, class P, class A>
111 bool operator!=(B<T, H, P, A> const &p1, B<T, H, P, A> const &p2) {
112     p1.table_.equals(p2.table_);
113 }
use_multiset_fwd_declared_function_typerun()114 void use_multiset_fwd_declared_function_typerun() {
115     int_multiset x, y;
116     x == y;
117     x != y;
118 }
119