Bug 20185 - assignment error in inline function
Summary: assignment error in inline function
Status: RESOLVED DUPLICATE of bug 21920
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.3.4
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-02-24 10:29 UTC by Dirk Clemens
Modified: 2005-07-23 22:49 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Dirk Clemens 2005-02-24 10:29:35 UTC
// Postet by dirk@cle-mens.de
// Compiler Error found:
//	gcc (GCC) 3.3.4 (pre 3.3.5 20040809)
//	under SuSE Linux kernel 2.6.8-24.10-default (i386)
//
// This Bug is a little bit different in relation to bug #20184
//
// If this littel programm is compiled with the option -O2
// the assignment in the inline function was wrong.
// If I remove the 'inline' the result is correct.
//
// Compiled with: g++ -Wall error.cpp
//		-> OK, printout = 0000000000000000
//
// Compiled with: g++ -Wall -O2 error.cpp
//		-> ERROR, printout = 0804836d00000000
//
// Compiled with: g++ -Wall -O2 error.cpp,,
//  but without 'inline' for func data::data()
//		-> OK, printout = 0000000000000000
//

#include <stdlib.h>
#include <stdio.h>

typedef unsigned int uint32;
typedef unsigned long long uint64;

class data
{
 public:
    uint32 lo;
    uint32 hi;

    data ( uint32 num );
    operator uint64 () const;
};

inline data::data ( uint32 num ) { lo = num; hi = -(num<0); }
inline data::operator uint64 () const { return *(uint64*)this; }

int main()
{
    printf("sizeof(uint32)=%d\n",sizeof(uint32));
    printf("sizeof(uint64)=%d\n",sizeof(uint64));
    printf("sizeof(data)  =%d\n",  sizeof(data));

    uint32 tab[] = { 0,0,0,0,0 };
    uint32 *p = tab;

    uint64 u64 = data(*p++);
    printf("%016llx\n",u64);
}
Comment 1 Falk Hueffner 2005-02-24 11:00:46 UTC
Invalid for the same reason as PR 20184...
Comment 2 Dirk Clemens 2005-02-24 12:21:48 UTC
(In reply to comment #1)
> Invalid for the same reason as PR 20184...
> 

I get the same failure if I use (little endian system)
  inline data::operator uint64 () const 
        { return *reinterpret_cast<const uint64*>(this); }
or
  inline data::operator uint64 () const 
        { return *reinterpret_cast<const uint64*>(&lo); }
or
  inline data::operator uint64 () const 
        { return *(uint64*)&lo; }

It looks like an optimation failure.
The function has to copy 64 bits, but it only copies the low 32 bits into the
result. For verifying this, I have changed the values of table 'tab[]' into
{1,1,1,1,1}

Let's have a lokk into the assembler listing

        movl    $1, -48(%ebp)
        movl    $0, -44(%ebp)  // this is data::data(1) -> u64

        pushl   %edx            // the hi-32-bits of u64, but edx was not set
        movl    -48(%ebp), %eax // the low-32-bit of u64
        pushl   %eax
        pushl   $.LC3
        call    printf

And again: This failure appears only with the combination of inline and the
option -O2.

-------
Another question: I marked this bug 'reopen' while I'm posting this. Is this the
correct way?
Comment 3 Falk Hueffner 2005-02-24 12:59:06 UTC
(In reply to comment #2)
> (In reply to comment #1)
> > Invalid for the same reason as PR 20184...
> > 
> 
> I get the same failure if I use (little endian system)
>   inline data::operator uint64 () const 
>         { return *reinterpret_cast<const uint64*>(this); }

Okay, once again. The ISO C++ standard says (3.10:15):

  If a program attempts to access the stored value of an object through
  an lvalue of other than one of the following types the behavior is
  undefined:

   -- the dynamic type of the object,
   -- a cv-qualified version of the dynamic type of the object,
   -- a type that is the signed or unsigned type corresponding to the
      dynamic type of the object,
   -- a type that is the signed or unsigned type corresponding to a
      cv-qualified version of the dynamic type of the object,
   -- an aggregate or union type that includes one of the
      aforementioned types among its members (including, recursively, a
      member of a subaggregate or contained union),
   -- a type that is a (possibly cv-qualified) base class type of the
      dynamic type of the object,
   -- a char or unsigned char type.

You are accessing an object of type "class data" through an lvalue of type
"uint64". The type "uint64" here matches none of the mentioned cases; therefore,
the behavior is undefined. This means that printing 0000000000000000, printing
0804836d00000000, crashing, or formatting your hard disk are all correct
results of your code, and there is no bug in the compiler for generating
code that does this.
Comment 4 Dirk Clemens 2005-02-24 13:56:02 UTC
(In reply to comment #3)
> (In reply to comment #2)
> > (In reply to comment #1)
>
> You are accessing an object of type "class data" through an lvalue of type
> "uint64". The type "uint64" here matches none of the mentioned cases; 

But if you take this line:
 inline data::operator uint64 () const 
        { return *(uint64*)&lo; }
... we have no class data.

And please see bug #20189: same error with a C example.

-------
Another question again: I marked this bug 'reopen' while I'm posting this. Is
this the
correct way?
Comment 5 Andrew Pinski 2005-02-24 14:04:53 UTC
Invalid you are violating C++98 aliasing rules.
Comment 6 Falk Hueffner 2005-02-24 14:21:22 UTC
(In reply to comment #4)
> (In reply to comment #3)
> > (In reply to comment #2)
> > > (In reply to comment #1)
> >
> > You are accessing an object of type "class data" through an lvalue of type
> > "uint64". The type "uint64" here matches none of the mentioned cases; 
> 
> But if you take this line:
>  inline data::operator uint64 () const 
>         { return *(uint64*)&lo; }
> ... we have no class data.

But an object of type uint32 = unsigned int, for which the same holds.
Comment 7 Andrew Pinski 2005-06-05 09:07:34 UTC
Reopening to ...
Comment 8 Andrew Pinski 2005-06-05 09:07:53 UTC
Mark as a dup of bug 21920.

*** This bug has been marked as a duplicate of 21920 ***