Hello gcc-c++ team, I'm trying to build squid with new gcc-c++, and I'm getting following error: libtool: compile: g++ -DHAVE_CONFIG_H -I../.. -I../../include -I../../lib -I../../src -I../../include -I/usr/include/libxml2 -I/usr/include/libxml2 -Wall -Wpointer-arith -Wwrite-strings -Wcomments -Wshadow -Woverloaded-virtual -Werror -pipe -D_REENTRANT -O2 -g -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -mcet -fcf-protection -fPIC -c PoolChunked.cc -fPIC -DPIC -o PoolChunked.o >/dev/null 2>&1 In file included from ../../src/anyp/PortCfg.h:14, from ../../src/MasterXaction.h:13, from ../../src/CommCalls.h:16, from ../../src/comm.h:13, from ../../src/CommRead.h:15, from ../../src/Store.h:15, from old_api.cc:26: ../../src/anyp/TrafficMode.h: In member function 'AnyP::TrafficMode& AnyP::TrafficMode::operator=(const AnyP::TrafficMode&)': ../../src/anyp/TrafficMode.h:26:93: error: 'void* memcpy(void*, const void*, size_t)' writing to an object of type 'class AnyP::TrafficMode' with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Werror=class-memaccess] TrafficMode &operator =(const TrafficMode &rhs) { memcpy(this, &rhs, sizeof(TrafficMode)); return *this; } ^ In file included from ../../src/anyp/PortCfg.h:14, from ../../src/MasterXaction.h:13, from ../../src/CommCalls.h:16, from ../../src/comm.h:13, from ../../src/CommRead.h:15, from ../../src/Store.h:15, from old_api.cc:26: ../../src/anyp/TrafficMode.h:21:7: note: 'class AnyP::TrafficMode' declared here class TrafficMode ^~~~~~~~~~~ In file included from ../../src/comm/Connection.h:18, from ../../src/anyp/PortCfg.h:15, from ../../src/MasterXaction.h:13, from ../../src/CommCalls.h:16, from ../../src/comm.h:13, from ../../src/CommRead.h:15, from ../../src/Store.h:15, from old_api.cc:26: ../../src/eui/Eui64.h: In member function 'Eui::Eui64& Eui::Eui64::operator=(const Eui::Eui64&)': ../../src/eui/Eui64.h:40:70: error: 'void* memcpy(void*, const void*, size_t)' writing to an object of type 'class Eui::Eui64' with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Werror=class-memaccess] Eui64& operator= (const Eui64 &t) {memcpy(this, &t, sizeof(Eui64)); return *this;} ^ ../../src/eui/Eui64.h:34:7: note: 'class Eui::Eui64' declared here class Eui64 ^~~~~ cc1plus: all warnings being treated as errors I guess, in this case, warning should not be printed.
The warning is designed to allow raw memory access in ctors and dtors of non-trivial classes with no non-trivial bases or members, but the exemption doesn't extend to assignment operators of such classes. Some such types (including squid's TrafficMode class) use memcpy in the special functions as a shortcut to copy multiple trivial members without having to explicitly enumerate them. Since this is safe it makes sense to exempt the copy assignment operator as well. Confirmed with the test case below. $ cat pr84850.C && gcc -S -Wall pr84850.C struct S { bool a, b; S (); S (const S&); ~S (); void operator= (const S&); }; S::S () { __builtin_memset (this, 0, sizeof *this); } S::S (const S &s) { __builtin_memcpy (this, &s, sizeof s); } S::~S () { __builtin_memset (this, 0, sizeof *this); } void S::operator= (const S &s) { __builtin_memcpy (this, &s, sizeof s); } pr84850.C: In member function ‘void S::operator=(const S&)’: pr84850.C:27:39: warning: ‘void* __builtin_memcpy(void*, const void*, long unsigned int)’ writing to an object of type ‘struct S’ with no trivial copy-assignment; use copy-assignment or copy-initialization instead [-Wclass-memaccess] __builtin_memcpy (this, &s, sizeof s); ^ pr84850.C:1:8: note: ‘struct S’ declared here struct S ^
Bug 84851 shows that the exemption for copy ctors is overly simplistic and broad. Using the same mechanism for copy assignment would not be appropriate because it would compromise the warning and prevent it from detecting some undefined cases. Adding an exemption for copy assignment will require checking all bases and members to make sure they are trivial. That makes the solution for this bug dependent on pr84851.
But this one is a regression while PR84851 is an improvement request.
I have a patch that handles both pr84851 and pr84850. I don't view this report as a regression any more than the other PR. The warning does what it was designed to do. It was just designed to be strict in this case and overly permissive in the other.
So just handle this PR now (warning less; handle copy assignment ops like copy ctors) and deal with the rest (warning more) for stage1.
Patch: https://gcc.gnu.org/ml/gcc-patches/2018-03/msg00915.html
Author: msebor Date: Wed Mar 21 15:14:02 2018 New Revision: 258719 URL: https://gcc.gnu.org/viewcvs?rev=258719&root=gcc&view=rev Log: PR c++/84850 - -Wclass-memaccess on a memcpy in a copy assignment operator with no nontrivial bases or members gcc/cp/ChangeLog: PR c++/84850 * call.c (first_non_public_field): New template and function. (first_non_trivial_field): New function. (maybe_warn_class_memaccess): Call them. gcc/testsuite/ChangeLog: PR c++/84850 * g++.dg/Wclass-memaccess-3.C: New test. * g++.dg/Wclass-memaccess-4.C: New test. Added: trunk/gcc/testsuite/g++.dg/Wclass-memaccess-3.C trunk/gcc/testsuite/g++.dg/Wclass-memaccess-4.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c trunk/gcc/testsuite/ChangeLog
Patch committed in r258719 with the fix for bug 84851 present but disabled. It will be enabled in stage 1 of GCC 9.