1 // RUN: %check_clang_tidy %s bugprone-sizeof-expression %t -- -config="{CheckOptions: [{key: bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression, value: 1}]}" --
2 
3 class C {
size()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 
AsBool()20 bool AsBool() { return false; }
AsInt()21 int AsInt() { return 0; }
AsEnum()22 E AsEnum() { return E_VALUE; }
AsEnumClass()23 EC AsEnumClass() { return EC::VALUE; }
AsStruct()24 S AsStruct() { return {}; }
25 
26 struct M {
AsIntM27   int AsInt() { return 0; }
AsEnumM28   E AsEnum() { return E_VALUE; }
AsStructM29   S AsStruct() { return {}; }
30 };
31 
ReturnOverload(int)32 int ReturnOverload(int) { return {}; }
ReturnOverload(S)33 S ReturnOverload(S) { return {}; }
34 
35 template <class T>
ReturnTemplate(T)36 T ReturnTemplate(T) { return {}; }
37 
38 template <class T>
TestTrait1()39 bool TestTrait1() {
40   return sizeof(ReturnOverload(T{})) == sizeof(A);
41 }
42 
43 template <class T>
TestTrait2()44 bool TestTrait2() {
45   return sizeof(ReturnTemplate(T{})) == sizeof(A);
46 }
47 
48 template <class T>
TestTrait3()49 bool TestTrait3() {
50   return sizeof(ReturnOverload(0)) == sizeof(T{});
51   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
52 }
53 
54 template <class T>
TestTrait4()55 bool TestTrait4() {
56   return sizeof(ReturnTemplate(0)) == sizeof(T{});
57   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
58 }
59 
TestTemplates()60 bool TestTemplates() {
61   bool b = true;
62   b &= TestTrait1<int>();
63   b &= TestTrait1<S>();
64   b &= TestTrait2<int>();
65   b &= TestTrait2<S>();
66   b &= TestTrait3<int>();
67   b &= TestTrait3<S>();
68   b &= TestTrait4<int>();
69   b &= TestTrait4<S>();
70   return b;
71 }
72 
Test1(const char * ptr)73 int Test1(const char* ptr) {
74   int sum = 0;
75   sum += sizeof(LEN);
76   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)'
77   sum += sizeof(LEN + 1);
78   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)'
79   sum += sizeof(sum, LEN);
80   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(..., ...)'
81   sum += sizeof(AsBool());
82   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
83   sum += sizeof(AsInt());
84   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
85   sum += sizeof(AsEnum());
86   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
87   sum += sizeof(AsEnumClass());
88   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
89   sum += sizeof(M{}.AsInt());
90   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
91   sum += sizeof(M{}.AsEnum());
92   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer
93   sum += sizeof(sizeof(X));
94   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
95   sum += sizeof(LEN + sizeof(X));
96   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
97   sum += sizeof(LEN + LEN + sizeof(X));
98   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
99   sum += sizeof(LEN + (LEN + sizeof(X)));
100   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
101   sum += sizeof(LEN + -sizeof(X));
102   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
103   sum += sizeof(LEN + - + -sizeof(X));
104   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
105   sum += sizeof(char) / sizeof(char);
106   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
107   sum += sizeof(A) / sizeof(S);
108   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
109   sum += sizeof(char) / sizeof(int);
110   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
111   sum += sizeof(char) / sizeof(A);
112   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
113   sum += sizeof(B[0]) / sizeof(A);
114   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
115   sum += sizeof(ptr) / sizeof(char);
116   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
117   sum += sizeof(ptr) / sizeof(ptr[0]);
118   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
119   sum += sizeof(ptr) / sizeof(char*);
120   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
121   sum += sizeof(ptr) / sizeof(void*);
122   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
123   sum += sizeof(ptr) / sizeof(const void volatile*);
124   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(P*)/sizeof(Q*)'
125   sum += sizeof(ptr) / sizeof(char);
126   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
127   sum += sizeof(ptr) / sizeof(ptr[0]);
128   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T*)/sizeof(T)'
129   sum += sizeof(int) * sizeof(char);
130   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
131   sum += sizeof(ptr) * sizeof(ptr[0]);
132   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
133   sum += sizeof(int) * (2 * sizeof(char));
134   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
135   sum += (2 * sizeof(char)) * sizeof(int);
136   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious 'sizeof' by 'sizeof' multiplication
137   if (sizeof(A) < 0x100000) sum += 42;
138   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: suspicious comparison of 'sizeof(expr)' to a constant
139   if (sizeof(A) <= 0xFFFFFFFEU) sum += 42;
140   // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: suspicious comparison of 'sizeof(expr)' to a constant
141   return sum;
142 }
143 
144 typedef char MyChar;
145 typedef const MyChar MyConstChar;
146 
147 int CE0 = sizeof sizeof(char);
148 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
149 int CE1 = sizeof +sizeof(char);
150 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
151 int CE2 = sizeof sizeof(const char*);
152 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
153 int CE3 = sizeof sizeof(const volatile char* const*);
154 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
155 int CE4 = sizeof sizeof(MyConstChar);
156 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
157 
Test2(MyConstChar * A)158 int Test2(MyConstChar* A) {
159   int sum = 0;
160   sum += sizeof(MyConstChar) / sizeof(char);
161   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
162   sum += sizeof(MyConstChar) / sizeof(MyChar);
163   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
164   sum += sizeof(A[0]) / sizeof(char);
165   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
166   return sum;
167 }
168 
169 template <int T>
Foo()170 int Foo() { int A[T]; return sizeof(T); }
171 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(K)'
172 template <typename T>
Bar()173 int Bar() { T A[5]; return sizeof(A[0]) / sizeof(T); }
174 // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
Test3()175 int Test3() { return Foo<42>() + Bar<char>(); }
176 
177 static const char* kABC = "abc";
178 static const wchar_t* kDEF = L"def";
Test4(const char A[10])179 int Test4(const char A[10]) {
180   int sum = 0;
181   sum += sizeof(kABC);
182   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)'
183   sum += sizeof(kDEF);
184   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)'
185   return sum;
186 }
187 
Test5()188 int Test5() {
189   typedef int Array10[10];
190   typedef C ArrayC[10];
191 
192   struct MyStruct {
193     Array10 arr;
194     Array10* ptr;
195   };
196   typedef const MyStruct TMyStruct;
197   typedef const MyStruct *PMyStruct;
198   typedef TMyStruct *PMyStruct2;
199 
200   static TMyStruct kGlocalMyStruct = {};
201   static TMyStruct volatile * kGlocalMyStructPtr = &kGlocalMyStruct;
202 
203   MyStruct S;
204   PMyStruct PS;
205   PMyStruct2 PS2;
206   Array10 A10;
207   C *PtrArray[10];
208   C *PC;
209 
210   int sum = 0;
211   sum += sizeof(&S.arr);
212   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
213   sum += sizeof(&kGlocalMyStruct.arr);
214   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
215   sum += sizeof(&kGlocalMyStructPtr->arr);
216   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
217   sum += sizeof(S.arr + 0);
218   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
219   sum += sizeof(+ S.arr);
220   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
221   sum += sizeof((int*)S.arr);
222   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
223 
224   sum += sizeof(S.ptr);
225   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
226   sum += sizeof(kGlocalMyStruct.ptr);
227   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
228   sum += sizeof(kGlocalMyStructPtr->ptr);
229   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
230 
231   sum += sizeof(&kGlocalMyStruct);
232   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
233   sum += sizeof(&S);
234   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
235   sum += sizeof(MyStruct*);
236   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
237   sum += sizeof(PMyStruct);
238   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
239   sum += sizeof(PS);
240   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
241   sum += sizeof(PS2);
242   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
243   sum += sizeof(&A10);
244   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
245   sum += sizeof(PtrArray) / sizeof(PtrArray[1]);
246   // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
247   sum += sizeof(A10) / sizeof(PtrArray[0]);
248   // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
249   sum += sizeof(PC) / sizeof(PtrArray[0]);
250   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
251   // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)'
252   // CHECK-MESSAGES: :[[@LINE-3]]:23: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
253   sum += sizeof(ArrayC) / sizeof(PtrArray[0]);
254   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
255   // CHECK-MESSAGES: :[[@LINE-2]]:27: warning: suspicious usage of 'sizeof(A*)'; pointer to aggregate
256 
257   return sum;
258 }
259 
Test6()260 int Test6() {
261   int sum = 0;
262 
263   struct S A = AsStruct(), B = AsStruct();
264   struct S *P = &A, *Q = &B;
265   sum += sizeof(struct S) == P - Q;
266   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
267   sum += 5 * sizeof(S) != P - Q;
268   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
269   sum += sizeof(S) < P - Q;
270   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
271   sum += 5 * sizeof(S) <= P - Q;
272   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
273   sum += 5 * sizeof(*P) >= P - Q;
274   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
275   sum += Q - P > 3 * sizeof(*P);
276   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
277   sum += sizeof(S) + (P - Q);
278   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
279   sum += 5 * sizeof(S) - (P - Q);
280   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
281   sum += (P - Q) / sizeof(S);
282   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
283   sum += (P - Q) / sizeof(*Q);
284   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
285 
286   return sum;
287 }
288 
ValidExpressions()289 int ValidExpressions() {
290   int A[] = {1, 2, 3, 4};
291   static const char str[] = "hello";
292   static const char* ptr[] { "aaa", "bbb", "ccc" };
293   typedef C *CA10[10];
294   C *PtrArray[10];
295   CA10 PtrArray1;
296 
297   int sum = 0;
298   if (sizeof(A) < 10)
299     sum += sizeof(A);
300   sum += sizeof(int);
301   sum += sizeof(AsStruct());
302   sum += sizeof(M{}.AsStruct());
303   sum += sizeof(A[sizeof(A) / sizeof(int)]);
304   sum += sizeof(&A[sizeof(A) / sizeof(int)]);
305   sum += sizeof(sizeof(0));  // Special case: sizeof size_t.
306   sum += sizeof(void*);
307   sum += sizeof(void const *);
308   sum += sizeof(void const *) / 4;
309   sum += sizeof(str);
310   sum += sizeof(str) / sizeof(char);
311   sum += sizeof(str) / sizeof(str[0]);
312   sum += sizeof(ptr) / sizeof(ptr[0]);
313   sum += sizeof(ptr) / sizeof(*(ptr));
314   sum += sizeof(PtrArray) / sizeof(PtrArray[0]);
315   // Canonical type of PtrArray1 is same as PtrArray.
316   sum = sizeof(PtrArray) / sizeof(PtrArray1[0]);
317   // There is no warning for 'sizeof(T*)/sizeof(Q)' case.
318   sum += sizeof(PtrArray) / sizeof(A[0]);
319   return sum;
320 }
321