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