Open MitalAshok opened 1 month ago
@llvm/issue-subscribers-clang-frontend
Author: Mital Ashok (MitalAshok)
CC @AaronBallman
I agree there's an issue here and we should treat VLAs consistently. However, VLAs are an extension in C++ and that means they should be supported fully within the language as best we can (it's on us to define how that support looks). Given that C++ allows memory allocations so long as they're paired with a deallocation, there's no reason for VLAs to not work in constant expressions. e.g.,
consteval int f(int n) {
if (n <= 0) return -1;
int array[n];
...
return array[0];
}
is semantically identical to
consteval int f(int n) {
if (n <= 0) return -1;
int *array = new int[n];
...
int ret = array[0];
delete [] array;
return ret;
}
While I think it's unfortunate that we enabled VLAs in C++ as an extension by default, it is a conforming extension and it is used in the wild. Further, GCC supports the same extension, but integrates it better with other C++ features: https://godbolt.org/z/rh4hE57Kr
Given something like: https://godbolt.org/z/x5n8KbqbW
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]; }
andif !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/1vYo9n5qGAt least that sort of use should be supported. This is more questionable:
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 markedconstexpr
even if no constant expression can actually be formed.