Clang Project

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