July 30, 2019
On Monday, 29 July 2019 at 01:19:36 UTC, Manu wrote:
> On Sun, Jul 28, 2019 at 5:20 PM Gregor Mückl via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>
>> On Monday, 22 July 2019 at 18:12:01 UTC, Manu wrote:
>> > [...]
>>
>> That's a pretty neat hack!
>>
>> I'm just worried about two things:
>> - it makes the generated code harder to read (not that big of a
>> deal)
>
> Barely... and a generated header is not really for human consumption either way.
>
>> - if you happen to include headers with conflicting D_ENUM* defines (e.g. a potential 3rd party D wrapper), you might get some nasty surprises :/
>
> C/C++ programmers now how to do macros and what to expect.

So should we go ahead with generating code based on the `-extern-std` value or by using defines?

After sleeping a bit on this, I prefer `-extern-std`.
July 30, 2019
On Tuesday, 30 July 2019 at 14:43:01 UTC, Eduard Staniloiu wrote:
> On Monday, 29 July 2019 at 01:19:36 UTC, Manu wrote:
>> On Sun, Jul 28, 2019 at 5:20 PM Gregor Mückl via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>
>>> On Monday, 22 July 2019 at 18:12:01 UTC, Manu wrote:
>>> > [...]
>>>
>>> That's a pretty neat hack!
>>>
>>> I'm just worried about two things:
>>> - it makes the generated code harder to read (not that big of a
>>> deal)
>>
>> Barely... and a generated header is not really for human consumption either way.
>>
>>> - if you happen to include headers with conflicting D_ENUM* defines (e.g. a potential 3rd party D wrapper), you might get some nasty surprises :/
>>
>> C/C++ programmers now how to do macros and what to expect.
>
> So should we go ahead with generating code based on the `-extern-std` value or by using defines?
>
> After sleeping a bit on this, I prefer `-extern-std`.

BTW, I went with `-extern-std` in the current implementation (on GH).

Another question is how should `align(n)` be generated. See the following two:

1) __attribute__((packed, aligned(n)))

or

2) __attribute__((aligned(n)))

Note the missing `packed` between 1) and 2)

Currently (on GH) the entire generated output looks like this

struct
#if defined(__GNUC__) || defined(__clang__)
    __attribute__((packed, aligned(8)))
#elif defined(_MSC_VER)
    __declspec(align(8))
#elif defined(__DMC__)
    #pragma pack(push, 8)
#endif
MyStruct
{
  /* fields */
}
#if defined(__DMC__)
    #pragma pack(pop)
#endif

July 30, 2019
On 7/30/19 10:50 AM, Eduard Staniloiu wrote:
> On Tuesday, 30 July 2019 at 14:43:01 UTC, Eduard Staniloiu wrote:
>> On Monday, 29 July 2019 at 01:19:36 UTC, Manu wrote:
>>> On Sun, Jul 28, 2019 at 5:20 PM Gregor Mückl via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>>
>>>> On Monday, 22 July 2019 at 18:12:01 UTC, Manu wrote:
>>>> > [...]
>>>>
>>>> That's a pretty neat hack!
>>>>
>>>> I'm just worried about two things:
>>>> - it makes the generated code harder to read (not that big of a
>>>> deal)
>>>
>>> Barely... and a generated header is not really for human consumption either way.
>>>
>>>> - if you happen to include headers with conflicting D_ENUM* defines (e.g. a potential 3rd party D wrapper), you might get some nasty surprises :/
>>>
>>> C/C++ programmers now how to do macros and what to expect.
>>
>> So should we go ahead with generating code based on the `-extern-std` value or by using defines?
>>
>> After sleeping a bit on this, I prefer `-extern-std`.
> 
> BTW, I went with `-extern-std` in the current implementation (on GH).
> 
> Another question is how should `align(n)` be generated. See the following two:
> 
> 1) __attribute__((packed, aligned(n)))
> 
> or
> 
> 2) __attribute__((aligned(n)))
> 
> Note the missing `packed` between 1) and 2)
> 
> Currently (on GH) the entire generated output looks like this
> 
> struct
> #if defined(__GNUC__) || defined(__clang__)
>      __attribute__((packed, aligned(8)))
> #elif defined(_MSC_VER)
>      __declspec(align(8))
> #elif defined(__DMC__)
>      #pragma pack(push, 8)
> #endif
> MyStruct
> {
>    /* fields */
> }
> #if defined(__DMC__)
>      #pragma pack(pop)
> #endif
> 

