xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/bugprone/too-small-loop-variable.cpp (revision a7520d9727d2638047e5c464b2937581f64e2ce5)
189a1d03eSRichard // RUN: %check_clang_tidy %s bugprone-too-small-loop-variable %t -- \
289a1d03eSRichard // RUN:   -config="{CheckOptions: \
3e8a3ddafSNathan James // RUN:             {bugprone-too-small-loop-variable.MagnitudeBitsUpperLimit: 1024}}" \
489a1d03eSRichard // RUN:   -- --target=x86_64-linux
589a1d03eSRichard 
size()689a1d03eSRichard long size() { return 294967296l; }
789a1d03eSRichard 
889a1d03eSRichard ////////////////////////////////////////////////////////////////////////////////
989a1d03eSRichard /// Test cases correctly caught by bugprone-too-small-loop-variable.
1089a1d03eSRichard 
voidBadForLoop()1189a1d03eSRichard void voidBadForLoop() {
1289a1d03eSRichard   for (int i = 0; i < size(); ++i) {
1389a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
1489a1d03eSRichard   }
1589a1d03eSRichard }
1689a1d03eSRichard 
voidBadForLoop2()1789a1d03eSRichard void voidBadForLoop2() {
1889a1d03eSRichard   for (int i = 0; i < size() + 10; ++i) {
1989a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
2089a1d03eSRichard   }
2189a1d03eSRichard }
2289a1d03eSRichard 
voidBadForLoop3()2389a1d03eSRichard void voidBadForLoop3() {
2489a1d03eSRichard   for (int i = 0; i <= size() - 1; ++i) {
2589a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
2689a1d03eSRichard   }
2789a1d03eSRichard }
2889a1d03eSRichard 
voidBadForLoop4()2989a1d03eSRichard void voidBadForLoop4() {
3089a1d03eSRichard   for (int i = 0; size() > i; ++i) {
3189a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
3289a1d03eSRichard   }
3389a1d03eSRichard }
3489a1d03eSRichard 
voidBadForLoop5()3589a1d03eSRichard void voidBadForLoop5() {
3689a1d03eSRichard   for (int i = 0; size() - 1 >= i; ++i) {
3789a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
3889a1d03eSRichard   }
3989a1d03eSRichard }
4089a1d03eSRichard 
voidBadForLoop6()4189a1d03eSRichard void voidBadForLoop6() {
4289a1d03eSRichard   int i = 0;
4389a1d03eSRichard   for (; i < size(); ++i) {
4489a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
4589a1d03eSRichard   }
4689a1d03eSRichard }
4789a1d03eSRichard 
voidBadForLoop7()48c7dac522SPiotr Zegar void voidBadForLoop7() {
49c7dac522SPiotr Zegar     struct Int  {
50c7dac522SPiotr Zegar         int value;
51c7dac522SPiotr Zegar     } i;
52c7dac522SPiotr Zegar 
53c7dac522SPiotr Zegar   for (i.value = 0; i.value < size(); ++i.value) {
54c7dac522SPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'int' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
55c7dac522SPiotr Zegar   }
56c7dac522SPiotr Zegar }
57c7dac522SPiotr Zegar 
voidForLoopUnsignedBound()5889a1d03eSRichard void voidForLoopUnsignedBound() {
5989a1d03eSRichard   unsigned size = 3147483647;
6089a1d03eSRichard   for (int i = 0; i < size; ++i) {
6189a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: loop variable has narrower type 'int' than iteration's upper bound 'unsigned int' [bugprone-too-small-loop-variable]
6289a1d03eSRichard   }
6389a1d03eSRichard }
6489a1d03eSRichard 
6589a1d03eSRichard // The iteration's upper bound has a template dependent value.
6689a1d03eSRichard template <long size>
doSomething()6789a1d03eSRichard void doSomething() {
6889a1d03eSRichard   for (short i = 0; i < size; ++i) {
6989a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
7089a1d03eSRichard   }
7189a1d03eSRichard }
7289a1d03eSRichard 
7389a1d03eSRichard // The iteration's upper bound has a template dependent type.
7489a1d03eSRichard template <class T>
doSomething()7589a1d03eSRichard void doSomething() {
7689a1d03eSRichard   for (T i = 0; i < size(); ++i) {
7789a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
7889a1d03eSRichard   }
7989a1d03eSRichard }
8089a1d03eSRichard 
voidForLoopInstantiation()8189a1d03eSRichard void voidForLoopInstantiation() {
8289a1d03eSRichard   // This line does not trigger the warning.
8389a1d03eSRichard   doSomething<long>();
8489a1d03eSRichard   // This one triggers the warning.
8589a1d03eSRichard   doSomething<short>();
8689a1d03eSRichard }
8789a1d03eSRichard 
8889a1d03eSRichard // A suspicious function used in a macro.
8989a1d03eSRichard #define SUSPICIOUS_SIZE (size())
voidBadForLoopWithMacroBound()9089a1d03eSRichard void voidBadForLoopWithMacroBound() {
9189a1d03eSRichard   for (short i = 0; i < SUSPICIOUS_SIZE; ++i) {
9289a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'long' [bugprone-too-small-loop-variable]
9389a1d03eSRichard   }
9489a1d03eSRichard }
9589a1d03eSRichard 
getVal()96*a7520d97SShourya Goel unsigned int getVal() {
97*a7520d97SShourya Goel     return 300;
98*a7520d97SShourya Goel }
99*a7520d97SShourya Goel 
100*a7520d97SShourya Goel // The iteration's upper bound has a function declaration.
voidBadForLoop8()101*a7520d97SShourya Goel void voidBadForLoop8() {
102*a7520d97SShourya Goel   const unsigned int l = getVal();
103*a7520d97SShourya Goel   for (unsigned char i = 0; i < l; ++i) {
104*a7520d97SShourya Goel     // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: loop variable has narrower type 'unsigned char' than iteration's upper bound 'const unsigned int' [bugprone-too-small-loop-variable]
105*a7520d97SShourya Goel   }
106*a7520d97SShourya Goel }
107*a7520d97SShourya Goel 
10889a1d03eSRichard ////////////////////////////////////////////////////////////////////////////////
10989a1d03eSRichard /// Correct loops: we should not warn here.
11089a1d03eSRichard 
11189a1d03eSRichard // A simple use case when both expressions have the same type.
voidGoodForLoop()11289a1d03eSRichard void voidGoodForLoop() {
11389a1d03eSRichard   for (long i = 0; i < size(); ++i) { // no warning
11489a1d03eSRichard   }
11589a1d03eSRichard }
11689a1d03eSRichard 
11789a1d03eSRichard // Other use case where both expressions have the same type,
11889a1d03eSRichard // but short expressions are converted to int by the compare operator.
voidGoodForLoop2()11989a1d03eSRichard void voidGoodForLoop2() {
12089a1d03eSRichard   short loopCond = 10;
12189a1d03eSRichard   for (short i = 0; i < loopCond; ++i) { // no warning
12289a1d03eSRichard   }
12389a1d03eSRichard }
12489a1d03eSRichard 
12589a1d03eSRichard // Because of the integer literal, the iteration's upper bound is int, but we suppress the warning here.
voidForLoopShortPlusLiteral()12689a1d03eSRichard void voidForLoopShortPlusLiteral() {
12789a1d03eSRichard   short size = 30000;
12889a1d03eSRichard   for (short i = 0; i <= (size - 1); ++i) { // no warning
12989a1d03eSRichard   }
13089a1d03eSRichard }
13189a1d03eSRichard 
13289a1d03eSRichard // Addition of two short variables results in an int value, but we suppress this to avoid false positives.
voidForLoopShortPlusShort()13389a1d03eSRichard void voidForLoopShortPlusShort() {
13489a1d03eSRichard   short size = 256;
13589a1d03eSRichard   short increment = 14;
13689a1d03eSRichard   for (short i = 0; i < size + increment; ++i) { // no warning
13789a1d03eSRichard   }
13889a1d03eSRichard }
13989a1d03eSRichard 
14089a1d03eSRichard // In this test case we have different integer types, but here the loop variable has the bigger type.
14189a1d03eSRichard // The iteration's bound is cast implicitly, not the loop variable.
voidForLoopBoundImplicitCast()14289a1d03eSRichard void voidForLoopBoundImplicitCast() {
14389a1d03eSRichard   short start = 256;
14489a1d03eSRichard   short end = 14;
14589a1d03eSRichard   for (int i = start; i >= end; --i) { // no warning
14689a1d03eSRichard   }
14789a1d03eSRichard }
14889a1d03eSRichard 
14989a1d03eSRichard // Range based loop and other iterator based loops are ignored by this check.
voidRangeBasedForLoop()15089a1d03eSRichard void voidRangeBasedForLoop() {
15189a1d03eSRichard   int array[] = {1, 2, 3, 4, 5};
15289a1d03eSRichard   for (const int &i : array) { // no warning
15389a1d03eSRichard   }
15489a1d03eSRichard }
15589a1d03eSRichard 
15689a1d03eSRichard ////////////////////////////////////////////////////////////////////////////////
15789a1d03eSRichard /// Future possibilites to improve the check.
15889a1d03eSRichard 
15989a1d03eSRichard // False positive: because of the int literal, iteration's upper bound has int type.
voidForLoopFalsePositive()16089a1d03eSRichard void voidForLoopFalsePositive() {
16189a1d03eSRichard   short size = 30000;
16289a1d03eSRichard   bool cond = false;
16389a1d03eSRichard   for (short i = 0; i < (cond ? 0 : size); ++i) {
16489a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'int' [bugprone-too-small-loop-variable]
16589a1d03eSRichard   }
16689a1d03eSRichard }
16789a1d03eSRichard 
voidForLoopFalsePositive2()16889a1d03eSRichard void voidForLoopFalsePositive2() {
16989a1d03eSRichard   short size = 30000;
17089a1d03eSRichard   bool cond = false;
17189a1d03eSRichard   for (short i = 0; i < (!cond ? size : 0); ++i) {
17289a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'int' [bugprone-too-small-loop-variable]
17389a1d03eSRichard   }
17489a1d03eSRichard }
17589a1d03eSRichard 
17689a1d03eSRichard // False positive: The loop bound expression contains nested binary operators.
voidForLoopFalsePositive3()17789a1d03eSRichard void voidForLoopFalsePositive3() {
17889a1d03eSRichard   short number = 30000;
17989a1d03eSRichard   for (short i = 0; i < ((number & 0x7f) + 1); ++i) {
18089a1d03eSRichard     // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: loop variable has narrower type 'short' than iteration's upper bound 'int' [bugprone-too-small-loop-variable]
18189a1d03eSRichard   }
18289a1d03eSRichard }
18389a1d03eSRichard 
18489a1d03eSRichard // TODO: handle while loop.
voidBadWhileLoop()18589a1d03eSRichard void voidBadWhileLoop() {
18689a1d03eSRichard   short i = 0;
18789a1d03eSRichard   while (i < size()) { // missing warning
18889a1d03eSRichard     ++i;
18989a1d03eSRichard   }
19089a1d03eSRichard }
19189a1d03eSRichard 
19289a1d03eSRichard // TODO: handle do-while loop.
voidBadDoWhileLoop()19389a1d03eSRichard void voidBadDoWhileLoop() {
19489a1d03eSRichard   short i = 0;
19589a1d03eSRichard   do {
19689a1d03eSRichard     ++i;
19789a1d03eSRichard   } while (i < size()); // missing warning
19889a1d03eSRichard }
19989a1d03eSRichard 
20089a1d03eSRichard // TODO: handle complex loop conditions.
voidComplexForCond()20189a1d03eSRichard void voidComplexForCond() {
20289a1d03eSRichard   bool additionalCond = true;
20389a1d03eSRichard   for (int i = 0; i < size() && additionalCond; ++i) { // missing warning
20489a1d03eSRichard   }
20589a1d03eSRichard }
20689a1d03eSRichard 
20789a1d03eSRichard ////////////////////////////////////////////////////////////////////////////////
20889a1d03eSRichard /// Suspicious test cases ingored by this check.
20989a1d03eSRichard 
21089a1d03eSRichard // Test case with a reverse iteration.
21189a1d03eSRichard // This is caught by -Wimplicit-int-conversion.
voidReverseForLoop()21289a1d03eSRichard void voidReverseForLoop() {
21389a1d03eSRichard   for (short i = size() - 1; i >= 0; --i) { // no warning
21489a1d03eSRichard   }
21589a1d03eSRichard }
21689a1d03eSRichard 
21789a1d03eSRichard // Macro defined literals are used inside the loop condition.
21889a1d03eSRichard #define SIZE 125
21989a1d03eSRichard #define SIZE2 (SIZE + 1)
voidForLoopWithMacroBound()22089a1d03eSRichard void voidForLoopWithMacroBound() {
22189a1d03eSRichard   for (short i = 0; i < SIZE2; ++i) { // no warning
22289a1d03eSRichard   }
22389a1d03eSRichard }
22489a1d03eSRichard 
22589a1d03eSRichard // A suspicious loop is not caught if the iteration's upper bound is a literal.
voidForLoopWithLiteralBound()22689a1d03eSRichard void voidForLoopWithLiteralBound() {
22789a1d03eSRichard   for (short i = 0; i < 125; ++i) { // no warning
22889a1d03eSRichard   }
22989a1d03eSRichard }
23089a1d03eSRichard 
23189a1d03eSRichard // The used literal leads to an infinite loop.
23289a1d03eSRichard // This is caught by -Wtautological-constant-out-of-range-compare.
voidForLoopWithBigLiteralBound()23389a1d03eSRichard void voidForLoopWithBigLiteralBound() {
23489a1d03eSRichard   for (short i = 0; i < 294967296l; ++i) { // no warning
23589a1d03eSRichard   }
23689a1d03eSRichard }
23789a1d03eSRichard 
23889a1d03eSRichard enum eSizeType {
23989a1d03eSRichard   START,
24089a1d03eSRichard   Y,
24189a1d03eSRichard   END
24289a1d03eSRichard };
24389a1d03eSRichard 
24489a1d03eSRichard // A suspicious loop is not caught if the iteration's upper bound is an enum value.
voidForLoopWithEnumBound()24589a1d03eSRichard void voidForLoopWithEnumBound() {
24689a1d03eSRichard   for (short i = eSizeType::START; i < eSizeType::END; ++i) { // no warning
24789a1d03eSRichard   }
24889a1d03eSRichard }
24989a1d03eSRichard 
25089a1d03eSRichard enum eSizeType2 : long {
25189a1d03eSRichard   START2 = 294967296l,
25289a1d03eSRichard   Y2,
25389a1d03eSRichard   END2
25489a1d03eSRichard };
25589a1d03eSRichard 
25689a1d03eSRichard // The used enum value leads to an infinite loop.
25789a1d03eSRichard // This is caught by -Wtautological-constant-out-of-range-compare.
voidForLoopWithBigEnumBound()25889a1d03eSRichard void voidForLoopWithBigEnumBound() {
25989a1d03eSRichard   for (short i = eSizeType2::START2; i < eSizeType2::END2; ++i) { // no warning
26089a1d03eSRichard   }
26189a1d03eSRichard }
26289a1d03eSRichard 
26389a1d03eSRichard // A suspicious loop is not caught if the iteration's upper bound is a constant variable.
voidForLoopWithConstBound()26489a1d03eSRichard void voidForLoopWithConstBound() {
26589a1d03eSRichard   const long size = 252l;
26689a1d03eSRichard   for (short i = 0; i < size; ++i) { // no warning
26789a1d03eSRichard   }
26889a1d03eSRichard }
26989a1d03eSRichard 
27089a1d03eSRichard // The used constant variable leads to an infinite loop.
27189a1d03eSRichard // This is caught by -Wtautological-constant-out-of-range-compare.
voidForLoopWithBigConstBound()27289a1d03eSRichard void voidForLoopWithBigConstBound() {
27389a1d03eSRichard   const long size = 294967296l;
27489a1d03eSRichard   for (short i = 0; i < size; ++i) { // no warning
27589a1d03eSRichard   }
27689a1d03eSRichard }
277c7dac522SPiotr Zegar 
278c7dac522SPiotr Zegar // Should detect proper size of upper bound bitfield
voidForLoopWithBitfieldOnUpperBound()279c7dac522SPiotr Zegar void voidForLoopWithBitfieldOnUpperBound() {
280c7dac522SPiotr Zegar   struct StructWithBitField {
281c7dac522SPiotr Zegar       unsigned bitfield : 5;
282c7dac522SPiotr Zegar   } value = {};
283c7dac522SPiotr Zegar 
284c7dac522SPiotr Zegar   for(unsigned char i = 0U; i < value.bitfield; ++i) { // no warning
285c7dac522SPiotr Zegar   }
286c7dac522SPiotr Zegar }
287c7dac522SPiotr Zegar 
288c7dac522SPiotr Zegar // Should detect proper size of loop variable bitfield
voidForLoopWithBitfieldOnLoopVar()289c7dac522SPiotr Zegar void voidForLoopWithBitfieldOnLoopVar() {
290c7dac522SPiotr Zegar   struct StructWithBitField {
291c7dac522SPiotr Zegar       unsigned bitfield : 9;
292c7dac522SPiotr Zegar   } value = {};
293c7dac522SPiotr Zegar 
294c7dac522SPiotr Zegar   unsigned char upperLimit = 100U;
295c7dac522SPiotr Zegar 
296c7dac522SPiotr Zegar   for(value.bitfield = 0U; value.bitfield < upperLimit; ++value.bitfield) {
297c7dac522SPiotr Zegar   }
298c7dac522SPiotr Zegar }
299c7dac522SPiotr Zegar 
300c7dac522SPiotr Zegar // Should detect proper size of loop variable and upper bound
voidForLoopWithBitfieldOnLoopVarAndUpperBound()301c7dac522SPiotr Zegar void voidForLoopWithBitfieldOnLoopVarAndUpperBound() {
302c7dac522SPiotr Zegar   struct StructWithBitField {
303c7dac522SPiotr Zegar       unsigned var : 5, limit : 4;
304c7dac522SPiotr Zegar   } value = {};
305c7dac522SPiotr Zegar 
306c7dac522SPiotr Zegar   for(value.var = 0U; value.var < value.limit; ++value.var) {
307c7dac522SPiotr Zegar   }
308c7dac522SPiotr Zegar }
309c7dac522SPiotr Zegar 
310c7dac522SPiotr Zegar // Should detect proper size of loop variable and upper bound on integers
voidForLoopWithBitfieldOnLoopVarAndUpperBoundOnInt()311c7dac522SPiotr Zegar void voidForLoopWithBitfieldOnLoopVarAndUpperBoundOnInt() {
312c7dac522SPiotr Zegar   struct StructWithBitField {
313c7dac522SPiotr Zegar       unsigned var : 5;
314c7dac522SPiotr Zegar       int limit : 6;
315c7dac522SPiotr Zegar   } value = {};
316c7dac522SPiotr Zegar 
317c7dac522SPiotr Zegar   for(value.var = 0U; value.var < value.limit; ++value.var) {
318c7dac522SPiotr Zegar   }
319c7dac522SPiotr Zegar }
320c7dac522SPiotr Zegar 
badForLoopWithBitfieldOnUpperBound()321c7dac522SPiotr Zegar void badForLoopWithBitfieldOnUpperBound() {
322c7dac522SPiotr Zegar   struct StructWithBitField {
323c7dac522SPiotr Zegar       unsigned bitfield : 9;
324c7dac522SPiotr Zegar   } value = {};
325c7dac522SPiotr Zegar 
326c7dac522SPiotr Zegar   for(unsigned char i = 0U; i < value.bitfield; ++i) {
327c7dac522SPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: loop variable has narrower type 'unsigned char' than iteration's upper bound 'unsigned int:9' [bugprone-too-small-loop-variable]
328c7dac522SPiotr Zegar   }
329c7dac522SPiotr Zegar }
330c7dac522SPiotr Zegar 
badForLoopWithBitfieldOnLoopVar()331c7dac522SPiotr Zegar void badForLoopWithBitfieldOnLoopVar() {
332c7dac522SPiotr Zegar   struct StructWithBitField {
333c7dac522SPiotr Zegar       unsigned bitfield : 7;
334c7dac522SPiotr Zegar   } value = {};
335c7dac522SPiotr Zegar 
336c7dac522SPiotr Zegar   unsigned char upperLimit = 100U;
337c7dac522SPiotr Zegar 
338c7dac522SPiotr Zegar   for(value.bitfield = 0U; value.bitfield < upperLimit; ++value.bitfield) {
339c7dac522SPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:28: warning: loop variable has narrower type 'unsigned int:7' than iteration's upper bound 'unsigned char' [bugprone-too-small-loop-variable]
340c7dac522SPiotr Zegar   }
341c7dac522SPiotr Zegar }
342c7dac522SPiotr Zegar 
badForLoopWithBitfieldOnLoopVarAndUpperBound()343c7dac522SPiotr Zegar void badForLoopWithBitfieldOnLoopVarAndUpperBound() {
344c7dac522SPiotr Zegar   struct StructWithBitField {
345c7dac522SPiotr Zegar       unsigned var : 5, limit : 6;
346c7dac522SPiotr Zegar   } value = {};
347c7dac522SPiotr Zegar 
348c7dac522SPiotr Zegar   for(value.var = 0U; value.var < value.limit; ++value.var) {
349c7dac522SPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: loop variable has narrower type 'unsigned int:5' than iteration's upper bound 'unsigned int:6' [bugprone-too-small-loop-variable]
350c7dac522SPiotr Zegar   }
351c7dac522SPiotr Zegar }
352c7dac522SPiotr Zegar 
badForLoopWithBitfieldOnLoopVarOnIntAndUpperBound()353c7dac522SPiotr Zegar void badForLoopWithBitfieldOnLoopVarOnIntAndUpperBound() {
354c7dac522SPiotr Zegar   struct StructWithBitField {
355c7dac522SPiotr Zegar       int var : 5;
356c7dac522SPiotr Zegar       unsigned limit : 5;
357c7dac522SPiotr Zegar   } value = {};
358c7dac522SPiotr Zegar 
359c7dac522SPiotr Zegar   for(value.var = 0U; value.var < value.limit; ++value.var) {
360c7dac522SPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: loop variable has narrower type 'int:5' than iteration's upper bound 'unsigned int:5' [bugprone-too-small-loop-variable]
361c7dac522SPiotr Zegar   }
362c7dac522SPiotr Zegar }
363c7dac522SPiotr Zegar 
badForLoopWithBitfieldOnLoopVarAndUpperBoundOnInt()364c7dac522SPiotr Zegar void badForLoopWithBitfieldOnLoopVarAndUpperBoundOnInt() {
365c7dac522SPiotr Zegar   struct StructWithBitField {
366c7dac522SPiotr Zegar       unsigned var : 5;
367c7dac522SPiotr Zegar       int limit : 7;
368c7dac522SPiotr Zegar   } value = {};
369c7dac522SPiotr Zegar 
370c7dac522SPiotr Zegar   for(value.var = 0U; value.var < value.limit; ++value.var) {
371c7dac522SPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: loop variable has narrower type 'unsigned int:5' than iteration's upper bound 'int:7' [bugprone-too-small-loop-variable]
372c7dac522SPiotr Zegar   }
373c7dac522SPiotr Zegar }
374c7dac522SPiotr Zegar 
badForLoopWithBitfieldOnLoopVarAndUpperBoundOnPtr()375c7dac522SPiotr Zegar void badForLoopWithBitfieldOnLoopVarAndUpperBoundOnPtr() {
376c7dac522SPiotr Zegar   struct StructWithBitField {
377c7dac522SPiotr Zegar       unsigned var : 5, limit : 6;
378c7dac522SPiotr Zegar   } value = {};
379c7dac522SPiotr Zegar 
380c7dac522SPiotr Zegar   StructWithBitField* ptr = &value;
381c7dac522SPiotr Zegar 
382c7dac522SPiotr Zegar   for(ptr->var = 0U; ptr->var < ptr->limit; ++ptr->var) {
383c7dac522SPiotr Zegar   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: loop variable has narrower type 'unsigned int:5' than iteration's upper bound 'unsigned int:6' [bugprone-too-small-loop-variable]
384c7dac522SPiotr Zegar   }
385c7dac522SPiotr Zegar }
386c7dac522SPiotr Zegar 
goodForLoopWithBitfieldOnUpperBoundOnly()387113f0190SPiotr Zegar void goodForLoopWithBitfieldOnUpperBoundOnly() {
388113f0190SPiotr Zegar   struct S {
389113f0190SPiotr Zegar     int x : 4;
390113f0190SPiotr Zegar   } s;
391113f0190SPiotr Zegar 
392113f0190SPiotr Zegar   for (int i = 10; i > s.x; --i) {
393113f0190SPiotr Zegar   }
394113f0190SPiotr Zegar }
395113f0190SPiotr Zegar 
goodForLoopWithIntegersOnUpperBoundOnly()396113f0190SPiotr Zegar void goodForLoopWithIntegersOnUpperBoundOnly() {
397113f0190SPiotr Zegar   struct S {
398113f0190SPiotr Zegar     short x;
399113f0190SPiotr Zegar   } s;
400113f0190SPiotr Zegar 
401113f0190SPiotr Zegar   for (int i = 10; i > s.x; --i) {
402113f0190SPiotr Zegar   }
403113f0190SPiotr Zegar }
404