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