Better yet:

#if defined(__GNUC__) || defined(__clang__)
    #define BEGIN_PACK(n) __attribute__((packed, aligned(n)))
#elif defined(_MSC_VER)
    #define BEGIN_PACK(n) __declspec(align(n))
#elif defined(__DMC__)
    #define BEGIN_PACK(n) #pragma pack(push, n)
#endif

#if defined(__DMC__)
    #define END_PACK() #pragma pack(pop)
#else
    #define END_PACK()
#endif

July 30, 2019
On Tuesday, 30 July 2019 at 14:43:01 UTC, Eduard Staniloiu wrote:
> On Monday, 29 July 2019 at 01:19:36 UTC, Manu wrote:
>> On Sun, Jul 28, 2019 at 5:20 PM Gregor Mückl via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>
>>> On Monday, 22 July 2019 at 18:12:01 UTC, Manu wrote:
>>> > [...]
>>>
>>> That's a pretty neat hack!
>>>
>>> I'm just worried about two things:
>>> - it makes the generated code harder to read (not that big of a
>>> deal)
>>
>> Barely... and a generated header is not really for human consumption either way.
>>
>>> - if you happen to include headers with conflicting D_ENUM* defines (e.g. a potential 3rd party D wrapper), you might get some nasty surprises :/
>>
>> C/C++ programmers now how to do macros and what to expect.
>
> So should we go ahead with generating code based on the `-extern-std` value or by using defines?
>
> After sleeping a bit on this, I prefer `-extern-std`.

Advantage of using defines is that you can use one header to rule them all.
I.e. you generate it once and then make it available to your clients/users.
=> it's immediately ready to be distributed

With -extern-std, you have to generate n-interfaces and distribute them to your clients + probably add a few defines yourself.

A comprise could be that by default you emit all combinations and only if -extern-std is defined you emit the headers for that standard.
July 30, 2019
On Tue, Jul 30, 2019 at 7:45 AM Eduard Staniloiu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Monday, 29 July 2019 at 01:19:36 UTC, Manu wrote:
> > On Sun, Jul 28, 2019 at 5:20 PM Gregor Mückl via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> >>
> >> On Monday, 22 July 2019 at 18:12:01 UTC, Manu wrote:
> >> > [...]
> >>
> >> That's a pretty neat hack!
> >>
> >> I'm just worried about two things:
> >> - it makes the generated code harder to read (not that big of a
> >> deal)
> >
> > Barely... and a generated header is not really for human consumption either way.
> >
> >> - if you happen to include headers with conflicting D_ENUM* defines (e.g. a potential 3rd party D wrapper), you might get some nasty surprises :/
> >
> > C/C++ programmers now how to do macros and what to expect.
>
> So should we go ahead with generating code based on the `-extern-std` value or by using defines?
>
> After sleeping a bit on this, I prefer `-extern-std`.

