Commit 2282d28d by Mark Mitchell Committed by Mark Mitchell

re PR c++/7188 (Segfault with template class and recursive (incorrect) initalizer list.)

	PR c++/7188.
	* cp-tree.def (CTOR_INITIALIZER): Use one slot, not two.
	* cp-tree.h (emit_base_init): Rename to ....
	(emit_mem_initializers): ... this.
	(expand_member_init): Change prototype.
	* init.c (perform_member_init): Compute explicit, rather than
	requiring it as a parameter.
	(sort_member_init): Rename to ...
	(sort_mem_initializers): ... this.  Process bases and data members
	together.
	(sort_base_init): Remove.
	(emit_base_init): Rename to ...
	(emit_mem_initializers): ... this.
	(expand_aggr_vbase_init_1): Remove.
	(construct_virtual_bases): Rename to ...
	(construct_virtual_base): ... this.
	(expand_member_init): Rework handling of base initializers.
	* method.c (do_build_copy_constructor): Use
	finish_mem_initializers.
	* parse.y (member_init): Adjust calls to expand_member_init.
	* pt.c (tsubst_expr): Simplify CTOR_INITIALIZER case.
	(tsubst_initializer_list): Use expand_member_init.
	* semantics.c (finish_mem_intiailizers): Simplify.

	PR c++/7188.
	* g++.dg/template/meminit1.C: New test.
	* g++.dg/warn/Wreorder-1.C: Likewise.
	* g++.old-deja/g++.mike/warn3.C: Tweak.
	* lib/prune.exp: Ingore "in copy constructor".

