[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang / test / SemaCXX / warn-comma-operator.cpp
blob75148cb416fdbd1b3a5b15bc2911f5d589c95b8d
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
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
9 // int returning function
10 int return_four(void) { return 5; }
12 // Test builtin operators
13 void test_builtin(void) {
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) {}
34 // Test nested comma operators
35 void test_nested(void) {
36 int x1, x2, x3;
37 int y1, *y2 = 0, y3 = 5;
39 #if __STDC_VERSION >= 199901L
40 for (int z1 = 5, z2 = 4, z3 = 3; x1 <4; ++x1) {}
41 #endif
44 // Confusing "," for "=="
45 void test_compare(void) {
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}:")"
52 if (return_four() == 5) {}
55 // Confusing "," for "+"
56 int test_plus(void) {
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}:")"
63 return return_four() + return_four();
66 // Be sure to look through parentheses
67 void test_parentheses(void) {
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}:")"
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}:")"
82 void test_increment(void) {
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}:")"
91 // Check for comma operator in conditions.
92 void 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}:")"
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}:")"
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}:")"
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}:")"
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}:")"
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}:")"
130 // Nested comma operator with fix-its.
131 void test_nested_fixits(void) {
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}:")"
144 void void_func();
145 int int_func() { return 0; }
147 void void_function_comma(){
148 void_func(), int_func(); // expected no -Wcomma because of the returning type `void`
149 // Reported by https://github.com/llvm/llvm-project/issues/57151
150 // Descriptions about -Wcomma: https://reviews.llvm.org/D3976
153 typedef void Void;
154 Void typedef_func();
156 void whatever() {
157 // We don't get confused about type aliases.
158 typedef_func(), int_func();
159 // Even function pointers don't confuse us.
160 void (*fp)() = void_func;
161 fp(), int_func();
164 #ifdef __cplusplus
165 class S2 {
166 public:
167 void advance();
169 S2 operator++();
170 S2 operator++(int);
171 S2 operator--();
172 S2 operator--(int);
173 S2 operator=(int);
174 S2 operator*=(int);
175 S2 operator/=(int);
176 S2 operator%=(int);
177 S2 operator+=(int);
178 S2 operator-=(int);
179 S2 operator<<=(int);
180 S2 operator>>=(int);
181 S2 operator&=(int);
182 S2 operator|=(int);
183 S2 operator^=(int);
186 // Test overloaded operators
187 void test_overloaded_operator() {
188 S2 x;
189 int y;
190 for (; y < 10; x++, y++) {}
191 for (; y < 10; ++x, y++) {}
192 for (; y < 10; x++, ++y) {}
193 for (; y < 10; ++x, ++y) {}
194 for (; y < 10; x--, ++y) {}
195 for (; y < 10; --x, ++y) {}
196 for (; y < 10; x = 5, ++y) {}
197 for (; y < 10; x *= 5, ++y) {}
198 for (; y < 10; x /= 5, ++y) {}
199 for (; y < 10; x %= 5, ++y) {}
200 for (; y < 10; x += 5, ++y) {}
201 for (; y < 10; x -= 5, ++y) {}
202 for (; y < 10; x <<= 5, ++y) {}
203 for (; y < 10; x >>= 5, ++y) {}
204 for (; y < 10; x &= 5, ++y) {}
205 for (; y < 10; x |= 5, ++y) {}
206 for (; y < 10; x ^= 5, ++y) {}
209 class Stream {
210 public:
211 Stream& operator<<(int);
212 } cout;
214 // Confusing "," for "<<"
215 void test_stream() {
216 cout << 5 << return_four();
217 cout << 5, return_four();
218 // expected-warning@-1{{comma operator}}
219 // expected-note@-2{{cast expression to void}}
220 // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast<void>("
221 // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:12-[[@LINE-4]]:12}:")"
224 void Concat(int);
225 void Concat(int, int);
227 // Testing extra parentheses in function call
228 void test_overloaded_function() {
229 Concat((return_four() , 5));
230 // expected-warning@-1{{comma operator}}
231 // expected-note@-2{{cast expression to void}}
232 // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast<void>("
233 // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:24-[[@LINE-4]]:24}:")"
235 Concat(return_four() , 5);
238 bool DoStuff();
239 class S9 {
240 public:
241 bool Advance();
242 bool More();
245 // Ignore comma operator in for-loop initializations and increments.
246 void test_for_loop() {
247 int x, y;
248 for (x = 0, y = 5; x < y; ++x) {}
249 for (x = 0; x < 10; DoStuff(), ++x) {}
250 for (S9 s; s.More(); s.Advance(), ++x) {}
253 // Ignore comma operator in templates.
254 namespace test_template {
255 template <bool T>
256 struct B { static const bool value = T; };
258 typedef B<true> true_type;
259 typedef B<false> false_type;
261 template <bool...>
262 struct bool_seq;
264 template <typename... xs>
265 class Foo {
266 typedef bool_seq<((void)xs::value, true)...> all_true;
267 typedef bool_seq<((void)xs::value, false)...> all_false;
268 typedef bool_seq<xs::value...> seq;
271 const auto X = Foo<true_type>();
274 namespace test_mutex {
275 class Mutex {
276 public:
277 Mutex();
278 ~Mutex();
280 class MutexLock {
281 public:
282 MutexLock(Mutex &);
283 MutexLock();
284 ~MutexLock();
286 class BuiltinMutex {
287 Mutex M;
289 Mutex StatusMutex;
290 bool Status;
292 bool get_status() {
293 return (MutexLock(StatusMutex), Status);
294 // expected-warning@-1{{comma operator}}
295 // expected-note@-2{{cast expression to void}}
296 // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast<void>("
297 // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:33-[[@LINE-4]]:33}:")"
298 return (MutexLock(), Status);
299 // expected-warning@-1{{comma operator}}
300 // expected-note@-2{{cast expression to void}}
301 // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast<void>("
302 // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:22-[[@LINE-4]]:22}:")"
303 return (BuiltinMutex(), Status);
304 // expected-warning@-1{{comma operator}}
305 // expected-note@-2{{cast expression to void}}
306 // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast<void>("
307 // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:25-[[@LINE-4]]:25}:")"
311 // PR39375 - test cast to void to silence warnings
312 template <typename T>
313 void test_dependent_cast() {
314 (void)42, 0;
315 static_cast<void>(42), 0;
317 (void)T{}, 0;
318 static_cast<void>(T{}), 0;
321 namespace {
323 // issue #57151
325 struct S {
326 void mem() {}
329 void whatever() {
330 struct S s;
331 // Member function calls also work as expected.
332 s.mem(), int_func();
333 // As do lambda calls.
334 []() { return; }(), int_func();
337 } // namespace
339 #endif // ifdef __cplusplus