1*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -Wcomma -std=c++11 -verify %s
2*67e74705SXin Li // RUN: %clang_cc1 -fsyntax-only -Wcomma -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
3*67e74705SXin Li
4*67e74705SXin Li // Test builtin operators
test1()5*67e74705SXin Li void test1() {
6*67e74705SXin Li int x = 0, y = 0;
7*67e74705SXin Li for (; y < 10; x++, y++) {}
8*67e74705SXin Li for (; y < 10; ++x, y++) {}
9*67e74705SXin Li for (; y < 10; x++, ++y) {}
10*67e74705SXin Li for (; y < 10; ++x, ++y) {}
11*67e74705SXin Li for (; y < 10; x--, ++y) {}
12*67e74705SXin Li for (; y < 10; --x, ++y) {}
13*67e74705SXin Li for (; y < 10; x = 5, ++y) {}
14*67e74705SXin Li for (; y < 10; x *= 5, ++y) {}
15*67e74705SXin Li for (; y < 10; x /= 5, ++y) {}
16*67e74705SXin Li for (; y < 10; x %= 5, ++y) {}
17*67e74705SXin Li for (; y < 10; x += 5, ++y) {}
18*67e74705SXin Li for (; y < 10; x -= 5, ++y) {}
19*67e74705SXin Li for (; y < 10; x <<= 5, ++y) {}
20*67e74705SXin Li for (; y < 10; x >>= 5, ++y) {}
21*67e74705SXin Li for (; y < 10; x &= 5, ++y) {}
22*67e74705SXin Li for (; y < 10; x |= 5, ++y) {}
23*67e74705SXin Li for (; y < 10; x ^= 5, ++y) {}
24*67e74705SXin Li }
25*67e74705SXin Li
26*67e74705SXin Li class S2 {
27*67e74705SXin Li public:
28*67e74705SXin Li void advance();
29*67e74705SXin Li
30*67e74705SXin Li S2 operator++();
31*67e74705SXin Li S2 operator++(int);
32*67e74705SXin Li S2 operator--();
33*67e74705SXin Li S2 operator--(int);
34*67e74705SXin Li S2 operator=(int);
35*67e74705SXin Li S2 operator*=(int);
36*67e74705SXin Li S2 operator/=(int);
37*67e74705SXin Li S2 operator%=(int);
38*67e74705SXin Li S2 operator+=(int);
39*67e74705SXin Li S2 operator-=(int);
40*67e74705SXin Li S2 operator<<=(int);
41*67e74705SXin Li S2 operator>>=(int);
42*67e74705SXin Li S2 operator&=(int);
43*67e74705SXin Li S2 operator|=(int);
44*67e74705SXin Li S2 operator^=(int);
45*67e74705SXin Li };
46*67e74705SXin Li
47*67e74705SXin Li // Test overloaded operators
test2()48*67e74705SXin Li void test2() {
49*67e74705SXin Li S2 x;
50*67e74705SXin Li int y;
51*67e74705SXin Li for (; y < 10; x++, y++) {}
52*67e74705SXin Li for (; y < 10; ++x, y++) {}
53*67e74705SXin Li for (; y < 10; x++, ++y) {}
54*67e74705SXin Li for (; y < 10; ++x, ++y) {}
55*67e74705SXin Li for (; y < 10; x--, ++y) {}
56*67e74705SXin Li for (; y < 10; --x, ++y) {}
57*67e74705SXin Li for (; y < 10; x = 5, ++y) {}
58*67e74705SXin Li for (; y < 10; x *= 5, ++y) {}
59*67e74705SXin Li for (; y < 10; x /= 5, ++y) {}
60*67e74705SXin Li for (; y < 10; x %= 5, ++y) {}
61*67e74705SXin Li for (; y < 10; x += 5, ++y) {}
62*67e74705SXin Li for (; y < 10; x -= 5, ++y) {}
63*67e74705SXin Li for (; y < 10; x <<= 5, ++y) {}
64*67e74705SXin Li for (; y < 10; x >>= 5, ++y) {}
65*67e74705SXin Li for (; y < 10; x &= 5, ++y) {}
66*67e74705SXin Li for (; y < 10; x |= 5, ++y) {}
67*67e74705SXin Li for (; y < 10; x ^= 5, ++y) {}
68*67e74705SXin Li }
69*67e74705SXin Li
70*67e74705SXin Li // Test nested comma operators
test3()71*67e74705SXin Li void test3() {
72*67e74705SXin Li int x1, x2, x3;
73*67e74705SXin Li int y1, *y2 = 0, y3 = 5;
74*67e74705SXin Li for (int z1 = 5, z2 = 4, z3 = 3; x1 <4; ++x1) {}
75*67e74705SXin Li }
76*67e74705SXin Li
77*67e74705SXin Li class Stream {
78*67e74705SXin Li public:
79*67e74705SXin Li Stream& operator<<(int);
80*67e74705SXin Li } cout;
81*67e74705SXin Li
return_four()82*67e74705SXin Li int return_four() { return 5; }
83*67e74705SXin Li
84*67e74705SXin Li // Confusing "," for "<<"
test4()85*67e74705SXin Li void test4() {
86*67e74705SXin Li cout << 5 << return_four();
87*67e74705SXin Li cout << 5, return_four();
88*67e74705SXin Li // expected-warning@-1{{comma operator}}
89*67e74705SXin Li // expected-note@-2{{cast expression to void}}
90*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>("
91*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:12-[[@LINE-4]]:12}:")"
92*67e74705SXin Li }
93*67e74705SXin Li
94*67e74705SXin Li // Confusing "," for "=="
test5()95*67e74705SXin Li void test5() {
96*67e74705SXin Li if (return_four(), 5) {}
97*67e74705SXin Li // expected-warning@-1{{comma operator}}
98*67e74705SXin Li // expected-note@-2{{cast expression to void}}
99*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast<void>("
100*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")"
101*67e74705SXin Li
102*67e74705SXin Li if (return_four() == 5) {}
103*67e74705SXin Li }
104*67e74705SXin Li
105*67e74705SXin Li // Confusing "," for "+"
test6()106*67e74705SXin Li int test6() {
107*67e74705SXin Li return return_four(), return_four();
108*67e74705SXin Li // expected-warning@-1{{comma operator}}
109*67e74705SXin Li // expected-note@-2{{cast expression to void}}
110*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>("
111*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")"
112*67e74705SXin Li
113*67e74705SXin Li return return_four() + return_four();
114*67e74705SXin Li }
115*67e74705SXin Li
116*67e74705SXin Li void Concat(int);
117*67e74705SXin Li void Concat(int, int);
118*67e74705SXin Li
119*67e74705SXin Li // Testing extra parentheses in function call
test7()120*67e74705SXin Li void test7() {
121*67e74705SXin Li Concat((return_four() , 5));
122*67e74705SXin Li // expected-warning@-1{{comma operator}}
123*67e74705SXin Li // expected-note@-2{{cast expression to void}}
124*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast<void>("
125*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:24-[[@LINE-4]]:24}:")"
126*67e74705SXin Li
127*67e74705SXin Li Concat(return_four() , 5);
128*67e74705SXin Li }
129*67e74705SXin Li
130*67e74705SXin Li // Be sure to look through parentheses
test8()131*67e74705SXin Li void test8() {
132*67e74705SXin Li int x, y;
133*67e74705SXin Li for (x = 0; return_four(), x;) {}
134*67e74705SXin Li // expected-warning@-1{{comma operator}}
135*67e74705SXin Li // expected-note@-2{{cast expression to void}}
136*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast<void>("
137*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:28-[[@LINE-4]]:28}:")"
138*67e74705SXin Li
139*67e74705SXin Li for (x = 0; (return_four()), (x) ;) {}
140*67e74705SXin Li // expected-warning@-1{{comma operator}}
141*67e74705SXin Li // expected-note@-2{{cast expression to void}}
142*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast<void>("
143*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")"
144*67e74705SXin Li }
145*67e74705SXin Li
146*67e74705SXin Li bool DoStuff();
147*67e74705SXin Li class S9 {
148*67e74705SXin Li public:
149*67e74705SXin Li bool Advance();
150*67e74705SXin Li bool More();
151*67e74705SXin Li };
152*67e74705SXin Li
153*67e74705SXin Li // Ignore comma operator in for-loop initializations and increments.
test9()154*67e74705SXin Li void test9() {
155*67e74705SXin Li int x, y;
156*67e74705SXin Li for (x = 0, y = 5; x < y; ++x) {}
157*67e74705SXin Li for (x = 0; x < 10; DoStuff(), ++x) {}
158*67e74705SXin Li for (S9 s; s.More(); s.Advance(), ++x) {}
159*67e74705SXin Li }
160*67e74705SXin Li
test10()161*67e74705SXin Li void test10() {
162*67e74705SXin Li int x, y;
163*67e74705SXin Li ++x, ++y;
164*67e74705SXin Li // expected-warning@-1{{comma operator}}
165*67e74705SXin Li // expected-note@-2{{cast expression to void}}
166*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>("
167*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:6-[[@LINE-4]]:6}:")"
168*67e74705SXin Li }
169*67e74705SXin Li
170*67e74705SXin Li // Ignore comma operator in templates.
171*67e74705SXin Li namespace test11 {
172*67e74705SXin Li template <bool T>
173*67e74705SXin Li struct B { static const bool value = T; };
174*67e74705SXin Li
175*67e74705SXin Li typedef B<true> true_type;
176*67e74705SXin Li typedef B<false> false_type;
177*67e74705SXin Li
178*67e74705SXin Li template <bool...>
179*67e74705SXin Li struct bool_seq;
180*67e74705SXin Li
181*67e74705SXin Li template <typename... xs>
182*67e74705SXin Li class Foo {
183*67e74705SXin Li typedef bool_seq<(xs::value, true)...> all_true;
184*67e74705SXin Li typedef bool_seq<(xs::value, false)...> all_false;
185*67e74705SXin Li typedef bool_seq<xs::value...> seq;
186*67e74705SXin Li };
187*67e74705SXin Li
188*67e74705SXin Li const auto X = Foo<true_type>();
189*67e74705SXin Li }
190*67e74705SXin Li
191*67e74705SXin Li namespace test12 {
192*67e74705SXin Li class Mutex {
193*67e74705SXin Li public:
194*67e74705SXin Li Mutex();
195*67e74705SXin Li ~Mutex();
196*67e74705SXin Li };
197*67e74705SXin Li class MutexLock {
198*67e74705SXin Li public:
199*67e74705SXin Li MutexLock(Mutex &);
200*67e74705SXin Li MutexLock();
201*67e74705SXin Li ~MutexLock();
202*67e74705SXin Li };
203*67e74705SXin Li class BuiltinMutex {
204*67e74705SXin Li Mutex M;
205*67e74705SXin Li };
206*67e74705SXin Li Mutex StatusMutex;
207*67e74705SXin Li bool Status;
208*67e74705SXin Li
get_status()209*67e74705SXin Li bool get_status() {
210*67e74705SXin Li return (MutexLock(StatusMutex), Status);
211*67e74705SXin Li // expected-warning@-1{{comma operator}}
212*67e74705SXin Li // expected-note@-2{{cast expression to void}}
213*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast<void>("
214*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:33-[[@LINE-4]]:33}:")"
215*67e74705SXin Li return (MutexLock(), Status);
216*67e74705SXin Li // expected-warning@-1{{comma operator}}
217*67e74705SXin Li // expected-note@-2{{cast expression to void}}
218*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast<void>("
219*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:22-[[@LINE-4]]:22}:")"
220*67e74705SXin Li return (BuiltinMutex(), Status);
221*67e74705SXin Li // expected-warning@-1{{comma operator}}
222*67e74705SXin Li // expected-note@-2{{cast expression to void}}
223*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast<void>("
224*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:25-[[@LINE-4]]:25}:")"
225*67e74705SXin Li }
226*67e74705SXin Li }
227*67e74705SXin Li
228*67e74705SXin Li // Check for comma operator in conditions.
test13(int x)229*67e74705SXin Li void test13(int x) {
230*67e74705SXin Li x = (return_four(), x);
231*67e74705SXin Li // expected-warning@-1{{comma operator}}
232*67e74705SXin Li // expected-note@-2{{cast expression to void}}
233*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:8-[[@LINE-3]]:8}:"static_cast<void>("
234*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:21-[[@LINE-4]]:21}:")"
235*67e74705SXin Li
236*67e74705SXin Li int y = (return_four(), x);
237*67e74705SXin Li // expected-warning@-1{{comma operator}}
238*67e74705SXin Li // expected-note@-2{{cast expression to void}}
239*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:"static_cast<void>("
240*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:25-[[@LINE-4]]:25}:")"
241*67e74705SXin Li
242*67e74705SXin Li for (; return_four(), x;) {}
243*67e74705SXin Li // expected-warning@-1{{comma operator}}
244*67e74705SXin Li // expected-note@-2{{cast expression to void}}
245*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>("
246*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")"
247*67e74705SXin Li
248*67e74705SXin Li while (return_four(), x) {}
249*67e74705SXin Li // expected-warning@-1{{comma operator}}
250*67e74705SXin Li // expected-note@-2{{cast expression to void}}
251*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast<void>("
252*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")"
253*67e74705SXin Li
254*67e74705SXin Li if (return_four(), x) {}
255*67e74705SXin Li // expected-warning@-1{{comma operator}}
256*67e74705SXin Li // expected-note@-2{{cast expression to void}}
257*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast<void>("
258*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")"
259*67e74705SXin Li
260*67e74705SXin Li do { } while (return_four(), x);
261*67e74705SXin Li // expected-warning@-1{{comma operator}}
262*67e74705SXin Li // expected-note@-2{{cast expression to void}}
263*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:"static_cast<void>("
264*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")"
265*67e74705SXin Li }
266*67e74705SXin Li
267*67e74705SXin Li // Nested comma operator with fix-its.
test14()268*67e74705SXin Li void test14() {
269*67e74705SXin Li return_four(), return_four(), return_four(), return_four();
270*67e74705SXin Li // expected-warning@-1 3{{comma operator}}
271*67e74705SXin Li // expected-note@-2 3{{cast expression to void}}
272*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>("
273*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:16-[[@LINE-4]]:16}:")"
274*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-5]]:18-[[@LINE-5]]:18}:"static_cast<void>("
275*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-6]]:31-[[@LINE-6]]:31}:")"
276*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-7]]:33-[[@LINE-7]]:33}:"static_cast<void>("
277*67e74705SXin Li // CHECK: fix-it:{{.*}}:{[[@LINE-8]]:46-[[@LINE-8]]:46}:")"
278*67e74705SXin Li }
279