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 10 int return_four() { return 5; } 11 12 // Test builtin operators 13 void 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 35 void 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 "==" 45 void 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 "+" 56 int 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 67 void 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 82 void 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. 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}:")" 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. 131 void 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 144 class S2 { 145 public: 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 166 void 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 188 class Stream { 189 public: 190 Stream& operator<<(int); 191 } cout; 192 193 // Confusing "," for "<<" 194 void 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 203 void Concat(int); 204 void Concat(int, int); 205 206 // Testing extra parentheses in function call 207 void 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 217 bool DoStuff(); 218 class S9 { 219 public: 220 bool Advance(); 221 bool More(); 222 }; 223 224 // Ignore comma operator in for-loop initializations and increments. 225 void 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. 233 namespace test_template { 234 template <bool T> 235 struct B { static const bool value = T; }; 236 237 typedef B<true> true_type; 238 typedef B<false> false_type; 239 240 template <bool...> 241 struct bool_seq; 242 243 template <typename... xs> 244 class Foo { 245 typedef bool_seq<((void)xs::value, true)...> all_true; 246 typedef bool_seq<((void)xs::value, false)...> all_false; 247 typedef bool_seq<xs::value...> seq; 248 }; 249 250 const auto X = Foo<true_type>(); 251 } 252 253 namespace test_mutex { 254 class Mutex { 255 public: 256 Mutex(); 257 ~Mutex(); 258 }; 259 class MutexLock { 260 public: 261 MutexLock(Mutex &); 262 MutexLock(); 263 ~MutexLock(); 264 }; 265 class BuiltinMutex { 266 Mutex M; 267 }; 268 Mutex StatusMutex; 269 bool Status; 270 271 bool 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 291 template <typename T> 292 void 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