2002-04-06 Jason Merrill <jason@redhat.com>
+ PR c++/525
+ * init.c (build_member_call): Use build_scoped_ref.
+ (resolve_offset_ref): Likewise.
+ * call.c (build_scoped_method_call): Likewise.
+ * tree.c (maybe_dummy_object): Kludge around current_class_type being
+ wrong.
+ * typeck2.c (build_scoped_ref): Return the binfo via binfo_p parm.
+ * cp-tree.h: Adjust.
+
+ * init.c (push_base_cleanups): Just use build_scoped_method_call.
+
PR c++/6179
* method.c (implicitly_declare_fn): Pass unqualified type to
synthesize_exception_spec.
return error_mark_node;
}
- if (! binfo)
- {
- binfo = lookup_base (type, basetype, ba_check, NULL);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (! binfo)
- error_not_base_type (basetype, type);
- }
+ decl = build_scoped_ref (exp, basetype, &binfo);
if (binfo)
{
- if (TREE_CODE (exp) == INDIRECT_REF)
- {
- decl = build_base_path (PLUS_EXPR,
- build_unary_op (ADDR_EXPR, exp, 0),
- binfo, 1);
- decl = build_indirect_ref (decl, NULL);
- }
- else
- decl = build_scoped_ref (exp, basetype);
-
/* Call to a destructor. */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
extern tree store_init_value PARAMS ((tree, tree));
extern tree digest_init PARAMS ((tree, tree, tree *));
-extern tree build_scoped_ref PARAMS ((tree, tree));
+extern tree build_scoped_ref PARAMS ((tree, tree, tree *));
extern tree build_x_arrow PARAMS ((tree));
extern tree build_m_component_ref PARAMS ((tree, tree));
extern tree build_functional_cast PARAMS ((tree, tree));
decl = maybe_dummy_object (type, &basetype_path);
/* Convert 'this' to the specified type to disambiguate conversion
- to the function's context. Apparently Standard C++ says that we
- shouldn't do this. */
- if (decl == current_class_ref
- && ! pedantic
- && ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))
- {
- tree olddecl = current_class_ptr;
- tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));
- if (oldtype != type)
- {
- tree newtype = build_qualified_type (type, TYPE_QUALS (oldtype));
- decl = convert_force (build_pointer_type (newtype), olddecl, 0);
- decl = build_indirect_ref (decl, NULL);
- }
+ to the function's context. */
+ if (decl == current_class_ref)
+ {
+ basetype_path = NULL_TREE;
+ decl = build_scoped_ref (decl, type, &basetype_path);
+ if (decl == error_mark_node)
+ return error_mark_node;
}
if (method_name == constructor_name (type)
if (TREE_CODE (member) == FIELD_DECL
&& (base == current_class_ref || is_dummy_object (base)))
{
- tree binfo = TYPE_BINFO (current_class_type);
+ tree binfo = NULL_TREE;
/* Try to get to basetype from 'this'; if that doesn't work,
nothing will. */
/* First convert to the intermediate base specified, if appropriate. */
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
- {
- binfo = binfo_or_else (TYPE_OFFSET_BASETYPE (type),
- current_class_type);
- if (!binfo)
- return error_mark_node;
- base = build_base_path (PLUS_EXPR, base, binfo, 1);
- }
+ base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type), &binfo);
return build_component_ref (base, member, binfo, 1);
}
/* At the beginning of a destructor, push cleanups that will call the
destructors for our base classes and members.
- Called from setup_vtbl_ptr. */
+ Called from begin_destructor_body. */
void
push_base_cleanups ()
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (base_type))
{
- tree base_ptr_type = build_pointer_type (base_type);
- expr = current_class_ptr;
-
- /* Convert to the basetype here, as we know the layout is
- fixed. What is more, if we let build_method_call do it,
- it will use the vtable, which may have been clobbered
- by the deletion of our primary base. */
-
- expr = build1 (NOP_EXPR, base_ptr_type, expr);
- expr = build (PLUS_EXPR, base_ptr_type, expr,
- BINFO_OFFSET (vbase));
- expr = build_indirect_ref (expr, NULL);
- expr = build_method_call (expr, base_dtor_identifier,
- NULL_TREE, vbase,
- LOOKUP_NORMAL);
+ expr = build_scoped_method_call (current_class_ref, vbase,
+ base_dtor_identifier,
+ NULL_TREE);
expr = build (COND_EXPR, void_type_node, cond,
expr, void_zero_node);
finish_decl_cleanup (NULL_TREE, expr);
};
we must be careful to do name lookup in the scope of S<T>,
- rather than in the current class. */
+ rather than in the current class.
+
+ ??? current_class_type affects a lot more than name lookup. This is
+ very fragile. Fortunately, it will go away when we do 2-phase name
+ binding properly. */
if (DECL_CLASS_SCOPE_P (fn))
pushclass (DECL_CONTEXT (fn), 2);
if (binfop)
*binfop = binfo;
- if (current_class_ref && context == current_class_type)
+ if (current_class_ref && context == current_class_type
+ // Kludge: Make sure that current_class_type is actually correct.
+ // It might not be if we're in the middle of tsubst_default_argument.
+ && same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)),
+ current_class_type))
decl = current_class_ref;
else
decl = build_dummy_object (context);
}
else if (is_aggr_type (basetype, 1))
{
- tree binfo = binfo_or_else (basetype, dtype);
- if (binfo)
- return build_x_component_ref (build_scoped_ref (datum, basetype),
- field, binfo, 1);
+ tree binfo = NULL_TREE;
+ datum = build_scoped_ref (datum, basetype, &binfo);
+ return build_x_component_ref (datum, field, binfo, 1);
}
return error_mark_node;
}
\f
/* Given a structure or union value DATUM, construct and return
the structure or union component which results from narrowing
- that value by the type specified in BASETYPE. For example, given the
+ that value to the base specified in BASETYPE. For example, given the
hierarchy
class L { int ii; };
I used to think that this was nonconformant, that the standard specified
that first we look up ii in A, then convert x to an L& and pull out the
ii part. But in fact, it does say that we convert x to an A&; A here
- is known as the "naming class". (jason 2000-12-19) */
+ is known as the "naming class". (jason 2000-12-19)
+
+ BINFO_P points to a variable initialized either to NULL_TREE or to the
+ binfo for the specific base subobject we want to convert to. */
tree
-build_scoped_ref (datum, basetype)
+build_scoped_ref (datum, basetype, binfo_p)
tree datum;
tree basetype;
+ tree *binfo_p;
{
- tree ref;
tree binfo;
if (datum == error_mark_node)
return error_mark_node;
- binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
+ if (*binfo_p)
+ binfo = *binfo_p;
+ else
+ binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (!binfo)
- return error_not_base_type (TREE_TYPE (datum), basetype);
-
- ref = build_unary_op (ADDR_EXPR, datum, 0);
- ref = build_base_path (PLUS_EXPR, ref, binfo, 1);
+ if (!binfo || binfo == error_mark_node)
+ {
+ *binfo_p = NULL_TREE;
+ if (!binfo)
+ error_not_base_type (basetype, TREE_TYPE (datum));
+ return error_mark_node;
+ }
- return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
+ *binfo_p = binfo;
+ return build_base_path (PLUS_EXPR, datum, binfo, 1);
}
/* Build a reference to an object specified by the C++ `->' operator.
--- /dev/null
+// PR c++/525
+// Bug: With -pedantic, we weren't converting this to D1* for the call.
+
+struct A
+{
+ void f();
+};
+
+struct B1: public A {};
+struct B2: public A {};
+
+struct C: public B1, public B2
+{
+ void g() { B1::f(); };
+};
}
void top_t::myf(int i) {
- inh::myf(i);
+ inh::myf(i); // ERROR - cannot convert to inh
+ mel::myf(i);
}