aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2003-03-16 14:36:43 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2003-03-16 14:36:43 +0000
commit1f5a253a36c2e680af7a627a5077a61fb8afe6b6 (patch)
tree7874404e7e5a23052c2153596208ca845cfa33ef /gcc
parent46ea50cb66f3edc9f5f474067e61bfe39c41cb06 (diff)
downloadgcc-1f5a253a36c2e680af7a627a5077a61fb8afe6b6.zip
gcc-1f5a253a36c2e680af7a627a5077a61fb8afe6b6.tar.gz
gcc-1f5a253a36c2e680af7a627a5077a61fb8afe6b6.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/class.c21
-rw-r--r--gcc/cp/cp-tree.h6
-rw-r--r--gcc/cp/init.c22
-rw-r--r--gcc/cp/parser.c12
-rw-r--r--gcc/cp/pt.c11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/init/ctor2.C34
8 files changed, 104 insertions, 21 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7cb5c9f..4a240a0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 6b89bec..0df87ae 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -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));
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 59699cd..587acbc 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 99812c6..d854283 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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;
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 1c83227..f80c260 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 410cd8f..87430b6 100644
--- a/gcc/cp/pt.c
+++ b/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;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 92db48b..d4558f6 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.dg/init/ctor2.C b/gcc/testsuite/g++.dg/init/ctor2.C
new file mode 100644
index 0000000..cf426f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/ctor2.C
@@ -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;
+}