It's possible that the correct answer is both.
The define technique I described empowers DMD to use its bizarre
naming strategy without special hacks in the header gen code.
I think perhaps the defines should be used, but the default code (when
the macros aren't specified by the user) could be driven by
-extern-std as you have it now.

July 30, 2019
On Tue, Jul 30, 2019 at 8:10 AM Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On 7/30/19 10:50 AM, Eduard Staniloiu wrote:
> > On Tuesday, 30 July 2019 at 14:43:01 UTC, Eduard Staniloiu wrote:
> >> On Monday, 29 July 2019 at 01:19:36 UTC, Manu wrote:
> >>> On Sun, Jul 28, 2019 at 5:20 PM Gregor Mückl via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> >>>>
> >>>> On Monday, 22 July 2019 at 18:12:01 UTC, Manu wrote:
> >>>> > [...]
> >>>>
> >>>> That's a pretty neat hack!
> >>>>
> >>>> I'm just worried about two things:
> >>>> - it makes the generated code harder to read (not that big of a
> >>>> deal)
> >>>
> >>> Barely... and a generated header is not really for human consumption either way.
> >>>
> >>>> - if you happen to include headers with conflicting D_ENUM* defines (e.g. a potential 3rd party D wrapper), you might get some nasty surprises :/
> >>>
> >>> C/C++ programmers now how to do macros and what to expect.
> >>
> >> So should we go ahead with generating code based on the `-extern-std` value or by using defines?
> >>
> >> After sleeping a bit on this, I prefer `-extern-std`.
> >
> > BTW, I went with `-extern-std` in the current implementation (on GH).
> >
> > Another question is how should `align(n)` be generated. See the
> > following two:
> >
> > 1) __attribute__((packed, aligned(n)))
> >
> > or
> >
> > 2) __attribute__((aligned(n)))
> >
> > Note the missing `packed` between 1) and 2)
> >
> > Currently (on GH) the entire generated output looks like this
> >
> > struct
> > #if defined(__GNUC__) || defined(__clang__)
> >      __attribute__((packed, aligned(8)))
> > #elif defined(_MSC_VER)
> >      __declspec(align(8))
> > #elif defined(__DMC__)
> >      #pragma pack(push, 8)
> > #endif
> > MyStruct
> > {
> >    /* fields */
> > }
> > #if defined(__DMC__)
> >      #pragma pack(pop)
> > #endif
> >
>
> Better yet:
>
> #if defined(__GNUC__) || defined(__clang__)
>      #define BEGIN_PACK(n) __attribute__((packed, aligned(n)))
> #elif defined(_MSC_VER)
>      #define BEGIN_PACK(n) __declspec(align(n))
> #elif defined(__DMC__)
>      #define BEGIN_PACK(n) #pragma pack(push, n)
> #endif
>
> #if defined(__DMC__)
>      #define END_PACK() #pragma pack(pop)
> #else
>      #define END_PACK()
> #endif

This is precisely what I was just about to propose ;)

July 30, 2019
On Tue, Jul 30, 2019 at 9:20 AM Seb via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>
> On Tuesday, 30 July 2019 at 14:43:01 UTC, Eduard Staniloiu wrote:
> > On Monday, 29 July 2019 at 01:19:36 UTC, Manu wrote:
> >> On Sun, Jul 28, 2019 at 5:20 PM Gregor Mückl via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> >>>
> >>> On Monday, 22 July 2019 at 18:12:01 UTC, Manu wrote:
> >>> > [...]
> >>>
> >>> That's a pretty neat hack!
> >>>
> >>> I'm just worried about two things:
> >>> - it makes the generated code harder to read (not that big of
> >>> a
> >>> deal)
> >>
> >> Barely... and a generated header is not really for human consumption either way.
> >>
> >>> - if you happen to include headers with conflicting D_ENUM* defines (e.g. a potential 3rd party D wrapper), you might get some nasty surprises :/
> >>
> >> C/C++ programmers now how to do macros and what to expect.
> >
> > So should we go ahead with generating code based on the `-extern-std` value or by using defines?
> >
> > After sleeping a bit on this, I prefer `-extern-std`.
>
> Advantage of using defines is that you can use one header to rule
> them all.
> I.e. you generate it once and then make it available to your
> clients/users.
> => it's immediately ready to be distributed
>
> With -extern-std, you have to generate n-interfaces and distribute them to your clients + probably add a few defines yourself.
>
> A comprise could be that by default you emit all combinations and only if -extern-std is defined you emit the headers for that standard.

Nar.. just emit the defines, and let the `-extern-std` drive the most likely desired default for when the macros are not defined by the user.

July 30, 2019
On Tuesday, 30 July 2019 at 18:00:44 UTC, Manu wrote:
> On Tue, Jul 30, 2019 at 8:10 AM Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>
>> On 7/30/19 10:50 AM, Eduard Staniloiu wrote:
>> >[...]
>>
>> Better yet:
>>
>> #if defined(__GNUC__) || defined(__clang__)
>>      #define BEGIN_PACK(n) __attribute__((packed, aligned(n)))
>> #elif defined(_MSC_VER)
>>      #define BEGIN_PACK(n) __declspec(align(n))
>> #elif defined(__DMC__)
>>      #define BEGIN_PACK(n) #pragma pack(push, n)
>> #endif
>>
>> #if defined(__DMC__)
>>      #define END_PACK() #pragma pack(pop)
>> #else
>>      #define END_PACK()
>> #endif
>
> This is precisely what I was just about to propose ;)

