Bug 447253

Summary: gcc with optimization higher than -O2 generates wrong code
Product: Red Hat Enterprise Linux 5 Reporter: ritz <rkhadgar>
Component: gccAssignee: Jakub Jelinek <jakub>
Status: CLOSED NOTABUG QA Contact:
Severity: low Docs Contact:
Priority: low    
Version: 5.2CC: tao
Target Milestone: rc   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2008-05-19 08:08:09 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
Test case none

Description ritz 2008-05-19 05:56:45 UTC
Description of problem:
compiler generates incorrect code, when compiled with optimization higher than O2

As quoted by customer - 
Gcc prints no warnings and this is really bad. Even FlexeLint prints warning
olny on -w3, i.e. very hight level of warnings though it is a bug from ISO point
of view."

"Why don't they print a warning/error?
How can we fix our legacy code? We even have reinterpret_cast which suppresses
warnings about C-style cast.
This is a real problem. Do they have such a request already? Absence of warning
is a bug. The code was perfectly legal for many years before standards were
accepted. It is a change of language without a warning. Must be error or warning. \

"Yes, there supposed to be a warning dereferencing type-punned pointer will
break strict-aliasing rules but even with -Wall it is absent."

On RHEL 5.1 , this function
   void CopyData (int **pdst, int **psrc) {
       *pdst = *psrc;
       *(int*)pdst |= 0x1;
   }
generates incorrect code if using gcc 4.1.2p2 with optimization -O2 and -O3.

It generates
   mov    (%edx),%edx
   orl    $0x1,(%eax)
   mov    %edx,(%eax)

where "mov" destroys the result or "orl". With -O1 the order of "orl" and "mov"
is reverse.
On Solaris 86 the same version of gcc works fine. 64-bit compiler and 32-bit one
both work incorrectly in both -m32 and -m64 modes.
Main one prints two pointers. They must be different if code is correct and the
same if the code is wrong.


Version-Release number of selected component (if applicable):
gcc 4.1.2p2
This issue is also reproducible on FC9 with gcc 4.3.0

How reproducible:
Test case attached.

Steps to Reproduce:
1. ./build
2. ./m

Actual results:
Value prined are the same

Expected results:
value printed should be different

Additional info:
Test case attached.

Comment 1 ritz 2008-05-19 05:56:46 UTC
Created attachment 305902 [details]
Test case

Comment 3 Jakub Jelinek 2008-05-19 08:08:09 UTC
Eh, this code is invalid even in ISO C90, so at least for 18 years.
-Wstrict-aliasing=3 doesn't warn in this case because it would have too many
false positives, many programs cast one type of pointer to another and
dereference it that way, that in itself is not a bug.  The problem is if you are
accessing some object using a wrong type.
Say
int i;
void bar (int **p)
{
  *(int *) p |= 1;
}
void foo (void)
{
  bar ((int **) (void *) &i);
}
is fine, i is accessed through a compatible type.  The documentation for
-Wstrict-aliasing clearly states that the warning catches only the most common
problems and still it has many false positives too.  ISO C doesn't require
diagnostics in this case and in many cases aliasing violations are even
theoretically impossible to detect, without whole program analysis.

If you have legacy code which doesn't honor the aliasing requirements, you can
always compile with -fno-strict-aliasing.  That is of course a performance
penalty, but you can that way postpone legacy code analysis.