https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83487
Jakub Jelinek <jakub at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |hjl.tools at gmail dot com, | |hubicka at gcc dot gnu.org, | |jason at gcc dot gnu.org, | |matz at gcc dot gnu.org --- Comment #14 from Jakub Jelinek <jakub at gcc dot gnu.org> --- Anyway, have the TYPE_EMPTY_P changes been cross-checked with the x86-64 psABI and other compilers? The psABI is at least vague in this regard. One thing is that we consider TYPE_EMPTY_P even aggregates larger than 16 bytes, like C++ struct B {}; struct C { struct B c[128]; }; where the psABI says it is passed in MEMORY. I presume it has been intentional change, but will the psABI be updated here so that other compilers know that they need to change too? Another thing is for aggregates <= 16 bytes, the psABI algorithm is that it is NO_CLASS for both 8byte halves if it is TYPE_EMPTY_P aggregate, and doesn't say where it is passed. Testcase for compiler compatibility: pr83487.h: #ifdef ALIGNED struct __attribute__ ((aligned (ALIGNED))) A {}; #else struct A {}; #endif struct B {}; #ifdef LARGE struct C { struct B c[128]; }; #else struct C {}; #endif pr83487-1.C: #include "pr83487.h" extern #ifdef __cplusplus "C" #endif void abort (); void f1 (int i, int j, int k, int l, int m, int n, int o, struct A) { if (i != 6 || j != 0 || k != 1 || l != 2 || m != 3 || n != 4 || o != 5) abort (); } void f3 (int i, int j, int k, int l, int m, int n, int o, struct A, int p, int q) { if (i != 6 || j != 0 || k != 1 || l != 2 || m != 3 || n != 4 || o != 5 || p != 7 || q != 8) abort (); } void f5 (int i, int j, int k, int l, int m, int n, int o, struct B, int p, int q) { if (i != 6 || j != 0 || k != 1 || l != 2 || m != 3 || n != 4 || o != 5 || p != 7 || q != 8) abort (); } void f7 (int i, int j, int k, int l, int m, int n, int o, struct C, int p, int q) { if (i != 6 || j != 0 || k != 1 || l != 2 || m != 3 || n != 4 || o != 5 || p != 7 || q != 8) abort (); } void f9 (int o, struct A) { if (o != 5) abort (); } void f11 (int o, struct A, int p, int q) { if (o != 5 || p != 7 || q != 8) abort (); } void f13 (int o, struct B, int p, int q) { if (o != 5 || p != 7 || q != 8) abort (); } void f15 (int o, struct C, int p, int q) { if (o != 5 || p != 7 || q != 8) abort (); } pr83487-2.C: #include "pr83487.h" struct A a; struct B b; struct C c; extern void f1 (int i, int j, int k, int l, int m, int n, int o, struct A); extern void f3 (int i, int j, int k, int l, int m, int n, int o, struct A, int p, int q); extern void f5 (int i, int j, int k, int l, int m, int n, int o, struct B, int p, int q); extern void f7 (int i, int j, int k, int l, int m, int n, int o, struct C, int p, int q); extern void f9 (int o, struct A); extern void f11 (int o, struct A, int p, int q); extern void f13 (int o, struct B, int p, int q); extern void f15 (int o, struct C, int p, int q); int main () { f1 (6, 0, 1, 2, 3, 4, 5, a); f3 (6, 0, 1, 2, 3, 4, 5, a, 7, 8); f5 (6, 0, 1, 2, 3, 4, 5, b, 7, 8); f7 (6, 0, 1, 2, 3, 4, 5, c, 7, 8); f9 (5, a); f11 (5, a, 7, 8); f13 (5, b, 7, 8); f15 (5, c, 7, 8); return 0; } Now, comparing clang r319307 with g++ with the above patch, without any #defines it seems the two compilers are compatible, ditto with -DALIGNED=16, with -DALIGNED=128 or -DLARGE they are not, because the aggregates then are > 16 bytes long and are passed in MEMORY by clang++ and in NO_CLASS by g++ (and it honors alignment). So, I think the #c13 change is correct, but we need to decide if TYPE_EMPTY_P should be set on > 16 byte types or not and if it should be, adjust the psABI to say so.