C 6.0 May Generate Incorrect Code for Nested Conditionals

ID Number: Q61310

5.10 6.00 | 5.10 6.00

MS-DOS | OS/2

buglist5.10 buglist6.00 fixlist6.00a

Summary:

The Microsoft C Compiler versions 5.1 and 6.0 may generate incorrect

code for nested conditionals with /Ot in large or compact memory model

if the the conditionals are the same expression.

More Information:

The sample code below demonstrates the problem, as shown by this

program output:

Actual Expected

------ --------

1 0

2 1

3 2

4 3

4

The following workarounds may be used to eliminate the error:

1. Change "i < 5" in the for loop or if statement to "i <= 4".

2. Use -Od to disable optimization when compiling.

3. Use the #pragma optimization ("t", off/on) statement to

disable/enable the default -Ot optimization before and after the

function.

4. Use a combination of optimizations (for example, -Ox, -Olt, and so

forth).

The problem is with the default -Ot optimization; in particular, when

used by itself, the optimizer will generate incorrect code.

In the code sample, the compiler does not generate the instruction for

the first comparison in the for loop (as shown below). This causes the

instruction pointer to jump to location $FC176 the first time through

the loop. The end result is the same as if "i" went from 1 to 4

instead of from 0 to 4.

.

.

mov WORD PTR [bp-2], 0

$F166:

cmp WORD PTR [bp-2], 5 ;<- This "cmp" is missing

jge $FC167

push WORD PTR [bp-2]

mov ax, OFFSET DGROUP:$SG170

push ax

call _printf

add sp,4

$FC176:

inc WORD PTR [bp-2]

cmp WORD PTR [bp-2], 5

jl $F166

.

.

Microsoft has confirmed this to be a problem in C versions 5.1 and

6.0. This problem was corrected in C version 6.0a.

Sample Code

-----------

/* Compile options needed: /AL /Ot

*/

#include <stdio.h>

void main (void)

{

int i;

for ( i = 0; i < 5; i++)

if (i < 5)

printf ("%d\n", i);

}