September 19, 2016
https://issues.dlang.org/show_bug.cgi?id=16243

--- Comment #11 from Brad Roberts <braddr@puremagic.com> ---
I haven't tested building with clang on osx in ages.  If it's at the point of passing tests then I'd be happy to convert any/all of the three testers back to their default compiler.

--
September 19, 2016
https://issues.dlang.org/show_bug.cgi?id=16243

--- Comment #12 from Jacob Carlborg <doob@me.com> ---
I've been using Clang for ages now and it passes the test suite, at least for 64bit. I'm running Apple LLVM version 7.3.0 (clang-703.0.31)

--
May 20, 2017
https://issues.dlang.org/show_bug.cgi?id=16243

--- Comment #13 from Joakim <dbugz@joakim.fea.st> ---
I spent a little time looking into this again.  The issue now appears to only be reproducible if clang compiles without any optimizations, which is what the dmd testsuite does.  When run without any optimizations, clang assumes the empty struct will not be passed in and only passes along the first six arguments, ie arg0 through arg5.  Since arg6 is not passed back to check13956, it asserts.

These issues only crop up on 32-bit arches, including ARM32, as kinke noted last summer, which explains why Jacob hasn't seen this on 64-bit OS X.

Here is the disassembly for what clang produces on linux/x86 without optimization:

00000000 <_Z9func139566S13956iiiiii>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   53                      push   %ebx
   4:   57                      push   %edi
   5:   56                      push   %esi
   6:   83 ec 3c                sub    $0x3c,%esp
   9:   8b 45 1c                mov    0x1c(%ebp),%eax
   c:   8b 4d 18                mov    0x18(%ebp),%ecx
   f:   8b 55 14                mov    0x14(%ebp),%edx
  12:   8b 75 10                mov    0x10(%ebp),%esi
  15:   8b 7d 0c                mov    0xc(%ebp),%edi
  18:   8b 5d 08                mov    0x8(%ebp),%ebx
  1b:   89 5d ec                mov    %ebx,-0x14(%ebp)
  1e:   89 7d e8                mov    %edi,-0x18(%ebp)
  21:   89 75 e4                mov    %esi,-0x1c(%ebp)
  24:   89 55 e0                mov    %edx,-0x20(%ebp)
  27:   89 4d dc                mov    %ecx,-0x24(%ebp)
  2a:   89 45 d8                mov    %eax,-0x28(%ebp)
  2d:   8b 45 ec                mov    -0x14(%ebp),%eax
  30:   8b 4d e8                mov    -0x18(%ebp),%ecx
  33:   8b 55 e4                mov    -0x1c(%ebp),%edx
  36:   8b 75 e0                mov    -0x20(%ebp),%esi
  39:   8b 7d dc                mov    -0x24(%ebp),%edi
  3c:   8b 5d d8                mov    -0x28(%ebp),%ebx
  3f:   89 04 24                mov    %eax,(%esp)
  42:   89 4c 24 04             mov    %ecx,0x4(%esp)
  46:   89 54 24 08             mov    %edx,0x8(%esp)
  4a:   89 74 24 0c             mov    %esi,0xc(%esp)
  4e:   89 7c 24 10             mov    %edi,0x10(%esp)
  52:   89 5c 24 14             mov    %ebx,0x14(%esp)
  56:   e8 fc ff ff ff          call   57 <_Z9func139566S13956iiiiii+0x57>
  57: R_386_PC32  _Z10check139566S13956iiiiii
  5b:   83 c4 3c                add    $0x3c,%esp
  5e:   5e                      pop    %esi
  5f:   5f                      pop    %edi
  60:   5b                      pop    %ebx
  61:   5d                      pop    %ebp
  62:   c3                      ret

Conversely, here's what gcc produces:

00000000 <_Z9func139566S13956iiiiii>:
   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 08                sub    $0x8,%esp
   6:   83 ec 04                sub    $0x4,%esp
   9:   ff 75 20                pushl  0x20(%ebp)
   c:   ff 75 1c                pushl  0x1c(%ebp)
   f:   ff 75 18                pushl  0x18(%ebp)
  12:   ff 75 14                pushl  0x14(%ebp)
  15:   ff 75 10                pushl  0x10(%ebp)
  18:   ff 75 0c                pushl  0xc(%ebp)
  1b:   50                      push   %eax
  1c:   e8 fc ff ff ff          call   1d <_Z9func139566S13956iiiiii+0x1d>
                        1d: R_386_PC32  _Z10check139566S13956iiiiii
  21:   83 c4 20                add    $0x20,%esp
  24:   90                      nop
  25:   c9                      leave
  26:   c3                      ret

When clang is run with optimization, it just calls the D function directly, which happens to avoid the problem, though likely the underlying assumption is still there:

00000000 <_Z9func139566S13956iiiiii>:
   0:   e9 fc ff ff ff          jmp    1 <_Z9func139566S13956iiiiii+0x1>
                        1: R_386_PC32   _Z10check139566S13956iiiiii

I'm not sure if clang with optimization always did this: just don't remember if I tried it before, maybe not.

As kinke said, clang and gcc assume different argument passing for empty structs on 32-bit arches, confirmed for both x86 and ARM32.  dmd and ldc work with the gcc approach, but not clang's.

--
May 20, 2017
https://issues.dlang.org/show_bug.cgi?id=16243

--- Comment #14 from Jacob Carlborg <doob@me.com> ---
(In reply to Joakim from comment #13)

> dmd and ldc work with the gcc approach, but not clang's.

Clang is the native compiler on macOS, so I would say that we should go with whatever Clang is doing.

--
February 24, 2018
https://issues.dlang.org/show_bug.cgi?id=16243

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |C++

--
February 24, 2018
https://issues.dlang.org/show_bug.cgi?id=16243

--- Comment #15 from Walter Bright <bugzilla@digitalmars.com> ---
*** Issue 18514 has been marked as a duplicate of this issue. ***

--
February 24, 2018
https://issues.dlang.org/show_bug.cgi?id=16243

--- Comment #16 from Walter Bright <bugzilla@digitalmars.com> ---
With the upgrade to FreeBSD 11, this is now happening on 32 bit FreeBSD.

--
February 24, 2018
https://issues.dlang.org/show_bug.cgi?id=16243

--- Comment #17 from Walter Bright <bugzilla@digitalmars.com> ---
On Linux x86, given the code:

  struct S { };
  int test(S s, int a) { return a; }

g++ produces:
    mov EAX,8[ESP]
    ret

while clang++ produces:

    mov EAX,4[ESP]
    ret

This is with optimization on. With it off, the same problem.

--
February 24, 2018
https://issues.dlang.org/show_bug.cgi?id=16243

--- Comment #18 from Walter Bright <bugzilla@digitalmars.com> ---
Temporary workaround

--
February 24, 2018
https://issues.dlang.org/show_bug.cgi?id=16243

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|wrong C++ argument passing  |wrong C++ argument passing
                   |with empty struct and 6     |with empty struct when
                   |integers                    |interfacing with Clang

--