Commit 1f5a253a by Nathan Sidwell Committed by Nathan Sidwell

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
parent 46ea50cb
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> 2003-03-16 Gabriel Dos Reis <gdr@integrable-solutions.net>
* decl.c (binding_for_name): Fix initialization thinko. * decl.c (binding_for_name): Fix initialization thinko.
...@@ -596,7 +608,7 @@ ...@@ -596,7 +608,7 @@
2003-02-21 Nathan Sidwell <nathan@codesourcery.com> 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 (bfs_walk): ... here, fix fencepost error. Fix merge lossage
in previous patch. in previous patch.
......
...@@ -302,8 +302,25 @@ build_base_path (enum tree_code code, ...@@ -302,8 +302,25 @@ build_base_path (enum tree_code code,
/* Going via virtual base V_BINFO. We need the static offset /* Going via virtual base V_BINFO. We need the static offset
from V_BINFO to BINFO, and the dynamic offset from D_BINFO to 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. */ V_BINFO. That offset is an entry in D_BINFO's vtable. */
tree v_offset = build_vfield_ref (build_indirect_ref (expr, NULL), tree v_offset;
TREE_TYPE (TREE_TYPE (expr)));
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 = build (PLUS_EXPR, TREE_TYPE (v_offset),
v_offset, BINFO_VPTR_FIELD (v_binfo)); v_offset, BINFO_VPTR_FIELD (v_binfo));
......
...@@ -866,6 +866,7 @@ struct language_function GTY(()) ...@@ -866,6 +866,7 @@ struct language_function GTY(())
int returns_null; int returns_null;
int returns_abnormally; int returns_abnormally;
int in_function_try_handler; int in_function_try_handler;
int in_base_initializer;
int x_expanding_p; int x_expanding_p;
struct named_label_use_list *x_named_label_uses; struct named_label_use_list *x_named_label_uses;
...@@ -936,6 +937,9 @@ struct language_function GTY(()) ...@@ -936,6 +937,9 @@ struct language_function GTY(())
#define doing_semantic_analysis_p() (!expanding_p) #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 #define in_function_try_handler cp_function_chain->in_function_try_handler
/* Expression always returned from function, or error_mark_node /* Expression always returned from function, or error_mark_node
...@@ -3915,7 +3919,7 @@ extern void add_friend (tree, tree); ...@@ -3915,7 +3919,7 @@ extern void add_friend (tree, tree);
extern tree do_friend (tree, tree, tree, tree, tree, enum overload_flags, tree, int); extern tree do_friend (tree, tree, tree, tree, tree, enum overload_flags, tree, int);
/* in init.c */ /* in init.c */
extern tree expand_member_init (tree, tree); extern tree expand_member_init (tree);
extern void emit_mem_initializers (tree); extern void emit_mem_initializers (tree);
extern tree build_aggr_init (tree, tree, int); extern tree build_aggr_init (tree, tree, int);
extern tree build_init (tree, tree, int); extern tree build_init (tree, tree, int);
......
...@@ -146,7 +146,7 @@ initialize_vtbl_ptrs (addr) ...@@ -146,7 +146,7 @@ initialize_vtbl_ptrs (addr)
list = build_tree_list (type, addr); list = build_tree_list (type, addr);
/* Walk through the hierarchy, initializing the vptr in each base /* 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 bases for a class until we've initialized the vtbl for that
class. */ class. */
dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs, dfs_walk_real (TYPE_BINFO (type), dfs_initialize_vtbl_ptrs,
...@@ -664,6 +664,8 @@ emit_mem_initializers (tree mem_inits) ...@@ -664,6 +664,8 @@ emit_mem_initializers (tree mem_inits)
initializations should be performed. */ initializations should be performed. */
mem_inits = sort_mem_initializers (current_class_type, mem_inits); mem_inits = sort_mem_initializers (current_class_type, mem_inits);
in_base_initializer = 1;
/* Initialize base classes. */ /* Initialize base classes. */
while (mem_inits while (mem_inits
&& TREE_CODE (TREE_PURPOSE (mem_inits)) != FIELD_DECL) && TREE_CODE (TREE_PURPOSE (mem_inits)) != FIELD_DECL)
...@@ -704,10 +706,11 @@ emit_mem_initializers (tree mem_inits) ...@@ -704,10 +706,11 @@ emit_mem_initializers (tree mem_inits)
mem_inits = TREE_CHAIN (mem_inits); mem_inits = TREE_CHAIN (mem_inits);
} }
in_base_initializer = 0;
/* Initialize the vptrs. */ /* Initialize the vptrs. */
initialize_vtbl_ptrs (current_class_ptr); initialize_vtbl_ptrs (current_class_ptr);
/* Initialize the data members. */ /* Initialize the data members. */
while (mem_inits) while (mem_inits)
{ {
...@@ -951,16 +954,15 @@ member_init_ok_or_else (field, type, member_name) ...@@ -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 /* 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. 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 either the base _TYPE, base
Check the validity of NAME, and return a TREE_LIST of the base binfo, or the FIELD_DECL of the member. If NAME is invalid, return
_TYPE or FIELD_DECL and the INIT. If NAME is invalid, return
NULL_TREE and issue a diagnostic. NULL_TREE and issue a diagnostic.
An old style unnamed direct single base construction is permitted, An old style unnamed direct single base construction is permitted,
where NAME is NULL. */ where NAME is NULL. */
tree tree
expand_member_init (tree name, tree init) expand_member_init (tree name)
{ {
tree basetype; tree basetype;
tree field; tree field;
...@@ -997,14 +999,12 @@ expand_member_init (tree name, tree init) ...@@ -997,14 +999,12 @@ expand_member_init (tree name, tree init)
else else
basetype = NULL_TREE; basetype = NULL_TREE;
my_friendly_assert (init != NULL_TREE, 0);
if (basetype) if (basetype)
{ {
tree binfo; tree binfo;
if (current_template_parms) if (current_template_parms)
return build_tree_list (basetype, init); return basetype;
binfo = lookup_base (current_class_type, basetype, binfo = lookup_base (current_class_type, basetype,
ba_ignore, NULL); ba_ignore, NULL);
...@@ -1020,7 +1020,7 @@ expand_member_init (tree name, tree init) ...@@ -1020,7 +1020,7 @@ expand_member_init (tree name, tree init)
name, current_class_type); name, current_class_type);
return NULL_TREE; return NULL_TREE;
} }
return build_tree_list (binfo, init); return binfo;
} }
else else
{ {
...@@ -1030,7 +1030,7 @@ expand_member_init (tree name, tree init) ...@@ -1030,7 +1030,7 @@ expand_member_init (tree name, tree init)
field = name; field = name;
if (member_init_ok_or_else (field, current_class_type, name)) if (member_init_ok_or_else (field, current_class_type, name))
return build_tree_list (field, init); return field;
} }
return NULL_TREE; return NULL_TREE;
......
...@@ -7236,7 +7236,8 @@ cp_parser_mem_initializer (cp_parser* parser) ...@@ -7236,7 +7236,8 @@ cp_parser_mem_initializer (cp_parser* parser)
{ {
tree mem_initializer_id; tree mem_initializer_id;
tree expression_list; tree expression_list;
tree member;
/* Find out what is being initialized. */ /* Find out what is being initialized. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)) if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{ {
...@@ -7245,6 +7246,10 @@ cp_parser_mem_initializer (cp_parser* parser) ...@@ -7245,6 +7246,10 @@ cp_parser_mem_initializer (cp_parser* parser)
} }
else else
mem_initializer_id = cp_parser_mem_initializer_id (parser); 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 `('. */ /* Look for the opening `('. */
cp_parser_require (parser, CPP_OPEN_PAREN, "`('"); cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
/* Parse the expression-list. */ /* Parse the expression-list. */
...@@ -7256,8 +7261,9 @@ cp_parser_mem_initializer (cp_parser* parser) ...@@ -7256,8 +7261,9 @@ cp_parser_mem_initializer (cp_parser* parser)
/* Look for the closing `)'. */ /* Look for the closing `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"); cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
return expand_member_init (mem_initializer_id, in_base_initializer = 0;
expression_list);
return member ? build_tree_list (member, expression_list) : NULL_TREE;
} }
/* Parse a mem-initializer-id. /* Parse a mem-initializer-id.
......
...@@ -11093,9 +11093,12 @@ tsubst_initializer_list (t, argvec) ...@@ -11093,9 +11093,12 @@ tsubst_initializer_list (t, argvec)
decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning, decl = tsubst_copy (TREE_PURPOSE (t), argvec, tf_error | tf_warning,
NULL_TREE); 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, init = tsubst_expr (TREE_VALUE (t), argvec, tf_error | tf_warning,
NULL_TREE); NULL_TREE);
if (!init) if (!init)
; ;
else if (TREE_CODE (init) == TREE_LIST) else if (TREE_CODE (init) == TREE_LIST)
...@@ -11104,9 +11107,11 @@ tsubst_initializer_list (t, argvec) ...@@ -11104,9 +11107,11 @@ tsubst_initializer_list (t, argvec)
else if (init != void_type_node) else if (init != void_type_node)
init = convert_from_reference (init); init = convert_from_reference (init);
init = expand_member_init (decl, init); in_base_initializer = 0;
if (init)
if (decl)
{ {
init = build_tree_list (decl, init);
TREE_CHAIN (init) = inits; TREE_CHAIN (init) = inits;
inits = init; inits = init;
} }
......
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> 2003-03-15 Roger Sayle <roger@eyesopen.com>
* g77.f-torture/compile/xformat.f: New test case. * g77.f-torture/compile/xformat.f: New test case.
......
// { 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;
}
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