+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.
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.
/* 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));
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;
#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
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);
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,
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)
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)
{
/* 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;
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);
name, current_class_type);
return NULL_TREE;
}
- return build_tree_list (binfo, init);
+ return binfo;
}
else
{
field = name;
if (member_init_ok_or_else (field, current_class_type, name))
- return build_tree_list (field, init);
+ return field;
}
return NULL_TREE;
{
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))
{
}
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. */
/* 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.
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)
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;
}
+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.
--- /dev/null
+// { 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;
+}