• Struct offset bug

    From BartC@21:1/5 to All on Mon Oct 10 11:06:07 2016
    Here's another bug but with lccwin64:

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

    typedef struct {
    int32_t a;
    int32_t b;
    union {
    int64_t c;
    struct {
    int32_t clow;
    int32_t chigh;
    };
    };
    } S;

    int main(void) {

    printf(".c offset: %d\n", offsetof(S,c));
    printf(".clow offset: %d\n", offsetof(S,clow));
    printf(".chigh offset: %d\n", offsetof(S,chigh));
    }

    'c' should have offset 8, and 'clow' and 'chigh' should have offsets of
    8 and 12. But lccwin64 reports them as 16 and 20.

    It's OK with lccwin32 (and with other 32 or 64-bit compilers I've tried).

    lccwin64 version is June 03 2016.

    --
    Bartc

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Keith Thompson@21:1/5 to BartC on Mon Oct 10 11:53:26 2016
    BartC <bc@freeuk.com> writes:
    Here's another bug but with lccwin64:

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

    typedef struct {
    int32_t a;
    int32_t b;
    union {
    int64_t c;
    struct {
    int32_t clow;
    int32_t chigh;
    };
    };
    } S;

    int main(void) {

    printf(".c offset: %d\n", offsetof(S,c));
    printf(".clow offset: %d\n", offsetof(S,clow));
    printf(".chigh offset: %d\n", offsetof(S,chigh));
    }

    'c' should have offset 8, and 'clow' and 'chigh' should have offsets of
    8 and 12. But lccwin64 reports them as 16 and 20.

    It's OK with lccwin32 (and with other 32 or 64-bit compilers I've tried).

    lccwin64 version is June 03 2016.

    BartC, does that compile? Ignoring the extra quotation marks on
    the #include directives, offsetof() is defined in <stddef.h>,
    not <stdlib.h>. A reference to offsetof() without `#include
    <stddef.h>` should at least be diagnosed at compile time, and
    preferably rejected.

    The actual offsets are implementation-defined due to padding, but
    assuming CHAR_BIT==8 I agree that 8 is the only reasonable value
    for offsetof(S, c) and offsetof(S, clow).

    I note that unnamed structs and unions, which this example depends
    on, are supported only in C11, not C90 or C99. I don't know the
    current status of lcc-win's C11 support. The issue can easily be
    avoided by naming the union and the struct.

    Regardless of the specific values, all members of a union should
    have an offset of 0 relative to the union, and the same offset
    relative to an enclosing structure.

    I offer an alternate version of the test program. It's possible
    that naming the nested union and struct might invalidate the test
    by working around the problem. I currently have no way to test that.

    #include <stdio.h>
    #include <stdint.h>
    #include <stddef.h>

    struct S {
    int32_t a;
    int32_t b;
    union {
    int64_t c;
    struct {
    int32_t clow;
    int32_t chigh;
    } s;
    } u;
    };

    int main(void) {
    printf(".c offset: %zu\n", offsetof(struct S, u.c));
    printf(".clow offset: %zu\n", offsetof(struct S, u.s.clow));
    printf(".chigh offset: %zu\n", offsetof(struct S, u.s.chigh));
    if (offsetof(struct S, u.c) == offsetof(struct S, u.s.clow)) {
    puts("ok");
    }
    else {
    puts("failed");
    }
    }

    The expected output is:

    .c offset: 8
    .clow offset: 8
    .chigh offset: 12
    ok

    Hope this helps.

    (godbolt.org provides online access to several versions of clang, gcc,
    and icc. Is there a similar site providing online access to lcc-win?)

    --
    Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From jacobnavia@21:1/5 to All on Wed Oct 12 08:58:28 2016
    Le 10/10/2016 à 12:06, BartC a écrit :
    Here's another bug but with lccwin64:

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

    typedef struct {
    int32_t a;
    int32_t b;
    union {
    int64_t c;
    struct {
    int32_t clow;
    int32_t chigh;
    };
    };
    } S;

    int main(void) {

    printf(".c offset: %d\n", offsetof(S,c));
    printf(".clow offset: %d\n", offsetof(S,clow));
    printf(".chigh offset: %d\n", offsetof(S,chigh));
    }

    'c' should have offset 8, and 'clow' and 'chigh' should have offsets of
    8 and 12. But lccwin64 reports them as 16 and 20.

    It's OK with lccwin32 (and with other 32 or 64-bit compilers I've tried).

    lccwin64 version is June 03 2016.


    Hi Bart

    Yes this is a bug, but now I am poerting lcc-win to the raspberry pi,
    and I can't fix it.

    Just give me some time till the week-end.

    Thanks

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From BartC@21:1/5 to Keith Thompson on Mon Oct 10 21:28:58 2016
    On 10/10/2016 19:53, Keith Thompson wrote:
    BartC <bc@freeuk.com> writes:
    Here's another bug but with lccwin64:

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

    typedef struct {
    int32_t a;
    int32_t b;
    union {
    int64_t c;
    struct {
    int32_t clow;
    int32_t chigh;
    };
    };
    } S;

    int main(void) {

    printf(".c offset: %d\n", offsetof(S,c));
    printf(".clow offset: %d\n", offsetof(S,clow));
    printf(".chigh offset: %d\n", offsetof(S,chigh));
    }

    'c' should have offset 8, and 'clow' and 'chigh' should have offsets of
    8 and 12. But lccwin64 reports them as 16 and 20.

    BartC, does that compile? Ignoring the extra quotation marks on
    the #include directives, offsetof() is defined in <stddef.h>,
    not <stdlib.h>. A reference to offsetof() without `#include
    <stddef.h>` should at least be diagnosed at compile time, and
    preferably rejected.

    The compilers didn't seem bothered about whether stddef.h was included
    or not.

    The actual offsets are implementation-defined due to padding, but
    assuming CHAR_BIT==8 I agree that 8 is the only reasonable value
    for offsetof(S, c) and offsetof(S, clow).

    The actual offset isn't important, only that it should be the same for
    those two members. But I do rely on the chigh offset being 4 bytes
    higher. (The actual struct is below.)

    I note that unnamed structs and unions, which this example depends
    on, are supported only in C11, not C90 or C99.

    I've looked at this before, and anonymous structs and unions seem to be recognised in all the compilers I've tried.

    I don't know the
    current status of lcc-win's C11 support. The issue can easily be
    avoided by naming the union and the struct.

    That will break a lot of things, as it means thousands of references
    will need the inclusion of an extra, arbitrary member name. But also the original language supports that feature, and I need C to be able to
    represent it (alternate representations in C can get very messy).

    Since most compilers seem to support the feature, there is no reason not
    to use it just because one compiler has a bug in that support.

    I offer an alternate version of the test program. It's possible
    that naming the nested union and struct might invalidate the test
    by working around the problem. I currently have no way to test that.

    struct S {
    int32_t a;
    int32_t b;
    union {
    int64_t c;
    struct {
    int32_t clow;
    int32_t chigh;
    } s;
    } u;
    };

    Yes the named version works. But as I said I can't really use it.


    typedef struct _unitrec unitrec;
    ....
    struct _unitrec {
    int32 tag;
    int32 lineno;
    struct _unitrec* a;
    struct _unitrec* b;
    struct _unitrec* c;
    struct _unitrec* nextunit;
    union {
    strec * def;
    int64 value;
    uint64 uvalue;
    double xvalue;
    char * svalue;
    strec * labeldef;
    struct {
    int32 range_lower;
    int32 range_upper;
    };
    };
    union {
    int32 opcode;
    int32 index;
    int32 trylevel;
    int32 slength;
    byte dottedname;
    };
    int32 valuemode;
    };


    --
    Bartc

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Keith Thompson@21:1/5 to BartC on Tue Oct 11 14:57:34 2016
    BartC <bc@freeuk.com> writes:
    On 10/10/2016 19:53, Keith Thompson wrote:
    BartC <bc@freeuk.com> writes:
    Here's another bug but with lccwin64:

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

    typedef struct {
    int32_t a;
    int32_t b;
    union {
    int64_t c;
    struct {
    int32_t clow;
    int32_t chigh;
    };
    };
    } S;

    int main(void) {

    printf(".c offset: %d\n", offsetof(S,c));
    printf(".clow offset: %d\n", offsetof(S,clow));
    printf(".chigh offset: %d\n", offsetof(S,chigh));
    }

    'c' should have offset 8, and 'clow' and 'chigh' should have offsets of
    8 and 12. But lccwin64 reports them as 16 and 20.

    BartC, does that compile? Ignoring the extra quotation marks on
    the #include directives, offsetof() is defined in <stddef.h>,
    not <stdlib.h>. A reference to offsetof() without `#include
    <stddef.h>` should at least be diagnosed at compile time, and
    preferably rejected.

    The compilers didn't seem bothered about whether stddef.h was included
    or not.

    Compilers, plural? Which ones? (If compilers other than lcc-win are
    affected this, discussion of them should probably take place elsewhere.)

    Here's a simpler test program to check for the problem:

    #include <stdlib.h>
    const int n = offsetof(struct { int x; }, x);

    This *should* be rejected. I note that tcc 0.9.25 on Linux fails to
    diagnose the error. It does complain if the `#include <stdlib.h>` is
    commented out. I believe that <stdlib.h> is indirectly including
    <stddef.h> -- so it's likely to be a bug in the headers provided by the
    runtime library, or in the integration between the headers and the
    compiler, not in the compiler itself. (As I understand it, that
    distinction is less relevant for lcc-win.)

    It's a minor bug that shouldn't affect correct code that doesn't try to
    define the name `offsetof` for its own purposes, which is a bad idea
    anyway. And let me emphasize that this does not affect me. My intent
    is to bring this potential problem to the attention of the compiler
    maintainer, not to request a fix.

    The actual offsets are implementation-defined due to padding, but
    assuming CHAR_BIT==8 I agree that 8 is the only reasonable value
    for offsetof(S, c) and offsetof(S, clow).

    The actual offset isn't important, only that it should be the same for
    those two members. But I do rely on the chigh offset being 4 bytes
    higher. (The actual struct is below.)

    I note that unnamed structs and unions, which this example depends
    on, are supported only in C11, not C90 or C99.

    I've looked at this before, and anonymous structs and unions seem to be recognised in all the compilers I've tried.

    If so, then they're an extension in any compiler that doesn't claim to
    conform to C11. There's nothing wrong with having such an extension.
    My concern is simply that a compiler bug report ideally should avoid the
    use of extensions if they're not needed to demonstrate the problem -- if nothing else it could make the maintainer's job a bit easier in tracking
    down the problem.

    I don't know the
    current status of lcc-win's C11 support. The issue can easily be
    avoided by naming the union and the struct.

    That will break a lot of things, as it means thousands of references
    will need the inclusion of an extra, arbitrary member name. But also the original language supports that feature, and I need C to be able to
    represent it (alternate representations in C can get very messy).

    Sorry, I may have been unclear. I meant that naming the union and
    struct avoids the issue *for the demonstration program for this bug
    report*.

    Since most compilers seem to support the feature, there is no reason not
    to use it just because one compiler has a bug in that support.

    That's your call -- though you might consider that compilers that
    implement them as an extension might not fully follow the C11
    requirements. If it works for you, great.

    [...]

    --
    Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst> Working, but not speaking, for JetHead Development, Inc.
    "We must do something. This is something. Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)