Commit a29e1034 by Jason Merrill Committed by Jason Merrill

re PR c++/525 (Problem with Multiple Inheritance and -pedantic)

        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.

From-SVN: r51956
parent f62ea157
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.
......
......@@ -298,27 +298,10 @@ build_scoped_method_call (exp, basetype, name, parms)
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)
{
......
......@@ -4387,7 +4387,7 @@ extern int abstract_virtuals_error PARAMS ((tree, tree));
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));
......
......@@ -1496,20 +1496,13 @@ build_member_call (type, name, parmlist)
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)
......@@ -1819,7 +1812,7 @@ resolve_offset_ref (exp)
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. */
......@@ -1827,13 +1820,7 @@ resolve_offset_ref (exp)
/* 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);
}
......@@ -3225,7 +3212,7 @@ build_delete (type, addr, auto_delete, flags, use_global_delete)
/* 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 ()
......@@ -3255,21 +3242,9 @@ 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);
......
......@@ -5559,7 +5559,11 @@ tsubst_default_argument (fn, type, arg)
};
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);
......
......@@ -1844,7 +1844,11 @@ maybe_dummy_object (type, binfop)
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);
......
......@@ -1826,10 +1826,9 @@ build_object_ref (datum, basetype, field)
}
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;
}
......
......@@ -954,7 +954,7 @@ process_init_constructor (type, init, elts)
/* 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; };
......@@ -975,29 +975,36 @@ process_init_constructor (type, init, elts)
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.
......
// 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(); };
};
......@@ -25,5 +25,6 @@ void inh::myf(int i) {
}
void top_t::myf(int i) {
inh::myf(i);
inh::myf(i); // ERROR - cannot convert to inh
mel::myf(i);
}
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