<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">