Problem: If a struct has a member which is a multi-dimensionnal array of class with an explicit assignment operator, a trivial implicit operator is generated instead of a non trivial one. Code: // #include <stdio.h> class Manager { public: Manager (void); Manager (const Manager &); ~Manager (void); Manager &operator= (const Manager&); private: /// The underlying data int ptr_; static int Count ; }; typedef Manager ArrayString[2]; typedef ArrayString ArrayOfArrayString[2]; struct DataItem { ArrayOfArrayString field; }; int Manager::Count = 0 ; Manager::Manager (void) : ptr_ (0) { } Manager::Manager (const Manager &rhs) : ptr_ (rhs.ptr_ + 100) {} Manager::~Manager (void) { printf ("Destructor: Ptr %d\n", ptr_) ; } Manager& Manager::operator= (const Manager &rhs) { ptr_ = rhs.ptr_ + 1 ; Count++ ; printf ("Assignment %d\n", Count) ; return *this; } void Check (const DataItem & item) { DataItem item_1 ; DataItem item_2 ; item_1 = item ; item_2 = item ; } int main (int argc, char ** argv) { DataItem item ; Check (item) ; } Build line : g++ -O0 -g -o assign assign.cpp Output: Destructor: Ptr 0 Destructor: Ptr 0 Destructor: Ptr 0 Destructor: Ptr 0 Destructor: Ptr 0 Destructor: Ptr 0 Destructor: Ptr 0 Destructor: Ptr 0 Destructor: Ptr 0 Destructor: Ptr 0 Destructor: Ptr 0 Destructor: Ptr 0 Assigment operator of class Manager was never called. g++ -v Reading specs from /opt/gcc332/lib/gcc-lib/i686-pc-linux-gnu/3.3.2/specs Configured with: ./configure --prefix=/opt/gcc332 --enable-threads=posix --enable-languages=c,c++ Thread model: posix gcc version 3.3.2 and Reading specs from /usr/lib/gcc/i586-mandrake-linux-gnu/3.4.1/specs Configured with: ../configure --prefix=/usr --libdir=/usr/lib --with-slibdir=/lib --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --enable-long-long --enable-__cxa_atexit --enable-clocale=gnu --disable-libunwind-exceptions --enable-languages=c,c++,ada,f77,objc,java --host=i586-mandrake-linux-gnu --with-system-zlib Thread model: posix gcc version 3.4.1 (Mandrakelinux 10.1 3.4.1-4mdk)
Here's a slightly reduced testcase. =================================================== #include<stdio.h> struct A { A() : i() {} A (const A&); ~A() { printf ("Destructor: i = %d\n", i); } A& operator= (const A &a) { static int count=0; i = a.i + 1; printf ("Assignment %d\n", ++count); return *this; } int i; }; struct B { A x[2][2]; }; int main() { B b; b = b; } =================================================== With versions prior to gcc 3.3 we get the output Assignment 1 Assignment 2 Assignment 3 Assignment 4 Destructor: i = 1 Destructor: i = 1 Destructor: i = 1 Destructor: i = 1 With gcc 3.3 and later we get Destructor: i = 0 Destructor: i = 0 Destructor: i = 0 Destructor: i = 0
Confirmed. Btw, the relevant part of the standard is [class.copy]/13.
Here's an even shorter testcase. It should return 0, but doesn't since GCC 3.3. If I remove A's constructor, we get the failure since GCC 3.0. ====================================================== int n=4; struct A { A() {} A& operator= (const A&) { --n; return *this; } }; struct B { A x[2][2]; }; int main() { B b; b = b; return n; } ======================================================
Subject: Bug 20142 CVSROOT: /cvs/gcc Module name: gcc Changes by: mmitchel@gcc.gnu.org 2005-03-09 07:28:12 Modified files: gcc/testsuite : ChangeLog gcc/cp : ChangeLog cp-tree.h decl.c init.c name-lookup.c typeck.c Added files: gcc/testsuite/g++.dg/init: array18.C Log message: PR c++/20142 * cp-tree.h (target_type): Remove. * decl.c (layout_var_decl): Remove #if 0'd code. (cp_finish_decl): Remove dead code. * init.c (build_vec_init): When determining whether or not the element type has an asignment operator, look through all array dimensions. * typeck.c (target_type): Remove. PR c++/20142 * g++.dg/init/array18.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.5128&r2=1.5129 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/init/array18.C.diff?cvsroot=gcc&r1=1.1&r2=1.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4654&r2=1.4655 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/cp-tree.h.diff?cvsroot=gcc&r1=1.1107&r2=1.1108 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/decl.c.diff?cvsroot=gcc&r1=1.1374&r2=1.1375 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/init.c.diff?cvsroot=gcc&r1=1.413&r2=1.414 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/name-lookup.c.diff?cvsroot=gcc&r1=1.110&r2=1.111 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/typeck.c.diff?cvsroot=gcc&r1=1.617&r2=1.618
Subject: Bug 20142 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-4_0-branch Changes by: mmitchel@gcc.gnu.org 2005-03-09 07:32:31 Modified files: gcc/cp : init.c ChangeLog gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/init: array18.C Log message: PR c++/20142 * init.c (build_vec_init): When determining whether or not the element type has an asignment operator, look through all array dimensions. PR c++/20142 * g++.dg/init/array18.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/init.c.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.412.2.1&r2=1.412.2.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.4648.2.5&r2=1.4648.2.6 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.5084.2.26&r2=1.5084.2.27 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/init/array18.C.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=NONE&r2=1.2.2.1
Subject: Bug 20142 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: mmitchel@gcc.gnu.org 2005-03-09 07:39:35 Modified files: gcc/cp : init.c ChangeLog gcc/testsuite : ChangeLog Log message: PR c++/20142 * init.c (build_vec_init): When determining whether or not the element type has an asignment operator, look through all array dimensions. PR c++/20142 * g++.dg/init/array18.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/init.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.356.2.16&r2=1.356.2.17 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3892.2.204&r2=1.3892.2.205 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3389.2.369&r2=1.3389.2.370
Subject: Bug 20142 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: mmitchel@gcc.gnu.org 2005-03-09 07:39:48 Added files: gcc/testsuite/g++.dg/init: array18a.C Log message: PR c++/20142 * g++.dg/init/array18.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/init/array18a.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.2.1
Subject: Bug 20142 CVSROOT: /cvs/gcc Module name: gcc Changes by: mmitchel@gcc.gnu.org 2005-03-09 07:41:00 Modified files: gcc/testsuite : ChangeLog gcc/testsuite/g++.dg/init: array18.C Log message: PR c++/20142 * g++.dg/init/array18.C: Add dg-do run marker. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.5129&r2=1.5130 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/init/array18.C.diff?cvsroot=gcc&r1=1.2&r2=1.3
Fixed in GCC 3.4.4.
*** Bug 25735 has been marked as a duplicate of this bug. ***