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]

c/2227: generates unsigned compare in comparison of int to sizeof()



>Number:         2227
>Category:       c
>Synopsis:       generates unsigned compare in comparison of int to sizeof()
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          wrong-code
>Submitter-Id:   net
>Arrival-Date:   Thu Mar 08 07:46:01 PST 2001
>Closed-Date:
>Last-Modified:
>Originator:     Chris Latham
>Release:        cygnus-2.7.2-960126
>Organization:
>Environment:
Pentium Xeon-based PC using the Motorola 68k GCC targeting a 68060 processor
>Description:
The following code generates an unsigned comparison when a signed comparison is obviously intended:

  if(((int) end_address - (int) begin_address) > (sizeof(RCCS_DATA) * 4) ||
   (end_address > Idtable[rccs_id]->raw_data_end_address) ||
   (end_address < Idtable[rccs_id]->raw_data_begin_address))
  {
    printf("Entered Conditional\n");
 
    memcpy((char *) &IDtable[rccs_id],(char *)Idtable[rccs_id],sizeof(IDTABLE_DATA));
    return;
  }

The pertinent values are as follows:

  int *begin_address          = 0x100F7834
  int *end_address            = 0x100F3834
  int *raw_data_begin_address = 0x100F3834
  int *raw_data_end_address   = 0x100F9834
  sizeof(RCCS_DATA)           = 8212

Using the '-S' option, the assembly output is as follows:

  movel a6@(12),a6@(-16)
  movel a6@(16),a6@(-20)
  clrl a6@(-8)
  movel a6@(-20),d0
  subl a6@(-16),d0
  cmpl #32848,d0
  jhi L3

The conditional block is entered, and the printf() is seen even though the condition is not satisfied.  I believe this is because BHI (JHI above) does an unsigned comparison of the values resulting in the negative left-value being larger than the right-value.
>How-To-Repeat:
Compile the code above in the ANSI C compiler mode.
>Fix:
The problem was solved by adding a cast to type int in front of the sizeof().  This would seem to indicate that sizeof() is being promoted to an unsigned int and that the conditional further promotes the left-value to an unsigned int when it is clearly intended to be an int.  The corrected code is as follows:

  if(((int) end_address - (int) begin_address) > (int)(sizeof(RCCS_DATA) * 4) ||
   (end_address > Idtable[rccs_id]->raw_data_end_address) ||
   (end_address < Idtable[rccs_id]->raw_data_begin_address))
  {
    printf("Entered Conditional\n");
 
    memcpy((char *) &IDtable[rccs_id],(char *)Idtable[rccs_id],sizeof(IDTABLE_DATA));
    return;
  }

This generates the expected assembly output:

  movel a6@(12),a6@(-16)
  movel a6@(16),a6@(-20)
  clrl a6@(-8)
  movel a6@(-20),d0
  subl a6@(-16),d0
  cmpl #32848,d0
  jgt L3

The BGT (JGT above) instruction is what we were looking for to begin with.
>Release-Note:
>Audit-Trail:
>Unformatted:


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