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:
parent
f62ea15730
commit
a29e103468
10 changed files with 75 additions and 76 deletions
|
@ -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.
|
||||
|
|
|
@ -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))
|
||||
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);
|
||||
|
|
|
@ -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.
|
||||
|
|
15
gcc/testsuite/g++.dg/lookup/disamb1.C
Normal file
15
gcc/testsuite/g++.dg/lookup/disamb1.C
Normal 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(); };
|
||||
};
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue