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
This commit is contained in:
Jason Merrill 2002-04-06 11:15:20 -05:00 committed by Jason Merrill
parent f62ea15730
commit a29e103468
10 changed files with 75 additions and 76 deletions

View File

@ -1,5 +1,16 @@
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.

View File

@ -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)
{

View File

@ -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));

View File

@ -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))
to the function's context. */
if (decl == current_class_ref)
{
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);
}
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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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.

View File

@ -0,0 +1,15 @@
// 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(); };
};

View File

@ -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);
}