| @@ -1,1285 +1,1286 @@ | | | @@ -1,1285 +1,1286 @@ |
1 | /* $NetBSD: decl.c,v 1.366 2023/07/29 07:49:14 rillig Exp $ */ | | 1 | /* $NetBSD: decl.c,v 1.367 2023/07/29 11:03:18 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. | | 4 | * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. |
5 | * Copyright (c) 1994, 1995 Jochen Pohl | | 5 | * Copyright (c) 1994, 1995 Jochen Pohl |
6 | * All Rights Reserved. | | 6 | * All Rights Reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. All advertising materials mentioning features or use of this software | | 16 | * 3. All advertising materials mentioning features or use of this software |
17 | * must display the following acknowledgement: | | 17 | * must display the following acknowledgement: |
18 | * This product includes software developed by Jochen Pohl for | | 18 | * This product includes software developed by Jochen Pohl for |
19 | * The NetBSD Project. | | 19 | * The NetBSD Project. |
20 | * 4. The name of the author may not be used to endorse or promote products | | 20 | * 4. The name of the author may not be used to endorse or promote products |
21 | * derived from this software without specific prior written permission. | | 21 | * derived from this software without specific prior written permission. |
22 | * | | 22 | * |
23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #if HAVE_NBTOOL_CONFIG_H | | 35 | #if HAVE_NBTOOL_CONFIG_H |
36 | #include "nbtool_config.h" | | 36 | #include "nbtool_config.h" |
37 | #endif | | 37 | #endif |
38 | | | 38 | |
39 | #include <sys/cdefs.h> | | 39 | #include <sys/cdefs.h> |
40 | #if defined(__RCSID) | | 40 | #if defined(__RCSID) |
41 | __RCSID("$NetBSD: decl.c,v 1.366 2023/07/29 07:49:14 rillig Exp $"); | | 41 | __RCSID("$NetBSD: decl.c,v 1.367 2023/07/29 11:03:18 rillig Exp $"); |
42 | #endif | | 42 | #endif |
43 | | | 43 | |
44 | #include <sys/param.h> | | 44 | #include <sys/param.h> |
45 | #include <limits.h> | | 45 | #include <limits.h> |
46 | #include <stdlib.h> | | 46 | #include <stdlib.h> |
47 | #include <string.h> | | 47 | #include <string.h> |
48 | | | 48 | |
49 | #include "lint1.h" | | 49 | #include "lint1.h" |
50 | | | 50 | |
51 | const char unnamed[] = "<unnamed>"; | | 51 | const char unnamed[] = "<unnamed>"; |
52 | | | 52 | |
53 | /* shared type structures for arithmetic types and void */ | | 53 | /* shared type structures for arithmetic types and void */ |
54 | static type_t typetab[NTSPEC]; | | 54 | static type_t typetab[NTSPEC]; |
55 | | | 55 | |
56 | /* value of next enumerator during declaration of enum types */ | | 56 | /* value of next enumerator during declaration of enum types */ |
57 | int enumval; | | 57 | int enumval; |
58 | | | 58 | |
59 | /* | | 59 | /* |
60 | * Points to the innermost element of a stack that contains information about | | 60 | * Points to the innermost element of a stack that contains information about |
61 | * nested declarations, such as struct declarations, function prototypes, | | 61 | * nested declarations, such as struct declarations, function prototypes, |
62 | * local variables. | | 62 | * local variables. |
63 | */ | | 63 | */ |
64 | decl_level *dcs; | | 64 | decl_level *dcs; |
65 | | | 65 | |
66 | | | 66 | |
67 | /* | | 67 | /* |
68 | * initializes all global vars used in declarations | | 68 | * initializes all global vars used in declarations |
69 | */ | | 69 | */ |
70 | void | | 70 | void |
71 | initdecl(void) | | 71 | initdecl(void) |
72 | { | | 72 | { |
73 | | | 73 | |
74 | /* declaration stack */ | | 74 | /* declaration stack */ |
75 | dcs = xcalloc(1, sizeof(*dcs)); | | 75 | dcs = xcalloc(1, sizeof(*dcs)); |
76 | dcs->d_kind = DLK_EXTERN; | | 76 | dcs->d_kind = DLK_EXTERN; |
77 | dcs->d_last_dlsym = &dcs->d_first_dlsym; | | 77 | dcs->d_last_dlsym = &dcs->d_first_dlsym; |
78 | | | 78 | |
79 | if (!pflag) { | | 79 | if (!pflag) { |
80 | for (size_t i = 0; i < NTSPEC; i++) { | | 80 | for (size_t i = 0; i < NTSPEC; i++) { |
81 | if (ttab[i].tt_rank_kind != RK_NONE) | | 81 | if (ttab[i].tt_rank_kind != RK_NONE) |
82 | ttab[i].tt_rank_value = | | 82 | ttab[i].tt_rank_value = |
83 | ttab[i].tt_size_in_bits; | | 83 | ttab[i].tt_size_in_bits; |
84 | } | | 84 | } |
85 | ttab[BOOL].tt_rank_value = 1; | | 85 | ttab[BOOL].tt_rank_value = 1; |
86 | } | | 86 | } |
87 | | | 87 | |
88 | if (Tflag) { | | 88 | if (Tflag) { |
89 | ttab[BOOL].tt_is_integer = false; | | 89 | ttab[BOOL].tt_is_integer = false; |
90 | ttab[BOOL].tt_is_uinteger = false; | | 90 | ttab[BOOL].tt_is_uinteger = false; |
91 | ttab[BOOL].tt_is_arithmetic = false; | | 91 | ttab[BOOL].tt_is_arithmetic = false; |
92 | } | | 92 | } |
93 | | | 93 | |
94 | /* struct, union, enum, ptr, array and func are not shared. */ | | 94 | /* struct, union, enum, ptr, array and func are not shared. */ |
95 | for (int i = (int)SIGNED; i < (int)STRUCT; i++) | | 95 | for (int i = (int)SIGNED; i < (int)STRUCT; i++) |
96 | typetab[i].t_tspec = (tspec_t)i; | | 96 | typetab[i].t_tspec = (tspec_t)i; |
97 | } | | 97 | } |
98 | | | 98 | |
99 | /* | | 99 | /* |
100 | * Returns a shared type structure for arithmetic types and void. | | 100 | * Returns a shared type structure for arithmetic types and void. |
101 | * | | 101 | * |
102 | * It's important to duplicate this structure using block_dup_type or | | 102 | * It's important to duplicate this structure using block_dup_type or |
103 | * expr_dup_type if it is to be modified (adding qualifiers or anything | | 103 | * expr_dup_type if it is to be modified (adding qualifiers or anything |
104 | * else). | | 104 | * else). |
105 | */ | | 105 | */ |
106 | type_t * | | 106 | type_t * |
107 | gettyp(tspec_t t) | | 107 | gettyp(tspec_t t) |
108 | { | | 108 | { |
109 | | | 109 | |
110 | lint_assert((int)t < (int)STRUCT); | | 110 | lint_assert((int)t < (int)STRUCT); |
111 | /* TODO: make the return type 'const' */ | | 111 | /* TODO: make the return type 'const' */ |
112 | return &typetab[t]; | | 112 | return &typetab[t]; |
113 | } | | 113 | } |
114 | | | 114 | |
115 | type_t * | | 115 | type_t * |
116 | block_dup_type(const type_t *tp) | | 116 | block_dup_type(const type_t *tp) |
117 | { | | 117 | { |
118 | | | 118 | |
119 | type_t *ntp = block_zero_alloc(sizeof(*ntp), "type"); | | 119 | type_t *ntp = block_zero_alloc(sizeof(*ntp), "type"); |
120 | *ntp = *tp; | | 120 | *ntp = *tp; |
121 | return ntp; | | 121 | return ntp; |
122 | } | | 122 | } |
123 | | | 123 | |
124 | /* Duplicate a type, free the allocated memory after the expression. */ | | 124 | /* Duplicate a type, free the allocated memory after the expression. */ |
125 | type_t * | | 125 | type_t * |
126 | expr_dup_type(const type_t *tp) | | 126 | expr_dup_type(const type_t *tp) |
127 | { | | 127 | { |
128 | | | 128 | |
129 | type_t *ntp = expr_zero_alloc(sizeof(*ntp), "type"); | | 129 | type_t *ntp = expr_zero_alloc(sizeof(*ntp), "type"); |
130 | *ntp = *tp; | | 130 | *ntp = *tp; |
131 | return ntp; | | 131 | return ntp; |
132 | } | | 132 | } |
133 | | | 133 | |
134 | /* | | 134 | /* |
135 | * Return the unqualified version of the type. The returned type is freed at | | 135 | * Return the unqualified version of the type. The returned type is freed at |
136 | * the end of the current expression. | | 136 | * the end of the current expression. |
137 | * | | 137 | * |
138 | * See C99 6.2.5p25. | | 138 | * See C99 6.2.5p25. |
139 | */ | | 139 | */ |
140 | type_t * | | 140 | type_t * |
141 | expr_unqualified_type(const type_t *tp) | | 141 | expr_unqualified_type(const type_t *tp) |
142 | { | | 142 | { |
143 | | | 143 | |
144 | type_t *ntp = expr_zero_alloc(sizeof(*ntp), "type"); | | 144 | type_t *ntp = expr_zero_alloc(sizeof(*ntp), "type"); |
145 | *ntp = *tp; | | 145 | *ntp = *tp; |
146 | ntp->t_const = false; | | 146 | ntp->t_const = false; |
147 | ntp->t_volatile = false; | | 147 | ntp->t_volatile = false; |
148 | | | 148 | |
149 | /* | | 149 | /* |
150 | * In case of a struct or union type, the members should lose their | | 150 | * In case of a struct or union type, the members should lose their |
151 | * qualifiers as well, but that would require a deep copy of the | | 151 | * qualifiers as well, but that would require a deep copy of the |
152 | * struct or union type. This in turn would defeat the type | | 152 | * struct or union type. This in turn would defeat the type |
153 | * comparison in types_compatible, which simply tests whether | | 153 | * comparison in types_compatible, which simply tests whether |
154 | * tp1->t_sou == tp2->t_sou. | | 154 | * tp1->t_sou == tp2->t_sou. |
155 | */ | | 155 | */ |
156 | | | 156 | |
157 | return ntp; | | 157 | return ntp; |
158 | } | | 158 | } |
159 | | | 159 | |
160 | /* | | 160 | /* |
161 | * Returns whether the argument is void or an incomplete array, struct, union | | 161 | * Returns whether the argument is void or an incomplete array, struct, union |
162 | * or enum type. | | 162 | * or enum type. |
163 | */ | | 163 | */ |
164 | bool | | 164 | bool |
165 | is_incomplete(const type_t *tp) | | 165 | is_incomplete(const type_t *tp) |
166 | { | | 166 | { |
167 | tspec_t t = tp->t_tspec; | | 167 | tspec_t t = tp->t_tspec; |
168 | | | 168 | |
169 | if (t == VOID) | | 169 | if (t == VOID) |
170 | return true; | | 170 | return true; |
171 | if (t == ARRAY) | | 171 | if (t == ARRAY) |
172 | return tp->t_incomplete_array; | | 172 | return tp->t_incomplete_array; |
173 | if (is_struct_or_union(t)) | | 173 | if (is_struct_or_union(t)) |
174 | return tp->t_sou->sou_incomplete; | | 174 | return tp->t_sou->sou_incomplete; |
175 | if (t == ENUM) | | 175 | if (t == ENUM) |
176 | return tp->t_enum->en_incomplete; | | 176 | return tp->t_enum->en_incomplete; |
177 | return false; | | 177 | return false; |
178 | } | | 178 | } |
179 | | | 179 | |
180 | void | | 180 | void |
181 | dcs_add_function_specifier(function_specifier fs) | | 181 | dcs_add_function_specifier(function_specifier fs) |
182 | { | | 182 | { |
183 | debug_step("%s: %s", __func__, function_specifier_name(fs)); | | 183 | debug_step("%s: %s", __func__, function_specifier_name(fs)); |
184 | if (fs == FS_INLINE) { | | 184 | if (fs == FS_INLINE) { |
185 | if (dcs->d_inline) | | 185 | if (dcs->d_inline) |
186 | /* duplicate '%s' */ | | 186 | /* duplicate '%s' */ |
187 | warning(10, "inline"); | | 187 | warning(10, "inline"); |
188 | dcs->d_inline = true; | | 188 | dcs->d_inline = true; |
189 | } | | 189 | } |
190 | } | | 190 | } |
191 | | | 191 | |
192 | /* | | 192 | /* |
193 | * Remember the storage class of the current declaration and detect multiple | | 193 | * Remember the storage class of the current declaration and detect multiple |
194 | * storage classes. | | 194 | * storage classes. |
195 | */ | | 195 | */ |
196 | void | | 196 | void |
197 | dcs_add_storage_class(scl_t sc) | | 197 | dcs_add_storage_class(scl_t sc) |
198 | { | | 198 | { |
199 | | | 199 | |
200 | if (dcs->d_type != NULL || dcs->d_abstract_type != NO_TSPEC || | | 200 | if (dcs->d_type != NULL || dcs->d_abstract_type != NO_TSPEC || |
201 | dcs->d_sign_mod != NO_TSPEC || dcs->d_rank_mod != NO_TSPEC) { | | 201 | dcs->d_sign_mod != NO_TSPEC || dcs->d_rank_mod != NO_TSPEC) { |
202 | /* storage class after type is obsolescent */ | | 202 | /* storage class after type is obsolescent */ |
203 | warning(83); | | 203 | warning(83); |
204 | } | | 204 | } |
205 | | | 205 | |
206 | if (dcs->d_scl == NOSCL) | | 206 | if (dcs->d_scl == NOSCL) |
207 | dcs->d_scl = sc; | | 207 | dcs->d_scl = sc; |
208 | else if ((dcs->d_scl == EXTERN && sc == THREAD_LOCAL) | | 208 | else if ((dcs->d_scl == EXTERN && sc == THREAD_LOCAL) |
209 | || (dcs->d_scl == THREAD_LOCAL && sc == EXTERN)) | | 209 | || (dcs->d_scl == THREAD_LOCAL && sc == EXTERN)) |
210 | dcs->d_scl = EXTERN; /* ignore thread_local */ | | 210 | dcs->d_scl = EXTERN; /* ignore thread_local */ |
211 | else if ((dcs->d_scl == STATIC && sc == THREAD_LOCAL) | | 211 | else if ((dcs->d_scl == STATIC && sc == THREAD_LOCAL) |
212 | || (dcs->d_scl == THREAD_LOCAL && sc == STATIC)) | | 212 | || (dcs->d_scl == THREAD_LOCAL && sc == STATIC)) |
213 | dcs->d_scl = STATIC; /* ignore thread_local */ | | 213 | dcs->d_scl = STATIC; /* ignore thread_local */ |
214 | else | | 214 | else |
215 | dcs->d_multiple_storage_classes = true; | | 215 | dcs->d_multiple_storage_classes = true; |
216 | } | | 216 | } |
217 | | | 217 | |
218 | /* Merge the signedness into the abstract type. */ | | 218 | /* Merge the signedness into the abstract type. */ |
219 | static tspec_t | | 219 | static tspec_t |
220 | merge_signedness(tspec_t t, tspec_t s) | | 220 | merge_signedness(tspec_t t, tspec_t s) |
221 | { | | 221 | { |
222 | | | 222 | |
223 | if (s == SIGNED) | | 223 | if (s == SIGNED) |
224 | return t == CHAR ? SCHAR : t; | | 224 | return t == CHAR ? SCHAR : t; |
225 | if (s != UNSIGN) | | 225 | if (s != UNSIGN) |
226 | return t; | | 226 | return t; |
227 | return t == CHAR ? UCHAR | | 227 | return t == CHAR ? UCHAR |
228 | : t == SHORT ? USHORT | | 228 | : t == SHORT ? USHORT |
229 | : t == INT ? UINT | | 229 | : t == INT ? UINT |
230 | : t == LONG ? ULONG | | 230 | : t == LONG ? ULONG |
231 | : t == LLONG ? ULLONG | | 231 | : t == LLONG ? ULLONG |
232 | : t; | | 232 | : t; |
233 | } | | 233 | } |
234 | | | 234 | |
235 | /* | | 235 | /* |
236 | * Called if a list of declaration specifiers contains a typedef name | | 236 | * Called if a list of declaration specifiers contains a typedef name |
237 | * and other specifiers (except struct, union, enum, typedef name). | | 237 | * and other specifiers (except struct, union, enum, typedef name). |
238 | */ | | 238 | */ |
239 | static type_t * | | 239 | static type_t * |
240 | typedef_error(type_t *td, tspec_t t) | | 240 | typedef_error(type_t *td, tspec_t t) |
241 | { | | 241 | { |
242 | | | 242 | |
243 | tspec_t t2 = td->t_tspec; | | 243 | tspec_t t2 = td->t_tspec; |
244 | | | 244 | |
245 | if ((t == SIGNED || t == UNSIGN) && | | 245 | if ((t == SIGNED || t == UNSIGN) && |
246 | (t2 == CHAR || t2 == SHORT || t2 == INT || | | 246 | (t2 == CHAR || t2 == SHORT || t2 == INT || |
247 | t2 == LONG || t2 == LLONG)) { | | 247 | t2 == LONG || t2 == LLONG)) { |
248 | if (allow_c90) | | 248 | if (allow_c90) |
249 | /* modifying typedef with '%s'; only qualifiers... */ | | 249 | /* modifying typedef with '%s'; only qualifiers... */ |
250 | warning(5, tspec_name(t)); | | 250 | warning(5, tspec_name(t)); |
251 | td = block_dup_type(gettyp(merge_signedness(t2, t))); | | 251 | td = block_dup_type(gettyp(merge_signedness(t2, t))); |
252 | td->t_typedef = true; | | 252 | td->t_typedef = true; |
253 | return td; | | 253 | return td; |
254 | } | | 254 | } |
255 | | | 255 | |
256 | if (t == SHORT && (t2 == INT || t2 == UINT)) { | | 256 | if (t == SHORT && (t2 == INT || t2 == UINT)) { |
257 | /* modifying typedef with '%s'; only qualifiers allowed */ | | 257 | /* modifying typedef with '%s'; only qualifiers allowed */ |
258 | warning(5, "short"); | | 258 | warning(5, "short"); |
259 | td = block_dup_type(gettyp(t2 == INT ? SHORT : USHORT)); | | 259 | td = block_dup_type(gettyp(t2 == INT ? SHORT : USHORT)); |
260 | td->t_typedef = true; | | 260 | td->t_typedef = true; |
261 | return td; | | 261 | return td; |
262 | } | | 262 | } |
263 | | | 263 | |
264 | if (t != LONG) | | 264 | if (t != LONG) |
265 | goto invalid; | | 265 | goto invalid; |
266 | | | 266 | |
| | | 267 | tspec_t lt; |
267 | if (t2 == INT) | | 268 | if (t2 == INT) |
268 | td = gettyp(LONG); | | 269 | lt = LONG; |
269 | else if (t2 == UINT) | | 270 | else if (t2 == UINT) |
270 | td = gettyp(ULONG); | | 271 | lt = ULONG; |
271 | else if (t2 == LONG) | | 272 | else if (t2 == LONG) |
272 | td = gettyp(LLONG); | | 273 | lt = LLONG; |
273 | else if (t2 == ULONG) | | 274 | else if (t2 == ULONG) |
274 | td = gettyp(ULLONG); | | 275 | lt = ULLONG; |
275 | else if (t2 == FLOAT) | | 276 | else if (t2 == FLOAT) |
276 | td = gettyp(DOUBLE); | | 277 | lt = DOUBLE; |
277 | else if (t2 == DOUBLE) | | 278 | else if (t2 == DOUBLE) |
278 | td = gettyp(LDOUBLE); | | 279 | lt = LDOUBLE; |
279 | else if (t2 == DCOMPLEX) | | 280 | else if (t2 == DCOMPLEX) |
280 | td = gettyp(LCOMPLEX); | | 281 | lt = LCOMPLEX; |
281 | else | | 282 | else |
282 | goto invalid; | | 283 | goto invalid; |
283 | | | 284 | |
284 | /* modifying typedef with '%s'; only qualifiers allowed */ | | 285 | /* modifying typedef with '%s'; only qualifiers allowed */ |
285 | warning(5, "long"); | | 286 | warning(5, "long"); |
286 | td = block_dup_type(td); | | 287 | td = block_dup_type(gettyp(lt)); |
287 | td->t_typedef = true; | | 288 | td->t_typedef = true; |
288 | return td; | | 289 | return td; |
289 | | | 290 | |
290 | invalid: | | 291 | invalid: |
291 | /* Anything else is not accepted. */ | | 292 | /* Anything else is not accepted. */ |
292 | dcs->d_invalid_type_combination = true; | | 293 | dcs->d_invalid_type_combination = true; |
293 | return td; | | 294 | return td; |
294 | } | | 295 | } |
295 | | | 296 | |
296 | /* | | 297 | /* |
297 | * Remember the type, modifier or typedef name returned by the parser in the | | 298 | * Remember the type, modifier or typedef name returned by the parser in the |
298 | * top element of the declaration stack. This information is used in | | 299 | * top element of the declaration stack. This information is used in |
299 | * dcs_end_type to build the type used for all declarators in this declaration. | | 300 | * dcs_end_type to build the type used for all declarators in this declaration. |
300 | * | | 301 | * |
301 | * If tp->t_typedef is true, the type comes from a previously defined typename. | | 302 | * If tp->t_typedef is true, the type comes from a previously defined typename. |
302 | * Otherwise, it comes from a type specifier (int, long, ...) or a | | 303 | * Otherwise, it comes from a type specifier (int, long, ...) or a |
303 | * struct/union/enum tag. | | 304 | * struct/union/enum tag. |
304 | */ | | 305 | */ |
305 | void | | 306 | void |
306 | dcs_add_type(type_t *tp) | | 307 | dcs_add_type(type_t *tp) |
307 | { | | 308 | { |
308 | | | 309 | |
309 | debug_step("%s: %s", __func__, type_name(tp)); | | 310 | debug_step("%s: %s", __func__, type_name(tp)); |
310 | if (tp->t_typedef) { | | 311 | if (tp->t_typedef) { |
311 | /* | | 312 | /* |
312 | * something like "typedef int a; int a b;" | | 313 | * something like "typedef int a; int a b;" |
313 | * This should not happen with current grammar. | | 314 | * This should not happen with current grammar. |
314 | */ | | 315 | */ |
315 | lint_assert(dcs->d_type == NULL); | | 316 | lint_assert(dcs->d_type == NULL); |
316 | lint_assert(dcs->d_abstract_type == NO_TSPEC); | | 317 | lint_assert(dcs->d_abstract_type == NO_TSPEC); |
317 | lint_assert(dcs->d_sign_mod == NO_TSPEC); | | 318 | lint_assert(dcs->d_sign_mod == NO_TSPEC); |
318 | lint_assert(dcs->d_rank_mod == NO_TSPEC); | | 319 | lint_assert(dcs->d_rank_mod == NO_TSPEC); |
319 | | | 320 | |
320 | dcs->d_type = tp; | | 321 | dcs->d_type = tp; |
321 | return; | | 322 | return; |
322 | } | | 323 | } |
323 | | | 324 | |
324 | tspec_t t = tp->t_tspec; | | 325 | tspec_t t = tp->t_tspec; |
325 | if (is_struct_or_union(t) || t == ENUM) { | | 326 | if (is_struct_or_union(t) || t == ENUM) { |
326 | /* | | 327 | /* |
327 | * something like "int struct a ..." | | 328 | * something like "int struct a ..." |
328 | * struct/union/enum with anything else is not allowed | | 329 | * struct/union/enum with anything else is not allowed |
329 | */ | | 330 | */ |
330 | if (dcs->d_type != NULL || dcs->d_abstract_type != NO_TSPEC || | | 331 | if (dcs->d_type != NULL || dcs->d_abstract_type != NO_TSPEC || |
331 | dcs->d_rank_mod != NO_TSPEC || dcs->d_sign_mod != NO_TSPEC) { | | 332 | dcs->d_rank_mod != NO_TSPEC || dcs->d_sign_mod != NO_TSPEC) { |
332 | dcs->d_invalid_type_combination = true; | | 333 | dcs->d_invalid_type_combination = true; |
333 | dcs->d_abstract_type = NO_TSPEC; | | 334 | dcs->d_abstract_type = NO_TSPEC; |
334 | dcs->d_sign_mod = NO_TSPEC; | | 335 | dcs->d_sign_mod = NO_TSPEC; |
335 | dcs->d_rank_mod = NO_TSPEC; | | 336 | dcs->d_rank_mod = NO_TSPEC; |
336 | } | | 337 | } |
337 | dcs->d_type = tp; | | 338 | dcs->d_type = tp; |
338 | return; | | 339 | return; |
339 | } | | 340 | } |
340 | | | 341 | |
341 | if (dcs->d_type != NULL && !dcs->d_type->t_typedef) { | | 342 | if (dcs->d_type != NULL && !dcs->d_type->t_typedef) { |
342 | /* | | 343 | /* |
343 | * something like "struct a int" | | 344 | * something like "struct a int" |
344 | * struct/union/enum with anything else is not allowed | | 345 | * struct/union/enum with anything else is not allowed |
345 | */ | | 346 | */ |
346 | dcs->d_invalid_type_combination = true; | | 347 | dcs->d_invalid_type_combination = true; |
347 | return; | | 348 | return; |
348 | } | | 349 | } |
349 | | | 350 | |
350 | if (t == COMPLEX) { | | 351 | if (t == COMPLEX) { |
351 | if (dcs->d_complex_mod == FLOAT) | | 352 | if (dcs->d_complex_mod == FLOAT) |
352 | t = FCOMPLEX; | | 353 | t = FCOMPLEX; |
353 | else if (dcs->d_complex_mod == DOUBLE) | | 354 | else if (dcs->d_complex_mod == DOUBLE) |
354 | t = DCOMPLEX; | | 355 | t = DCOMPLEX; |
355 | else { | | 356 | else { |
356 | /* invalid type for _Complex */ | | 357 | /* invalid type for _Complex */ |
357 | error(308); | | 358 | error(308); |
358 | t = DCOMPLEX; /* just as a fallback */ | | 359 | t = DCOMPLEX; /* just as a fallback */ |
359 | } | | 360 | } |
360 | dcs->d_complex_mod = NO_TSPEC; | | 361 | dcs->d_complex_mod = NO_TSPEC; |
361 | } | | 362 | } |
362 | | | 363 | |
363 | if (t == LONG && dcs->d_rank_mod == LONG) { | | 364 | if (t == LONG && dcs->d_rank_mod == LONG) { |
364 | /* "long long" or "long ... long" */ | | 365 | /* "long long" or "long ... long" */ |
365 | t = LLONG; | | 366 | t = LLONG; |
366 | dcs->d_rank_mod = NO_TSPEC; | | 367 | dcs->d_rank_mod = NO_TSPEC; |
367 | if (!suppress_longlong) | | 368 | if (!suppress_longlong) |
368 | /* %s does not support 'long long' */ | | 369 | /* %s does not support 'long long' */ |
369 | c99ism(265, allow_c90 ? "C90" : "traditional C"); | | 370 | c99ism(265, allow_c90 ? "C90" : "traditional C"); |
370 | } | | 371 | } |
371 | | | 372 | |
372 | if (dcs->d_type != NULL && dcs->d_type->t_typedef) { | | 373 | if (dcs->d_type != NULL && dcs->d_type->t_typedef) { |
373 | /* something like "typedef int a; a long ..." */ | | 374 | /* something like "typedef int a; a long ..." */ |
374 | dcs->d_type = typedef_error(dcs->d_type, t); | | 375 | dcs->d_type = typedef_error(dcs->d_type, t); |
375 | return; | | 376 | return; |
376 | } | | 377 | } |
377 | | | 378 | |
378 | /* now it can be only a combination of arithmetic types and void */ | | 379 | /* now it can be only a combination of arithmetic types and void */ |
379 | if (t == SIGNED || t == UNSIGN) { | | 380 | if (t == SIGNED || t == UNSIGN) { |
380 | if (dcs->d_sign_mod != NO_TSPEC) | | 381 | if (dcs->d_sign_mod != NO_TSPEC) |
381 | dcs->d_invalid_type_combination = true; | | 382 | dcs->d_invalid_type_combination = true; |
382 | dcs->d_sign_mod = t; | | 383 | dcs->d_sign_mod = t; |
383 | } else if (t == SHORT || t == LONG || t == LLONG) { | | 384 | } else if (t == SHORT || t == LONG || t == LLONG) { |
384 | if (dcs->d_rank_mod != NO_TSPEC) | | 385 | if (dcs->d_rank_mod != NO_TSPEC) |
385 | dcs->d_invalid_type_combination = true; | | 386 | dcs->d_invalid_type_combination = true; |
386 | dcs->d_rank_mod = t; | | 387 | dcs->d_rank_mod = t; |
387 | } else if (t == FLOAT || t == DOUBLE) { | | 388 | } else if (t == FLOAT || t == DOUBLE) { |
388 | if (dcs->d_rank_mod == NO_TSPEC || dcs->d_rank_mod == LONG) { | | 389 | if (dcs->d_rank_mod == NO_TSPEC || dcs->d_rank_mod == LONG) { |
389 | if (dcs->d_complex_mod != NO_TSPEC | | 390 | if (dcs->d_complex_mod != NO_TSPEC |
390 | || (t == FLOAT && dcs->d_rank_mod == LONG)) | | 391 | || (t == FLOAT && dcs->d_rank_mod == LONG)) |
391 | dcs->d_invalid_type_combination = true; | | 392 | dcs->d_invalid_type_combination = true; |
392 | dcs->d_complex_mod = t; | | 393 | dcs->d_complex_mod = t; |
393 | } else { | | 394 | } else { |
394 | if (dcs->d_abstract_type != NO_TSPEC) | | 395 | if (dcs->d_abstract_type != NO_TSPEC) |
395 | dcs->d_invalid_type_combination = true; | | 396 | dcs->d_invalid_type_combination = true; |
396 | dcs->d_abstract_type = t; | | 397 | dcs->d_abstract_type = t; |
397 | } | | 398 | } |
398 | } else if (t == PTR) { | | 399 | } else if (t == PTR) { |
399 | dcs->d_type = tp; | | 400 | dcs->d_type = tp; |
400 | } else { | | 401 | } else { |
401 | if (dcs->d_abstract_type != NO_TSPEC) | | 402 | if (dcs->d_abstract_type != NO_TSPEC) |
402 | dcs->d_invalid_type_combination = true; | | 403 | dcs->d_invalid_type_combination = true; |
403 | dcs->d_abstract_type = t; | | 404 | dcs->d_abstract_type = t; |
404 | } | | 405 | } |
405 | } | | 406 | } |
406 | | | 407 | |
407 | static void | | 408 | static void |
408 | set_first_typedef(type_t *tp, sym_t *sym) | | 409 | set_first_typedef(type_t *tp, sym_t *sym) |
409 | { | | 410 | { |
410 | | | 411 | |
411 | tspec_t t = tp->t_tspec; | | 412 | tspec_t t = tp->t_tspec; |
412 | if (is_struct_or_union(t) && tp->t_sou->sou_first_typedef == NULL) | | 413 | if (is_struct_or_union(t) && tp->t_sou->sou_first_typedef == NULL) |
413 | tp->t_sou->sou_first_typedef = sym; | | 414 | tp->t_sou->sou_first_typedef = sym; |
414 | if (t == ENUM && tp->t_enum->en_first_typedef == NULL) | | 415 | if (t == ENUM && tp->t_enum->en_first_typedef == NULL) |
415 | tp->t_enum->en_first_typedef = sym; | | 416 | tp->t_enum->en_first_typedef = sym; |
416 | } | | 417 | } |
417 | | | 418 | |
418 | static unsigned int | | 419 | static unsigned int |
419 | bit_fields_width(const sym_t **mem, bool *named) | | 420 | bit_fields_width(const sym_t **mem, bool *named) |
420 | { | | 421 | { |
421 | unsigned int width = 0; | | 422 | unsigned int width = 0; |
422 | unsigned int align = 0; | | 423 | unsigned int align = 0; |
423 | while (*mem != NULL && (*mem)->s_type->t_bitfield) { | | 424 | while (*mem != NULL && (*mem)->s_type->t_bitfield) { |
424 | if ((*mem)->s_name != unnamed) | | 425 | if ((*mem)->s_name != unnamed) |
425 | *named = true; | | 426 | *named = true; |
426 | width += (*mem)->s_type->t_bit_field_width; | | 427 | width += (*mem)->s_type->t_bit_field_width; |
427 | unsigned int mem_align = alignment_in_bits((*mem)->s_type); | | 428 | unsigned int mem_align = alignment_in_bits((*mem)->s_type); |
428 | if (mem_align > align) | | 429 | if (mem_align > align) |
429 | align = mem_align; | | 430 | align = mem_align; |
430 | *mem = (*mem)->s_next; | | 431 | *mem = (*mem)->s_next; |
431 | } | | 432 | } |
432 | return (width + align - 1) & -align; | | 433 | return (width + align - 1) & -align; |
433 | } | | 434 | } |
434 | | | 435 | |
435 | static void | | 436 | static void |
436 | pack_struct_or_union(type_t *tp) | | 437 | pack_struct_or_union(type_t *tp) |
437 | { | | 438 | { |
438 | | | 439 | |
439 | if (!is_struct_or_union(tp->t_tspec)) { | | 440 | if (!is_struct_or_union(tp->t_tspec)) { |
440 | /* attribute '%s' ignored for '%s' */ | | 441 | /* attribute '%s' ignored for '%s' */ |
441 | warning(326, "packed", type_name(tp)); | | 442 | warning(326, "packed", type_name(tp)); |
442 | return; | | 443 | return; |
443 | } | | 444 | } |
444 | | | 445 | |
445 | unsigned int bits = 0; | | 446 | unsigned int bits = 0; |
446 | bool named = false; | | 447 | bool named = false; |
447 | for (const sym_t *mem = tp->t_sou->sou_first_member; | | 448 | for (const sym_t *mem = tp->t_sou->sou_first_member; |
448 | mem != NULL; mem = mem->s_next) { | | 449 | mem != NULL; mem = mem->s_next) { |
449 | // TODO: Maybe update mem->u.s_member.sm_offset_in_bits. | | 450 | // TODO: Maybe update mem->u.s_member.sm_offset_in_bits. |
450 | if (mem->s_type->t_bitfield) { | | 451 | if (mem->s_type->t_bitfield) { |
451 | bits += bit_fields_width(&mem, &named); | | 452 | bits += bit_fields_width(&mem, &named); |
452 | if (mem == NULL) | | 453 | if (mem == NULL) |
453 | break; | | 454 | break; |
454 | } | | 455 | } |
455 | unsigned int mem_bits = type_size_in_bits(mem->s_type); | | 456 | unsigned int mem_bits = type_size_in_bits(mem->s_type); |
456 | if (tp->t_tspec == STRUCT) | | 457 | if (tp->t_tspec == STRUCT) |
457 | bits += mem_bits; | | 458 | bits += mem_bits; |
458 | else if (mem_bits > bits) | | 459 | else if (mem_bits > bits) |
459 | bits = mem_bits; | | 460 | bits = mem_bits; |
460 | } | | 461 | } |
461 | tp->t_sou->sou_size_in_bits = bits; | | 462 | tp->t_sou->sou_size_in_bits = bits; |
462 | } | | 463 | } |
463 | | | 464 | |
464 | void | | 465 | void |
465 | dcs_add_packed(void) | | 466 | dcs_add_packed(void) |
466 | { | | 467 | { |
467 | if (dcs->d_type == NULL) | | 468 | if (dcs->d_type == NULL) |
468 | dcs->d_packed = true; | | 469 | dcs->d_packed = true; |
469 | else | | 470 | else |
470 | pack_struct_or_union(dcs->d_type); | | 471 | pack_struct_or_union(dcs->d_type); |
471 | } | | 472 | } |
472 | | | 473 | |
473 | void | | 474 | void |
474 | dcs_set_used(void) | | 475 | dcs_set_used(void) |
475 | { | | 476 | { |
476 | dcs->d_used = true; | | 477 | dcs->d_used = true; |
477 | } | | 478 | } |
478 | | | 479 | |
479 | /* | | 480 | /* |
480 | * Remember a qualifier that is part of the declaration specifiers (and not the | | 481 | * Remember a qualifier that is part of the declaration specifiers (and not the |
481 | * declarator). The remembered qualifier is used by dcs_end_type for all | | 482 | * declarator). The remembered qualifier is used by dcs_end_type for all |
482 | * declarators. | | 483 | * declarators. |
483 | */ | | 484 | */ |
484 | void | | 485 | void |
485 | dcs_add_qualifiers(type_qualifiers qs) | | 486 | dcs_add_qualifiers(type_qualifiers qs) |
486 | { | | 487 | { |
487 | add_type_qualifiers(&dcs->d_qual, qs); | | 488 | add_type_qualifiers(&dcs->d_qual, qs); |
488 | } | | 489 | } |
489 | | | 490 | |
490 | void | | 491 | void |
491 | begin_declaration_level(decl_level_kind kind) | | 492 | begin_declaration_level(decl_level_kind kind) |
492 | { | | 493 | { |
493 | | | 494 | |
494 | decl_level *dl = xcalloc(1, sizeof(*dl)); | | 495 | decl_level *dl = xcalloc(1, sizeof(*dl)); |
495 | dl->d_enclosing = dcs; | | 496 | dl->d_enclosing = dcs; |
496 | dl->d_kind = kind; | | 497 | dl->d_kind = kind; |
497 | dl->d_last_dlsym = &dl->d_first_dlsym; | | 498 | dl->d_last_dlsym = &dl->d_first_dlsym; |
498 | dcs = dl; | | 499 | dcs = dl; |
499 | debug_enter(); | | 500 | debug_enter(); |
500 | debug_dcs(true); | | 501 | debug_dcs(true); |
501 | } | | 502 | } |
502 | | | 503 | |
503 | void | | 504 | void |
504 | end_declaration_level(void) | | 505 | end_declaration_level(void) |
505 | { | | 506 | { |
506 | | | 507 | |
507 | debug_dcs(true); | | 508 | debug_dcs(true); |
508 | | | 509 | |
509 | decl_level *dl = dcs; | | 510 | decl_level *dl = dcs; |
510 | dcs = dl->d_enclosing; | | 511 | dcs = dl->d_enclosing; |
511 | lint_assert(dcs != NULL); | | 512 | lint_assert(dcs != NULL); |
512 | | | 513 | |
513 | switch (dl->d_kind) { | | 514 | switch (dl->d_kind) { |
514 | case DLK_STRUCT: | | 515 | case DLK_STRUCT: |
515 | case DLK_UNION: | | 516 | case DLK_UNION: |
516 | case DLK_ENUM: | | 517 | case DLK_ENUM: |
517 | /* | | 518 | /* |
518 | * Symbols declared in (nested) structs or enums are part of | | 519 | * Symbols declared in (nested) structs or enums are part of |
519 | * the next level (they are removed from the symbol table if | | 520 | * the next level (they are removed from the symbol table if |
520 | * the symbols of the outer level are removed). | | 521 | * the symbols of the outer level are removed). |
521 | */ | | 522 | */ |
522 | if ((*dcs->d_last_dlsym = dl->d_first_dlsym) != NULL) | | 523 | if ((*dcs->d_last_dlsym = dl->d_first_dlsym) != NULL) |
523 | dcs->d_last_dlsym = dl->d_last_dlsym; | | 524 | dcs->d_last_dlsym = dl->d_last_dlsym; |
524 | break; | | 525 | break; |
525 | case DLK_OLD_STYLE_ARGS: | | 526 | case DLK_OLD_STYLE_ARGS: |
526 | /* | | 527 | /* |
527 | * All symbols in dcs->d_first_dlsym are introduced in | | 528 | * All symbols in dcs->d_first_dlsym are introduced in |
528 | * old-style argument declarations (it's not clean, but | | 529 | * old-style argument declarations (it's not clean, but |
529 | * possible). They are appended to the list of symbols declared | | 530 | * possible). They are appended to the list of symbols declared |
530 | * in an old-style argument identifier list or a new-style | | 531 | * in an old-style argument identifier list or a new-style |
531 | * parameter type list. | | 532 | * parameter type list. |
532 | */ | | 533 | */ |
533 | if (dl->d_first_dlsym != NULL) { | | 534 | if (dl->d_first_dlsym != NULL) { |
534 | *dl->d_last_dlsym = dcs->d_func_proto_syms; | | 535 | *dl->d_last_dlsym = dcs->d_func_proto_syms; |
535 | dcs->d_func_proto_syms = dl->d_first_dlsym; | | 536 | dcs->d_func_proto_syms = dl->d_first_dlsym; |
536 | } | | 537 | } |
537 | break; | | 538 | break; |
538 | case DLK_ABSTRACT: | | 539 | case DLK_ABSTRACT: |
539 | /* | | 540 | /* |
540 | * Append all symbols declared in the abstract declaration to | | 541 | * Append all symbols declared in the abstract declaration to |
541 | * the list of symbols declared in the surrounding declaration | | 542 | * the list of symbols declared in the surrounding declaration |
542 | * or block. | | 543 | * or block. |
543 | * | | 544 | * |
544 | * XXX I'm not sure whether they should be removed from the | | 545 | * XXX I'm not sure whether they should be removed from the |
545 | * symbol table now or later. | | 546 | * symbol table now or later. |
546 | */ | | 547 | */ |
547 | if ((*dcs->d_last_dlsym = dl->d_first_dlsym) != NULL) | | 548 | if ((*dcs->d_last_dlsym = dl->d_first_dlsym) != NULL) |
548 | dcs->d_last_dlsym = dl->d_last_dlsym; | | 549 | dcs->d_last_dlsym = dl->d_last_dlsym; |
549 | break; | | 550 | break; |
550 | case DLK_AUTO: | | 551 | case DLK_AUTO: |
551 | check_usage(dl); | | 552 | check_usage(dl); |
552 | /* FALLTHROUGH */ | | 553 | /* FALLTHROUGH */ |
553 | case DLK_PROTO_PARAMS: | | 554 | case DLK_PROTO_PARAMS: |
554 | /* usage of arguments will be checked by end_function() */ | | 555 | /* usage of arguments will be checked by end_function() */ |
555 | symtab_remove_level(dl->d_first_dlsym); | | 556 | symtab_remove_level(dl->d_first_dlsym); |
556 | break; | | 557 | break; |
557 | case DLK_EXTERN: | | 558 | case DLK_EXTERN: |
558 | /* there is nothing around an external declaration */ | | 559 | /* there is nothing around an external declaration */ |
559 | /* FALLTHROUGH */ | | 560 | /* FALLTHROUGH */ |
560 | default: | | 561 | default: |
561 | lint_assert(/*CONSTCOND*/false); | | 562 | lint_assert(/*CONSTCOND*/false); |
562 | } | | 563 | } |
563 | free(dl); | | 564 | free(dl); |
564 | debug_leave(); | | 565 | debug_leave(); |
565 | } | | 566 | } |
566 | | | 567 | |
567 | /* | | 568 | /* |
568 | * Set flag d_asm in all declaration stack elements up to the outermost one. | | 569 | * Set flag d_asm in all declaration stack elements up to the outermost one. |
569 | * | | 570 | * |
570 | * This is used to mark compound statements which have, possibly in nested | | 571 | * This is used to mark compound statements which have, possibly in nested |
571 | * compound statements, asm statements. For these compound statements, no | | 572 | * compound statements, asm statements. For these compound statements, no |
572 | * warnings about unused or uninitialized variables are printed. | | 573 | * warnings about unused or uninitialized variables are printed. |
573 | * | | 574 | * |
574 | * There is no need to clear d_asm in decl_level structs with context AUTO, as | | 575 | * There is no need to clear d_asm in decl_level structs with context AUTO, as |
575 | * these structs are freed at the end of the compound statement. But it must be | | 576 | * these structs are freed at the end of the compound statement. But it must be |
576 | * cleared in the outermost decl_level struct, which has context EXTERN. This | | 577 | * cleared in the outermost decl_level struct, which has context EXTERN. This |
577 | * could be done in dcs_begin_type and would work for C90, but not for C99 or | | 578 | * could be done in dcs_begin_type and would work for C90, but not for C99 or |
578 | * C++ (due to mixed statements and declarations). Thus, we clear it in | | 579 | * C++ (due to mixed statements and declarations). Thus, we clear it in |
579 | * global_clean_up_decl. | | 580 | * global_clean_up_decl. |
580 | */ | | 581 | */ |
581 | void | | 582 | void |
582 | dcs_set_asm(void) | | 583 | dcs_set_asm(void) |
583 | { | | 584 | { |
584 | | | 585 | |
585 | for (decl_level *dl = dcs; dl != NULL; dl = dl->d_enclosing) | | 586 | for (decl_level *dl = dcs; dl != NULL; dl = dl->d_enclosing) |
586 | dl->d_asm = true; | | 587 | dl->d_asm = true; |
587 | } | | 588 | } |
588 | | | 589 | |
589 | void | | 590 | void |
590 | dcs_begin_type(void) | | 591 | dcs_begin_type(void) |
591 | { | | 592 | { |
592 | | | 593 | |
593 | debug_enter(); | | 594 | debug_enter(); |
594 | dcs->d_abstract_type = NO_TSPEC; | | 595 | dcs->d_abstract_type = NO_TSPEC; |
595 | dcs->d_complex_mod = NO_TSPEC; | | 596 | dcs->d_complex_mod = NO_TSPEC; |
596 | dcs->d_sign_mod = NO_TSPEC; | | 597 | dcs->d_sign_mod = NO_TSPEC; |
597 | dcs->d_rank_mod = NO_TSPEC; | | 598 | dcs->d_rank_mod = NO_TSPEC; |
598 | dcs->d_scl = NOSCL; | | 599 | dcs->d_scl = NOSCL; |
599 | dcs->d_type = NULL; | | 600 | dcs->d_type = NULL; |
600 | dcs->d_qual = (type_qualifiers) { .tq_const = false }; | | 601 | dcs->d_qual = (type_qualifiers) { .tq_const = false }; |
601 | dcs->d_inline = false; | | 602 | dcs->d_inline = false; |
602 | dcs->d_multiple_storage_classes = false; | | 603 | dcs->d_multiple_storage_classes = false; |
603 | dcs->d_invalid_type_combination = false; | | 604 | dcs->d_invalid_type_combination = false; |
604 | dcs->d_nonempty_decl = false; | | 605 | dcs->d_nonempty_decl = false; |
605 | dcs->d_no_type_specifier = false; | | 606 | dcs->d_no_type_specifier = false; |
606 | } | | 607 | } |
607 | | | 608 | |
608 | static void | | 609 | static void |
609 | dcs_adjust_storage_class(void) | | 610 | dcs_adjust_storage_class(void) |
610 | { | | 611 | { |
611 | if (dcs->d_kind == DLK_EXTERN) { | | 612 | if (dcs->d_kind == DLK_EXTERN) { |
612 | if (dcs->d_scl == REG || dcs->d_scl == AUTO) { | | 613 | if (dcs->d_scl == REG || dcs->d_scl == AUTO) { |
613 | /* illegal storage class */ | | 614 | /* illegal storage class */ |
614 | error(8); | | 615 | error(8); |
615 | dcs->d_scl = NOSCL; | | 616 | dcs->d_scl = NOSCL; |
616 | } | | 617 | } |
617 | } else if (dcs->d_kind == DLK_OLD_STYLE_ARGS || | | 618 | } else if (dcs->d_kind == DLK_OLD_STYLE_ARGS || |
618 | dcs->d_kind == DLK_PROTO_PARAMS) { | | 619 | dcs->d_kind == DLK_PROTO_PARAMS) { |
619 | if (dcs->d_scl != NOSCL && dcs->d_scl != REG) { | | 620 | if (dcs->d_scl != NOSCL && dcs->d_scl != REG) { |
620 | /* only 'register' is valid as storage class ... */ | | 621 | /* only 'register' is valid as storage class ... */ |
621 | error(9); | | 622 | error(9); |
622 | dcs->d_scl = NOSCL; | | 623 | dcs->d_scl = NOSCL; |
623 | } | | 624 | } |
624 | } | | 625 | } |
625 | } | | 626 | } |
626 | | | 627 | |
627 | /* | | 628 | /* |
628 | * Merge the declaration specifiers from dcs into dcs->d_type. | | 629 | * Merge the declaration specifiers from dcs into dcs->d_type. |
629 | * | | 630 | * |
630 | * See C99 6.7.2 "Type specifiers". | | 631 | * See C99 6.7.2 "Type specifiers". |
631 | */ | | 632 | */ |
632 | static void | | 633 | static void |
633 | dcs_merge_declaration_specifiers(void) | | 634 | dcs_merge_declaration_specifiers(void) |
634 | { | | 635 | { |
635 | tspec_t t = dcs->d_abstract_type; | | 636 | tspec_t t = dcs->d_abstract_type; |
636 | tspec_t c = dcs->d_complex_mod; | | 637 | tspec_t c = dcs->d_complex_mod; |
637 | tspec_t s = dcs->d_sign_mod; | | 638 | tspec_t s = dcs->d_sign_mod; |
638 | tspec_t l = dcs->d_rank_mod; | | 639 | tspec_t l = dcs->d_rank_mod; |
639 | type_t *tp = dcs->d_type; | | 640 | type_t *tp = dcs->d_type; |
640 | | | 641 | |
641 | if (tp != NULL) { | | 642 | if (tp != NULL) { |
642 | lint_assert(t == NO_TSPEC); | | 643 | lint_assert(t == NO_TSPEC); |
643 | lint_assert(s == NO_TSPEC); | | 644 | lint_assert(s == NO_TSPEC); |
644 | lint_assert(l == NO_TSPEC); | | 645 | lint_assert(l == NO_TSPEC); |
645 | return; | | 646 | return; |
646 | } | | 647 | } |
647 | | | 648 | |
648 | debug_step("%s: %s", __func__, type_name(tp)); | | 649 | debug_step("%s: %s", __func__, type_name(tp)); |
649 | | | 650 | |
650 | if (t == NO_TSPEC && s == NO_TSPEC && l == NO_TSPEC && c == NO_TSPEC) | | 651 | if (t == NO_TSPEC && s == NO_TSPEC && l == NO_TSPEC && c == NO_TSPEC) |
651 | dcs->d_no_type_specifier = true; | | 652 | dcs->d_no_type_specifier = true; |
652 | if (t == NO_TSPEC && s == NO_TSPEC && (l == NO_TSPEC || l == LONG)) | | 653 | if (t == NO_TSPEC && s == NO_TSPEC && (l == NO_TSPEC || l == LONG)) |
653 | t = c; | | 654 | t = c; |
654 | | | 655 | |
655 | if (t == NO_TSPEC) | | 656 | if (t == NO_TSPEC) |
656 | t = INT; | | 657 | t = INT; |
657 | if (s == NO_TSPEC && t == INT) | | 658 | if (s == NO_TSPEC && t == INT) |
658 | s = SIGNED; | | 659 | s = SIGNED; |
659 | if (l != NO_TSPEC && t == CHAR) { | | 660 | if (l != NO_TSPEC && t == CHAR) { |
660 | dcs->d_invalid_type_combination = true; | | 661 | dcs->d_invalid_type_combination = true; |
661 | l = NO_TSPEC; | | 662 | l = NO_TSPEC; |
662 | } | | 663 | } |
663 | if (l == LONG && t == FLOAT) { | | 664 | if (l == LONG && t == FLOAT) { |
664 | l = NO_TSPEC; | | 665 | l = NO_TSPEC; |
665 | t = DOUBLE; | | 666 | t = DOUBLE; |
666 | if (allow_c90) | | 667 | if (allow_c90) |
667 | /* use 'double' instead of 'long float' */ | | 668 | /* use 'double' instead of 'long float' */ |
668 | warning(6); | | 669 | warning(6); |
669 | } | | 670 | } |
670 | if ((l == LONG && t == DOUBLE) || t == LDOUBLE) { | | 671 | if ((l == LONG && t == DOUBLE) || t == LDOUBLE) { |
671 | l = NO_TSPEC; | | 672 | l = NO_TSPEC; |
672 | t = LDOUBLE; | | 673 | t = LDOUBLE; |
673 | } | | 674 | } |
674 | if (t == LDOUBLE && !allow_c90) { | | 675 | if (t == LDOUBLE && !allow_c90) { |
675 | /* 'long double' is illegal in traditional C */ | | 676 | /* 'long double' is illegal in traditional C */ |
676 | warning(266); | | 677 | warning(266); |
677 | } | | 678 | } |
678 | if (l == LONG && t == DCOMPLEX) { | | 679 | if (l == LONG && t == DCOMPLEX) { |
679 | l = NO_TSPEC; | | 680 | l = NO_TSPEC; |
680 | t = LCOMPLEX; | | 681 | t = LCOMPLEX; |
681 | } | | 682 | } |
682 | | | 683 | |
683 | if (t != INT && t != CHAR && (s != NO_TSPEC || l != NO_TSPEC)) { | | 684 | if (t != INT && t != CHAR && (s != NO_TSPEC || l != NO_TSPEC)) { |
684 | dcs->d_invalid_type_combination = true; | | 685 | dcs->d_invalid_type_combination = true; |
685 | l = s = NO_TSPEC; | | 686 | l = s = NO_TSPEC; |
686 | } | | 687 | } |
687 | if (l != NO_TSPEC) | | 688 | if (l != NO_TSPEC) |
688 | t = l; | | 689 | t = l; |
689 | dcs->d_type = gettyp(merge_signedness(t, s)); | | 690 | dcs->d_type = gettyp(merge_signedness(t, s)); |
690 | } | | 691 | } |
691 | | | 692 | |
692 | /* Create a type in 'dcs->d_type' from the information gathered in 'dcs'. */ | | 693 | /* Create a type in 'dcs->d_type' from the information gathered in 'dcs'. */ |
693 | void | | 694 | void |
694 | dcs_end_type(void) | | 695 | dcs_end_type(void) |
695 | { | | 696 | { |
696 | | | 697 | |
697 | dcs_merge_declaration_specifiers(); | | 698 | dcs_merge_declaration_specifiers(); |
698 | | | 699 | |
699 | if (dcs->d_multiple_storage_classes) { | | 700 | if (dcs->d_multiple_storage_classes) { |
700 | /* only one storage class allowed */ | | 701 | /* only one storage class allowed */ |
701 | error(7); | | 702 | error(7); |
702 | } | | 703 | } |
703 | if (dcs->d_invalid_type_combination) { | | 704 | if (dcs->d_invalid_type_combination) { |
704 | /* illegal type combination */ | | 705 | /* illegal type combination */ |
705 | error(4); | | 706 | error(4); |
706 | } | | 707 | } |
707 | | | 708 | |
708 | dcs_adjust_storage_class(); | | 709 | dcs_adjust_storage_class(); |
709 | | | 710 | |
710 | if (dcs->d_qual.tq_const && dcs->d_type->t_const | | 711 | if (dcs->d_qual.tq_const && dcs->d_type->t_const |
711 | && !dcs->d_type->t_typeof) { | | 712 | && !dcs->d_type->t_typeof) { |
712 | lint_assert(dcs->d_type->t_typedef); | | 713 | lint_assert(dcs->d_type->t_typedef); |
713 | /* typedef already qualified with '%s' */ | | 714 | /* typedef already qualified with '%s' */ |
714 | warning(68, "const"); | | 715 | warning(68, "const"); |
715 | } | | 716 | } |
716 | if (dcs->d_qual.tq_volatile && dcs->d_type->t_volatile && | | 717 | if (dcs->d_qual.tq_volatile && dcs->d_type->t_volatile && |
717 | !dcs->d_type->t_typeof) { | | 718 | !dcs->d_type->t_typeof) { |
718 | lint_assert(dcs->d_type->t_typedef); | | 719 | lint_assert(dcs->d_type->t_typedef); |
719 | /* typedef already qualified with '%s' */ | | 720 | /* typedef already qualified with '%s' */ |
720 | warning(68, "volatile"); | | 721 | warning(68, "volatile"); |
721 | } | | 722 | } |
722 | | | 723 | |
723 | if (dcs->d_qual.tq_const || dcs->d_qual.tq_volatile) { | | 724 | if (dcs->d_qual.tq_const || dcs->d_qual.tq_volatile) { |
724 | dcs->d_type = block_dup_type(dcs->d_type); | | 725 | dcs->d_type = block_dup_type(dcs->d_type); |
725 | dcs->d_type->t_const |= dcs->d_qual.tq_const; | | 726 | dcs->d_type->t_const |= dcs->d_qual.tq_const; |
726 | dcs->d_type->t_volatile |= dcs->d_qual.tq_volatile; | | 727 | dcs->d_type->t_volatile |= dcs->d_qual.tq_volatile; |
727 | } | | 728 | } |
728 | | | 729 | |
729 | debug_leave(); | | 730 | debug_leave(); |
730 | } | | 731 | } |
731 | | | 732 | |
732 | /* | | 733 | /* |
733 | * Return the length of a type in bits. For bit-fields, return the length of | | 734 | * Return the length of a type in bits. For bit-fields, return the length of |
734 | * the underlying storage type. | | 735 | * the underlying storage type. |
735 | * | | 736 | * |
736 | * Printing a message if the outermost dimension of an array is 0 must | | 737 | * Printing a message if the outermost dimension of an array is 0 must |
737 | * be done by the caller. All other problems are reported by this function | | 738 | * be done by the caller. All other problems are reported by this function |
738 | * if name is not NULL. | | 739 | * if name is not NULL. |
739 | */ | | 740 | */ |
740 | int | | 741 | int |
741 | length_in_bits(const type_t *tp, const char *name) | | 742 | length_in_bits(const type_t *tp, const char *name) |
742 | { | | 743 | { |
743 | | | 744 | |
744 | if (tp == NULL) | | 745 | if (tp == NULL) |
745 | return -1; | | 746 | return -1; |
746 | | | 747 | |
747 | unsigned int elem = 1; | | 748 | unsigned int elem = 1; |
748 | while (tp->t_tspec == ARRAY) { | | 749 | while (tp->t_tspec == ARRAY) { |
749 | elem *= tp->t_dim; | | 750 | elem *= tp->t_dim; |
750 | tp = tp->t_subt; | | 751 | tp = tp->t_subt; |
751 | } | | 752 | } |
752 | | | 753 | |
753 | if (is_struct_or_union(tp->t_tspec)) { | | 754 | if (is_struct_or_union(tp->t_tspec)) { |
754 | if (is_incomplete(tp) && name != NULL) { | | 755 | if (is_incomplete(tp) && name != NULL) { |
755 | /* '%s' has incomplete type '%s' */ | | 756 | /* '%s' has incomplete type '%s' */ |
756 | error(31, name, type_name(tp)); | | 757 | error(31, name, type_name(tp)); |
757 | } | | 758 | } |
758 | return (int)(elem * tp->t_sou->sou_size_in_bits); | | 759 | return (int)(elem * tp->t_sou->sou_size_in_bits); |
759 | } | | 760 | } |
760 | | | 761 | |
761 | if (tp->t_tspec == ENUM && is_incomplete(tp) && name != NULL) | | 762 | if (tp->t_tspec == ENUM && is_incomplete(tp) && name != NULL) |
762 | /* incomplete enum type '%s' */ | | 763 | /* incomplete enum type '%s' */ |
763 | warning(13, name); | | 764 | warning(13, name); |
764 | | | 765 | |
765 | lint_assert(tp->t_tspec != FUNC); | | 766 | lint_assert(tp->t_tspec != FUNC); |
766 | | | 767 | |
767 | unsigned int elsz = size_in_bits(tp->t_tspec); | | 768 | unsigned int elsz = size_in_bits(tp->t_tspec); |
768 | /* | | 769 | /* |
769 | * Workaround until the type parser (see add_function, add_array, | | 770 | * Workaround until the type parser (see add_function, add_array, |
770 | * add_pointer) does not construct the invalid intermediate declaration | | 771 | * add_pointer) does not construct the invalid intermediate declaration |
771 | * 'void b[4]' for the legitimate declaration 'void *b[4]'. | | 772 | * 'void b[4]' for the legitimate declaration 'void *b[4]'. |
772 | */ | | 773 | */ |
773 | if (sytxerr > 0 && elsz == 0) | | 774 | if (sytxerr > 0 && elsz == 0) |
774 | elsz = CHAR_SIZE; | | 775 | elsz = CHAR_SIZE; |
775 | lint_assert(elsz > 0); | | 776 | lint_assert(elsz > 0); |
776 | return (int)(elem * elsz); | | 777 | return (int)(elem * elsz); |
777 | } | | 778 | } |
778 | | | 779 | |
779 | unsigned int | | 780 | unsigned int |
780 | alignment_in_bits(const type_t *tp) | | 781 | alignment_in_bits(const type_t *tp) |
781 | { | | 782 | { |
782 | | | 783 | |
783 | /* Super conservative so that it works for most systems. */ | | 784 | /* Super conservative so that it works for most systems. */ |
784 | unsigned int worst_align_in_bits = 2 * LONG_SIZE; | | 785 | unsigned int worst_align_in_bits = 2 * LONG_SIZE; |
785 | | | 786 | |
786 | while (tp->t_tspec == ARRAY) | | 787 | while (tp->t_tspec == ARRAY) |
787 | tp = tp->t_subt; | | 788 | tp = tp->t_subt; |
788 | | | 789 | |
789 | tspec_t t = tp->t_tspec; | | 790 | tspec_t t = tp->t_tspec; |
790 | unsigned int a; | | 791 | unsigned int a; |
791 | if (is_struct_or_union(t)) | | 792 | if (is_struct_or_union(t)) |
792 | a = tp->t_sou->sou_align_in_bits; | | 793 | a = tp->t_sou->sou_align_in_bits; |
793 | else { | | 794 | else { |
794 | lint_assert(t != FUNC); | | 795 | lint_assert(t != FUNC); |
795 | if ((a = size_in_bits(t)) == 0) | | 796 | if ((a = size_in_bits(t)) == 0) |
796 | a = CHAR_SIZE; | | 797 | a = CHAR_SIZE; |
797 | else if (a > worst_align_in_bits) | | 798 | else if (a > worst_align_in_bits) |
798 | a = worst_align_in_bits; | | 799 | a = worst_align_in_bits; |
799 | } | | 800 | } |
800 | lint_assert(a >= CHAR_SIZE); | | 801 | lint_assert(a >= CHAR_SIZE); |
801 | lint_assert(a <= worst_align_in_bits); | | 802 | lint_assert(a <= worst_align_in_bits); |
802 | return a; | | 803 | return a; |
803 | } | | 804 | } |
804 | | | 805 | |
805 | /* | | 806 | /* |
806 | * Concatenate two lists of symbols by s_next. Used by declarations of | | 807 | * Concatenate two lists of symbols by s_next. Used by declarations of |
807 | * struct/union/enum elements and parameters. | | 808 | * struct/union/enum elements and parameters. |
808 | */ | | 809 | */ |
809 | sym_t * | | 810 | sym_t * |
810 | concat_symbols(sym_t *l1, sym_t *l2) | | 811 | concat_symbols(sym_t *l1, sym_t *l2) |
811 | { | | 812 | { |
812 | | | 813 | |
813 | if (l1 == NULL) | | 814 | if (l1 == NULL) |
814 | return l2; | | 815 | return l2; |
815 | sym_t *l = l1; | | 816 | sym_t *l = l1; |
816 | while (l->s_next != NULL) | | 817 | while (l->s_next != NULL) |
817 | l = l->s_next; | | 818 | l = l->s_next; |
818 | l->s_next = l2; | | 819 | l->s_next = l2; |
819 | return l1; | | 820 | return l1; |
820 | } | | 821 | } |
821 | | | 822 | |
822 | /* | | 823 | /* |
823 | * Check if the type of the given symbol is valid. | | 824 | * Check if the type of the given symbol is valid. |
824 | * | | 825 | * |
825 | * Invalid types are: | | 826 | * Invalid types are: |
826 | * - arrays of incomplete types or functions | | 827 | * - arrays of incomplete types or functions |
827 | * - functions returning arrays or functions | | 828 | * - functions returning arrays or functions |
828 | * - void types other than type of function or pointer | | 829 | * - void types other than type of function or pointer |
829 | */ | | 830 | */ |
830 | void | | 831 | void |
831 | check_type(sym_t *sym) | | 832 | check_type(sym_t *sym) |
832 | { | | 833 | { |
833 | | | 834 | |
834 | type_t **tpp = &sym->s_type; | | 835 | type_t **tpp = &sym->s_type; |
835 | tspec_t to = NO_TSPEC; | | 836 | tspec_t to = NO_TSPEC; |
836 | while (*tpp != NULL) { | | 837 | while (*tpp != NULL) { |
837 | type_t *tp = *tpp; | | 838 | type_t *tp = *tpp; |
838 | tspec_t t = tp->t_tspec; | | 839 | tspec_t t = tp->t_tspec; |
839 | /* | | 840 | /* |
840 | * If this is the type of an old-style function definition, | | 841 | * If this is the type of an old-style function definition, |
841 | * a better warning is printed in begin_function(). | | 842 | * a better warning is printed in begin_function(). |
842 | */ | | 843 | */ |
843 | if (t == FUNC && !tp->t_proto && | | 844 | if (t == FUNC && !tp->t_proto && |
844 | !(to == NO_TSPEC && sym->s_osdef)) { | | 845 | !(to == NO_TSPEC && sym->s_osdef)) { |
845 | /* TODO: Make this an error in C99 mode as well. */ | | 846 | /* TODO: Make this an error in C99 mode as well. */ |
846 | if ((!allow_trad && !allow_c99) && hflag) | | 847 | if ((!allow_trad && !allow_c99) && hflag) |
847 | /* function declaration is not a prototype */ | | 848 | /* function declaration is not a prototype */ |
848 | warning(287); | | 849 | warning(287); |
849 | } | | 850 | } |
850 | if (to == FUNC) { | | 851 | if (to == FUNC) { |
851 | if (t == FUNC || t == ARRAY) { | | 852 | if (t == FUNC || t == ARRAY) { |
852 | /* function returns illegal type '%s' */ | | 853 | /* function returns illegal type '%s' */ |
853 | error(15, type_name(tp)); | | 854 | error(15, type_name(tp)); |
854 | *tpp = block_derive_type( | | 855 | *tpp = block_derive_type( |
855 | t == FUNC ? *tpp : (*tpp)->t_subt, PTR); | | 856 | t == FUNC ? *tpp : (*tpp)->t_subt, PTR); |
856 | return; | | 857 | return; |
857 | } | | 858 | } |
858 | if (tp->t_const || tp->t_volatile) { | | 859 | if (tp->t_const || tp->t_volatile) { |
859 | /* TODO: Make this a warning in C99 mode as well. */ | | 860 | /* TODO: Make this a warning in C99 mode as well. */ |
860 | if (!allow_trad && !allow_c99) { /* XXX or better allow_c90? */ | | 861 | if (!allow_trad && !allow_c99) { /* XXX or better allow_c90? */ |
861 | /* function cannot return const... */ | | 862 | /* function cannot return const... */ |
862 | warning(228); | | 863 | warning(228); |
863 | } | | 864 | } |
864 | } | | 865 | } |
865 | } else if (to == ARRAY) { | | 866 | } else if (to == ARRAY) { |
866 | if (t == FUNC) { | | 867 | if (t == FUNC) { |
867 | /* array of function is illegal */ | | 868 | /* array of function is illegal */ |
868 | error(16); | | 869 | error(16); |
869 | *tpp = gettyp(INT); | | 870 | *tpp = gettyp(INT); |
870 | return; | | 871 | return; |
871 | } | | 872 | } |
872 | if (t == ARRAY && tp->t_dim == 0) { | | 873 | if (t == ARRAY && tp->t_dim == 0) { |
873 | /* null dimension */ | | 874 | /* null dimension */ |
874 | error(17); | | 875 | error(17); |
875 | return; | | 876 | return; |
876 | } | | 877 | } |
877 | if (t == VOID) { | | 878 | if (t == VOID) { |
878 | /* illegal use of 'void' */ | | 879 | /* illegal use of 'void' */ |
879 | error(18); | | 880 | error(18); |
880 | *tpp = gettyp(INT); | | 881 | *tpp = gettyp(INT); |
881 | } | | 882 | } |
882 | /* | | 883 | /* |
883 | * No need to check for incomplete types here as | | 884 | * No need to check for incomplete types here as |
884 | * length_in_bits already does this. | | 885 | * length_in_bits already does this. |
885 | */ | | 886 | */ |
886 | } else if (to == NO_TSPEC && t == VOID) { | | 887 | } else if (to == NO_TSPEC && t == VOID) { |
887 | if (dcs->d_kind == DLK_PROTO_PARAMS) { | | 888 | if (dcs->d_kind == DLK_PROTO_PARAMS) { |
888 | if (sym->s_scl != ABSTRACT) { | | 889 | if (sym->s_scl != ABSTRACT) { |
889 | lint_assert(sym->s_name != unnamed); | | 890 | lint_assert(sym->s_name != unnamed); |
890 | /* void parameter '%s' cannot ... */ | | 891 | /* void parameter '%s' cannot ... */ |
891 | error(61, sym->s_name); | | 892 | error(61, sym->s_name); |
892 | *tpp = gettyp(INT); | | 893 | *tpp = gettyp(INT); |
893 | } | | 894 | } |
894 | } else if (dcs->d_kind == DLK_ABSTRACT) { | | 895 | } else if (dcs->d_kind == DLK_ABSTRACT) { |
895 | /* ok */ | | 896 | /* ok */ |
896 | } else if (sym->s_scl != TYPEDEF) { | | 897 | } else if (sym->s_scl != TYPEDEF) { |
897 | /* void type for '%s' */ | | 898 | /* void type for '%s' */ |
898 | error(19, sym->s_name); | | 899 | error(19, sym->s_name); |
899 | *tpp = gettyp(INT); | | 900 | *tpp = gettyp(INT); |
900 | } | | 901 | } |
901 | } | | 902 | } |
902 | if (t == VOID && to != PTR) { | | 903 | if (t == VOID && to != PTR) { |
903 | if (tp->t_const || tp->t_volatile) { | | 904 | if (tp->t_const || tp->t_volatile) { |
904 | /* inappropriate qualifiers with 'void' */ | | 905 | /* inappropriate qualifiers with 'void' */ |
905 | warning(69); | | 906 | warning(69); |
906 | tp->t_const = tp->t_volatile = false; | | 907 | tp->t_const = tp->t_volatile = false; |
907 | } | | 908 | } |
908 | } | | 909 | } |
909 | tpp = &tp->t_subt; | | 910 | tpp = &tp->t_subt; |
910 | to = t; | | 911 | to = t; |
911 | } | | 912 | } |
912 | } | | 913 | } |
913 | | | 914 | |
914 | /* | | 915 | /* |
915 | * In traditional C, the only portable type for bit-fields is unsigned int. | | 916 | * In traditional C, the only portable type for bit-fields is unsigned int. |
916 | * | | 917 | * |
917 | * In C90, the only allowed types for bit-fields are int, signed int and | | 918 | * In C90, the only allowed types for bit-fields are int, signed int and |
918 | * unsigned int (3.5.2.1). There is no mention of implementation-defined | | 919 | * unsigned int (3.5.2.1). There is no mention of implementation-defined |
919 | * types. | | 920 | * types. |
920 | * | | 921 | * |
921 | * In C99, the only portable types for bit-fields are _Bool, signed int and | | 922 | * In C99, the only portable types for bit-fields are _Bool, signed int and |
922 | * unsigned int (6.7.2.1p4). In addition, C99 allows "or some other | | 923 | * unsigned int (6.7.2.1p4). In addition, C99 allows "or some other |
923 | * implementation-defined type". | | 924 | * implementation-defined type". |
924 | */ | | 925 | */ |
925 | static void | | 926 | static void |
926 | check_bit_field_type(sym_t *dsym, type_t **const inout_tp, tspec_t *inout_t) | | 927 | check_bit_field_type(sym_t *dsym, type_t **const inout_tp, tspec_t *inout_t) |
927 | { | | 928 | { |
928 | type_t *tp = *inout_tp; | | 929 | type_t *tp = *inout_tp; |
929 | tspec_t t = *inout_t; | | 930 | tspec_t t = *inout_t; |
930 | | | 931 | |
931 | if (t == CHAR || t == UCHAR || t == SCHAR || | | 932 | if (t == CHAR || t == UCHAR || t == SCHAR || |
932 | t == SHORT || t == USHORT || t == ENUM) { | | 933 | t == SHORT || t == USHORT || t == ENUM) { |
933 | if (!suppress_bitfieldtype) { | | 934 | if (!suppress_bitfieldtype) { |
934 | /* TODO: Make this an error in C99 mode as well. */ | | 935 | /* TODO: Make this an error in C99 mode as well. */ |
935 | if (!allow_trad && !allow_c99) { | | 936 | if (!allow_trad && !allow_c99) { |
936 | type_t *btp = block_dup_type(tp); | | 937 | type_t *btp = block_dup_type(tp); |
937 | btp->t_bitfield = false; | | 938 | btp->t_bitfield = false; |
938 | /* bit-field type '%s' invalid in ANSI C */ | | 939 | /* bit-field type '%s' invalid in ANSI C */ |
939 | warning(273, type_name(btp)); | | 940 | warning(273, type_name(btp)); |
940 | } else if (pflag) { | | 941 | } else if (pflag) { |
941 | type_t *btp = block_dup_type(tp); | | 942 | type_t *btp = block_dup_type(tp); |
942 | btp->t_bitfield = false; | | 943 | btp->t_bitfield = false; |
943 | /* nonportable bit-field type '%s' */ | | 944 | /* nonportable bit-field type '%s' */ |
944 | warning(34, type_name(btp)); | | 945 | warning(34, type_name(btp)); |
945 | } | | 946 | } |
946 | } | | 947 | } |
947 | } else if (t == INT && dcs->d_sign_mod == NO_TSPEC) { | | 948 | } else if (t == INT && dcs->d_sign_mod == NO_TSPEC) { |
948 | if (pflag && !suppress_bitfieldtype) { | | 949 | if (pflag && !suppress_bitfieldtype) { |
949 | /* bit-field of type plain 'int' has ... */ | | 950 | /* bit-field of type plain 'int' has ... */ |
950 | warning(344); | | 951 | warning(344); |
951 | } | | 952 | } |
952 | } else if (!(t == INT || t == UINT || t == BOOL | | 953 | } else if (!(t == INT || t == UINT || t == BOOL |
953 | || (is_integer(t) && (suppress_bitfieldtype || allow_gcc)))) { | | 954 | || (is_integer(t) && (suppress_bitfieldtype || allow_gcc)))) { |
954 | | | 955 | |
955 | type_t *btp = block_dup_type(tp); | | 956 | type_t *btp = block_dup_type(tp); |
956 | btp->t_bitfield = false; | | 957 | btp->t_bitfield = false; |
957 | /* illegal bit-field type '%s' */ | | 958 | /* illegal bit-field type '%s' */ |
958 | warning(35, type_name(btp)); | | 959 | warning(35, type_name(btp)); |
959 | | | 960 | |
960 | unsigned int width = tp->t_bit_field_width; | | 961 | unsigned int width = tp->t_bit_field_width; |
961 | dsym->s_type = tp = block_dup_type(gettyp(t = INT)); | | 962 | dsym->s_type = tp = block_dup_type(gettyp(t = INT)); |
962 | if ((tp->t_bit_field_width = width) > size_in_bits(t)) | | 963 | if ((tp->t_bit_field_width = width) > size_in_bits(t)) |
963 | tp->t_bit_field_width = size_in_bits(t); | | 964 | tp->t_bit_field_width = size_in_bits(t); |
964 | *inout_t = t; | | 965 | *inout_t = t; |
965 | *inout_tp = tp; | | 966 | *inout_tp = tp; |
966 | } | | 967 | } |
967 | } | | 968 | } |
968 | | | 969 | |
969 | static void | | 970 | static void |
970 | check_bit_field(sym_t *dsym, tspec_t *inout_t, type_t **const inout_tp) | | 971 | check_bit_field(sym_t *dsym, tspec_t *inout_t, type_t **const inout_tp) |
971 | { | | 972 | { |
972 | | | 973 | |
973 | check_bit_field_type(dsym, inout_tp, inout_t); | | 974 | check_bit_field_type(dsym, inout_tp, inout_t); |
974 | | | 975 | |
975 | type_t *tp = *inout_tp; | | 976 | type_t *tp = *inout_tp; |
976 | tspec_t t = *inout_t; | | 977 | tspec_t t = *inout_t; |
977 | unsigned int t_width = size_in_bits(t); | | 978 | unsigned int t_width = size_in_bits(t); |
978 | if (tp->t_bit_field_width > t_width) { | | 979 | if (tp->t_bit_field_width > t_width) { |
979 | /* illegal bit-field size: %d */ | | 980 | /* illegal bit-field size: %d */ |
980 | error(36, (int)tp->t_bit_field_width); | | 981 | error(36, (int)tp->t_bit_field_width); |
981 | tp->t_bit_field_width = t_width; | | 982 | tp->t_bit_field_width = t_width; |
982 | } else if (tp->t_bit_field_width == 0 && dsym->s_name != unnamed) { | | 983 | } else if (tp->t_bit_field_width == 0 && dsym->s_name != unnamed) { |
983 | /* zero size bit-field */ | | 984 | /* zero size bit-field */ |
984 | error(37); | | 985 | error(37); |
985 | tp->t_bit_field_width = t_width; | | 986 | tp->t_bit_field_width = t_width; |
986 | } | | 987 | } |
987 | if (dsym->s_scl == UNION_MEMBER) { | | 988 | if (dsym->s_scl == UNION_MEMBER) { |
988 | /* bit-field in union is very unusual */ | | 989 | /* bit-field in union is very unusual */ |
989 | warning(41); | | 990 | warning(41); |
990 | dsym->s_type->t_bitfield = false; | | 991 | dsym->s_type->t_bitfield = false; |
991 | dsym->s_bitfield = false; | | 992 | dsym->s_bitfield = false; |
992 | } | | 993 | } |
993 | } | | 994 | } |
994 | | | 995 | |
995 | /* Aligns the next structure element as required. */ | | 996 | /* Aligns the next structure element as required. */ |
996 | static void | | 997 | static void |
997 | dcs_align(unsigned int member_alignment, unsigned int bit_field_width) | | 998 | dcs_align(unsigned int member_alignment, unsigned int bit_field_width) |
998 | { | | 999 | { |
999 | | | 1000 | |
1000 | if (member_alignment > dcs->d_sou_align_in_bits) | | 1001 | if (member_alignment > dcs->d_sou_align_in_bits) |
1001 | dcs->d_sou_align_in_bits = member_alignment; | | 1002 | dcs->d_sou_align_in_bits = member_alignment; |
1002 | | | 1003 | |
1003 | unsigned int offset = (dcs->d_sou_size_in_bits + member_alignment - 1) | | 1004 | unsigned int offset = (dcs->d_sou_size_in_bits + member_alignment - 1) |
1004 | & ~(member_alignment - 1); | | 1005 | & ~(member_alignment - 1); |
1005 | if (bit_field_width == 0 | | 1006 | if (bit_field_width == 0 |
1006 | || dcs->d_sou_size_in_bits + bit_field_width > offset) | | 1007 | || dcs->d_sou_size_in_bits + bit_field_width > offset) |
1007 | dcs->d_sou_size_in_bits = offset; | | 1008 | dcs->d_sou_size_in_bits = offset; |
1008 | } | | 1009 | } |
1009 | | | 1010 | |
1010 | /* Add a member to the struct or union type that is being built in 'dcs'. */ | | 1011 | /* Add a member to the struct or union type that is being built in 'dcs'. */ |
1011 | static void | | 1012 | static void |
1012 | dcs_add_member(sym_t *mem) | | 1013 | dcs_add_member(sym_t *mem) |
1013 | { | | 1014 | { |
1014 | type_t *tp = mem->s_type; | | 1015 | type_t *tp = mem->s_type; |
1015 | | | 1016 | |
1016 | unsigned int union_size = 0; | | 1017 | unsigned int union_size = 0; |
1017 | if (dcs->d_kind == DLK_UNION) { | | 1018 | if (dcs->d_kind == DLK_UNION) { |
1018 | union_size = dcs->d_sou_size_in_bits; | | 1019 | union_size = dcs->d_sou_size_in_bits; |
1019 | dcs->d_sou_size_in_bits = 0; | | 1020 | dcs->d_sou_size_in_bits = 0; |
1020 | } | | 1021 | } |
1021 | | | 1022 | |
1022 | if (mem->s_bitfield) { | | 1023 | if (mem->s_bitfield) { |
1023 | dcs_align(alignment_in_bits(tp), tp->t_bit_field_width); | | 1024 | dcs_align(alignment_in_bits(tp), tp->t_bit_field_width); |
1024 | // XXX: Why round down? | | 1025 | // XXX: Why round down? |
1025 | mem->u.s_member.sm_offset_in_bits = dcs->d_sou_size_in_bits | | 1026 | mem->u.s_member.sm_offset_in_bits = dcs->d_sou_size_in_bits |
1026 | - dcs->d_sou_size_in_bits % size_in_bits(tp->t_tspec); | | 1027 | - dcs->d_sou_size_in_bits % size_in_bits(tp->t_tspec); |
1027 | tp->t_bit_field_offset = dcs->d_sou_size_in_bits | | 1028 | tp->t_bit_field_offset = dcs->d_sou_size_in_bits |
1028 | - mem->u.s_member.sm_offset_in_bits; | | 1029 | - mem->u.s_member.sm_offset_in_bits; |
1029 | dcs->d_sou_size_in_bits += tp->t_bit_field_width; | | 1030 | dcs->d_sou_size_in_bits += tp->t_bit_field_width; |
1030 | } else { | | 1031 | } else { |
1031 | dcs_align(alignment_in_bits(tp), 0); | | 1032 | dcs_align(alignment_in_bits(tp), 0); |
1032 | mem->u.s_member.sm_offset_in_bits = dcs->d_sou_size_in_bits; | | 1033 | mem->u.s_member.sm_offset_in_bits = dcs->d_sou_size_in_bits; |
1033 | dcs->d_sou_size_in_bits += type_size_in_bits(tp); | | 1034 | dcs->d_sou_size_in_bits += type_size_in_bits(tp); |
1034 | } | | 1035 | } |
1035 | | | 1036 | |
1036 | if (union_size > dcs->d_sou_size_in_bits) | | 1037 | if (union_size > dcs->d_sou_size_in_bits) |
1037 | dcs->d_sou_size_in_bits = union_size; | | 1038 | dcs->d_sou_size_in_bits = union_size; |
1038 | } | | 1039 | } |
1039 | | | 1040 | |
1040 | sym_t * | | 1041 | sym_t * |
1041 | declare_unnamed_member(void) | | 1042 | declare_unnamed_member(void) |
1042 | { | | 1043 | { |
1043 | | | 1044 | |
1044 | sym_t *mem = block_zero_alloc(sizeof(*mem), "sym"); | | 1045 | sym_t *mem = block_zero_alloc(sizeof(*mem), "sym"); |
1045 | mem->s_name = unnamed; | | 1046 | mem->s_name = unnamed; |
1046 | mem->s_kind = FMEMBER; | | 1047 | mem->s_kind = FMEMBER; |
1047 | mem->s_scl = dcs->d_kind == DLK_STRUCT ? STRUCT_MEMBER : UNION_MEMBER; | | 1048 | mem->s_scl = dcs->d_kind == DLK_STRUCT ? STRUCT_MEMBER : UNION_MEMBER; |
1048 | mem->s_block_level = -1; | | 1049 | mem->s_block_level = -1; |
1049 | mem->s_type = dcs->d_type; | | 1050 | mem->s_type = dcs->d_type; |
1050 | mem->u.s_member.sm_containing_type = dcs->d_tag_type->t_sou; | | 1051 | mem->u.s_member.sm_containing_type = dcs->d_tag_type->t_sou; |
1051 | | | 1052 | |
1052 | dcs_add_member(mem); | | 1053 | dcs_add_member(mem); |
1053 | suppress_bitfieldtype = false; | | 1054 | suppress_bitfieldtype = false; |
1054 | return mem; | | 1055 | return mem; |
1055 | } | | 1056 | } |
1056 | | | 1057 | |
1057 | sym_t * | | 1058 | sym_t * |
1058 | declare_member(sym_t *dsym) | | 1059 | declare_member(sym_t *dsym) |
1059 | { | | 1060 | { |
1060 | | | 1061 | |
1061 | lint_assert(is_member(dsym)); | | 1062 | lint_assert(is_member(dsym)); |
1062 | | | 1063 | |
1063 | if (dcs->d_redeclared_symbol != NULL) { | | 1064 | if (dcs->d_redeclared_symbol != NULL) { |
1064 | lint_assert(is_member(dcs->d_redeclared_symbol)); | | 1065 | lint_assert(is_member(dcs->d_redeclared_symbol)); |
1065 | | | 1066 | |
1066 | if (dsym->u.s_member.sm_containing_type == | | 1067 | if (dsym->u.s_member.sm_containing_type == |
1067 | dcs->d_redeclared_symbol->u.s_member.sm_containing_type) { | | 1068 | dcs->d_redeclared_symbol->u.s_member.sm_containing_type) { |
1068 | /* duplicate member name '%s' */ | | 1069 | /* duplicate member name '%s' */ |
1069 | error(33, dsym->s_name); | | 1070 | error(33, dsym->s_name); |
1070 | rmsym(dcs->d_redeclared_symbol); | | 1071 | rmsym(dcs->d_redeclared_symbol); |
1071 | } | | 1072 | } |
1072 | } | | 1073 | } |
1073 | | | 1074 | |
1074 | check_type(dsym); | | 1075 | check_type(dsym); |
1075 | | | 1076 | |
1076 | type_t *tp = dsym->s_type; | | 1077 | type_t *tp = dsym->s_type; |
1077 | tspec_t t = tp->t_tspec; | | 1078 | tspec_t t = tp->t_tspec; |
1078 | if (dsym->s_bitfield) | | 1079 | if (dsym->s_bitfield) |
1079 | check_bit_field(dsym, &t, &tp); | | 1080 | check_bit_field(dsym, &t, &tp); |
1080 | else if (t == FUNC) { | | 1081 | else if (t == FUNC) { |
1081 | /* function illegal in structure or union */ | | 1082 | /* function illegal in structure or union */ |
1082 | error(38); | | 1083 | error(38); |
1083 | dsym->s_type = tp = block_derive_type(tp, t = PTR); | | 1084 | dsym->s_type = tp = block_derive_type(tp, t = PTR); |
1084 | } | | 1085 | } |
1085 | | | 1086 | |
1086 | /* | | 1087 | /* |
1087 | * bit-fields of length 0 are not warned about because length_in_bits | | 1088 | * bit-fields of length 0 are not warned about because length_in_bits |
1088 | * does not return the length of the bit-field but the length | | 1089 | * does not return the length of the bit-field but the length |
1089 | * of the type the bit-field is packed in (it's ok) | | 1090 | * of the type the bit-field is packed in (it's ok) |
1090 | */ | | 1091 | */ |
1091 | int sz = length_in_bits(dsym->s_type, dsym->s_name); | | 1092 | int sz = length_in_bits(dsym->s_type, dsym->s_name); |
1092 | if (sz == 0 && t == ARRAY && dsym->s_type->t_dim == 0) { | | 1093 | if (sz == 0 && t == ARRAY && dsym->s_type->t_dim == 0) { |
1093 | /* zero-sized array '%s' in struct is a C99 extension */ | | 1094 | /* zero-sized array '%s' in struct is a C99 extension */ |
1094 | c99ism(39, dsym->s_name); | | 1095 | c99ism(39, dsym->s_name); |
1095 | } | | 1096 | } |
1096 | | | 1097 | |
1097 | dcs_add_member(dsym); | | 1098 | dcs_add_member(dsym); |
1098 | | | 1099 | |
1099 | check_function_definition(dsym, false); | | 1100 | check_function_definition(dsym, false); |
1100 | | | 1101 | |
1101 | suppress_bitfieldtype = false; | | 1102 | suppress_bitfieldtype = false; |
1102 | | | 1103 | |
1103 | return dsym; | | 1104 | return dsym; |
1104 | } | | 1105 | } |
1105 | | | 1106 | |
1106 | sym_t * | | 1107 | sym_t * |
1107 | set_bit_field_width(sym_t *dsym, int bit_field_width) | | 1108 | set_bit_field_width(sym_t *dsym, int bit_field_width) |
1108 | { | | 1109 | { |
1109 | | | 1110 | |
1110 | if (dsym == NULL) { | | 1111 | if (dsym == NULL) { |
1111 | dsym = block_zero_alloc(sizeof(*dsym), "sym"); | | 1112 | dsym = block_zero_alloc(sizeof(*dsym), "sym"); |
1112 | dsym->s_name = unnamed; | | 1113 | dsym->s_name = unnamed; |
1113 | dsym->s_kind = FMEMBER; | | 1114 | dsym->s_kind = FMEMBER; |
1114 | dsym->s_scl = STRUCT_MEMBER; | | 1115 | dsym->s_scl = STRUCT_MEMBER; |
1115 | dsym->s_type = gettyp(UINT); | | 1116 | dsym->s_type = gettyp(UINT); |
1116 | dsym->s_block_level = -1; | | 1117 | dsym->s_block_level = -1; |
1117 | } | | 1118 | } |
1118 | dsym->s_type = block_dup_type(dsym->s_type); | | 1119 | dsym->s_type = block_dup_type(dsym->s_type); |
1119 | dsym->s_type->t_bitfield = true; | | 1120 | dsym->s_type->t_bitfield = true; |
1120 | dsym->s_type->t_bit_field_width = bit_field_width; | | 1121 | dsym->s_type->t_bit_field_width = bit_field_width; |
1121 | dsym->s_bitfield = true; | | 1122 | dsym->s_bitfield = true; |
1122 | return dsym; | | 1123 | return dsym; |
1123 | } | | 1124 | } |
1124 | | | 1125 | |
1125 | void | | 1126 | void |
1126 | add_type_qualifiers(type_qualifiers *dst, type_qualifiers src) | | 1127 | add_type_qualifiers(type_qualifiers *dst, type_qualifiers src) |
1127 | { | | 1128 | { |
1128 | | | 1129 | |
1129 | if (src.tq_const && dst->tq_const) | | 1130 | if (src.tq_const && dst->tq_const) |
1130 | /* duplicate '%s' */ | | 1131 | /* duplicate '%s' */ |
1131 | warning(10, "const"); | | 1132 | warning(10, "const"); |
1132 | if (src.tq_volatile && dst->tq_volatile) | | 1133 | if (src.tq_volatile && dst->tq_volatile) |
1133 | /* duplicate '%s' */ | | 1134 | /* duplicate '%s' */ |
1134 | warning(10, "volatile"); | | 1135 | warning(10, "volatile"); |
1135 | | | 1136 | |
1136 | dst->tq_const = dst->tq_const | src.tq_const; | | 1137 | dst->tq_const = dst->tq_const | src.tq_const; |
1137 | dst->tq_restrict = dst->tq_restrict | src.tq_restrict; | | 1138 | dst->tq_restrict = dst->tq_restrict | src.tq_restrict; |
1138 | dst->tq_volatile = dst->tq_volatile | src.tq_volatile; | | 1139 | dst->tq_volatile = dst->tq_volatile | src.tq_volatile; |
1139 | dst->tq_atomic = dst->tq_atomic | src.tq_atomic; | | 1140 | dst->tq_atomic = dst->tq_atomic | src.tq_atomic; |
1140 | } | | 1141 | } |
1141 | | | 1142 | |
1142 | qual_ptr * | | 1143 | qual_ptr * |
1143 | append_qualified_pointer(qual_ptr *p1, qual_ptr *p2) | | 1144 | append_qualified_pointer(qual_ptr *p1, qual_ptr *p2) |
1144 | { | | 1145 | { |
1145 | | | 1146 | |
1146 | qual_ptr *tail = p2; | | 1147 | qual_ptr *tail = p2; |
1147 | while (tail->p_next != NULL) | | 1148 | while (tail->p_next != NULL) |
1148 | tail = tail->p_next; | | 1149 | tail = tail->p_next; |
1149 | tail->p_next = p1; | | 1150 | tail->p_next = p1; |
1150 | return p2; | | 1151 | return p2; |
1151 | } | | 1152 | } |
1152 | | | 1153 | |
1153 | static type_t * | | 1154 | static type_t * |
1154 | block_derive_pointer(type_t *stp, bool is_const, bool is_volatile) | | 1155 | block_derive_pointer(type_t *stp, bool is_const, bool is_volatile) |
1155 | { | | 1156 | { |
1156 | | | 1157 | |
1157 | type_t *tp = block_derive_type(stp, PTR); | | 1158 | type_t *tp = block_derive_type(stp, PTR); |
1158 | tp->t_const = is_const; | | 1159 | tp->t_const = is_const; |
1159 | tp->t_volatile = is_volatile; | | 1160 | tp->t_volatile = is_volatile; |
1160 | return tp; | | 1161 | return tp; |
1161 | } | | 1162 | } |
1162 | | | 1163 | |
1163 | /* | | 1164 | /* |
1164 | * The following 3 functions extend the type of a declarator with | | 1165 | * The following 3 functions extend the type of a declarator with |
1165 | * pointer, function and array types. | | 1166 | * pointer, function and array types. |
1166 | * | | 1167 | * |
1167 | * The current type is the type built by dcs_end_type (dcs->d_type) and | | 1168 | * The current type is the type built by dcs_end_type (dcs->d_type) and |
1168 | * pointer, function and array types already added for this | | 1169 | * pointer, function and array types already added for this |
1169 | * declarator. The new type extension is inserted between both. | | 1170 | * declarator. The new type extension is inserted between both. |
1170 | */ | | 1171 | */ |
1171 | sym_t * | | 1172 | sym_t * |
1172 | add_pointer(sym_t *decl, qual_ptr *p) | | 1173 | add_pointer(sym_t *decl, qual_ptr *p) |
1173 | { | | 1174 | { |
1174 | | | 1175 | |
1175 | debug_dcs(false); | | 1176 | debug_dcs(false); |
1176 | | | 1177 | |
1177 | type_t **tpp = &decl->s_type; | | 1178 | type_t **tpp = &decl->s_type; |
1178 | while (*tpp != NULL && *tpp != dcs->d_type) | | 1179 | while (*tpp != NULL && *tpp != dcs->d_type) |
1179 | tpp = &(*tpp)->t_subt; | | 1180 | tpp = &(*tpp)->t_subt; |
1180 | if (*tpp == NULL) { | | 1181 | if (*tpp == NULL) { |
1181 | debug_step("add_pointer: unchanged '%s'", | | 1182 | debug_step("add_pointer: unchanged '%s'", |
1182 | type_name(decl->s_type)); | | 1183 | type_name(decl->s_type)); |
1183 | return decl; | | 1184 | return decl; |
1184 | } | | 1185 | } |
1185 | | | 1186 | |
1186 | while (p != NULL) { | | 1187 | while (p != NULL) { |
1187 | *tpp = block_derive_pointer(dcs->d_type, | | 1188 | *tpp = block_derive_pointer(dcs->d_type, |
1188 | p->qualifiers.tq_const, p->qualifiers.tq_volatile); | | 1189 | p->qualifiers.tq_const, p->qualifiers.tq_volatile); |
1189 | | | 1190 | |
1190 | tpp = &(*tpp)->t_subt; | | 1191 | tpp = &(*tpp)->t_subt; |
1191 | | | 1192 | |
1192 | qual_ptr *next = p->p_next; | | 1193 | qual_ptr *next = p->p_next; |
1193 | free(p); | | 1194 | free(p); |
1194 | p = next; | | 1195 | p = next; |
1195 | } | | 1196 | } |
1196 | debug_step("add_pointer: '%s'", type_name(decl->s_type)); | | 1197 | debug_step("add_pointer: '%s'", type_name(decl->s_type)); |
1197 | return decl; | | 1198 | return decl; |
1198 | } | | 1199 | } |
1199 | | | 1200 | |
1200 | static type_t * | | 1201 | static type_t * |
1201 | block_derive_array(type_t *stp, bool dim, int len) | | 1202 | block_derive_array(type_t *stp, bool dim, int len) |
1202 | { | | 1203 | { |
1203 | | | 1204 | |
1204 | type_t *tp = block_derive_type(stp, ARRAY); | | 1205 | type_t *tp = block_derive_type(stp, ARRAY); |
1205 | tp->t_dim = len; | | 1206 | tp->t_dim = len; |
1206 | | | 1207 | |
1207 | #if 0 | | 1208 | #if 0 |
1208 | /* | | 1209 | /* |
1209 | * As of 2022-04-03, the implementation of the type parser (see | | 1210 | * As of 2022-04-03, the implementation of the type parser (see |
1210 | * add_function, add_array, add_pointer) is strange. When it sees | | 1211 | * add_function, add_array, add_pointer) is strange. When it sees |
1211 | * the type 'void *b[4]', it first creates 'void b[4]' and only later | | 1212 | * the type 'void *b[4]', it first creates 'void b[4]' and only later |
1212 | * inserts the '*' in the middle of the type. Late modifications like | | 1213 | * inserts the '*' in the middle of the type. Late modifications like |
1213 | * these should not be done at all, instead the parser should be fixed | | 1214 | * these should not be done at all, instead the parser should be fixed |
1214 | * to process the type names in the proper syntactical order. | | 1215 | * to process the type names in the proper syntactical order. |
1215 | * | | 1216 | * |
1216 | * Since the intermediate type would be an array of void, but the | | 1217 | * Since the intermediate type would be an array of void, but the |
1217 | * final type is valid, this check cannot be enabled yet. | | 1218 | * final type is valid, this check cannot be enabled yet. |
1218 | */ | | 1219 | */ |
1219 | if (stp->t_tspec == VOID) { | | 1220 | if (stp->t_tspec == VOID) { |
1220 | /* array of incomplete type */ | | 1221 | /* array of incomplete type */ |
1221 | error(301); | | 1222 | error(301); |
1222 | tp->t_subt = gettyp(CHAR); | | 1223 | tp->t_subt = gettyp(CHAR); |
1223 | } | | 1224 | } |
1224 | #endif | | 1225 | #endif |
1225 | if (len < 0) { | | 1226 | if (len < 0) { |
1226 | /* negative array dimension (%d) */ | | 1227 | /* negative array dimension (%d) */ |
1227 | error(20, len); | | 1228 | error(20, len); |
1228 | } else if (len == 0 && dim) { | | 1229 | } else if (len == 0 && dim) { |
1229 | /* zero sized array is a C99 extension */ | | 1230 | /* zero sized array is a C99 extension */ |
1230 | c99ism(322); | | 1231 | c99ism(322); |
1231 | } else if (len == 0 && !dim) | | 1232 | } else if (len == 0 && !dim) |
1232 | tp->t_incomplete_array = true; | | 1233 | tp->t_incomplete_array = true; |
1233 | | | 1234 | |
1234 | return tp; | | 1235 | return tp; |
1235 | } | | 1236 | } |
1236 | | | 1237 | |
1237 | /* | | 1238 | /* |
1238 | * If a dimension was specified, dim is true, otherwise false | | 1239 | * If a dimension was specified, dim is true, otherwise false |
1239 | * n is the specified dimension | | 1240 | * n is the specified dimension |
1240 | */ | | 1241 | */ |
1241 | sym_t * | | 1242 | sym_t * |
1242 | add_array(sym_t *decl, bool dim, int n) | | 1243 | add_array(sym_t *decl, bool dim, int n) |
1243 | { | | 1244 | { |
1244 | | | 1245 | |
1245 | debug_dcs(false); | | 1246 | debug_dcs(false); |
1246 | | | 1247 | |
1247 | type_t **tpp = &decl->s_type; | | 1248 | type_t **tpp = &decl->s_type; |
1248 | while (*tpp != NULL && *tpp != dcs->d_type) | | 1249 | while (*tpp != NULL && *tpp != dcs->d_type) |
1249 | tpp = &(*tpp)->t_subt; | | 1250 | tpp = &(*tpp)->t_subt; |
1250 | if (*tpp == NULL) { | | 1251 | if (*tpp == NULL) { |
1251 | debug_step("add_array: unchanged '%s'", | | 1252 | debug_step("add_array: unchanged '%s'", |
1252 | type_name(decl->s_type)); | | 1253 | type_name(decl->s_type)); |
1253 | return decl; | | 1254 | return decl; |
1254 | } | | 1255 | } |
1255 | | | 1256 | |
1256 | *tpp = block_derive_array(dcs->d_type, dim, n); | | 1257 | *tpp = block_derive_array(dcs->d_type, dim, n); |
1257 | | | 1258 | |
1258 | debug_step("add_array: '%s'", type_name(decl->s_type)); | | 1259 | debug_step("add_array: '%s'", type_name(decl->s_type)); |
1259 | return decl; | | 1260 | return decl; |
1260 | } | | 1261 | } |
1261 | | | 1262 | |
1262 | static type_t * | | 1263 | static type_t * |
1263 | block_derive_function(type_t *ret, bool proto, sym_t *args, bool vararg) | | 1264 | block_derive_function(type_t *ret, bool proto, sym_t *args, bool vararg) |
1264 | { | | 1265 | { |
1265 | | | 1266 | |
1266 | type_t *tp = block_derive_type(ret, FUNC); | | 1267 | type_t *tp = block_derive_type(ret, FUNC); |
1267 | tp->t_proto = proto; | | 1268 | tp->t_proto = proto; |
1268 | if (proto) | | 1269 | if (proto) |
1269 | tp->t_args = args; | | 1270 | tp->t_args = args; |
1270 | tp->t_vararg = vararg; | | 1271 | tp->t_vararg = vararg; |
1271 | return tp; | | 1272 | return tp; |
1272 | } | | 1273 | } |
1273 | | | 1274 | |
1274 | static void | | 1275 | static void |
1275 | check_prototype_parameters(sym_t *args) | | 1276 | check_prototype_parameters(sym_t *args) |
1276 | { | | 1277 | { |
1277 | | | 1278 | |
1278 | for (sym_t *sym = dcs->d_first_dlsym; | | 1279 | for (sym_t *sym = dcs->d_first_dlsym; |
1279 | sym != NULL; sym = sym->s_level_next) { | | 1280 | sym != NULL; sym = sym->s_level_next) { |
1280 | scl_t sc = sym->s_scl; | | 1281 | scl_t sc = sym->s_scl; |
1281 | if (sc == STRUCT_TAG || sc == UNION_TAG || sc == ENUM_TAG) { | | 1282 | if (sc == STRUCT_TAG || sc == UNION_TAG || sc == ENUM_TAG) { |
1282 | /* dubious tag declaration '%s %s' */ | | 1283 | /* dubious tag declaration '%s %s' */ |
1283 | warning(85, storage_class_name(sc), sym->s_name); | | 1284 | warning(85, storage_class_name(sc), sym->s_name); |
1284 | } | | 1285 | } |
1285 | } | | 1286 | } |