diff options
author | Jason Merrill <jason@redhat.com> | 2002-04-06 11:15:20 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2002-04-06 11:15:20 -0500 |
commit | a29e103468238970130eeccec0bc239490a91300 (patch) | |
tree | b6c3cda163f08bc0122fe499f1ac70867a11fc42 /gcc | |
parent | f62ea15730209b4024837b30e9f0eb7e39fae3d9 (diff) | |
download | gcc-a29e103468238970130eeccec0bc239490a91300.zip gcc-a29e103468238970130eeccec0bc239490a91300.tar.gz gcc-a29e103468238970130eeccec0bc239490a91300.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/cp/call.c | 19 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 2 | ||||
-rw-r--r-- | gcc/cp/init.c | 51 | ||||
-rw-r--r-- | gcc/cp/pt.c | 6 | ||||
-rw-r--r-- | gcc/cp/tree.c | 6 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 7 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 33 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/lookup/disamb1.C | 15 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.jason/access8.C | 3 |
10 files changed, 76 insertions, 77 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6f2a6ab..524cbea 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 1a74f74..d341fb0 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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) { diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b65467b..8b3a256 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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)); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 57b3dba..5caa69c 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b705783..30a6ddb 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index e0f7361..641d82b 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 593e2bb..be07b2e 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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; } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 48caade..d7ac3d7 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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. diff --git a/gcc/testsuite/g++.dg/lookup/disamb1.C b/gcc/testsuite/g++.dg/lookup/disamb1.C new file mode 100644 index 0000000..8a3be65 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/disamb1.C @@ -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(); }; +}; diff --git a/gcc/testsuite/g++.old-deja/g++.jason/access8.C b/gcc/testsuite/g++.old-deja/g++.jason/access8.C index c8addcd..91e114a 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/access8.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/access8.C @@ -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); } |