1 // RUN: %check_clang_tidy %s bugprone-sizeof-expression %t -- -config="{CheckOptions: {bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression: 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 ReturnOverload(int) { return {}; } 33 S ReturnOverload(S) { return {}; } 34 35 template <class T> 36 T ReturnTemplate(T) { return {}; } 37 38 template <class T> 39 bool TestTrait1() { 40 return sizeof(ReturnOverload(T{})) == sizeof(A); 41 } 42 43 template <class T> 44 bool TestTrait2() { 45 return sizeof(ReturnTemplate(T{})) == sizeof(A); 46 } 47 48 template <class T> 49 bool TestTrait3() { 50 return sizeof(ReturnOverload(0)) == sizeof(T{}); 51 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type 52 } 53 54 template <class T> 55 bool TestTrait4() { 56 return sizeof(ReturnTemplate(0)) == sizeof(T{}); 57 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type 58 } 59 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 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]]:20: warning: suspicious usage of 'sizeof(..., ...)' 81 sum += sizeof(AsBool()); 82 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type 83 sum += sizeof(AsInt()); 84 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type 85 sum += sizeof(AsEnum()); 86 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type 87 sum += sizeof(AsEnumClass()); 88 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type 89 sum += sizeof(M{}.AsInt()); 90 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type 91 sum += sizeof(M{}.AsEnum()); 92 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type 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]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type 107 sum += sizeof(A) / sizeof(S); 108 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator 109 sum += sizeof(char) / sizeof(int); 110 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator 111 sum += sizeof(char) / sizeof(A); 112 // CHECK-MESSAGES: :[[@LINE-1]]:23: 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]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator 115 sum += sizeof(ptr) / sizeof(char); 116 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer is divided by size of pointed type 117 sum += sizeof(ptr) / sizeof(ptr[0]); 118 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer is divided by size of pointed type 119 sum += sizeof(ptr) / sizeof(char*); 120 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have pointer types 121 sum += sizeof(ptr) / sizeof(void*); 122 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have pointer types 123 sum += sizeof(ptr) / sizeof(const void volatile*); 124 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have pointer types 125 sum += sizeof(ptr) / sizeof(char); 126 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer is divided by size of pointed type 127 sum += sizeof(int) * sizeof(char); 128 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication 129 sum += sizeof(ptr) * sizeof(ptr[0]); 130 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication 131 sum += sizeof(int) * (2 * sizeof(char)); 132 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication 133 sum += (2 * sizeof(char)) * sizeof(int); 134 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious 'sizeof' by 'sizeof' multiplication 135 if (sizeof(A) < 0x100000) sum += 42; 136 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: suspicious comparison of 'sizeof(expr)' to a constant 137 if (sizeof(A) <= 0xFFFFFFFEU) sum += 42; 138 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: suspicious comparison of 'sizeof(expr)' to a constant 139 return sum; 140 } 141 142 typedef char MyChar; 143 typedef const MyChar MyConstChar; 144 145 int CE0 = sizeof sizeof(char); 146 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))' 147 int CE1 = sizeof +sizeof(char); 148 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))' 149 int CE2 = sizeof sizeof(const char*); 150 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))' 151 int CE3 = sizeof sizeof(const volatile char* const*); 152 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))' 153 int CE4 = sizeof sizeof(MyConstChar); 154 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))' 155 156 int Test2(MyConstChar* A) { 157 int sum = 0; 158 sum += sizeof(MyConstChar) / sizeof(char); 159 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type 160 sum += sizeof(MyConstChar) / sizeof(MyChar); 161 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type 162 sum += sizeof(A[0]) / sizeof(char); 163 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type 164 return sum; 165 } 166 167 template <int T> 168 int Foo() { int A[T]; return sizeof(T); } 169 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(K)' 170 template <typename T> 171 int Bar() { T A[5]; return sizeof(A[0]) / sizeof(T); } 172 // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type 173 int Test3() { return Foo<42>() + Bar<char>(); } 174 175 static const char* kABC = "abc"; 176 static const wchar_t* kDEF = L"def"; 177 int Test4(const char A[10]) { 178 int sum = 0; 179 sum += sizeof(kABC); 180 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)' 181 sum += sizeof(kDEF); 182 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)' 183 return sum; 184 } 185 186 int Test5() { 187 typedef int Array10[10]; 188 typedef C ArrayC[10]; 189 190 struct MyStruct { 191 Array10 arr; 192 Array10* ptr; 193 }; 194 typedef const MyStruct TMyStruct; 195 typedef const MyStruct *PMyStruct; 196 typedef TMyStruct *PMyStruct2; 197 198 static TMyStruct kGlocalMyStruct = {}; 199 static TMyStruct volatile * kGlocalMyStructPtr = &kGlocalMyStruct; 200 201 MyStruct S; 202 PMyStruct PS; 203 PMyStruct2 PS2; 204 Array10 A10; 205 C *PtrArray[10]; 206 C *PC; 207 208 char *PChar; 209 int *PInt, **PPInt; 210 MyStruct **PPMyStruct; 211 212 int sum = 0; 213 sum += sizeof(&S.arr); 214 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 215 sum += sizeof(&kGlocalMyStruct.arr); 216 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 217 sum += sizeof(&kGlocalMyStructPtr->arr); 218 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 219 sum += sizeof(S.arr + 0); 220 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 221 sum += sizeof(+ S.arr); 222 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 223 sum += sizeof((int*)S.arr); 224 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 225 226 sum += sizeof(S.ptr); 227 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 228 sum += sizeof(kGlocalMyStruct.ptr); 229 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 230 sum += sizeof(kGlocalMyStructPtr->ptr); 231 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 232 233 sum += sizeof(&kGlocalMyStruct); 234 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 235 sum += sizeof(&S); 236 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 237 sum += sizeof(MyStruct*); 238 sum += sizeof(PMyStruct); 239 sum += sizeof(PS); 240 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 241 sum += sizeof(PS2); 242 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 243 sum += sizeof(&A10); 244 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 245 sum += sizeof(PtrArray) / sizeof(PtrArray[1]); 246 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression of pointer type 247 sum += sizeof(A10) / sizeof(PtrArray[0]); 248 sum += sizeof(PC) / sizeof(PtrArray[0]); 249 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type 250 // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type 251 sum += sizeof(ArrayC) / sizeof(PtrArray[0]); 252 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator 253 254 // These pointers do not point to aggregate types, so they are not reported in this mode: 255 sum += sizeof(PChar); 256 sum += sizeof(PInt); 257 sum += sizeof(PPInt); 258 sum += sizeof(PPMyStruct); 259 260 return sum; 261 } 262 263 int Test6() { 264 int sum = 0; 265 266 struct S A = AsStruct(), B = AsStruct(); 267 struct S *P = &A, *Q = &B; 268 sum += sizeof(struct S) == P - Q; 269 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic 270 sum += 5 * sizeof(S) != P - Q; 271 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic 272 sum += sizeof(S) < P - Q; 273 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic 274 sum += 5 * sizeof(S) <= P - Q; 275 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic 276 sum += 5 * sizeof(*P) >= P - Q; 277 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic 278 sum += Q - P > 3 * sizeof(*P); 279 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic 280 sum += sizeof(S) + (P - Q); 281 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic 282 sum += 5 * sizeof(S) - (P - Q); 283 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic 284 sum += (P - Q) / sizeof(S); 285 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic 286 sum += (P - Q) / sizeof(*Q); 287 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic 288 289 return sum; 290 } 291 292 static constexpr inline int BufferSize = 1024; 293 294 template <typename T> 295 T next(const T *&Read) { 296 T value = *Read; 297 Read += sizeof(T); 298 return value; 299 } 300 301 void Test7() { 302 int Buffer[BufferSize]; 303 int *P = &Buffer[0]; 304 305 const int *P2 = P; 306 int V1 = next(P2); 307 // CHECK-MESSAGES: :[[@LINE-10]]:8: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+=' operator 308 // CHECK-MESSAGES: :[[@LINE-11]]:8: note: '+=' in pointer arithmetic internally scales with 'sizeof(const int)' == {{[0-9]+}} 309 int V2 = next(P2); 310 (void)V1; 311 (void)V2; 312 313 int *Q = P; 314 while (Q < P + sizeof(Buffer)) { 315 // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator 316 // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}} 317 *Q++ = 0; 318 } 319 } 320 321 #ifdef __SIZEOF_INT128__ 322 template <__int128_t N> 323 #else 324 template <long N> // Fallback for platforms which do not define `__int128_t` 325 #endif 326 bool Baz() { return sizeof(A) < N; } 327 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: suspicious comparison of 'sizeof(expr)' to a constant 328 bool Test8() { return Baz<-1>(); } 329 330 void some_generic_function(const void *arg, int argsize); 331 int *IntP, **IntPP; 332 C *ClassP, **ClassPP; 333 334 void GenericFunctionTest() { 335 // The `sizeof(pointer)` checks ignore situations where the pointer is 336 // produced by dereferencing a pointer-to-pointer, because this is unlikely 337 // to be an accident and can appear in legitimate code that tries to call 338 // a generic function which emulates dynamic typing within C. 339 some_generic_function(IntPP, sizeof(*IntPP)); 340 some_generic_function(ClassPP, sizeof(*ClassPP)); 341 // Using `...[0]` instead of the dereference operator is another common 342 // variant, which is also widespread in the idiomatic array-size calculation: 343 // `sizeof(array) / sizeof(array[0])`. 344 some_generic_function(IntPP, sizeof(IntPP[0])); 345 some_generic_function(ClassPP, sizeof(ClassPP[0])); 346 // FIXME: There is a third common pattern where the generic function is 347 // called with `&Variable` and `sizeof(Variable)`. Right now these are 348 // reported by the `sizeof(pointer)` checks, but this causes some false 349 // positives, so it would be good to create an exception for them. 350 // NOTE: `sizeof(IntP)` is only reported with `WarnOnSizeOfPointer=true`. 351 some_generic_function(&IntPP, sizeof(IntP)); 352 some_generic_function(&ClassPP, sizeof(ClassP)); 353 // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression of pointer type 354 } 355 356 int ValidExpressions() { 357 int A[] = {1, 2, 3, 4}; 358 static const char str[] = "hello"; 359 static const char* ptr[] { "aaa", "bbb", "ccc" }; 360 typedef C *CA10[10]; 361 C *PtrArray[10]; 362 CA10 PtrArray1; 363 364 int sum = 0; 365 if (sizeof(A) < 10) 366 sum += sizeof(A); 367 sum += sizeof(int); 368 sum += sizeof(AsStruct()); 369 sum += sizeof(M{}.AsStruct()); 370 sum += sizeof(A[sizeof(A) / sizeof(int)]); 371 sum += sizeof(&A[sizeof(A) / sizeof(int)]); 372 sum += sizeof(sizeof(0)); // Special case: sizeof size_t. 373 sum += sizeof(void*); 374 sum += sizeof(void const *); 375 sum += sizeof(void const *) / 4; 376 sum += sizeof(str); 377 sum += sizeof(str) / sizeof(char); 378 sum += sizeof(str) / sizeof(str[0]); 379 sum += sizeof(ptr) / sizeof(ptr[0]); 380 sum += sizeof(ptr) / sizeof(*(ptr)); 381 sum += sizeof(PtrArray) / sizeof(PtrArray[0]); 382 // Canonical type of PtrArray1 is same as PtrArray. 383 sum = sizeof(PtrArray) / sizeof(PtrArray1[0]); 384 // There is no warning for 'sizeof(T*)/sizeof(Q)' case. 385 sum += sizeof(PtrArray) / sizeof(A[0]); 386 return sum; 387 } 388 389 namespace gh115175 { 390 template<class T> 391 int ValidateTemplateTypeExpressions(T t) { 392 return sizeof(t.val) / sizeof(t.val[0]); 393 } 394 } // namespace gh115175 395