https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104855
Bug ID: 104855 Summary: -Wclass-memaccess is too broad with valid code Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: soap at gentoo dot org Target Milestone: --- Given the following snippet: #include <cassert> #include <cstring> #include <type_traits> struct A { A() = default; A(unsigned a, unsigned b) : data_(a + b) {} private: unsigned data_; }; static_assert(std::is_trivial_v<A>, ""); static_assert(std::is_trivially_copyable_v<A>, ""); A foo(unsigned x) { A result; std::memcpy(&result, &x, sizeof(x)); return result; } with GCC 11 and -Wall, I get the following warning example.cpp: In function ‘A foo(unsigned int)’: example.cpp:20:16: warning: ‘void* memcpy(void*, const void*, size_t)’ copying an object of type ‘struct A’ with ‘private’ member ‘A::data_’ from an array of ‘unsigned int’; use assignment or copy-initialization instead [-Wclass-memaccess] 20 | std::memcpy(&result, &x, sizeof(x)); | ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~ example.cpp:5:8: note: ‘struct A’ declared here 5 | struct A | ^ which seems overbroad given that the code is 100% valid. I have asked Martin Sebor, and his reason for this warning is > about it breaking encapsulation by modifying a private data member. > In the test case the modification might violate the invariant that > the class represent the sum of the arguments it's constructed with. which I understand, but I still consider this warning too broad for valid code, especially because the suggested workaround is to cast the &result to a void*, which involves reinterpret_cast and will raise eyebrows. Clang doesn't do this, and I think it's right on this one.