Bug 65210 - Wrong base class alignment (nvalign vs. align)
Wrong base class alignment (nvalign vs. align)
Status: CLOSED CURRENTRELEASE
Product: Red Hat Linux
Classification: Retired
Component: gcc3 (Show other bugs)
7.2
ia64 Linux
medium Severity high
: ---
: ---
Assigned To: Jakub Jelinek
:
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2002-05-20 07:56 EDT by Grigory Zagorodnev
Modified: 2007-04-18 12:42 EDT (History)
0 users

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2004-10-02 16:36:15 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
The testcase (836 bytes, text/plain)
2002-05-20 07:57 EDT, Grigory Zagorodnev
no flags Details

  None (edit)
Description Grigory Zagorodnev 2002-05-20 07:56:00 EDT
From Bugzilla Helper:
User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; NetCaptor 
6.5.0PB8)

Description of problem:
G++3 gives wrong layout of class E object in the testcase below.

1. The testcase
---------------
struct A {
    int a;
};

struct B : public virtual A {};

struct C {
  long double c;
};

struct D : public virtual C {
    int d;
};

struct E : public B, public D {
    int e;
};


2. The issue
------------
Expected layout of class E on ia64 is the following:
    Offset Size	Contents
    [0000] 8	B's virtual table pointer (B is the primary base for E)
    [0008] 8	D's virtual table pointer
    [0010] 4	D::d
    [0014] 4	Padding to round up D size to multiple of pointer align (8)
    [0018] 4	E::e
    [001c] 4	A::a
    [0020] 16	C::c

But G++3 compiler gives another object layout for E:
    Offset Size	Contents
    [0000] 8	B's virtual table pointer (B is the primary base for E)
    [0008] 8	Padding 
    [0010] 8	D's virtual table pointer
    [0018] 4	D::d
    [001c] 4	E::e
    [0020] 4	A::a
    [0024] 12	Padding
    [0030] 16	C::c

The layout is different and is wrong.

3. Details and analisis
-----------------------
We see difference in three points here, all related to padding bytes added.

I. Padding after B's virtual table pointer
This is the major inconsistency. Let's see...

The C++ ABI says [Chapter 2: Data Layout/2.4 Non-POD Class Types/II. Allocation 
of Members Other Than Virtual Bases]:
"if D is not an empty base class (including all data members), start at offset 
dsize(C), incremented if necessary for alignment to nvalign(type(D)) for base 
classes or to align(type(D)) for data members. "

In our case, nvalign(D) == 8, align(D) == 16. 
So, it looks like g++3 did increment address to keep 16-bytes alignment of 
class D. But this is valid for data members only and not for base classes. Such 
behaviour is wrong. Since D is the base class, it should be aligned to nvalign
(D)==8 bytes within class E and there should not be any padding.

In other words, g++3 erroneously uses align(D) instead of nvalign(D).

II. No padding after D::d
Class D is laying out using common rules. It means that D should be finalized 
either - rounded up to a non-zero multiple of align(D). 
g++3 does not perform this step for base classes. See Bugzilla Bug #64535 for 
details.


III. Extra padding after A::a
There is nothing wrong - C::c should be 16-byte aligned.
Difference is just a side-effect of inconsistency listed above.


Version-Release number of selected component (if applicable):


How reproducible:
Always

Steps to Reproduce:
It's not so easy to dump object as showed above. So we are using run-time test 
which checks offset of class D within the object E. It used to be sizeof(void 
*), i.e. D is comming right after class B, when B contains only the virtual 
table pointer.

1. Build attached fail.cpp test using simple command line
     g++3 fail.cpp
2. Run it
     ./a.out
3. Look for 'passed' word in the output


Actual Results:  failed
D's offset is 16
expected 8


Expected Results:  passed

Additional info:
Comment 1 Grigory Zagorodnev 2002-05-20 07:57:02 EDT
Created attachment 58005 [details]
The testcase
Comment 2 Alan Cox 2002-12-15 15:32:24 EST
Ok with g++ 3.2 on x86 at least
Comment 3 Richard Henderson 2004-10-02 16:36:15 EDT
The given test case does pass with gcc 3.2, though the layout is
slightly different than described.  It's

[000] vptr for B
[008] vptr for D
[010] D::d
[014] E::e
[018] A::a
[020] C::c

I.e. E is using the tail padding in D.  I don't see anything wrong
with this.

Note You need to log in before you can comment on or make changes to this bug.