public inbox for gcc-prs@sourceware.org
help / color / mirror / Atom feed
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	[thread overview]
Message-ID: <20010613142131.4125.qmail@sourceware.cygnus.com> (raw)

>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<iostream>
#include<stdio.h>
#include<cstdarg>

#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 "<<this<<"."<<std::endl;
}

base_t::base_t(const base_t &org) {
  std::cerr<<"\"base_t::Copyconstructor\" called. Constructing "<<this<<"."<<std::endl;
}

base_t::~base_t(void) {
  std::cerr<<"\"base_t::Destructor\" called. Destroying "<<this<<"."<<std::endl;
}

const int base_t::secret=42;

int ellipses(char *fmt, ...);

int ellipses(char *fmt, ...)
{
  std::cerr<<"\"ellipses()\": Function entered."<<std::endl;
  int retval;
  va_list arg;
  va_start(arg,fmt);
  base_t base
  #ifdef COPY
    =va_arg(arg,base_t)
  #else
    ; base=va_arg(arg,base_t)
  #endif
  ;
  retval=fprintf(stderr,"\"ellipses()\": Strange: %d.\n",base.secret);
  va_end(arg);
  std::cerr<<"\"ellipses()\": Function ending."<<std::endl;
  return retval;
}

int main() {
  base_t base;
  std::cerr<<"\"main()\": Secret is "<<base.secret<<"."<<std::endl;
  ellipses("",CAST base);
  std::cerr<<"\"main()\": Function call over."<<std::endl;
  return 0;
}


             reply	other threads:[~2001-06-13  7:26 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2001-06-13  7:26 philipp.bachmann [this message]
2001-06-13  9:16 Artem Khodush
2001-06-14 19:00 rodrigc

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20010613142131.4125.qmail@sourceware.cygnus.com \
    --to=philipp.bachmann@obtree.com \
    --cc=gcc-gnats@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).