aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2002-03-18 14:44:29 -0500
committerJason Merrill <jason@gcc.gnu.org>2002-03-18 14:44:29 -0500
commit097955f2b05559906c8cee612eaffd06c97c2f20 (patch)
treea736a461b660acd1f9c921b9d578952f38b9650a
parentc2d8e20aff09aec125e2377c3403cc1cbc1f2d00 (diff)
downloadgcc-097955f2b05559906c8cee612eaffd06c97c2f20.zip
gcc-097955f2b05559906c8cee612eaffd06c97c2f20.tar.gz
gcc-097955f2b05559906c8cee612eaffd06c97c2f20.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/init.c33
-rw-r--r--gcc/testsuite/g++.dg/lookup/anon1.C47
3 files changed, 58 insertions, 25 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 12d865e..6b791d5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,8 @@
2002-03-18 Jason Merrill <jason@redhat.com>
+ 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 54954de..53c9eef 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 0000000..e4db50d
--- /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;
+}