https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98884
--- Comment #6 from David Brown <david at westcontrol dot com> --- (In reply to Jakub Jelinek from comment #3) > If GCC and Clang are ABI incompatible on this, then one of the two compilers > is buggy. So, it is needed to look at the EABI and find out which case it > is. I've had a look at the ARM C++ ABI, to the best of my abilities: <https://developer.arm.com/documentation/ihi0041/latest> Section 4.1 has this to say: GC++ABI ยง2.27POD Data Types The GC++ABI defines the way in which empty class types are laid out. For the purposes of parameter passing in [AAPCS], a parameter whose type is an empty class shall be treated as if its type were an aggregate with a single member of type unsigned byte. Note: Of course, the single member has undefined content. (This references <http://itanium-cxx-abi.github.io/cxx-abi/abi.html#pod>) If my reading is correct, then gcc is correct and clang is wrong here - empty classes are treated as containing a single unsigned byte, and then expanded to a 32-bit type before passing. (There is still no need to put a zero in these parameters, as the value is unspecified.) It may be that the x86 gcc port is wrong here, but I haven't looked at the details of x86 calling conventions. I hope someone can check this out, and a perhaps file a bug report for clang so that they can correct it. (Alternatively, file a bug report with ARM so that they can change the ABI!) However, in this particular case, if clang is wrong then I don't want to be right. I can see no benefit, and significant cost, in passing zeros for these empty tag structs. I'd be quite happy with an explicitly non-conforming switch to enable such optimisations (just like "-fshort-enums" or other switches that mess with caller and callee registers). Or I'd be even happier to find that clang is wrong and gcc ARM gets optimised without a flag :-)