| @@ -1,1831 +1,1833 @@ | | | @@ -1,1831 +1,1833 @@ |
1 | /* $NetBSD: decl.c,v 1.200 2021/07/15 07:58:05 rin Exp $ */ | | 1 | /* $NetBSD: decl.c,v 1.201 2021/07/15 21:56:51 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) && !defined(lint) | | 40 | #if defined(__RCSID) && !defined(lint) |
41 | __RCSID("$NetBSD: decl.c,v 1.200 2021/07/15 07:58:05 rin Exp $"); | | 41 | __RCSID("$NetBSD: decl.c,v 1.201 2021/07/15 21:56:51 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; | | 54 | static type_t *typetab; |
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 | * pointer to top element of a stack which contains information local | | 60 | * pointer to top element of a stack which contains information local |
61 | * to nested declarations | | 61 | * to nested declarations |
62 | */ | | 62 | */ |
63 | dinfo_t *dcs; | | 63 | dinfo_t *dcs; |
64 | | | 64 | |
65 | static type_t *tdeferr(type_t *, tspec_t); | | 65 | static type_t *tdeferr(type_t *, tspec_t); |
66 | static void settdsym(type_t *, sym_t *); | | 66 | static void settdsym(type_t *, sym_t *); |
67 | static tspec_t merge_type_specifiers(tspec_t, tspec_t); | | 67 | static tspec_t merge_type_specifiers(tspec_t, tspec_t); |
68 | static void align(int, int); | | 68 | static void align(int, int); |
69 | static sym_t *newtag(sym_t *, scl_t, bool, bool); | | 69 | static sym_t *newtag(sym_t *, scl_t, bool, bool); |
70 | static bool eqargs(const type_t *, const type_t *, bool *); | | 70 | static bool eqargs(const type_t *, const type_t *, bool *); |
71 | static bool mnoarg(const type_t *, bool *); | | 71 | static bool mnoarg(const type_t *, bool *); |
72 | static bool check_old_style_definition(sym_t *, sym_t *); | | 72 | static bool check_old_style_definition(sym_t *, sym_t *); |
73 | static bool check_prototype_declaration(sym_t *, sym_t *); | | 73 | static bool check_prototype_declaration(sym_t *, sym_t *); |
74 | static sym_t *new_style_function(sym_t *, sym_t *); | | 74 | static sym_t *new_style_function(sym_t *, sym_t *); |
75 | static void old_style_function(sym_t *, sym_t *); | | 75 | static void old_style_function(sym_t *, sym_t *); |
76 | static void declare_external_in_block(sym_t *); | | 76 | static void declare_external_in_block(sym_t *); |
77 | static bool check_init(sym_t *); | | 77 | static bool check_init(sym_t *); |
78 | static void check_argument_usage(bool, sym_t *); | | 78 | static void check_argument_usage(bool, sym_t *); |
79 | static void check_variable_usage(bool, sym_t *); | | 79 | static void check_variable_usage(bool, sym_t *); |
80 | static void check_label_usage(sym_t *); | | 80 | static void check_label_usage(sym_t *); |
81 | static void check_tag_usage(sym_t *); | | 81 | static void check_tag_usage(sym_t *); |
82 | static void check_global_variable(const sym_t *); | | 82 | static void check_global_variable(const sym_t *); |
83 | static void check_global_variable_size(const sym_t *); | | 83 | static void check_global_variable_size(const sym_t *); |
84 | | | 84 | |
85 | /* | | 85 | /* |
86 | * initializes all global vars used in declarations | | 86 | * initializes all global vars used in declarations |
87 | */ | | 87 | */ |
88 | void | | 88 | void |
89 | #ifdef __sh3__ | | 89 | #ifdef __sh3__ |
90 | /* XXX port-sh3/56311 */ | | 90 | /* XXX port-sh3/56311 */ |
91 | __attribute__((optimize("O0"))) | | 91 | __attribute__((optimize("O0"))) |
92 | #endif | | 92 | #endif |
93 | initdecl(void) | | 93 | initdecl(void) |
94 | { | | 94 | { |
95 | int i; | | 95 | int i; |
96 | | | 96 | |
97 | /* declaration stack */ | | 97 | /* declaration stack */ |
98 | dcs = xcalloc(1, sizeof(*dcs)); | | 98 | dcs = xcalloc(1, sizeof(*dcs)); |
99 | dcs->d_ctx = EXTERN; | | 99 | dcs->d_ctx = EXTERN; |
100 | dcs->d_ldlsym = &dcs->d_dlsyms; | | 100 | dcs->d_ldlsym = &dcs->d_dlsyms; |
101 | | | 101 | |
102 | /* type information and classification */ | | 102 | /* type information and classification */ |
103 | inittyp(); | | 103 | inittyp(); |
104 | | | 104 | |
105 | /* shared type structures */ | | 105 | /* shared type structures */ |
106 | typetab = xcalloc(NTSPEC, sizeof(*typetab)); | | 106 | typetab = xcalloc(NTSPEC, sizeof(*typetab)); |
107 | for (i = 0; i < NTSPEC; i++) | | 107 | for (i = 0; i < NTSPEC; i++) |
108 | typetab[i].t_tspec = NOTSPEC; | | 108 | typetab[i].t_tspec = NOTSPEC; |
109 | typetab[BOOL].t_tspec = BOOL; | | 109 | typetab[BOOL].t_tspec = BOOL; |
110 | typetab[CHAR].t_tspec = CHAR; | | 110 | typetab[CHAR].t_tspec = CHAR; |
111 | typetab[SCHAR].t_tspec = SCHAR; | | 111 | typetab[SCHAR].t_tspec = SCHAR; |
112 | typetab[UCHAR].t_tspec = UCHAR; | | 112 | typetab[UCHAR].t_tspec = UCHAR; |
113 | typetab[SHORT].t_tspec = SHORT; | | 113 | typetab[SHORT].t_tspec = SHORT; |
114 | typetab[USHORT].t_tspec = USHORT; | | 114 | typetab[USHORT].t_tspec = USHORT; |
115 | typetab[INT].t_tspec = INT; | | 115 | typetab[INT].t_tspec = INT; |
116 | typetab[UINT].t_tspec = UINT; | | 116 | typetab[UINT].t_tspec = UINT; |
117 | typetab[LONG].t_tspec = LONG; | | 117 | typetab[LONG].t_tspec = LONG; |
118 | typetab[ULONG].t_tspec = ULONG; | | 118 | typetab[ULONG].t_tspec = ULONG; |
119 | typetab[QUAD].t_tspec = QUAD; | | 119 | typetab[QUAD].t_tspec = QUAD; |
120 | typetab[UQUAD].t_tspec = UQUAD; | | 120 | typetab[UQUAD].t_tspec = UQUAD; |
121 | typetab[FLOAT].t_tspec = FLOAT; | | 121 | typetab[FLOAT].t_tspec = FLOAT; |
122 | typetab[DOUBLE].t_tspec = DOUBLE; | | 122 | typetab[DOUBLE].t_tspec = DOUBLE; |
123 | typetab[LDOUBLE].t_tspec = LDOUBLE; | | 123 | typetab[LDOUBLE].t_tspec = LDOUBLE; |
124 | typetab[FCOMPLEX].t_tspec = FCOMPLEX; | | 124 | typetab[FCOMPLEX].t_tspec = FCOMPLEX; |
125 | typetab[DCOMPLEX].t_tspec = DCOMPLEX; | | 125 | typetab[DCOMPLEX].t_tspec = DCOMPLEX; |
126 | typetab[LCOMPLEX].t_tspec = LCOMPLEX; | | 126 | typetab[LCOMPLEX].t_tspec = LCOMPLEX; |
127 | typetab[COMPLEX].t_tspec = COMPLEX; | | 127 | typetab[COMPLEX].t_tspec = COMPLEX; |
128 | typetab[VOID].t_tspec = VOID; | | 128 | typetab[VOID].t_tspec = VOID; |
129 | /* | | 129 | /* |
130 | * Next two are not real types. They are only used by the parser | | 130 | * Next two are not real types. They are only used by the parser |
131 | * to return keywords "signed" and "unsigned" | | 131 | * to return keywords "signed" and "unsigned" |
132 | */ | | 132 | */ |
133 | typetab[SIGNED].t_tspec = SIGNED; | | 133 | typetab[SIGNED].t_tspec = SIGNED; |
134 | typetab[UNSIGN].t_tspec = UNSIGN; | | 134 | typetab[UNSIGN].t_tspec = UNSIGN; |
135 | } | | 135 | } |
136 | | | 136 | |
137 | /* | | 137 | /* |
138 | * Returns a shared type structure for arithmetic types and void. | | 138 | * Returns a shared type structure for arithmetic types and void. |
139 | * | | 139 | * |
140 | * It's important to duplicate this structure (using dup_type() or | | 140 | * It's important to duplicate this structure (using dup_type() or |
141 | * expr_dup_type()) if it is to be modified (adding qualifiers or anything | | 141 | * expr_dup_type()) if it is to be modified (adding qualifiers or anything |
142 | * else). | | 142 | * else). |
143 | */ | | 143 | */ |
144 | type_t * | | 144 | type_t * |
145 | gettyp(tspec_t t) | | 145 | gettyp(tspec_t t) |
146 | { | | 146 | { |
147 | | | 147 | |
148 | /* TODO: make the return type 'const' */ | | 148 | /* TODO: make the return type 'const' */ |
149 | return &typetab[t]; | | 149 | return &typetab[t]; |
150 | } | | 150 | } |
151 | | | 151 | |
152 | type_t * | | 152 | type_t * |
153 | dup_type(const type_t *tp) | | 153 | dup_type(const type_t *tp) |
154 | { | | 154 | { |
155 | type_t *ntp; | | 155 | type_t *ntp; |
156 | | | 156 | |
157 | ntp = getblk(sizeof(*ntp)); | | 157 | ntp = getblk(sizeof(*ntp)); |
158 | *ntp = *tp; | | 158 | *ntp = *tp; |
159 | return ntp; | | 159 | return ntp; |
160 | } | | 160 | } |
161 | | | 161 | |
162 | /* | | 162 | /* |
163 | * Use expr_dup_type() instead of dup_type() inside expressions (if the | | 163 | * Use expr_dup_type() instead of dup_type() inside expressions (if the |
164 | * allocated memory should be freed after the expr). | | 164 | * allocated memory should be freed after the expr). |
165 | */ | | 165 | */ |
166 | type_t * | | 166 | type_t * |
167 | expr_dup_type(const type_t *tp) | | 167 | expr_dup_type(const type_t *tp) |
168 | { | | 168 | { |
169 | type_t *ntp; | | 169 | type_t *ntp; |
170 | | | 170 | |
171 | ntp = expr_zalloc(sizeof(*ntp)); | | 171 | ntp = expr_zalloc(sizeof(*ntp)); |
172 | *ntp = *tp; | | 172 | *ntp = *tp; |
173 | return ntp; | | 173 | return ntp; |
174 | } | | 174 | } |
175 | | | 175 | |
176 | /* | | 176 | /* |
177 | * Returns whether the argument is void or an incomplete array, | | 177 | * Returns whether the argument is void or an incomplete array, |
178 | * struct, union or enum type. | | 178 | * struct, union or enum type. |
179 | */ | | 179 | */ |
180 | bool | | 180 | bool |
181 | is_incomplete(const type_t *tp) | | 181 | is_incomplete(const type_t *tp) |
182 | { | | 182 | { |
183 | tspec_t t; | | 183 | tspec_t t; |
184 | | | 184 | |
185 | if ((t = tp->t_tspec) == VOID) { | | 185 | if ((t = tp->t_tspec) == VOID) { |
186 | return true; | | 186 | return true; |
187 | } else if (t == ARRAY) { | | 187 | } else if (t == ARRAY) { |
188 | return tp->t_incomplete_array; | | 188 | return tp->t_incomplete_array; |
189 | } else if (t == STRUCT || t == UNION) { | | 189 | } else if (t == STRUCT || t == UNION) { |
190 | return tp->t_str->sou_incomplete; | | 190 | return tp->t_str->sou_incomplete; |
191 | } else if (t == ENUM) { | | 191 | } else if (t == ENUM) { |
192 | return tp->t_enum->en_incomplete; | | 192 | return tp->t_enum->en_incomplete; |
193 | } | | 193 | } |
194 | return false; | | 194 | return false; |
195 | } | | 195 | } |
196 | | | 196 | |
197 | /* | | 197 | /* |
198 | * Mark an array, struct, union or enum type as complete or incomplete. | | 198 | * Mark an array, struct, union or enum type as complete or incomplete. |
199 | */ | | 199 | */ |
200 | void | | 200 | void |
201 | setcomplete(type_t *tp, bool complete) | | 201 | setcomplete(type_t *tp, bool complete) |
202 | { | | 202 | { |
203 | tspec_t t; | | 203 | tspec_t t; |
204 | | | 204 | |
205 | lint_assert(tp != NULL); | | 205 | lint_assert(tp != NULL); |
206 | if ((t = tp->t_tspec) == ARRAY) { | | 206 | if ((t = tp->t_tspec) == ARRAY) { |
207 | tp->t_incomplete_array = !complete; | | 207 | tp->t_incomplete_array = !complete; |
208 | } else if (t == STRUCT || t == UNION) { | | 208 | } else if (t == STRUCT || t == UNION) { |
209 | tp->t_str->sou_incomplete = !complete; | | 209 | tp->t_str->sou_incomplete = !complete; |
210 | } else { | | 210 | } else { |
211 | lint_assert(t == ENUM); | | 211 | lint_assert(t == ENUM); |
212 | tp->t_enum->en_incomplete = !complete; | | 212 | tp->t_enum->en_incomplete = !complete; |
213 | } | | 213 | } |
214 | } | | 214 | } |
215 | | | 215 | |
216 | /* | | 216 | /* |
217 | * Remember the storage class of the current declaration in dcs->d_scl | | 217 | * Remember the storage class of the current declaration in dcs->d_scl |
218 | * (the top element of the declaration stack) and detect multiple | | 218 | * (the top element of the declaration stack) and detect multiple |
219 | * storage classes. | | 219 | * storage classes. |
220 | */ | | 220 | */ |
221 | void | | 221 | void |
222 | add_storage_class(scl_t sc) | | 222 | add_storage_class(scl_t sc) |
223 | { | | 223 | { |
224 | | | 224 | |
225 | if (sc == INLINE) { | | 225 | if (sc == INLINE) { |
226 | if (dcs->d_inline) | | 226 | if (dcs->d_inline) |
227 | /* duplicate '%s' */ | | 227 | /* duplicate '%s' */ |
228 | warning(10, "inline"); | | 228 | warning(10, "inline"); |
229 | dcs->d_inline = true; | | 229 | dcs->d_inline = true; |
230 | return; | | 230 | return; |
231 | } | | 231 | } |
232 | if (dcs->d_type != NULL || dcs->d_abstract_type != NOTSPEC || | | 232 | if (dcs->d_type != NULL || dcs->d_abstract_type != NOTSPEC || |
233 | dcs->d_sign_mod != NOTSPEC || dcs->d_rank_mod != NOTSPEC) { | | 233 | dcs->d_sign_mod != NOTSPEC || dcs->d_rank_mod != NOTSPEC) { |
234 | /* storage class after type is obsolescent */ | | 234 | /* storage class after type is obsolescent */ |
235 | warning(83); | | 235 | warning(83); |
236 | } | | 236 | } |
237 | if (dcs->d_scl == NOSCL) { | | 237 | if (dcs->d_scl == NOSCL) { |
238 | dcs->d_scl = sc; | | 238 | dcs->d_scl = sc; |
239 | } else { | | 239 | } else { |
240 | /* | | 240 | /* |
241 | * multiple storage classes. An error will be reported in | | 241 | * multiple storage classes. An error will be reported in |
242 | * end_type(). | | 242 | * end_type(). |
243 | */ | | 243 | */ |
244 | dcs->d_mscl = true; | | 244 | dcs->d_mscl = true; |
245 | } | | 245 | } |
246 | } | | 246 | } |
247 | | | 247 | |
248 | /* | | 248 | /* |
249 | * Remember the type, modifier or typedef name returned by the parser | | 249 | * Remember the type, modifier or typedef name returned by the parser |
250 | * in *dcs (top element of decl stack). This information is used in | | 250 | * in *dcs (top element of decl stack). This information is used in |
251 | * end_type() to build the type used for all declarators in this | | 251 | * end_type() to build the type used for all declarators in this |
252 | * declaration. | | 252 | * declaration. |
253 | * | | 253 | * |
254 | * If tp->t_typedef is 1, the type comes from a previously defined typename. | | 254 | * If tp->t_typedef is 1, the type comes from a previously defined typename. |
255 | * Otherwise it comes from a type specifier (int, long, ...) or a | | 255 | * Otherwise it comes from a type specifier (int, long, ...) or a |
256 | * struct/union/enum tag. | | 256 | * struct/union/enum tag. |
257 | */ | | 257 | */ |
258 | void | | 258 | void |
259 | add_type(type_t *tp) | | 259 | add_type(type_t *tp) |
260 | { | | 260 | { |
261 | tspec_t t; | | 261 | tspec_t t; |
262 | #ifdef DEBUG | | 262 | #ifdef DEBUG |
263 | printf("%s: %s\n", __func__, type_name(tp)); | | 263 | printf("%s: %s\n", __func__, type_name(tp)); |
264 | #endif | | 264 | #endif |
265 | if (tp->t_typedef) { | | 265 | if (tp->t_typedef) { |
266 | /* | | 266 | /* |
267 | * something like "typedef int a; int a b;" | | 267 | * something like "typedef int a; int a b;" |
268 | * This should not happen with current grammar. | | 268 | * This should not happen with current grammar. |
269 | */ | | 269 | */ |
270 | lint_assert(dcs->d_type == NULL); | | 270 | lint_assert(dcs->d_type == NULL); |
271 | lint_assert(dcs->d_abstract_type == NOTSPEC); | | 271 | lint_assert(dcs->d_abstract_type == NOTSPEC); |
272 | lint_assert(dcs->d_sign_mod == NOTSPEC); | | 272 | lint_assert(dcs->d_sign_mod == NOTSPEC); |
273 | lint_assert(dcs->d_rank_mod == NOTSPEC); | | 273 | lint_assert(dcs->d_rank_mod == NOTSPEC); |
274 | | | 274 | |
275 | dcs->d_type = tp; | | 275 | dcs->d_type = tp; |
276 | return; | | 276 | return; |
277 | } | | 277 | } |
278 | | | 278 | |
279 | t = tp->t_tspec; | | 279 | t = tp->t_tspec; |
280 | | | 280 | |
281 | if (t == STRUCT || t == UNION || t == ENUM) { | | 281 | if (t == STRUCT || t == UNION || t == ENUM) { |
282 | /* | | 282 | /* |
283 | * something like "int struct a ..." | | 283 | * something like "int struct a ..." |
284 | * struct/union/enum with anything else is not allowed | | 284 | * struct/union/enum with anything else is not allowed |
285 | */ | | 285 | */ |
286 | if (dcs->d_type != NULL || dcs->d_abstract_type != NOTSPEC || | | 286 | if (dcs->d_type != NULL || dcs->d_abstract_type != NOTSPEC || |
287 | dcs->d_rank_mod != NOTSPEC || dcs->d_sign_mod != NOTSPEC) { | | 287 | dcs->d_rank_mod != NOTSPEC || dcs->d_sign_mod != NOTSPEC) { |
288 | /* | | 288 | /* |
289 | * remember that an error must be reported in | | 289 | * remember that an error must be reported in |
290 | * end_type(). | | 290 | * end_type(). |
291 | */ | | 291 | */ |
292 | dcs->d_terr = true; | | 292 | dcs->d_terr = true; |
293 | dcs->d_abstract_type = NOTSPEC; | | 293 | dcs->d_abstract_type = NOTSPEC; |
294 | dcs->d_sign_mod = NOTSPEC; | | 294 | dcs->d_sign_mod = NOTSPEC; |
295 | dcs->d_rank_mod = NOTSPEC; | | 295 | dcs->d_rank_mod = NOTSPEC; |
296 | } | | 296 | } |
297 | dcs->d_type = tp; | | 297 | dcs->d_type = tp; |
298 | return; | | 298 | return; |
299 | } | | 299 | } |
300 | | | 300 | |
301 | if (dcs->d_type != NULL && !dcs->d_type->t_typedef) { | | 301 | if (dcs->d_type != NULL && !dcs->d_type->t_typedef) { |
302 | /* | | 302 | /* |
303 | * something like "struct a int" | | 303 | * something like "struct a int" |
304 | * struct/union/enum with anything else is not allowed | | 304 | * struct/union/enum with anything else is not allowed |
305 | */ | | 305 | */ |
306 | dcs->d_terr = true; | | 306 | dcs->d_terr = true; |
307 | return; | | 307 | return; |
308 | } | | 308 | } |
309 | | | 309 | |
310 | if (t == COMPLEX) { | | 310 | if (t == COMPLEX) { |
311 | if (dcs->d_complex_mod == FLOAT) | | 311 | if (dcs->d_complex_mod == FLOAT) |
312 | t = FCOMPLEX; | | 312 | t = FCOMPLEX; |
313 | else if (dcs->d_complex_mod == DOUBLE) | | 313 | else if (dcs->d_complex_mod == DOUBLE) |
314 | t = DCOMPLEX; | | 314 | t = DCOMPLEX; |
315 | else { | | 315 | else { |
316 | /* invalid type for _Complex */ | | 316 | /* invalid type for _Complex */ |
317 | error(308); | | 317 | error(308); |
318 | t = DCOMPLEX; /* just as a fallback */ | | 318 | t = DCOMPLEX; /* just as a fallback */ |
319 | } | | 319 | } |
320 | dcs->d_complex_mod = NOTSPEC; | | 320 | dcs->d_complex_mod = NOTSPEC; |
321 | } | | 321 | } |
322 | | | 322 | |
323 | if (t == LONG && dcs->d_rank_mod == LONG) { | | 323 | if (t == LONG && dcs->d_rank_mod == LONG) { |
324 | /* "long long" or "long ... long" */ | | 324 | /* "long long" or "long ... long" */ |
325 | t = QUAD; | | 325 | t = QUAD; |
326 | dcs->d_rank_mod = NOTSPEC; | | 326 | dcs->d_rank_mod = NOTSPEC; |
327 | if (!quadflg) | | 327 | if (!quadflg) |
328 | /* %s C does not support 'long long' */ | | 328 | /* %s C does not support 'long long' */ |
329 | c99ism(265, tflag ? "traditional" : "c89"); | | 329 | c99ism(265, tflag ? "traditional" : "c89"); |
330 | } | | 330 | } |
331 | | | 331 | |
332 | if (dcs->d_type != NULL && dcs->d_type->t_typedef) { | | 332 | if (dcs->d_type != NULL && dcs->d_type->t_typedef) { |
333 | /* something like "typedef int a; a long ..." */ | | 333 | /* something like "typedef int a; a long ..." */ |
334 | dcs->d_type = tdeferr(dcs->d_type, t); | | 334 | dcs->d_type = tdeferr(dcs->d_type, t); |
335 | return; | | 335 | return; |
336 | } | | 336 | } |
337 | | | 337 | |
338 | /* now it can be only a combination of arithmetic types and void */ | | 338 | /* now it can be only a combination of arithmetic types and void */ |
339 | if (t == SIGNED || t == UNSIGN) { | | 339 | if (t == SIGNED || t == UNSIGN) { |
340 | /* | | 340 | /* |
341 | * remember specifiers "signed" & "unsigned" in | | 341 | * remember specifiers "signed" & "unsigned" in |
342 | * dcs->d_sign_mod | | 342 | * dcs->d_sign_mod |
343 | */ | | 343 | */ |
344 | if (dcs->d_sign_mod != NOTSPEC) | | 344 | if (dcs->d_sign_mod != NOTSPEC) |
345 | /* | | 345 | /* |
346 | * more than one "signed" and/or "unsigned"; print | | 346 | * more than one "signed" and/or "unsigned"; print |
347 | * an error in end_type() | | 347 | * an error in end_type() |
348 | */ | | 348 | */ |
349 | dcs->d_terr = true; | | 349 | dcs->d_terr = true; |
350 | dcs->d_sign_mod = t; | | 350 | dcs->d_sign_mod = t; |
351 | } else if (t == SHORT || t == LONG || t == QUAD) { | | 351 | } else if (t == SHORT || t == LONG || t == QUAD) { |
352 | /* | | 352 | /* |
353 | * remember specifiers "short", "long" and "long long" in | | 353 | * remember specifiers "short", "long" and "long long" in |
354 | * dcs->d_rank_mod | | 354 | * dcs->d_rank_mod |
355 | */ | | 355 | */ |
356 | if (dcs->d_rank_mod != NOTSPEC) | | 356 | if (dcs->d_rank_mod != NOTSPEC) |
357 | /* more than one, print error in end_type() */ | | 357 | /* more than one, print error in end_type() */ |
358 | dcs->d_terr = true; | | 358 | dcs->d_terr = true; |
359 | dcs->d_rank_mod = t; | | 359 | dcs->d_rank_mod = t; |
360 | } else if (t == FLOAT || t == DOUBLE) { | | 360 | } else if (t == FLOAT || t == DOUBLE) { |
361 | if (dcs->d_rank_mod == NOTSPEC || dcs->d_rank_mod == LONG) { | | 361 | if (dcs->d_rank_mod == NOTSPEC || dcs->d_rank_mod == LONG) { |
362 | if (dcs->d_complex_mod != NOTSPEC | | 362 | if (dcs->d_complex_mod != NOTSPEC |
363 | || (t == FLOAT && dcs->d_rank_mod == LONG)) | | 363 | || (t == FLOAT && dcs->d_rank_mod == LONG)) |
364 | dcs->d_terr = true; | | 364 | dcs->d_terr = true; |
365 | dcs->d_complex_mod = t; | | 365 | dcs->d_complex_mod = t; |
366 | } else { | | 366 | } else { |
367 | if (dcs->d_abstract_type != NOTSPEC) | | 367 | if (dcs->d_abstract_type != NOTSPEC) |
368 | dcs->d_terr = true; | | 368 | dcs->d_terr = true; |
369 | dcs->d_abstract_type = t; | | 369 | dcs->d_abstract_type = t; |
370 | } | | 370 | } |
371 | } else if (t == PTR) { | | 371 | } else if (t == PTR) { |
372 | dcs->d_type = tp; | | 372 | dcs->d_type = tp; |
373 | } else { | | 373 | } else { |
374 | /* | | 374 | /* |
375 | * remember specifiers "void", "char", "int", | | 375 | * remember specifiers "void", "char", "int", |
376 | * or "_Complex" in dcs->d_abstract_type | | 376 | * or "_Complex" in dcs->d_abstract_type |
377 | */ | | 377 | */ |
378 | if (dcs->d_abstract_type != NOTSPEC) | | 378 | if (dcs->d_abstract_type != NOTSPEC) |
379 | /* more than one, print error in end_type() */ | | 379 | /* more than one, print error in end_type() */ |
380 | dcs->d_terr = true; | | 380 | dcs->d_terr = true; |
381 | dcs->d_abstract_type = t; | | 381 | dcs->d_abstract_type = t; |
382 | } | | 382 | } |
383 | } | | 383 | } |
384 | | | 384 | |
385 | /* | | 385 | /* |
386 | * called if a list of declaration specifiers contains a typedef name | | 386 | * called if a list of declaration specifiers contains a typedef name |
387 | * and other specifiers (except struct, union, enum, typedef name) | | 387 | * and other specifiers (except struct, union, enum, typedef name) |
388 | */ | | 388 | */ |
389 | static type_t * | | 389 | static type_t * |
390 | tdeferr(type_t *td, tspec_t t) | | 390 | tdeferr(type_t *td, tspec_t t) |
391 | { | | 391 | { |
392 | tspec_t t2; | | 392 | tspec_t t2; |
393 | | | 393 | |
394 | t2 = td->t_tspec; | | 394 | t2 = td->t_tspec; |
395 | | | 395 | |
396 | switch (t) { | | 396 | switch (t) { |
397 | case SIGNED: | | 397 | case SIGNED: |
398 | case UNSIGN: | | 398 | case UNSIGN: |
399 | if (t2 == CHAR || t2 == SHORT || t2 == INT || t2 == LONG || | | 399 | if (t2 == CHAR || t2 == SHORT || t2 == INT || t2 == LONG || |
400 | t2 == QUAD) { | | 400 | t2 == QUAD) { |
401 | if (!tflag) | | 401 | if (!tflag) |
402 | /* modifying typedef with '%s'; only ... */ | | 402 | /* modifying typedef with '%s'; only ... */ |
403 | warning(5, ttab[t].tt_name); | | 403 | warning(5, ttab[t].tt_name); |
404 | td = dup_type(gettyp(merge_type_specifiers(t2, t))); | | 404 | td = dup_type(gettyp(merge_type_specifiers(t2, t))); |
405 | td->t_typedef = true; | | 405 | td->t_typedef = true; |
406 | return td; | | 406 | return td; |
407 | } | | 407 | } |
408 | break; | | 408 | break; |
409 | case SHORT: | | 409 | case SHORT: |
410 | if (t2 == INT || t2 == UINT) { | | 410 | if (t2 == INT || t2 == UINT) { |
411 | /* modifying typedef with '%s'; only qualifiers ... */ | | 411 | /* modifying typedef with '%s'; only qualifiers ... */ |
412 | warning(5, "short"); | | 412 | warning(5, "short"); |
413 | td = dup_type(gettyp(t2 == INT ? SHORT : USHORT)); | | 413 | td = dup_type(gettyp(t2 == INT ? SHORT : USHORT)); |
414 | td->t_typedef = true; | | 414 | td->t_typedef = true; |
415 | return td; | | 415 | return td; |
416 | } | | 416 | } |
417 | break; | | 417 | break; |
418 | case LONG: | | 418 | case LONG: |
419 | if (t2 == INT || t2 == UINT || t2 == LONG || t2 == ULONG || | | 419 | if (t2 == INT || t2 == UINT || t2 == LONG || t2 == ULONG || |
420 | t2 == FLOAT || t2 == DOUBLE || t2 == DCOMPLEX) { | | 420 | t2 == FLOAT || t2 == DOUBLE || t2 == DCOMPLEX) { |
421 | /* modifying typedef with '%s'; only qualifiers ... */ | | 421 | /* modifying typedef with '%s'; only qualifiers ... */ |
422 | warning(5, "long"); | | 422 | warning(5, "long"); |
423 | if (t2 == INT) { | | 423 | if (t2 == INT) { |
424 | td = gettyp(LONG); | | 424 | td = gettyp(LONG); |
425 | } else if (t2 == UINT) { | | 425 | } else if (t2 == UINT) { |
426 | td = gettyp(ULONG); | | 426 | td = gettyp(ULONG); |
427 | } else if (t2 == LONG) { | | 427 | } else if (t2 == LONG) { |
428 | td = gettyp(QUAD); | | 428 | td = gettyp(QUAD); |
429 | } else if (t2 == ULONG) { | | 429 | } else if (t2 == ULONG) { |
430 | td = gettyp(UQUAD); | | 430 | td = gettyp(UQUAD); |
431 | } else if (t2 == FLOAT) { | | 431 | } else if (t2 == FLOAT) { |
432 | td = gettyp(DOUBLE); | | 432 | td = gettyp(DOUBLE); |
433 | } else if (t2 == DOUBLE) { | | 433 | } else if (t2 == DOUBLE) { |
434 | td = gettyp(LDOUBLE); | | 434 | td = gettyp(LDOUBLE); |
435 | } else if (t2 == DCOMPLEX) { | | 435 | } else if (t2 == DCOMPLEX) { |
436 | td = gettyp(LCOMPLEX); | | 436 | td = gettyp(LCOMPLEX); |
437 | } | | 437 | } |
438 | td = dup_type(td); | | 438 | td = dup_type(td); |
439 | td->t_typedef = true; | | 439 | td->t_typedef = true; |
440 | return td; | | 440 | return td; |
441 | } | | 441 | } |
442 | break; | | 442 | break; |
443 | /* LINTED206: (enumeration values not handled in switch) */ | | 443 | /* LINTED206: (enumeration values not handled in switch) */ |
444 | case NOTSPEC: | | 444 | case NOTSPEC: |
445 | case USHORT: | | 445 | case USHORT: |
446 | case UCHAR: | | 446 | case UCHAR: |
447 | case SCHAR: | | 447 | case SCHAR: |
448 | case CHAR: | | 448 | case CHAR: |
449 | case BOOL: | | 449 | case BOOL: |
450 | case FUNC: | | 450 | case FUNC: |
451 | case ARRAY: | | 451 | case ARRAY: |
452 | case PTR: | | 452 | case PTR: |
453 | case ENUM: | | 453 | case ENUM: |
454 | case UNION: | | 454 | case UNION: |
455 | case STRUCT: | | 455 | case STRUCT: |
456 | case VOID: | | 456 | case VOID: |
457 | case LDOUBLE: | | 457 | case LDOUBLE: |
458 | case FLOAT: | | 458 | case FLOAT: |
459 | case DOUBLE: | | 459 | case DOUBLE: |
460 | case UQUAD: | | 460 | case UQUAD: |
461 | case QUAD: | | 461 | case QUAD: |
462 | #ifdef INT128_SIZE | | 462 | #ifdef INT128_SIZE |
463 | case UINT128: | | 463 | case UINT128: |
464 | case INT128: | | 464 | case INT128: |
465 | #endif | | 465 | #endif |
466 | case ULONG: | | 466 | case ULONG: |
467 | case UINT: | | 467 | case UINT: |
468 | case INT: | | 468 | case INT: |
469 | case FCOMPLEX: | | 469 | case FCOMPLEX: |
470 | case DCOMPLEX: | | 470 | case DCOMPLEX: |
471 | case LCOMPLEX: | | 471 | case LCOMPLEX: |
472 | case COMPLEX: | | 472 | case COMPLEX: |
473 | break; | | 473 | break; |
474 | } | | 474 | } |
475 | | | 475 | |
476 | /* Anything other is not accepted. */ | | 476 | /* Anything other is not accepted. */ |
477 | | | 477 | |
478 | dcs->d_terr = true; | | 478 | dcs->d_terr = true; |
479 | return td; | | 479 | return td; |
480 | } | | 480 | } |
481 | | | 481 | |
482 | /* | | 482 | /* |
483 | * Remember the symbol of a typedef name (2nd arg) in a struct, union | | 483 | * Remember the symbol of a typedef name (2nd arg) in a struct, union |
484 | * or enum tag if the typedef name is the first defined for this tag. | | 484 | * or enum tag if the typedef name is the first defined for this tag. |
485 | * | | 485 | * |
486 | * If the tag is unnamed, the typdef name is used for identification | | 486 | * If the tag is unnamed, the typdef name is used for identification |
487 | * of this tag in lint2. Although it's possible that more than one typedef | | 487 | * of this tag in lint2. Although it's possible that more than one typedef |
488 | * name is defined for one tag, the first name defined should be unique | | 488 | * name is defined for one tag, the first name defined should be unique |
489 | * if the tag is unnamed. | | 489 | * if the tag is unnamed. |
490 | */ | | 490 | */ |
491 | static void | | 491 | static void |
492 | settdsym(type_t *tp, sym_t *sym) | | 492 | settdsym(type_t *tp, sym_t *sym) |
493 | { | | 493 | { |
494 | tspec_t t; | | 494 | tspec_t t; |
495 | | | 495 | |
496 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { | | 496 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { |
497 | if (tp->t_str->sou_first_typedef == NULL) | | 497 | if (tp->t_str->sou_first_typedef == NULL) |
498 | tp->t_str->sou_first_typedef = sym; | | 498 | tp->t_str->sou_first_typedef = sym; |
499 | } else if (t == ENUM) { | | 499 | } else if (t == ENUM) { |
500 | if (tp->t_enum->en_first_typedef == NULL) | | 500 | if (tp->t_enum->en_first_typedef == NULL) |
501 | tp->t_enum->en_first_typedef = sym; | | 501 | tp->t_enum->en_first_typedef = sym; |
502 | } | | 502 | } |
503 | } | | 503 | } |
504 | | | 504 | |
505 | static size_t | | 505 | static size_t |
506 | bitfieldsize(sym_t **mem) | | 506 | bitfieldsize(sym_t **mem) |
507 | { | | 507 | { |
508 | size_t len = (*mem)->s_type->t_flen; | | 508 | size_t len = (*mem)->s_type->t_flen; |
509 | while (*mem != NULL && (*mem)->s_type->t_bitfield) { | | 509 | while (*mem != NULL && (*mem)->s_type->t_bitfield) { |
510 | len += (*mem)->s_type->t_flen; | | 510 | len += (*mem)->s_type->t_flen; |
511 | *mem = (*mem)->s_next; | | 511 | *mem = (*mem)->s_next; |
512 | } | | 512 | } |
513 | return ((len + INT_SIZE - 1) / INT_SIZE) * INT_SIZE; | | 513 | return ((len + INT_SIZE - 1) / INT_SIZE) * INT_SIZE; |
514 | } | | 514 | } |
515 | | | 515 | |
516 | static void | | 516 | static void |
517 | setpackedsize(type_t *tp) | | 517 | setpackedsize(type_t *tp) |
518 | { | | 518 | { |
519 | struct_or_union *sp; | | 519 | struct_or_union *sp; |
520 | sym_t *mem; | | 520 | sym_t *mem; |
521 | | | 521 | |
522 | switch (tp->t_tspec) { | | 522 | switch (tp->t_tspec) { |
523 | case STRUCT: | | 523 | case STRUCT: |
524 | case UNION: | | 524 | case UNION: |
525 | sp = tp->t_str; | | 525 | sp = tp->t_str; |
526 | sp->sou_size_in_bits = 0; | | 526 | sp->sou_size_in_bits = 0; |
527 | for (mem = sp->sou_first_member; | | 527 | for (mem = sp->sou_first_member; |
528 | mem != NULL; mem = mem->s_next) { | | 528 | mem != NULL; mem = mem->s_next) { |
529 | if (mem->s_type->t_bitfield) { | | 529 | if (mem->s_type->t_bitfield) { |
530 | sp->sou_size_in_bits += bitfieldsize(&mem); | | 530 | sp->sou_size_in_bits += bitfieldsize(&mem); |
531 | if (mem == NULL) | | 531 | if (mem == NULL) |
532 | break; | | 532 | break; |
533 | } | | 533 | } |
534 | size_t x = (size_t)type_size_in_bits(mem->s_type); | | 534 | size_t x = (size_t)type_size_in_bits(mem->s_type); |
535 | if (tp->t_tspec == STRUCT) | | 535 | if (tp->t_tspec == STRUCT) |
536 | sp->sou_size_in_bits += x; | | 536 | sp->sou_size_in_bits += x; |
537 | else if (x > sp->sou_size_in_bits) | | 537 | else if (x > sp->sou_size_in_bits) |
538 | sp->sou_size_in_bits = x; | | 538 | sp->sou_size_in_bits = x; |
539 | } | | 539 | } |
540 | break; | | 540 | break; |
541 | default: | | 541 | default: |
542 | /* %s attribute ignored for %s */ | | 542 | /* %s attribute ignored for %s */ |
543 | warning(326, "packed", type_name(tp)); | | 543 | warning(326, "packed", type_name(tp)); |
544 | break; | | 544 | break; |
545 | } | | 545 | } |
546 | } | | 546 | } |
547 | | | 547 | |
548 | void | | 548 | void |
549 | addpacked(void) | | 549 | addpacked(void) |
550 | { | | 550 | { |
551 | if (dcs->d_type == NULL) | | 551 | if (dcs->d_type == NULL) |
552 | dcs->d_packed = true; | | 552 | dcs->d_packed = true; |
553 | else | | 553 | else |
554 | setpackedsize(dcs->d_type); | | 554 | setpackedsize(dcs->d_type); |
555 | } | | 555 | } |
556 | | | 556 | |
557 | void | | 557 | void |
558 | add_attr_used(void) | | 558 | add_attr_used(void) |
559 | { | | 559 | { |
560 | dcs->d_used = true; | | 560 | dcs->d_used = true; |
561 | } | | 561 | } |
562 | | | 562 | |
563 | /* | | 563 | /* |
564 | * Remember a qualifier which is part of the declaration specifiers | | 564 | * Remember a qualifier which is part of the declaration specifiers |
565 | * (and not the declarator) in the top element of the declaration stack. | | 565 | * (and not the declarator) in the top element of the declaration stack. |
566 | * Also detect multiple qualifiers of the same kind. | | 566 | * Also detect multiple qualifiers of the same kind. |
567 | | | 567 | |
568 | * The remembered qualifier is used by end_type() to construct the type | | 568 | * The remembered qualifier is used by end_type() to construct the type |
569 | * for all declarators. | | 569 | * for all declarators. |
570 | */ | | 570 | */ |
571 | void | | 571 | void |
572 | add_qualifier(tqual_t q) | | 572 | add_qualifier(tqual_t q) |
573 | { | | 573 | { |
574 | | | 574 | |
575 | if (q == CONST) { | | 575 | if (q == CONST) { |
576 | if (dcs->d_const) { | | 576 | if (dcs->d_const) { |
577 | /* duplicate '%s' */ | | 577 | /* duplicate '%s' */ |
578 | warning(10, "const"); | | 578 | warning(10, "const"); |
579 | } | | 579 | } |
580 | dcs->d_const = true; | | 580 | dcs->d_const = true; |
581 | } else if (q == VOLATILE) { | | 581 | } else if (q == VOLATILE) { |
582 | if (dcs->d_volatile) { | | 582 | if (dcs->d_volatile) { |
583 | /* duplicate '%s' */ | | 583 | /* duplicate '%s' */ |
584 | warning(10, "volatile"); | | 584 | warning(10, "volatile"); |
585 | } | | 585 | } |
586 | dcs->d_volatile = true; | | 586 | dcs->d_volatile = true; |
587 | } else { | | 587 | } else { |
588 | lint_assert(q == RESTRICT || q == THREAD); | | 588 | lint_assert(q == RESTRICT || q == THREAD); |
589 | /* Silently ignore these qualifiers. */ | | 589 | /* Silently ignore these qualifiers. */ |
590 | } | | 590 | } |
591 | } | | 591 | } |
592 | | | 592 | |
593 | /* | | 593 | /* |
594 | * Go to the next declaration level (structs, nested structs, blocks, | | 594 | * Go to the next declaration level (structs, nested structs, blocks, |
595 | * argument declaration lists ...) | | 595 | * argument declaration lists ...) |
596 | */ | | 596 | */ |
597 | void | | 597 | void |
598 | begin_declaration_level(scl_t sc) | | 598 | begin_declaration_level(scl_t sc) |
599 | { | | 599 | { |
600 | dinfo_t *di; | | 600 | dinfo_t *di; |
601 | | | 601 | |
602 | /* put a new element on the declaration stack */ | | 602 | /* put a new element on the declaration stack */ |
603 | di = xcalloc(1, sizeof(*di)); | | 603 | di = xcalloc(1, sizeof(*di)); |
604 | di->d_next = dcs; | | 604 | di->d_next = dcs; |
605 | dcs = di; | | 605 | dcs = di; |
606 | di->d_ctx = sc; | | 606 | di->d_ctx = sc; |
607 | di->d_ldlsym = &di->d_dlsyms; | | 607 | di->d_ldlsym = &di->d_dlsyms; |
608 | if (dflag) | | 608 | if (dflag) |
609 | (void)printf("%s(%p %s)\n", __func__, dcs, scl_name(sc)); | | 609 | (void)printf("%s(%p %s)\n", __func__, dcs, scl_name(sc)); |
610 | } | | 610 | } |
611 | | | 611 | |
612 | /* | | 612 | /* |
613 | * Go back to previous declaration level | | 613 | * Go back to previous declaration level |
614 | */ | | 614 | */ |
615 | void | | 615 | void |
616 | end_declaration_level(void) | | 616 | end_declaration_level(void) |
617 | { | | 617 | { |
618 | dinfo_t *di; | | 618 | dinfo_t *di; |
619 | | | 619 | |
620 | if (dflag) | | 620 | if (dflag) |
621 | (void)printf("%s(%p %s)\n", | | 621 | (void)printf("%s(%p %s)\n", |
622 | __func__, dcs, scl_name(dcs->d_ctx)); | | 622 | __func__, dcs, scl_name(dcs->d_ctx)); |
623 | | | 623 | |
624 | lint_assert(dcs->d_next != NULL); | | 624 | lint_assert(dcs->d_next != NULL); |
625 | di = dcs; | | 625 | di = dcs; |
626 | dcs = di->d_next; | | 626 | dcs = di->d_next; |
627 | switch (di->d_ctx) { | | 627 | switch (di->d_ctx) { |
628 | case MOS: | | 628 | case MOS: |
629 | case MOU: | | 629 | case MOU: |
630 | case CTCONST: | | 630 | case CTCONST: |
631 | /* | | 631 | /* |
632 | * Symbols declared in (nested) structs or enums are | | 632 | * Symbols declared in (nested) structs or enums are |
633 | * part of the next level (they are removed from the | | 633 | * part of the next level (they are removed from the |
634 | * symbol table if the symbols of the outer level are | | 634 | * symbol table if the symbols of the outer level are |
635 | * removed). | | 635 | * removed). |
636 | */ | | 636 | */ |
637 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) | | 637 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) |
638 | dcs->d_ldlsym = di->d_ldlsym; | | 638 | dcs->d_ldlsym = di->d_ldlsym; |
639 | break; | | 639 | break; |
640 | case ARG: | | 640 | case ARG: |
641 | /* | | 641 | /* |
642 | * All symbols in dcs->d_dlsyms are introduced in old style | | 642 | * All symbols in dcs->d_dlsyms are introduced in old style |
643 | * argument declarations (it's not clean, but possible). | | 643 | * argument declarations (it's not clean, but possible). |
644 | * They are appended to the list of symbols declared in | | 644 | * They are appended to the list of symbols declared in |
645 | * an old style argument identifier list or a new style | | 645 | * an old style argument identifier list or a new style |
646 | * parameter type list. | | 646 | * parameter type list. |
647 | */ | | 647 | */ |
648 | if (di->d_dlsyms != NULL) { | | 648 | if (di->d_dlsyms != NULL) { |
649 | *di->d_ldlsym = dcs->d_func_proto_syms; | | 649 | *di->d_ldlsym = dcs->d_func_proto_syms; |
650 | dcs->d_func_proto_syms = di->d_dlsyms; | | 650 | dcs->d_func_proto_syms = di->d_dlsyms; |
651 | } | | 651 | } |
652 | break; | | 652 | break; |
653 | case ABSTRACT: | | 653 | case ABSTRACT: |
654 | /* | | 654 | /* |
655 | * casts and sizeof | | 655 | * casts and sizeof |
656 | * Append all symbols declared in the abstract declaration | | 656 | * Append all symbols declared in the abstract declaration |
657 | * to the list of symbols declared in the surrounding | | 657 | * to the list of symbols declared in the surrounding |
658 | * declaration or block. | | 658 | * declaration or block. |
659 | * XXX I'm not sure whether they should be removed from the | | 659 | * XXX I'm not sure whether they should be removed from the |
660 | * symbol table now or later. | | 660 | * symbol table now or later. |
661 | */ | | 661 | */ |
662 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) | | 662 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) |
663 | dcs->d_ldlsym = di->d_ldlsym; | | 663 | dcs->d_ldlsym = di->d_ldlsym; |
664 | break; | | 664 | break; |
665 | case AUTO: | | 665 | case AUTO: |
666 | /* check usage of local vars */ | | 666 | /* check usage of local vars */ |
667 | check_usage(di); | | 667 | check_usage(di); |
668 | /* FALLTHROUGH */ | | 668 | /* FALLTHROUGH */ |
669 | case PROTO_ARG: | | 669 | case PROTO_ARG: |
670 | /* usage of arguments will be checked by funcend() */ | | 670 | /* usage of arguments will be checked by funcend() */ |
671 | rmsyms(di->d_dlsyms); | | 671 | rmsyms(di->d_dlsyms); |
672 | break; | | 672 | break; |
673 | case EXTERN: | | 673 | case EXTERN: |
674 | /* there is nothing after external declarations */ | | 674 | /* there is nothing after external declarations */ |
675 | /* FALLTHROUGH */ | | 675 | /* FALLTHROUGH */ |
676 | default: | | 676 | default: |
677 | lint_assert(/*CONSTCOND*/false); | | 677 | lint_assert(/*CONSTCOND*/false); |
678 | } | | 678 | } |
679 | free(di); | | 679 | free(di); |
680 | } | | 680 | } |
681 | | | 681 | |
682 | /* | | 682 | /* |
683 | * Set flag d_asm in all declaration stack elements up to the | | 683 | * Set flag d_asm in all declaration stack elements up to the |
684 | * outermost one. | | 684 | * outermost one. |
685 | * | | 685 | * |
686 | * This is used to mark compound statements which have, possibly in | | 686 | * This is used to mark compound statements which have, possibly in |
687 | * nested compound statements, asm statements. For these compound | | 687 | * nested compound statements, asm statements. For these compound |
688 | * statements no warnings about unused or uninitialized variables are | | 688 | * statements no warnings about unused or uninitialized variables are |
689 | * printed. | | 689 | * printed. |
690 | * | | 690 | * |
691 | * There is no need to clear d_asm in dinfo structs with context AUTO, | | 691 | * There is no need to clear d_asm in dinfo structs with context AUTO, |
692 | * because these structs are freed at the end of the compound statement. | | 692 | * because these structs are freed at the end of the compound statement. |
693 | * But it must be cleared in the outermost dinfo struct, which has | | 693 | * But it must be cleared in the outermost dinfo struct, which has |
694 | * context EXTERN. This could be done in begin_type() and would work for C90, | | 694 | * context EXTERN. This could be done in begin_type() and would work for C90, |
695 | * but not for C99 or C++ (due to mixed statements and declarations). Thus | | 695 | * but not for C99 or C++ (due to mixed statements and declarations). Thus |
696 | * we clear it in global_clean_up_decl(), which is used to do some cleanup | | 696 | * we clear it in global_clean_up_decl(), which is used to do some cleanup |
697 | * after global declarations/definitions. | | 697 | * after global declarations/definitions. |
698 | */ | | 698 | */ |
699 | void | | 699 | void |
700 | setasm(void) | | 700 | setasm(void) |
701 | { | | 701 | { |
702 | dinfo_t *di; | | 702 | dinfo_t *di; |
703 | | | 703 | |
704 | for (di = dcs; di != NULL; di = di->d_next) | | 704 | for (di = dcs; di != NULL; di = di->d_next) |
705 | di->d_asm = true; | | 705 | di->d_asm = true; |
706 | } | | 706 | } |
707 | | | 707 | |
708 | /* | | 708 | /* |
709 | * Clean all elements of the top element of declaration stack which | | 709 | * Clean all elements of the top element of declaration stack which |
710 | * will be used by the next declaration | | 710 | * will be used by the next declaration |
711 | */ | | 711 | */ |
712 | void | | 712 | void |
713 | begin_type(void) | | 713 | begin_type(void) |
714 | { | | 714 | { |
715 | | | 715 | |
716 | dcs->d_abstract_type = NOTSPEC; | | 716 | dcs->d_abstract_type = NOTSPEC; |
717 | dcs->d_complex_mod = NOTSPEC; | | 717 | dcs->d_complex_mod = NOTSPEC; |
718 | dcs->d_sign_mod = NOTSPEC; | | 718 | dcs->d_sign_mod = NOTSPEC; |
719 | dcs->d_rank_mod = NOTSPEC; | | 719 | dcs->d_rank_mod = NOTSPEC; |
720 | dcs->d_scl = NOSCL; | | 720 | dcs->d_scl = NOSCL; |
721 | dcs->d_type = NULL; | | 721 | dcs->d_type = NULL; |
722 | dcs->d_const = false; | | 722 | dcs->d_const = false; |
723 | dcs->d_volatile = false; | | 723 | dcs->d_volatile = false; |
724 | dcs->d_inline = false; | | 724 | dcs->d_inline = false; |
725 | dcs->d_mscl = false; | | 725 | dcs->d_mscl = false; |
726 | dcs->d_terr = false; | | 726 | dcs->d_terr = false; |
727 | dcs->d_nonempty_decl = false; | | 727 | dcs->d_nonempty_decl = false; |
728 | dcs->d_notyp = false; | | 728 | dcs->d_notyp = false; |
729 | } | | 729 | } |
730 | | | 730 | |
731 | static void | | 731 | static void |
732 | dcs_adjust_storage_class(void) | | 732 | dcs_adjust_storage_class(void) |
733 | { | | 733 | { |
734 | if (dcs->d_ctx == EXTERN) { | | 734 | if (dcs->d_ctx == EXTERN) { |
735 | if (dcs->d_scl == REG || dcs->d_scl == AUTO) { | | 735 | if (dcs->d_scl == REG || dcs->d_scl == AUTO) { |
736 | /* illegal storage class */ | | 736 | /* illegal storage class */ |
737 | error(8); | | 737 | error(8); |
738 | dcs->d_scl = NOSCL; | | 738 | dcs->d_scl = NOSCL; |
739 | } | | 739 | } |
740 | } else if (dcs->d_ctx == ARG || dcs->d_ctx == PROTO_ARG) { | | 740 | } else if (dcs->d_ctx == ARG || dcs->d_ctx == PROTO_ARG) { |
741 | if (dcs->d_scl != NOSCL && dcs->d_scl != REG) { | | 741 | if (dcs->d_scl != NOSCL && dcs->d_scl != REG) { |
742 | /* only register valid as formal parameter storage... */ | | 742 | /* only register valid as formal parameter storage... */ |
743 | error(9); | | 743 | error(9); |
744 | dcs->d_scl = NOSCL; | | 744 | dcs->d_scl = NOSCL; |
745 | } | | 745 | } |
746 | } | | 746 | } |
747 | } | | 747 | } |
748 | | | 748 | |
749 | /* | | 749 | /* |
750 | * Create a type structure from the information gathered in | | 750 | * Create a type structure from the information gathered in |
751 | * the declaration stack. | | 751 | * the declaration stack. |
752 | * Complain about storage classes which are not possible in current | | 752 | * Complain about storage classes which are not possible in current |
753 | * context. | | 753 | * context. |
754 | */ | | 754 | */ |
755 | void | | 755 | void |
756 | end_type(void) | | 756 | end_type(void) |
757 | { | | 757 | { |
758 | tspec_t t, s, l, c; | | 758 | tspec_t t, s, l, c; |
759 | type_t *tp; | | 759 | type_t *tp; |
760 | | | 760 | |
761 | t = dcs->d_abstract_type; /* VOID, BOOL, CHAR, INT or COMPLEX */ | | 761 | t = dcs->d_abstract_type; /* VOID, BOOL, CHAR, INT or COMPLEX */ |
762 | c = dcs->d_complex_mod; /* FLOAT or DOUBLE */ | | 762 | c = dcs->d_complex_mod; /* FLOAT or DOUBLE */ |
763 | s = dcs->d_sign_mod; /* SIGNED or UNSIGN */ | | 763 | s = dcs->d_sign_mod; /* SIGNED or UNSIGN */ |
764 | l = dcs->d_rank_mod; /* SHORT, LONG or QUAD */ | | 764 | l = dcs->d_rank_mod; /* SHORT, LONG or QUAD */ |
765 | tp = dcs->d_type; | | 765 | tp = dcs->d_type; |
766 | | | 766 | |
767 | #ifdef DEBUG | | 767 | #ifdef DEBUG |
768 | printf("%s: %s\n", __func__, type_name(tp)); | | 768 | printf("%s: %s\n", __func__, type_name(tp)); |
769 | #endif | | 769 | #endif |
770 | if (t == NOTSPEC && s == NOTSPEC && l == NOTSPEC && c == NOTSPEC && | | 770 | if (t == NOTSPEC && s == NOTSPEC && l == NOTSPEC && c == NOTSPEC && |
771 | tp == NULL) | | 771 | tp == NULL) |
772 | dcs->d_notyp = true; | | 772 | dcs->d_notyp = true; |
773 | if (t == NOTSPEC && s == NOTSPEC && (l == NOTSPEC || l == LONG) && | | 773 | if (t == NOTSPEC && s == NOTSPEC && (l == NOTSPEC || l == LONG) && |
774 | tp == NULL) | | 774 | tp == NULL) |
775 | t = c; | | 775 | t = c; |
776 | | | 776 | |
777 | if (tp != NULL) { | | 777 | if (tp != NULL) { |
778 | lint_assert(t == NOTSPEC); | | 778 | lint_assert(t == NOTSPEC); |
779 | lint_assert(s == NOTSPEC); | | 779 | lint_assert(s == NOTSPEC); |
780 | lint_assert(l == NOTSPEC); | | 780 | lint_assert(l == NOTSPEC); |
781 | } | | 781 | } |
782 | | | 782 | |
783 | if (tp == NULL) { | | 783 | if (tp == NULL) { |
784 | switch (t) { | | 784 | switch (t) { |
785 | case BOOL: | | 785 | case BOOL: |
786 | break; | | 786 | break; |
787 | case NOTSPEC: | | 787 | case NOTSPEC: |
788 | t = INT; | | 788 | t = INT; |
789 | /* FALLTHROUGH */ | | 789 | /* FALLTHROUGH */ |
790 | case INT: | | 790 | case INT: |
791 | if (s == NOTSPEC) | | 791 | if (s == NOTSPEC) |
792 | s = SIGNED; | | 792 | s = SIGNED; |
793 | break; | | 793 | break; |
794 | case CHAR: | | 794 | case CHAR: |
795 | if (l != NOTSPEC) { | | 795 | if (l != NOTSPEC) { |
796 | dcs->d_terr = true; | | 796 | dcs->d_terr = true; |
797 | l = NOTSPEC; | | 797 | l = NOTSPEC; |
798 | } | | 798 | } |
799 | break; | | 799 | break; |
800 | case FLOAT: | | 800 | case FLOAT: |
801 | if (l == LONG) { | | 801 | if (l == LONG) { |
802 | l = NOTSPEC; | | 802 | l = NOTSPEC; |
803 | t = DOUBLE; | | 803 | t = DOUBLE; |
804 | if (!tflag) | | 804 | if (!tflag) |
805 | /* use 'double' instead of 'long ... */ | | 805 | /* use 'double' instead of 'long ... */ |
806 | warning(6); | | 806 | warning(6); |
807 | } | | 807 | } |
808 | break; | | 808 | break; |
809 | case DOUBLE: | | 809 | case DOUBLE: |
810 | if (l == LONG) { | | 810 | if (l == LONG) { |
811 | case LDOUBLE: | | 811 | case LDOUBLE: |
812 | l = NOTSPEC; | | 812 | l = NOTSPEC; |
813 | t = LDOUBLE; | | 813 | t = LDOUBLE; |
814 | if (tflag) | | 814 | if (tflag) |
815 | /* 'long double' is illegal in ... */ | | 815 | /* 'long double' is illegal in ... */ |
816 | warning(266); | | 816 | warning(266); |
817 | } | | 817 | } |
818 | break; | | 818 | break; |
819 | case DCOMPLEX: | | 819 | case DCOMPLEX: |
820 | if (l == LONG) { | | 820 | if (l == LONG) { |
821 | l = NOTSPEC; | | 821 | l = NOTSPEC; |
822 | t = LCOMPLEX; | | 822 | t = LCOMPLEX; |
823 | if (tflag) | | 823 | if (tflag) |
824 | /* 'long double' is illegal in ... */ | | 824 | /* 'long double' is illegal in ... */ |
825 | warning(266); | | 825 | warning(266); |
826 | } | | 826 | } |
827 | break; | | 827 | break; |
828 | case VOID: | | 828 | case VOID: |
829 | case FCOMPLEX: | | 829 | case FCOMPLEX: |
830 | case LCOMPLEX: | | 830 | case LCOMPLEX: |
831 | break; | | 831 | break; |
832 | default: | | 832 | default: |
| | | 833 | if (is_integer(t)) |
| | | 834 | break; |
833 | INTERNAL_ERROR("end_type(%s)", tspec_name(t)); | | 835 | INTERNAL_ERROR("end_type(%s)", tspec_name(t)); |
834 | } | | 836 | } |
835 | if (t != INT && t != CHAR && (s != NOTSPEC || l != NOTSPEC)) { | | 837 | if (t != INT && t != CHAR && (s != NOTSPEC || l != NOTSPEC)) { |
836 | dcs->d_terr = true; | | 838 | dcs->d_terr = true; |
837 | l = s = NOTSPEC; | | 839 | l = s = NOTSPEC; |
838 | } | | 840 | } |
839 | if (l != NOTSPEC) | | 841 | if (l != NOTSPEC) |
840 | t = l; | | 842 | t = l; |
841 | dcs->d_type = gettyp(merge_type_specifiers(t, s)); | | 843 | dcs->d_type = gettyp(merge_type_specifiers(t, s)); |
842 | } | | 844 | } |
843 | | | 845 | |
844 | if (dcs->d_mscl) { | | 846 | if (dcs->d_mscl) { |
845 | /* only one storage class allowed */ | | 847 | /* only one storage class allowed */ |
846 | error(7); | | 848 | error(7); |
847 | } | | 849 | } |
848 | if (dcs->d_terr) { | | 850 | if (dcs->d_terr) { |
849 | /* illegal type combination */ | | 851 | /* illegal type combination */ |
850 | error(4); | | 852 | error(4); |
851 | } | | 853 | } |
852 | | | 854 | |
853 | dcs_adjust_storage_class(); | | 855 | dcs_adjust_storage_class(); |
854 | | | 856 | |
855 | if (dcs->d_const && dcs->d_type->t_const) { | | 857 | if (dcs->d_const && dcs->d_type->t_const) { |
856 | lint_assert(dcs->d_type->t_typedef); | | 858 | lint_assert(dcs->d_type->t_typedef); |
857 | /* typedef already qualified with '%s' */ | | 859 | /* typedef already qualified with '%s' */ |
858 | warning(68, "const"); | | 860 | warning(68, "const"); |
859 | } | | 861 | } |
860 | if (dcs->d_volatile && dcs->d_type->t_volatile) { | | 862 | if (dcs->d_volatile && dcs->d_type->t_volatile) { |
861 | lint_assert(dcs->d_type->t_typedef); | | 863 | lint_assert(dcs->d_type->t_typedef); |
862 | /* typedef already qualified with '%s' */ | | 864 | /* typedef already qualified with '%s' */ |
863 | warning(68, "volatile"); | | 865 | warning(68, "volatile"); |
864 | } | | 866 | } |
865 | | | 867 | |
866 | if (dcs->d_const || dcs->d_volatile) { | | 868 | if (dcs->d_const || dcs->d_volatile) { |
867 | dcs->d_type = dup_type(dcs->d_type); | | 869 | dcs->d_type = dup_type(dcs->d_type); |
868 | dcs->d_type->t_const |= dcs->d_const; | | 870 | dcs->d_type->t_const |= dcs->d_const; |
869 | dcs->d_type->t_volatile |= dcs->d_volatile; | | 871 | dcs->d_type->t_volatile |= dcs->d_volatile; |
870 | } | | 872 | } |
871 | } | | 873 | } |
872 | | | 874 | |
873 | /* | | 875 | /* |
874 | * Merge type specifiers (char, ..., long long, signed, unsigned). | | 876 | * Merge type specifiers (char, ..., long long, signed, unsigned). |
875 | */ | | 877 | */ |
876 | static tspec_t | | 878 | static tspec_t |
877 | merge_type_specifiers(tspec_t t, tspec_t s) | | 879 | merge_type_specifiers(tspec_t t, tspec_t s) |
878 | { | | 880 | { |
879 | | | 881 | |
880 | if (s != SIGNED && s != UNSIGN) | | 882 | if (s != SIGNED && s != UNSIGN) |
881 | return t; | | 883 | return t; |
882 | | | 884 | |
883 | if (t == CHAR) | | 885 | if (t == CHAR) |
884 | return s == SIGNED ? SCHAR : UCHAR; | | 886 | return s == SIGNED ? SCHAR : UCHAR; |
885 | if (t == SHORT) | | 887 | if (t == SHORT) |
886 | return s == SIGNED ? SHORT : USHORT; | | 888 | return s == SIGNED ? SHORT : USHORT; |
887 | if (t == INT) | | 889 | if (t == INT) |
888 | return s == SIGNED ? INT : UINT; | | 890 | return s == SIGNED ? INT : UINT; |
889 | if (t == LONG) | | 891 | if (t == LONG) |
890 | return s == SIGNED ? LONG : ULONG; | | 892 | return s == SIGNED ? LONG : ULONG; |
891 | if (t == QUAD) | | 893 | if (t == QUAD) |
892 | return s == SIGNED ? QUAD : UQUAD; | | 894 | return s == SIGNED ? QUAD : UQUAD; |
893 | return t; | | 895 | return t; |
894 | } | | 896 | } |
895 | | | 897 | |
896 | /* | | 898 | /* |
897 | * Return the length of a type in bits. | | 899 | * Return the length of a type in bits. |
898 | * | | 900 | * |
899 | * Printing a message if the outermost dimension of an array is 0 must | | 901 | * Printing a message if the outermost dimension of an array is 0 must |
900 | * be done by the caller. All other problems are reported by length() | | 902 | * be done by the caller. All other problems are reported by length() |
901 | * if name is not NULL. | | 903 | * if name is not NULL. |
902 | */ | | 904 | */ |
903 | int | | 905 | int |
904 | length(const type_t *tp, const char *name) | | 906 | length(const type_t *tp, const char *name) |
905 | { | | 907 | { |
906 | int elem, elsz; | | 908 | int elem, elsz; |
907 | | | 909 | |
908 | elem = 1; | | 910 | elem = 1; |
909 | while (tp != NULL && tp->t_tspec == ARRAY) { | | 911 | while (tp != NULL && tp->t_tspec == ARRAY) { |
910 | elem *= tp->t_dim; | | 912 | elem *= tp->t_dim; |
911 | tp = tp->t_subt; | | 913 | tp = tp->t_subt; |
912 | } | | 914 | } |
913 | if (tp == NULL) | | 915 | if (tp == NULL) |
914 | return -1; | | 916 | return -1; |
915 | | | 917 | |
916 | switch (tp->t_tspec) { | | 918 | switch (tp->t_tspec) { |
917 | case FUNC: | | 919 | case FUNC: |
918 | /* compiler takes size of function */ | | 920 | /* compiler takes size of function */ |
919 | INTERNAL_ERROR("%s", msgs[12]); | | 921 | INTERNAL_ERROR("%s", msgs[12]); |
920 | /* NOTREACHED */ | | 922 | /* NOTREACHED */ |
921 | case STRUCT: | | 923 | case STRUCT: |
922 | case UNION: | | 924 | case UNION: |
923 | if (is_incomplete(tp) && name != NULL) { | | 925 | if (is_incomplete(tp) && name != NULL) { |
924 | /* '%s' has incomplete type '%s' */ | | 926 | /* '%s' has incomplete type '%s' */ |
925 | error(31, name, type_name(tp)); | | 927 | error(31, name, type_name(tp)); |
926 | } | | 928 | } |
927 | elsz = tp->t_str->sou_size_in_bits; | | 929 | elsz = tp->t_str->sou_size_in_bits; |
928 | break; | | 930 | break; |
929 | case ENUM: | | 931 | case ENUM: |
930 | if (is_incomplete(tp) && name != NULL) { | | 932 | if (is_incomplete(tp) && name != NULL) { |
931 | /* incomplete enum type: %s */ | | 933 | /* incomplete enum type: %s */ |
932 | warning(13, name); | | 934 | warning(13, name); |
933 | } | | 935 | } |
934 | /* FALLTHROUGH */ | | 936 | /* FALLTHROUGH */ |
935 | default: | | 937 | default: |
936 | elsz = size_in_bits(tp->t_tspec); | | 938 | elsz = size_in_bits(tp->t_tspec); |
937 | if (elsz <= 0) | | 939 | if (elsz <= 0) |
938 | INTERNAL_ERROR("length(%d)", elsz); | | 940 | INTERNAL_ERROR("length(%d)", elsz); |
939 | break; | | 941 | break; |
940 | } | | 942 | } |
941 | return elem * elsz; | | 943 | return elem * elsz; |
942 | } | | 944 | } |
943 | | | 945 | |
944 | int | | 946 | int |
945 | alignment_in_bits(const type_t *tp) | | 947 | alignment_in_bits(const type_t *tp) |
946 | { | | 948 | { |
947 | size_t a; | | 949 | size_t a; |
948 | tspec_t t; | | 950 | tspec_t t; |
949 | | | 951 | |
950 | while (tp != NULL && tp->t_tspec == ARRAY) | | 952 | while (tp != NULL && tp->t_tspec == ARRAY) |
951 | tp = tp->t_subt; | | 953 | tp = tp->t_subt; |
952 | | | 954 | |
953 | if (tp == NULL) | | 955 | if (tp == NULL) |
954 | return -1; | | 956 | return -1; |
955 | | | 957 | |
956 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { | | 958 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { |
957 | a = tp->t_str->sou_align_in_bits; | | 959 | a = tp->t_str->sou_align_in_bits; |
958 | } else if (t == FUNC) { | | 960 | } else if (t == FUNC) { |
959 | /* compiler takes alignment of function */ | | 961 | /* compiler takes alignment of function */ |
960 | error(14); | | 962 | error(14); |
961 | a = WORST_ALIGN(1) * CHAR_SIZE; | | 963 | a = WORST_ALIGN(1) * CHAR_SIZE; |
962 | } else { | | 964 | } else { |
963 | if ((a = size_in_bits(t)) == 0) { | | 965 | if ((a = size_in_bits(t)) == 0) { |
964 | a = CHAR_SIZE; | | 966 | a = CHAR_SIZE; |
965 | } else if (a > WORST_ALIGN(1) * CHAR_SIZE) { | | 967 | } else if (a > WORST_ALIGN(1) * CHAR_SIZE) { |
966 | a = WORST_ALIGN(1) * CHAR_SIZE; | | 968 | a = WORST_ALIGN(1) * CHAR_SIZE; |
967 | } | | 969 | } |
968 | } | | 970 | } |
969 | lint_assert(a >= CHAR_SIZE); | | 971 | lint_assert(a >= CHAR_SIZE); |
970 | lint_assert(a <= WORST_ALIGN(1) * CHAR_SIZE); | | 972 | lint_assert(a <= WORST_ALIGN(1) * CHAR_SIZE); |
971 | return a; | | 973 | return a; |
972 | } | | 974 | } |
973 | | | 975 | |
974 | /* | | 976 | /* |
975 | * Concatenate two lists of symbols by s_next. Used by declarations of | | 977 | * Concatenate two lists of symbols by s_next. Used by declarations of |
976 | * struct/union/enum elements and parameters. | | 978 | * struct/union/enum elements and parameters. |
977 | */ | | 979 | */ |
978 | sym_t * | | 980 | sym_t * |
979 | lnklst(sym_t *l1, sym_t *l2) | | 981 | lnklst(sym_t *l1, sym_t *l2) |
980 | { | | 982 | { |
981 | sym_t *l; | | 983 | sym_t *l; |
982 | | | 984 | |
983 | if ((l = l1) == NULL) | | 985 | if ((l = l1) == NULL) |
984 | return l2; | | 986 | return l2; |
985 | while (l1->s_next != NULL) | | 987 | while (l1->s_next != NULL) |
986 | l1 = l1->s_next; | | 988 | l1 = l1->s_next; |
987 | l1->s_next = l2; | | 989 | l1->s_next = l2; |
988 | return l; | | 990 | return l; |
989 | } | | 991 | } |
990 | | | 992 | |
991 | /* | | 993 | /* |
992 | * Check if the type of the given symbol is valid and print an error | | 994 | * Check if the type of the given symbol is valid and print an error |
993 | * message if it is not. | | 995 | * message if it is not. |
994 | * | | 996 | * |
995 | * Invalid types are: | | 997 | * Invalid types are: |
996 | * - arrays of incomplete types or functions | | 998 | * - arrays of incomplete types or functions |
997 | * - functions returning arrays or functions | | 999 | * - functions returning arrays or functions |
998 | * - void types other than type of function or pointer | | 1000 | * - void types other than type of function or pointer |
999 | */ | | 1001 | */ |
1000 | void | | 1002 | void |
1001 | check_type(sym_t *sym) | | 1003 | check_type(sym_t *sym) |
1002 | { | | 1004 | { |
1003 | tspec_t to, t; | | 1005 | tspec_t to, t; |
1004 | type_t **tpp, *tp; | | 1006 | type_t **tpp, *tp; |
1005 | | | 1007 | |
1006 | tpp = &sym->s_type; | | 1008 | tpp = &sym->s_type; |
1007 | to = NOTSPEC; | | 1009 | to = NOTSPEC; |
1008 | while ((tp = *tpp) != NULL) { | | 1010 | while ((tp = *tpp) != NULL) { |
1009 | t = tp->t_tspec; | | 1011 | t = tp->t_tspec; |
1010 | /* | | 1012 | /* |
1011 | * If this is the type of an old style function definition, | | 1013 | * If this is the type of an old style function definition, |
1012 | * a better warning is printed in funcdef(). | | 1014 | * a better warning is printed in funcdef(). |
1013 | */ | | 1015 | */ |
1014 | if (t == FUNC && !tp->t_proto && | | 1016 | if (t == FUNC && !tp->t_proto && |
1015 | !(to == NOTSPEC && sym->s_osdef)) { | | 1017 | !(to == NOTSPEC && sym->s_osdef)) { |
1016 | if (sflag && hflag) | | 1018 | if (sflag && hflag) |
1017 | /* function declaration is not a prototype */ | | 1019 | /* function declaration is not a prototype */ |
1018 | warning(287); | | 1020 | warning(287); |
1019 | } | | 1021 | } |
1020 | if (to == FUNC) { | | 1022 | if (to == FUNC) { |
1021 | if (t == FUNC || t == ARRAY) { | | 1023 | if (t == FUNC || t == ARRAY) { |
1022 | /* function returns illegal type */ | | 1024 | /* function returns illegal type */ |
1023 | error(15); | | 1025 | error(15); |
1024 | if (t == FUNC) { | | 1026 | if (t == FUNC) { |
1025 | *tpp = derive_type(*tpp, PTR); | | 1027 | *tpp = derive_type(*tpp, PTR); |
1026 | } else { | | 1028 | } else { |
1027 | *tpp = derive_type((*tpp)->t_subt, PTR); | | 1029 | *tpp = derive_type((*tpp)->t_subt, PTR); |
1028 | } | | 1030 | } |
1029 | return; | | 1031 | return; |
1030 | } else if (tp->t_const || tp->t_volatile) { | | 1032 | } else if (tp->t_const || tp->t_volatile) { |
1031 | if (sflag) { /* XXX or better !tflag ? */ | | 1033 | if (sflag) { /* XXX or better !tflag ? */ |
1032 | /* function cannot return const... */ | | 1034 | /* function cannot return const... */ |
1033 | warning(228); | | 1035 | warning(228); |
1034 | } | | 1036 | } |
1035 | } | | 1037 | } |
1036 | } if (to == ARRAY) { | | 1038 | } if (to == ARRAY) { |
1037 | if (t == FUNC) { | | 1039 | if (t == FUNC) { |
1038 | /* array of function is illegal */ | | 1040 | /* array of function is illegal */ |
1039 | error(16); | | 1041 | error(16); |
1040 | *tpp = gettyp(INT); | | 1042 | *tpp = gettyp(INT); |
1041 | return; | | 1043 | return; |
1042 | } else if (t == ARRAY && tp->t_dim == 0) { | | 1044 | } else if (t == ARRAY && tp->t_dim == 0) { |
1043 | /* null dimension */ | | 1045 | /* null dimension */ |
1044 | error(17); | | 1046 | error(17); |
1045 | return; | | 1047 | return; |
1046 | } else if (t == VOID) { | | 1048 | } else if (t == VOID) { |
1047 | /* illegal use of 'void' */ | | 1049 | /* illegal use of 'void' */ |
1048 | error(18); | | 1050 | error(18); |
1049 | *tpp = gettyp(INT); | | 1051 | *tpp = gettyp(INT); |
1050 | #if 0 /* errors are produced by length() */ | | 1052 | #if 0 /* errors are produced by length() */ |
1051 | } else if (is_incomplete(tp)) { | | 1053 | } else if (is_incomplete(tp)) { |
1052 | /* array of incomplete type */ | | 1054 | /* array of incomplete type */ |
1053 | if (sflag) { | | 1055 | if (sflag) { |
1054 | /* array of incomplete type */ | | 1056 | /* array of incomplete type */ |
1055 | error(301); | | 1057 | error(301); |
1056 | } else { | | 1058 | } else { |
1057 | /* array of incomplete type */ | | 1059 | /* array of incomplete type */ |
1058 | warning(301); | | 1060 | warning(301); |
1059 | } | | 1061 | } |
1060 | #endif | | 1062 | #endif |
1061 | } | | 1063 | } |
1062 | } else if (to == NOTSPEC && t == VOID) { | | 1064 | } else if (to == NOTSPEC && t == VOID) { |
1063 | if (dcs->d_ctx == PROTO_ARG) { | | 1065 | if (dcs->d_ctx == PROTO_ARG) { |
1064 | if (sym->s_scl != ABSTRACT) { | | 1066 | if (sym->s_scl != ABSTRACT) { |
1065 | lint_assert(sym->s_name != unnamed); | | 1067 | lint_assert(sym->s_name != unnamed); |
1066 | /* void param. cannot have name: %s */ | | 1068 | /* void param. cannot have name: %s */ |
1067 | error(61, sym->s_name); | | 1069 | error(61, sym->s_name); |
1068 | *tpp = gettyp(INT); | | 1070 | *tpp = gettyp(INT); |
1069 | } | | 1071 | } |
1070 | } else if (dcs->d_ctx == ABSTRACT) { | | 1072 | } else if (dcs->d_ctx == ABSTRACT) { |
1071 | /* ok */ | | 1073 | /* ok */ |
1072 | } else if (sym->s_scl != TYPEDEF) { | | 1074 | } else if (sym->s_scl != TYPEDEF) { |
1073 | /* void type for '%s' */ | | 1075 | /* void type for '%s' */ |
1074 | error(19, sym->s_name); | | 1076 | error(19, sym->s_name); |
1075 | *tpp = gettyp(INT); | | 1077 | *tpp = gettyp(INT); |
1076 | } | | 1078 | } |
1077 | } | | 1079 | } |
1078 | if (t == VOID && to != PTR) { | | 1080 | if (t == VOID && to != PTR) { |
1079 | if (tp->t_const || tp->t_volatile) { | | 1081 | if (tp->t_const || tp->t_volatile) { |
1080 | /* inappropriate qualifiers with 'void' */ | | 1082 | /* inappropriate qualifiers with 'void' */ |
1081 | warning(69); | | 1083 | warning(69); |
1082 | tp->t_const = tp->t_volatile = false; | | 1084 | tp->t_const = tp->t_volatile = false; |
1083 | } | | 1085 | } |
1084 | } | | 1086 | } |
1085 | tpp = &tp->t_subt; | | 1087 | tpp = &tp->t_subt; |
1086 | to = t; | | 1088 | to = t; |
1087 | } | | 1089 | } |
1088 | } | | 1090 | } |
1089 | | | 1091 | |
1090 | /* | | 1092 | /* |
1091 | * In traditional C, the only portable type for bit-fields is unsigned int. | | 1093 | * In traditional C, the only portable type for bit-fields is unsigned int. |
1092 | * | | 1094 | * |
1093 | * In C90, the only allowed types for bit-fields are int, signed int and | | 1095 | * In C90, the only allowed types for bit-fields are int, signed int and |
1094 | * unsigned int (3.5.2.1). There is no mention of implementation-defined | | 1096 | * unsigned int (3.5.2.1). There is no mention of implementation-defined |
1095 | * types. | | 1097 | * types. |
1096 | * | | 1098 | * |
1097 | * In C99, the only portable types for bit-fields are _Bool, signed int and | | 1099 | * In C99, the only portable types for bit-fields are _Bool, signed int and |
1098 | * unsigned int (6.7.2.1p4). In addition, C99 allows "or some other | | 1100 | * unsigned int (6.7.2.1p4). In addition, C99 allows "or some other |
1099 | * implementation-defined type". | | 1101 | * implementation-defined type". |
1100 | */ | | 1102 | */ |
1101 | static void | | 1103 | static void |
1102 | check_bit_field_type(sym_t *dsym, type_t **const inout_tp, tspec_t *inout_t) | | 1104 | check_bit_field_type(sym_t *dsym, type_t **const inout_tp, tspec_t *inout_t) |
1103 | { | | 1105 | { |
1104 | type_t *tp = *inout_tp; | | 1106 | type_t *tp = *inout_tp; |
1105 | tspec_t t = *inout_t; | | 1107 | tspec_t t = *inout_t; |
1106 | | | 1108 | |
1107 | if (t == CHAR || t == UCHAR || t == SCHAR || | | 1109 | if (t == CHAR || t == UCHAR || t == SCHAR || |
1108 | t == SHORT || t == USHORT || t == ENUM) { | | 1110 | t == SHORT || t == USHORT || t == ENUM) { |
1109 | if (!bitfieldtype_ok) { | | 1111 | if (!bitfieldtype_ok) { |
1110 | if (sflag) { | | 1112 | if (sflag) { |
1111 | /* bit-field type '%s' invalid in ANSI C */ | | 1113 | /* bit-field type '%s' invalid in ANSI C */ |
1112 | warning(273, type_name(tp)); | | 1114 | warning(273, type_name(tp)); |
1113 | } else if (pflag) { | | 1115 | } else if (pflag) { |
1114 | /* nonportable bit-field type '%s' */ | | 1116 | /* nonportable bit-field type '%s' */ |
1115 | warning(34, type_name(tp)); | | 1117 | warning(34, type_name(tp)); |
1116 | } | | 1118 | } |
1117 | } | | 1119 | } |
1118 | } else if (t == INT && dcs->d_sign_mod == NOTSPEC) { | | 1120 | } else if (t == INT && dcs->d_sign_mod == NOTSPEC) { |
1119 | if (pflag && !bitfieldtype_ok) { | | 1121 | if (pflag && !bitfieldtype_ok) { |
1120 | /* bit-field of type plain 'int' has ... */ | | 1122 | /* bit-field of type plain 'int' has ... */ |
1121 | warning(344); | | 1123 | warning(344); |
1122 | } | | 1124 | } |
1123 | } else if (t != INT && t != UINT && t != BOOL) { | | 1125 | } else if (t != INT && t != UINT && t != BOOL) { |
1124 | /* | | 1126 | /* |
1125 | * Non-integer types are always illegal for bitfields, | | 1127 | * Non-integer types are always illegal for bitfields, |
1126 | * regardless of BITFIELDTYPE. Integer types not dealt with | | 1128 | * regardless of BITFIELDTYPE. Integer types not dealt with |
1127 | * above are okay only if BITFIELDTYPE is in effect. | | 1129 | * above are okay only if BITFIELDTYPE is in effect. |
1128 | */ | | 1130 | */ |
1129 | if (!(bitfieldtype_ok || gflag) || !is_integer(t)) { | | 1131 | if (!(bitfieldtype_ok || gflag) || !is_integer(t)) { |
1130 | /* illegal bit-field type '%s' */ | | 1132 | /* illegal bit-field type '%s' */ |
1131 | warning(35, type_name(tp)); | | 1133 | warning(35, type_name(tp)); |
1132 | int sz = tp->t_flen; | | 1134 | int sz = tp->t_flen; |
1133 | dsym->s_type = tp = dup_type(gettyp(t = INT)); | | 1135 | dsym->s_type = tp = dup_type(gettyp(t = INT)); |
1134 | if ((tp->t_flen = sz) > size_in_bits(t)) | | 1136 | if ((tp->t_flen = sz) > size_in_bits(t)) |
1135 | tp->t_flen = size_in_bits(t); | | 1137 | tp->t_flen = size_in_bits(t); |
1136 | *inout_t = t; | | 1138 | *inout_t = t; |
1137 | *inout_tp = tp; | | 1139 | *inout_tp = tp; |
1138 | } | | 1140 | } |
1139 | } | | 1141 | } |
1140 | } | | 1142 | } |
1141 | | | 1143 | |
1142 | static void | | 1144 | static void |
1143 | declare_bit_field(sym_t *dsym, tspec_t *inout_t, type_t **const inout_tp) | | 1145 | declare_bit_field(sym_t *dsym, tspec_t *inout_t, type_t **const inout_tp) |
1144 | { | | 1146 | { |
1145 | | | 1147 | |
1146 | check_bit_field_type(dsym, inout_tp, inout_t); | | 1148 | check_bit_field_type(dsym, inout_tp, inout_t); |
1147 | | | 1149 | |
1148 | type_t *const tp = *inout_tp; | | 1150 | type_t *const tp = *inout_tp; |
1149 | tspec_t const t = *inout_t; | | 1151 | tspec_t const t = *inout_t; |
1150 | if (tp->t_flen < 0 || tp->t_flen > (ssize_t)size_in_bits(t)) { | | 1152 | if (tp->t_flen < 0 || tp->t_flen > (ssize_t)size_in_bits(t)) { |
1151 | /* illegal bit-field size: %d */ | | 1153 | /* illegal bit-field size: %d */ |
1152 | error(36, tp->t_flen); | | 1154 | error(36, tp->t_flen); |
1153 | tp->t_flen = size_in_bits(t); | | 1155 | tp->t_flen = size_in_bits(t); |
1154 | } else if (tp->t_flen == 0 && dsym->s_name != unnamed) { | | 1156 | } else if (tp->t_flen == 0 && dsym->s_name != unnamed) { |
1155 | /* zero size bit-field */ | | 1157 | /* zero size bit-field */ |
1156 | error(37); | | 1158 | error(37); |
1157 | tp->t_flen = size_in_bits(t); | | 1159 | tp->t_flen = size_in_bits(t); |
1158 | } | | 1160 | } |
1159 | if (dsym->s_scl == MOU) { | | 1161 | if (dsym->s_scl == MOU) { |
1160 | /* illegal use of bit-field */ | | 1162 | /* illegal use of bit-field */ |
1161 | error(41); | | 1163 | error(41); |
1162 | dsym->s_type->t_bitfield = false; | | 1164 | dsym->s_type->t_bitfield = false; |
1163 | dsym->s_bitfield = false; | | 1165 | dsym->s_bitfield = false; |
1164 | } | | 1166 | } |
1165 | } | | 1167 | } |
1166 | | | 1168 | |
1167 | /* | | 1169 | /* |
1168 | * Process the declarator of a struct/union element. | | 1170 | * Process the declarator of a struct/union element. |
1169 | */ | | 1171 | */ |
1170 | sym_t * | | 1172 | sym_t * |
1171 | declarator_1_struct_union(sym_t *dsym) | | 1173 | declarator_1_struct_union(sym_t *dsym) |
1172 | { | | 1174 | { |
1173 | type_t *tp; | | 1175 | type_t *tp; |
1174 | tspec_t t; | | 1176 | tspec_t t; |
1175 | int sz; | | 1177 | int sz; |
1176 | int o = 0; /* Appease GCC */ | | 1178 | int o = 0; /* Appease GCC */ |
1177 | | | 1179 | |
1178 | lint_assert(dsym->s_scl == MOS || dsym->s_scl == MOU); | | 1180 | lint_assert(dsym->s_scl == MOS || dsym->s_scl == MOU); |
1179 | | | 1181 | |
1180 | if (dcs->d_redeclared_symbol != NULL) { | | 1182 | if (dcs->d_redeclared_symbol != NULL) { |
1181 | /* should be ensured by storesym() */ | | 1183 | /* should be ensured by storesym() */ |
1182 | lint_assert(dcs->d_redeclared_symbol->s_scl == MOS || | | 1184 | lint_assert(dcs->d_redeclared_symbol->s_scl == MOS || |
1183 | dcs->d_redeclared_symbol->s_scl == MOU); | | 1185 | dcs->d_redeclared_symbol->s_scl == MOU); |
1184 | | | 1186 | |
1185 | if (dsym->s_styp == dcs->d_redeclared_symbol->s_styp) { | | 1187 | if (dsym->s_styp == dcs->d_redeclared_symbol->s_styp) { |
1186 | /* duplicate member name: %s */ | | 1188 | /* duplicate member name: %s */ |
1187 | error(33, dsym->s_name); | | 1189 | error(33, dsym->s_name); |
1188 | rmsym(dcs->d_redeclared_symbol); | | 1190 | rmsym(dcs->d_redeclared_symbol); |
1189 | } | | 1191 | } |
1190 | } | | 1192 | } |
1191 | | | 1193 | |
1192 | check_type(dsym); | | 1194 | check_type(dsym); |
1193 | | | 1195 | |
1194 | t = (tp = dsym->s_type)->t_tspec; | | 1196 | t = (tp = dsym->s_type)->t_tspec; |
1195 | | | 1197 | |
1196 | if (dsym->s_bitfield) { | | 1198 | if (dsym->s_bitfield) { |
1197 | declare_bit_field(dsym, &t, &tp); | | 1199 | declare_bit_field(dsym, &t, &tp); |
1198 | } else if (t == FUNC) { | | 1200 | } else if (t == FUNC) { |
1199 | /* function illegal in structure or union */ | | 1201 | /* function illegal in structure or union */ |
1200 | error(38); | | 1202 | error(38); |
1201 | dsym->s_type = tp = derive_type(tp, t = PTR); | | 1203 | dsym->s_type = tp = derive_type(tp, t = PTR); |
1202 | } | | 1204 | } |
1203 | | | 1205 | |
1204 | /* | | 1206 | /* |
1205 | * bit-fields of length 0 are not warned about because length() | | 1207 | * bit-fields of length 0 are not warned about because length() |
1206 | * does not return the length of the bit-field but the length | | 1208 | * does not return the length of the bit-field but the length |
1207 | * of the type the bit-field is packed in (it's ok) | | 1209 | * of the type the bit-field is packed in (it's ok) |
1208 | */ | | 1210 | */ |
1209 | if ((sz = length(dsym->s_type, dsym->s_name)) == 0) { | | 1211 | if ((sz = length(dsym->s_type, dsym->s_name)) == 0) { |
1210 | if (t == ARRAY && dsym->s_type->t_dim == 0) { | | 1212 | if (t == ARRAY && dsym->s_type->t_dim == 0) { |
1211 | /* zero sized array in struct is a C99 extension: %s */ | | 1213 | /* zero sized array in struct is a C99 extension: %s */ |
1212 | c99ism(39, dsym->s_name); | | 1214 | c99ism(39, dsym->s_name); |
1213 | } | | 1215 | } |
1214 | } | | 1216 | } |
1215 | | | 1217 | |
1216 | if (dcs->d_ctx == MOU) { | | 1218 | if (dcs->d_ctx == MOU) { |
1217 | o = dcs->d_offset; | | 1219 | o = dcs->d_offset; |
1218 | dcs->d_offset = 0; | | 1220 | dcs->d_offset = 0; |
1219 | } | | 1221 | } |
1220 | if (dsym->s_bitfield) { | | 1222 | if (dsym->s_bitfield) { |
1221 | align(alignment_in_bits(tp), tp->t_flen); | | 1223 | align(alignment_in_bits(tp), tp->t_flen); |
1222 | dsym->s_value.v_quad = | | 1224 | dsym->s_value.v_quad = |
1223 | (dcs->d_offset / size_in_bits(t)) * size_in_bits(t); | | 1225 | (dcs->d_offset / size_in_bits(t)) * size_in_bits(t); |
1224 | tp->t_foffs = dcs->d_offset - (int)dsym->s_value.v_quad; | | 1226 | tp->t_foffs = dcs->d_offset - (int)dsym->s_value.v_quad; |
1225 | dcs->d_offset += tp->t_flen; | | 1227 | dcs->d_offset += tp->t_flen; |
1226 | } else { | | 1228 | } else { |
1227 | align(alignment_in_bits(tp), 0); | | 1229 | align(alignment_in_bits(tp), 0); |
1228 | dsym->s_value.v_quad = dcs->d_offset; | | 1230 | dsym->s_value.v_quad = dcs->d_offset; |
1229 | dcs->d_offset += sz; | | 1231 | dcs->d_offset += sz; |
1230 | } | | 1232 | } |
1231 | if (dcs->d_ctx == MOU) { | | 1233 | if (dcs->d_ctx == MOU) { |
1232 | if (o > dcs->d_offset) | | 1234 | if (o > dcs->d_offset) |
1233 | dcs->d_offset = o; | | 1235 | dcs->d_offset = o; |
1234 | } | | 1236 | } |
1235 | | | 1237 | |
1236 | check_function_definition(dsym, false); | | 1238 | check_function_definition(dsym, false); |
1237 | | | 1239 | |
1238 | /* | | 1240 | /* |
1239 | * Clear the BITFIELDTYPE indicator after processing each | | 1241 | * Clear the BITFIELDTYPE indicator after processing each |
1240 | * structure element. | | 1242 | * structure element. |
1241 | */ | | 1243 | */ |
1242 | bitfieldtype_ok = false; | | 1244 | bitfieldtype_ok = false; |
1243 | | | 1245 | |
1244 | return dsym; | | 1246 | return dsym; |
1245 | } | | 1247 | } |
1246 | | | 1248 | |
1247 | /* | | 1249 | /* |
1248 | * Aligns next structure element as required. | | 1250 | * Aligns next structure element as required. |
1249 | * | | 1251 | * |
1250 | * al contains the required alignment, len the length of a bit-field. | | 1252 | * al contains the required alignment, len the length of a bit-field. |
1251 | */ | | 1253 | */ |
1252 | static void | | 1254 | static void |
1253 | align(int al, int len) | | 1255 | align(int al, int len) |
1254 | { | | 1256 | { |
1255 | int no; | | 1257 | int no; |
1256 | | | 1258 | |
1257 | /* | | 1259 | /* |
1258 | * The alignment of the current element becomes the alignment of | | 1260 | * The alignment of the current element becomes the alignment of |
1259 | * the struct/union if it is larger than the current alignment | | 1261 | * the struct/union if it is larger than the current alignment |
1260 | * of the struct/union. | | 1262 | * of the struct/union. |
1261 | */ | | 1263 | */ |
1262 | if (al > dcs->d_sou_align_in_bits) | | 1264 | if (al > dcs->d_sou_align_in_bits) |
1263 | dcs->d_sou_align_in_bits = al; | | 1265 | dcs->d_sou_align_in_bits = al; |
1264 | | | 1266 | |
1265 | no = (dcs->d_offset + (al - 1)) & ~(al - 1); | | 1267 | no = (dcs->d_offset + (al - 1)) & ~(al - 1); |
1266 | if (len == 0 || dcs->d_offset + len > no) | | 1268 | if (len == 0 || dcs->d_offset + len > no) |
1267 | dcs->d_offset = no; | | 1269 | dcs->d_offset = no; |
1268 | } | | 1270 | } |
1269 | | | 1271 | |
1270 | /* | | 1272 | /* |
1271 | * Remember the width of the field in its type structure. | | 1273 | * Remember the width of the field in its type structure. |
1272 | */ | | 1274 | */ |
1273 | sym_t * | | 1275 | sym_t * |
1274 | bitfield(sym_t *dsym, int len) | | 1276 | bitfield(sym_t *dsym, int len) |
1275 | { | | 1277 | { |
1276 | | | 1278 | |
1277 | if (dsym == NULL) { | | 1279 | if (dsym == NULL) { |
1278 | dsym = getblk(sizeof(*dsym)); | | 1280 | dsym = getblk(sizeof(*dsym)); |
1279 | dsym->s_name = unnamed; | | 1281 | dsym->s_name = unnamed; |
1280 | dsym->s_kind = FMEMBER; | | 1282 | dsym->s_kind = FMEMBER; |
1281 | dsym->s_scl = MOS; | | 1283 | dsym->s_scl = MOS; |
1282 | dsym->s_type = gettyp(UINT); | | 1284 | dsym->s_type = gettyp(UINT); |
1283 | dsym->s_block_level = -1; | | 1285 | dsym->s_block_level = -1; |
1284 | } | | 1286 | } |
1285 | dsym->s_type = dup_type(dsym->s_type); | | 1287 | dsym->s_type = dup_type(dsym->s_type); |
1286 | dsym->s_type->t_bitfield = true; | | 1288 | dsym->s_type->t_bitfield = true; |
1287 | dsym->s_type->t_flen = len; | | 1289 | dsym->s_type->t_flen = len; |
1288 | dsym->s_bitfield = true; | | 1290 | dsym->s_bitfield = true; |
1289 | return dsym; | | 1291 | return dsym; |
1290 | } | | 1292 | } |
1291 | | | 1293 | |
1292 | /* | | 1294 | /* |
1293 | * A sequence of asterisks and qualifiers, from right to left. For example, | | 1295 | * A sequence of asterisks and qualifiers, from right to left. For example, |
1294 | * 'const ***volatile **const volatile' results in [cvp, p, vp, p, p]. The | | 1296 | * 'const ***volatile **const volatile' results in [cvp, p, vp, p, p]. The |
1295 | * leftmost 'const' is not included in this list, it is stored in dcs->d_const | | 1297 | * leftmost 'const' is not included in this list, it is stored in dcs->d_const |
1296 | * instead. | | 1298 | * instead. |
1297 | */ | | 1299 | */ |
1298 | qual_ptr * | | 1300 | qual_ptr * |
1299 | merge_qualified_pointer(qual_ptr *p1, qual_ptr *p2) | | 1301 | merge_qualified_pointer(qual_ptr *p1, qual_ptr *p2) |
1300 | { | | 1302 | { |
1301 | qual_ptr *tail; | | 1303 | qual_ptr *tail; |
1302 | | | 1304 | |
1303 | if (p2 == NULL) | | 1305 | if (p2 == NULL) |
1304 | return p1; /* for optional qualifiers */ | | 1306 | return p1; /* for optional qualifiers */ |
1305 | | | 1307 | |
1306 | if (p2->p_pointer) { | | 1308 | if (p2->p_pointer) { |
1307 | /* append p1 to p2, keeping p2 */ | | 1309 | /* append p1 to p2, keeping p2 */ |
1308 | for (tail = p2; tail->p_next != NULL; tail = tail->p_next) | | 1310 | for (tail = p2; tail->p_next != NULL; tail = tail->p_next) |
1309 | continue; | | 1311 | continue; |
1310 | tail->p_next = p1; | | 1312 | tail->p_next = p1; |
1311 | return p2; | | 1313 | return p2; |
1312 | } | | 1314 | } |
1313 | | | 1315 | |
1314 | /* merge p2 into p1, keeping p1 */ | | 1316 | /* merge p2 into p1, keeping p1 */ |
1315 | if (p2->p_const) { | | 1317 | if (p2->p_const) { |
1316 | if (p1->p_const) { | | 1318 | if (p1->p_const) { |
1317 | /* duplicate '%s' */ | | 1319 | /* duplicate '%s' */ |
1318 | warning(10, "const"); | | 1320 | warning(10, "const"); |
1319 | } | | 1321 | } |
1320 | p1->p_const = true; | | 1322 | p1->p_const = true; |
1321 | } | | 1323 | } |
1322 | if (p2->p_volatile) { | | 1324 | if (p2->p_volatile) { |
1323 | if (p1->p_volatile) { | | 1325 | if (p1->p_volatile) { |
1324 | /* duplicate '%s' */ | | 1326 | /* duplicate '%s' */ |
1325 | warning(10, "volatile"); | | 1327 | warning(10, "volatile"); |
1326 | } | | 1328 | } |
1327 | p1->p_volatile = true; | | 1329 | p1->p_volatile = true; |
1328 | } | | 1330 | } |
1329 | free(p2); | | 1331 | free(p2); |
1330 | return p1; | | 1332 | return p1; |
1331 | } | | 1333 | } |
1332 | | | 1334 | |
1333 | /* | | 1335 | /* |
1334 | * The following 3 functions extend the type of a declarator with | | 1336 | * The following 3 functions extend the type of a declarator with |
1335 | * pointer, function and array types. | | 1337 | * pointer, function and array types. |
1336 | * | | 1338 | * |
1337 | * The current type is the type built by end_type() (dcs->d_type) and | | 1339 | * The current type is the type built by end_type() (dcs->d_type) and |
1338 | * pointer, function and array types already added for this | | 1340 | * pointer, function and array types already added for this |
1339 | * declarator. The new type extension is inserted between both. | | 1341 | * declarator. The new type extension is inserted between both. |
1340 | */ | | 1342 | */ |
1341 | sym_t * | | 1343 | sym_t * |
1342 | add_pointer(sym_t *decl, qual_ptr *p) | | 1344 | add_pointer(sym_t *decl, qual_ptr *p) |
1343 | { | | 1345 | { |
1344 | type_t **tpp, *tp; | | 1346 | type_t **tpp, *tp; |
1345 | qual_ptr *next; | | 1347 | qual_ptr *next; |
1346 | | | 1348 | |
1347 | tpp = &decl->s_type; | | 1349 | tpp = &decl->s_type; |
1348 | while (*tpp != NULL && *tpp != dcs->d_type) | | 1350 | while (*tpp != NULL && *tpp != dcs->d_type) |
1349 | tpp = &(*tpp)->t_subt; | | 1351 | tpp = &(*tpp)->t_subt; |
1350 | if (*tpp == NULL) | | 1352 | if (*tpp == NULL) |
1351 | return decl; | | 1353 | return decl; |
1352 | | | 1354 | |
1353 | while (p != NULL) { | | 1355 | while (p != NULL) { |
1354 | *tpp = tp = getblk(sizeof(*tp)); | | 1356 | *tpp = tp = getblk(sizeof(*tp)); |
1355 | tp->t_tspec = PTR; | | 1357 | tp->t_tspec = PTR; |
1356 | tp->t_const = p->p_const; | | 1358 | tp->t_const = p->p_const; |
1357 | tp->t_volatile = p->p_volatile; | | 1359 | tp->t_volatile = p->p_volatile; |
1358 | *(tpp = &tp->t_subt) = dcs->d_type; | | 1360 | *(tpp = &tp->t_subt) = dcs->d_type; |
1359 | next = p->p_next; | | 1361 | next = p->p_next; |
1360 | free(p); | | 1362 | free(p); |
1361 | p = next; | | 1363 | p = next; |
1362 | } | | 1364 | } |
1363 | return decl; | | 1365 | return decl; |
1364 | } | | 1366 | } |
1365 | | | 1367 | |
1366 | /* | | 1368 | /* |
1367 | * If a dimension was specified, dim is true, otherwise false | | 1369 | * If a dimension was specified, dim is true, otherwise false |
1368 | * n is the specified dimension | | 1370 | * n is the specified dimension |
1369 | */ | | 1371 | */ |
1370 | sym_t * | | 1372 | sym_t * |
1371 | add_array(sym_t *decl, bool dim, int n) | | 1373 | add_array(sym_t *decl, bool dim, int n) |
1372 | { | | 1374 | { |
1373 | type_t **tpp, *tp; | | 1375 | type_t **tpp, *tp; |
1374 | | | 1376 | |
1375 | tpp = &decl->s_type; | | 1377 | tpp = &decl->s_type; |
1376 | while (*tpp != NULL && *tpp != dcs->d_type) | | 1378 | while (*tpp != NULL && *tpp != dcs->d_type) |
1377 | tpp = &(*tpp)->t_subt; | | 1379 | tpp = &(*tpp)->t_subt; |
1378 | if (*tpp == NULL) | | 1380 | if (*tpp == NULL) |
1379 | return decl; | | 1381 | return decl; |
1380 | | | 1382 | |
1381 | *tpp = tp = getblk(sizeof(*tp)); | | 1383 | *tpp = tp = getblk(sizeof(*tp)); |
1382 | tp->t_tspec = ARRAY; | | 1384 | tp->t_tspec = ARRAY; |
1383 | tp->t_subt = dcs->d_type; | | 1385 | tp->t_subt = dcs->d_type; |
1384 | tp->t_dim = n; | | 1386 | tp->t_dim = n; |
1385 | | | 1387 | |
1386 | if (n < 0) { | | 1388 | if (n < 0) { |
1387 | /* negative array dimension (%d) */ | | 1389 | /* negative array dimension (%d) */ |
1388 | error(20, n); | | 1390 | error(20, n); |
1389 | n = 0; | | 1391 | n = 0; |
1390 | } else if (n == 0 && dim) { | | 1392 | } else if (n == 0 && dim) { |
1391 | /* zero sized array is a C99 extension */ | | 1393 | /* zero sized array is a C99 extension */ |
1392 | c99ism(322); | | 1394 | c99ism(322); |
1393 | } else if (n == 0 && !dim) { | | 1395 | } else if (n == 0 && !dim) { |
1394 | setcomplete(tp, false); | | 1396 | setcomplete(tp, false); |
1395 | } | | 1397 | } |
1396 | | | 1398 | |
1397 | return decl; | | 1399 | return decl; |
1398 | } | | 1400 | } |
1399 | | | 1401 | |
1400 | sym_t * | | 1402 | sym_t * |
1401 | add_function(sym_t *decl, sym_t *args) | | 1403 | add_function(sym_t *decl, sym_t *args) |
1402 | { | | 1404 | { |
1403 | type_t **tpp, *tp; | | 1405 | type_t **tpp, *tp; |
1404 | | | 1406 | |
1405 | if (dcs->d_proto) { | | 1407 | if (dcs->d_proto) { |
1406 | if (tflag) | | 1408 | if (tflag) |
1407 | /* function prototypes are illegal in traditional C */ | | 1409 | /* function prototypes are illegal in traditional C */ |
1408 | warning(270); | | 1410 | warning(270); |
1409 | args = new_style_function(decl, args); | | 1411 | args = new_style_function(decl, args); |
1410 | } else { | | 1412 | } else { |
1411 | old_style_function(decl, args); | | 1413 | old_style_function(decl, args); |
1412 | } | | 1414 | } |
1413 | | | 1415 | |
1414 | /* | | 1416 | /* |
1415 | * The symbols are removed from the symbol table by | | 1417 | * The symbols are removed from the symbol table by |
1416 | * end_declaration_level after add_function. To be able to restore | | 1418 | * end_declaration_level after add_function. To be able to restore |
1417 | * them if this is a function definition, a pointer to the list of all | | 1419 | * them if this is a function definition, a pointer to the list of all |
1418 | * symbols is stored in dcs->d_next->d_func_proto_syms. Also a list of | | 1420 | * symbols is stored in dcs->d_next->d_func_proto_syms. Also a list of |
1419 | * the arguments (concatenated by s_next) is stored in | | 1421 | * the arguments (concatenated by s_next) is stored in |
1420 | * dcs->d_next->d_func_args. (dcs->d_next must be used because *dcs is | | 1422 | * dcs->d_next->d_func_args. (dcs->d_next must be used because *dcs is |
1421 | * the declaration stack element created for the list of params and is | | 1423 | * the declaration stack element created for the list of params and is |
1422 | * removed after add_function.) | | 1424 | * removed after add_function.) |
1423 | */ | | 1425 | */ |
1424 | if (dcs->d_next->d_ctx == EXTERN && | | 1426 | if (dcs->d_next->d_ctx == EXTERN && |
1425 | decl->s_type == dcs->d_next->d_type) { | | 1427 | decl->s_type == dcs->d_next->d_type) { |
1426 | dcs->d_next->d_func_proto_syms = dcs->d_dlsyms; | | 1428 | dcs->d_next->d_func_proto_syms = dcs->d_dlsyms; |
1427 | dcs->d_next->d_func_args = args; | | 1429 | dcs->d_next->d_func_args = args; |
1428 | } | | 1430 | } |
1429 | | | 1431 | |
1430 | tpp = &decl->s_type; | | 1432 | tpp = &decl->s_type; |
1431 | while (*tpp != NULL && *tpp != dcs->d_next->d_type) | | 1433 | while (*tpp != NULL && *tpp != dcs->d_next->d_type) |
1432 | tpp = &(*tpp)->t_subt; | | 1434 | tpp = &(*tpp)->t_subt; |
1433 | if (*tpp == NULL) | | 1435 | if (*tpp == NULL) |
1434 | return decl; | | 1436 | return decl; |
1435 | | | 1437 | |
1436 | *tpp = tp = getblk(sizeof(*tp)); | | 1438 | *tpp = tp = getblk(sizeof(*tp)); |
1437 | tp->t_tspec = FUNC; | | 1439 | tp->t_tspec = FUNC; |
1438 | tp->t_subt = dcs->d_next->d_type; | | 1440 | tp->t_subt = dcs->d_next->d_type; |
1439 | if ((tp->t_proto = dcs->d_proto) != false) | | 1441 | if ((tp->t_proto = dcs->d_proto) != false) |
1440 | tp->t_args = args; | | 1442 | tp->t_args = args; |
1441 | tp->t_vararg = dcs->d_vararg; | | 1443 | tp->t_vararg = dcs->d_vararg; |
1442 | | | 1444 | |
1443 | return decl; | | 1445 | return decl; |
1444 | } | | 1446 | } |
1445 | | | 1447 | |
1446 | /* | | 1448 | /* |
1447 | * Called for new style function declarations. | | 1449 | * Called for new style function declarations. |
1448 | */ | | 1450 | */ |
1449 | /* ARGSUSED */ | | 1451 | /* ARGSUSED */ |
1450 | static sym_t * | | 1452 | static sym_t * |
1451 | new_style_function(sym_t *decl, sym_t *args) | | 1453 | new_style_function(sym_t *decl, sym_t *args) |
1452 | { | | 1454 | { |
1453 | sym_t *arg, *sym; | | 1455 | sym_t *arg, *sym; |
1454 | scl_t sc; | | 1456 | scl_t sc; |
1455 | int n; | | 1457 | int n; |
1456 | | | 1458 | |
1457 | /* | | 1459 | /* |
1458 | * Declarations of structs/unions/enums in param lists are legal, | | 1460 | * Declarations of structs/unions/enums in param lists are legal, |
1459 | * but senseless. | | 1461 | * but senseless. |
1460 | */ | | 1462 | */ |
1461 | for (sym = dcs->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) { | | 1463 | for (sym = dcs->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) { |
1462 | sc = sym->s_scl; | | 1464 | sc = sym->s_scl; |
1463 | if (sc == STRUCT_TAG || sc == UNION_TAG || sc == ENUM_TAG) { | | 1465 | if (sc == STRUCT_TAG || sc == UNION_TAG || sc == ENUM_TAG) { |
1464 | /* dubious tag declaration: %s %s */ | | 1466 | /* dubious tag declaration: %s %s */ |
1465 | warning(85, storage_class_name(sc), sym->s_name); | | 1467 | warning(85, storage_class_name(sc), sym->s_name); |
1466 | } | | 1468 | } |
1467 | } | | 1469 | } |
1468 | | | 1470 | |
1469 | n = 1; | | 1471 | n = 1; |
1470 | for (arg = args; arg != NULL; arg = arg->s_next) { | | 1472 | for (arg = args; arg != NULL; arg = arg->s_next) { |
1471 | if (arg->s_type->t_tspec == VOID) { | | 1473 | if (arg->s_type->t_tspec == VOID) { |
1472 | if (n > 1 || arg->s_next != NULL) { | | 1474 | if (n > 1 || arg->s_next != NULL) { |
1473 | /* void must be sole parameter */ | | 1475 | /* void must be sole parameter */ |
1474 | error(60); | | 1476 | error(60); |
1475 | arg->s_type = gettyp(INT); | | 1477 | arg->s_type = gettyp(INT); |
1476 | } | | 1478 | } |
1477 | } | | 1479 | } |
1478 | n++; | | 1480 | n++; |
1479 | } | | 1481 | } |
1480 | | | 1482 | |
1481 | /* return NULL if first param is VOID */ | | 1483 | /* return NULL if first param is VOID */ |
1482 | return args != NULL && args->s_type->t_tspec != VOID ? args : NULL; | | 1484 | return args != NULL && args->s_type->t_tspec != VOID ? args : NULL; |
1483 | } | | 1485 | } |
1484 | | | 1486 | |
1485 | /* | | 1487 | /* |
1486 | * Called for old style function declarations. | | 1488 | * Called for old style function declarations. |
1487 | */ | | 1489 | */ |
1488 | static void | | 1490 | static void |
1489 | old_style_function(sym_t *decl, sym_t *args) | | 1491 | old_style_function(sym_t *decl, sym_t *args) |
1490 | { | | 1492 | { |
1491 | | | 1493 | |
1492 | /* | | 1494 | /* |
1493 | * Remember list of params only if this is really seams to be | | 1495 | * Remember list of params only if this is really seams to be |
1494 | * a function definition. | | 1496 | * a function definition. |
1495 | */ | | 1497 | */ |
1496 | if (dcs->d_next->d_ctx == EXTERN && | | 1498 | if (dcs->d_next->d_ctx == EXTERN && |
1497 | decl->s_type == dcs->d_next->d_type) { | | 1499 | decl->s_type == dcs->d_next->d_type) { |
1498 | /* | | 1500 | /* |
1499 | * We assume that this becomes a function definition. If | | 1501 | * We assume that this becomes a function definition. If |
1500 | * we are wrong, it's corrected in check_function_definition(). | | 1502 | * we are wrong, it's corrected in check_function_definition(). |
1501 | */ | | 1503 | */ |
1502 | if (args != NULL) { | | 1504 | if (args != NULL) { |
1503 | decl->s_osdef = true; | | 1505 | decl->s_osdef = true; |
1504 | decl->s_args = args; | | 1506 | decl->s_args = args; |
1505 | } | | 1507 | } |
1506 | } else { | | 1508 | } else { |
1507 | if (args != NULL) | | 1509 | if (args != NULL) |
1508 | /* function prototype parameters must have types */ | | 1510 | /* function prototype parameters must have types */ |
1509 | warning(62); | | 1511 | warning(62); |
1510 | } | | 1512 | } |
1511 | } | | 1513 | } |
1512 | | | 1514 | |
1513 | /* | | 1515 | /* |
1514 | * Lists of identifiers in functions declarations are allowed only if | | 1516 | * Lists of identifiers in functions declarations are allowed only if |
1515 | * it's also a function definition. If this is not the case, print an | | 1517 | * it's also a function definition. If this is not the case, print an |
1516 | * error message. | | 1518 | * error message. |
1517 | */ | | 1519 | */ |
1518 | void | | 1520 | void |
1519 | check_function_definition(sym_t *sym, bool msg) | | 1521 | check_function_definition(sym_t *sym, bool msg) |
1520 | { | | 1522 | { |
1521 | | | 1523 | |
1522 | if (sym->s_osdef) { | | 1524 | if (sym->s_osdef) { |
1523 | if (msg) { | | 1525 | if (msg) { |
1524 | /* incomplete or misplaced function definition */ | | 1526 | /* incomplete or misplaced function definition */ |
1525 | error(22); | | 1527 | error(22); |
1526 | } | | 1528 | } |
1527 | sym->s_osdef = false; | | 1529 | sym->s_osdef = false; |
1528 | sym->s_args = NULL; | | 1530 | sym->s_args = NULL; |
1529 | } | | 1531 | } |
1530 | } | | 1532 | } |
1531 | | | 1533 | |
1532 | /* | | 1534 | /* |
1533 | * Process the name in a declarator. | | 1535 | * Process the name in a declarator. |
1534 | * The symbol gets one of the storage classes EXTERN, STATIC, AUTO or | | 1536 | * The symbol gets one of the storage classes EXTERN, STATIC, AUTO or |
1535 | * TYPEDEF. | | 1537 | * TYPEDEF. |
1536 | * s_def and s_reg are valid after declarator_name(). | | 1538 | * s_def and s_reg are valid after declarator_name(). |
1537 | */ | | 1539 | */ |
1538 | sym_t * | | 1540 | sym_t * |
1539 | declarator_name(sym_t *sym) | | 1541 | declarator_name(sym_t *sym) |
1540 | { | | 1542 | { |
1541 | scl_t sc = NOSCL; | | 1543 | scl_t sc = NOSCL; |
1542 | | | 1544 | |
1543 | if (sym->s_scl == NOSCL) { | | 1545 | if (sym->s_scl == NOSCL) { |
1544 | dcs->d_redeclared_symbol = NULL; | | 1546 | dcs->d_redeclared_symbol = NULL; |
1545 | } else if (sym->s_defarg) { | | 1547 | } else if (sym->s_defarg) { |
1546 | sym->s_defarg = false; | | 1548 | sym->s_defarg = false; |
1547 | dcs->d_redeclared_symbol = NULL; | | 1549 | dcs->d_redeclared_symbol = NULL; |
1548 | } else { | | 1550 | } else { |
1549 | dcs->d_redeclared_symbol = sym; | | 1551 | dcs->d_redeclared_symbol = sym; |
1550 | sym = pushdown(sym); | | 1552 | sym = pushdown(sym); |
1551 | } | | 1553 | } |
1552 | | | 1554 | |
1553 | switch (dcs->d_ctx) { | | 1555 | switch (dcs->d_ctx) { |
1554 | case MOS: | | 1556 | case MOS: |
1555 | case MOU: | | 1557 | case MOU: |
1556 | /* Set parent */ | | 1558 | /* Set parent */ |
1557 | sym->s_styp = dcs->d_tagtyp->t_str; | | 1559 | sym->s_styp = dcs->d_tagtyp->t_str; |
1558 | sym->s_def = DEF; | | 1560 | sym->s_def = DEF; |
1559 | sym->s_value.v_tspec = INT; | | 1561 | sym->s_value.v_tspec = INT; |
1560 | sc = dcs->d_ctx; | | 1562 | sc = dcs->d_ctx; |
1561 | break; | | 1563 | break; |
1562 | case EXTERN: | | 1564 | case EXTERN: |
1563 | /* | | 1565 | /* |
1564 | * static and external symbols without "extern" are | | 1566 | * static and external symbols without "extern" are |
1565 | * considered to be tentative defined, external | | 1567 | * considered to be tentative defined, external |
1566 | * symbols with "extern" are declared, and typedef names | | 1568 | * symbols with "extern" are declared, and typedef names |
1567 | * are defined. Tentative defined and declared symbols | | 1569 | * are defined. Tentative defined and declared symbols |
1568 | * may become defined if an initializer is present or | | 1570 | * may become defined if an initializer is present or |
1569 | * this is a function definition. | | 1571 | * this is a function definition. |
1570 | */ | | 1572 | */ |
1571 | if ((sc = dcs->d_scl) == NOSCL) { | | 1573 | if ((sc = dcs->d_scl) == NOSCL) { |
1572 | sc = EXTERN; | | 1574 | sc = EXTERN; |
1573 | sym->s_def = TDEF; | | 1575 | sym->s_def = TDEF; |
1574 | } else if (sc == STATIC) { | | 1576 | } else if (sc == STATIC) { |
1575 | sym->s_def = TDEF; | | 1577 | sym->s_def = TDEF; |
1576 | } else if (sc == TYPEDEF) { | | 1578 | } else if (sc == TYPEDEF) { |
1577 | sym->s_def = DEF; | | 1579 | sym->s_def = DEF; |
1578 | } else { | | 1580 | } else { |
1579 | lint_assert(sc == EXTERN); | | 1581 | lint_assert(sc == EXTERN); |
1580 | sym->s_def = DECL; | | 1582 | sym->s_def = DECL; |
1581 | } | | 1583 | } |
1582 | break; | | 1584 | break; |
1583 | case PROTO_ARG: | | 1585 | case PROTO_ARG: |
1584 | sym->s_arg = true; | | 1586 | sym->s_arg = true; |
1585 | /* FALLTHROUGH */ | | 1587 | /* FALLTHROUGH */ |
1586 | case ARG: | | 1588 | case ARG: |
1587 | if ((sc = dcs->d_scl) == NOSCL) { | | 1589 | if ((sc = dcs->d_scl) == NOSCL) { |
1588 | sc = AUTO; | | 1590 | sc = AUTO; |
1589 | } else { | | 1591 | } else { |
1590 | lint_assert(sc == REG); | | 1592 | lint_assert(sc == REG); |
1591 | sym->s_reg = true; | | 1593 | sym->s_reg = true; |
1592 | sc = AUTO; | | 1594 | sc = AUTO; |
1593 | } | | 1595 | } |
1594 | sym->s_def = DEF; | | 1596 | sym->s_def = DEF; |
1595 | break; | | 1597 | break; |
1596 | case AUTO: | | 1598 | case AUTO: |
1597 | if ((sc = dcs->d_scl) == NOSCL) { | | 1599 | if ((sc = dcs->d_scl) == NOSCL) { |
1598 | /* | | 1600 | /* |
1599 | * XXX somewhat ugly because we dont know whether | | 1601 | * XXX somewhat ugly because we dont know whether |
1600 | * this is AUTO or EXTERN (functions). If we are | | 1602 | * this is AUTO or EXTERN (functions). If we are |
1601 | * wrong it must be corrected in declare_local(), | | 1603 | * wrong it must be corrected in declare_local(), |
1602 | * where we have the necessary type information. | | 1604 | * where we have the necessary type information. |
1603 | */ | | 1605 | */ |
1604 | sc = AUTO; | | 1606 | sc = AUTO; |
1605 | sym->s_def = DEF; | | 1607 | sym->s_def = DEF; |
1606 | } else if (sc == AUTO || sc == STATIC || sc == TYPEDEF) { | | 1608 | } else if (sc == AUTO || sc == STATIC || sc == TYPEDEF) { |
1607 | sym->s_def = DEF; | | 1609 | sym->s_def = DEF; |
1608 | } else if (sc == REG) { | | 1610 | } else if (sc == REG) { |
1609 | sym->s_reg = true; | | 1611 | sym->s_reg = true; |
1610 | sc = AUTO; | | 1612 | sc = AUTO; |
1611 | sym->s_def = DEF; | | 1613 | sym->s_def = DEF; |
1612 | } else { | | 1614 | } else { |
1613 | lint_assert(sc == EXTERN); | | 1615 | lint_assert(sc == EXTERN); |
1614 | sym->s_def = DECL; | | 1616 | sym->s_def = DECL; |
1615 | } | | 1617 | } |
1616 | break; | | 1618 | break; |
1617 | default: | | 1619 | default: |
1618 | lint_assert(/*CONSTCOND*/false); | | 1620 | lint_assert(/*CONSTCOND*/false); |
1619 | } | | 1621 | } |
1620 | sym->s_scl = sc; | | 1622 | sym->s_scl = sc; |
1621 | | | 1623 | |
1622 | sym->s_type = dcs->d_type; | | 1624 | sym->s_type = dcs->d_type; |
1623 | | | 1625 | |
1624 | dcs->d_func_proto_syms = NULL; | | 1626 | dcs->d_func_proto_syms = NULL; |
1625 | | | 1627 | |
1626 | return sym; | | 1628 | return sym; |
1627 | } | | 1629 | } |
1628 | | | 1630 | |
1629 | /* | | 1631 | /* |
1630 | * Process a name in the list of formal parameters in an old style function | | 1632 | * Process a name in the list of formal parameters in an old style function |
1631 | * definition. | | 1633 | * definition. |
1632 | */ | | 1634 | */ |
1633 | sym_t * | | 1635 | sym_t * |
1634 | old_style_function_name(sym_t *sym) | | 1636 | old_style_function_name(sym_t *sym) |
1635 | { | | 1637 | { |
1636 | | | 1638 | |
1637 | if (sym->s_scl != NOSCL) { | | 1639 | if (sym->s_scl != NOSCL) { |
1638 | if (block_level == sym->s_block_level) { | | 1640 | if (block_level == sym->s_block_level) { |
1639 | /* redeclaration of formal parameter %s */ | | 1641 | /* redeclaration of formal parameter %s */ |
1640 | error(21, sym->s_name); | | 1642 | error(21, sym->s_name); |
1641 | lint_assert(sym->s_defarg); | | 1643 | lint_assert(sym->s_defarg); |
1642 | } | | 1644 | } |
1643 | sym = pushdown(sym); | | 1645 | sym = pushdown(sym); |
1644 | } | | 1646 | } |
1645 | sym->s_type = gettyp(INT); | | 1647 | sym->s_type = gettyp(INT); |
1646 | sym->s_scl = AUTO; | | 1648 | sym->s_scl = AUTO; |
1647 | sym->s_def = DEF; | | 1649 | sym->s_def = DEF; |
1648 | sym->s_defarg = sym->s_arg = true; | | 1650 | sym->s_defarg = sym->s_arg = true; |
1649 | return sym; | | 1651 | return sym; |
1650 | } | | 1652 | } |
1651 | | | 1653 | |
1652 | /* | | 1654 | /* |
1653 | * Create the type of a tag. | | 1655 | * Create the type of a tag. |
1654 | * | | 1656 | * |
1655 | * tag points to the symbol table entry of the tag | | 1657 | * tag points to the symbol table entry of the tag |
1656 | * kind is the kind of the tag (STRUCT/UNION/ENUM) | | 1658 | * kind is the kind of the tag (STRUCT/UNION/ENUM) |
1657 | * decl is true if the type of the tag will be completed in this declaration | | 1659 | * decl is true if the type of the tag will be completed in this declaration |
1658 | * (the following token is T_LBRACE) | | 1660 | * (the following token is T_LBRACE) |
1659 | * semi is true if the following token is T_SEMI | | 1661 | * semi is true if the following token is T_SEMI |
1660 | */ | | 1662 | */ |
1661 | type_t * | | 1663 | type_t * |
1662 | mktag(sym_t *tag, tspec_t kind, bool decl, bool semi) | | 1664 | mktag(sym_t *tag, tspec_t kind, bool decl, bool semi) |
1663 | { | | 1665 | { |
1664 | scl_t scl; | | 1666 | scl_t scl; |
1665 | type_t *tp; | | 1667 | type_t *tp; |
1666 | | | 1668 | |
1667 | if (kind == STRUCT) { | | 1669 | if (kind == STRUCT) { |
1668 | scl = STRUCT_TAG; | | 1670 | scl = STRUCT_TAG; |
1669 | } else if (kind == UNION) { | | 1671 | } else if (kind == UNION) { |
1670 | scl = UNION_TAG; | | 1672 | scl = UNION_TAG; |
1671 | } else { | | 1673 | } else { |
1672 | lint_assert(kind == ENUM); | | 1674 | lint_assert(kind == ENUM); |
1673 | scl = ENUM_TAG; | | 1675 | scl = ENUM_TAG; |
1674 | } | | 1676 | } |
1675 | | | 1677 | |
1676 | if (tag != NULL) { | | 1678 | if (tag != NULL) { |
1677 | if (tag->s_scl != NOSCL) { | | 1679 | if (tag->s_scl != NOSCL) { |
1678 | tag = newtag(tag, scl, decl, semi); | | 1680 | tag = newtag(tag, scl, decl, semi); |
1679 | } else { | | 1681 | } else { |
1680 | /* a new tag, no empty declaration */ | | 1682 | /* a new tag, no empty declaration */ |
1681 | dcs->d_next->d_nonempty_decl = true; | | 1683 | dcs->d_next->d_nonempty_decl = true; |
1682 | if (scl == ENUM_TAG && !decl) { | | 1684 | if (scl == ENUM_TAG && !decl) { |
1683 | if (!tflag && (sflag || pflag)) | | 1685 | if (!tflag && (sflag || pflag)) |
1684 | /* forward reference to enum type */ | | 1686 | /* forward reference to enum type */ |
1685 | warning(42); | | 1687 | warning(42); |
1686 | } | | 1688 | } |
1687 | } | | 1689 | } |
1688 | if (tag->s_scl == NOSCL) { | | 1690 | if (tag->s_scl == NOSCL) { |
1689 | tag->s_scl = scl; | | 1691 | tag->s_scl = scl; |
1690 | tag->s_type = tp = getblk(sizeof(*tp)); | | 1692 | tag->s_type = tp = getblk(sizeof(*tp)); |
1691 | tp->t_packed = dcs->d_packed; | | 1693 | tp->t_packed = dcs->d_packed; |
1692 | } else { | | 1694 | } else { |
1693 | tp = tag->s_type; | | 1695 | tp = tag->s_type; |
1694 | } | | 1696 | } |
1695 | } else { | | 1697 | } else { |
1696 | tag = getblk(sizeof(*tag)); | | 1698 | tag = getblk(sizeof(*tag)); |
1697 | tag->s_name = unnamed; | | 1699 | tag->s_name = unnamed; |
1698 | UNIQUE_CURR_POS(tag->s_def_pos); | | 1700 | UNIQUE_CURR_POS(tag->s_def_pos); |
1699 | tag->s_kind = FTAG; | | 1701 | tag->s_kind = FTAG; |
1700 | tag->s_scl = scl; | | 1702 | tag->s_scl = scl; |
1701 | tag->s_block_level = -1; | | 1703 | tag->s_block_level = -1; |
1702 | tag->s_type = tp = getblk(sizeof(*tp)); | | 1704 | tag->s_type = tp = getblk(sizeof(*tp)); |
1703 | tp->t_packed = dcs->d_packed; | | 1705 | tp->t_packed = dcs->d_packed; |
1704 | dcs->d_next->d_nonempty_decl = true; | | 1706 | dcs->d_next->d_nonempty_decl = true; |
1705 | } | | 1707 | } |
1706 | | | 1708 | |
1707 | if (tp->t_tspec == NOTSPEC) { | | 1709 | if (tp->t_tspec == NOTSPEC) { |
1708 | tp->t_tspec = kind; | | 1710 | tp->t_tspec = kind; |
1709 | if (kind != ENUM) { | | 1711 | if (kind != ENUM) { |
1710 | tp->t_str = getblk(sizeof(*tp->t_str)); | | 1712 | tp->t_str = getblk(sizeof(*tp->t_str)); |
1711 | tp->t_str->sou_align_in_bits = CHAR_SIZE; | | 1713 | tp->t_str->sou_align_in_bits = CHAR_SIZE; |
1712 | tp->t_str->sou_tag = tag; | | 1714 | tp->t_str->sou_tag = tag; |
1713 | } else { | | 1715 | } else { |
1714 | tp->t_is_enum = true; | | 1716 | tp->t_is_enum = true; |
1715 | tp->t_enum = getblk(sizeof(*tp->t_enum)); | | 1717 | tp->t_enum = getblk(sizeof(*tp->t_enum)); |
1716 | tp->t_enum->en_tag = tag; | | 1718 | tp->t_enum->en_tag = tag; |
1717 | } | | 1719 | } |
1718 | setcomplete(tp, false); | | 1720 | setcomplete(tp, false); |
1719 | } | | 1721 | } |
1720 | return tp; | | 1722 | return tp; |
1721 | } | | 1723 | } |
1722 | | | 1724 | |
1723 | /* | | 1725 | /* |
1724 | * Checks all possible cases of tag redeclarations. | | 1726 | * Checks all possible cases of tag redeclarations. |
1725 | * decl is true if T_LBRACE follows | | 1727 | * decl is true if T_LBRACE follows |
1726 | * semi is true if T_SEMI follows | | 1728 | * semi is true if T_SEMI follows |
1727 | */ | | 1729 | */ |
1728 | static sym_t * | | 1730 | static sym_t * |
1729 | newtag(sym_t *tag, scl_t scl, bool decl, bool semi) | | 1731 | newtag(sym_t *tag, scl_t scl, bool decl, bool semi) |
1730 | { | | 1732 | { |
1731 | | | 1733 | |
1732 | if (tag->s_block_level < block_level) { | | 1734 | if (tag->s_block_level < block_level) { |
1733 | if (semi) { | | 1735 | if (semi) { |
1734 | /* "struct a;" */ | | 1736 | /* "struct a;" */ |
1735 | if (!tflag) { | | 1737 | if (!tflag) { |
1736 | if (!sflag) | | 1738 | if (!sflag) |
1737 | /* decl. introduces new type ... */ | | 1739 | /* decl. introduces new type ... */ |
1738 | warning(44, storage_class_name(scl), | | 1740 | warning(44, storage_class_name(scl), |
1739 | tag->s_name); | | 1741 | tag->s_name); |
1740 | tag = pushdown(tag); | | 1742 | tag = pushdown(tag); |
1741 | } else if (tag->s_scl != scl) { | | 1743 | } else if (tag->s_scl != scl) { |
1742 | /* base type is really '%s %s' */ | | 1744 | /* base type is really '%s %s' */ |
1743 | warning(45, storage_class_name(tag->s_scl), | | 1745 | warning(45, storage_class_name(tag->s_scl), |
1744 | tag->s_name); | | 1746 | tag->s_name); |
1745 | } | | 1747 | } |
1746 | dcs->d_next->d_nonempty_decl = true; | | 1748 | dcs->d_next->d_nonempty_decl = true; |
1747 | } else if (decl) { | | 1749 | } else if (decl) { |
1748 | /* "struct a { ... } " */ | | 1750 | /* "struct a { ... } " */ |
1749 | if (hflag) | | 1751 | if (hflag) |
1750 | /* redefinition hides earlier one: %s */ | | 1752 | /* redefinition hides earlier one: %s */ |
1751 | warning(43, tag->s_name); | | 1753 | warning(43, tag->s_name); |
1752 | tag = pushdown(tag); | | 1754 | tag = pushdown(tag); |
1753 | dcs->d_next->d_nonempty_decl = true; | | 1755 | dcs->d_next->d_nonempty_decl = true; |
1754 | } else if (tag->s_scl != scl) { | | 1756 | } else if (tag->s_scl != scl) { |
1755 | /* base type is really '%s %s' */ | | 1757 | /* base type is really '%s %s' */ |
1756 | warning(45, storage_class_name(tag->s_scl), | | 1758 | warning(45, storage_class_name(tag->s_scl), |
1757 | tag->s_name); | | 1759 | tag->s_name); |
1758 | /* declaration introduces new type in ANSI C: %s %s */ | | 1760 | /* declaration introduces new type in ANSI C: %s %s */ |
1759 | if (!sflag) { | | 1761 | if (!sflag) { |
1760 | /* decl. introduces new type in ANSI C: %s %s */ | | 1762 | /* decl. introduces new type in ANSI C: %s %s */ |
1761 | warning(44, storage_class_name(scl), | | 1763 | warning(44, storage_class_name(scl), |
1762 | tag->s_name); | | 1764 | tag->s_name); |
1763 | } | | 1765 | } |
1764 | tag = pushdown(tag); | | 1766 | tag = pushdown(tag); |
1765 | dcs->d_next->d_nonempty_decl = true; | | 1767 | dcs->d_next->d_nonempty_decl = true; |
1766 | } | | 1768 | } |
1767 | } else { | | 1769 | } else { |
1768 | if (tag->s_scl != scl) { | | 1770 | if (tag->s_scl != scl) { |
1769 | /* (%s) tag redeclared */ | | 1771 | /* (%s) tag redeclared */ |
1770 | error(46, storage_class_name(tag->s_scl)); | | 1772 | error(46, storage_class_name(tag->s_scl)); |
1771 | print_previous_declaration(-1, tag); | | 1773 | print_previous_declaration(-1, tag); |
1772 | tag = pushdown(tag); | | 1774 | tag = pushdown(tag); |
1773 | dcs->d_next->d_nonempty_decl = true; | | 1775 | dcs->d_next->d_nonempty_decl = true; |
1774 | } else if (decl && !is_incomplete(tag->s_type)) { | | 1776 | } else if (decl && !is_incomplete(tag->s_type)) { |
1775 | /* (%s) tag redeclared */ | | 1777 | /* (%s) tag redeclared */ |
1776 | error(46, storage_class_name(tag->s_scl)); | | 1778 | error(46, storage_class_name(tag->s_scl)); |
1777 | print_previous_declaration(-1, tag); | | 1779 | print_previous_declaration(-1, tag); |
1778 | tag = pushdown(tag); | | 1780 | tag = pushdown(tag); |
1779 | dcs->d_next->d_nonempty_decl = true; | | 1781 | dcs->d_next->d_nonempty_decl = true; |
1780 | } else if (semi || decl) { | | 1782 | } else if (semi || decl) { |
1781 | dcs->d_next->d_nonempty_decl = true; | | 1783 | dcs->d_next->d_nonempty_decl = true; |
1782 | } | | 1784 | } |
1783 | } | | 1785 | } |
1784 | return tag; | | 1786 | return tag; |
1785 | } | | 1787 | } |
1786 | | | 1788 | |
1787 | const char * | | 1789 | const char * |
1788 | storage_class_name(scl_t sc) | | 1790 | storage_class_name(scl_t sc) |
1789 | { | | 1791 | { |
1790 | switch (sc) { | | 1792 | switch (sc) { |
1791 | case EXTERN: return "extern"; | | 1793 | case EXTERN: return "extern"; |
1792 | case STATIC: return "static"; | | 1794 | case STATIC: return "static"; |
1793 | case AUTO: return "auto"; | | 1795 | case AUTO: return "auto"; |
1794 | case REG: return "register"; | | 1796 | case REG: return "register"; |
1795 | case TYPEDEF: return "typedef"; | | 1797 | case TYPEDEF: return "typedef"; |
1796 | case STRUCT_TAG:return "struct"; | | 1798 | case STRUCT_TAG:return "struct"; |
1797 | case UNION_TAG: return "union"; | | 1799 | case UNION_TAG: return "union"; |
1798 | case ENUM_TAG: return "enum"; | | 1800 | case ENUM_TAG: return "enum"; |
1799 | default: lint_assert(/*CONSTCOND*/false); | | 1801 | default: lint_assert(/*CONSTCOND*/false); |
1800 | } | | 1802 | } |
1801 | } | | 1803 | } |
1802 | | | 1804 | |
1803 | /* | | 1805 | /* |
1804 | * tp points to the type of the tag, fmem to the list of members. | | 1806 | * tp points to the type of the tag, fmem to the list of members. |
1805 | */ | | 1807 | */ |
1806 | type_t * | | 1808 | type_t * |
1807 | complete_tag_struct_or_union(type_t *tp, sym_t *fmem) | | 1809 | complete_tag_struct_or_union(type_t *tp, sym_t *fmem) |
1808 | { | | 1810 | { |
1809 | tspec_t t; | | 1811 | tspec_t t; |
1810 | struct_or_union *sp; | | 1812 | struct_or_union *sp; |
1811 | int n; | | 1813 | int n; |
1812 | sym_t *mem; | | 1814 | sym_t *mem; |
1813 | | | 1815 | |
1814 | if (tp == NULL) /* in case of syntax errors */ | | 1816 | if (tp == NULL) /* in case of syntax errors */ |
1815 | return gettyp(INT); | | 1817 | return gettyp(INT); |
1816 | | | 1818 | |
1817 | setcomplete(tp, true); | | 1819 | setcomplete(tp, true); |
1818 | | | 1820 | |
1819 | t = tp->t_tspec; | | 1821 | t = tp->t_tspec; |
1820 | align(dcs->d_sou_align_in_bits, 0); | | 1822 | align(dcs->d_sou_align_in_bits, 0); |
1821 | sp = tp->t_str; | | 1823 | sp = tp->t_str; |
1822 | sp->sou_align_in_bits = dcs->d_sou_align_in_bits; | | 1824 | sp->sou_align_in_bits = dcs->d_sou_align_in_bits; |
1823 | sp->sou_first_member = fmem; | | 1825 | sp->sou_first_member = fmem; |
1824 | if (tp->t_packed) | | 1826 | if (tp->t_packed) |
1825 | setpackedsize(tp); | | 1827 | setpackedsize(tp); |
1826 | else | | 1828 | else |
1827 | sp->sou_size_in_bits = dcs->d_offset; | | 1829 | sp->sou_size_in_bits = dcs->d_offset; |
1828 | | | 1830 | |
1829 | if (sp->sou_size_in_bits == 0) { | | 1831 | if (sp->sou_size_in_bits == 0) { |
1830 | /* zero sized %s is a C9X feature */ | | 1832 | /* zero sized %s is a C9X feature */ |
1831 | c99ism(47, ttab[t].tt_name); | | 1833 | c99ism(47, ttab[t].tt_name); |