re PR c++/9629 (virtual inheritance segfault)

cp:
	PR c++/9629
	* cp-tree.h (struct language_function): Add in_base_initializer.
	(in_base_initializer): define it.
	(expand_member_init): Remove INIT param.
	* init.c (expand_member_init): Remove INIT param, return the member.
	(emit_mem_initializers): Set in_base_initializer.
	* class.c (build_base_path): Check in_base_initializer.
	* parser.c (cp_parser_mem_initializer): Set in_base_initializer.
	* pt.c (tsubst_initializer_list): Likewise.
testsuite:
	PR c++/9629
	* g++.dg/init/ctor2.C: New test.

From-SVN: r64438
This commit is contained in:
Nathan Sidwell 2003-03-16 14:36:43 +00:00 committed by Nathan Sidwell
parent 46ea50cb66
commit 1f5a253a36
8 changed files with 104 additions and 21 deletions

View File

@ -1,3 +1,15 @@
2003-03-16 Nathan Sidwell <nathan@codesourcery.com>
PR c++/9629
* cp-tree.h (struct language_function): Add in_base_initializer.
(in_base_initializer): define it.
(expand_member_init): Remove INIT param.
* init.c (expand_member_init): Remove INIT param, return the member.
(emit_mem_initializers): Set in_base_initializer.
* class.c (build_base_path): Check in_base_initializer.
* parser.c (cp_parser_mem_initializer): Set in_base_initializer.
* pt.c (tsubst_initializer_list): Likewise.
2003-03-16 Gabriel Dos Reis <gdr@integrable-solutions.net>
* decl.c (binding_for_name): Fix initialization thinko.
@ -596,7 +608,7 @@
2003-02-21 Nathan Sidwell <nathan@codesourcery.com>
* search.c (bfs_walk_grow): Remove. Fold into ...
* search.c (grow_bfs_bases): Remove. Fold into ...
(bfs_walk): ... here, fix fencepost error. Fix merge lossage
in previous patch.

View File

@ -302,8 +302,25 @@ build_base_path (enum tree_code code,
/* Going via virtual base V_BINFO. We need the static offset
from V_BINFO to BINFO, and the dynamic offset from D_BINFO to
V_BINFO. That offset is an entry in D_BINFO's vtable. */
tree v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
TREE_TYPE (TREE_TYPE (expr)));
tree v_offset;
if (fixed_type_p < 0 && in_base_initializer)
{
/* In a base member initializer, we cannot rely on
the vtable being set up. We have to use the vtt_parm. */
tree derived = BINFO_INHERITANCE_CHAIN (v_binfo);
v_offset = build (PLUS_EXPR, TREE_TYPE (current_vtt_parm),
current_vtt_parm, BINFO_VPTR_INDEX (derived));
v_offset = build1 (INDIRECT_REF,
TREE_TYPE (TYPE_VFIELD (BINFO_TYPE (derived))),
v_offset);
}
else
v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
TREE_TYPE (TREE_TYPE (expr)));
v_offset = build (PLUS_EXPR, TREE_TYPE (v_offset),
v_offset, BINFO_VPTR_FIELD (v_binfo));

View File

@ -866,6 +866,7 @@ struct language_function GTY(())
int returns_null;
int returns_abnormally;
int in_function_try_handler;
int in_base_initializer;
int x_expanding_p;
struct named_label_use_list *x_named_label_uses;
@ -936,6 +937,9 @@ struct language_function GTY(())
#define doing_semantic_analysis_p() (!expanding_p)
/* Non-zero if we are processing a base initializer. Zero elsewhere. */
#define in_base_initializer cp_function_chain->in_base_initializer
#define in_function_try_handler cp_function_chain->in_function_try_handler
/* Expression always returned from function, or error_mark_node
@ -3915,7 +3919,7 @@ extern void add_friend (tree, tree);
extern tree do_friend (tree, tree, tree, tree, tree, enum overload_flags, tree, int);
/* in init.c */
extern tree expand_member_init (tree, tree);
extern tree expand_member_init (tree);
extern void emit_mem_initializers (tree);
extern tree build_aggr_init (tree, tree, int);
extern tree build_init (tree, tree, int);

View File

