I have this snippet of code (lets name it problem.cpp
):
#include <string>
using str = std::wstring;
static str foo(str text = str())
{
text.resize(4);
return text;
}
int main()
{
str a = foo();
return 0;
}
GCC (version 12.2.1) called with -O1
and C++20 conformity (g++ problem.cpp -Werror -O1 -std=c++20
) leads to this error:
In file included from /usr/include/features.h:490,
from /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/x86_64-pc-linux-gnu/bits/os_defines.h:39,
from /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/x86_64-pc-linux-gnu/bits/c++config.h:655,
from /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/string:38,
from problem.cpp:1:
In function ‘wchar_t* wmemcpy(wchar_t*, const wchar_t*, size_t)’,
inlined from ‘static constexpr std::char_traits<wchar_t>::char_type* std::char_traits<wchar_t>::copy(char_type*, const char_type*, std::size_t)’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/bits/char_traits.h:558:16,
inlined from ‘constexpr std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&&) [with _CharT = wchar_t; _Traits = std::char_traits<wchar_t>; _Alloc = std::allocator<wchar_t>]’ at /usr/lib/gcc/x86_64-pc-linux-gnu/12/include/g++-v12/bits/basic_string.h:675:23,
inlined from ‘str foo(str)’ at problem.cpp:7:9,
inlined from ‘int main()’ at problem.cpp:12:14:
/usr/include/bits/wchar2.h:39:10: error: call to ‘__wmemcpy_chk_warn’ declared with attribute warning: wmemcpy called with length bigger than size of destination buffer [-Werror=attribute-warning]
39 | return __glibc_fortify_n (wmemcpy, __n, sizeof (wchar_t),
| ^~~~~~~~~~~~~~~~~
cc1plus: all warnings being treated as errors
Interestingly, I cannot trigger this error, either by using std::string
(in contrast to std::wstring
), using lower resize values, or anything below C++20 or O1
.
To me, this snippet of code does not look suspicious. Unfortunately, I can't reproduce this with Godbolt. Maybe Godbolt uses another and/or not fortified glibc version? I'm using glibc version 2.36 on Gentoo Linux, but I have seen this on Ubuntu as well. However, before I suspect a bug in glibc or the compiler, I'm reaching out here, if this is in fact a false positive.
Any ideas?
EDIT: In the meantime, I could reproduce a similar error using Godbolt: https://godbolt.org/z/joPaYKK11
This is a bug in the libstdc++
.
The developers reacted very quickly and fixed the problem for 12.3.
Thanks to srohmen, KamilCuk and user17732522 for the helpful discussion in question and comments above!
The warning came from a branch of code that is never executed in the case that triggered the warning. The fix is to tell the compiler this by inserting __builtin_unreachable()
.
C++23 introduces std::unreachable
which also has the task to tell the compiler that this branch in the code will never be executed. Note that it is not necessarily equivalent to GCC's __builtin_unreachable()
, since std::unreachable
only guarantees undefined behavior! In practice you have to test whether std::unreachable
solves a concrete problem or whether you have to fall back on a compiler-specific well-defined builtin.