<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/79580>79580</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            bugprone-too-small-loop-variable - false-negative when const variable is used as loop bound
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang-tidy,
            false-negative
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          PiotrZSL
      </td>
    </tr>
</table>

<pre>
    Example:
```
unsigned int getVal() {
    return 300; // or just have some other function calls here that at the end return value above 255
}

int main() {
 {
        const auto l = getVal();
        for (unsigned char i = 0; i < l; ++i)    {  ; }
    }

    {
        const unsigned int l = getVal();
        for (unsigned char i = 0; i < l; ++i)    {  ; }
 }
}
```

Above issues are not detected, and lead to endless loop. This is because in AST this code looks like this:
```
`-ForStmt <line:13:9, line:16:9>
    |   |-DeclStmt <line:13:14, col:27>
    | | `-VarDecl <col:14, col:26> col:22 used i 'uint8_t':'unsigned char' cinit
    |   |   `-ImplicitCastExpr <col:26> 'uint8_t':'unsigned char' <IntegralCast>
    |   |     `-IntegerLiteral <col:26> 'int' 0
    | |-<<<NULL>>>
    |   |-BinaryOperator <col:29, col:33> 'bool' '<'
    | | |-ImplicitCastExpr <col:29> 'std::uint32_t':'unsigned int' <IntegralCast>
    |   | | `-ImplicitCastExpr <col:29> 'uint8_t':'unsigned char' <LValueToRValue>
    |   | |   `-DeclRefExpr <col:29> 'uint8_t':'unsigned char' lvalue Var 0xc827c30 'i' 'uint8_t':'unsigned char'
    |   | `-ImplicitCastExpr <col:33> 'std::uint32_t':'unsigned int' <LValueToRValue>
    |   |   `-DeclRefExpr <col:33> 'const std::uint32_t':'const unsigned int' lvalue Var 0xc827900 'l' 'const std::uint32_t':'const unsigned int'
    |   |-UnaryOperator <col:36, col:38> 'uint8_t':'unsigned char' lvalue prefix '++' cannot overflow
    | | `-DeclRefExpr <col:38> 'uint8_t':'unsigned char' lvalue Var 0xc827c30 'i' 'uint8_t':'unsigned char'
```
Type used for loop bound is actually const, because local variable is const.

And in check code matcher:
```
 StatementMatcher LoopBoundMatcher =
 expr(ignoringParenImpCasts(allOf(hasType(isInteger()),
 unless(integerLiteral()),
 unless(hasType(isConstQualified())),
 unless(hasType(enumType())))))
 .bind(LoopUpperBoundName);
```

uses `unless(hasType(isConstQualified()))` to ignore code like this:

```
 // A suspicious loop is not caught if the iteration's upper bound is a constant variable.
 void voidForLoopWithConstBound() {
   const long size = 252l;
   for (short i = 0; i < size; ++i) { // no warning
   }
 }

 // The used constant variable leads to an infinite loop.
 // This is caught by -Wtautological-constant-out-of-range-compare.
 void voidForLoopWithBigConstBound() {
   const long size = 294967296l;
 for (short i = 0; i < size; ++i) { // no warning
   }
 }
```

Originally this were used to ignore code duplication between -Wtautological-constant-out-of-range-compare compiler warning and this check, but it were implemented incorrectly.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8V91u4zoOfhrlhnDgyvnzRS6StAUG6J45e9rpAfZmIcuMrRlFMiQ5bffpF5SdNGk83XYWmMK1HYHiz0eK_Cy8V5VBXLLpmk2vR6INtXXLP5UN7l_3d6PCli_Lm2exazSybMXSa5au2Cztr_izNVFHCcoEqDA8Cs34gvEc2HzdiQAAOAytM5ClKcvWwPgt47dgHXxvfYBa7BG83SHYUKODbWtkUNaAFFp7qNEhhFoEEAFCjYCmPCjcC90iiMLuEfh02rs4v-5f4p082wllLvw685D-pDU-gGiDBQ0suz4LiGVvpLfWAeOLIwKyFg5U3BejpNcN6C7gNeNrReYByC5AXD442q2eed0LDjl4hvlvdvTVy-PLeUF091XMiPK-RQ_CIRgboMSAMmDJ-AaEKUGjKCFYyqdG70Fb24zhoVYelIcCpWg9gjKwun-AQMvSlkhiPzxo9QPj4s8qk83S5Na6-7ALFJ9Whor4KmPZKicPDguzuJDdnMK-6e7JNUo9pOBqQhqk1Sxb8fnF5vg_S5NH4UgD7e5kz_bNWHZzeOfQekooMD5vlQmLfwdGilf0-zRvjM9BKqPCgLt0n6XJl12jlVRhI3y4eW7cq_nO5EdMsGzzxQSsnNCkZhieWFzRIomiu1MBndAD9pQhW5BewJSwbNNdf3y7uyMz3TWQi7Uywr18bdCJYE-Dyl8xzbLeYGGtjnFQhBu6XyZovnkPqrzX5ENJGGUrwizjQ6D10X0Ms0NtfMD0R7J090gd8MH-FZ_v2OwyReX4F25_1aDu-u2jcJA-ywWfyyyN-e2x_l8KBp17F4xjRj-Vhw-h8g4iR6tdw_257cuGPAhTnkaYDiX5S1qHzsS34SORzU6OxOKTyW0cbtVzPDlxGMSOIww1cLtHt9X2abjbDSP5WfP_Z229GQIPLw12rZWGIA0YKGxrShowQoZWaP3STVVC7DBytJVCw144JQpNY6wTGZ9NOFJiQNYof3RzaSeCrNH9bB7BfRABd2jCPzpBuLO2WZM3hwWWHcYsPjeO8YWqjHXKVH8Kh-bLrqHz4RlfCK2_bhlf1MJThCTp-ybcc4DYFXtlraHxSkJnffo9yVPFG4r9n63QaqtoeB93vb8RTbvrX082HK5u27hQhjQSEt-aBl2E4w-xw1MeM8gwWo-eyu6zLs9SohwRWOz5xCWTGMxfz1pX4FvfKKls21EWqg86HVK0VR1AbSNJjRgTi6XeBS0Fd1J6XUEJE45V1hcX7K0q4-3WOoLlbxXqGE6EZoBbd81CW1OBV__BSOv4lOtTGtgzQF9bFy6ZH217Q_6I-fXxGgtPwhllqqO6ITp4htFD3Z-6izAj6fOUAmFAmS1RGeyY31sVHQ3sUS1eIPk7EDXXtlJS6OSgOrFtSOw2ccJUmEi7a4R7F821qj4PaD7JZ3Oez05g_Q2gDhX-V6cqZWLjipz4iT6PIthv6rpsaajGGoQCwxOi-RSGQE-l0R1cjaS94-HU9WLHbAOo0Pmg6DuR-lscWdI6hzLol_GoXGZlnuVihMureTrjs3ya8VG9lNui4DnKYo6iKGU2ySbzUk7KVMzTTM5nI7XkKZ-kV3x2dTWZZnxc5FJeodzy-YQXZZ6zSYo7ofRY6_1ubF01ip8cy3k-XaQjLQrUPn7dci61MFUSVPnCOKfGxflWaI-JwUoEtUdanl6P3JJ0JUVbeTZJtfLBv2oPKmhcFm3VOGswCdYmfie0TqiAk2ONJ3CuGp5qNH1dnU6VmDXhT-bSqHV6WYfQxGYUa6VSoW6LsbQ7xm_Jk_6RNM5-RxkYv-2-sxi_jXH_NwAA__9ltKOL">