From-SVN: r57748
parent 854ef390
2002-10-02 Mark Mitchell <mark@codesourcery.com>
PR c++/7188.
* cp-tree.def (CTOR_INITIALIZER): Use one slot, not two.
* cp-tree.h (emit_base_init): Rename to ....
(emit_mem_initializers): ... this.
(expand_member_init): Change prototype.
* init.c (perform_member_init): Compute explicit, rather than
requiring it as a parameter.
(sort_member_init): Rename to ...
(sort_mem_initializers): ... this. Process bases and data members
together.
(sort_base_init): Remove.
(emit_base_init): Rename to ...
(emit_mem_initializers): ... this.
(expand_aggr_vbase_init_1): Remove.
(construct_virtual_bases): Rename to ...
(construct_virtual_base): ... this.
(expand_member_init): Rework handling of base initializers.
* method.c (do_build_copy_constructor): Use
finish_mem_initializers.
* parse.y (member_init): Adjust calls to expand_member_init.
* pt.c (tsubst_expr): Simplify CTOR_INITIALIZER case.
(tsubst_initializer_list): Use expand_member_init.
* semantics.c (finish_mem_intiailizers): Simplify.
2002-10-02 Roger Sayle <roger@eyesopen.com> 2002-10-02 Roger Sayle <roger@eyesopen.com>
PR optimization/6627 PR optimization/6627
......
...@@ -251,7 +251,7 @@ DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", 'e', 3) ...@@ -251,7 +251,7 @@ DEFTREECODE (PSEUDO_DTOR_EXPR, "pseudo_dtor_expr", 'e', 3)
/* CTOR_INITIALIZER is a placeholder in template code for a call to /* CTOR_INITIALIZER is a placeholder in template code for a call to
setup_vtbl_pointer (and appears in all functions, not just ctors). */ setup_vtbl_pointer (and appears in all functions, not just ctors). */
DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 2) DEFTREECODE (CTOR_INITIALIZER, "ctor_initializer", 'e', 1)
DEFTREECODE (RETURN_INIT, "return_init", 'e', 2) DEFTREECODE (RETURN_INIT, "return_init", 'e', 2)
DEFTREECODE (TRY_BLOCK, "try_block", 'e', 2) DEFTREECODE (TRY_BLOCK, "try_block", 'e', 2)
DEFTREECODE (EH_SPEC_BLOCK, "eh_spec_block", 'e', 2) DEFTREECODE (EH_SPEC_BLOCK, "eh_spec_block", 'e', 2)
......
...@@ -3845,8 +3845,8 @@ extern void add_friend PARAMS ((tree, tree)); ...@@ -3845,8 +3845,8 @@ extern void add_friend PARAMS ((tree, tree));
extern tree do_friend PARAMS ((tree, tree, tree, tree, tree, enum overload_flags, tree, int)); extern tree do_friend PARAMS ((tree, tree, tree, tree, tree, enum overload_flags, tree, int));
/* in init.c */ /* in init.c */
extern void emit_base_init PARAMS ((tree, tree)); extern tree expand_member_init (tree, tree);
extern tree expand_member_init PARAMS ((tree, tree, tree)); extern void emit_mem_initializers (tree);
extern tree build_aggr_init PARAMS ((tree, tree, int)); extern tree build_aggr_init PARAMS ((tree, tree, int));
extern tree build_init PARAMS ((tree, tree, int)); extern tree build_init PARAMS ((tree, tree, int));
extern int is_aggr_type PARAMS ((tree, int)); extern int is_aggr_type PARAMS ((tree, int));
......
...@@ -536,7 +536,6 @@ do_build_copy_constructor (fndecl) ...@@ -536,7 +536,6 @@ do_build_copy_constructor (fndecl)
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 member_init_list = NULL_TREE;
tree base_init_list = NULL_TREE;
int cvquals = cp_type_quals (TREE_TYPE (parm)); int cvquals = cp_type_quals (TREE_TYPE (parm));
int i; int i;
...@@ -550,10 +549,12 @@ do_build_copy_constructor (fndecl) ...@@ -550,10 +549,12 @@ do_build_copy_constructor (fndecl)
{ {
tree binfo = TREE_VALUE (t); tree binfo = TREE_VALUE (t);
base_init_list = tree_cons (binfo, member_init_list
= tree_cons (binfo,
build_tree_list (NULL_TREE,
build_base_path (PLUS_EXPR, parm, build_base_path (PLUS_EXPR, parm,
binfo, 1), binfo, 1)),
base_init_list); member_init_list);
} }
for (i = 0; i < n_bases; ++i) for (i = 0; i < n_bases; ++i)
...@@ -562,10 +563,12 @@ do_build_copy_constructor (fndecl) ...@@ -562,10 +563,12 @@ do_build_copy_constructor (fndecl)
if (TREE_VIA_VIRTUAL (binfo)) if (TREE_VIA_VIRTUAL (binfo))
continue; continue;
base_init_list = tree_cons (binfo, member_init_list
= tree_cons (binfo,
build_tree_list (NULL_TREE,
build_base_path (PLUS_EXPR, parm, build_base_path (PLUS_EXPR, parm,
binfo, 1), binfo, 1)),
base_init_list); member_init_list);
} }
for (; fields; fields = TREE_CHAIN (fields)) for (; fields; fields = TREE_CHAIN (fields))
...@@ -609,9 +612,7 @@ do_build_copy_constructor (fndecl) ...@@ -609,9 +612,7 @@ do_build_copy_constructor (fndecl)
member_init_list member_init_list
= tree_cons (field, init, member_init_list); = tree_cons (field, init, member_init_list);
} }
member_init_list = nreverse (member_init_list); finish_mem_initializers (member_init_list);
base_init_list = nreverse (base_init_list);
emit_base_init (member_init_list, base_init_list);
} }
} }
......
...@@ -981,31 +981,27 @@ member_init: ...@@ -981,31 +981,27 @@ 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 (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, $$ = expand_member_init (NULL_TREE,
NULL_TREE,
void_type_node); void_type_node);
} }
| notype_identifier '(' nonnull_exprlist ')' | notype_identifier '(' nonnull_exprlist ')'
{ $$ = expand_member_init (current_class_ref, $1, $3); } { $$ = expand_member_init ($1, $3); }
| notype_identifier LEFT_RIGHT | notype_identifier LEFT_RIGHT
{ $$ = expand_member_init (current_class_ref, $1, { $$ = expand_member_init ($1, void_type_node); }
void_type_node); }
| nonnested_type '(' nonnull_exprlist ')' | nonnested_type '(' nonnull_exprlist ')'
{ $$ = expand_member_init (current_class_ref, $1, $3); } { $$ = expand_member_init ($1, $3); }
| nonnested_type LEFT_RIGHT | nonnested_type LEFT_RIGHT
{ $$ = expand_member_init (current_class_ref, $1, { $$ = expand_member_init ($1, void_type_node); }
void_type_node); }
| typename_sub '(' nonnull_exprlist ')' | typename_sub '(' nonnull_exprlist ')'
{ $$ = expand_member_init (current_class_ref, $1, $3); } { $$ = expand_member_init ($1, $3); }
| typename_sub LEFT_RIGHT | typename_sub LEFT_RIGHT
{ $$ = expand_member_init (current_class_ref, $1, { $$ = expand_member_init ($1, void_type_node); }
void_type_node); }
| error | error
{ $$ = NULL_TREE; } { $$ = NULL_TREE; }
; ;
......
...@@ -7369,18 +7369,10 @@ tsubst_expr (t, args, complain, in_decl) ...@@ -7369,18 +7369,10 @@ tsubst_expr (t, args, complain, in_decl)
break; break;
case CTOR_INITIALIZER: case CTOR_INITIALIZER:
{
tree member_init_list;
tree base_init_list;
prep_stmt (t); prep_stmt (t);
member_init_list finish_mem_initializers (tsubst_initializer_list
= tsubst_initializer_list (TREE_OPERAND (t, 0), args); (TREE_OPERAND (t, 0), args));
base_init_list
= tsubst_initializer_list (TREE_OPERAND (t, 1), args);
emit_base_init (member_init_list, base_init_list);
break; break;
}
case RETURN_STMT: case RETURN_STMT:
prep_stmt (t); prep_stmt (t);
...@@ -10293,8 +10285,7 @@ static tree ...@@ -10293,8 +10285,7 @@ static tree
tsubst_initializer_list (t, argvec) tsubst_initializer_list (t, argvec)
tree t, argvec; tree t, argvec;
{ {
tree first = NULL_TREE; tree inits = NULL_TREE;
tree *p = &first;
for (; t; t = TREE_CHAIN (t)) for (; t; t = TREE_CHAIN (t))
{ {
...@@ -10312,13 +10303,17 @@ tsubst_initializer_list (t, argvec) ...@@ -10312,13 +10303,17 @@ tsubst_initializer_list (t, argvec)
else if (TREE_CODE (init) == TREE_LIST) else if (TREE_CODE (init) == TREE_LIST)
for (val = init; val; val = TREE_CHAIN (val)) for (val = init; val; val = TREE_CHAIN (val))
TREE_VALUE (val) = convert_from_reference (TREE_VALUE (val)); TREE_VALUE (val) = convert_from_reference (TREE_VALUE (val));
else else if (init != void_type_node)
init = convert_from_reference (init); init = convert_from_reference (init);
*p = build_tree_list (decl, init); init = expand_member_init (decl, init);
p = &TREE_CHAIN (*p); if (init)
{
TREE_CHAIN (init) = inits;
inits = init;
}
} }
return first; return inits;
} }
/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */ /* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
......
...@@ -1094,67 +1094,21 @@ begin_mem_initializers () ...@@ -1094,67 +1094,21 @@ begin_mem_initializers ()
error ("only constructors take base initializers"); error ("only constructors take base initializers");
} }
/* The INIT_LIST is a list of mem-initializers, in the order they were /* The MEM_INITS is a list of mem-initializers, in reverse of the
written by the user. The TREE_VALUE of each node is a list of order they were written by the user. Each node is as for
initializers for a particular subobject. The TREE_PURPOSE is a emit_mem_initializers. */
FIELD_DECL is the initializer is for a non-static data member, and
a class type if the initializer is for a base class. */
void void
finish_mem_initializers (init_list) finish_mem_initializers (tree mem_inits)
tree init_list;
{ {
tree member_init_list; /* Reorder the MEM_INITS so that they are in the order they appeared
tree base_init_list; in the source program. */
tree last_base_warned_about; mem_inits = nreverse (mem_inits);
tree next;
tree init;
member_init_list = NULL_TREE;
base_init_list = NULL_TREE;
last_base_warned_about = NULL_TREE;
for (init = init_list; 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;
/* We're running through the initializers from right to left
as we process them here. So, if we see a data member
initializer after we see a base initializer, that
actually means that the base initializer preceded the
data member initializer. */
if (warn_reorder && last_base_warned_about != base_init_list)
{
tree base;
for (base = base_init_list;
base != last_base_warned_about;
base = TREE_CHAIN (base))
{
warning ("base initializer for `%T'",
TREE_PURPOSE (base));
warning (" will be re-ordered to precede member initializations");
}
last_base_warned_about = base_init_list;
}
}
else
{
TREE_CHAIN (init) = base_init_list;
base_init_list = init;
}
}
if (processing_template_decl) if (processing_template_decl)
add_stmt (build_min_nt (CTOR_INITIALIZER, add_stmt (build_min_nt (CTOR_INITIALIZER, mem_inits));
member_init_list, base_init_list));
else else
emit_base_init (member_init_list, base_init_list); emit_mem_initializers (mem_inits);
} }
/* Returns the stack of SCOPE_STMTs for the current function. */ /* Returns the stack of SCOPE_STMTs for the current function. */
......
2002-10-02 Mark Mitchell <mark@codesourcery.com>
PR c++/7188.
* g++.dg/template/meminit1.C: New test.
* g++.dg/warn/Wreorder-1.C: Likewise.
* g++.old-deja/g++.mike/warn3.C: Tweak.
* lib/prune.exp: Ingore "in copy constructor".
2002-10-02 Andreas Jaeger <aj@suse.de> 2002-10-02 Andreas Jaeger <aj@suse.de>
* gcc.dg/20020919-1.c, gcc.dg/inline-2.c, gcc.dg/980211-1.c, * gcc.dg/20020919-1.c, gcc.dg/inline-2.c, gcc.dg/980211-1.c,
......
template <class T >
struct S
{
S() : S() {} // { dg-error "base" }
};
S<int> s; // { dg-error "instantiated" }
// { dg-options "-Wreorder -W" }
struct S {
S ();
};
struct T {
T ();
};
struct U : virtual public S, virtual public T {
U () : T (), S () {} // { dg-warning "" }
U (const U&) : S () {} // { dg-warning "copy" }
};
...@@ -7,6 +7,6 @@ public: ...@@ -7,6 +7,6 @@ public:
}; };
class D : public B { class D : public B {
int member; int member; // WARNING - reordered
D() : member(0), B(member) { } // WARNING - reordered D() : member(0), B(member) { } // WARNING - reordered
}; };
# Copyright (C) 1997, 1999, 2000 Free Software Foundation, Inc. # Copyright (C) 1997, 1999, 2000, 2002 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify # This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
proc prune_gcc_output { text } { proc prune_gcc_output { text } {
#send_user "Before:$text\n" #send_user "Before:$text\n"
regsub -all "(^|\n)\[^\n\]*: In (function|member|method|constructor|instantiation|program|subroutine|block-data) \[^\n\]*" $text "" text regsub -all "(^|\n)\[^\n\]*: In (function|member|method|(copy )?constructor|instantiation|program|subroutine|block-data) \[^\n\]*" $text "" text
regsub -all "(^|\n)\[^\n\]*: At (top level|global scope):\[^\n\]*" $text "" text regsub -all "(^|\n)\[^\n\]*: At (top level|global scope):\[^\n\]*" $text "" text
regsub -all "(^|\n)collect2: ld returned \[^\n\]*" $text "" text regsub -all "(^|\n)collect2: ld returned \[^\n\]*" $text "" text
regsub -all "(^|\n)Please submit.*instructions\[^\n\]*" $text "" text regsub -all "(^|\n)Please submit.*instructions\[^\n\]*" $text "" text
......
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