Commit fd74ca0b by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (struct language_function): Remove x_base_init_list and x_member_init_list.

	* cp-tree.h (struct language_function): Remove x_base_init_list
	and x_member_init_list.
	(current_base_init_list): Remove.
	(current_member_init_list): Likewise.
	(setup_vtbl_ptr): Change prototype.
	(emit_base_init): Likewise.
	(expand_member_init): Likewise.
	(reinit_parse_for_function): Remove.
	* decl.c (save_function_data): Don't clear x_base_init_list and
	x_member_init_list.
	(mark_language_function): Don't mark them.
	* init.c (perform_member_init): Tweak comment.
	(sort_member_init): Take the list of initializers as an argument.
	(sort_base_init): Likewise.
	(emit_base_init): Likewise.
	(expand_member_init): Return the initializer.  Don't use global
	variables.
	* lex.c (reinit_parse_for_function): Remove.
	* method.c (build_template_parm_names): Correct substitution.
	(do_build_copy_constructor): Don't use current_member_init_list
	and current_base_init_list.
	(synthesize_method): Likewise.
	* parse.y (base_init): Split mem-initializers into
	base-initializers and field-initializers.
	(member_init_list): Build up the list here.
	(member_init): Return the initializer.
	(fn.depfn): Don't use reinit_parse_for_function.
	* parse.c: Regenerated.
	* pt.c (convert_nontype_argument): Don't make an ADDR_EXPR of the
	ERROR_MARK.
	(tsubst_expr): Don't use current_member_init_list
	and current_base_init_list.
	(tsubst_expr_values): Rename to ...
	(tsubst_initializer_list): ... this.  Use convert_from_reference.
	* semantics.c (setup_vtbl_ptr): Don't use current_member_init_list
	and current_base_init_list.
	(begin_function_definition): Don't call reinit_parse_for_function.

	* dump.c (dequeue_and_dump): Use TREE_VEC_LENGTH with vectors.

	* error.c (dump_expr): Handle ADDR_EXPRs with REFERENCE_TYPE
	correctly.

