This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix anonymous aggregates
- To: jason at redhat dot com, mark at codesourcery dot com
- Subject: [C++ PATCH] Fix anonymous aggregates
- From: Jakub Jelinek <jakub at redhat dot com>
- Date: Tue, 30 Jan 2001 21:16:05 +0100
- Cc: gcc-patches at gcc dot gnu dot org
- Reply-To: Jakub Jelinek <jakub at redhat dot com>
Hi!
anon6.C below fails to compile (one gets errors about duplicate declarations
even if one declaration is e.g. in anonymous union inside of the base class
and the other is in the derived class).
Alexandre Oliva said to this:
> This case seems to fail to compile because of a mis-reading of
> [class.union]/2. It says members of an anonymous union should have
> names distinct from the names of any other entity in the scope in
> which the anonymous union is declared. It doesn't mean their names
> should be distinct from names in scope at the point in which it is
> declared.
but from looking at the code it just looks anonymous aggregates have not
been taken into account.
This patch seems to fix this by looking up first non-anynymous containing
context for the purpose of setting INHERITED_VALUE_BINDING_P.
Bootstrapped on i386-redhat-linux, no regressions.
Ok to commit?
2001-01-30 Jakub Jelinek <jakub@redhat.com>
* decl.c (push_class_binding): If DECL is in anonymous aggregate
context, lookup its surrounding context.
* g++.old-deja/g++.other/anon6.C: New test.
* g++.old-deja/g++.other/anon7.C: New test.
--- gcc/cp/decl.c.jj Sun Jan 28 12:36:36 2001
+++ gcc/cp/decl.c Tue Jan 30 17:02:06 2001
@@ -1127,6 +1127,14 @@ push_class_binding (id, decl)
context = CP_DECL_CONTEXT (decl);
}
+ /* Skip all nested anonymous unions from context. */
+ while (ANON_AGGR_TYPE_P (context))
+ {
+ if (TREE_CODE (TREE_CHAIN (context)) != TYPE_DECL)
+ abort ();
+ context = CP_DECL_CONTEXT (TREE_CHAIN (context));
+ }
+
if (is_properly_derived_from (current_class_type, context))
INHERITED_VALUE_BINDING_P (binding) = 1;
else
--- gcc/testsuite/g++.old-deja/g++.other/anon6.C.jj Tue Jan 30 17:05:08 2001
+++ gcc/testsuite/g++.old-deja/g++.other/anon6.C Tue Jan 30 18:21:59 2001
@@ -0,0 +1,36 @@
+extern "C" void abort ();
+
+struct A {
+ union {
+ int a;
+ double b;
+ int d;
+ };
+ int c;
+};
+
+struct B : public A {
+ union {
+ double a;
+ void *c;
+ };
+ float b;
+ int e;
+};
+
+int main ()
+{
+ struct B b;
+
+ b.a = 1.5;
+ b.b = 2.5;
+ b.d = 1;
+ b.e = 2;
+ if (b.a != 1.5 || b.b != 2.5 || b.d != 1 || b.e != 2)
+ abort ();
+ b.c = &b.a;
+ b.d = b.e;
+ if (b.c != &b.a || b.d != 2)
+ abort ();
+ return 0;
+}
--- gcc/testsuite/g++.old-deja/g++.other/anon7.C.jj Tue Jan 30 17:16:56 2001
+++ gcc/testsuite/g++.old-deja/g++.other/anon7.C Tue Jan 30 17:22:52 2001
@@ -0,0 +1,24 @@
+// Build don't link:
+
+struct A {
+ union {
+ int a; // ERROR - conflicts with previous declaration
+ };
+ int a; // ERROR -
+};
+
+struct B {
+ int b; // ERROR - conflicts with previous declaration
+ union {
+ int b; // ERROR - duplicate member
+ }; // ERROR - declaration of
+};
+
+struct C {
+ union {
+ int c; // ERROR - conflicts with previous declaration
+ };
+ union {
+ int c; // ERROR - duplicate member
+ }; // ERROR - declaration of
+};
Jakub