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 | |