1
+ // clang-format off
1
2
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 ))
3
17
{
18
+ // Comma in simple if statement (prototypical example):
19
+
4
20
if (i)
5
21
(void )i, // GOOD
6
22
(void )j;
@@ -9,11 +25,123 @@ void test(int i, int j, int (*foo)(int))
9
25
(void )i, // BAD
10
26
(void )j;
11
27
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 ;
19
127
}
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