From 097955f2b05559906c8cee612eaffd06c97c2f20 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 18 Mar 2002 14:44:29 -0500 Subject: [PATCH] re PR c++/2039 (bad code generated for access to unnamed union in base class) PR c++/2039 * init.c (resolve_offset_ref): Hand off to build_component_ref. From-SVN: r50991 --- gcc/cp/ChangeLog | 3 ++ gcc/cp/init.c | 33 +++++--------------- gcc/testsuite/g++.dg/lookup/anon1.C | 47 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 25 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/anon1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 12d865e8bb89..6b791d54bde5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,8 @@ 2002-03-18 Jason Merrill + PR c++/2039 + * init.c (resolve_offset_ref): Hand off to build_component_ref. + PR c++/4222, c++/5995 * call.c (build_over_call): Fix empty class logic. diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 54954de566e6..53c9eef17493 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1819,9 +1819,7 @@ resolve_offset_ref (exp) if (TREE_CODE (member) == FIELD_DECL && (base == current_class_ref || is_dummy_object (base))) { - tree expr; - - basetype = DECL_CONTEXT (member); + tree binfo = TYPE_BINFO (current_class_type); /* Try to get to basetype from 'this'; if that doesn't work, nothing will. */ @@ -1829,30 +1827,15 @@ resolve_offset_ref (exp) /* First convert to the intermediate base specified, if appropriate. */ if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE) - base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type)); - - /* Don't check access on the conversion; we might be after a member - promoted by an access- or using-declaration, and we have already - checked access for the member itself. */ - basetype = lookup_base (TREE_TYPE (base), basetype, ba_ignore, NULL); - expr = build_base_path (PLUS_EXPR, base, basetype, 1); - - if (expr == error_mark_node) - return error_mark_node; - - type = TREE_TYPE (member); - if (TREE_CODE (type) != REFERENCE_TYPE) { - int quals = cp_type_quals (type) | cp_type_quals (TREE_TYPE (expr)); - - if (DECL_MUTABLE_P (member)) - quals &= ~TYPE_QUAL_CONST; - - type = cp_build_qualified_type (type, quals); + 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); } - - expr = build (COMPONENT_REF, type, expr, member); - return convert_from_reference (expr); + + return build_component_ref (base, member, binfo, 1); } /* Ensure that we have an object. */ diff --git a/gcc/testsuite/g++.dg/lookup/anon1.C b/gcc/testsuite/g++.dg/lookup/anon1.C new file mode 100644 index 000000000000..e4db50d946cb --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/anon1.C @@ -0,0 +1,47 @@ +// PR c++/2039 +// Test that a scoped reference to a member of an anonymous union member of +// a base class works properly. + +// { dg-do run } + +struct A +{ + long ia1; + union + { + long ia2; + }; +}; + +struct B : public A +{ + void f1(); + void f2(); +}; + +void B::f1() +{ + ia1 = 11; + ia2 = 22; +} + +void B::f2() +{ + ia1 = 33; + A::ia2 = 44; // <<< !!!???? +} + +int main() +{ + B x; + + x.f1(); + if (x.ia1 != 11 || x.ia2 != 22) + return 1; + + x.f2(); + if (x.ia1 != 33 || x.ia2 != 44) + return 1; + + return 0; +}