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 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 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 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 82 int return_four() { return 5; } 83 84 // Confusing "," for "<<" 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 "==" 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 "+" 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 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 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. 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 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 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. 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. 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