// RUN: %check_clang_tidy %s bugprone-sizeof-expression %t -- -config="{CheckOptions: {bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression: true, bugprone-sizeof-expression.WarnOnSizeOfPointer: true}}" -- class C { int size() { return sizeof(this); } // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(this)' }; #define LEN 8 int X; extern int A[10]; extern short B[10]; #pragma pack(1) struct S { char a, b, c; }; enum E { E_VALUE = 0 }; enum class EC { VALUE = 0 }; bool AsBool() { return false; } int AsInt() { return 0; } E AsEnum() { return E_VALUE; } EC AsEnumClass() { return EC::VALUE; } S AsStruct() { return {}; } struct M { int AsInt() { return 0; } E AsEnum() { return E_VALUE; } S AsStruct() { return {}; } }; int Test1(const char* ptr) { int sum = 0; sum += sizeof(LEN); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)' sum += sizeof(LEN + 1); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)' sum += sizeof(sum, LEN); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(..., ...)' sum += sizeof(AsBool()); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type sum += sizeof(AsInt()); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type sum += sizeof(AsEnum()); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type sum += sizeof(AsEnumClass()); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type sum += sizeof(M{}.AsInt()); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type sum += sizeof(M{}.AsEnum()); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type sum += sizeof(sizeof(X)); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' sum += sizeof(LEN + sizeof(X)); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' sum += sizeof(LEN + LEN + sizeof(X)); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' sum += sizeof(LEN + (LEN + sizeof(X))); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' sum += sizeof(LEN + -sizeof(X)); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' sum += sizeof(LEN + - + -sizeof(X)); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))' sum += sizeof(char) / sizeof(char); // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type sum += sizeof(A) / sizeof(S); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator sum += sizeof(char) / sizeof(int); // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator sum += sizeof(char) / sizeof(A); // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator sum += sizeof(B[0]) / sizeof(A); // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator sum += sizeof(ptr) / sizeof(char); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(ptr) / sizeof(ptr[0]); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(ptr) / sizeof(char*); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(ptr) / sizeof(void*); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(ptr) / sizeof(const void volatile*); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(ptr) / sizeof(char); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(int) * sizeof(char); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication sum += sizeof(ptr) * sizeof(ptr[0]); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type // CHECK-MESSAGES: :[[@LINE-2]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication sum += sizeof(int) * (2 * sizeof(char)); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication sum += (2 * sizeof(char)) * sizeof(int); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious 'sizeof' by 'sizeof' multiplication if (sizeof(A) < 0x100000) sum += 42; // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: suspicious comparison of 'sizeof(expr)' to a constant if (sizeof(A) <= 0xFFFFFFFEU) sum += 42; // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: suspicious comparison of 'sizeof(expr)' to a constant return sum; } int Test5() { typedef int Array10[10]; typedef C ArrayC[10]; struct MyStruct { Array10 arr; Array10* ptr; }; typedef const MyStruct TMyStruct; typedef const MyStruct *PMyStruct; typedef TMyStruct *PMyStruct2; static TMyStruct kGlocalMyStruct = {}; static TMyStruct volatile * kGlocalMyStructPtr = &kGlocalMyStruct; MyStruct S; PMyStruct PS; PMyStruct2 PS2; Array10 A10; C *PtrArray[10]; C *PC; char *PChar; int *PInt, **PPInt; MyStruct **PPMyStruct; int sum = 0; sum += sizeof(&S.arr); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(&kGlocalMyStruct.arr); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(&kGlocalMyStructPtr->arr); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(S.arr + 0); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(+ S.arr); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof((int*)S.arr); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(S.ptr); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(kGlocalMyStruct.ptr); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(kGlocalMyStructPtr->ptr); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(&kGlocalMyStruct); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(&S); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(MyStruct*); sum += sizeof(PMyStruct); sum += sizeof(PS); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(PS2); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(&A10); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(PtrArray) / sizeof(PtrArray[1]); // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(A10) / sizeof(PtrArray[0]); sum += sizeof(PC) / sizeof(PtrArray[0]); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type sum += sizeof(ArrayC) / sizeof(PtrArray[0]); // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator sum += sizeof(PChar); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(PInt); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(PPInt); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(PPMyStruct); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type return sum; } void some_generic_function(const void *arg, int argsize); int *IntP, **IntPP; C *ClassP, **ClassPP; void GenericFunctionTest() { // The `sizeof(pointer)` checks ignore situations where the pointer is // produced by dereferencing a pointer-to-pointer, because this is unlikely // to be an accident and can appear in legitimate code that tries to call // a generic function which emulates dynamic typing within C. some_generic_function(IntPP, sizeof(*IntPP)); some_generic_function(ClassPP, sizeof(*ClassPP)); // Using `...[0]` instead of the dereference operator is another common // variant, which is also widespread in the idiomatic array-size calculation: // `sizeof(array) / sizeof(array[0])`. some_generic_function(IntPP, sizeof(IntPP[0])); some_generic_function(ClassPP, sizeof(ClassPP[0])); // FIXME: There is a third common pattern where the generic function is // called with `&Variable` and `sizeof(Variable)`. Right now these are // reported by the `sizeof(pointer)` checks, but this causes some false // positives, so it would be good to create an exception for them. some_generic_function(&IntPP, sizeof(IntP)); // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: suspicious usage of 'sizeof()' on an expression of pointer type some_generic_function(&ClassPP, sizeof(ClassP)); // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression of pointer type } int ValidExpressions() { int A[] = {1, 2, 3, 4}; static const char str[] = "hello"; static const char* ptr[] { "aaa", "bbb", "ccc" }; typedef C *CA10[10]; C *PtrArray[10]; CA10 PtrArray1; int sum = 0; if (sizeof(A) < 10) sum += sizeof(A); sum += sizeof(int); sum += sizeof(AsStruct()); sum += sizeof(M{}.AsStruct()); sum += sizeof(A[sizeof(A) / sizeof(int)]); // Here the outer sizeof is reported, but the inner ones are accepted: sum += sizeof(&A[sizeof(A) / sizeof(int)]); // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type sum += sizeof(sizeof(0)); // Special case: sizeof size_t. sum += sizeof(void*); sum += sizeof(void const *); sum += sizeof(void const *) / 4; sum += sizeof(str); sum += sizeof(str) / sizeof(char); sum += sizeof(str) / sizeof(str[0]); sum += sizeof(ptr) / sizeof(ptr[0]); sum += sizeof(ptr) / sizeof(*(ptr)); sum += sizeof(PtrArray) / sizeof(PtrArray[0]); // Canonical type of PtrArray1 is same as PtrArray. sum = sizeof(PtrArray) / sizeof(PtrArray1[0]); // There is no warning for 'sizeof(T*)/sizeof(Q)' case. sum += sizeof(PtrArray) / sizeof(A[0]); return sum; }