1 | // RUN: %check_clang_tidy %s bugprone-sizeof-expression %t -- -config="{CheckOptions: {bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression: true, bugprone-sizeof-expression.WarnOnSizeOfPointer: true}}" -- |
2 | |
3 | class C { |
4 | int size() { return sizeof(this); } |
5 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(this)' |
6 | }; |
7 | |
8 | #define LEN 8 |
9 | |
10 | int X; |
11 | extern int A[10]; |
12 | extern short B[10]; |
13 | |
14 | #pragma pack(1) |
15 | struct S { char a, b, c; }; |
16 | |
17 | enum E { E_VALUE = 0 }; |
18 | enum class EC { VALUE = 0 }; |
19 | |
20 | bool AsBool() { return false; } |
21 | int AsInt() { return 0; } |
22 | E AsEnum() { return E_VALUE; } |
23 | EC AsEnumClass() { return EC::VALUE; } |
24 | S AsStruct() { return {}; } |
25 | |
26 | struct M { |
27 | int AsInt() { return 0; } |
28 | E AsEnum() { return E_VALUE; } |
29 | S AsStruct() { return {}; } |
30 | }; |
31 | |
32 | int Test1(const char* ptr) { |
33 | int sum = 0; |
34 | sum += sizeof(LEN); |
35 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)' |
36 | sum += sizeof(LEN + 1); |
37 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)' |
38 | sum += sizeof(sum, LEN); |
39 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(..., ...)' |
40 | sum += sizeof(AsBool()); |
41 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type |
42 | sum += sizeof(AsInt()); |
43 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type |
44 | sum += sizeof(AsEnum()); |
45 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type |
46 | sum += sizeof(AsEnumClass()); |
47 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type |
48 | sum += sizeof(M{}.AsInt()); |
49 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type |
50 | sum += sizeof(M{}.AsEnum()); |
51 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type |
52 | sum += sizeof(sizeof(X)); |
53 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' |
54 | sum += sizeof(LEN + sizeof(X)); |
55 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' |
56 | sum += sizeof(LEN + LEN + sizeof(X)); |
57 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' |
58 | sum += sizeof(LEN + (LEN + sizeof(X))); |
59 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' |
60 | sum += sizeof(LEN + -sizeof(X)); |
61 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' |
62 | sum += sizeof(LEN + - + -sizeof(X)); |
63 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' |
64 | sum += sizeof(char) / sizeof(char); |
65 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type |
66 | sum += sizeof(A) / sizeof(S); |
67 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator |
68 | sum += sizeof(char) / sizeof(int); |
69 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator |
70 | sum += sizeof(char) / sizeof(A); |
71 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator |
72 | sum += sizeof(B[0]) / sizeof(A); |
73 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator |
74 | sum += sizeof(ptr) / sizeof(char); |
75 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
76 | sum += sizeof(ptr) / sizeof(ptr[0]); |
77 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
78 | sum += sizeof(ptr) / sizeof(char*); |
79 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
80 | sum += sizeof(ptr) / sizeof(void*); |
81 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
82 | sum += sizeof(ptr) / sizeof(const void volatile*); |
83 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
84 | sum += sizeof(ptr) / sizeof(char); |
85 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
86 | sum += sizeof(int) * sizeof(char); |
87 | // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication |
88 | sum += sizeof(ptr) * sizeof(ptr[0]); |
89 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
90 | // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication |
91 | sum += sizeof(int) * (2 * sizeof(char)); |
92 | // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication |
93 | sum += (2 * sizeof(char)) * sizeof(int); |
94 | // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious 'sizeof' by 'sizeof' multiplication |
95 | if (sizeof(A) < 0x100000) sum += 42; |
96 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: suspicious comparison of 'sizeof(expr)' to a constant |
97 | if (sizeof(A) <= 0xFFFFFFFEU) sum += 42; |
98 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: suspicious comparison of 'sizeof(expr)' to a constant |
99 | return sum; |
100 | } |
101 | |
102 | int Test5() { |
103 | typedef int Array10[10]; |
104 | typedef C ArrayC[10]; |
105 | |
106 | struct MyStruct { |
107 | Array10 arr; |
108 | Array10* ptr; |
109 | }; |
110 | typedef const MyStruct TMyStruct; |
111 | typedef const MyStruct *PMyStruct; |
112 | typedef TMyStruct *PMyStruct2; |
113 | |
114 | static TMyStruct kGlocalMyStruct = {}; |
115 | static TMyStruct volatile * kGlocalMyStructPtr = &kGlocalMyStruct; |
116 | |
117 | MyStruct S; |
118 | PMyStruct PS; |
119 | PMyStruct2 PS2; |
120 | Array10 A10; |
121 | C *PtrArray[10]; |
122 | C *PC; |
123 | |
124 | char *PChar; |
125 | int *PInt, **PPInt; |
126 | MyStruct **PPMyStruct; |
127 | |
128 | int sum = 0; |
129 | sum += sizeof(&S.arr); |
130 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
131 | sum += sizeof(&kGlocalMyStruct.arr); |
132 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
133 | sum += sizeof(&kGlocalMyStructPtr->arr); |
134 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
135 | sum += sizeof(S.arr + 0); |
136 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
137 | sum += sizeof(+ S.arr); |
138 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
139 | sum += sizeof((int*)S.arr); |
140 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
141 | |
142 | sum += sizeof(S.ptr); |
143 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
144 | sum += sizeof(kGlocalMyStruct.ptr); |
145 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
146 | sum += sizeof(kGlocalMyStructPtr->ptr); |
147 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
148 | |
149 | sum += sizeof(&kGlocalMyStruct); |
150 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
151 | sum += sizeof(&S); |
152 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
153 | sum += sizeof(MyStruct*); |
154 | sum += sizeof(PMyStruct); |
155 | sum += sizeof(PS); |
156 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
157 | sum += sizeof(PS2); |
158 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
159 | sum += sizeof(&A10); |
160 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
161 | sum += sizeof(PtrArray) / sizeof(PtrArray[1]); |
162 | // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
163 | sum += sizeof(A10) / sizeof(PtrArray[0]); |
164 | sum += sizeof(PC) / sizeof(PtrArray[0]); |
165 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
166 | // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type |
167 | sum += sizeof(ArrayC) / sizeof(PtrArray[0]); |
168 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator |
169 | |
170 | sum += sizeof(PChar); |
171 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
172 | sum += sizeof(PInt); |
173 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
174 | sum += sizeof(PPInt); |
175 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
176 | sum += sizeof(PPMyStruct); |
177 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
178 | |
179 | return sum; |
180 | } |
181 | |
182 | void some_generic_function(const void *arg, int argsize); |
183 | int *IntP, **IntPP; |
184 | C *ClassP, **ClassPP; |
185 | |
186 | void GenericFunctionTest() { |
187 | // The `sizeof(pointer)` checks ignore situations where the pointer is |
188 | // produced by dereferencing a pointer-to-pointer, because this is unlikely |
189 | // to be an accident and can appear in legitimate code that tries to call |
190 | // a generic function which emulates dynamic typing within C. |
191 | some_generic_function(arg: IntPP, argsize: sizeof(*IntPP)); |
192 | some_generic_function(arg: ClassPP, argsize: sizeof(*ClassPP)); |
193 | // Using `...[0]` instead of the dereference operator is another common |
194 | // variant, which is also widespread in the idiomatic array-size calculation: |
195 | // `sizeof(array) / sizeof(array[0])`. |
196 | some_generic_function(arg: IntPP, argsize: sizeof(IntPP[0])); |
197 | some_generic_function(arg: ClassPP, argsize: sizeof(ClassPP[0])); |
198 | // FIXME: There is a third common pattern where the generic function is |
199 | // called with `&Variable` and `sizeof(Variable)`. Right now these are |
200 | // reported by the `sizeof(pointer)` checks, but this causes some false |
201 | // positives, so it would be good to create an exception for them. |
202 | some_generic_function(arg: &IntPP, argsize: sizeof(IntP)); |
203 | // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
204 | some_generic_function(arg: &ClassPP, argsize: sizeof(ClassP)); |
205 | // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
206 | } |
207 | |
208 | int ValidExpressions() { |
209 | int A[] = {1, 2, 3, 4}; |
210 | static const char str[] = "hello" ; |
211 | static const char* ptr[] { "aaa" , "bbb" , "ccc" }; |
212 | typedef C *CA10[10]; |
213 | C *PtrArray[10]; |
214 | CA10 PtrArray1; |
215 | |
216 | int sum = 0; |
217 | if (sizeof(A) < 10) |
218 | sum += sizeof(A); |
219 | sum += sizeof(int); |
220 | sum += sizeof(AsStruct()); |
221 | sum += sizeof(M{}.AsStruct()); |
222 | sum += sizeof(A[sizeof(A) / sizeof(int)]); |
223 | // Here the outer sizeof is reported, but the inner ones are accepted: |
224 | sum += sizeof(&A[sizeof(A) / sizeof(int)]); |
225 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
226 | sum += sizeof(sizeof(0)); // Special case: sizeof size_t. |
227 | sum += sizeof(void*); |
228 | sum += sizeof(void const *); |
229 | sum += sizeof(void const *) / 4; |
230 | sum += sizeof(str); |
231 | sum += sizeof(str) / sizeof(char); |
232 | sum += sizeof(str) / sizeof(str[0]); |
233 | sum += sizeof(ptr) / sizeof(ptr[0]); |
234 | sum += sizeof(ptr) / sizeof(*(ptr)); |
235 | sum += sizeof(PtrArray) / sizeof(PtrArray[0]); |
236 | // Canonical type of PtrArray1 is same as PtrArray. |
237 | sum = sizeof(PtrArray) / sizeof(PtrArray1[0]); |
238 | // There is no warning for 'sizeof(T*)/sizeof(Q)' case. |
239 | sum += sizeof(PtrArray) / sizeof(A[0]); |
240 | return sum; |
241 | } |
242 | |