C9204002: C 6.x May Generate Bad Code with /Oweg or /Oaeg

ID Number: Q83219

6.00 6.00a 6.00ax | 6.00 6.00a

MS-DOS | OS/2

buglist6.00

Summary:

PROBLEM ID: C9204002

SYMPTOMS

The Microsoft C Compiler versions 6.0, 6.0a, and 6.0ax may generate

incorrect code when optimizing with /Oweg or /Oaeg.

CAUSE

The C compiler tries to optimize the code by saving a repeated

value for future reference, but incorrectly calculates the value.

The value is incorrectly calculated because of the register

allocation method being used with these compiler options.

RESOLUTION

Use one of the following workarounds to eliminate the problem in C

versions 6.0, 6.0a, and 6.0ax:

1. Compile with the /Os (size optimization) option

-or-

2. Do not compile with the /Og, /Oe, /Oa, or /Ow option.

-or-

3. Use the optimize pragma to change the optimizations for the function

in which the error occurs. The "#pragma optimize" directive is

documented on page 7 of "Microsoft C Advanced Programming

Techniques."

-or-

4. Compile with the /qc (quick compile) option.

-or-

4. Change the code in some way. In the example below, if you declare

var2 as volatile, the program works correctly. Using volatile

causes the compiler to recalculate the 10*var2 for the return

statement. However, the compiler still generates the first instance

of 10*var2 incorrectly. The volatile type-qualifier tells the

compiler that the variable may change at any time. A description of

the volatile keyword can be found on page 14 of "Microsoft C

Advanced Programming Techniques."

STATUS

Microsoft has confirmed this to be a problem in C versions 6.0,

6.0a, and 6.0ax. This problem was corrected in C/C++ version 7.0.

More Information:

The sample code below demonstrates the problem.

Sample Code

-----------

/* Compile options needed: /Oweg or /Oaeg

Program prints 16 instead of 20.

*/

#include <stdio.h>

int var1 = 29;

char var2 = 2;

char func1 (char arg3)

{

if ((arg3-'0') > (char)(var1 - 10*var2)) /* Optimize bug 10*var2 */

{

if (0 < var1)

return -1;

else

return 0;

}

else

return (char)((arg3-'0') + 10*var2); /* Reuses wrong result */

}

void main()

{

printf("%d",func1('0'));

}

Additional reference words: 6.00 6.00a 6.00ax