This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug target/29907] ARM Optimization Bug
- From: "rearnsha at gcc dot gnu dot org" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 20 Nov 2006 16:59:08 -0000
- Subject: [Bug target/29907] ARM Optimization Bug
- References: <bug-29907-13594@http.gcc.gnu.org/bugzilla/>
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
------- Comment #3 from rearnsha at gcc dot gnu dot org 2006-11-20 16:59 -------
The fact that your code does not work correctly when compiled by gcc-4.1 does
not automatically imply that there is a bug, it may just be that other versions
of the compiler missed an optimization opportunity.
The C standard permits structures to have common layout for *initial* elements
and casting between these *is* permitted. But your code is taking the address
of an element in the *middle* of the structure and this has no defined
behaviour in the standard. Consider, for example
struct a
{
short a;
short b;
long c;
};
struct b
{
short b;
long c;
};
When these get laid out in memory, the first structure takes up two words (on a
32-bit machine); the second structure also takes up two words, with some
padding in the middle. It's therefore clearly unsafe to set a struct b* = &a.b
and to dereference c, since this would result in an alignment fault.
Further investigation, however, suggests that there is a bug as can be
demonstrated by a small modification of your test-case:
typedef struct Chain_Node_struct Chain_Node;
struct Chain_Node_struct {
Chain_Node *next;
Chain_Node *previous;
};
typedef struct {
Chain_Node *permanent_null;
Chain_Node *last;
Chain_Node *first;
} Chain_Control;
extern Chain_Control *rdy;
void func(Chain_Node *a )
{
if( rdy->first != rdy->last )
{
Chain_Node *next;
Chain_Node *previous;
Chain_Node *old_last_node;
next = a->next;
previous = a->previous;
next->previous = previous;
previous->next = next;
a->next = (Chain_Node*)&rdy->permanent_null;
old_last_node = rdy->last;
rdy->last = a;
old_last_node->next = a;
a->previous = old_last_node;
}
}
note that now we can take the address of permanent_null and treat it as a
Chain_Node * since it is the first element of the structure and the structures
have identical initial layout.
4.2 seems to have fixed this problem, but I've no idea when this was done.
--
rearnsha at gcc dot gnu dot org changed:
What |Removed |Added
----------------------------------------------------------------------------
Status|RESOLVED |UNCONFIRMED
Resolution|INVALID |
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29907