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

    <tr>
        <th>Summary</th>
        <td>
            [C++] Inconsistent treatment of VLAs in C++23 constexpr/consteval functions
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

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

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

<pre>
    Given something like: https://godbolt.org/z/x5n8KbqbW

```c++
consteval bool f(int n) {
  int vla[n];
  return true;
}
static_assert(f(1));
```

This doesn't compile in C++20 because the VLA is not considered a literal type.

However, this does compile in C++23 (<https://godbolt.org/z/sdTK7zvxb>), with just a warning about the VLA extension.  
VLA variables can't be used for much during constant evaluations (`sizeof(vla)`, `vla[0] = 1` and `(void)vla[0]` are all considered invalid subexpressions in constant expressions), so this seems unintentional.

It should probably just be an invalid to flow over the initialization of a VLA during a constant expression in C++23 (and allow `if (false) { int vla[n]; }` and `if !consteval { int vla[n]; }`).

---

On a related note, typedefs for vlas are banned even when not used inside `constexpr` functions in C++23: https://godbolt.org/z/1vYo9n5qG

```c++
constexpr bool f(int n) {
  if !consteval {
    typedef int vla_t[n];
    vla_t vla;
 }
  return true;
}
```

```
<source>:3:13: error: variably-modified type 'int[n]' cannot be used in a constexpr function
 3 |     typedef int vla_t[n];
      | ^~~~~~~~~~~~
```

At least that sort of use should be supported. This is more questionable:

```c++
constexpr bool f(int g()) {
 typedef int vla_t[g()];
  if !consteval { vla_t vla; }
  return true;
}
```

It could get the same treatment as VLA variables (as long as control doesn't flow over it, so it works in `if (false) { typedef int vla_t[g()]; }`), or it could "just work" and evaluate the bounds expression during the constant evaluation and discard the result.

The intent of C++23 `constexpr` declaration rules is that every function can be marked `constexpr` even if no constant expression can actually be formed.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJykVltv2zgT_TX0yyCGTMUXPfjBdep-Rb_FvhS72KdiKI5sNjTpkpQd52F_-2Io-ZLGaILdQEgUXoaHZ-acEcZo1o5oLsYfxPhhgG3a-DD_zSS0i7jxjwPl9XH-yezJQfRbShvj1mDNI4lyAZuUdlGUCyFXQq7WXitv09CHtZCrZyFXT2M3-6J-qD9F8SCKRf97UnRPLeQHfvJo7V1MtEcLynsLjZAz4xI4ISsQ034RAI_tLYrxByfGD6I8TwRKbXCQQkvnUTF96F5iwmTqbxgjhSTkjKOPhKz4OS8-wbrG-nVjImhP0Qk5TVD77c5YAuNg2YGXBSiqsY0EaUPwx_8XYCI4z2tdNJoCaUCwJlFAC-m4o-H1Af_zB9pTEHIJ6XTWrWNKEHImyuVbjEf99cv0ef-kRPkxX3AJB5M28L2NCRAOGBwnEJVv0xkxPSVy0Xg3BOhg8egeg0FlGQ9211cEbSQNjQ-wbesN6DZwtJw7dAk4fy0m413MeCdFNM_kmW5OmqyYXrkEMSm6JBZi_ACifICRmBSATkNeMdt7o4WsLovydCBAa6-ZNW6P1miIraKnXaAY89nGXWG6jPeERN9xHYm2EVpnXCLHoNG-yM3nBHHjW6thF7xCZY8djYoA3fno5KGx_gB-TyEzapxJBq15zkSAbwAzyz1ZeAvaq1QzFWg5rpgUpuGhBm2kXg6vdQBc7BcO85bRRVS_2iNk9eLed3d31__-7gAhkMVEmiubcrEed6SpibkW9hZjzo5C50gDsVscNuSyEHLJmJwyRtZhetoFRtu0rk6nlJ0JeI-1jPZ_-cqNf3x6r7U87cIb1vKastMUnO574vBbeu1A0E1kis-jZwt6w6Fuus_Pg-Uy-jbUxNouF0zTKHNFIfjAL71kj3dbr01jSGfcIOTUuDNiOWVBc2ZOejbuVJWZpVNSeuAliOkS3k0C5OVi_PHvy88v7rhIYAkjmxEmiD4kVgz7aa89RRDb3c6HRHoI2ZBNhK0PBD9ailm3ynI7-teVsGavyt3gKum3Lnta-OLKt6R2XQn_rQY-cydhHtbUGXbELUEKhGlLLgFGeGnWbB4RrGer4VbiUvD2qoddzMqk3g1NgoMPj1mEt-3mTTIuVsIxPQfvcQsps2vyCULKbFB9n-h6pvKt0_HaDHun5MkbrSVH0CbWGHReEyi2Ng1f9m32YbZ1rqYrZ_3JfzTVFkMXNrRMn4ldJXJXPp6lwIrhStxieCT9Kkw2PNOA8zfNnTdjnVq09shRGh-2pIcDPS91VVY4oPloKsv7qizLyWAzv0dNMz2dVtMKG1TVeKKUnsxGiFQ3o3scmLks5H0xG0lZFLPxZDielc1oorSicUXTZizuC9qisUNr91t2zYGJsaX5qJDVtBhYVGRj_uiT0tEB8qyQkr8Bw5w33al2HcV9YU1M8RImmWTz12LPKffvzy535JjpvlSmb7gyXzr7xWWEXF0kc24DgzbY-U_Wb9KmVcPab4VcMY7-z90u-O9UJyFXGX3kptBdbz-X_wQAAP__vUlafw">