Bug 65210 - Wrong base class alignment (nvalign vs. align)
Wrong base class alignment (nvalign vs. align)
Product: Red Hat Linux
Classification: Retired
Component: gcc3 (Show other bugs)
ia64 Linux
medium Severity high
: ---
: ---
Assigned To: Jakub Jelinek
Depends On:
  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:
Last Closed: 2004-10-02 16:36:15 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
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 

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 

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:

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
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.