From-SVN: r34571
parent ff1c0096
...@@ -12,6 +12,49 @@ ...@@ -12,6 +12,49 @@
2000-06-15 Mark Mitchell <mark@codesourcery.com> 2000-06-15 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (struct language_function): Remove x_base_init_list
and x_member_init_list.
(current_base_init_list): Remove.
(current_member_init_list): Likewise.
(setup_vtbl_ptr): Change prototype.
(emit_base_init): Likewise.
(expand_member_init): Likewise.
(reinit_parse_for_function): Remove.
* decl.c (save_function_data): Don't clear x_base_init_list and
x_member_init_list.
(mark_language_function): Don't mark them.
* init.c (perform_member_init): Tweak comment.
(sort_member_init): Take the list of initializers as an argument.
(sort_base_init): Likewise.
(emit_base_init): Likewise.
(expand_member_init): Return the initializer. Don't use global
variables.
* lex.c (reinit_parse_for_function): Remove.
* method.c (build_template_parm_names): Correct substitution.
(do_build_copy_constructor): Don't use current_member_init_list
and current_base_init_list.
(synthesize_method): Likewise.
* parse.y (base_init): Split mem-initializers into
base-initializers and field-initializers.
(member_init_list): Build up the list here.
(member_init): Return the initializer.
(fn.depfn): Don't use reinit_parse_for_function.
* parse.c: Regenerated.
* pt.c (convert_nontype_argument): Don't make an ADDR_EXPR of the
ERROR_MARK.
(tsubst_expr): Don't use current_member_init_list
and current_base_init_list.
(tsubst_expr_values): Rename to ...
(tsubst_initializer_list): ... this. Use convert_from_reference.
* semantics.c (setup_vtbl_ptr): Don't use current_member_init_list
and current_base_init_list.
(begin_function_definition): Don't call reinit_parse_for_function.
* dump.c (dequeue_and_dump): Use TREE_VEC_LENGTH with vectors.
* error.c (dump_expr): Handle ADDR_EXPRs with REFERENCE_TYPE
correctly.
* cp-tree.h (DECL_PENDING_INLINE_P): Relax checking. * cp-tree.h (DECL_PENDING_INLINE_P): Relax checking.
2000-06-14 Benjamin Chelf <chelf@cabriolet.stanford.edu> 2000-06-14 Benjamin Chelf <chelf@cabriolet.stanford.edu>
......
...@@ -883,8 +883,6 @@ struct language_function ...@@ -883,8 +883,6 @@ struct language_function
{ {
tree x_ctor_label; tree x_ctor_label;
tree x_dtor_label; tree x_dtor_label;
tree x_base_init_list;
tree x_member_init_list;
tree x_current_class_ptr; tree x_current_class_ptr;
tree x_current_class_ref; tree x_current_class_ref;
tree x_eh_spec_try_block; tree x_eh_spec_try_block;
...@@ -927,19 +925,6 @@ struct language_function ...@@ -927,19 +925,6 @@ struct language_function
#define ctor_label cp_function_chain->x_ctor_label #define ctor_label cp_function_chain->x_ctor_label
/* In C++, structures with well-defined constructors are initialized by
those constructors, unasked. CURRENT_BASE_INIT_LIST
holds a list of stmts for a BASE_INIT term in the grammar.
This list has one element for each base class which must be
initialized. The list elements are [basename, init], with
type basetype. This allows the possibly anachronistic form
(assuming d : a, b, c) "d (int a) : c(a+5), b (a-4), a (a+3)"
where each successive term can be handed down the constructor
line. Perhaps this was not intended. */
#define current_base_init_list cp_function_chain->x_base_init_list
#define current_member_init_list cp_function_chain->x_member_init_list
/* When we're processing a member function, current_class_ptr is the /* When we're processing a member function, current_class_ptr is the
PARM_DECL for the `this' pointer. The current_class_ref is an PARM_DECL for the `this' pointer. The current_class_ref is an
expression for `*this'. */ expression for `*this'. */
...@@ -4082,7 +4067,7 @@ extern int copy_assignment_arg_p PARAMS ((tree, int)); ...@@ -4082,7 +4067,7 @@ extern int copy_assignment_arg_p PARAMS ((tree, int));
extern void cplus_decl_attributes PARAMS ((tree, tree, tree)); extern void cplus_decl_attributes PARAMS ((tree, tree, tree));
extern tree constructor_name_full PARAMS ((tree)); extern tree constructor_name_full PARAMS ((tree));
extern tree constructor_name PARAMS ((tree)); extern tree constructor_name PARAMS ((tree));
extern void setup_vtbl_ptr PARAMS ((void)); extern void setup_vtbl_ptr PARAMS ((tree, tree));
extern void defer_fn PARAMS ((tree)); extern void defer_fn PARAMS ((tree));
extern tree get_temp_name PARAMS ((tree, int)); extern tree get_temp_name PARAMS ((tree, int));
extern void finish_anon_union PARAMS ((tree)); extern void finish_anon_union PARAMS ((tree));
...@@ -4174,8 +4159,8 @@ extern tree do_friend PARAMS ((tree, tree, tree, tree, tree, enum overload_fl ...@@ -4174,8 +4159,8 @@ extern tree do_friend PARAMS ((tree, tree, tree, tree, tree, enum overload_fl
/* in init.c */ /* in init.c */
extern void init_init_processing PARAMS ((void)); extern void init_init_processing PARAMS ((void));
extern void emit_base_init PARAMS ((void)); extern void emit_base_init PARAMS ((tree, tree));
extern void expand_member_init PARAMS ((tree, tree, tree)); extern tree expand_member_init PARAMS ((tree, tree, tree));
extern tree build_aggr_init PARAMS ((tree, tree, int)); extern tree build_aggr_init PARAMS ((tree, tree, int));
extern int is_aggr_type PARAMS ((tree, int)); extern int is_aggr_type PARAMS ((tree, int));
extern tree get_aggr_from_typedef PARAMS ((tree, int)); extern tree get_aggr_from_typedef PARAMS ((tree, int));
...@@ -4209,7 +4194,6 @@ extern void lang_finish PARAMS ((void)); ...@@ -4209,7 +4194,6 @@ extern void lang_finish PARAMS ((void));
#if 0 #if 0
extern void reinit_lang_specific PARAMS ((void)); extern void reinit_lang_specific PARAMS ((void));
#endif #endif
extern void reinit_parse_for_function PARAMS ((void));
extern void print_parse_statistics PARAMS ((void)); extern void print_parse_statistics PARAMS ((void));
extern void extract_interface_info PARAMS ((void)); extern void extract_interface_info PARAMS ((void));
extern void do_pending_inlines PARAMS ((void)); extern void do_pending_inlines PARAMS ((void));
......
...@@ -14090,8 +14090,6 @@ save_function_data (decl) ...@@ -14090,8 +14090,6 @@ save_function_data (decl)
DECL_SAVED_FUNCTION_DATA (decl) = f; DECL_SAVED_FUNCTION_DATA (decl) = f;
/* Clear out the bits we don't need. */ /* Clear out the bits we don't need. */
f->x_base_init_list = NULL_TREE;
f->x_member_init_list = NULL_TREE;
f->x_stmt_tree.x_last_stmt = NULL_TREE; f->x_stmt_tree.x_last_stmt = NULL_TREE;
f->x_stmt_tree.x_last_expr_type = NULL_TREE; f->x_stmt_tree.x_last_expr_type = NULL_TREE;
f->x_result_rtx = NULL_RTX; f->x_result_rtx = NULL_RTX;
...@@ -14972,8 +14970,6 @@ mark_lang_function (p) ...@@ -14972,8 +14970,6 @@ mark_lang_function (p)
ggc_mark_tree (p->x_ctor_label); ggc_mark_tree (p->x_ctor_label);
ggc_mark_tree (p->x_dtor_label); ggc_mark_tree (p->x_dtor_label);
ggc_mark_tree (p->x_base_init_list);
ggc_mark_tree (p->x_member_init_list);
ggc_mark_tree (p->x_current_class_ptr); ggc_mark_tree (p->x_current_class_ptr);
ggc_mark_tree (p->x_current_class_ref); ggc_mark_tree (p->x_current_class_ref);
ggc_mark_tree (p->x_eh_spec_try_block); ggc_mark_tree (p->x_eh_spec_try_block);
......
...@@ -454,7 +454,7 @@ dequeue_and_dump (di) ...@@ -454,7 +454,7 @@ dequeue_and_dump (di)
break; break;
case TREE_VEC: case TREE_VEC:
dump_int (di, "lngt", IDENTIFIER_LENGTH (t)); dump_int (di, "lngt", TREE_VEC_LENGTH (t));
for (i = 0; i < TREE_VEC_LENGTH (t); ++i) for (i = 0; i < TREE_VEC_LENGTH (t); ++i)
{ {
char buffer[32]; char buffer[32];
......
...@@ -1741,7 +1741,12 @@ dump_expr (t, flags) ...@@ -1741,7 +1741,12 @@ dump_expr (t, flags)
case ADDR_EXPR: case ADDR_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
|| TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST) || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST
/* An ADDR_EXPR can have reference type. In that case, we
shouldn't print the `&' doing so indicates to the user
that the expression has pointer type. */
|| (TREE_TYPE (t)
&& TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE))
dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS); dump_expr (TREE_OPERAND (t, 0), flags | TS_EXPR_PARENS);
else else
dump_unary_op ("&", t, flags); dump_unary_op ("&", t, flags);
......
...@@ -40,11 +40,11 @@ static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int)); ...@@ -40,11 +40,11 @@ static void expand_aggr_init_1 PARAMS ((tree, tree, tree, tree, int));
static void expand_default_init PARAMS ((tree, tree, tree, tree, int)); static void expand_default_init PARAMS ((tree, tree, tree, tree, int));
static tree build_vec_delete_1 PARAMS ((tree, tree, tree, special_function_kind, int)); static tree build_vec_delete_1 PARAMS ((tree, tree, tree, special_function_kind, int));
static void perform_member_init PARAMS ((tree, tree, int)); static void perform_member_init PARAMS ((tree, tree, int));
static void sort_base_init PARAMS ((tree, tree *, tree *)); static void sort_base_init PARAMS ((tree, tree, tree *, tree *));
static tree build_builtin_delete_call PARAMS ((tree)); static tree build_builtin_delete_call PARAMS ((tree));
static int member_init_ok_or_else PARAMS ((tree, tree, const char *)); static int member_init_ok_or_else PARAMS ((tree, tree, const char *));
static void expand_virtual_init PARAMS ((tree, tree)); static void expand_virtual_init PARAMS ((tree, tree));
static tree sort_member_init PARAMS ((tree)); static tree sort_member_init PARAMS ((tree, tree));
static tree initializing_context PARAMS ((tree)); static tree initializing_context PARAMS ((tree));
static void expand_cleanup_for_base PARAMS ((tree, tree)); static void expand_cleanup_for_base PARAMS ((tree, tree));
static tree get_temp_regvar PARAMS ((tree, tree)); static tree get_temp_regvar PARAMS ((tree, tree));
...@@ -213,7 +213,7 @@ perform_member_init (member, init, explicit) ...@@ -213,7 +213,7 @@ perform_member_init (member, init, explicit)
else if (TYPE_NEEDS_CONSTRUCTING (type) else if (TYPE_NEEDS_CONSTRUCTING (type)
|| (init && TYPE_HAS_CONSTRUCTOR (type))) || (init && TYPE_HAS_CONSTRUCTOR (type)))
{ {
/* Since `init' is already a TREE_LIST on the current_member_init_list, /* Since `init' is already a TREE_LIST on the member_init_list,
only build it into one if we aren't already a list. */ only build it into one if we aren't already a list. */
if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST) if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST)
init = build_tree_list (NULL_TREE, init); init = build_tree_list (NULL_TREE, init);
...@@ -338,11 +338,17 @@ build_field_list (t, list, uses_unions_p) ...@@ -338,11 +338,17 @@ build_field_list (t, list, uses_unions_p)
return list; return list;
} }
/* Subroutine of emit_member_init. */ /* The MEMBER_INIT_LIST is a TREE_LIST. The TREE_PURPOSE of each list
gives a FIELD_DECL in T that needs initialization. The TREE_VALUE
gives the initializer, or list of initializer arguments. Sort the
MEMBER_INIT_LIST, returning a version that contains the same
information but in the order that the fields should actually be
initialized. Perform error-checking in the process. */
static tree static tree
sort_member_init (t) sort_member_init (t, member_init_list)
tree t; tree t;
tree member_init_list;
{ {
tree init_list; tree init_list;
tree last_field; tree last_field;
...@@ -355,7 +361,7 @@ sort_member_init (t) ...@@ -355,7 +361,7 @@ sort_member_init (t)
/* Go through the explicit initializers, adding them to the /* Go through the explicit initializers, adding them to the
INIT_LIST. */ INIT_LIST. */
last_field = init_list; last_field = init_list;
for (init = current_member_init_list; init; init = TREE_CHAIN (init)) for (init = member_init_list; init; init = TREE_CHAIN (init))
{ {
tree f; tree f;
tree initialized_field; tree initialized_field;
...@@ -492,9 +498,15 @@ sort_member_init (t) ...@@ -492,9 +498,15 @@ sort_member_init (t)
return init_list; return init_list;
} }
/* Like sort_member_init, but used for initializers of base classes.
*RBASE_PTR is filled in with the initializers for non-virtual bases;
vbase_ptr gets the virtual bases. */
static void static void
sort_base_init (t, rbase_ptr, vbase_ptr) sort_base_init (t, base_init_list, rbase_ptr, vbase_ptr)
tree t, *rbase_ptr, *vbase_ptr; tree t;
tree base_init_list;
tree *rbase_ptr, *vbase_ptr;
{ {
tree binfos = BINFO_BASETYPES (TYPE_BINFO (t)); tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));
int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0; int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
...@@ -513,7 +525,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr) ...@@ -513,7 +525,7 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
/* First walk through and splice out vbase and invalid initializers. /* First walk through and splice out vbase and invalid initializers.
Also replace names with binfos. */ Also replace names with binfos. */
last = tree_cons (NULL_TREE, NULL_TREE, current_base_init_list); last = tree_cons (NULL_TREE, NULL_TREE, base_init_list);
for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x)) for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))
{ {
tree basetype = TREE_PURPOSE (x); tree basetype = TREE_PURPOSE (x);
...@@ -580,20 +592,24 @@ sort_base_init (t, rbase_ptr, vbase_ptr) ...@@ -580,20 +592,24 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
for (i = 0; i < n_baseclasses; ++i) for (i = 0; i < n_baseclasses; ++i)
{ {
/* The base for which we're currently initializing. */
tree base_binfo = TREE_VEC_ELT (binfos, i); tree base_binfo = TREE_VEC_ELT (binfos, i);
/* The initializer for BASE_BINFO. */
tree init;
int pos; int pos;
if (TREE_VIA_VIRTUAL (base_binfo)) if (TREE_VIA_VIRTUAL (base_binfo))
continue; continue;
for (x = current_base_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos) /* We haven't found the BASE_BINFO yet. */
init = NULL_TREE;
/* Loop through all the explicitly initialized bases, looking
for an appropriate initializer. */
for (x = base_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)
{ {
tree binfo = TREE_PURPOSE (x); tree binfo = TREE_PURPOSE (x);
if (binfo == NULL_TREE) if (binfo == base_binfo && !init)
continue;
if (binfo == base_binfo)
{ {
if (warn_reorder) if (warn_reorder)
{ {
...@@ -609,17 +625,22 @@ sort_base_init (t, rbase_ptr, vbase_ptr) ...@@ -609,17 +625,22 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
/* Make sure we won't try to work on this init again. */ /* Make sure we won't try to work on this init again. */
TREE_PURPOSE (x) = NULL_TREE; TREE_PURPOSE (x) = NULL_TREE;
x = build_tree_list (binfo, TREE_VALUE (x)); init = build_tree_list (binfo, TREE_VALUE (x));
goto got_it; }
else if (binfo == base_binfo)
{
cp_error ("base class `%T' already initialized",
BINFO_TYPE (binfo));
break;
} }
} }
/* If we didn't find BASE_BINFO in the list, create a dummy entry /* If we didn't find BASE_BINFO in the list, create a dummy entry
so the two lists (RBASES and the list of bases) will be so the two lists (RBASES and the list of bases) will be
symmetrical. */ symmetrical. */
x = build_tree_list (NULL_TREE, NULL_TREE); if (!init)
got_it: init = build_tree_list (NULL_TREE, NULL_TREE);
rbases = chainon (rbases, x); rbases = chainon (rbases, init);
} }
*rbase_ptr = rbases; *rbase_ptr = rbases;
...@@ -627,10 +648,9 @@ sort_base_init (t, rbase_ptr, vbase_ptr) ...@@ -627,10 +648,9 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
} }
/* Perform whatever initializations have yet to be done on the base /* Perform whatever initializations have yet to be done on the base
class of the class variable. These actions are in the global class, and non-static data members, of the CURRENT_CLASS_TYPE.
variable CURRENT_BASE_INIT_LIST. Such an action could be These actions are given by the BASE_INIT_LIST and MEM_INIT_LIST,
NULL_TREE, meaning that the user has explicitly called the base respectively.
class constructor with no arguments.
If there is a need for a call to a constructor, we must surround If there is a need for a call to a constructor, we must surround
that call with a pushlevel/poplevel pair, since we are technically that call with a pushlevel/poplevel pair, since we are technically
...@@ -640,10 +660,11 @@ sort_base_init (t, rbase_ptr, vbase_ptr) ...@@ -640,10 +660,11 @@ sort_base_init (t, rbase_ptr, vbase_ptr)
classes. That is done specially, elsewhere. */ classes. That is done specially, elsewhere. */
void void
emit_base_init () emit_base_init (mem_init_list, base_init_list)
tree mem_init_list;
tree base_init_list;
{ {
tree member; tree member;
tree mem_init_list;
tree rbase_init_list, vbase_init_list; tree rbase_init_list, vbase_init_list;
tree t = current_class_type; tree t = current_class_type;
tree t_binfo = TYPE_BINFO (t); tree t_binfo = TYPE_BINFO (t);
...@@ -651,11 +672,8 @@ emit_base_init () ...@@ -651,11 +672,8 @@ emit_base_init ()
int i; int i;
int n_baseclasses = BINFO_N_BASETYPES (t_binfo); int n_baseclasses = BINFO_N_BASETYPES (t_binfo);
mem_init_list = sort_member_init (t); mem_init_list = sort_member_init (t, mem_init_list);
current_member_init_list = NULL_TREE; sort_base_init (t, base_init_list, &rbase_init_list, &vbase_init_list);
sort_base_init (t, &rbase_init_list, &vbase_init_list);
current_base_init_list = NULL_TREE;
/* First, initialize the virtual base classes, if we are /* First, initialize the virtual base classes, if we are
constructing the most-derived object. */ constructing the most-derived object. */
...@@ -1004,13 +1022,9 @@ member_init_ok_or_else (field, type, member_name) ...@@ -1004,13 +1022,9 @@ member_init_ok_or_else (field, type, member_name)
We do not yet have a fixed-point finder to instantiate types We do not yet have a fixed-point finder to instantiate types
being fed to overloaded constructors. If there is a unique being fed to overloaded constructors. If there is a unique
constructor, then argument types can be got from that one. constructor, then argument types can be got from that one. */
If INIT is non-NULL, then it the initialization should tree
be placed in `current_base_init_list', where it will be processed
by `emit_base_init'. */
void
expand_member_init (exp, name, init) expand_member_init (exp, name, init)
tree exp, name, init; tree exp, name, init;
{ {
...@@ -1018,7 +1032,7 @@ expand_member_init (exp, name, init) ...@@ -1018,7 +1032,7 @@ expand_member_init (exp, name, init)
tree type; tree type;
if (exp == NULL_TREE) if (exp == NULL_TREE)
return; /* complain about this later */ return NULL_TREE;
type = TYPE_MAIN_VARIANT (TREE_TYPE (exp)); type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));
...@@ -1033,14 +1047,14 @@ expand_member_init (exp, name, init) ...@@ -1033,14 +1047,14 @@ expand_member_init (exp, name, init)
{ {
case 0: case 0:
error ("base class initializer specified, but no base class to initialize"); error ("base class initializer specified, but no base class to initialize");
return; return NULL_TREE;
case 1: case 1:
basetype = TYPE_BINFO_BASETYPE (type, 0); basetype = TYPE_BINFO_BASETYPE (type, 0);
break; break;
default: default:
error ("initializer for unnamed base class ambiguous"); error ("initializer for unnamed base class ambiguous");
cp_error ("(type `%T' uses multiple inheritance)", type); cp_error ("(type `%T' uses multiple inheritance)", type);
return; return NULL_TREE;
} }
my_friendly_assert (init != NULL_TREE, 0); my_friendly_assert (init != NULL_TREE, 0);
...@@ -1056,8 +1070,6 @@ expand_member_init (exp, name, init) ...@@ -1056,8 +1070,6 @@ expand_member_init (exp, name, init)
if (name == NULL_TREE || basetype) if (name == NULL_TREE || basetype)
{ {
tree base_init;
if (name == NULL_TREE) if (name == NULL_TREE)
{ {
#if 0 #if 0
...@@ -1084,43 +1096,23 @@ expand_member_init (exp, name, init) ...@@ -1084,43 +1096,23 @@ expand_member_init (exp, name, init)
else else
cp_error ("type `%T' is not an immediate basetype for `%T'", cp_error ("type `%T' is not an immediate basetype for `%T'",
basetype, type); basetype, type);
return; return NULL_TREE;
} }
if (purpose_member (basetype, current_base_init_list)) init = build_tree_list (basetype, init);
{
cp_error ("base class `%T' already initialized", basetype);
return;
}
if (warn_reorder && current_member_init_list)
{
cp_warning ("base initializer for `%T'", basetype);
warning (" will be re-ordered to precede member initializations");
}
base_init = build_tree_list (basetype, init);
current_base_init_list = chainon (current_base_init_list, base_init);
} }
else else
{ {
tree member_init;
try_member: try_member:
field = lookup_field (type, name, 1, 0); field = lookup_field (type, name, 1, 0);
if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name))) if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))
return; return NULL_TREE;
if (purpose_member (name, current_member_init_list))
{
cp_error ("field `%D' already initialized", field);
return;
}
member_init = build_tree_list (field, init); init = build_tree_list (field, init);
current_member_init_list = chainon (current_member_init_list, member_init);
} }
return init;
} }
/* This is like `expand_member_init', only it stores one aggregate /* This is like `expand_member_init', only it stores one aggregate
......
...@@ -730,13 +730,6 @@ finish_parse () ...@@ -730,13 +730,6 @@ finish_parse ()
fclose (finput); fclose (finput);
#endif #endif
} }
void
reinit_parse_for_function ()
{
current_base_init_list = NULL_TREE;
current_member_init_list = NULL_TREE;
}
inline void inline void
yyprint (file, yychar, yylval) yyprint (file, yychar, yylval)
......
...@@ -987,7 +987,7 @@ build_template_parm_names (parmlist, arglist) ...@@ -987,7 +987,7 @@ build_template_parm_names (parmlist, arglist)
} }
else else
{ {
parm = tsubst (parm, arglist, /*complain=*/1, NULL_TREE); parm = tsubst (parm, inner_args, /*complain=*/1, NULL_TREE);
/* It's a PARM_DECL. */ /* It's a PARM_DECL. */
build_mangled_name_for_type (TREE_TYPE (parm)); build_mangled_name_for_type (TREE_TYPE (parm));
build_overload_value (TREE_TYPE (parm), arg, build_overload_value (TREE_TYPE (parm), arg,
...@@ -2315,22 +2315,24 @@ do_build_copy_constructor (fndecl) ...@@ -2315,22 +2315,24 @@ do_build_copy_constructor (fndecl)
tree fields = TYPE_FIELDS (current_class_type); tree fields = TYPE_FIELDS (current_class_type);
int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type); int n_bases = CLASSTYPE_N_BASECLASSES (current_class_type);
tree binfos = TYPE_BINFO_BASETYPES (current_class_type); tree binfos = TYPE_BINFO_BASETYPES (current_class_type);
tree member_init_list = NULL_TREE;
tree base_init_list = NULL_TREE;
int i; int i;
/* Initialize all the base-classes. */ /* Initialize all the base-classes. */
for (t = CLASSTYPE_VBASECLASSES (current_class_type); t; for (t = CLASSTYPE_VBASECLASSES (current_class_type); t;
t = TREE_CHAIN (t)) t = TREE_CHAIN (t))
current_base_init_list base_init_list
= tree_cons (BINFO_TYPE (TREE_VALUE (t)), parm, = tree_cons (BINFO_TYPE (TREE_VALUE (t)), parm,
current_base_init_list); base_init_list);
for (i = 0; i < n_bases; ++i) for (i = 0; i < n_bases; ++i)
{ {
t = TREE_VEC_ELT (binfos, i); t = TREE_VEC_ELT (binfos, i);
if (TREE_VIA_VIRTUAL (t)) if (TREE_VIA_VIRTUAL (t))
continue; continue;
current_base_init_list base_init_list
= tree_cons (BINFO_TYPE (t), parm, current_base_init_list); = tree_cons (BINFO_TYPE (t), parm, base_init_list);
} }
for (; fields; fields = TREE_CHAIN (fields)) for (; fields; fields = TREE_CHAIN (fields))
...@@ -2364,12 +2366,12 @@ do_build_copy_constructor (fndecl) ...@@ -2364,12 +2366,12 @@ do_build_copy_constructor (fndecl)
init = build (COMPONENT_REF, TREE_TYPE (field), init, field); init = build (COMPONENT_REF, TREE_TYPE (field), init, field);
init = build_tree_list (NULL_TREE, init); init = build_tree_list (NULL_TREE, init);
current_member_init_list member_init_list
= tree_cons (field, init, current_member_init_list); = tree_cons (field, init, member_init_list);
} }
current_member_init_list = nreverse (current_member_init_list); member_init_list = nreverse (member_init_list);
current_base_init_list = nreverse (current_base_init_list); base_init_list = nreverse (base_init_list);
setup_vtbl_ptr (); setup_vtbl_ptr (member_init_list, base_init_list);
} }
} }
...@@ -2512,7 +2514,7 @@ synthesize_method (fndecl) ...@@ -2512,7 +2514,7 @@ synthesize_method (fndecl)
need_body = 0; need_body = 0;
} }
else if (DECL_DESTRUCTOR_P (fndecl)) else if (DECL_DESTRUCTOR_P (fndecl))
setup_vtbl_ptr (); setup_vtbl_ptr (NULL_TREE, NULL_TREE);
else else
{ {
tree arg_chain = FUNCTION_ARG_CHAIN (fndecl); tree arg_chain = FUNCTION_ARG_CHAIN (fndecl);
...@@ -2521,7 +2523,7 @@ synthesize_method (fndecl) ...@@ -2521,7 +2523,7 @@ synthesize_method (fndecl)
if (arg_chain != void_list_node) if (arg_chain != void_list_node)
do_build_copy_constructor (fndecl); do_build_copy_constructor (fndecl);
else if (TYPE_NEEDS_CONSTRUCTING (current_class_type)) else if (TYPE_NEEDS_CONSTRUCTING (current_class_type))
setup_vtbl_ptr (); setup_vtbl_ptr (NULL_TREE, NULL_TREE);
} }
/* If we haven't yet generated the body of the function, just /* If we haven't yet generated the body of the function, just
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -389,7 +389,8 @@ cp_parse_init () ...@@ -389,7 +389,8 @@ cp_parse_init ()
%type <itype> new delete %type <itype> new delete
/* %type <ttype> primary_no_id */ /* %type <ttype> primary_no_id */
%type <ttype> maybe_parmlist %type <ttype> maybe_parmlist
%type <itype> member_init_list %type <ttype> member_init
%type <ftype> member_init_list
%type <ttype> template_header template_parm_list template_parm %type <ttype> template_header template_parm_list template_parm
%type <ttype> template_type_parm template_template_parm %type <ttype> template_type_parm template_template_parm
%type <code> template_close_bracket %type <code> template_close_bracket
...@@ -853,9 +854,40 @@ return_init: ...@@ -853,9 +854,40 @@ return_init:
base_init: base_init:
':' .set_base_init member_init_list ':' .set_base_init member_init_list
{ {
if ($3 == 0) tree member_init_list = NULL_TREE;
error ("no base initializers given following ':'"); tree base_init_list = NULL_TREE;
setup_vtbl_ptr (); tree init;
tree next;
int seen_member_init_p;
if ($3.new_type_flag == 0)
error ("no base or member initializers given following ':'");
seen_member_init_p = 0;
for (init = $3.t; init; init = next)
{
next = TREE_CHAIN (init);
if (TREE_CODE (TREE_PURPOSE (init)) == FIELD_DECL)
{
TREE_CHAIN (init) = member_init_list;
member_init_list = init;
seen_member_init_p = 1;
}
else
{
if (warn_reorder && seen_member_init_p)
{
cp_warning ("base initializer for `%T'",
TREE_PURPOSE (init));
warning (" will be re-ordered to precede member initializations");
}
TREE_CHAIN (init) = base_init_list;
base_init_list = init;
}
}
setup_vtbl_ptr (member_init_list, base_init_list);
} }
; ;
...@@ -877,10 +909,26 @@ base_init: ...@@ -877,10 +909,26 @@ base_init:
member_init_list: member_init_list:
/* empty */ /* empty */
{ $$ = 0; } {
$$.new_type_flag = 0;
$$.t = NULL_TREE;
}
| member_init | member_init
{ $$ = 1; } {
$$.new_type_flag = 1;
$$.t = $1;
}
| member_init_list ',' member_init | member_init_list ',' member_init
{
if ($3)
{
$$.new_type_flag = 1;
TREE_CHAIN ($3) = $1.t;
$$.t = $3;
}
else
$$ = $1;
}
| member_init_list error | member_init_list error
; ;
...@@ -889,29 +937,36 @@ member_init: ...@@ -889,29 +937,36 @@ member_init:
{ {
if (current_class_name) if (current_class_name)
pedwarn ("anachronistic old style base class initializer"); pedwarn ("anachronistic old style base class initializer");
expand_member_init (current_class_ref, NULL_TREE, $2); $$ = expand_member_init (current_class_ref, NULL_TREE, $2);
} }
| LEFT_RIGHT | LEFT_RIGHT
{ {
if (current_class_name) if (current_class_name)
pedwarn ("anachronistic old style base class initializer"); pedwarn ("anachronistic old style base class initializer");
expand_member_init (current_class_ref, NULL_TREE, void_type_node); $$ = expand_member_init (current_class_ref,
NULL_TREE,
void_type_node);
} }
| notype_identifier '(' nonnull_exprlist ')' | notype_identifier '(' nonnull_exprlist ')'
{ expand_member_init (current_class_ref, $1, $3); } { $$ = expand_member_init (current_class_ref, $1, $3); }
| notype_identifier LEFT_RIGHT | notype_identifier LEFT_RIGHT
{ expand_member_init (current_class_ref, $1, void_type_node); } { $$ = expand_member_init (current_class_ref, $1,
void_type_node); }
| nonnested_type '(' nonnull_exprlist ')' | nonnested_type '(' nonnull_exprlist ')'
{ expand_member_init (current_class_ref, $1, $3); } { $$ = expand_member_init (current_class_ref, $1, $3); }
| nonnested_type LEFT_RIGHT | nonnested_type LEFT_RIGHT
{ expand_member_init (current_class_ref, $1, void_type_node); } { $$ = expand_member_init (current_class_ref, $1,
void_type_node); }
| typename_sub '(' nonnull_exprlist ')' | typename_sub '(' nonnull_exprlist ')'
{ expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1), { $$ = expand_member_init (current_class_ref,
$3); } TYPE_MAIN_DECL ($1),
$3); }
| typename_sub LEFT_RIGHT | typename_sub LEFT_RIGHT
{ expand_member_init (current_class_ref, TYPE_MAIN_DECL ($1), { $$ = expand_member_init (current_class_ref,
void_type_node); } TYPE_MAIN_DECL ($1),
void_type_node); }
| error | error
{ $$ = NULL_TREE }
; ;
identifier: identifier:
...@@ -1654,7 +1709,7 @@ nodecls: ...@@ -1654,7 +1709,7 @@ nodecls:
{ {
if (! current_function_parms_stored) if (! current_function_parms_stored)
store_parm_decls (); store_parm_decls ();
setup_vtbl_ptr (); setup_vtbl_ptr (NULL_TREE, NULL_TREE);
} }
; ;
...@@ -2096,8 +2151,7 @@ fn.defpen: ...@@ -2096,8 +2151,7 @@ fn.defpen:
PRE_PARSED_FUNCTION_DECL PRE_PARSED_FUNCTION_DECL
{ start_function (NULL_TREE, $1->fndecl, NULL_TREE, { start_function (NULL_TREE, $1->fndecl, NULL_TREE,
(SF_DEFAULT | SF_PRE_PARSED (SF_DEFAULT | SF_PRE_PARSED
| SF_INCLASS_INLINE)); | SF_INCLASS_INLINE)); }
reinit_parse_for_function (); }
pending_inline: pending_inline:
fn.defpen maybe_return_init ctor_initializer_opt compstmt_or_error fn.defpen maybe_return_init ctor_initializer_opt compstmt_or_error
......
...@@ -104,7 +104,7 @@ static int push_tinst_level PARAMS ((tree)); ...@@ -104,7 +104,7 @@ static int push_tinst_level PARAMS ((tree));
static void reopen_tinst_level PARAMS ((tree)); static void reopen_tinst_level PARAMS ((tree));
static tree classtype_mangled_name PARAMS ((tree)); static tree classtype_mangled_name PARAMS ((tree));
static char *mangle_class_name_for_template PARAMS ((char *, tree, tree)); static char *mangle_class_name_for_template PARAMS ((char *, tree, tree));
static tree tsubst_expr_values PARAMS ((tree, tree)); static tree tsubst_initializer_list PARAMS ((tree, tree));
static int list_eq PARAMS ((tree, tree)); static int list_eq PARAMS ((tree, tree));
static tree get_class_bindings PARAMS ((tree, tree, tree)); static tree get_class_bindings PARAMS ((tree, tree, tree));
static tree coerce_template_parms PARAMS ((tree, tree, tree, int, int)); static tree coerce_template_parms PARAMS ((tree, tree, tree, int, int));
...@@ -3009,7 +3009,7 @@ convert_nontype_argument (type, expr) ...@@ -3009,7 +3009,7 @@ convert_nontype_argument (type, expr)
|| !at_least_as_qualified_p (type_referred_to, || !at_least_as_qualified_p (type_referred_to,
expr_type) expr_type)
|| !real_lvalue_p (expr)) || !real_lvalue_p (expr))
expr = error_mark_node; return error_mark_node;
} }
mark_addressable (expr); mark_addressable (expr);
...@@ -7145,14 +7145,19 @@ tsubst_expr (t, args, complain, in_decl) ...@@ -7145,14 +7145,19 @@ tsubst_expr (t, args, complain, in_decl)
break; break;
case CTOR_INITIALIZER: case CTOR_INITIALIZER:
prep_stmt (t); {
current_member_init_list tree member_init_list;
= tsubst_expr_values (TREE_OPERAND (t, 0), args); tree base_init_list;
current_base_init_list
= tsubst_expr_values (TREE_OPERAND (t, 1), args); prep_stmt (t);
setup_vtbl_ptr (); member_init_list
tsubst_expr (TREE_CHAIN (t), args, complain, in_decl); = tsubst_initializer_list (TREE_OPERAND (t, 0), args);
break; base_init_list
= tsubst_initializer_list (TREE_OPERAND (t, 1), args);
setup_vtbl_ptr (member_init_list, base_init_list);
tsubst_expr (TREE_CHAIN (t), args, complain, in_decl);
break;
}
case RETURN_STMT: case RETURN_STMT:
prep_stmt (t); prep_stmt (t);
...@@ -9837,12 +9842,13 @@ instantiate_pending_templates () ...@@ -9837,12 +9842,13 @@ instantiate_pending_templates ()
return instantiated_something; return instantiated_something;
} }
/* Substitute ARGVEC into T, which is a TREE_LIST. In particular, it /* Substitute ARGVEC into T, which is a list of initializers for
is an initializer list: the TREE_PURPOSEs are DECLs, and the either base class or a non-static data member. The TREE_PURPOSEs
TREE_VALUEs are initializer values. Used by instantiate_decl. */ are DECLs, and the TREE_VALUEs are the initializer values. Used by
instantiate_decl. */
static tree static tree
tsubst_expr_values (t, argvec) tsubst_initializer_list (t, argvec)
tree t, argvec; tree t, argvec;
{ {
tree first = NULL_TREE; tree first = NULL_TREE;
...@@ -9850,11 +9856,24 @@ tsubst_expr_values (t, argvec) ...@@ -9850,11 +9856,24 @@ tsubst_expr_values (t, argvec)
for (; t; t = TREE_CHAIN (t)) for (; t; t = TREE_CHAIN (t))
{ {
tree pur = tsubst_copy (TREE_PURPOSE (t), argvec, tree decl;
/*complain=*/1, NULL_TREE); tree init;
tree val = tsubst_expr (TREE_VALUE (t), argvec, /*complain=*/1, tree val;
NULL_TREE);
*p = build_tree_list (pur, val); decl = tsubst_copy (TREE_PURPOSE (t), argvec, /*complain=*/1,
NULL_TREE);
init = tsubst_expr (TREE_VALUE (t), argvec, /*complain=*/1,
NULL_TREE);
if (!init)
;
else if (TREE_CODE (init) == TREE_LIST)
for (val = init; val; val = TREE_CHAIN (val))
TREE_VALUE (val) = convert_from_reference (TREE_VALUE (val));
else
init = convert_from_reference (init);
*p = build_tree_list (decl, init);
p = &TREE_CHAIN (*p); p = &TREE_CHAIN (*p);
} }
return first; return first;
......
...@@ -1235,7 +1235,9 @@ finish_named_return_value (return_id, init) ...@@ -1235,7 +1235,9 @@ finish_named_return_value (return_id, init)
more than one virtual function call is made this function. */ more than one virtual function call is made this function. */
void void
setup_vtbl_ptr () setup_vtbl_ptr (member_init_list, base_init_list)
tree member_init_list;
tree base_init_list;
{ {
my_friendly_assert (doing_semantic_analysis_p (), 19990919); my_friendly_assert (doing_semantic_analysis_p (), 19990919);
...@@ -1248,7 +1250,7 @@ setup_vtbl_ptr () ...@@ -1248,7 +1250,7 @@ setup_vtbl_ptr ()
if (processing_template_decl) if (processing_template_decl)
add_tree (build_min_nt add_tree (build_min_nt
(CTOR_INITIALIZER, (CTOR_INITIALIZER,
current_member_init_list, current_base_init_list)); member_init_list, base_init_list));
else else
{ {
tree ctor_stmt; tree ctor_stmt;
...@@ -1259,7 +1261,7 @@ setup_vtbl_ptr () ...@@ -1259,7 +1261,7 @@ setup_vtbl_ptr ()
add_tree (ctor_stmt); add_tree (ctor_stmt);
/* And actually initialize the base-classes and members. */ /* And actually initialize the base-classes and members. */
emit_base_init (); emit_base_init (member_init_list, base_init_list);
} }
} }
else if (DECL_DESTRUCTOR_P (current_function_decl) else if (DECL_DESTRUCTOR_P (current_function_decl)
...@@ -1776,7 +1778,6 @@ begin_function_definition (decl_specs, declarator) ...@@ -1776,7 +1778,6 @@ begin_function_definition (decl_specs, declarator)
deferred_type_access_control (); deferred_type_access_control ();
type_lookups = error_mark_node; type_lookups = error_mark_node;
reinit_parse_for_function ();
/* The things we're about to see are not directly qualified by any /* The things we're about to see are not directly qualified by any
template headers we've seen thus far. */ template headers we've seen thus far. */
reset_specialization (); reset_specialization ();
......
// Origin: John Wilkinson <jfw@sgi.com>
template <class T, int& Size>
struct Base {
Base() : obj(Size) {}
T obj;
};
int globalInt = 5;
struct A {
A(int arg) : ia(arg) {}
int ia;
};
int main()
{
Base<A, globalInt> ob;
if (ob.obj.ia != 5)
return 1;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment