Thread overview
[Bug 226] Union alignof is less than the alignof for each of its fields
May 21, 2016
Iain Buclaw
May 21, 2016
Iain Buclaw
May 21, 2016
Iain Buclaw
May 21, 2016
http://bugzilla.gdcproject.org/show_bug.cgi?id=226

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |INVALID
             Status|NEW                         |RESOLVED

--- Comment #1 from Iain Buclaw <ibuclaw@gdcproject.org> ---
bug226.c
---
#include <stdio.h>
#define MAX(a,b) (((a)>(b))?(a):(b))

typedef unsigned long long ulong;
typedef union Foo
{
     double a;
     ulong b;
} Foo;

int main()
{
    printf("%d >= %d\n%d >= %d\n",
           sizeof(Foo), MAX(sizeof(double), sizeof(ulong)),
           __alignof__(Foo), MAX(__alignof__(double), __alignof__(ulong)));
}

---

bug226.cc
---
#include <iostream>
#include <algorithm>

union Foo
{
     double a;
     ulong b;
};

int main()
{
    std::cout << sizeof(Foo) << " >= "
        << std::max(sizeof(double), sizeof(ulong)) << "\n";
    std::cout << alignof(Foo) << " >= "
        << std::max(alignof(double), alignof(ulong)) << "\n";
}
---

bug226.d
---
import std.stdio;
import std.algorithm;

union Foo
{
     double a;
     ulong b;
}

void main()
{
    writeln(Foo.sizeof, " >= ", max(double.sizeof, ulong.sizeof));
    writeln(Foo.alignof, " >= ", max(double.alignof, ulong.alignof));
}
---

$ gcc -m32 bug226.c -o gccm32
$ g++ -m32 bug226.cc -o gxxm32
$ gdc -m32 bug226.d -o gdcm32
$ ./gccm32
8 >= 8
4 >= 8
$ ./gxxm32
8 >= 8
4 >= 8
$ ./gdcm32
8 >= 8
4 >= 8
---

GDC may be different from other D compilers, but it stays true to ABI of C and C++ here, so what do you expect me to do?  Everyone else is in the wrong here.

The alignment of double and ulong on x86 may be 8 bytes, but the field alignment is worked out differently.

---
version (X86_64)
    return T.alignof;
else version (X86)
{
    static if (isIntegral(T) || is(T == double) || is(T == cdouble))
        return min(4, T.alignof);
    else
        return T.alignof;
}
---

The above is roughly what LDC and DMD should be doing.

-- 
You are receiving this mail because:
You are watching all bug changes.
May 21, 2016
http://bugzilla.gdcproject.org/show_bug.cgi?id=226

--- Comment #2 from Iain Buclaw <ibuclaw@gdcproject.org> ---
NB: There is Target::fieldalign which allows other compilers to implement this independently.  So it's *not* a front-end bug per-say.

-- 
You are receiving this mail because:
You are watching all bug changes.
May 21, 2016
http://bugzilla.gdcproject.org/show_bug.cgi?id=226

--- Comment #3 from Iain Buclaw <ibuclaw@gdcproject.org> ---
(In reply to Iain Buclaw from comment #2)
> NB: There is Target::fieldalign which allows other compilers to implement this independently.  So it's *not* a front-end bug per-say.

Ah wait, I initially misread it.  It's not Target::fieldalign that is wrong, it's Target::typealign that is wrong in the other compilers!  As all compilers get the align of the union correct, but the align of the individual types wrong.


printf("%d:%d:%d\n", alignof(Foo), alignof(double), alignof(ulong));
=> 4:8:8

-- 
You are receiving this mail because:
You are watching all bug changes.
May 21, 2016
http://bugzilla.gdcproject.org/show_bug.cgi?id=226

--- Comment #4 from thomas.bockman@gmail.com ---
I found a workaround:
---
struct Foo(A, B)
{
    align(max(A.sizeof, B.sizeof)) union
    {
        A a;
        B b;
    }

    static assert (typeof(this).sizeof  >= max(A.sizeof,  B.sizeof));
    static assert (typeof(this).alignof >= max(A.alignof, B.alignof));
}
---
It would need Kenji's "align(n) with n compile-time constant" PR to work
without string mixins, though:
    https://github.com/dlang/dmd/pull/5750

-- 
You are receiving this mail because:
You are watching all bug changes.