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 g(int * ip,float * fp,char * cp)11void 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); fip(int * i)26void fip(int *i) {} 27 28 void ffp(TU); ffp(float * f)29void ffp(float *f) {} 30 31 void flp(TU); flp(long * l)32void flp(long *l) {} 33 34 void fvp(TU); // expected-note{{previous declaration is here}} fvp(void * p)35void fvp(void *p) {} // expected-error{{conflicting types}} 36 37 void fsp(TU); // expected-note{{previous declaration is here}} fsp(short * s)38void fsp(short *s) {} // expected-error{{conflicting types}} 39 40 void fi(TU); // expected-note{{previous declaration is here}} fi(int i)41void fi(int i) {} // expected-error{{conflicting types}} 42 43 void fvpp(TU); // expected-note{{previous declaration is here}} fvpp(void ** v)44void 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 f_triple0(TU tu)49void 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 *); f_triple1(TU tu)54void 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}} f_triple2(TU tu)59void f_triple2(TU tu) {} 60 61 /* Test calling redeclared function taking a transparent_union arg. */ 62 63 void f_callee(TU); f_callee(int * i)64void f_callee(int *i) {} // expected-note{{passing argument to parameter 'i' here}} 65 caller(void)66void 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 foo11(int * i)148void foo11(int *i) { 149 bar(i); 150 } foo2(struct st * s)151void foo2(struct st *s) { 152 bar(s); 153 } 154