cppfront
cppfront copied to clipboard
[BUG] Cannot emit `static constexpr` function local variables
Describe the bug
I can't find a Cpp2 syntax to emit a static constexpr
local variable. static constexpr
variables are useful (particularly in debug/non-optimised builds) for look-up tables in a function where you want the data initialised once and also prefer to keep the variable close to its use in the function, rather than declaring it globally.
See:
-
C++ Weekly - Ep 312 - Stop Using
constexpr
(And Use This [static constexpr] Instead!) - C++ Weekly - Ep 315 - constexpr vs static constexpr
- Does static constexpr variable inside a function make sense?
To Reproduce Run cppfront on this code:
main: () -> int = {
ints: std::array == (11, 22, 33);
it: == std::find(ints.cbegin(), ints.cend(), 33);
return it*;
}
It lowers to:
auto main() -> int{
std::array constexpr ints{ 11, 22, 33 };
auto constexpr it = std::find(CPP2_UFCS(cbegin)(ints), CPP2_UFCS(cend)(ints), 33);
return *cpp2::impl::assert_not_null(it);
}
which produces a C++ compiler error:
main.cpp2:3:20: error: constexpr variable 'it' must be initialized by a constant expression
3 | auto constexpr it = std::find(CPP2_UFCS(cbegin)(ints), CPP2_UFCS(cend)(ints), 33);
| ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp2:3:20: note: pointer to subobject of 'ints' is not a constant expression
main.cpp2:2:26: note: address of non-static constexpr variable 'ints' may differ on each invocation of the enclosing function; add 'static' to give it a constant address
2 | std::array constexpr ints{ 11, 22, 33 };
| ^
| static
Why static constexpr
Here's a C++ example demonstrating why static constexpr
is useful:
Side-by-side repro on Godbolt
With static constexpr
int main()
{
static constexpr std::array ints = {11, 22, 33};
constexpr auto it = std::find(ints.cbegin(), ints.cend(), 33);
return *it;
}
MSVC Release `/O2`
main PROC ; COMDAT
mov eax, 33 ; 00000021H
ret 0
main ENDP
MSVC Debug `/Od`
std::array<int,3> const `main'::`2'::ints DD 0bH ; `main'::`2'::ints
DD 016H
DD 021H
it$ = 32
main PROC
$LN3:
sub rsp, 56 ; 00000038H
lea rax, OFFSET FLAT:std::array<int,3> const `main'::`2'::ints
add rax, 8
mov QWORD PTR it$[rsp], rax
lea rcx, QWORD PTR it$[rsp]
call int const & std::_Array_const_iterator<int,3>::operator*(void)const ; std::_Array_const_iterator<int,3>::operator*
mov eax, DWORD PTR [rax]
add rsp, 56 ; 00000038H
ret 0
main ENDP
Without static constexpr
int main()
{
std::array ints = {11, 22, 33};
auto it = std::find(ints.cbegin(), ints.cend(), 33);
return *it;
}
MSVC Release `/O2`
ints$ = 32
__$ArrayPad$ = 48
main PROC ; COMDAT
$LN41:
sub rsp, 72 ; 00000048H
mov rax, QWORD PTR __security_cookie
xor rax, rsp
mov QWORD PTR __$ArrayPad$[rsp], rax
mov r8d, 33 ; 00000021H
mov DWORD PTR ints$[rsp], 11
lea rdx, QWORD PTR ints$[rsp+12]
mov DWORD PTR ints$[rsp+4], 22
lea rcx, QWORD PTR ints$[rsp]
mov DWORD PTR ints$[rsp+8], 33 ; 00000021H
call __std_find_trivial_4
mov eax, DWORD PTR [rax]
mov rcx, QWORD PTR __$ArrayPad$[rsp]
xor rcx, rsp
call __security_check_cookie
add rsp, 72 ; 00000048H
ret 0
main ENDP
MSVC Debug `/Od`
voltbl SEGMENT
DDSymXIndex: FLAT:main
voltbl ENDS
$T1 = 32
$T2 = 40
$T3 = 48
it$ = 56
$T4 = 64
$T5 = 72
ints$ = 80
__$ArrayPad$ = 96
main PROC
$LN3:
sub rsp, 120 ; 00000078H
mov rax, QWORD PTR __security_cookie
xor rax, rsp
mov QWORD PTR __$ArrayPad$[rsp], rax
mov DWORD PTR ints$[rsp], 11
mov DWORD PTR ints$[rsp+4], 22
mov DWORD PTR ints$[rsp+8], 33 ; 00000021H
mov DWORD PTR $T1[rsp], 33 ; 00000021H
lea rdx, QWORD PTR $T4[rsp]
lea rcx, QWORD PTR ints$[rsp]
call std::_Array_const_iterator<int,3> std::array<int,3>::cend(void)const ; std::array<int,3>::cend
mov rax, QWORD PTR [rax]
mov QWORD PTR $T2[rsp], rax
lea rdx, QWORD PTR $T5[rsp]
lea rcx, QWORD PTR ints$[rsp]
call std::_Array_const_iterator<int,3> std::array<int,3>::cbegin(void)const ; std::array<int,3>::cbegin
mov rax, QWORD PTR [rax]
mov QWORD PTR $T3[rsp], rax
lea r9, QWORD PTR $T1[rsp]
mov r8, QWORD PTR $T2[rsp]
mov rdx, QWORD PTR $T3[rsp]
lea rcx, QWORD PTR it$[rsp]
call std::_Array_const_iterator<int,3> std::find<std::_Array_const_iterator<int,3>,int>(std::_Array_const_iterator<int,3>,std::_Array_const_iterator<int,3>,int const &) ; std::find<std::_Array_const_iterator<int,3>,int>
lea rcx, QWORD PTR it$[rsp]
call int const & std::_Array_const_iterator<int,3>::operator*(void)const ; std::_Array_const_iterator<int,3>::operator*
mov eax, DWORD PTR [rax]
mov rcx, QWORD PTR __$ArrayPad$[rsp]
xor rcx, rsp
call __security_check_cookie
add rsp, 120 ; 00000078H
ret 0
main ENDP