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

    <tr>
        <th>Summary</th>
        <td>
            Bogus core.uninitialized.Assign in range-based for loop on VLA
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang:static analyzer
      </td>
    </tr>

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

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

<pre>
    Let's consider the following code:

```c++
unsigned f();

void g() {
    int array[f()];

#ifdef RANGE
    for (auto& x : array)
        ;
#else
    auto &&__range1 = array;
    auto __begin1 = __range1;
    auto __end1 = __range1 + sizeof(array) / sizeof(int);
    for (; __begin1 != __end1; ++__begin1)
        auto& x = *__begin1;
#endif
}
```

With `clang --analyze -Xanalyzer -analyzer-output=text -DRANGE` this produces
```
range.cpp:7:18: warning: Assigned value is garbage or undefined [core.uninitialized.Assign]
    for (auto& x : array)
                 ^
range.cpp:4:15: note: Uninitialized value stored to '__range1'
    int array[f()];
              ^~~
range.cpp:7:18: note: Assigned value is garbage or undefined
    for (auto& x : array)
                 ^
```
but not without `-DRANGE`. CodeGen produces exactly the same IR for both cases, and the AST is the basically the same except for `sizeof(array)`: the regular for loop has
```
UnaryExprOrTypeTraitExpr 'unsigned long' sizeof
`-ParenExpr 'int [f()]' lvalue
  `-DeclRefExpr 'int [f()]' lvalue Var  'array' 'int [f()]'
```
whereas the range-based for loop has
```
UnaryExprOrTypeTraitExpr 'unsigned long' sizeof 'int [f()]'
`-CallExpr 'unsigned int'
  `-ImplicitCastExpr 'unsigned int (*)()' <FunctionToPointerDecay>
    `-DeclRefExpr 'unsigned int ()' lvalue Function  'f' 'unsigned int ()'
```
I guess that might be a problem (we don't actually want to evaluate the size expression again, and gladly CodeGen ignores that), but I'm not sure if it's related. Just for reference, with `sizeof(decltype(array))` the regular loop has simply
```
UnaryExprOrTypeTraitExpr 'unsigned long' sizeof 'decltype(array)':'int [f()]'
```

Apart from a different order of blocks, the CFG only differs in the first block:
```diff
--- a/regular.cfg
+++ b/range.cfg
@@ -29,23 +31,30 @@ void g()
  [B4]
-   1: f
-   2: [B4.1] (ImplicitCastExpr, FunctionToPointerDecay, unsigned int (*)(void))
-   3: [B4.2]()
+   1: [B4.9]
+   2: [B4.10] (ImplicitCastExpr, FunctionToPointerDecay, unsigned int (*)(void))
+   3: [B4.11]
    4: int array[f()];
    5: array
    6: auto &&__range1 = array;
    7: __range1
    8: [B4.7] (ImplicitCastExpr, ArrayToPointerDecay, int *)
-   9: auto __begin1 = __range1;
-  10: __range1
-  11: [B4.10] (ImplicitCastExpr, ArrayToPointerDecay, int *)
-  12: sizeof (array)
+   9: f
+  10: [B4.9] (ImplicitCastExpr, FunctionToPointerDecay, unsigned int (*)(void))
+  11: [B4.10]()
+  12: sizeof(int [f()])
   13: sizeof(int)
   14: [B4.12] / [B4.13]
