This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug target/29907] ARM Optimization Bug



------- 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]