From mboxrd@z Thu Jan 1 00:00:00 1970 From: philipp.bachmann@obtree.com To: gcc-gnats@gcc.gnu.org Subject: c++/3167: Copyconstructor not called when entering function (var args) Date: Wed, 13 Jun 2001 07:26:00 -0000 Message-id: <20010613142131.4125.qmail@sourceware.cygnus.com> X-SW-Source: 2001-06/msg00559.html List-Id: >Number: 3167 >Category: c++ >Synopsis: Copyconstructor not called when entering function (var args) >Confidential: no >Severity: serious >Priority: medium >Responsible: unassigned >State: open >Class: sw-bug >Submitter-Id: net >Arrival-Date: Wed Jun 13 07:26:01 PDT 2001 >Closed-Date: >Last-Modified: >Originator: Philipp Bachmann >Release: g++ 2.95.3 >Organization: >Environment: Sun Solaris 7 SPARC >Description: The code provided compiles successfully with the warnings: [583]$ g++ copyconstr2.c++ copyconstr2.c++: In function `int ellipses(char *, ...)': copyconstr2.c++:70: warning: cannot pass objects of type `base_t' through `...' copyconstr2.c++:70: warning: cannot pass objects of type `base_t' through `...' copyconstr2.c++: In function `int main()': copyconstr2.c++:84: warning: cannot pass objects of type `base_t' through `...' (These warnings are issued only if "base_t" explicitly has a copy constructor defined.) If the code is run, the following happens: [584]$ ./a.out "base_t::Constructor" called. Constructing 0xffbef2f0. "main()": Secret is 42. "ellipses()": Function entered. "base_t::Copyconstructor" called. Constructing 0xffbef260. "ellipses()": Strange: 42. "ellipses()": Function ending. "base_t::Destructor" called. Destroying 0xffbef260. "main()": Function call over. "base_t::Destructor" called. Destroying 0xffbef2f0. If I understand, what's behind the scene, when calling a function, correctly, then I expect a call to the copy constructor on entering the function, i.e. I would expect the hypothetical output [584]$ ./a.out "base_t::Constructor" called. Constructing 0xffbef2f0. "main()": Secret is 42. "base_t::Copyconstructor" called. Constructing 0xfoo. "ellipses()": Function entered. "base_t::Copyconstructor" called. Constructing 0xffbef260. "ellipses()": Strange: 42. "ellipses()": Function ending. "base_t::Destructor" called. Destroying 0xffbef260. "base_t::Destructor" called. Destroying 0xfoo. "main()": Function call over. "base_t::Destructor" called. Destroying 0xffbef2f0. There is no reason in my opinion, why the compiler needs any information about the argument types of the _function_ called (because there is a variable argument list, there is indeed no such information on all arguments but the first one) to call the copy constructor to put a copy of "base" onto the stack - the only information, the compiler needs to have (and it has, because "base" is defined as "base_t" two lines before the call to the "ellipses()" function) for calling the copy constructor is the type of "base". The call to the copyconstructor that can be seen, though, results from the initialization of local variable "base" inside of the function "ellipses()" and can easily be switched off by undefining "COPY". This is correct behaviour. I've compared g++'s behaviour with the one of Sun CC 6 Update 1 (unpatched). Sun's compiler calls the copyconstructor when entering the function, but has another bug: It never destoys the space constructed... >How-To-Repeat: [583]$ g++ copyconstr2.c++ [584]$ ./a.out >Fix: >Release-Note: >Audit-Trail: >Unformatted: ----gnatsweb-attachment---- Content-Type: text/plain; name="copyconstr2.c++.txt" Content-Disposition: inline; filename="copyconstr2.c++.txt" /* Very simple program to show two bugs in two different compilers: Sun Forte 6 Update 1 (unpatched) calls "base_t::base_t(const base_t &)" on calling "ellipses("",CAST base)" even if "CAST" is replaced by nothing - but will never call "base_t::~base_t(void)" to destroy the copyconstructed formal parameter; if "CAST" is defined to be "(base_t)", then "base_t::base_t(const base_t &)" is called twice, but "base_t::~base_t(void)" is called only once to destroy the temporary instance resulting from the cast operation. GNU g++ 2.95.3, however, only calles "base_t::base_t(const base_t &)", "on" entering the function, if the argument "base" in the function call is explicitly casted to its own type; expected behaviour was to always cast the copyconstructor at least once on entering the function. */ /* $Log: copyconstr2.c++,v $ * Revision 1.2 2001/06/13 14:55:15 bachlipp * Introduced "COPY" #define. Slightly presiced comment on * g++ behaviour. * * Revision 1.1 2001/06/13 10:34:26 bachlipp * Initial revision * */ static const char rcsid[]="@@(#)$Id: copyconstr2.c++,v 1.2 2001/06/13 14:55:15 bachlipp Exp $"; #include #include #include #define CAST // #define CAST (base_t) #define COPY class base_t { public : base_t(void); base_t(const base_t &); virtual ~base_t(void); static const int secret; }; base_t::base_t(void) { std::cerr<<"\"base_t::Constructor\" called. Constructing "<