<html>
    <head>
      <base href="https://bugs.llvm.org/">
    </head>
    <body><table border="1" cellspacing="0" cellpadding="8">
        <tr>
          <th>Bug ID</th>
          <td><a class="bz_bug_link 
          bz_status_NEW "
   title="NEW - gcc/clang calling convension mismatch"
   href="https://bugs.llvm.org/show_bug.cgi?id=35046">35046</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>gcc/clang calling convension mismatch
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>clang
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>unspecified
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>PC
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>Linux
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>enhancement
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>-New Bugs
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedclangbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>vanyacpp@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Recently I have discovered that empty arguments are passed differently by gcc
and by clang.

struct empty
{};

void f(empty, empty, empty);

int main()
{
    f(empty{}, empty{}, empty{});
}

GCC pushed 0 to stack for each empty struct while clang does nothing.

main(GCC):
  sub rsp, 16
  xor eax, eax
  push rax
  push rax
  push rax
  call f(empty, empty, empty)
  xor eax, eax
  add rsp, 40
  ret

main(clang):
  push rax
  call f(empty, empty, empty)
  xor eax, eax
  pop rcx
  ret

I would say that I like the code generated by clang more. As the struct is
empty no value needs to be passed. In a case the callee needs to take the
address of the argument it can allocate the argument in its own frame as the
argument is passed by value.

As the code generated differs I wondered if I can construct an example where
parameters get wrong values because of this. Turned out it wasn't very
difficult.

The following program

struct empty
{};

struct big
{
    int a;
    int b;
    int c;
    int d;
    int e;
};

void print_7th(empty, empty, empty, empty, empty, empty, big seventh)
{
    std::cout << seventh.a
       << ' ' << seventh.b
       << ' ' << seventh.c
       << ' ' << seventh.d
       << ' ' << seventh.e << std::endl;
}

int main()
{
    empty e;
    print_7th(e, e, e, e, e, e, big{1, 2, 3, 4, 5});
}

prints different output when print_7th and main are compiled with different
compilers:

./gcc-to-gcc
1 2 3 4 5
./clang-to-gcc
5 32767 0 0 635911936
./gcc-to-clang
192 0 -1204279016 32765 1
./clang-to-clang
1 2 3 4 5

Another easy way to see that compilers pass arguments differently is compiling
this code:

int sum(empty, empty, empty, empty, empty, empty, big seventh)
{
    return seventh.a + seventh.b + seventh.c + seventh.d + seventh.e;
}

GCC generates:

sum:
  mov eax, DWORD PTR [rsp+60]
  add eax, DWORD PTR [rsp+56]
  add eax, DWORD PTR [rsp+64]
  add eax, DWORD PTR [rsp+68]
  add eax, DWORD PTR [rsp+72]
  ret

while clang generates:

sum:
  mov eax, dword ptr [rsp + 12]
  add eax, dword ptr [rsp + 8]
  add eax, dword ptr [rsp + 16]
  add eax, dword ptr [rsp + 20]
  add eax, dword ptr [rsp + 24]
  ret

I don't know which compiler is right in this case and which conform to SysV ABI
better. I would prefer GCC to adopt clang behavior as it is more efficient.
Because if we have two popular major compilers that both are widely used and
are incompatible with each other and we have to break compatibility of one of
them it's better to choose the better alternative. Also using empty struct as
parameters is common in C++ code, and it's great to make them free.

I have already reported this issue against gcc:
<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82693">https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82693</a> I report this issue here
too, to let clang developers know about the issue too.</pre>
        </div>
      </p>


      <hr>
      <span>You are receiving this mail because:</span>

      <ul>
          <li>You are on the CC list for the bug.</li>
      </ul>
    </body>
</html>