Will use this, but my question still stands:
__attribute__ packed or not?

Given the following struct
```
struct S
{
    int x;
    char y;
}
```

With `struct __attribute__((packed, aligned(8))) S` -> sizeof(S) is 5

With `struct __attribute__((aligned(8))) S` -> sizeof(S) is 8
July 30, 2019
On Tuesday, 30 July 2019 at 18:40:04 UTC, Eduard Staniloiu wrote:
> On Tuesday, 30 July 2019 at 18:00:44 UTC, Manu wrote:
>> On Tue, Jul 30, 2019 at 8:10 AM Andrei Alexandrescu via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
>>>
>>> On 7/30/19 10:50 AM, Eduard Staniloiu wrote:
>>> >[...]
>>>
>>> Better yet:
>>>
>>> #if defined(__GNUC__) || defined(__clang__)
>>>      #define BEGIN_PACK(n) __attribute__((packed, aligned(n)))
>>> #elif defined(_MSC_VER)
>>>      #define BEGIN_PACK(n) __declspec(align(n))
>>> #elif defined(__DMC__)
>>>      #define BEGIN_PACK(n) #pragma pack(push, n)
>>> #endif
>>>
>>> #if defined(__DMC__)
>>>      #define END_PACK() #pragma pack(pop)
>>> #else
>>>      #define END_PACK()
>>> #endif
>>
>> This is precisely what I was just about to propose ;)
>
> Will use this, but my question still stands:
> __attribute__ packed or not?
>
> Given the following struct
> ```
> struct S
> {
>     int x;
>     char y;
> }
> ```
>
> With `struct __attribute__((packed, aligned(8))) S` -> sizeof(S) is 5
>
> With `struct __attribute__((aligned(8))) S` -> sizeof(S) is 8

I've only found 2 explicit alignments in the *frontend* files (dmd/{libomf,scanmscoff}.d aren't part of the frontend):

1) dmd/root/longdouble.d:
-----
struct longdouble_soft
{
    // DMD's x87 `real` on Windows is packed (alignof = 2 -> sizeof = 10).
    align(2) ulong mantissa;
    ushort exp_sign;
}
-----

2) dmd/expression.d:
-----
align(8) union __AnonStruct__u { ... }
-----

These 2 instances can be altered not to require any explicit alignment. Then there wouldn't be any current need for align() support.

Instance 1, `longdouble_soft`, is only relevant for MSVC. It could consist of data `ushort[4] mantissa_; ushort exp_sign` (natural alignment of 2 and size 10) and feature a `ref ulong mantissa()` property performing a reinterpret-cast.

Instance 2 only needs an additional `long __for_alignment_only` union member (union alignment is already handled like this in another union I don't remember OTOH).
August 02, 2019
On Tuesday, 30 July 2019 at 14:50:15 UTC, Eduard Staniloiu wrote:
> Another question is how should `align(n)` be generated. See the following two:
>
> 1) __attribute__((packed, aligned(n)))
>
> or
>
> 2) __attribute__((aligned(n)))
>
> Note the missing `packed` between 1) and 2)
>
> Currently (on GH) the entire generated output looks like this
>
> struct
> #if defined(__GNUC__) || defined(__clang__)
>     __attribute__((packed, aligned(8)))
> #elif defined(_MSC_VER)
>     __declspec(align(8))
> #elif defined(__DMC__)
>     #pragma pack(push, 8)
> #endif
> MyStruct
> {
>   /* fields */
> }
> #if defined(__DMC__)
>     #pragma pack(pop)
> #endif

This only covers structure packing rules, right? So alignment of the aggregate as a whole (equivalent to C++ alignas(n) statement) is out of scope?

If so,

#pragma pack(push,n)

and

#pragma pack(pop,n)

work on MSVC, GCC and clang in my experience. DMC is documented to have the same behavior. So you should be able to dispense with the #ifdef's completely.