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