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:
parent
46ea50cb66
commit
1f5a253a36
@ -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.
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
11
gcc/cp/pt.c
11
gcc/cp/pt.c
@ -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;
|
||||
}
|
||||
|
@ -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.
|
||||
|
34
gcc/testsuite/g++.dg/init/ctor2.C
Normal file
34
gcc/testsuite/g++.dg/init/ctor2.C
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user