// RUN: %clang_cc1 -fsyntax-only -Wcomma -std=c++11 -verify %s // RUN: %clang_cc1 -fsyntax-only -Wcomma -std=c++11 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s // Test builtin operators void test1() { int x = 0, y = 0; for (; y < 10; x++, y++) {} for (; y < 10; ++x, y++) {} for (; y < 10; x++, ++y) {} for (; y < 10; ++x, ++y) {} for (; y < 10; x--, ++y) {} for (; y < 10; --x, ++y) {} for (; y < 10; x = 5, ++y) {} for (; y < 10; x *= 5, ++y) {} for (; y < 10; x /= 5, ++y) {} for (; y < 10; x %= 5, ++y) {} for (; y < 10; x += 5, ++y) {} for (; y < 10; x -= 5, ++y) {} for (; y < 10; x <<= 5, ++y) {} for (; y < 10; x >>= 5, ++y) {} for (; y < 10; x &= 5, ++y) {} for (; y < 10; x |= 5, ++y) {} for (; y < 10; x ^= 5, ++y) {} } class S2 { public: void advance(); S2 operator++(); S2 operator++(int); S2 operator--(); S2 operator--(int); S2 operator=(int); S2 operator*=(int); S2 operator/=(int); S2 operator%=(int); S2 operator+=(int); S2 operator-=(int); S2 operator<<=(int); S2 operator>>=(int); S2 operator&=(int); S2 operator|=(int); S2 operator^=(int); }; // Test overloaded operators void test2() { S2 x; int y; for (; y < 10; x++, y++) {} for (; y < 10; ++x, y++) {} for (; y < 10; x++, ++y) {} for (; y < 10; ++x, ++y) {} for (; y < 10; x--, ++y) {} for (; y < 10; --x, ++y) {} for (; y < 10; x = 5, ++y) {} for (; y < 10; x *= 5, ++y) {} for (; y < 10; x /= 5, ++y) {} for (; y < 10; x %= 5, ++y) {} for (; y < 10; x += 5, ++y) {} for (; y < 10; x -= 5, ++y) {} for (; y < 10; x <<= 5, ++y) {} for (; y < 10; x >>= 5, ++y) {} for (; y < 10; x &= 5, ++y) {} for (; y < 10; x |= 5, ++y) {} for (; y < 10; x ^= 5, ++y) {} } // Test nested comma operators void test3() { int x1, x2, x3; int y1, *y2 = 0, y3 = 5; for (int z1 = 5, z2 = 4, z3 = 3; x1 <4; ++x1) {} } class Stream { public: Stream& operator<<(int); } cout; int return_four() { return 5; } // Confusing "," for "<<" void test4() { cout << 5 << return_four(); cout << 5, return_four(); // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:12-[[@LINE-4]]:12}:")" } // Confusing "," for "==" void test5() { if (return_four(), 5) {} // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")" if (return_four() == 5) {} } // Confusing "," for "+" int test6() { return return_four(), return_four(); // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")" return return_four() + return_four(); } void Concat(int); void Concat(int, int); // Testing extra parentheses in function call void test7() { Concat((return_four() , 5)); // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:24-[[@LINE-4]]:24}:")" Concat(return_four() , 5); } // Be sure to look through parentheses void test8() { int x, y; for (x = 0; return_four(), x;) {} // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:28-[[@LINE-4]]:28}:")" for (x = 0; (return_four()), (x) ;) {} // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:15-[[@LINE-3]]:15}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")" } bool DoStuff(); class S9 { public: bool Advance(); bool More(); }; // Ignore comma operator in for-loop initializations and increments. void test9() { int x, y; for (x = 0, y = 5; x < y; ++x) {} for (x = 0; x < 10; DoStuff(), ++x) {} for (S9 s; s.More(); s.Advance(), ++x) {} } void test10() { int x, y; ++x, ++y; // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:6-[[@LINE-4]]:6}:")" } // Ignore comma operator in templates. namespace test11 { template struct B { static const bool value = T; }; typedef B true_type; typedef B false_type; template struct bool_seq; template class Foo { typedef bool_seq<(xs::value, true)...> all_true; typedef bool_seq<(xs::value, false)...> all_false; typedef bool_seq seq; }; const auto X = Foo(); } namespace test12 { class Mutex { public: Mutex(); ~Mutex(); }; class MutexLock { public: MutexLock(Mutex &); MutexLock(); ~MutexLock(); }; class BuiltinMutex { Mutex M; }; Mutex StatusMutex; bool Status; bool get_status() { return (MutexLock(StatusMutex), Status); // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:33-[[@LINE-4]]:33}:")" return (MutexLock(), Status); // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:22-[[@LINE-4]]:22}:")" return (BuiltinMutex(), Status); // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:11-[[@LINE-3]]:11}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:25-[[@LINE-4]]:25}:")" } } // Check for comma operator in conditions. void test13(int x) { x = (return_four(), x); // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:8-[[@LINE-3]]:8}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:21-[[@LINE-4]]:21}:")" int y = (return_four(), x); // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:12-[[@LINE-3]]:12}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:25-[[@LINE-4]]:25}:")" for (; return_four(), x;) {} // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")" while (return_four(), x) {} // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:10-[[@LINE-3]]:10}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:23-[[@LINE-4]]:23}:")" if (return_four(), x) {} // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:7-[[@LINE-3]]:7}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:20-[[@LINE-4]]:20}:")" do { } while (return_four(), x); // expected-warning@-1{{comma operator}} // expected-note@-2{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:17-[[@LINE-3]]:17}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:30-[[@LINE-4]]:30}:")" } // Nested comma operator with fix-its. void test14() { return_four(), return_four(), return_four(), return_four(); // expected-warning@-1 3{{comma operator}} // expected-note@-2 3{{cast expression to void}} // CHECK: fix-it:{{.*}}:{[[@LINE-3]]:3-[[@LINE-3]]:3}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-4]]:16-[[@LINE-4]]:16}:")" // CHECK: fix-it:{{.*}}:{[[@LINE-5]]:18-[[@LINE-5]]:18}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-6]]:31-[[@LINE-6]]:31}:")" // CHECK: fix-it:{{.*}}:{[[@LINE-7]]:33-[[@LINE-7]]:33}:"static_cast(" // CHECK: fix-it:{{.*}}:{[[@LINE-8]]:46-[[@LINE-8]]:46}:")" }