xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/bugprone/sizeof-expression.cpp (revision e855feac41fd89aebf540a155d21f12a3e82f05b)
1e8a3ddafSNathan James // RUN: %check_clang_tidy %s bugprone-sizeof-expression %t -- -config="{CheckOptions: {bugprone-sizeof-expression.WarnOnSizeOfIntegerExpression: true}}" --
289a1d03eSRichard 
389a1d03eSRichard class C {
489a1d03eSRichard   int size() { return sizeof(this); }
589a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(this)'
689a1d03eSRichard };
789a1d03eSRichard 
889a1d03eSRichard #define LEN 8
989a1d03eSRichard 
1089a1d03eSRichard int X;
1189a1d03eSRichard extern int A[10];
1289a1d03eSRichard extern short B[10];
1389a1d03eSRichard 
1489a1d03eSRichard #pragma pack(1)
1589a1d03eSRichard struct  S { char a, b, c; };
1689a1d03eSRichard 
1789a1d03eSRichard enum E { E_VALUE = 0 };
1889a1d03eSRichard enum class EC { VALUE = 0 };
1989a1d03eSRichard 
2089a1d03eSRichard bool AsBool() { return false; }
2189a1d03eSRichard int AsInt() { return 0; }
2289a1d03eSRichard E AsEnum() { return E_VALUE; }
2389a1d03eSRichard EC AsEnumClass() { return EC::VALUE; }
2489a1d03eSRichard S AsStruct() { return {}; }
2589a1d03eSRichard 
2689a1d03eSRichard struct M {
2789a1d03eSRichard   int AsInt() { return 0; }
2889a1d03eSRichard   E AsEnum() { return E_VALUE; }
2989a1d03eSRichard   S AsStruct() { return {}; }
3089a1d03eSRichard };
3189a1d03eSRichard 
3289a1d03eSRichard int ReturnOverload(int) { return {}; }
3389a1d03eSRichard S ReturnOverload(S) { return {}; }
3489a1d03eSRichard 
3589a1d03eSRichard template <class T>
3689a1d03eSRichard T ReturnTemplate(T) { return {}; }
3789a1d03eSRichard 
3889a1d03eSRichard template <class T>
3989a1d03eSRichard bool TestTrait1() {
4089a1d03eSRichard   return sizeof(ReturnOverload(T{})) == sizeof(A);
4189a1d03eSRichard }
4289a1d03eSRichard 
4389a1d03eSRichard template <class T>
4489a1d03eSRichard bool TestTrait2() {
4589a1d03eSRichard   return sizeof(ReturnTemplate(T{})) == sizeof(A);
4689a1d03eSRichard }
4789a1d03eSRichard 
4889a1d03eSRichard template <class T>
4989a1d03eSRichard bool TestTrait3() {
5089a1d03eSRichard   return sizeof(ReturnOverload(0)) == sizeof(T{});
51fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
5289a1d03eSRichard }
5389a1d03eSRichard 
5489a1d03eSRichard template <class T>
5589a1d03eSRichard bool TestTrait4() {
5689a1d03eSRichard   return sizeof(ReturnTemplate(0)) == sizeof(T{});
57fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
5889a1d03eSRichard }
5989a1d03eSRichard 
6089a1d03eSRichard bool TestTemplates() {
6189a1d03eSRichard   bool b = true;
6289a1d03eSRichard   b &= TestTrait1<int>();
6389a1d03eSRichard   b &= TestTrait1<S>();
6489a1d03eSRichard   b &= TestTrait2<int>();
6589a1d03eSRichard   b &= TestTrait2<S>();
6689a1d03eSRichard   b &= TestTrait3<int>();
6789a1d03eSRichard   b &= TestTrait3<S>();
6889a1d03eSRichard   b &= TestTrait4<int>();
6989a1d03eSRichard   b &= TestTrait4<S>();
7089a1d03eSRichard   return b;
7189a1d03eSRichard }
7289a1d03eSRichard 
7389a1d03eSRichard int Test1(const char* ptr) {
7489a1d03eSRichard   int sum = 0;
7589a1d03eSRichard   sum += sizeof(LEN);
7689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)'
7789a1d03eSRichard   sum += sizeof(LEN + 1);
7889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(K)'
7989a1d03eSRichard   sum += sizeof(sum, LEN);
800e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(..., ...)'
8189a1d03eSRichard   sum += sizeof(AsBool());
82fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
8389a1d03eSRichard   sum += sizeof(AsInt());
84fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
8589a1d03eSRichard   sum += sizeof(AsEnum());
86fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
8789a1d03eSRichard   sum += sizeof(AsEnumClass());
88fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
8989a1d03eSRichard   sum += sizeof(M{}.AsInt());
90fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
9189a1d03eSRichard   sum += sizeof(M{}.AsEnum());
92fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of integer type
9389a1d03eSRichard   sum += sizeof(sizeof(X));
9489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
9589a1d03eSRichard   sum += sizeof(LEN + sizeof(X));
9689a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
9789a1d03eSRichard   sum += sizeof(LEN + LEN + sizeof(X));
9889a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
9989a1d03eSRichard   sum += sizeof(LEN + (LEN + sizeof(X)));
10089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
10189a1d03eSRichard   sum += sizeof(LEN + -sizeof(X));
10289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
10389a1d03eSRichard   sum += sizeof(LEN + - + -sizeof(X));
10489a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(sizeof(...))'
10589a1d03eSRichard   sum += sizeof(char) / sizeof(char);
106fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
10789a1d03eSRichard   sum += sizeof(A) / sizeof(S);
1080e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
10989a1d03eSRichard   sum += sizeof(char) / sizeof(int);
1100e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
11189a1d03eSRichard   sum += sizeof(char) / sizeof(A);
1120e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
11389a1d03eSRichard   sum += sizeof(B[0]) / sizeof(A);
1140e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
11589a1d03eSRichard   sum += sizeof(ptr) / sizeof(char);
116fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer is divided by size of pointed type
11789a1d03eSRichard   sum += sizeof(ptr) / sizeof(ptr[0]);
118fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer is divided by size of pointed type
11989a1d03eSRichard   sum += sizeof(ptr) / sizeof(char*);
120fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have pointer types
12189a1d03eSRichard   sum += sizeof(ptr) / sizeof(void*);
122fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have pointer types
12389a1d03eSRichard   sum += sizeof(ptr) / sizeof(const void volatile*);
124fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have pointer types
12589a1d03eSRichard   sum += sizeof(ptr) / sizeof(char);
126fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; size of pointer is divided by size of pointed type
12789a1d03eSRichard   sum += sizeof(int) * sizeof(char);
1280e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication
12989a1d03eSRichard   sum += sizeof(ptr) * sizeof(ptr[0]);
1300e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication
13189a1d03eSRichard   sum += sizeof(int) * (2 * sizeof(char));
1320e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious 'sizeof' by 'sizeof' multiplication
13389a1d03eSRichard   sum += (2 * sizeof(char)) * sizeof(int);
1340e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious 'sizeof' by 'sizeof' multiplication
13589a1d03eSRichard   if (sizeof(A) < 0x100000) sum += 42;
1360e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: suspicious comparison of 'sizeof(expr)' to a constant
13789a1d03eSRichard   if (sizeof(A) <= 0xFFFFFFFEU) sum += 42;
1380e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: suspicious comparison of 'sizeof(expr)' to a constant
13989a1d03eSRichard   return sum;
14089a1d03eSRichard }
14189a1d03eSRichard 
14289a1d03eSRichard typedef char MyChar;
14389a1d03eSRichard typedef const MyChar MyConstChar;
14489a1d03eSRichard 
14589a1d03eSRichard int CE0 = sizeof sizeof(char);
14689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
14789a1d03eSRichard int CE1 = sizeof +sizeof(char);
14889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
14989a1d03eSRichard int CE2 = sizeof sizeof(const char*);
15089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
15189a1d03eSRichard int CE3 = sizeof sizeof(const volatile char* const*);
15289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
15389a1d03eSRichard int CE4 = sizeof sizeof(MyConstChar);
15489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: suspicious usage of 'sizeof(sizeof(...))'
15589a1d03eSRichard 
15689a1d03eSRichard int Test2(MyConstChar* A) {
15789a1d03eSRichard   int sum = 0;
15889a1d03eSRichard   sum += sizeof(MyConstChar) / sizeof(char);
159fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
16089a1d03eSRichard   sum += sizeof(MyConstChar) / sizeof(MyChar);
161fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
16289a1d03eSRichard   sum += sizeof(A[0]) / sizeof(char);
163fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
16489a1d03eSRichard   return sum;
16589a1d03eSRichard }
16689a1d03eSRichard 
16789a1d03eSRichard template <int T>
16889a1d03eSRichard int Foo() { int A[T]; return sizeof(T); }
16989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: suspicious usage of 'sizeof(K)'
17089a1d03eSRichard template <typename T>
17189a1d03eSRichard int Bar() { T A[5]; return sizeof(A[0]) / sizeof(T); }
172fdcfb277SDonát Nagy // CHECK-MESSAGES: :[[@LINE-1]]:41: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
17389a1d03eSRichard int Test3() { return Foo<42>() + Bar<char>(); }
17489a1d03eSRichard 
17589a1d03eSRichard static const char* kABC = "abc";
17689a1d03eSRichard static const wchar_t* kDEF = L"def";
17789a1d03eSRichard int Test4(const char A[10]) {
17889a1d03eSRichard   int sum = 0;
17989a1d03eSRichard   sum += sizeof(kABC);
18089a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)'
18189a1d03eSRichard   sum += sizeof(kDEF);
18289a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(char*)'
18389a1d03eSRichard   return sum;
18489a1d03eSRichard }
18589a1d03eSRichard 
18689a1d03eSRichard int Test5() {
18789a1d03eSRichard   typedef int Array10[10];
18889a1d03eSRichard   typedef C ArrayC[10];
18989a1d03eSRichard 
19089a1d03eSRichard   struct MyStruct {
19189a1d03eSRichard     Array10 arr;
19289a1d03eSRichard     Array10* ptr;
19389a1d03eSRichard   };
19489a1d03eSRichard   typedef const MyStruct TMyStruct;
19589a1d03eSRichard   typedef const MyStruct *PMyStruct;
19689a1d03eSRichard   typedef TMyStruct *PMyStruct2;
19789a1d03eSRichard 
19889a1d03eSRichard   static TMyStruct kGlocalMyStruct = {};
19989a1d03eSRichard   static TMyStruct volatile * kGlocalMyStructPtr = &kGlocalMyStruct;
20089a1d03eSRichard 
20189a1d03eSRichard   MyStruct S;
20289a1d03eSRichard   PMyStruct PS;
20389a1d03eSRichard   PMyStruct2 PS2;
20489a1d03eSRichard   Array10 A10;
20589a1d03eSRichard   C *PtrArray[10];
20689a1d03eSRichard   C *PC;
20789a1d03eSRichard 
208546c816aSDonát Nagy   char *PChar;
209546c816aSDonát Nagy   int *PInt, **PPInt;
210546c816aSDonát Nagy   MyStruct **PPMyStruct;
211546c816aSDonát Nagy 
21289a1d03eSRichard   int sum = 0;
21389a1d03eSRichard   sum += sizeof(&S.arr);
214fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
21589a1d03eSRichard   sum += sizeof(&kGlocalMyStruct.arr);
216fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
21789a1d03eSRichard   sum += sizeof(&kGlocalMyStructPtr->arr);
218fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
21989a1d03eSRichard   sum += sizeof(S.arr + 0);
220fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
22189a1d03eSRichard   sum += sizeof(+ S.arr);
222fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
22389a1d03eSRichard   sum += sizeof((int*)S.arr);
224fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
22589a1d03eSRichard 
22689a1d03eSRichard   sum += sizeof(S.ptr);
227fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
22889a1d03eSRichard   sum += sizeof(kGlocalMyStruct.ptr);
229fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
23089a1d03eSRichard   sum += sizeof(kGlocalMyStructPtr->ptr);
231fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
23289a1d03eSRichard 
23389a1d03eSRichard   sum += sizeof(&kGlocalMyStruct);
234fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
23589a1d03eSRichard   sum += sizeof(&S);
236fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
23789a1d03eSRichard   sum += sizeof(MyStruct*);
23889a1d03eSRichard   sum += sizeof(PMyStruct);
23989a1d03eSRichard   sum += sizeof(PS);
240fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
24189a1d03eSRichard   sum += sizeof(PS2);
242fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
24389a1d03eSRichard   sum += sizeof(&A10);
244fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
24589a1d03eSRichard   sum += sizeof(PtrArray) / sizeof(PtrArray[1]);
246fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: suspicious usage of 'sizeof()' on an expression of pointer type
24789a1d03eSRichard   sum += sizeof(A10) / sizeof(PtrArray[0]);
24889a1d03eSRichard   sum += sizeof(PC) / sizeof(PtrArray[0]);
249fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof()' on an expression of pointer type
250fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-2]]:21: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; both expressions have the same type
25189a1d03eSRichard   sum += sizeof(ArrayC) / sizeof(PtrArray[0]);
2520e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: suspicious usage of 'sizeof(...)/sizeof(...)'; numerator is not a multiple of denominator
253546c816aSDonát Nagy 
254546c816aSDonát Nagy   // These pointers do not point to aggregate types, so they are not reported in this mode:
255546c816aSDonát Nagy   sum += sizeof(PChar);
256546c816aSDonát Nagy   sum += sizeof(PInt);
257546c816aSDonát Nagy   sum += sizeof(PPInt);
258546c816aSDonát Nagy   sum += sizeof(PPMyStruct);
25989a1d03eSRichard 
26089a1d03eSRichard   return sum;
26189a1d03eSRichard }
26289a1d03eSRichard 
26389a1d03eSRichard int Test6() {
26489a1d03eSRichard   int sum = 0;
26589a1d03eSRichard 
26689a1d03eSRichard   struct S A = AsStruct(), B = AsStruct();
26789a1d03eSRichard   struct S *P = &A, *Q = &B;
26889a1d03eSRichard   sum += sizeof(struct S) == P - Q;
26989a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
27089a1d03eSRichard   sum += 5 * sizeof(S) != P - Q;
2710e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
27289a1d03eSRichard   sum += sizeof(S) < P - Q;
27389a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
27489a1d03eSRichard   sum += 5 * sizeof(S) <= P - Q;
2750e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
27689a1d03eSRichard   sum += 5 * sizeof(*P) >= P - Q;
2770e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
27889a1d03eSRichard   sum += Q - P > 3 * sizeof(*P);
2790e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
28089a1d03eSRichard   sum += sizeof(S) + (P - Q);
28189a1d03eSRichard   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
28289a1d03eSRichard   sum += 5 * sizeof(S) - (P - Q);
2830e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
28489a1d03eSRichard   sum += (P - Q) / sizeof(S);
2850e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
28689a1d03eSRichard   sum += (P - Q) / sizeof(*Q);
2870e55fef0SNathan James   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic
28889a1d03eSRichard 
28989a1d03eSRichard   return sum;
29089a1d03eSRichard }
29189a1d03eSRichard 
292267ad430SZoltán Porkoláb static constexpr inline int BufferSize = 1024;
293267ad430SZoltán Porkoláb 
294267ad430SZoltán Porkoláb template <typename T>
295267ad430SZoltán Porkoláb T next(const T *&Read) {
296267ad430SZoltán Porkoláb   T value = *Read;
297267ad430SZoltán Porkoláb   Read += sizeof(T);
298267ad430SZoltán Porkoláb   return value;
299267ad430SZoltán Porkoláb }
300267ad430SZoltán Porkoláb 
301267ad430SZoltán Porkoláb void Test7() {
302267ad430SZoltán Porkoláb   int Buffer[BufferSize];
303267ad430SZoltán Porkoláb   int *P = &Buffer[0];
304267ad430SZoltán Porkoláb 
305267ad430SZoltán Porkoláb   const int *P2 = P;
306267ad430SZoltán Porkoláb   int V1 = next(P2);
307267ad430SZoltán Porkoláb   // CHECK-MESSAGES: :[[@LINE-10]]:8: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+=' operator
308267ad430SZoltán Porkoláb   // CHECK-MESSAGES: :[[@LINE-11]]:8: note: '+=' in pointer arithmetic internally scales with 'sizeof(const int)' == {{[0-9]+}}
309267ad430SZoltán Porkoláb   int V2 = next(P2);
310267ad430SZoltán Porkoláb   (void)V1;
311267ad430SZoltán Porkoláb   (void)V2;
312267ad430SZoltán Porkoláb 
313267ad430SZoltán Porkoláb   int *Q = P;
314267ad430SZoltán Porkoláb   while (Q < P + sizeof(Buffer)) {
315267ad430SZoltán Porkoláb     // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: suspicious usage of 'sizeof(...)' in pointer arithmetic; this scaled value will be scaled again by the '+' operator
316267ad430SZoltán Porkoláb     // CHECK-MESSAGES: :[[@LINE-2]]:16: note: '+' in pointer arithmetic internally scales with 'sizeof(int)' == {{[0-9]+}}
317267ad430SZoltán Porkoláb     *Q++ = 0;
318267ad430SZoltán Porkoláb   }
319267ad430SZoltán Porkoláb }
320267ad430SZoltán Porkoláb 
32189a1d03eSRichard #ifdef __SIZEOF_INT128__
32289a1d03eSRichard template <__int128_t N>
32389a1d03eSRichard #else
32489a1d03eSRichard template <long N> // Fallback for platforms which do not define `__int128_t`
32589a1d03eSRichard #endif
32689a1d03eSRichard bool Baz() { return sizeof(A) < N; }
3270e55fef0SNathan James // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: suspicious comparison of 'sizeof(expr)' to a constant
328267ad430SZoltán Porkoláb bool Test8() { return Baz<-1>(); }
32989a1d03eSRichard 
330546c816aSDonát Nagy void some_generic_function(const void *arg, int argsize);
331546c816aSDonát Nagy int *IntP, **IntPP;
332546c816aSDonát Nagy C *ClassP, **ClassPP;
333546c816aSDonát Nagy 
334546c816aSDonát Nagy void GenericFunctionTest() {
335546c816aSDonát Nagy   // The `sizeof(pointer)` checks ignore situations where the pointer is
336546c816aSDonát Nagy   // produced by dereferencing a pointer-to-pointer, because this is unlikely
337546c816aSDonát Nagy   // to be an accident and can appear in legitimate code that tries to call
338546c816aSDonát Nagy   // a generic function which emulates dynamic typing within C.
339546c816aSDonát Nagy   some_generic_function(IntPP, sizeof(*IntPP));
340546c816aSDonát Nagy   some_generic_function(ClassPP, sizeof(*ClassPP));
341546c816aSDonát Nagy   // Using `...[0]` instead of the dereference operator is another common
342546c816aSDonát Nagy   // variant, which is also widespread in the idiomatic array-size calculation:
343546c816aSDonát Nagy   // `sizeof(array) / sizeof(array[0])`.
344546c816aSDonát Nagy   some_generic_function(IntPP, sizeof(IntPP[0]));
345546c816aSDonát Nagy   some_generic_function(ClassPP, sizeof(ClassPP[0]));
346546c816aSDonát Nagy   // FIXME: There is a third common pattern where the generic function is
347546c816aSDonát Nagy   // called with `&Variable` and `sizeof(Variable)`. Right now these are
348546c816aSDonát Nagy   // reported by the `sizeof(pointer)` checks, but this causes some false
349546c816aSDonát Nagy   // positives, so it would be good to create an exception for them.
350546c816aSDonát Nagy   // NOTE: `sizeof(IntP)` is only reported with `WarnOnSizeOfPointer=true`.
351546c816aSDonát Nagy   some_generic_function(&IntPP, sizeof(IntP));
352546c816aSDonát Nagy   some_generic_function(&ClassPP, sizeof(ClassP));
353fdcfb277SDonát Nagy   // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: suspicious usage of 'sizeof()' on an expression of pointer type
354546c816aSDonát Nagy }
355546c816aSDonát Nagy 
35689a1d03eSRichard int ValidExpressions() {
35789a1d03eSRichard   int A[] = {1, 2, 3, 4};
35889a1d03eSRichard   static const char str[] = "hello";
35989a1d03eSRichard   static const char* ptr[] { "aaa", "bbb", "ccc" };
36089a1d03eSRichard   typedef C *CA10[10];
36189a1d03eSRichard   C *PtrArray[10];
36289a1d03eSRichard   CA10 PtrArray1;
36389a1d03eSRichard 
36489a1d03eSRichard   int sum = 0;
36589a1d03eSRichard   if (sizeof(A) < 10)
36689a1d03eSRichard     sum += sizeof(A);
36789a1d03eSRichard   sum += sizeof(int);
36889a1d03eSRichard   sum += sizeof(AsStruct());
36989a1d03eSRichard   sum += sizeof(M{}.AsStruct());
37089a1d03eSRichard   sum += sizeof(A[sizeof(A) / sizeof(int)]);
37189a1d03eSRichard   sum += sizeof(&A[sizeof(A) / sizeof(int)]);
37289a1d03eSRichard   sum += sizeof(sizeof(0));  // Special case: sizeof size_t.
37389a1d03eSRichard   sum += sizeof(void*);
37489a1d03eSRichard   sum += sizeof(void const *);
37589a1d03eSRichard   sum += sizeof(void const *) / 4;
37689a1d03eSRichard   sum += sizeof(str);
37789a1d03eSRichard   sum += sizeof(str) / sizeof(char);
37889a1d03eSRichard   sum += sizeof(str) / sizeof(str[0]);
37989a1d03eSRichard   sum += sizeof(ptr) / sizeof(ptr[0]);
38089a1d03eSRichard   sum += sizeof(ptr) / sizeof(*(ptr));
38189a1d03eSRichard   sum += sizeof(PtrArray) / sizeof(PtrArray[0]);
38289a1d03eSRichard   // Canonical type of PtrArray1 is same as PtrArray.
38389a1d03eSRichard   sum = sizeof(PtrArray) / sizeof(PtrArray1[0]);
38489a1d03eSRichard   // There is no warning for 'sizeof(T*)/sizeof(Q)' case.
38589a1d03eSRichard   sum += sizeof(PtrArray) / sizeof(A[0]);
38689a1d03eSRichard   return sum;
38789a1d03eSRichard }
388*e855feacSCongcong Cai 
389*e855feacSCongcong Cai namespace gh115175 {
390*e855feacSCongcong Cai template<class T>
391*e855feacSCongcong Cai int ValidateTemplateTypeExpressions(T t) {
392*e855feacSCongcong Cai   return sizeof(t.val) / sizeof(t.val[0]);
393*e855feacSCongcong Cai }
394*e855feacSCongcong Cai } // namespace gh115175
395