1+ // clang-format off
12
2- void test (int i, int j, int (*foo)(int ))
3+ typedef unsigned size_t ;
4+
5+ struct X {
6+ int foo (int y) { return y; }
7+ } x;
8+
9+ #define FOO (x ) ( \
10+ (x), \
11+ (x) \
12+ )
13+
14+ #define BAR (x, y ) ((x), (y))
15+
16+ int test (int i, int j, int (*foo)(int ), int (*bar)(int , int ))
317{
18+ // Comma in simple if statement (prototypical example):
19+
420 if (i)
521 (void )i, // GOOD
622 (void )j;
@@ -9,11 +25,123 @@ void test(int i, int j, int (*foo)(int))
925 (void )i, // BAD
1026 (void )j;
1127
12- foo ((i++, j++)); // GOOD
13- foo ((i++, // GOOD
14- j++));
15- foo ((i++
16- , j++)); // GOOD
17- foo ((i++,
18- j++)); // BAD (?)
28+ // Parenthesized comma (borderline example):
29+
30+ foo (i++), j++; // GOOD
31+ (foo (i++), j++); // GOOD
32+ (foo (i++), // GOOD
33+ j++);
34+ (foo (i++),
35+ j++); // BAD (?)
36+
37+ x.foo (i++), j++; // GOOD
38+ (x.foo (i++), j++); // GOOD
39+ (x.foo (i++), // GOOD [FALSE POSITIVE]
40+ j++);
41+ (x.foo (i++),
42+ j++); // BAD (?)
43+
44+ FOO (i++), j++; // GOOD
45+ (FOO (i++), j++); // GOOD
46+ (FOO (i++), // GOOD
47+ j++);
48+ (FOO (i++),
49+ j++); // BAD (?)
50+
51+ (void )(i++), j++; // GOOD
52+ ((void )(i++), j++); // GOOD
53+ ((void )(i++), // GOOD [FALSE POSITIVE]
54+ j++);
55+ ((void )(i++),
56+ j++); // BAD (?)
57+
58+ // Comma in argument list doesn't count:
59+
60+ bar (i++, j++); // GOOD
61+ bar (i++,
62+ j++); // GOOD
63+ bar (i++
64+ , j++); // GOOD
65+ bar (i++,
66+ j++); // GOOD: common pattern and unlikely to be misread.
67+
68+ BAR (i++, j++); // GOOD
69+ BAR (i++,
70+ j++); // GOOD
71+ BAR (i++
72+ , j++); // GOOD
73+ BAR (i++,
74+ j++); // GOOD: common pattern and unlikely to be misread.
75+
76+ using T = decltype (x.foo (i++), // GOOD [FALSE POSITIVE]
77+ j++);
78+ (void )sizeof (x.foo (i++), // GOOD [FALSE POSITIVE]
79+ j++);
80+
81+ // Comma in loops
82+
83+ while (i = foo (j++), // GOOD
84+ i != j && i != 42 &&
85+ !foo (j)) {
86+ i = j = i + j;
87+ }
88+
89+ // Mixed tabs and spaces (ugly case):
90+
91+ for (i = 0 , // GOOD if tab >= 4 spaces else BAD
92+ j = 0 ;
93+ i + j < 10 ;
94+ i++, // GOOD if tab >= 4 spaces else BAD
95+ j++);
96+
97+ if (i)
98+ (void )i, // GOOD if tab >= 4 spaces else BAD
99+ (void )j;
100+
101+ // One char difference (common but borderline):
102+
103+ for (i = 0 , // GOOD? [FALSE POSITIVE]
104+ j = 1 ;
105+ i + j < 10 ;
106+ i++, j++);
107+
108+ for (i = 0 ,
109+ j = 1 ; i < 10 ; i += 2 , // GOOD? [FALSE POSITIVE]
110+ j++) {}
111+
112+ // LHS ends on same line RHS begins on:
113+
114+ int k = (foo (
115+ i++
116+ ), j++); // GOOD? [FALSE POSITIVE]
117+
118+ // Weird case:
119+
120+ if (foo (j))
121+ return i++
122+ , i++ // GOOD(?) [FALSE POSITIVE]
123+ ? 1
124+ : 2 ;
125+
126+ return 0 ;
19127}
128+
129+ // Comma in variadic template splice:
130+
131+ namespace std {
132+ template <size_t ... Is>
133+ struct index_sequence {};
134+ }
135+
136+ template <size_t I>
137+ struct zip_index {};
138+
139+ template <size_t I>
140+ int & at (zip_index<I>) { throw 1 ; }
141+
142+ template <class Fn , class At , size_t ... Is>
143+ void for_each_input (Fn&& fn, std::index_sequence<Is...>) {
144+ (fn (zip_index<Is>{}, at (zip_index<Is>{})), ...); // GOOD
145+ }
146+
147+ // clang-format on
0 commit comments