1 // PR c++/21802
2 // { dg-do run }
3 #include <cassert>
4 
5 struct X;
6 int I = 6;
7 
8 /* A mostly exhaustive and ad-hoc assortment of operator overloads and calls
9    thereof, to stress-test two-stage name lookup of operators inside template
10    definitions and then to verify that the calls get built correctly.  */
11 
12 template <typename T>
13 inline int operator+(const X &, T x) { return x; }
14 inline int operator-(const X &, int x) { return x; }
15 inline int operator*(const X &, int x) { return x; }
16 inline int operator/(const X &, int x) { return x; }
17 inline int operator+=(const X &, int x) { return x; }
18 
19 struct X
20 {
XX21   X () : m (1) { }
22   template <typename T>
23   int operator%(T x) { return m + x; }
24   virtual int operator>>(int x) { return m + x; }
25   int operator<<(int x) { return m + x; }
26   int operator&(int x) { return m + x; }
27   int operator|(int x) { return m + x; }
28   int operator^(int x) { return m + x; }
29   int operator&&(int x) { return m + x; }
30   int operator||(int x) { return m + x; }
31   friend int operator==(X o, int x) { return o.m + x; }
32   int operator!=(int x) { return m + x; }
33   int operator<(int x) { return m + x; }
34   int operator<=(int x) { return m + x; }
35   int operator>(int x) { return m + x; }
36   int operator>=(int x) { return m + x; }
37   int operator*() { return m + I; }
38   int operator!() { return m + I; }
39   int operator~() { return m + I; }
40   int operator++() { return m + I + 100; }
41   int operator--() { return m + I + 100; }
42   int operator++(int) { return m + I; }
43   int operator--(int) { return m + I; }
operatorX44   int operator()() { return m + I; }
45   int operator,(int x) { return m + x; }
46   int operator[](int x) { return m + x; }
47   int operator*=(int x) { return m + x; }
48   int operator-=(int x) { return m + x; }
49   int operator/=(int x) { return m + x; }
50   virtual int operator& () { return m + I; }
51   int m;
52 };
53 struct Y : virtual X
54 {
55   /* Virtual override.  */
56   int operator>>(int x) { return m + x + 1; }
57   int operator& () { return m + I + 1; }
58 
59   /* Not virtual.  */
60   template <typename T>
61   int operator&(T x) { return m + x + 1; }
62   friend int operator==(Y o, int x) { return o.m + x + 1; }
63   int operator!=(int x) { return m + x + 1; }
64 };
65 
66 /* The folloiwng "FooN" functions each contain a different way to call and to
67    resolve these operator overloads.  */
68 
69 template <typename T>
70 void
Foo1(T)71 Foo1 (T)
72 {
73   Y x;
74   { int t = x + I; assert (t == 6); }
75   { int t = x - I; assert (t == 6); }
76   { int t = x * I; assert (t == 6); }
77   { int t = x / I; assert (t == 6); }
78   { int t = (x+=I); assert (t == 6); }
79 
80   { int t = x % I; assert (t == 7); }
81   { int t = x << I; assert (t == 7); }
82   { int t = x | I; assert (t == 7); }
83   { int t = x && I; assert (t == 7); }
84   { int t = x || I; assert (t == 7); }
85   { int t = x < I; assert (t == 7); }
86   { int t = x <= I; assert (t == 7); }
87   { int t = x > I; assert (t == 7); }
88   { int t = x >= I; assert (t == 7); }
89   { int t = *x; assert (t == 7); }
90   { int t = !x; assert (t == 7); }
91   { int t = ~x; assert (t == 7); }
92   { int t = x++; assert (t == 7); }
93   { int t = x--; assert (t == 7); }
94   { int t = ++x; assert (t == 107); }
95   { int t = --x; assert (t == 107); }
96   { int t = x (); assert (t == 7); }
97   { int t = (x, I); assert (t == 7); }
98   { int t = x[I]; assert (t == 7); }
99   { int t = (x-=I); assert (t == 7); }
100   { int t = (x/=I); assert (t == 7); }
101   { int t = (x*=I); assert (t == 7); }
102 
103   { int t = x >> I; assert (t == 8); }
104   { int t = x & I; assert (t == 8); }
105   { int t = &x; assert (t == 8); }
106   { int t = x == I; assert (t == 8); }
107   { int t = x != I; assert (t == 8); }
108 }
109 
110 template <typename T>
111 void
Foo2(T)112 Foo2 (T)
113 {
114   X x;
115   { int t = x + I; assert (t == 6); }
116   { int t = x - I; assert (t == 6); }
117   { int t = x * I; assert (t == 6); }
118   { int t = x / I; assert (t == 6); }
119   { int t = (x+=I); assert (t == 6); }
120 
121   { int t = x % I; assert (t == 7); }
122   { int t = x >> I; assert (t == 7); }
123   { int t = x << I; assert (t == 7); }
124   { int t = x | I; assert (t == 7); }
125   { int t = x && I; assert (t == 7); }
126   { int t = x || I; assert (t == 7); }
127   { int t = x == I; assert (t == 7); }
128   { int t = x != I; assert (t == 7); }
129   { int t = x < I; assert (t == 7); }
130   { int t = x <= I; assert (t == 7); }
131   { int t = x > I; assert (t == 7); }
132   { int t = x >= I; assert (t == 7); }
133   { int t = *x; assert (t == 7); }
134   { int t = !x; assert (t == 7); }
135   { int t = ~x; assert (t == 7); }
136   { int t = x++; assert (t == 7); }
137   { int t = x--; assert (t == 7); }
138   { int t = ++x; assert (t == 107); }
139   { int t = --x; assert (t == 107); }
140   { int t = x (); assert (t == 7); }
141   { int t = (x, I); assert (t == 7); }
142   { int t = x[I]; assert (t == 7); }
143   { int t = &x; assert (t == 7); }
144   { int t = (x-=I); assert (t == 7); }
145   { int t = (x/=I); assert (t == 7); }
146   { int t = (x*=I); assert (t == 7); }
147   { int t = x & I; assert (t == 7); }
148 }
149 
150 template <typename T>
151 void
Foo3(T)152 Foo3 (T)
153 {
154   Y o;
155   X &x = o;
156   { int t = x + I; assert (t == 6); }
157   { int t = x - I; assert (t == 6); }
158   { int t = x * I; assert (t == 6); }
159   { int t = x / I; assert (t == 6); }
160   { int t = (x+=I); assert (t == 6); }
161 
162   { int t = x % I; assert (t == 7); }
163   { int t = x << I; assert (t == 7); }
164   { int t = x | I; assert (t == 7); }
165   { int t = x && I; assert (t == 7); }
166   { int t = x || I; assert (t == 7); }
167   { int t = x == I; assert (t == 7); }
168   { int t = x != I; assert (t == 7); }
169   { int t = x < I; assert (t == 7); }
170   { int t = x <= I; assert (t == 7); }
171   { int t = x > I; assert (t == 7); }
172   { int t = x >= I; assert (t == 7); }
173   { int t = *x; assert (t == 7); }
174   { int t = !x; assert (t == 7); }
175   { int t = ~x; assert (t == 7); }
176   { int t = x++; assert (t == 7); }
177   { int t = x--; assert (t == 7); }
178   { int t = ++x; assert (t == 107); }
179   { int t = --x; assert (t == 107); }
180   { int t = x (); assert (t == 7); }
181   { int t = (x, I); assert (t == 7); }
182   { int t = x[I]; assert (t == 7); }
183   { int t = (x-=I); assert (t == 7); }
184   { int t = (x/=I); assert (t == 7); }
185   { int t = (x*=I); assert (t == 7); }
186 
187   { int t = x & I; assert (t == 7); }
188   { int t = x >> I; assert (t == 8); }
189   { int t = &x; assert (t == 8); }
190 }
191 
192 template <typename T>
193 void
Foo4(T)194 Foo4 (T)
195 {
196   Y x;
197   { int t = operator+ (x, I); assert (t == 6); }
198   { int t = operator- (x, I); assert (t == 6); }
199   { int t = operator* (x, I); assert (t == 6); }
200   { int t = operator/ (x, I); assert (t == 6); }
201   { int t = operator+= (x, I); assert (t == 6); }
202 
203   { int t = x.operator% (I); assert (t == 7); }
204   { int t = x.operator<< (I); assert (t == 7); }
205   { int t = x.operator| (I); assert (t == 7); }
206   { int t = x.operator&& (I); assert (t == 7); }
207   { int t = x.operator|| (I); assert (t == 7); }
208   { int t = x.operator< (I); assert (t == 7); }
209   { int t = x.operator<= (I); assert (t == 7); }
210   { int t = x.operator> (I); assert (t == 7); }
211   { int t = x.operator>= (I); assert (t == 7); }
212   { int t = x.operator* (); assert (t == 7); }
213   { int t = x.operator! (); assert (t == 7); }
214   { int t = x.operator~ (); assert (t == 7); }
215   { int t = x.operator++ (0); assert (t == 7); }
216   { int t = x.operator-- (0); assert (t == 7); }
217   { int t = x.operator++ (); assert (t == 107); }
218   { int t = x.operator-- (); assert (t == 107); }
219   { int t = x.operator() (); assert (t == 7); }
220   { int t = x.operator, (I); assert (t == 7); }
221   { int t = x.operator[] (I); assert (t == 7); }
222   { int t = x.operator-= (I); assert (t == 7); }
223   { int t = x.operator/= (I); assert (t == 7); }
224   { int t = x.operator*= (I); assert (t == 7); }
225 
226   { int t = x.operator>> (I); assert (t == 8); }
227   { int t = x.operator& (); assert (t == 8); }
228   { int t = x.operator& (I); assert (t == 8); }
229   { int t = operator== (x, I); assert (t == 8); }
230   { int t = x.operator!= (I); assert (t == 8); }
231 }
232 
233 
234 /* These definitions should be irrelevant to operator lookup of non-dependent
235    expressions inside the above templates since they are not in scope at
236    template-definition time (even though they are in scope at instantiation
237    time).  */
238 inline int operator+(const Y&, int) { return 11; }
239 inline int operator-(const Y&, int) { return 11; }
240 inline int operator*(const Y&, int) { return 11; }
241 inline int operator/(const Y&, int) { return 11; }
242 inline int operator%(const Y&, int) { return 11; }
243 inline int operator>>(const Y&, int) { return 11; }
244 inline int operator<<(const Y&, int) { return 11; }
245 inline int operator&(const Y&, int) { return 11; }
246 inline int operator|(const Y&, int) { return 11; }
247 inline int operator^(const Y&, int) { return 11; }
248 inline int operator&&(const Y&, int) { return 11; }
249 inline int operator||(const Y&, int) { return 11; }
250 inline int operator==(const Y&, int) { return 11; }
251 inline int operator!=(const Y&, int) { return 11; }
252 inline int operator<(const Y&, int) { return 11; }
253 inline int operator<=(const Y&, int) { return 11; }
254 inline int operator>(const Y&, int) { return 11; }
255 inline int operator>=(const Y&, int) { return 11; }
256 inline int operator*(const Y&) { return 11; }
257 inline int operator!(const Y&) { return 11; }
258 inline int operator~(const Y&) { return 11; }
259 inline int operator++(const Y&) { return 11; }
260 inline int operator--(const Y&) { return 11; }
261 inline int operator++(const Y&, int) { return 11; }
262 inline int operator--(const Y&, int) { return 11; }
263 inline int operator,(const Y&, int) { return 11; }
264 inline int operator&(const Y&) { return 11; }
265 inline int operator+=(const Y&, int x) { return 11; }
266 inline int operator*=(const Y&, int x) { return 11; }
267 inline int operator-=(const Y&, int x) { return 11; }
268 inline int operator/=(const Y&, int x) { return 11; }
269 
270 int
main()271 main ()
272 {
273   Foo1 (0);
274   Foo2 (0);
275   Foo3 (0);
276   Foo4 (0);
277 }
278