| Bug#: 15471 | Product: gcc | Version: 3.4.0 | |
| Host: i486-slackware-linux | Target: i486-slackware-linux | Build: n/a | |
| Status: RESOLVED | Severity: critical | Priority: P2 | |
| Resolution: FIXED | Assigned To: mark@codesourcery.com | Reported By: us15@os.inf.tu-dresden.de | |
| Component: c++ | Target Milestone: 3.4.1 | ||
| Summary: [3.4/4.0 Regression] Incorrect member pointer offsets in anonymous structs/unions | |||
| Keywords: wrong-code | |||
| Opened: 2004-05-15 21:39 | |||
| Description: | Last confirmed: 2004-05-26 12:07 | Opened: 2004-05-15 21:39 |
The code below outputs the addresses of member variables of class "myclass"
using a table of pointers to member variables and using an instance of
"myclass". I'd expect both methods to produce the same result, however, the
addresses of member variables x and y are wrong when applying the member
pointers to object "foo".
Compiler version:
Reading specs from /usr/lib/gcc/i486-slackware-linux/3.4.0/specs
Configured with: ../gcc-3.4.0/configure --prefix=/usr --enable-shared
--enable-threads=posix --enable-__cxa_atexit --disable-checking --with-gnu-ld
--verbose --target=i486-slackware-linux --host=i486-slackware-linux
Thread model: posix
gcc version 3.4.0
Example code to demonstrate the problem:
#include <stdio.h>
class myclass
{
public:
union
{
unsigned state[5];
struct
{
unsigned a;
unsigned b;
union
{
unsigned nums[2];
struct
{
unsigned x, y;
};
};
unsigned c;
};
};
};
unsigned
myclass::*
members[] = {
&myclass::a,
&myclass::b,
&myclass::x,
&myclass::y,
&myclass::c,
};
myclass
foo;
int
main (void)
{
printf ("a -> %p %p\n", &(foo.*members[0]), &foo.a);
printf ("b -> %p %p\n", &(foo.*members[1]), &foo.b);
printf ("x -> %p %p\n", &(foo.*members[2]), &foo.x); // differs
printf ("y -> %p %p\n", &(foo.*members[3]), &foo.y); // differs
printf ("c -> %p %p\n", &(foo.*members[4]), &foo.c);
return 0;
}
anonymous structs are an extension to c++ so they could act any way.
I don't know what we're supposed to do here, but this is indeed
surprising:
-----------------------
#include <stdio.h>
struct myclass {
unsigned a;
union {
unsigned x;
};
};
int main () {
myclass foo;
unsigned myclass::* member = &myclass::x;
printf ("x -> %p %p\n", &(foo.*member), &foo.x);
}
-----------------------
One would expect the two pointers to be the same, but they're not:
g/x> /home/bangerth/bin/gcc-3.4-pre/bin/c++ x.cc ; ./a.out
x -> 0xbfffeaa0 0xbfffeaa4
It has indeed to do with the anonymous union (which in this case only
contains a single element), since if I remove it and bring the variable
x to the myclass scope, then the problem disappears.
W.
I couldn't find the relevant paragraph in the standard, thus I am not sure this is actually legal code. It must be noted that EDG in strict mode accepts it and generates the same address for both pointers (which is by no doubt the correct behaviour, once we assume the code is legal). GCC rejects this snippet up to 3.4. Since 3.4, we accept the snippet but generate wrong code with it. I rate this as a regression nonetheless, since wrong-code is much worse than what we used to do.
Subject: Bug 15471 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: mmitchel@gcc.gnu.org 2004-05-28 22:29:44 Modified files: gcc/cp : ChangeLog decl2.c init.c name-lookup.c typeck.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/expr: ptrmem4.C gcc/testsuite/g++.dg/template: operator3.C gcc/testsuite/g++.dg/warn: noeffect5.C Log message: PR c++/15083 * decl2.c (delete_sanity): Set TREE_SIDE_EFFECTS on a DELETE_EXPR, even in a templat.e * init.c (build_new): Likewise. PR c++/15640 * name-lookup.c (arg_assoc): Robustify. PR c++/15471 * typeck.c (unary_complex_lvalue): Use context_for_name_lookup when determining the scope to use for a pointer to member. PR c++/15083 * g++.dg/warn/noeffect5.C: New test. PR c++/15471 * g++.dg/expr/ptrmem4.C: New test. PR c++/15640 * g++.dg/template/operator3.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3892.2.107&r2=1.3892.2.108 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/decl2.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.695.4.7&r2=1.695.4.8 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/init.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.356.2.9&r2=1.356.2.10 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/name-lookup.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.34.2.12&r2=1.34.2.13 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/typeck.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.519.2.16&r2=1.519.2.17 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3389.2.185&r2=1.3389.2.186 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/expr/ptrmem4.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/operator3.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.1.2.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/warn/noeffect5.C.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=NONE&r2=1.2.4.1
Subject: Bug 15471 CVSROOT: /cvs/gcc Module name: gcc Changes by: mmitchel@gcc.gnu.org 2004-05-28 22:35:50 Modified files: gcc/cp : ChangeLog decl2.c init.c name-lookup.c typeck.c gcc/testsuite : ChangeLog Added files: gcc/testsuite/g++.dg/expr: ptrmem4.C gcc/testsuite/g++.dg/template: operator3.C gcc/testsuite/g++.dg/warn: noeffect6.C Log message: PR c++/15083 * decl2.c (delete_sanity): Set TREE_SIDE_EFFECTS on a DELETE_EXPR, even in a templat.e * init.c (build_new): Likewise. PR c++/15640 * name-lookup.c (arg_assoc): Robustify. PR c++/15471 * typeck.c (unary_complex_lvalue): Use context_for_name_lookup when determining the scope to use for a pointer to member. PR c++/15083 * g++.dg/warn/noeffect5.C: New test. PR c++/15471 * g++.dg/expr/ptrmem4.C: New test. PR c++/15640 * g++.dg/template/operator3.C: New test. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4064&r2=1.4065 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/decl2.c.diff?cvsroot=gcc&r1=1.709&r2=1.710 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/init.c.diff?cvsroot=gcc&r1=1.370&r2=1.371 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/name-lookup.c.diff?cvsroot=gcc&r1=1.54&r2=1.55 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/typeck.c.diff?cvsroot=gcc&r1=1.544&r2=1.545 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/ChangeLog.diff?cvsroot=gcc&r1=1.3789&r2=1.3790 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/expr/ptrmem4.C.diff?cvsroot=gcc&r1=1.1&r2=1.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/template/operator3.C.diff?cvsroot=gcc&r1=1.1&r2=1.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/testsuite/g++.dg/warn/noeffect6.C.diff?cvsroot=gcc&r1=NONE&r2=1.1
Subject: Bug 15471 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: mmitchel@gcc.gnu.org 2004-05-28 23:33:40 Modified files: gcc/cp : ChangeLog cp-tree.h expr.c typeck.c Log message: PR c++/15471 * typeck.c (unary_complex_lvalue): Use context_for_name_lookup when determining the scope to use for a pointer to member. (lookup_anon_field): Give it external linkage. * cp-tree.h (lookup_anon_field): Declare it. * expr.c (cplus_expand_constant): Use it. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.3892.2.108&r2=1.3892.2.109 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/cp-tree.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.946.4.11&r2=1.946.4.12 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/expr.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.75.4.1&r2=1.75.4.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/typeck.c.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.519.2.17&r2=1.519.2.18
Subject: Bug 15471 CVSROOT: /cvs/gcc Module name: gcc Changes by: mmitchel@gcc.gnu.org 2004-05-28 23:34:39 Modified files: gcc/cp : ChangeLog cp-tree.h expr.c typeck.c Log message: PR c++/15471 * typeck.c (unary_complex_lvalue): Use context_for_name_lookup when determining the scope to use for a pointer to member. (lookup_anon_field): Give it external linkage. * cp-tree.h (lookup_anon_field): Declare it. * expr.c (cplus_expand_constant): Use it. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/ChangeLog.diff?cvsroot=gcc&r1=1.4065&r2=1.4066 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/cp-tree.h.diff?cvsroot=gcc&r1=1.968&r2=1.969 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/expr.c.diff?cvsroot=gcc&r1=1.77&r2=1.78 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/cp/typeck.c.diff?cvsroot=gcc&r1=1.545&r2=1.546