@ -146,7 +146,7 @@ initialize_vtbl_ptrs (addr)
list = build_tree_list (type, addr);
/* Walk through the hierarchy, initializing the vptr in each base
class. We do these in pre-order because can't find the virtual
class. We do these in pre-order because we can't find the virtual
bases for a class until we've initialized the vtbl for that
class. */
dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
@ -664,6 +664,8 @@ emit_mem_initializers (tree mem_inits)
initializations should be performed. */
mem_inits = sort_mem_initializers (current_class_type, mem_inits);
in_base_initializer = 1;
/* Initialize base classes. */
while (mem_inits
&& TREE_CODE (TREE_PURPOSE (mem_inits)) != FIELD_DECL)
@ -704,10 +706,11 @@ emit_mem_initializers (tree mem_inits)
mem_inits = TREE_CHAIN (mem_inits);
}
in_base_initializer = 0;
/* Initialize the vptrs. */
initialize_vtbl_ptrs (current_class_ptr);
/* Initialize the data members. */
while (mem_inits)
{
@ -951,16 +954,15 @@ member_init_ok_or_else (field, type, member_name)
/* NAME is a FIELD_DECL, an IDENTIFIER_NODE which names a field, or it
is a _TYPE node or TYPE_DECL which names a base for that type.
INIT is a parameter list for that field's or base's constructor.
Check the validity of NAME, and return a TREE_LIST of the base
_TYPE or FIELD_DECL and the INIT. If NAME is invalid, return
Check the validity of NAME, and return either the base _TYPE, base
binfo, or the FIELD_DECL of the member. If NAME is invalid, return
NULL_TREE and issue a diagnostic.
An old style unnamed direct single base construction is permitted,
where NAME is NULL. */
tree
expand_member_init (tree name, tree init)
expand_member_init (tree name)
{
tree basetype;
tree field;
@ -997,14 +999,12 @@ expand_member_init (tree name, tree init)
else
basetype = NULL_TREE;
my_friendly_assert (init != NULL_TREE, 0);
if (basetype)
{
tree binfo;
if (current_template_parms)
return build_tree_list (basetype, init);
return basetype;
binfo = lookup_base (current_class_type, basetype,
ba_ignore, NULL);
@ -1020,7 +1020,7 @@ expand_member_init (tree name, tree init)
name, current_class_type);
return NULL_TREE;
}
return build_tree_list (binfo, init);
return binfo;
}
else
{
@ -1030,7 +1030,7 @@ expand_member_init (tree name, tree init)
field = name;
if (member_init_ok_or_else (field, current_class_type, name))
return build_tree_list (field, init);
return field;
}
return NULL_TREE;

View File

@ -7236,7 +7236,8 @@ cp_parser_mem_initializer (cp_parser* parser)
{
tree mem_initializer_id;
tree expression_list;
tree member;
/* Find out what is being initialized. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
@ -7245,6 +7246,10 @@ cp_parser_mem_initializer (cp_parser* parser)
}
else
mem_initializer_id = cp_parser_mem_initializer_id (parser);
member = expand_member_init (mem_initializer_id);
if (member && !DECL_P (member))
in_base_initializer = 1;
/* Look for the opening `('. */
cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
/* Parse the expression-list. */
@ -7256,8 +7261,9 @@ cp_parser_mem_initializer (cp_parser* parser)
/* Look for the closing `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
return expand_member_init (mem_initializer_id,
expression_list);
in_base_initializer = 0;
return member ? build_tree_list (member, expression_list) : NULL_TREE;
}
/* Parse a mem-initializer-id.

View File

@ -11093,9 +11093,12 @@ tsubst_initializer_list (t, argvec)
decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning,
NULL_TREE);
decl = expand_member_init (decl);
if (decl && !DECL_P (decl))
in_base_initializer = 1;
init = tsubst_expr (TREE_VALUE (t), argvec, tf_error | tf_warning,
NULL_TREE);
if (!init)
;
else if (TREE_CODE (init) == TREE_LIST)
@ -11104,9 +11107,11 @@ tsubst_initializer_list (t, argvec)
else if (init != void_type_node)
init = convert_from_reference (init);
init = expand_member_init (decl, init);
if (init)
in_base_initializer = 0;
if (decl)
{
init = build_tree_list (decl, init);
TREE_CHAIN (init) = inits;
inits = init;
}

View File

@ -1,3 +1,8 @@
2003-03-16 Nathan Sidwell <nathan@codesourcery.com>
PR c++/9629
* g++.dg/init/ctor2.C: New test.
2003-03-15 Roger Sayle <roger@eyesopen.com>
* g77.f-torture/compile/xformat.f: New test case.

View File

@ -0,0 +1,34 @@
// { dg-do run }
// Copyright (C) 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 14 Mar 2003 <nathan@codesourcery.com>
// PR 9629. The vtable is not set up until the base initializers have
// run.
struct A {
static A *a;
A ();
};
A *A::a;
A::A () {a = this;}
struct B {
static A *a;
B (A *);
};
A *B::a;
B::B(A *a_) {a = a_;}
struct C : virtual public A, public B {
C();
};
C::C () : B(this) {}
struct D : virtual public C {};
int main()
{
new D();
return A::a != B::a;
}