https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110900
Bug ID: 110900
Summary: std::string initializes SSO object subfield without
making the SSO object active in the union
Product: gcc
Version: 11.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: danakj at orodu dot net
Target Milestone: ---
Specific errors by clang:
note: construction of subobject of member '_M_local_buf' of union with no
active member is not allowed in a constant expression
error: accessing ‘std::__cxx11::basic_string<char>::<unnamed
union>::_M_allocated_capacity’ member instead of initialized
‘std::__cxx11::basic_string<char>::<unnamed union>::_M_local_buf’ member in
constant expression
Specific error by GCC:
error: accessing ‘std::__cxx11::basic_string<char>::<unnamed
union>::_M_allocated_capacity’ member instead of initialized
‘std::__cxx11::basic_string<char>::<unnamed union>::_M_local_buf’ member in
constant expression
Full errors:
Here's the clang 17 error:
/usr/include/c++/12/bits/stl_construct.h:97:14: note: construction of subobject
of member '_M_local_buf' of union with no active member is not allowed in a
constant expression
97 | { return ::new((void*)__location)
_Tp(std::forward<_Args>(__args)...); }
| ^
/usr/include/c++/12/bits/char_traits.h:262:6: note: in call to
'construct_at(&[]() {
std::string acc;
sus::Array<char, 5>::with('a', 'b', 'c', 'd',
'e').into_iter().for_each([&](char v) {
acc.push_back(v);
});
return acc;
}().._M_local_buf[0], acc.._M_local_buf[0])'
262 | std::construct_at(__s1 + __i, __s2[__i]);
| ^
/usr/include/c++/12/bits/char_traits.h:429:11: note: in call to 'copy(&[]() {
std::string acc;
sus::Array<char, 5>::with('a', 'b', 'c', 'd',
'e').into_iter().for_each([&](char v) {
acc.push_back(v);
});
return acc;
}().._M_local_buf[0], &acc.._M_local_buf[0], 6)'
429 | return __gnu_cxx::char_traits<char_type>::copy(__s1, __s2,
__n);
| ^
/usr/include/c++/12/bits/basic_string.h:675:6: note: in call to 'copy(&[]() {
std::string acc;
sus::Array<char, 5>::with('a', 'b', 'c', 'd',
'e').into_iter().for_each([&](char v) {
acc.push_back(v);
});
return acc;
}().._M_local_buf[0], &acc.._M_local_buf[0], 6)'
675 | traits_type::copy(_M_local_buf, __str._M_local_buf,
| ^
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1864:12:
note: in call to 'basic_string(acc)'
1864 | return acc;
| ^
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1859:17:
note: in call to '[]() {
std::string acc;
sus::Array<char, 5>::with('a', 'b', 'c', 'd',
'e').into_iter().for_each([&](char v) {
acc.push_back(v);
});
return acc;
}.operator()()'
1859 | static_assert([]() {
| ^
Here's the g++ 13 error:
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:24:
error: non-constant condition for static assertion
1787 | static_assert(sus::Array<char, 5>::with('a', 'b', 'c', 'd', 'e')
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1788 | .into_iter()
| ~~~~~~~~~~~~
1789 | .fold(std::string(), [](std::string acc, char v) {
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1790 | acc.push_back(v);
| ~~~~~~~~~~~~~~~~~
1791 | return acc;
| ~~~~~~~~~~~
1792 | }) == "abcde");
| ~~~^~~~~~~~~~
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:35: in
‘constexpr’ expansion of ‘sus::iter::IteratorBase<Iter, Item>::fold(B, F) &&
[with B = std::__cxx11::basic_string<char>; F =
{anonymous}::Iterator_Fold_Test::TestBody()::<lambda(std::string, char)>; Iter
= sus::containers::ArrayIntoIter<char, 5>; ItemT =
char](std::__cxx11::basic_string<char>(), (<lambda closure
object>{anonymous}::Iterator_Fold_Test::TestBody()::<lambda(std::string,
char)>(), {anonymous}::Iterator_Fold_Test::TestBody()::<lambda(std::string,
char)>()))’
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:35: in
‘constexpr’ expansion of ‘sus::fn::call_mut(F&&, Args&& ...) [with F =
{anonymous}::Iterator_Fold_Test::TestBody()::<lambda(std::string, char)>&; Args
= {std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >, char}]((* &
sus::mem::move<std::__cxx11::basic_string<char>&>(init)), (&
sus::mem::move<sus::option::Option<char>&>(o))->sus::option::Option<char>::unwrap())’
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:35: in
‘constexpr’ expansion of ‘std::invoke(_Callable&&, _Args&& ...) [with _Callable
= {anonymous}::Iterator_Fold_Test::TestBody()::<lambda(string, char)>&; _Args =
{__cxx11::basic_string<char, char_traits<char>, allocator<char> >, char};
invoke_result_t<_Fn, _Args ...> = __cxx11::basic_string<char>]((* &
sus::mem::forward<std::__cxx11::basic_string<char> >((* & args#0))), (* &
sus::mem::forward<char>((* & args#1))))’
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:35: in
‘constexpr’ expansion of ‘std::__invoke(_Callable&&, _Args&& ...) [with
_Callable = {anonymous}::Iterator_Fold_Test::TestBody()::<lambda(string,
char)>&; _Args = {__cxx11::basic_string<char, char_traits<char>,
allocator<char> >, char}; typename __invoke_result<_Functor, _ArgTypes>::type =
__cxx11::basic_string<char>]((* & std::forward<__cxx11::basic_string<char> >((*
& __args#0))), (* & std::forward<char>((* & __args#1))))’
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:35: in
‘constexpr’ expansion of ‘std::__invoke_impl(__invoke_other, _Fn&&, _Args&&
...) [with _Res = __cxx11::basic_string<char>; _Fn =
{anonymous}::Iterator_Fold_Test::TestBody()::<lambda(string, char)>&; _Args =
{__cxx11::basic_string<char, char_traits<char>, allocator<char> >, char}]((* &
std::forward<{anonymous}::Iterator_Fold_Test::TestBody()::<lambda(string,
char)>&>((* & __fn))), (* & std::forward<__cxx11::basic_string<char> >((* &
__args#0))), (* & std::forward<char>((* & __args#1))))’
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:35: in
‘constexpr’ expansion of ‘std::__cxx11::basic_string<char>((* &
std::forward<__cxx11::basic_string<char> >((* & __args#0))))’
/home/runner/work/subspace/subspace/sus/iter/iterator_unittest.cc:1792:24:
error: accessing ‘std::__cxx11::basic_string<char>::<unnamed
union>::_M_allocated_capacity’ member instead of initialized
‘std::__cxx11::basic_string<char>::<unnamed union>::_M_local_buf’ member in
constant expression
I don't have a great minimal repo atm, and I don't have a local machine that
uses libstdc++, but the Iterator.Fold unittest in iterator_unittest.cc is an
example that causes it here:
https://github.com/danakj/subspace/blob/experiment-iters/sus/iter/iterator_unittest.cc#L1787-L1792
With gcc-13:
git clone --recurse-submodules https://github.com/danakj/subspace
cd subspace
git checkout test origin/experiment-iters
CXX=path/to/gcc-13 cmake -B out -DSUBSPACE_BUILD_TESTS=ON
cmake --build out -j 20