| 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 | struct A { |
| 168 | int array[10]; |
| 169 | }; |
| 170 | |
| 171 | struct B { |
| 172 | struct A a; |
| 173 | }; |
| 174 | |
| 175 | void loop_access_elements(int num, struct B b) { |
| 176 | struct A arr[10]; |
| 177 | char buf[20]; |
| 178 | |
| 179 | // CHECK-MESSAGES: :[[@LINE+1]]:22: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression] |
| 180 | for(int i = 0; i < sizeof(arr); i++) { |
| 181 | struct A a = arr[i]; |
| 182 | } |
| 183 | |
| 184 | // Loop warning should not trigger here, even though this code is incorrect |
| 185 | // CHECK-MESSAGES: :[[@LINE+2]]:22: warning: suspicious usage of 'sizeof(K)'; did you mean 'K'? [bugprone-sizeof-expression] |
| 186 | // CHECK-MESSAGES: :[[@LINE+1]]:32: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator [bugprone-sizeof-expression] |
| 187 | for(int i = 0; i < sizeof(10)/sizeof(A); i++) { |
| 188 | struct A a = arr[i]; |
| 189 | } |
| 190 | |
| 191 | // Should not warn here |
| 192 | for(int i = 0; i < sizeof(arr)/sizeof(A); i++) {} |
| 193 | |
| 194 | // Should not warn here |
| 195 | for (int i = 0; i < 10; i++) { |
| 196 | if (sizeof(arr) != 0) { |
| 197 | |
| 198 | } |
| 199 | } |
| 200 | |
| 201 | for (int i = 0; i < 10; i++) { |
| 202 | // CHECK-MESSAGES: :[[@LINE+1]]:25: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression] |
| 203 | for (int j = 0; j < sizeof(arr); j++) { |
| 204 | } |
| 205 | } |
| 206 | |
| 207 | // CHECK-MESSAGES: :[[@LINE+1]]:22: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression] |
| 208 | for(int j = 0; j < sizeof(b.a.array); j++) {} |
| 209 | |
| 210 | // Should not warn here |
| 211 | for(int i = 0; i < sizeof(buf); i++) {} |
| 212 | |
| 213 | // Should not warn here |
| 214 | for(int i = 0; i < (sizeof(arr) << 3); i++) {} |
| 215 | |
| 216 | int i = 0; |
| 217 | // CHECK-MESSAGES: :[[@LINE+1]]:14: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression] |
| 218 | while(i <= sizeof(arr)) {i++;} |
| 219 | |
| 220 | i = 0; |
| 221 | do { |
| 222 | i++; |
| 223 | // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression] |
| 224 | } while(i <= sizeof(arr)); |
| 225 | |
| 226 | // CHECK-MESSAGES: :[[@LINE+1]]:29: warning: suspicious usage of 'sizeof' in the loop [bugprone-sizeof-expression] |
| 227 | for(int i = 0, j = 0; i < sizeof(arr) && j < sizeof(buf); i++, j++) {} |
| 228 | } |
| 229 | |
| 230 | template <int T> |
| 231 | int Foo() { int A[T]; return sizeof(T); } |
| 232 | // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(K)' |
| 233 | template <typename T> |
| 234 | int Bar() { T A[5]; return sizeof(A[0]) / sizeof(T); } |
| 235 | // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type |
| 236 | int Test3() { return Foo<42>() + Bar<char>(); } |
| 237 | |
| 238 | static const char* kABC = "abc" ; |
| 239 | static const wchar_t* kDEF = L"def" ; |
| 240 | int Test4(const char A[10]) { |
| 241 | int sum = 0; |
| 242 | sum += sizeof(kABC); |
| 243 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)' |
| 244 | sum += sizeof(kDEF); |
| 245 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)' |
| 246 | return sum; |
| 247 | } |
| 248 | |
| 249 | int Test5() { |
| 250 | typedef int Array10[10]; |
| 251 | typedef C ArrayC[10]; |
| 252 | |
| 253 | struct MyStruct { |
| 254 | Array10 arr; |
| 255 | Array10* ptr; |
| 256 | }; |
| 257 | typedef const MyStruct TMyStruct; |
| 258 | typedef const MyStruct *PMyStruct; |
| 259 | typedef TMyStruct *PMyStruct2; |
| 260 | |
| 261 | static TMyStruct kGlocalMyStruct = {}; |
| 262 | static TMyStruct volatile * kGlocalMyStructPtr = &kGlocalMyStruct; |
| 263 | |
| 264 | MyStruct S; |
| 265 | PMyStruct PS; |
| 266 | PMyStruct2 PS2; |
| 267 | Array10 A10; |
| 268 | C *PtrArray[10]; |
| 269 | C *PC; |
| 270 | |
| 271 | char *PChar; |
| 272 | int *PInt, **PPInt; |
| 273 | MyStruct **PPMyStruct; |
| 274 | |
| 275 | int sum = 0; |
| 276 | sum += sizeof(&S.arr); |
| 277 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 278 | sum += sizeof(&kGlocalMyStruct.arr); |
| 279 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 280 | sum += sizeof(&kGlocalMyStructPtr->arr); |
| 281 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 282 | sum += sizeof(S.arr + 0); |
| 283 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 284 | sum += sizeof(+ S.arr); |
| 285 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 286 | sum += sizeof((int*)S.arr); |
| 287 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 288 | |
| 289 | sum += sizeof(S.ptr); |
| 290 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 291 | sum += sizeof(kGlocalMyStruct.ptr); |
| 292 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 293 | sum += sizeof(kGlocalMyStructPtr->ptr); |
| 294 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 295 | |
| 296 | sum += sizeof(&kGlocalMyStruct); |
| 297 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 298 | sum += sizeof(&S); |
| 299 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 300 | sum += sizeof(MyStruct*); |
| 301 | sum += sizeof(PMyStruct); |
| 302 | sum += sizeof(PS); |
| 303 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 304 | sum += sizeof(PS2); |
| 305 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 306 | sum += sizeof(&A10); |
| 307 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 308 | sum += sizeof(PtrArray) / sizeof(PtrArray[1]); |
| 309 | // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 310 | sum += sizeof(A10) / sizeof(PtrArray[0]); |
| 311 | sum += sizeof(PC) / sizeof(PtrArray[0]); |
| 312 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 313 | // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type |
| 314 | sum += sizeof(ArrayC) / sizeof(PtrArray[0]); |
| 315 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator |
| 316 | |
| 317 | // These pointers do not point to aggregate types, so they are not reported in this mode: |
| 318 | sum += sizeof(PChar); |
| 319 | sum += sizeof(PInt); |
| 320 | sum += sizeof(PPInt); |
| 321 | sum += sizeof(PPMyStruct); |
| 322 | |
| 323 | return sum; |
| 324 | } |
| 325 | |
| 326 | int Test6() { |
| 327 | int sum = 0; |
| 328 | |
| 329 | struct S A = AsStruct(), B = AsStruct(); |
| 330 | struct S *P = &A, *Q = &B; |
| 331 | sum += sizeof(struct S) == P - Q; |
| 332 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic |
| 333 | sum += 5 * sizeof(S) != P - Q; |
| 334 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic |
| 335 | sum += sizeof(S) < P - Q; |
| 336 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic |
| 337 | sum += 5 * sizeof(S) <= P - Q; |
| 338 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic |
| 339 | sum += 5 * sizeof(*P) >= P - Q; |
| 340 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic |
| 341 | sum += Q - P > 3 * sizeof(*P); |
| 342 | // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic |
| 343 | sum += sizeof(S) + (P - Q); |
| 344 | // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic |
| 345 | sum += 5 * sizeof(S) - (P - Q); |
| 346 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic |
| 347 | sum += (P - Q) / sizeof(S); |
| 348 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic |
| 349 | sum += (P - Q) / sizeof(*Q); |
| 350 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic |
| 351 | |
| 352 | return sum; |
| 353 | } |
| 354 | |
| 355 | static constexpr inline int BufferSize = 1024; |
| 356 | |
| 357 | template <typename T> |
| 358 | T next(const T *&Read) { |
| 359 | T value = *Read; |
| 360 | Read += sizeof(T); |
| 361 | return value; |
| 362 | } |
| 363 | |
| 364 | void Test7() { |
| 365 | int Buffer[BufferSize]; |
| 366 | int *P = &Buffer[0]; |
| 367 | |
| 368 | const int *P2 = P; |
| 369 | int V1 = next(Read&: P2); |
| 370 | // CHECK-MESSAGES: :[[@LINE-10]]:8: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+=' operator |
| 371 | // CHECK-MESSAGES: :[[@LINE-11]]:8: note: '+=' in pointer arithmetic internally scales with 'sizeof(const int)' == {{[0-9]+}} |
| 372 | int V2 = next(Read&: P2); |
| 373 | (void)V1; |
| 374 | (void)V2; |
| 375 | |
| 376 | int *Q = P; |
| 377 | while (Q < P + sizeof(Buffer)) { |
| 378 | // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator |
| 379 | // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}} |
| 380 | *Q++ = 0; |
| 381 | } |
| 382 | } |
| 383 | |
| 384 | #ifdef __SIZEOF_INT128__ |
| 385 | template <__int128_t N> |
| 386 | #else |
| 387 | template <long N> // Fallback for platforms which do not define `__int128_t` |
| 388 | #endif |
| 389 | bool Baz() { return sizeof(A) < N; } |
| 390 | // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: suspicious comparison of 'sizeof(expr)' to a constant |
| 391 | bool Test8() { return Baz<-1>(); } |
| 392 | |
| 393 | void some_generic_function(const void *arg, int argsize); |
| 394 | int *IntP, **IntPP; |
| 395 | C *ClassP, **ClassPP; |
| 396 | |
| 397 | void GenericFunctionTest() { |
| 398 | // The `sizeof(pointer)` checks ignore situations where the pointer is |
| 399 | // produced by dereferencing a pointer-to-pointer, because this is unlikely |
| 400 | // to be an accident and can appear in legitimate code that tries to call |
| 401 | // a generic function which emulates dynamic typing within C. |
| 402 | some_generic_function(arg: IntPP, argsize: sizeof(*IntPP)); |
| 403 | some_generic_function(arg: ClassPP, argsize: sizeof(*ClassPP)); |
| 404 | // Using `...[0]` instead of the dereference operator is another common |
| 405 | // variant, which is also widespread in the idiomatic array-size calculation: |
| 406 | // `sizeof(array) / sizeof(array[0])`. |
| 407 | some_generic_function(arg: IntPP, argsize: sizeof(IntPP[0])); |
| 408 | some_generic_function(arg: ClassPP, argsize: sizeof(ClassPP[0])); |
| 409 | // FIXME: There is a third common pattern where the generic function is |
| 410 | // called with `&Variable` and `sizeof(Variable)`. Right now these are |
| 411 | // reported by the `sizeof(pointer)` checks, but this causes some false |
| 412 | // positives, so it would be good to create an exception for them. |
| 413 | // NOTE: `sizeof(IntP)` is only reported with `WarnOnSizeOfPointer=true`. |
| 414 | some_generic_function(arg: &IntPP, argsize: sizeof(IntP)); |
| 415 | some_generic_function(arg: &ClassPP, argsize: sizeof(ClassP)); |
| 416 | // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression of pointer type |
| 417 | } |
| 418 | |
| 419 | int ValidExpressions() { |
| 420 | int A[] = {1, 2, 3, 4}; |
| 421 | static const char str[] = "hello" ; |
| 422 | static const char* ptr[] { "aaa" , "bbb" , "ccc" }; |
| 423 | typedef C *CA10[10]; |
| 424 | C *PtrArray[10]; |
| 425 | CA10 PtrArray1; |
| 426 | |
| 427 | int sum = 0; |
| 428 | if (sizeof(A) < 10) |
| 429 | sum += sizeof(A); |
| 430 | sum += sizeof(int); |
| 431 | sum += sizeof(AsStruct()); |
| 432 | sum += sizeof(M{}.AsStruct()); |
| 433 | sum += sizeof(A[sizeof(A) / sizeof(int)]); |
| 434 | sum += sizeof(&A[sizeof(A) / sizeof(int)]); |
| 435 | sum += sizeof(sizeof(0)); // Special case: sizeof size_t. |
| 436 | sum += sizeof(void*); |
| 437 | sum += sizeof(void const *); |
| 438 | sum += sizeof(void const *) / 4; |
| 439 | sum += sizeof(str); |
| 440 | sum += sizeof(str) / sizeof(char); |
| 441 | sum += sizeof(str) / sizeof(str[0]); |
| 442 | sum += sizeof(ptr) / sizeof(ptr[0]); |
| 443 | sum += sizeof(ptr) / sizeof(*(ptr)); |
| 444 | sum += sizeof(PtrArray) / sizeof(PtrArray[0]); |
| 445 | // Canonical type of PtrArray1 is same as PtrArray. |
| 446 | sum = sizeof(PtrArray) / sizeof(PtrArray1[0]); |
| 447 | // There is no warning for 'sizeof(T*)/sizeof(Q)' case. |
| 448 | sum += sizeof(PtrArray) / sizeof(A[0]); |
| 449 | return sum; |
| 450 | } |
| 451 | |
| 452 | namespace gh115175 { |
| 453 | template<class T> |
| 454 | int ValidateTemplateTypeExpressions(T t) { |
| 455 | return sizeof(t.val) / sizeof(t.val[0]); |
| 456 | } |
| 457 | } // namespace gh115175 |
| 458 | |