Article View: gnu.g++.bug
Article #1099Fix for G++ 2.3.1 copy constructor bug
From: Chip Salzenberg
Date: Fri, 06 Nov 1992 09:00
Date: Fri, 06 Nov 1992 09:00
385 lines
11942 bytes
11942 bytes
G++ 2.3.1, when creating default copy constructors, fails to call the
copy constructors of base classes and member objects. The below patch
fixes this omission.
This patch has been tested on a fairly large application. However, it
has not been tested with virtual inheritance, which we do not use.
=======================================================================
Thu Nov 5 12:23:37 1992 Chip Salzenberg (chip@tct.com)
* cp-class.c (needs_const_ctor): Eliminate as meaningless.
(finish_struct) Always generate default functions.
Generate exactly one copy constructor: either "X(X&)" or
"X(const X&)", but not both.
* cp-lex.c (cons_up_default_function): Take list of fields
as a new parameter. Use default_copy_constructor_body.
Set TREE_PUBLIC and DECL_EXTERNAL correctly for usage with
#pragma interface.
(default_copy_constructor_body): New function.
Index: cp-class.c
*************** struct base_info
*** 1429,1433 ****
char needs_default_ctor;
char cant_have_default_ctor;
- char needs_const_ctor;
char cant_have_const_ctor;
char members_need_dtors;
--- 1429,1432 ----
*************** finish_base_struct (t, b, binfos)
*** 1496,1502 ****
else if (TYPE_HAS_CONSTRUCTOR (basetype))
b->cant_have_default_ctor = 1;
! if (TYPE_GETS_CONST_INIT_REF (basetype))
! b->needs_const_ctor = 1;
! else if (TYPE_GETS_INIT_REF (basetype))
b->cant_have_const_ctor = 1;
--- 1495,1500 ----
else if (TYPE_HAS_CONSTRUCTOR (basetype))
b->cant_have_default_ctor = 1;
! if (TYPE_GETS_INIT_REF (basetype)
! && !TYPE_GETS_CONST_INIT_REF (basetype))
b->cant_have_const_ctor = 1;
*************** finish_struct (t, list_of_fieldlists, em
*** 2179,2185 ****
int old;
int round_up_size = 1;
- /* Set non-zero to debug using default functions.
- Not set by program. */
- static int debug_default_functions = 0;
enum tree_code code = TREE_CODE (t);
--- 2177,2180 ----
*************** finish_struct (t, list_of_fieldlists, em
*** 2198,2202 ****
int needs_default_ctor;
int cant_have_default_ctor;
- int needs_const_ctor;
int cant_have_const_ctor;
--- 2193,2196 ----
*************** finish_struct (t, list_of_fieldlists, em
*** 2295,2299 ****
needs_default_ctor = base_info.needs_default_ctor;
cant_have_default_ctor = base_info.cant_have_default_ctor;
- needs_const_ctor = base_info.needs_const_ctor;
cant_have_const_ctor = base_info.cant_have_const_ctor;
members_need_dtors = base_info.members_need_dtors;
--- 2289,2292 ----
*************** finish_struct (t, list_of_fieldlists, em
*** 2312,2316 ****
needs_default_ctor = 0;
cant_have_default_ctor = 0;
- needs_const_ctor = 0;
cant_have_const_ctor = 0;
members_need_dtors = 0;
--- 2305,2308 ----
*************** finish_struct (t, list_of_fieldlists, em
*** 2507,2513 ****
if (TYPE_HAS_DEFAULT_CONSTRUCTOR (TREE_TYPE (x)))
needs_default_ctor = 1;
! if (TYPE_GETS_CONST_INIT_REF (TREE_TYPE (x)))
! needs_const_ctor = 1;
! else if (TYPE_GETS_INIT_REF (TREE_TYPE (x)))
cant_have_const_ctor = 1;
}
--- 2499,2504 ----
if (TYPE_HAS_DEFAULT_CONSTRUCTOR (TREE_TYPE (x)))
needs_default_ctor = 1;
! if (TYPE_GETS_INIT_REF (TREE_TYPE (x))
! && !TYPE_GETS_CONST_INIT_REF (TREE_TYPE (x)))
cant_have_const_ctor = 1;
}
*************** finish_struct (t, list_of_fieldlists, em
*** 2692,2696 ****
{
/* Here we must cons up a destructor on the fly. */
! tree dtor = cons_up_default_function (t, name,
needs_virtual_dtor != 0);
--- 2683,2687 ----
{
/* Here we must cons up a destructor on the fly. */
! tree dtor = cons_up_default_function (t, name, fields,
needs_virtual_dtor != 0);
*************** finish_struct (t, list_of_fieldlists, em
*** 2718,2745 ****
}
! if (debug_default_functions)
{
! if ((TYPE_NEEDS_CONSTRUCTOR (t) || TYPE_HAS_CONSTRUCTOR (t) || needs_ctor)
! && ! TYPE_HAS_INIT_REF (t))
! {
! tree default_fn = cons_up_default_function (t, name, 4);
! TREE_CHAIN (default_fn) = fn_fields;
! fn_fields = default_fn;
! TYPE_HAS_INIT_REF (t) = 1;
! default_fn = cons_up_default_function (t, name, 3);
! TREE_CHAIN (default_fn) = fn_fields;
! fn_fields = default_fn;
! nonprivate_method = 1;
! }
! if (! TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
! && needs_default_ctor && ! cant_have_default_ctor)
! {
! tree default_fn = cons_up_default_function (t, name, 2);
! TREE_CHAIN (default_fn) = fn_fields;
! fn_fields = default_fn;
! TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
! nonprivate_method = 1;
! }
}
--- 2709,2738 ----
}
! /* Create default constructor, if needed. */
!
! if (! TYPE_HAS_DEFAULT_CONSTRUCTOR (t)
! && needs_default_ctor && ! cant_have_default_ctor)
{
! tree default_fn = cons_up_default_function (t, name, fields, 2);
! TREE_CHAIN (default_fn) = fn_fields;
! fn_fields = default_fn;
! TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 1;
! nonprivate_method = 1;
! }
! /* Create default copy constructor, if needed. */
!
! if ((TYPE_NEEDS_CONSTRUCTOR (t) || TYPE_HAS_CONSTRUCTOR (t) || needs_ctor)
! && ! TYPE_HAS_INIT_REF (t))
! {
! /* ARM 12.18: You get either X(X&) or X(const X&), but
! not both. --Chip */
! tree default_fn =
! cons_up_default_function (t, name, fields,
! cant_have_const_ctor ? 4 : 3);
! TREE_CHAIN (default_fn) = fn_fields;
! fn_fields = default_fn;
! TYPE_HAS_INIT_REF (t) = 1;
! nonprivate_method = 1;
}
Index: cp-lex.c
*************** extern int *token_count;
*** 125,129 ****
/* Textual definition used for default functions. */
! static char default_def[] = "{}";
/* Return something to represent absolute declarators containing a *.
--- 125,129 ----
/* Textual definition used for default functions. */
! static void default_copy_constructor_body ();
/* Return something to represent absolute declarators containing a *.
*************** reinit_parse_for_block (yychar, obstackp
*** 1443,1452 ****
tree
! cons_up_default_function (type, name, kind)
! tree type, name;
int kind;
{
extern tree void_list_node, constructor_name ();
! int len;
tree declspecs = NULL_TREE;
tree fn, args;
--- 1443,1453 ----
tree
! cons_up_default_function (type, name, fields, kind)
! tree type, name, fields;
int kind;
{
extern tree void_list_node, constructor_name ();
! char *def_buf = "{}";
! int def_len = 2;
tree declspecs = NULL_TREE;
tree fn, args;
*************** cons_up_default_function (type, name, ki
*** 1475,1480 ****
args = tree_cons (NULL_TREE,
build_tree_list (hash_tree_chain (argtype, NULL_TREE),
! get_identifier ("arg")),
void_list_node);
break;
--- 1476,1482 ----
args = tree_cons (NULL_TREE,
build_tree_list (hash_tree_chain (argtype, NULL_TREE),
! get_identifier ("_ctor_arg")),
void_list_node);
+ default_copy_constructor_body (&def_buf, &def_len, type, fields);
break;
*************** cons_up_default_function (type, name, ki
*** 1492,1497 ****
current_member_init_list = NULL_TREE;
- len = 3;
-
{
struct pending_inline *t;
--- 1494,1497 ----
*************** cons_up_default_function (type, name, ki
*** 1499,1504 ****
t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
sizeof (struct pending_inline));
! t->buf = default_def;
! t->len = len;
t->lineno = lineno;
t->filename = input_filename;
--- 1499,1504 ----
t = (struct pending_inline *) obstack_alloc (&inline_text_obstack,
sizeof (struct pending_inline));
! t->buf = def_buf;
! t->len = def_len + 1;
t->lineno = lineno;
t->filename = input_filename;
*************** cons_up_default_function (type, name, ki
*** 1510,1515 ****
: (interface_only ? 0 : 2));
store_pending_inline (fn, t);
! /* We make this declaration private (static in the C sense). */
! TREE_PUBLIC (fn) = 0;
}
finish_method (fn);
--- 1510,1520 ----
: (interface_only ? 0 : 2));
store_pending_inline (fn, t);
! if (interface_unknown)
! TREE_PUBLIC (fn) = 0;
! else
! {
! TREE_PUBLIC (fn) = 1;
! DECL_EXTERNAL (fn) = interface_only;
! }
}
finish_method (fn);
*************** cons_up_default_function (type, name, ki
*** 1518,1521 ****
--- 1523,1633 ----
DECL_SOURCE_LINE (fn) = 0;
return fn;
+ }
+
+ /* Construct the body of a default copy constructor. */
+ static void
+ default_copy_constructor_body(bufp, lenp, type, fields)
+ char **bufp;
+ int *lenp;
+ tree type, fields;
+ {
+ char *buf;
+ int alloc, len;
+ int n_bases = 0;
+ char sep = ':';
+
+ if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type))
+ n_bases = CLASSTYPE_N_BASECLASSES (type);
+
+ buf = xmalloc (alloc = 100);
+ len = 0;
+
+ /* Call base class constructors. */
+
+ if (n_bases)
+ {
+ int i;
+
+ for (i = 0; i < n_bases; ++i)
+ {
+ tree base = TYPE_BINFO_BASETYPE (type, i);
+
+ if (TYPE_HAS_CONSTRUCTOR (base))
+ {
+ char *basename =
+ IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (base)));
+
+ while (len + strlen(basename) + 30 > alloc)
+ buf = xrealloc (buf, alloc *= 2);
+
+ buf[len++] = sep;
+ sep = ',';
+
+ sprintf (buf + len, "%s(_ctor_arg)", basename);
+ len += strlen (buf + len);
+ }
+ }
+ }
+
+ /* Construct fields. */
+
+ if (fields)
+ {
+ tree f;
+
+ for (f = fields; f; f = TREE_CHAIN (f))
+ {
+ if (TREE_CODE (f) == FIELD_DECL && DECL_NAME (f))
+ {
+ char *fieldname = IDENTIFIER_POINTER (DECL_NAME (f));
+
+ while (len + (strlen (fieldname) * 2) + 30 > alloc)
+ buf = xrealloc (buf, alloc *= 2);
+
+ buf[len++] = sep;
+ sep = ',';
+
+ sprintf (buf + len, "%s(_ctor_arg.%s)", fieldname, fieldname);
+ len += strlen(buf + len);
+ }
+ }
+ }
+
+ /* Begin constructor body. */
+
+ buf[len++] = '{';
+
+ /* Copy members of base classes without constructors. */
+
+ if (n_bases)
+ {
+ int i;
+
+ for (i = 0; i < n_bases; ++i)
+ {
+ tree base = TYPE_BINFO_BASETYPE (type, i);
+
+ if (!TYPE_HAS_CONSTRUCTOR (base))
+ {
+ char *basename =
+ IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (base)));
+
+ while (len + (strlen(basename) * 2) + 30 > alloc)
+ buf = xrealloc (buf, alloc *= 2);
+
+ sprintf (buf + len, "*(%s*)this=(%s&)_ctor_arg;",
+ basename, basename);
+ len += strlen (buf + len);
+ }
+ }
+ }
+
+ /* End constructor body. */
+
+ buf[len++] = '}';
+ buf[len] = '\0';
+
+ *bufp = buf;
+ *lenp = len;
}
--
Chip Salzenberg at Teltronics/TCT <chip@tct.com>, <73717.366@compuserve.com>
Technical Details
Message-ID:
<m0mnYun-0000XGC@animal.tct.com>Path:
arc1-ca.pugleaf.net!sparky!uunet!charon.amdahl.com!pacbell.com!sgiblab!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!tct.COM!chipShow Full Headers
Complete Article Headers
Newsgroups: gnu.g++.bug Path: arc1-ca.pugleaf.net!sparky!uunet!charon.amdahl.com!pacbell.com!sgiblab!zaphod.mps.ohio-state.edu!cis.ohio-state.edu!tct.COM!chip From: chip@tct.COM (Chip Salzenberg) Subject: Fix for G++ 2.3.1 copy constructor bug Message-ID: <m0mnYun-0000XGC@animal.tct.com> Sender: gnulists@ai.mit.edu Organization: GNUs Not Usenet Distribution: gnu Date: Fri, 6 Nov 1992 09:00:16 GMT Approved: bug-g++@prep.ai.mit.edu Lines: 386