-  15: [B4.11] + [B4.14]
-  16: auto __end1 = __range1 + sizeof (array) / sizeof(int);
+  15: [B4.8] + [B4.14]
+  16: auto __end1 = __range1 + sizeof(int [f()]) / sizeof(int);
+  17: __range1
+  18: [B4.17] (ImplicitCastExpr, ArrayToPointerDecay, int *)
+  19: auto __begin1 = __range1;
```
Again the only difference seems to be the reevaluation of `f` and the `sizeof` expression. Not sure if the forward references are a problem for the CFG, though it's a bit weird to see e.g. [B4.1] reference [B4.9].
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy1WNty2zYQ_RrqBUMOL6IoPehBkqOMO5k0TZ20bx6QBCm0FKEBwcjK13cX4AW62FU7iYa2RWCBPbt7FrtwKvLT8gNTTpg0JBN1w3MmidoxUoiqEkdelzCcMydaOf6D4_e_Z755Midc46NHW1he1iwnhRPOnXDhRGt70TfBc1KaKeIk3RyBD68VoVLSkxOv-7Xxw8VyJ4x4kbOCfF59fP9uXFwISWANbZVwwhl5IYC12w22GcTwM-4YRqxq2DiLq2GXGTzPz5LWJQtA-qHbJ1pfSD4_p6zktZHpF9wSY3V-LgRK1qTh35lAQ3uYMLodR8EdtvcsI2HM0h0GZmdUgjMmFv38lfW2hx5AeDVI2m6pc150b8nDRbTtcPzB1Y4gAyqwi7gurWl1-s6I-2f3TZJ-TLqiVYdWgVrFXhRxH0wIZz4wjTfkIEXeZqy5qU27zcsOBwhrAj_BHON7pLIGbuLXVdOx7hutWkZgv5LKlJaMgM_aGhjDcRaolQnJvBbWccVpBd7OPbMYyfZ_-DR8nPjdNdopoo1xdS0UZhD5Yuvu8DYKUOVE0y8ZqBQmd2fHNZJEP294r8dzn-t-kGsu4pq2CnGQI_AI6IFUGnnhkQ0cOu9ZPXCDsBeaqeqkz6aG7hl5_KzxpAJ4mNEG6BNuCK1zLbH6_QnNwa8pbXhGK3spe8nYQRlzZv5VNiJGMAzFJSvbikotWglxIDt6m6ZfaipP714O8lf5dDqwJ0m5wleM6nAuVgIoGyZ9pvf7uJ-oZHUvjeE-jzSsqHSEehdrX7Gs-syKO1aRr2AAynT2Ja_J3zTsuGOSUeNKzSYXHIpn_E_wyL8CczcQyKtN9HmZ2M553B8qnnG1oc21Tq0Bd1-hAqMGnRJttm2dKS7qJ_FJgBST4GQ8_q1qc8P11xsvLOf3e-oIFJ33by-56cZHUrasQf9TRfa83CmSMkIxMdKK7XH1kZFc1LABnBOZajXXjxR2hkOFIQqqmCE_eBnIf5CwIUKiJeV1nzZlRXNY2Cce4IODyejV8DYEU_YR1Ox14jathCOjINw0D5JVoCb3yC9tY1JLsgKoU2cM1x67cjEkWw5OVMALO-906p3lXc8wgA4hPf1Iot0EgGfkf8kO83t1oBJslmIPgYH6qe1WcIhiMwXa0kpkf-vzCW3bbN8TUYOrjWQDJDAdF5fgOS07tlu9OpQ1Q67rEgr9QuciLyvKvnqvzUNSnDYn_zA59eEhro5kGGGvEEGZ2UQ-6abs9mzIpXi9ng7V0QX-B3gyFuN7iO9azAtAEOl4mXxo9yuZBTOvpiXi6UgxaItGbaGOyggW7e7gGYHFgNtM2Uj9nwvVKLTABsFZi4GdwT1lPR7r6zA202N3t6tI6LFDHYbnI7bkDV-scL9rRxj7V2ehWQy43m6OQTbwr0HhcHBnhO5HFeigDzk_P-9VTJgWFqP1iIE3kuhnE-XK7ita22aY-8Hl6TR2X0F0KXs2O7V0hca4bf8e2ZluOleLvvrm0r2fnQnBzAr9WxceOwJv3niM0RaA-av6jei9CF5x3h1gbuSRmbAyKfgBqWQ2vTeZLqrRCuu5riVWfcEKTBrG9g32Aynr6mvXGGAbgJGZ-QXW3r5_His1DI4dg0c-WpXf_JtAwl0sH4t9A4eQ3Z9gJ9BVPVMARVvu-qaBkpTDFYBxqW9AgJIwr_TsgjJsbGWkN8mXUb6IFnSiuKrYci3KFv9_8cr9Divszd4VjP_6YTVpZbXcKXVodPXfwlNCu9KmXib28FJV3_o_Lpj1F8sA_ZY3TYuXjm089efJZLdM2CJKM3_uRzGdzrI0yaZpGE9ncZKmcTJfTCqasqpZgh1OGOp7M-hrFAQhI_1VGWbAwAlfhn6ITxwGwTSeeck0maVFOI8WiZ_OGYOKzfaUVx6i8oQsJ3KpAaZt2cBkxRvVjJPU3PRYp3xHxUfxW6cLeLYTckmpFPWhzaDfVxNt3FJb9g-EOjST">