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 that results in an integer 42 sum += sizeof(AsInt()); 43 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer 44 sum += sizeof(AsEnum()); 45 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer 46 sum += sizeof(AsEnumClass()); 47 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer 48 sum += sizeof(M{}.AsInt()); 49 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer 50 sum += sizeof(M{}.AsEnum()); 51 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in an integer 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 pointer 'sizeof(T)/sizeof(T)' 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 that results in a pointer 76 sum += sizeof(ptr) / sizeof(ptr[0]); 77 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 78 sum += sizeof(ptr) / sizeof(char*); 79 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 80 sum += sizeof(ptr) / sizeof(void*); 81 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 82 sum += sizeof(ptr) / sizeof(const void volatile*); 83 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 84 sum += sizeof(ptr) / sizeof(char); 85 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 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 that results in a pointer 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 that results in a pointer 131 sum += sizeof(&kGlocalMyStruct.arr); 132 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 133 sum += sizeof(&kGlocalMyStructPtr->arr); 134 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 135 sum += sizeof(S.arr + 0); 136 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 137 sum += sizeof(+ S.arr); 138 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 139 sum += sizeof((int*)S.arr); 140 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 141 142 sum += sizeof(S.ptr); 143 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 144 sum += sizeof(kGlocalMyStruct.ptr); 145 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 146 sum += sizeof(kGlocalMyStructPtr->ptr); 147 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 148 149 sum += sizeof(&kGlocalMyStruct); 150 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 151 sum += sizeof(&S); 152 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 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 that results in a pointer 157 sum += sizeof(PS2); 158 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 159 sum += sizeof(&A10); 160 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 161 sum += sizeof(PtrArray) / sizeof(PtrArray[1]); 162 // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 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 that results in a pointer 166 // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of sizeof pointer 'sizeof(T)/sizeof(T)' 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 that results in a pointer 172 sum += sizeof(PInt); 173 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 174 sum += sizeof(PPInt); 175 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 176 sum += sizeof(PPMyStruct); 177 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 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(IntPP, sizeof(*IntPP)); 192 some_generic_function(ClassPP, 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(IntPP, sizeof(IntPP[0])); 197 some_generic_function(ClassPP, 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(&IntPP, sizeof(IntP)); 203 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 204 some_generic_function(&ClassPP, sizeof(ClassP)); 205 // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression that results in a pointer 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 that results in a pointer 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