| 1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
| 2 | typedef union { |
| 3 | int *ip; |
| 4 | float *fp; |
| 5 | long *__restrict rlp; |
| 6 | void *vpa[1]; |
| 7 | } TU __attribute__((transparent_union)); |
| 8 | |
| 9 | void f(TU); // expected-note{{passing argument to parameter here}} |
| 10 | |
| 11 | void g(int *ip, float *fp, char *cp) { |
| 12 | f(ip); |
| 13 | f(fp); |
| 14 | f(cp); // expected-error{{incompatible type}} |
| 15 | f(0); |
| 16 | |
| 17 | TU tu_ip = ip; // expected-error{{incompatible type}} |
| 18 | TU tu; |
| 19 | tu.ip = ip; |
| 20 | } |
| 21 | |
| 22 | /* Test ability to redeclare a function taking a transparent_union arg |
| 23 | with various compatible and incompatible argument types. */ |
| 24 | |
| 25 | void fip(TU); |
| 26 | void fip(int *i) {} |
| 27 | |
| 28 | void ffp(TU); |
| 29 | void ffp(float *f) {} |
| 30 | |
| 31 | void flp(TU); |
| 32 | void flp(long *l) {} |
| 33 | |
| 34 | void fvp(TU); // expected-note{{previous declaration is here}} |
| 35 | void fvp(void *p) {} // expected-error{{conflicting types}} |
| 36 | |
| 37 | void fsp(TU); // expected-note{{previous declaration is here}} |
| 38 | void fsp(short *s) {} // expected-error{{conflicting types}} |
| 39 | |
| 40 | void fi(TU); // expected-note{{previous declaration is here}} |
| 41 | void fi(int i) {} // expected-error{{conflicting types}} |
| 42 | |
| 43 | void fvpp(TU); // expected-note{{previous declaration is here}} |
| 44 | void fvpp(void **v) {} // expected-error{{conflicting types}} |
| 45 | |
| 46 | /* Test redeclaring a function taking a transparent_union arg more than twice. |
| 47 | Merging different declarations depends on their order, vary order too. */ |
| 48 | |
| 49 | void f_triple0(TU tu) {} |
| 50 | void f_triple0(int *); // expected-note{{previous declaration is here}} |
| 51 | void f_triple0(float *f); // expected-error{{conflicting types}} |
| 52 | |
| 53 | void f_triple1(int *); |
| 54 | void f_triple1(TU tu) {} // expected-note{{previous definition is here}} |
| 55 | void f_triple1(float *f); // expected-error{{conflicting types}} |
| 56 | |
| 57 | void f_triple2(int *); // expected-note{{previous declaration is here}} |
| 58 | void f_triple2(float *f); // expected-error{{conflicting types}} |
| 59 | void f_triple2(TU tu) {} |
| 60 | |
| 61 | /* Test calling redeclared function taking a transparent_union arg. */ |
| 62 | |
| 63 | void f_callee(TU); |
| 64 | void f_callee(int *i) {} // expected-note{{passing argument to parameter 'i' here}} |
| 65 | |
| 66 | void caller(void) { |
| 67 | TU tu; |
| 68 | f_callee(tu); // expected-error{{passing 'TU' to parameter of incompatible type 'int *'}} |
| 69 | |
| 70 | int *i; |
| 71 | f_callee(i); |
| 72 | } |
| 73 | |
| 74 | |
| 75 | /* FIXME: we'd like to just use an "int" here and align it differently |
| 76 | from the normal "int", but if we do so we lose the alignment |
| 77 | information from the typedef within the compiler. */ |
| 78 | typedef struct { int x, y; } __attribute__((aligned(8))) aligned_struct8; |
| 79 | |
| 80 | typedef struct { int x, y; } __attribute__((aligned(4))) aligned_struct4; |
| 81 | typedef union { |
| 82 | aligned_struct4 s4; // expected-note{{alignment of first field}} |
| 83 | aligned_struct8 s8; // expected-warning{{alignment of field}} |
| 84 | } TU1 __attribute__((transparent_union)); |
| 85 | |
| 86 | typedef union __attribute__((transparent_union)) { |
| 87 | aligned_struct4 s4; // expected-note{{alignment of first field}} |
| 88 | aligned_struct8 s8; // expected-warning{{alignment of field}} |
| 89 | } TU1b ; |
| 90 | |
| 91 | typedef union { |
| 92 | char c; // expected-note{{size of first field is 8 bits}} |
| 93 | int i; // expected-warning{{size of field}} |
| 94 | } TU2 __attribute__((transparent_union)); |
| 95 | |
| 96 | typedef union __attribute__((transparent_union)){ |
| 97 | char c; // expected-note{{size of first field is 8 bits}} |
| 98 | int i; // expected-warning{{size of field}} |
| 99 | } TU2b; |
| 100 | |
| 101 | typedef union { |
| 102 | float f; // expected-warning{{floating}} |
| 103 | } TU3 __attribute__((transparent_union)); |
| 104 | |
| 105 | typedef union { } TU4 __attribute__((transparent_union)); // expected-warning{{field}} |
| 106 | |
| 107 | typedef int int4 __attribute__((ext_vector_type(4))); |
| 108 | typedef union { |
| 109 | int4 vec; // expected-warning{{first field of a transparent union cannot have vector type 'int4' (vector of 4 'int' values); transparent_union attribute ignored}} |
| 110 | } TU5 __attribute__((transparent_union)); |
| 111 | |
| 112 | union pr15134 { |
| 113 | unsigned int u; |
| 114 | struct { |
| 115 | unsigned int expo:2; |
| 116 | unsigned int mant:30; |
| 117 | } __attribute__((packed)); |
| 118 | // The packed attribute is acceptable because it defines a less strict |
| 119 | // alignment than required by the first field of the transparent union. |
| 120 | } __attribute__((transparent_union)); |
| 121 | |
| 122 | union pr15134v2 { |
| 123 | struct { // expected-note {{alignment of first field is 32 bits}} |
| 124 | unsigned int u1; |
| 125 | unsigned int u2; |
| 126 | }; |
| 127 | struct { // expected-warning {{alignment of field '' (64 bits) does not match the alignment of the first field in transparent union; transparent_union attribute ignored}} |
| 128 | unsigned int u3; |
| 129 | } __attribute__((aligned(8))); |
| 130 | } __attribute__((transparent_union)); |
| 131 | |
| 132 | union pr30520v { void b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'void'}} |
| 133 | |
| 134 | union pr30520a { int b[]; } __attribute__((transparent_union)); // expected-error {{flexible array member 'b' in a union is not allowed}} |
| 135 | |
| 136 | // expected-note@+1 2 {{forward declaration of 'struct stb'}} |
| 137 | union pr30520s { struct stb b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'struct stb'}} |
| 138 | |
| 139 | union pr30520s2 { int *v; struct stb b; } __attribute__((transparent_union)); // expected-error {{field has incomplete type 'struct stb'}} |
| 140 | |
| 141 | typedef union __attribute__((__transparent_union__)) { |
| 142 | int *i; |
| 143 | struct st *s; |
| 144 | } TU6; |
| 145 | |
| 146 | void bar(TU6); |
| 147 | |
| 148 | void foo11(int *i) { |
| 149 | bar(i); |
| 150 | } |
| 151 | void foo2(struct st *s) { |
| 152 | bar(s); |
| 153 | } |
| 154 | |