| @@ -1,1398 +1,1398 @@ | | | @@ -1,1398 +1,1398 @@ |
1 | /* $NetBSD: decl.c,v 1.100 2021/01/02 17:17:00 rillig Exp $ */ | | 1 | /* $NetBSD: decl.c,v 1.101 2021/01/02 18:06:01 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.100 2021/01/02 17:17:00 rillig Exp $"); | | 41 | __RCSID("$NetBSD: decl.c,v 1.101 2021/01/02 18:06:01 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 arithmtic types and void */ | | 53 | /* shared type structures for arithmtic 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, int, int); | | 69 | static sym_t *newtag(sym_t *, scl_t, int, int); |
70 | static int eqargs(type_t *, type_t *, int *); | | 70 | static int eqargs(type_t *, type_t *, int *); |
71 | static int mnoarg(type_t *, int *); | | 71 | static int mnoarg(type_t *, int *); |
72 | static int check_old_style_definition(sym_t *, sym_t *); | | 72 | static int check_old_style_definition(sym_t *, sym_t *); |
73 | static int check_prototype_declaration(sym_t *, sym_t *); | | 73 | static int 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 ledecl(sym_t *); | | 76 | static void ledecl(sym_t *); |
77 | static int check_init(sym_t *); | | 77 | static int check_init(sym_t *); |
78 | static void check_argument_usage(int, sym_t *); | | 78 | static void check_argument_usage(int, sym_t *); |
79 | static void check_variable_usage(int, sym_t *); | | 79 | static void check_variable_usage(int, 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(sym_t *); | | 82 | static void check_global_variable(sym_t *); |
83 | static void check_global_variable_size(sym_t *); | | 83 | static void check_global_variable_size(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 | initdecl(void) | | 89 | initdecl(void) |
90 | { | | 90 | { |
91 | int i; | | 91 | int i; |
92 | | | 92 | |
93 | /* declaration stack */ | | 93 | /* declaration stack */ |
94 | dcs = xcalloc(1, sizeof (dinfo_t)); | | 94 | dcs = xcalloc(1, sizeof (dinfo_t)); |
95 | dcs->d_ctx = EXTERN; | | 95 | dcs->d_ctx = EXTERN; |
96 | dcs->d_ldlsym = &dcs->d_dlsyms; | | 96 | dcs->d_ldlsym = &dcs->d_dlsyms; |
97 | | | 97 | |
98 | /* type information and classification */ | | 98 | /* type information and classification */ |
99 | inittyp(); | | 99 | inittyp(); |
100 | | | 100 | |
101 | /* shared type structures */ | | 101 | /* shared type structures */ |
102 | typetab = xcalloc(NTSPEC, sizeof (type_t)); | | 102 | typetab = xcalloc(NTSPEC, sizeof (type_t)); |
103 | for (i = 0; i < NTSPEC; i++) | | 103 | for (i = 0; i < NTSPEC; i++) |
104 | typetab[i].t_tspec = NOTSPEC; | | 104 | typetab[i].t_tspec = NOTSPEC; |
105 | typetab[BOOL].t_tspec = BOOL; | | 105 | typetab[BOOL].t_tspec = BOOL; |
106 | typetab[CHAR].t_tspec = CHAR; | | 106 | typetab[CHAR].t_tspec = CHAR; |
107 | typetab[SCHAR].t_tspec = SCHAR; | | 107 | typetab[SCHAR].t_tspec = SCHAR; |
108 | typetab[UCHAR].t_tspec = UCHAR; | | 108 | typetab[UCHAR].t_tspec = UCHAR; |
109 | typetab[SHORT].t_tspec = SHORT; | | 109 | typetab[SHORT].t_tspec = SHORT; |
110 | typetab[USHORT].t_tspec = USHORT; | | 110 | typetab[USHORT].t_tspec = USHORT; |
111 | typetab[INT].t_tspec = INT; | | 111 | typetab[INT].t_tspec = INT; |
112 | typetab[UINT].t_tspec = UINT; | | 112 | typetab[UINT].t_tspec = UINT; |
113 | typetab[LONG].t_tspec = LONG; | | 113 | typetab[LONG].t_tspec = LONG; |
114 | typetab[ULONG].t_tspec = ULONG; | | 114 | typetab[ULONG].t_tspec = ULONG; |
115 | typetab[QUAD].t_tspec = QUAD; | | 115 | typetab[QUAD].t_tspec = QUAD; |
116 | typetab[UQUAD].t_tspec = UQUAD; | | 116 | typetab[UQUAD].t_tspec = UQUAD; |
117 | typetab[FLOAT].t_tspec = FLOAT; | | 117 | typetab[FLOAT].t_tspec = FLOAT; |
118 | typetab[DOUBLE].t_tspec = DOUBLE; | | 118 | typetab[DOUBLE].t_tspec = DOUBLE; |
119 | typetab[LDOUBLE].t_tspec = LDOUBLE; | | 119 | typetab[LDOUBLE].t_tspec = LDOUBLE; |
120 | typetab[FCOMPLEX].t_tspec = FCOMPLEX; | | 120 | typetab[FCOMPLEX].t_tspec = FCOMPLEX; |
121 | typetab[DCOMPLEX].t_tspec = DCOMPLEX; | | 121 | typetab[DCOMPLEX].t_tspec = DCOMPLEX; |
122 | typetab[LCOMPLEX].t_tspec = LCOMPLEX; | | 122 | typetab[LCOMPLEX].t_tspec = LCOMPLEX; |
123 | typetab[COMPLEX].t_tspec = COMPLEX; | | 123 | typetab[COMPLEX].t_tspec = COMPLEX; |
124 | typetab[VOID].t_tspec = VOID; | | 124 | typetab[VOID].t_tspec = VOID; |
125 | /* | | 125 | /* |
126 | * Next two are not real types. They are only used by the parser | | 126 | * Next two are not real types. They are only used by the parser |
127 | * to return keywords "signed" and "unsigned" | | 127 | * to return keywords "signed" and "unsigned" |
128 | */ | | 128 | */ |
129 | typetab[SIGNED].t_tspec = SIGNED; | | 129 | typetab[SIGNED].t_tspec = SIGNED; |
130 | typetab[UNSIGN].t_tspec = UNSIGN; | | 130 | typetab[UNSIGN].t_tspec = UNSIGN; |
131 | } | | 131 | } |
132 | | | 132 | |
133 | /* | | 133 | /* |
134 | * Returns a shared type structure for arithmetic types and void. | | 134 | * Returns a shared type structure for arithmetic types and void. |
135 | * | | 135 | * |
136 | * It's important to duplicate this structure (using duptyp() or tduptyp()) | | 136 | * It's important to duplicate this structure (using duptyp() or tduptyp()) |
137 | * if it is to be modified (adding qualifiers or anything else). | | 137 | * if it is to be modified (adding qualifiers or anything else). |
138 | */ | | 138 | */ |
139 | type_t * | | 139 | type_t * |
140 | gettyp(tspec_t t) | | 140 | gettyp(tspec_t t) |
141 | { | | 141 | { |
142 | | | 142 | |
143 | return &typetab[t]; | | 143 | return &typetab[t]; |
144 | } | | 144 | } |
145 | | | 145 | |
146 | type_t * | | 146 | type_t * |
147 | duptyp(const type_t *tp) | | 147 | duptyp(const type_t *tp) |
148 | { | | 148 | { |
149 | type_t *ntp; | | 149 | type_t *ntp; |
150 | | | 150 | |
151 | ntp = getblk(sizeof (type_t)); | | 151 | ntp = getblk(sizeof (type_t)); |
152 | *ntp = *tp; | | 152 | *ntp = *tp; |
153 | return ntp; | | 153 | return ntp; |
154 | } | | 154 | } |
155 | | | 155 | |
156 | /* | | 156 | /* |
157 | * Use tduptyp() instead of duptyp() inside expressions (if the | | 157 | * Use tduptyp() instead of duptyp() inside expressions (if the |
158 | * allocated memory should be freed after the expr). | | 158 | * allocated memory should be freed after the expr). |
159 | */ | | 159 | */ |
160 | type_t * | | 160 | type_t * |
161 | tduptyp(const type_t *tp) | | 161 | tduptyp(const type_t *tp) |
162 | { | | 162 | { |
163 | type_t *ntp; | | 163 | type_t *ntp; |
164 | | | 164 | |
165 | ntp = tgetblk(sizeof (type_t)); | | 165 | ntp = tgetblk(sizeof (type_t)); |
166 | *ntp = *tp; | | 166 | *ntp = *tp; |
167 | return ntp; | | 167 | return ntp; |
168 | } | | 168 | } |
169 | | | 169 | |
170 | /* | | 170 | /* |
171 | * Returns 1 if the argument is void or an incomplete array, | | 171 | * Returns 1 if the argument is void or an incomplete array, |
172 | * struct, union or enum type. | | 172 | * struct, union or enum type. |
173 | */ | | 173 | */ |
174 | int | | 174 | int |
175 | incompl(type_t *tp) | | 175 | incompl(type_t *tp) |
176 | { | | 176 | { |
177 | tspec_t t; | | 177 | tspec_t t; |
178 | | | 178 | |
179 | if ((t = tp->t_tspec) == VOID) { | | 179 | if ((t = tp->t_tspec) == VOID) { |
180 | return 1; | | 180 | return 1; |
181 | } else if (t == ARRAY) { | | 181 | } else if (t == ARRAY) { |
182 | return tp->t_aincompl; | | 182 | return tp->t_aincompl; |
183 | } else if (t == STRUCT || t == UNION) { | | 183 | } else if (t == STRUCT || t == UNION) { |
184 | return tp->t_str->sincompl; | | 184 | return tp->t_str->sincompl; |
185 | } else if (t == ENUM) { | | 185 | } else if (t == ENUM) { |
186 | return tp->t_enum->eincompl; | | 186 | return tp->t_enum->eincompl; |
187 | } | | 187 | } |
188 | return 0; | | 188 | return 0; |
189 | } | | 189 | } |
190 | | | 190 | |
191 | /* | | 191 | /* |
192 | * Mark an array, struct, union or enum type as complete or incomplete. | | 192 | * Mark an array, struct, union or enum type as complete or incomplete. |
193 | */ | | 193 | */ |
194 | void | | 194 | void |
195 | setcomplete(type_t *tp, int complete) | | 195 | setcomplete(type_t *tp, int complete) |
196 | { | | 196 | { |
197 | tspec_t t; | | 197 | tspec_t t; |
198 | | | 198 | |
199 | if ((t = tp->t_tspec) == ARRAY) { | | 199 | if ((t = tp->t_tspec) == ARRAY) { |
200 | tp->t_aincompl = !complete; | | 200 | tp->t_aincompl = !complete; |
201 | } else if (t == STRUCT || t == UNION) { | | 201 | } else if (t == STRUCT || t == UNION) { |
202 | tp->t_str->sincompl = !complete; | | 202 | tp->t_str->sincompl = !complete; |
203 | } else { | | 203 | } else { |
204 | lint_assert(t == ENUM); | | 204 | lint_assert(t == ENUM); |
205 | tp->t_enum->eincompl = !complete; | | 205 | tp->t_enum->eincompl = !complete; |
206 | } | | 206 | } |
207 | } | | 207 | } |
208 | | | 208 | |
209 | /* | | 209 | /* |
210 | * Remember the storage class of the current declaration in dcs->d_scl | | 210 | * Remember the storage class of the current declaration in dcs->d_scl |
211 | * (the top element of the declaration stack) and detect multiple | | 211 | * (the top element of the declaration stack) and detect multiple |
212 | * storage classes. | | 212 | * storage classes. |
213 | */ | | 213 | */ |
214 | void | | 214 | void |
215 | add_storage_class(scl_t sc) | | 215 | add_storage_class(scl_t sc) |
216 | { | | 216 | { |
217 | | | 217 | |
218 | if (sc == INLINE) { | | 218 | if (sc == INLINE) { |
219 | if (dcs->d_inline) | | 219 | if (dcs->d_inline) |
220 | /* duplicate '%s' */ | | 220 | /* duplicate '%s' */ |
221 | warning(10, "inline"); | | 221 | warning(10, "inline"); |
222 | dcs->d_inline = 1; | | 222 | dcs->d_inline = 1; |
223 | return; | | 223 | return; |
224 | } | | 224 | } |
225 | if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC || | | 225 | if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC || |
226 | dcs->d_smod != NOTSPEC || dcs->d_lmod != NOTSPEC) { | | 226 | dcs->d_smod != NOTSPEC || dcs->d_lmod != NOTSPEC) { |
227 | /* storage class after type is obsolescent */ | | 227 | /* storage class after type is obsolescent */ |
228 | warning(83); | | 228 | warning(83); |
229 | } | | 229 | } |
230 | if (dcs->d_scl == NOSCL) { | | 230 | if (dcs->d_scl == NOSCL) { |
231 | dcs->d_scl = sc; | | 231 | dcs->d_scl = sc; |
232 | } else { | | 232 | } else { |
233 | /* | | 233 | /* |
234 | * multiple storage classes. An error will be reported in | | 234 | * multiple storage classes. An error will be reported in |
235 | * deftyp(). | | 235 | * deftyp(). |
236 | */ | | 236 | */ |
237 | dcs->d_mscl = 1; | | 237 | dcs->d_mscl = 1; |
238 | } | | 238 | } |
239 | } | | 239 | } |
240 | | | 240 | |
241 | /* | | 241 | /* |
242 | * Remember the type, modifier or typedef name returned by the parser | | 242 | * Remember the type, modifier or typedef name returned by the parser |
243 | * in *dcs (top element of decl stack). This information is used in | | 243 | * in *dcs (top element of decl stack). This information is used in |
244 | * deftyp() to build the type used for all declarators in this | | 244 | * deftyp() to build the type used for all declarators in this |
245 | * declaration. | | 245 | * declaration. |
246 | * | | 246 | * |
247 | * If tp->t_typedef is 1, the type comes from a previously defined typename. | | 247 | * If tp->t_typedef is 1, the type comes from a previously defined typename. |
248 | * Otherwise it comes from a type specifier (int, long, ...) or a | | 248 | * Otherwise it comes from a type specifier (int, long, ...) or a |
249 | * struct/union/enum tag. | | 249 | * struct/union/enum tag. |
250 | */ | | 250 | */ |
251 | void | | 251 | void |
252 | add_type(type_t *tp) | | 252 | add_type(type_t *tp) |
253 | { | | 253 | { |
254 | tspec_t t; | | 254 | tspec_t t; |
255 | #ifdef DEBUG | | 255 | #ifdef DEBUG |
256 | printf("%s: %s\n", __func__, type_name(tp)); | | 256 | printf("%s: %s\n", __func__, type_name(tp)); |
257 | #endif | | 257 | #endif |
258 | if (tp->t_typedef) { | | 258 | if (tp->t_typedef) { |
259 | /* | | 259 | /* |
260 | * something like "typedef int a; int a b;" | | 260 | * something like "typedef int a; int a b;" |
261 | * This should not happen with current grammar. | | 261 | * This should not happen with current grammar. |
262 | */ | | 262 | */ |
263 | lint_assert(dcs->d_type == NULL); | | 263 | lint_assert(dcs->d_type == NULL); |
264 | lint_assert(dcs->d_atyp == NOTSPEC); | | 264 | lint_assert(dcs->d_atyp == NOTSPEC); |
265 | lint_assert(dcs->d_lmod == NOTSPEC); | | 265 | lint_assert(dcs->d_lmod == NOTSPEC); |
266 | lint_assert(dcs->d_smod == NOTSPEC); | | 266 | lint_assert(dcs->d_smod == NOTSPEC); |
267 | | | 267 | |
268 | dcs->d_type = tp; | | 268 | dcs->d_type = tp; |
269 | return; | | 269 | return; |
270 | } | | 270 | } |
271 | | | 271 | |
272 | t = tp->t_tspec; | | 272 | t = tp->t_tspec; |
273 | | | 273 | |
274 | if (t == STRUCT || t == UNION || t == ENUM) { | | 274 | if (t == STRUCT || t == UNION || t == ENUM) { |
275 | /* | | 275 | /* |
276 | * something like "int struct a ..." | | 276 | * something like "int struct a ..." |
277 | * struct/union/enum with anything else is not allowed | | 277 | * struct/union/enum with anything else is not allowed |
278 | */ | | 278 | */ |
279 | if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC || | | 279 | if (dcs->d_type != NULL || dcs->d_atyp != NOTSPEC || |
280 | dcs->d_lmod != NOTSPEC || dcs->d_smod != NOTSPEC) { | | 280 | dcs->d_lmod != NOTSPEC || dcs->d_smod != NOTSPEC) { |
281 | /* | | 281 | /* |
282 | * remember that an error must be reported in | | 282 | * remember that an error must be reported in |
283 | * deftyp(). | | 283 | * deftyp(). |
284 | */ | | 284 | */ |
285 | dcs->d_terr = 1; | | 285 | dcs->d_terr = 1; |
286 | dcs->d_atyp = dcs->d_lmod = dcs->d_smod = NOTSPEC; | | 286 | dcs->d_atyp = dcs->d_lmod = dcs->d_smod = NOTSPEC; |
287 | } | | 287 | } |
288 | dcs->d_type = tp; | | 288 | dcs->d_type = tp; |
289 | return; | | 289 | return; |
290 | } | | 290 | } |
291 | | | 291 | |
292 | if (dcs->d_type != NULL && !dcs->d_type->t_typedef) { | | 292 | if (dcs->d_type != NULL && !dcs->d_type->t_typedef) { |
293 | /* | | 293 | /* |
294 | * something like "struct a int" | | 294 | * something like "struct a int" |
295 | * struct/union/enum with anything else is not allowed | | 295 | * struct/union/enum with anything else is not allowed |
296 | */ | | 296 | */ |
297 | dcs->d_terr = 1; | | 297 | dcs->d_terr = 1; |
298 | return; | | 298 | return; |
299 | } | | 299 | } |
300 | | | 300 | |
301 | if (t == COMPLEX) { | | 301 | if (t == COMPLEX) { |
302 | if (dcs->d_cmod == FLOAT) | | 302 | if (dcs->d_cmod == FLOAT) |
303 | t = FCOMPLEX; | | 303 | t = FCOMPLEX; |
304 | else if (dcs->d_cmod == DOUBLE) | | 304 | else if (dcs->d_cmod == DOUBLE) |
305 | t = DCOMPLEX; | | 305 | t = DCOMPLEX; |
306 | else { | | 306 | else { |
307 | /* Invalid type for _Complex */ | | 307 | /* Invalid type for _Complex */ |
308 | error(308); | | 308 | error(308); |
309 | t = DCOMPLEX; /* just as a fallback */ | | 309 | t = DCOMPLEX; /* just as a fallback */ |
310 | } | | 310 | } |
311 | dcs->d_cmod = NOTSPEC; | | 311 | dcs->d_cmod = NOTSPEC; |
312 | } | | 312 | } |
313 | | | 313 | |
314 | if (t == LONG && dcs->d_lmod == LONG) { | | 314 | if (t == LONG && dcs->d_lmod == LONG) { |
315 | /* "long long" or "long ... long" */ | | 315 | /* "long long" or "long ... long" */ |
316 | t = QUAD; | | 316 | t = QUAD; |
317 | dcs->d_lmod = NOTSPEC; | | 317 | dcs->d_lmod = NOTSPEC; |
318 | if (!quadflg) | | 318 | if (!quadflg) |
319 | /* %s C does not support 'long long' */ | | 319 | /* %s C does not support 'long long' */ |
320 | (void)c99ism(265, tflag ? "traditional" : "c89"); | | 320 | (void)c99ism(265, tflag ? "traditional" : "c89"); |
321 | } | | 321 | } |
322 | | | 322 | |
323 | if (dcs->d_type != NULL && dcs->d_type->t_typedef) { | | 323 | if (dcs->d_type != NULL && dcs->d_type->t_typedef) { |
324 | /* something like "typedef int a; a long ..." */ | | 324 | /* something like "typedef int a; a long ..." */ |
325 | dcs->d_type = tdeferr(dcs->d_type, t); | | 325 | dcs->d_type = tdeferr(dcs->d_type, t); |
326 | return; | | 326 | return; |
327 | } | | 327 | } |
328 | | | 328 | |
329 | /* now it can be only a combination of arithmetic types and void */ | | 329 | /* now it can be only a combination of arithmetic types and void */ |
330 | if (t == SIGNED || t == UNSIGN) { | | 330 | if (t == SIGNED || t == UNSIGN) { |
331 | /* remember specifiers "signed" & "unsigned" in dcs->d_smod */ | | 331 | /* remember specifiers "signed" & "unsigned" in dcs->d_smod */ |
332 | if (dcs->d_smod != NOTSPEC) | | 332 | if (dcs->d_smod != NOTSPEC) |
333 | /* | | 333 | /* |
334 | * more than one "signed" and/or "unsigned"; print | | 334 | * more than one "signed" and/or "unsigned"; print |
335 | * an error in deftyp() | | 335 | * an error in deftyp() |
336 | */ | | 336 | */ |
337 | dcs->d_terr = 1; | | 337 | dcs->d_terr = 1; |
338 | dcs->d_smod = t; | | 338 | dcs->d_smod = t; |
339 | } else if (t == SHORT || t == LONG || t == QUAD) { | | 339 | } else if (t == SHORT || t == LONG || t == QUAD) { |
340 | /* | | 340 | /* |
341 | * remember specifiers "short", "long" and "long long" in | | 341 | * remember specifiers "short", "long" and "long long" in |
342 | * dcs->d_lmod | | 342 | * dcs->d_lmod |
343 | */ | | 343 | */ |
344 | if (dcs->d_lmod != NOTSPEC) | | 344 | if (dcs->d_lmod != NOTSPEC) |
345 | /* more than one, print error in deftyp() */ | | 345 | /* more than one, print error in deftyp() */ |
346 | dcs->d_terr = 1; | | 346 | dcs->d_terr = 1; |
347 | dcs->d_lmod = t; | | 347 | dcs->d_lmod = t; |
348 | } else if (t == FLOAT || t == DOUBLE) { | | 348 | } else if (t == FLOAT || t == DOUBLE) { |
349 | if (dcs->d_lmod == NOTSPEC || dcs->d_lmod == LONG) { | | 349 | if (dcs->d_lmod == NOTSPEC || dcs->d_lmod == LONG) { |
350 | if (dcs->d_cmod != NOTSPEC | | 350 | if (dcs->d_cmod != NOTSPEC |
351 | || (t == FLOAT && dcs->d_lmod == LONG)) | | 351 | || (t == FLOAT && dcs->d_lmod == LONG)) |
352 | dcs->d_terr = 1; | | 352 | dcs->d_terr = 1; |
353 | dcs->d_cmod = t; | | 353 | dcs->d_cmod = t; |
354 | } else { | | 354 | } else { |
355 | if (dcs->d_atyp != NOTSPEC) | | 355 | if (dcs->d_atyp != NOTSPEC) |
356 | dcs->d_terr = 1; | | 356 | dcs->d_terr = 1; |
357 | dcs->d_atyp = t; | | 357 | dcs->d_atyp = t; |
358 | } | | 358 | } |
359 | } else if (t == PTR) { | | 359 | } else if (t == PTR) { |
360 | dcs->d_type = tp; | | 360 | dcs->d_type = tp; |
361 | } else { | | 361 | } else { |
362 | /* | | 362 | /* |
363 | * remember specifiers "void", "char", "int", | | 363 | * remember specifiers "void", "char", "int", |
364 | * or "_Complex" int dcs->d_atyp | | 364 | * or "_Complex" int dcs->d_atyp |
365 | */ | | 365 | */ |
366 | if (dcs->d_atyp != NOTSPEC) | | 366 | if (dcs->d_atyp != NOTSPEC) |
367 | /* more than one, print error in deftyp() */ | | 367 | /* more than one, print error in deftyp() */ |
368 | dcs->d_terr = 1; | | 368 | dcs->d_terr = 1; |
369 | dcs->d_atyp = t; | | 369 | dcs->d_atyp = t; |
370 | } | | 370 | } |
371 | } | | 371 | } |
372 | | | 372 | |
373 | /* | | 373 | /* |
374 | * called if a list of declaration specifiers contains a typedef name | | 374 | * called if a list of declaration specifiers contains a typedef name |
375 | * and other specifiers (except struct, union, enum, typedef name) | | 375 | * and other specifiers (except struct, union, enum, typedef name) |
376 | */ | | 376 | */ |
377 | static type_t * | | 377 | static type_t * |
378 | tdeferr(type_t *td, tspec_t t) | | 378 | tdeferr(type_t *td, tspec_t t) |
379 | { | | 379 | { |
380 | tspec_t t2; | | 380 | tspec_t t2; |
381 | | | 381 | |
382 | t2 = td->t_tspec; | | 382 | t2 = td->t_tspec; |
383 | | | 383 | |
384 | switch (t) { | | 384 | switch (t) { |
385 | case SIGNED: | | 385 | case SIGNED: |
386 | case UNSIGN: | | 386 | case UNSIGN: |
387 | if (t2 == CHAR || t2 == SHORT || t2 == INT || t2 == LONG || | | 387 | if (t2 == CHAR || t2 == SHORT || t2 == INT || t2 == LONG || |
388 | t2 == QUAD) { | | 388 | t2 == QUAD) { |
389 | if (!tflag) | | 389 | if (!tflag) |
390 | /* modifying typedef with ... */ | | 390 | /* modifying typedef with '%s'; only ... */ |
391 | warning(5, ttab[t].tt_name); | | 391 | warning(5, ttab[t].tt_name); |
392 | td = duptyp(gettyp(merge_type_specifiers(t2, t))); | | 392 | td = duptyp(gettyp(merge_type_specifiers(t2, t))); |
393 | td->t_typedef = 1; | | 393 | td->t_typedef = 1; |
394 | return td; | | 394 | return td; |
395 | } | | 395 | } |
396 | break; | | 396 | break; |
397 | case SHORT: | | 397 | case SHORT: |
398 | if (t2 == INT || t2 == UINT) { | | 398 | if (t2 == INT || t2 == UINT) { |
399 | /* modifying typedef with ... */ | | 399 | /* modifying typedef with '%s'; only qualifiers ... */ |
400 | warning(5, "short"); | | 400 | warning(5, "short"); |
401 | td = duptyp(gettyp(t2 == INT ? SHORT : USHORT)); | | 401 | td = duptyp(gettyp(t2 == INT ? SHORT : USHORT)); |
402 | td->t_typedef = 1; | | 402 | td->t_typedef = 1; |
403 | return td; | | 403 | return td; |
404 | } | | 404 | } |
405 | break; | | 405 | break; |
406 | case LONG: | | 406 | case LONG: |
407 | if (t2 == INT || t2 == UINT || t2 == LONG || t2 == ULONG || | | 407 | if (t2 == INT || t2 == UINT || t2 == LONG || t2 == ULONG || |
408 | t2 == FLOAT || t2 == DOUBLE || t2 == DCOMPLEX) { | | 408 | t2 == FLOAT || t2 == DOUBLE || t2 == DCOMPLEX) { |
409 | /* modifying typedef with ... */ | | 409 | /* modifying typedef with ... */ |
410 | warning(5, "long"); | | 410 | warning(5, "long"); |
411 | if (t2 == INT) { | | 411 | if (t2 == INT) { |
412 | td = gettyp(LONG); | | 412 | td = gettyp(LONG); |
413 | } else if (t2 == UINT) { | | 413 | } else if (t2 == UINT) { |
414 | td = gettyp(ULONG); | | 414 | td = gettyp(ULONG); |
415 | } else if (t2 == LONG) { | | 415 | } else if (t2 == LONG) { |
416 | td = gettyp(QUAD); | | 416 | td = gettyp(QUAD); |
417 | } else if (t2 == ULONG) { | | 417 | } else if (t2 == ULONG) { |
418 | td = gettyp(UQUAD); | | 418 | td = gettyp(UQUAD); |
419 | } else if (t2 == FLOAT) { | | 419 | } else if (t2 == FLOAT) { |
420 | td = gettyp(DOUBLE); | | 420 | td = gettyp(DOUBLE); |
421 | } else if (t2 == DOUBLE) { | | 421 | } else if (t2 == DOUBLE) { |
422 | td = gettyp(LDOUBLE); | | 422 | td = gettyp(LDOUBLE); |
423 | } else if (t2 == DCOMPLEX) { | | 423 | } else if (t2 == DCOMPLEX) { |
424 | td = gettyp(LCOMPLEX); | | 424 | td = gettyp(LCOMPLEX); |
425 | } | | 425 | } |
426 | td = duptyp(td); | | 426 | td = duptyp(td); |
427 | td->t_typedef = 1; | | 427 | td->t_typedef = 1; |
428 | return td; | | 428 | return td; |
429 | } | | 429 | } |
430 | break; | | 430 | break; |
431 | /* LINTED206: (enumeration values not handled in switch) */ | | 431 | /* LINTED206: (enumeration values not handled in switch) */ |
432 | case NOTSPEC: | | 432 | case NOTSPEC: |
433 | case USHORT: | | 433 | case USHORT: |
434 | case UCHAR: | | 434 | case UCHAR: |
435 | case SCHAR: | | 435 | case SCHAR: |
436 | case CHAR: | | 436 | case CHAR: |
437 | case BOOL: | | 437 | case BOOL: |
438 | case FUNC: | | 438 | case FUNC: |
439 | case ARRAY: | | 439 | case ARRAY: |
440 | case PTR: | | 440 | case PTR: |
441 | case ENUM: | | 441 | case ENUM: |
442 | case UNION: | | 442 | case UNION: |
443 | case STRUCT: | | 443 | case STRUCT: |
444 | case VOID: | | 444 | case VOID: |
445 | case LDOUBLE: | | 445 | case LDOUBLE: |
446 | case FLOAT: | | 446 | case FLOAT: |
447 | case DOUBLE: | | 447 | case DOUBLE: |
448 | case UQUAD: | | 448 | case UQUAD: |
449 | case QUAD: | | 449 | case QUAD: |
450 | #ifdef INT128_SIZE | | 450 | #ifdef INT128_SIZE |
451 | case UINT128: | | 451 | case UINT128: |
452 | case INT128: | | 452 | case INT128: |
453 | #endif | | 453 | #endif |
454 | case ULONG: | | 454 | case ULONG: |
455 | case UINT: | | 455 | case UINT: |
456 | case INT: | | 456 | case INT: |
457 | case FCOMPLEX: | | 457 | case FCOMPLEX: |
458 | case DCOMPLEX: | | 458 | case DCOMPLEX: |
459 | case LCOMPLEX: | | 459 | case LCOMPLEX: |
460 | case COMPLEX: | | 460 | case COMPLEX: |
461 | break; | | 461 | break; |
462 | } | | 462 | } |
463 | | | 463 | |
464 | /* Anything other is not accepted. */ | | 464 | /* Anything other is not accepted. */ |
465 | | | 465 | |
466 | dcs->d_terr = 1; | | 466 | dcs->d_terr = 1; |
467 | return td; | | 467 | return td; |
468 | } | | 468 | } |
469 | | | 469 | |
470 | /* | | 470 | /* |
471 | * Remember the symbol of a typedef name (2nd arg) in a struct, union | | 471 | * Remember the symbol of a typedef name (2nd arg) in a struct, union |
472 | * or enum tag if the typedef name is the first defined for this tag. | | 472 | * or enum tag if the typedef name is the first defined for this tag. |
473 | * | | 473 | * |
474 | * If the tag is unnamed, the typdef name is used for identification | | 474 | * If the tag is unnamed, the typdef name is used for identification |
475 | * of this tag in lint2. Although it's possible that more than one typedef | | 475 | * of this tag in lint2. Although it's possible that more than one typedef |
476 | * name is defined for one tag, the first name defined should be unique | | 476 | * name is defined for one tag, the first name defined should be unique |
477 | * if the tag is unnamed. | | 477 | * if the tag is unnamed. |
478 | */ | | 478 | */ |
479 | static void | | 479 | static void |
480 | settdsym(type_t *tp, sym_t *sym) | | 480 | settdsym(type_t *tp, sym_t *sym) |
481 | { | | 481 | { |
482 | tspec_t t; | | 482 | tspec_t t; |
483 | | | 483 | |
484 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { | | 484 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { |
485 | if (tp->t_str->stdef == NULL) | | 485 | if (tp->t_str->stdef == NULL) |
486 | tp->t_str->stdef = sym; | | 486 | tp->t_str->stdef = sym; |
487 | } else if (t == ENUM) { | | 487 | } else if (t == ENUM) { |
488 | if (tp->t_enum->etdef == NULL) | | 488 | if (tp->t_enum->etdef == NULL) |
489 | tp->t_enum->etdef = sym; | | 489 | tp->t_enum->etdef = sym; |
490 | } | | 490 | } |
491 | } | | 491 | } |
492 | | | 492 | |
493 | static size_t | | 493 | static size_t |
494 | bitfieldsize(sym_t **mem) | | 494 | bitfieldsize(sym_t **mem) |
495 | { | | 495 | { |
496 | size_t len = (*mem)->s_type->t_flen; | | 496 | size_t len = (*mem)->s_type->t_flen; |
497 | while (*mem && (*mem)->s_type->t_isfield) { | | 497 | while (*mem && (*mem)->s_type->t_isfield) { |
498 | len += (*mem)->s_type->t_flen; | | 498 | len += (*mem)->s_type->t_flen; |
499 | *mem = (*mem)->s_next; | | 499 | *mem = (*mem)->s_next; |
500 | } | | 500 | } |
501 | return ((len + INT_SIZE - 1) / INT_SIZE) * INT_SIZE; | | 501 | return ((len + INT_SIZE - 1) / INT_SIZE) * INT_SIZE; |
502 | } | | 502 | } |
503 | | | 503 | |
504 | static void | | 504 | static void |
505 | setpackedsize(type_t *tp) | | 505 | setpackedsize(type_t *tp) |
506 | { | | 506 | { |
507 | str_t *sp; | | 507 | str_t *sp; |
508 | sym_t *mem; | | 508 | sym_t *mem; |
509 | | | 509 | |
510 | switch (tp->t_tspec) { | | 510 | switch (tp->t_tspec) { |
511 | case STRUCT: | | 511 | case STRUCT: |
512 | case UNION: | | 512 | case UNION: |
513 | sp = tp->t_str; | | 513 | sp = tp->t_str; |
514 | sp->size = 0; | | 514 | sp->size = 0; |
515 | for (mem = sp->memb; mem != NULL; mem = mem->s_next) { | | 515 | for (mem = sp->memb; mem != NULL; mem = mem->s_next) { |
516 | if (mem->s_type->t_isfield) { | | 516 | if (mem->s_type->t_isfield) { |
517 | sp->size += bitfieldsize(&mem); | | 517 | sp->size += bitfieldsize(&mem); |
518 | if (mem == NULL) | | 518 | if (mem == NULL) |
519 | break; | | 519 | break; |
520 | } | | 520 | } |
521 | size_t x = (size_t)tsize(mem->s_type); | | 521 | size_t x = (size_t)tsize(mem->s_type); |
522 | if (tp->t_tspec == STRUCT) | | 522 | if (tp->t_tspec == STRUCT) |
523 | sp->size += x; | | 523 | sp->size += x; |
524 | else if (x > sp->size) | | 524 | else if (x > sp->size) |
525 | sp->size = x; | | 525 | sp->size = x; |
526 | } | | 526 | } |
527 | break; | | 527 | break; |
528 | default: | | 528 | default: |
529 | /* %s attribute ignored for %s */ | | 529 | /* %s attribute ignored for %s */ |
530 | warning(326, "packed", type_name(tp)); | | 530 | warning(326, "packed", type_name(tp)); |
531 | break; | | 531 | break; |
532 | } | | 532 | } |
533 | } | | 533 | } |
534 | | | 534 | |
535 | void | | 535 | void |
536 | addpacked(void) | | 536 | addpacked(void) |
537 | { | | 537 | { |
538 | if (dcs->d_type == NULL) | | 538 | if (dcs->d_type == NULL) |
539 | dcs->d_ispacked = 1; | | 539 | dcs->d_ispacked = 1; |
540 | else | | 540 | else |
541 | setpackedsize(dcs->d_type); | | 541 | setpackedsize(dcs->d_type); |
542 | } | | 542 | } |
543 | | | 543 | |
544 | void | | 544 | void |
545 | add_attr_used(void) | | 545 | add_attr_used(void) |
546 | { | | 546 | { |
547 | dcs->d_used = 1; | | 547 | dcs->d_used = 1; |
548 | } | | 548 | } |
549 | | | 549 | |
550 | /* | | 550 | /* |
551 | * Remember a qualifier which is part of the declaration specifiers | | 551 | * Remember a qualifier which is part of the declaration specifiers |
552 | * (and not the declarator) in the top element of the declaration stack. | | 552 | * (and not the declarator) in the top element of the declaration stack. |
553 | * Also detect multiple qualifiers of the same kind. | | 553 | * Also detect multiple qualifiers of the same kind. |
554 | | | 554 | |
555 | * The remembered qualifier is used by deftyp() to construct the type | | 555 | * The remembered qualifier is used by deftyp() to construct the type |
556 | * for all declarators. | | 556 | * for all declarators. |
557 | */ | | 557 | */ |
558 | void | | 558 | void |
559 | add_qualifier(tqual_t q) | | 559 | add_qualifier(tqual_t q) |
560 | { | | 560 | { |
561 | | | 561 | |
562 | if (q == CONST) { | | 562 | if (q == CONST) { |
563 | if (dcs->d_const) { | | 563 | if (dcs->d_const) { |
564 | /* duplicate '%s' */ | | 564 | /* duplicate '%s' */ |
565 | warning(10, "const"); | | 565 | warning(10, "const"); |
566 | } | | 566 | } |
567 | dcs->d_const = 1; | | 567 | dcs->d_const = 1; |
568 | } else { | | 568 | } else { |
569 | if (q == THREAD) | | 569 | if (q == THREAD) |
570 | return; | | 570 | return; |
571 | lint_assert(q == VOLATILE); | | 571 | lint_assert(q == VOLATILE); |
572 | if (dcs->d_volatile) { | | 572 | if (dcs->d_volatile) { |
573 | /* duplicate '%s' */ | | 573 | /* duplicate '%s' */ |
574 | warning(10, "volatile"); | | 574 | warning(10, "volatile"); |
575 | } | | 575 | } |
576 | dcs->d_volatile = 1; | | 576 | dcs->d_volatile = 1; |
577 | } | | 577 | } |
578 | } | | 578 | } |
579 | | | 579 | |
580 | /* | | 580 | /* |
581 | * Go to the next declaration level (structs, nested structs, blocks, | | 581 | * Go to the next declaration level (structs, nested structs, blocks, |
582 | * argument declaration lists ...) | | 582 | * argument declaration lists ...) |
583 | */ | | 583 | */ |
584 | void | | 584 | void |
585 | pushdecl(scl_t sc) | | 585 | pushdecl(scl_t sc) |
586 | { | | 586 | { |
587 | dinfo_t *di; | | 587 | dinfo_t *di; |
588 | | | 588 | |
589 | /* put a new element on the declaration stack */ | | 589 | /* put a new element on the declaration stack */ |
590 | di = xcalloc(1, sizeof (dinfo_t)); | | 590 | di = xcalloc(1, sizeof (dinfo_t)); |
591 | di->d_next = dcs; | | 591 | di->d_next = dcs; |
592 | dcs = di; | | 592 | dcs = di; |
593 | di->d_ctx = sc; | | 593 | di->d_ctx = sc; |
594 | di->d_ldlsym = &di->d_dlsyms; | | 594 | di->d_ldlsym = &di->d_dlsyms; |
595 | if (dflag) | | 595 | if (dflag) |
596 | (void)printf("pushdecl(%p %d)\n", dcs, (int)sc); | | 596 | (void)printf("pushdecl(%p %d)\n", dcs, (int)sc); |
597 | | | 597 | |
598 | } | | 598 | } |
599 | | | 599 | |
600 | /* | | 600 | /* |
601 | * Go back to previous declaration level | | 601 | * Go back to previous declaration level |
602 | */ | | 602 | */ |
603 | void | | 603 | void |
604 | popdecl(void) | | 604 | popdecl(void) |
605 | { | | 605 | { |
606 | dinfo_t *di; | | 606 | dinfo_t *di; |
607 | | | 607 | |
608 | if (dflag) | | 608 | if (dflag) |
609 | (void)printf("popdecl(%p %d)\n", dcs, (int)dcs->d_ctx); | | 609 | (void)printf("popdecl(%p %d)\n", dcs, (int)dcs->d_ctx); |
610 | | | 610 | |
611 | lint_assert(dcs->d_next != NULL); | | 611 | lint_assert(dcs->d_next != NULL); |
612 | di = dcs; | | 612 | di = dcs; |
613 | dcs = di->d_next; | | 613 | dcs = di->d_next; |
614 | switch (di->d_ctx) { | | 614 | switch (di->d_ctx) { |
615 | case MOS: | | 615 | case MOS: |
616 | case MOU: | | 616 | case MOU: |
617 | case ENUMCON: | | 617 | case ENUMCON: |
618 | /* | | 618 | /* |
619 | * Symbols declared in (nested) structs or enums are | | 619 | * Symbols declared in (nested) structs or enums are |
620 | * part of the next level (they are removed from the | | 620 | * part of the next level (they are removed from the |
621 | * symbol table if the symbols of the outher level are | | 621 | * symbol table if the symbols of the outher level are |
622 | * removed). | | 622 | * removed). |
623 | */ | | 623 | */ |
624 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) | | 624 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) |
625 | dcs->d_ldlsym = di->d_ldlsym; | | 625 | dcs->d_ldlsym = di->d_ldlsym; |
626 | break; | | 626 | break; |
627 | case ARG: | | 627 | case ARG: |
628 | /* | | 628 | /* |
629 | * All symbols in dcs->d_dlsyms are introduced in old style | | 629 | * All symbols in dcs->d_dlsyms are introduced in old style |
630 | * argument declarations (it's not clean, but possible). | | 630 | * argument declarations (it's not clean, but possible). |
631 | * They are appended to the list of symbols declared in | | 631 | * They are appended to the list of symbols declared in |
632 | * an old style argument identifier list or a new style | | 632 | * an old style argument identifier list or a new style |
633 | * parameter type list. | | 633 | * parameter type list. |
634 | */ | | 634 | */ |
635 | if (di->d_dlsyms != NULL) { | | 635 | if (di->d_dlsyms != NULL) { |
636 | *di->d_ldlsym = dcs->d_fpsyms; | | 636 | *di->d_ldlsym = dcs->d_fpsyms; |
637 | dcs->d_fpsyms = di->d_dlsyms; | | 637 | dcs->d_fpsyms = di->d_dlsyms; |
638 | } | | 638 | } |
639 | break; | | 639 | break; |
640 | case ABSTRACT: | | 640 | case ABSTRACT: |
641 | /* | | 641 | /* |
642 | * casts and sizeof | | 642 | * casts and sizeof |
643 | * Append all symbols declared in the abstract declaration | | 643 | * Append all symbols declared in the abstract declaration |
644 | * to the list of symbols declared in the surrounding | | 644 | * to the list of symbols declared in the surrounding |
645 | * declaration or block. | | 645 | * declaration or block. |
646 | * XXX I'm not sure whether they should be removed from the | | 646 | * XXX I'm not sure whether they should be removed from the |
647 | * symbol table now or later. | | 647 | * symbol table now or later. |
648 | */ | | 648 | */ |
649 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) | | 649 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) |
650 | dcs->d_ldlsym = di->d_ldlsym; | | 650 | dcs->d_ldlsym = di->d_ldlsym; |
651 | break; | | 651 | break; |
652 | case AUTO: | | 652 | case AUTO: |
653 | /* check usage of local vars */ | | 653 | /* check usage of local vars */ |
654 | check_usage(di); | | 654 | check_usage(di); |
655 | /* FALLTHROUGH */ | | 655 | /* FALLTHROUGH */ |
656 | case PARG: | | 656 | case PARG: |
657 | /* usage of arguments will be checked by funcend() */ | | 657 | /* usage of arguments will be checked by funcend() */ |
658 | rmsyms(di->d_dlsyms); | | 658 | rmsyms(di->d_dlsyms); |
659 | break; | | 659 | break; |
660 | case EXTERN: | | 660 | case EXTERN: |
661 | /* there is nothing after external declarations */ | | 661 | /* there is nothing after external declarations */ |
662 | /* FALLTHROUGH */ | | 662 | /* FALLTHROUGH */ |
663 | default: | | 663 | default: |
664 | lint_assert(0); | | 664 | lint_assert(0); |
665 | } | | 665 | } |
666 | free(di); | | 666 | free(di); |
667 | } | | 667 | } |
668 | | | 668 | |
669 | /* | | 669 | /* |
670 | * Set flag d_asm in all declaration stack elements up to the | | 670 | * Set flag d_asm in all declaration stack elements up to the |
671 | * outermost one. | | 671 | * outermost one. |
672 | * | | 672 | * |
673 | * This is used to mark compound statements which have, possibly in | | 673 | * This is used to mark compound statements which have, possibly in |
674 | * nested compound statements, asm statements. For these compound | | 674 | * nested compound statements, asm statements. For these compound |
675 | * statements no warnings about unused or unitialized variables are | | 675 | * statements no warnings about unused or unitialized variables are |
676 | * printed. | | 676 | * printed. |
677 | * | | 677 | * |
678 | * There is no need to clear d_asm in dinfo structs with context AUTO, | | 678 | * There is no need to clear d_asm in dinfo structs with context AUTO, |
679 | * because these structs are freed at the end of the compound statement. | | 679 | * because these structs are freed at the end of the compound statement. |
680 | * But it must be cleared in the outermost dinfo struct, which has | | 680 | * But it must be cleared in the outermost dinfo struct, which has |
681 | * context EXTERN. This could be done in clrtyp() and would work for | | 681 | * context EXTERN. This could be done in clrtyp() and would work for |
682 | * C, but not for C++ (due to mixed statements and declarations). Thus | | 682 | * C, but not for C++ (due to mixed statements and declarations). Thus |
683 | * we clear it in global_clean_up_decl(), which is used to do some cleanup | | 683 | * we clear it in global_clean_up_decl(), which is used to do some cleanup |
684 | * after global declarations/definitions. | | 684 | * after global declarations/definitions. |
685 | */ | | 685 | */ |
686 | void | | 686 | void |
687 | setasm(void) | | 687 | setasm(void) |
688 | { | | 688 | { |
689 | dinfo_t *di; | | 689 | dinfo_t *di; |
690 | | | 690 | |
691 | for (di = dcs; di != NULL; di = di->d_next) | | 691 | for (di = dcs; di != NULL; di = di->d_next) |
692 | di->d_asm = 1; | | 692 | di->d_asm = 1; |
693 | } | | 693 | } |
694 | | | 694 | |
695 | /* | | 695 | /* |
696 | * Clean all elements of the top element of declaration stack which | | 696 | * Clean all elements of the top element of declaration stack which |
697 | * will be used by the next declaration | | 697 | * will be used by the next declaration |
698 | */ | | 698 | */ |
699 | void | | 699 | void |
700 | clrtyp(void) | | 700 | clrtyp(void) |
701 | { | | 701 | { |
702 | | | 702 | |
703 | dcs->d_atyp = dcs->d_cmod = dcs->d_smod = dcs->d_lmod = NOTSPEC; | | 703 | dcs->d_atyp = dcs->d_cmod = dcs->d_smod = dcs->d_lmod = NOTSPEC; |
704 | dcs->d_scl = NOSCL; | | 704 | dcs->d_scl = NOSCL; |
705 | dcs->d_type = NULL; | | 705 | dcs->d_type = NULL; |
706 | dcs->d_const = dcs->d_volatile = 0; | | 706 | dcs->d_const = dcs->d_volatile = 0; |
707 | dcs->d_inline = 0; | | 707 | dcs->d_inline = 0; |
708 | dcs->d_mscl = dcs->d_terr = 0; | | 708 | dcs->d_mscl = dcs->d_terr = 0; |
709 | dcs->d_nedecl = 0; | | 709 | dcs->d_nedecl = 0; |
710 | dcs->d_notyp = 0; | | 710 | dcs->d_notyp = 0; |
711 | } | | 711 | } |
712 | | | 712 | |
713 | /* | | 713 | /* |
714 | * Create a type structure from the information gathered in | | 714 | * Create a type structure from the information gathered in |
715 | * the declaration stack. | | 715 | * the declaration stack. |
716 | * Complain about storage classes which are not possible in current | | 716 | * Complain about storage classes which are not possible in current |
717 | * context. | | 717 | * context. |
718 | */ | | 718 | */ |
719 | void | | 719 | void |
720 | deftyp(void) | | 720 | deftyp(void) |
721 | { | | 721 | { |
722 | tspec_t t, s, l, c; | | 722 | tspec_t t, s, l, c; |
723 | type_t *tp; | | 723 | type_t *tp; |
724 | scl_t scl; | | 724 | scl_t scl; |
725 | | | 725 | |
726 | t = dcs->d_atyp; /* BOOL, CHAR, INT, COMPLEX, VOID */ | | 726 | t = dcs->d_atyp; /* BOOL, CHAR, INT, COMPLEX, VOID */ |
727 | s = dcs->d_smod; /* SIGNED, UNSIGNED */ | | 727 | s = dcs->d_smod; /* SIGNED, UNSIGNED */ |
728 | l = dcs->d_lmod; /* SHORT, LONG, QUAD */ | | 728 | l = dcs->d_lmod; /* SHORT, LONG, QUAD */ |
729 | c = dcs->d_cmod; /* FLOAT, DOUBLE */ | | 729 | c = dcs->d_cmod; /* FLOAT, DOUBLE */ |
730 | tp = dcs->d_type; | | 730 | tp = dcs->d_type; |
731 | scl = dcs->d_scl; | | 731 | scl = dcs->d_scl; |
732 | | | 732 | |
733 | #ifdef DEBUG | | 733 | #ifdef DEBUG |
734 | printf("%s: %s\n", __func__, type_name(tp)); | | 734 | printf("%s: %s\n", __func__, type_name(tp)); |
735 | #endif | | 735 | #endif |
736 | if (t == NOTSPEC && s == NOTSPEC && l == NOTSPEC && c == NOTSPEC && | | 736 | if (t == NOTSPEC && s == NOTSPEC && l == NOTSPEC && c == NOTSPEC && |
737 | tp == NULL) | | 737 | tp == NULL) |
738 | dcs->d_notyp = 1; | | 738 | dcs->d_notyp = 1; |
739 | if (t == NOTSPEC && s == NOTSPEC && (l == NOTSPEC || l == LONG) && | | 739 | if (t == NOTSPEC && s == NOTSPEC && (l == NOTSPEC || l == LONG) && |
740 | tp == NULL) | | 740 | tp == NULL) |
741 | t = c; | | 741 | t = c; |
742 | | | 742 | |
743 | if (tp != NULL) { | | 743 | if (tp != NULL) { |
744 | lint_assert(t == NOTSPEC); | | 744 | lint_assert(t == NOTSPEC); |
745 | lint_assert(s == NOTSPEC); | | 745 | lint_assert(s == NOTSPEC); |
746 | lint_assert(l == NOTSPEC); | | 746 | lint_assert(l == NOTSPEC); |
747 | } | | 747 | } |
748 | | | 748 | |
749 | if (tp == NULL) { | | 749 | if (tp == NULL) { |
750 | switch (t) { | | 750 | switch (t) { |
751 | case BOOL: | | 751 | case BOOL: |
752 | break; | | 752 | break; |
753 | case NOTSPEC: | | 753 | case NOTSPEC: |
754 | t = INT; | | 754 | t = INT; |
755 | /* FALLTHROUGH */ | | 755 | /* FALLTHROUGH */ |
756 | case INT: | | 756 | case INT: |
757 | if (s == NOTSPEC) | | 757 | if (s == NOTSPEC) |
758 | s = SIGNED; | | 758 | s = SIGNED; |
759 | break; | | 759 | break; |
760 | case CHAR: | | 760 | case CHAR: |
761 | if (l != NOTSPEC) { | | 761 | if (l != NOTSPEC) { |
762 | dcs->d_terr = 1; | | 762 | dcs->d_terr = 1; |
763 | l = NOTSPEC; | | 763 | l = NOTSPEC; |
764 | } | | 764 | } |
765 | break; | | 765 | break; |
766 | case FLOAT: | | 766 | case FLOAT: |
767 | if (l == LONG) { | | 767 | if (l == LONG) { |
768 | l = NOTSPEC; | | 768 | l = NOTSPEC; |
769 | t = DOUBLE; | | 769 | t = DOUBLE; |
770 | if (!tflag) | | 770 | if (!tflag) |
771 | /* use 'double' instead of 'long ... */ | | 771 | /* use 'double' instead of 'long ... */ |
772 | warning(6); | | 772 | warning(6); |
773 | } | | 773 | } |
774 | break; | | 774 | break; |
775 | case DOUBLE: | | 775 | case DOUBLE: |
776 | if (l == LONG) { | | 776 | if (l == LONG) { |
777 | case LDOUBLE: | | 777 | case LDOUBLE: |
778 | l = NOTSPEC; | | 778 | l = NOTSPEC; |
779 | t = LDOUBLE; | | 779 | t = LDOUBLE; |
780 | if (tflag) | | 780 | if (tflag) |
781 | /* 'long double' is illegal in ... */ | | 781 | /* 'long double' is illegal in ... */ |
782 | warning(266); | | 782 | warning(266); |
783 | } | | 783 | } |
784 | break; | | 784 | break; |
785 | case DCOMPLEX: | | 785 | case DCOMPLEX: |
786 | if (l == LONG) { | | 786 | if (l == LONG) { |
787 | l = NOTSPEC; | | 787 | l = NOTSPEC; |
788 | t = LCOMPLEX; | | 788 | t = LCOMPLEX; |
789 | if (tflag) | | 789 | if (tflag) |
790 | /* 'long double' is illegal in ... */ | | 790 | /* 'long double' is illegal in ... */ |
791 | warning(266); | | 791 | warning(266); |
792 | } | | 792 | } |
793 | break; | | 793 | break; |
794 | case VOID: | | 794 | case VOID: |
795 | case FCOMPLEX: | | 795 | case FCOMPLEX: |
796 | case LCOMPLEX: | | 796 | case LCOMPLEX: |
797 | break; | | 797 | break; |
798 | default: | | 798 | default: |
799 | LERROR("deftyp(%s)", tspec_name(t)); | | 799 | LERROR("deftyp(%s)", tspec_name(t)); |
800 | } | | 800 | } |
801 | if (t != INT && t != CHAR && (s != NOTSPEC || l != NOTSPEC)) { | | 801 | if (t != INT && t != CHAR && (s != NOTSPEC || l != NOTSPEC)) { |
802 | dcs->d_terr = 1; | | 802 | dcs->d_terr = 1; |
803 | l = s = NOTSPEC; | | 803 | l = s = NOTSPEC; |
804 | } | | 804 | } |
805 | if (l != NOTSPEC) | | 805 | if (l != NOTSPEC) |
806 | t = l; | | 806 | t = l; |
807 | dcs->d_type = gettyp(merge_type_specifiers(t, s)); | | 807 | dcs->d_type = gettyp(merge_type_specifiers(t, s)); |
808 | } | | 808 | } |
809 | | | 809 | |
810 | if (dcs->d_mscl) { | | 810 | if (dcs->d_mscl) { |
811 | /* only one storage class allowed */ | | 811 | /* only one storage class allowed */ |
812 | error(7); | | 812 | error(7); |
813 | } | | 813 | } |
814 | if (dcs->d_terr) { | | 814 | if (dcs->d_terr) { |
815 | /* illegal type combination */ | | 815 | /* illegal type combination */ |
816 | error(4); | | 816 | error(4); |
817 | } | | 817 | } |
818 | | | 818 | |
819 | if (dcs->d_ctx == EXTERN) { | | 819 | if (dcs->d_ctx == EXTERN) { |
820 | if (scl == REG || scl == AUTO) { | | 820 | if (scl == REG || scl == AUTO) { |
821 | /* illegal storage class */ | | 821 | /* illegal storage class */ |
822 | error(8); | | 822 | error(8); |
823 | scl = NOSCL; | | 823 | scl = NOSCL; |
824 | } | | 824 | } |
825 | } else if (dcs->d_ctx == ARG || dcs->d_ctx == PARG) { | | 825 | } else if (dcs->d_ctx == ARG || dcs->d_ctx == PARG) { |
826 | if (scl != NOSCL && scl != REG) { | | 826 | if (scl != NOSCL && scl != REG) { |
827 | /* only register valid ... */ | | 827 | /* only register valid ... */ |
828 | error(9); | | 828 | error(9); |
829 | scl = NOSCL; | | 829 | scl = NOSCL; |
830 | } | | 830 | } |
831 | } | | 831 | } |
832 | | | 832 | |
833 | dcs->d_scl = scl; | | 833 | dcs->d_scl = scl; |
834 | | | 834 | |
835 | if (dcs->d_const && dcs->d_type->t_const) { | | 835 | if (dcs->d_const && dcs->d_type->t_const) { |
836 | lint_assert(dcs->d_type->t_typedef); | | 836 | lint_assert(dcs->d_type->t_typedef); |
837 | /* typedef already qualified with '%s' */ | | 837 | /* typedef already qualified with '%s' */ |
838 | warning(68, "const"); | | 838 | warning(68, "const"); |
839 | } | | 839 | } |
840 | if (dcs->d_volatile && dcs->d_type->t_volatile) { | | 840 | if (dcs->d_volatile && dcs->d_type->t_volatile) { |
841 | lint_assert(dcs->d_type->t_typedef); | | 841 | lint_assert(dcs->d_type->t_typedef); |
842 | /* typedef already qualified with '%s' */ | | 842 | /* typedef already qualified with '%s' */ |
843 | warning(68, "volatile"); | | 843 | warning(68, "volatile"); |
844 | } | | 844 | } |
845 | | | 845 | |
846 | if (dcs->d_const || dcs->d_volatile) { | | 846 | if (dcs->d_const || dcs->d_volatile) { |
847 | dcs->d_type = duptyp(dcs->d_type); | | 847 | dcs->d_type = duptyp(dcs->d_type); |
848 | dcs->d_type->t_const |= dcs->d_const; | | 848 | dcs->d_type->t_const |= dcs->d_const; |
849 | dcs->d_type->t_volatile |= dcs->d_volatile; | | 849 | dcs->d_type->t_volatile |= dcs->d_volatile; |
850 | } | | 850 | } |
851 | } | | 851 | } |
852 | | | 852 | |
853 | /* | | 853 | /* |
854 | * Merge type specifiers (char, ..., long long, signed, unsigned). | | 854 | * Merge type specifiers (char, ..., long long, signed, unsigned). |
855 | */ | | 855 | */ |
856 | static tspec_t | | 856 | static tspec_t |
857 | merge_type_specifiers(tspec_t t, tspec_t s) | | 857 | merge_type_specifiers(tspec_t t, tspec_t s) |
858 | { | | 858 | { |
859 | | | 859 | |
860 | if (s == SIGNED || s == UNSIGN) { | | 860 | if (s == SIGNED || s == UNSIGN) { |
861 | if (t == CHAR) { | | 861 | if (t == CHAR) { |
862 | t = s == SIGNED ? SCHAR : UCHAR; | | 862 | t = s == SIGNED ? SCHAR : UCHAR; |
863 | } else if (t == SHORT) { | | 863 | } else if (t == SHORT) { |
864 | t = s == SIGNED ? SHORT : USHORT; | | 864 | t = s == SIGNED ? SHORT : USHORT; |
865 | } else if (t == INT) { | | 865 | } else if (t == INT) { |
866 | t = s == SIGNED ? INT : UINT; | | 866 | t = s == SIGNED ? INT : UINT; |
867 | } else if (t == LONG) { | | 867 | } else if (t == LONG) { |
868 | t = s == SIGNED ? LONG : ULONG; | | 868 | t = s == SIGNED ? LONG : ULONG; |
869 | } else if (t == QUAD) { | | 869 | } else if (t == QUAD) { |
870 | t = s == SIGNED ? QUAD : UQUAD; | | 870 | t = s == SIGNED ? QUAD : UQUAD; |
871 | } | | 871 | } |
872 | } | | 872 | } |
873 | | | 873 | |
874 | return t; | | 874 | return t; |
875 | } | | 875 | } |
876 | | | 876 | |
877 | /* | | 877 | /* |
878 | * Return the length of a type in bits. | | 878 | * Return the length of a type in bits. |
879 | * | | 879 | * |
880 | * Printing a message if the outhermost dimension of an array is 0 must | | 880 | * Printing a message if the outhermost dimension of an array is 0 must |
881 | * be done by the caller. All other problems are reported by length() | | 881 | * be done by the caller. All other problems are reported by length() |
882 | * if name is not NULL. | | 882 | * if name is not NULL. |
883 | */ | | 883 | */ |
884 | int | | 884 | int |
885 | length(type_t *tp, const char *name) | | 885 | length(type_t *tp, const char *name) |
886 | { | | 886 | { |
887 | int elem, elsz; | | 887 | int elem, elsz; |
888 | | | 888 | |
889 | elem = 1; | | 889 | elem = 1; |
890 | while (tp && tp->t_tspec == ARRAY) { | | 890 | while (tp && tp->t_tspec == ARRAY) { |
891 | elem *= tp->t_dim; | | 891 | elem *= tp->t_dim; |
892 | tp = tp->t_subt; | | 892 | tp = tp->t_subt; |
893 | } | | 893 | } |
894 | if (tp == NULL) | | 894 | if (tp == NULL) |
895 | return -1; | | 895 | return -1; |
896 | | | 896 | |
897 | switch (tp->t_tspec) { | | 897 | switch (tp->t_tspec) { |
898 | case FUNC: | | 898 | case FUNC: |
899 | /* compiler takes size of function */ | | 899 | /* compiler takes size of function */ |
900 | LERROR("%s", msgs[12]); | | 900 | LERROR("%s", msgs[12]); |
901 | /* NOTREACHED */ | | 901 | /* NOTREACHED */ |
902 | case STRUCT: | | 902 | case STRUCT: |
903 | case UNION: | | 903 | case UNION: |
904 | if (incompl(tp) && name != NULL) { | | 904 | if (incompl(tp) && name != NULL) { |
905 | /* incomplete structure or union %s: %s */ | | 905 | /* incomplete structure or union %s: %s */ |
906 | error(31, tp->t_str->stag->s_name, name); | | 906 | error(31, tp->t_str->stag->s_name, name); |
907 | } | | 907 | } |
908 | elsz = tp->t_str->size; | | 908 | elsz = tp->t_str->size; |
909 | break; | | 909 | break; |
910 | case ENUM: | | 910 | case ENUM: |
911 | if (incompl(tp) && name != NULL) { | | 911 | if (incompl(tp) && name != NULL) { |
912 | /* incomplete enum type: %s */ | | 912 | /* incomplete enum type: %s */ |
913 | warning(13, name); | | 913 | warning(13, name); |
914 | } | | 914 | } |
915 | /* FALLTHROUGH */ | | 915 | /* FALLTHROUGH */ |
916 | default: | | 916 | default: |
917 | elsz = size(tp->t_tspec); | | 917 | elsz = size(tp->t_tspec); |
918 | if (elsz <= 0) | | 918 | if (elsz <= 0) |
919 | LERROR("length(%d)", elsz); | | 919 | LERROR("length(%d)", elsz); |
920 | break; | | 920 | break; |
921 | } | | 921 | } |
922 | return elem * elsz; | | 922 | return elem * elsz; |
923 | } | | 923 | } |
924 | | | 924 | |
925 | /* | | 925 | /* |
926 | * Get the alignment of the given Type in bits. | | 926 | * Get the alignment of the given Type in bits. |
927 | */ | | 927 | */ |
928 | int | | 928 | int |
929 | getbound(type_t *tp) | | 929 | getbound(type_t *tp) |
930 | { | | 930 | { |
931 | size_t a; | | 931 | size_t a; |
932 | tspec_t t; | | 932 | tspec_t t; |
933 | | | 933 | |
934 | while (tp && tp->t_tspec == ARRAY) | | 934 | while (tp && tp->t_tspec == ARRAY) |
935 | tp = tp->t_subt; | | 935 | tp = tp->t_subt; |
936 | | | 936 | |
937 | if (tp == NULL) | | 937 | if (tp == NULL) |
938 | return -1; | | 938 | return -1; |
939 | | | 939 | |
940 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { | | 940 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { |
941 | a = tp->t_str->align; | | 941 | a = tp->t_str->align; |
942 | } else if (t == FUNC) { | | 942 | } else if (t == FUNC) { |
943 | /* compiler takes alignment of function */ | | 943 | /* compiler takes alignment of function */ |
944 | error(14); | | 944 | error(14); |
945 | a = WORST_ALIGN(1) * CHAR_BIT; | | 945 | a = WORST_ALIGN(1) * CHAR_BIT; |
946 | } else { | | 946 | } else { |
947 | if ((a = size(t)) == 0) { | | 947 | if ((a = size(t)) == 0) { |
948 | a = CHAR_BIT; | | 948 | a = CHAR_BIT; |
949 | } else if (a > WORST_ALIGN(1) * CHAR_BIT) { | | 949 | } else if (a > WORST_ALIGN(1) * CHAR_BIT) { |
950 | a = WORST_ALIGN(1) * CHAR_BIT; | | 950 | a = WORST_ALIGN(1) * CHAR_BIT; |
951 | } | | 951 | } |
952 | } | | 952 | } |
953 | lint_assert(a >= CHAR_BIT); | | 953 | lint_assert(a >= CHAR_BIT); |
954 | lint_assert(a <= WORST_ALIGN(1) * CHAR_BIT); | | 954 | lint_assert(a <= WORST_ALIGN(1) * CHAR_BIT); |
955 | return a; | | 955 | return a; |
956 | } | | 956 | } |
957 | | | 957 | |
958 | /* | | 958 | /* |
959 | * Concatenate two lists of symbols by s_next. Used by declarations of | | 959 | * Concatenate two lists of symbols by s_next. Used by declarations of |
960 | * struct/union/enum elements and parameters. | | 960 | * struct/union/enum elements and parameters. |
961 | */ | | 961 | */ |
962 | sym_t * | | 962 | sym_t * |
963 | lnklst(sym_t *l1, sym_t *l2) | | 963 | lnklst(sym_t *l1, sym_t *l2) |
964 | { | | 964 | { |
965 | sym_t *l; | | 965 | sym_t *l; |
966 | | | 966 | |
967 | if ((l = l1) == NULL) | | 967 | if ((l = l1) == NULL) |
968 | return l2; | | 968 | return l2; |
969 | while (l1->s_next != NULL) | | 969 | while (l1->s_next != NULL) |
970 | l1 = l1->s_next; | | 970 | l1 = l1->s_next; |
971 | l1->s_next = l2; | | 971 | l1->s_next = l2; |
972 | return l; | | 972 | return l; |
973 | } | | 973 | } |
974 | | | 974 | |
975 | /* | | 975 | /* |
976 | * Check if the type of the given symbol is valid and print an error | | 976 | * Check if the type of the given symbol is valid and print an error |
977 | * message if it is not. | | 977 | * message if it is not. |
978 | * | | 978 | * |
979 | * Invalid types are: | | 979 | * Invalid types are: |
980 | * - arrays of incomlete types or functions | | 980 | * - arrays of incomlete types or functions |
981 | * - functions returning arrays or functions | | 981 | * - functions returning arrays or functions |
982 | * - void types other than type of function or pointer | | 982 | * - void types other than type of function or pointer |
983 | */ | | 983 | */ |
984 | void | | 984 | void |
985 | check_type(sym_t *sym) | | 985 | check_type(sym_t *sym) |
986 | { | | 986 | { |
987 | tspec_t to, t; | | 987 | tspec_t to, t; |
988 | type_t **tpp, *tp; | | 988 | type_t **tpp, *tp; |
989 | | | 989 | |
990 | tpp = &sym->s_type; | | 990 | tpp = &sym->s_type; |
991 | to = NOTSPEC; | | 991 | to = NOTSPEC; |
992 | while ((tp = *tpp) != NULL) { | | 992 | while ((tp = *tpp) != NULL) { |
993 | t = tp->t_tspec; | | 993 | t = tp->t_tspec; |
994 | /* | | 994 | /* |
995 | * If this is the type of an old style function definition, | | 995 | * If this is the type of an old style function definition, |
996 | * a better warning is printed in funcdef(). | | 996 | * a better warning is printed in funcdef(). |
997 | */ | | 997 | */ |
998 | if (t == FUNC && !tp->t_proto && | | 998 | if (t == FUNC && !tp->t_proto && |
999 | !(to == NOTSPEC && sym->s_osdef)) { | | 999 | !(to == NOTSPEC && sym->s_osdef)) { |
1000 | if (sflag && hflag) | | 1000 | if (sflag && hflag) |
1001 | /* function declaration is not a prototype */ | | 1001 | /* function declaration is not a prototype */ |
1002 | warning(287); | | 1002 | warning(287); |
1003 | } | | 1003 | } |
1004 | if (to == FUNC) { | | 1004 | if (to == FUNC) { |
1005 | if (t == FUNC || t == ARRAY) { | | 1005 | if (t == FUNC || t == ARRAY) { |
1006 | /* function returns illegal type */ | | 1006 | /* function returns illegal type */ |
1007 | error(15); | | 1007 | error(15); |
1008 | if (t == FUNC) { | | 1008 | if (t == FUNC) { |
1009 | *tpp = incref(*tpp, PTR); | | 1009 | *tpp = incref(*tpp, PTR); |
1010 | } else { | | 1010 | } else { |
1011 | *tpp = incref((*tpp)->t_subt, PTR); | | 1011 | *tpp = incref((*tpp)->t_subt, PTR); |
1012 | } | | 1012 | } |
1013 | return; | | 1013 | return; |
1014 | } else if (tp->t_const || tp->t_volatile) { | | 1014 | } else if (tp->t_const || tp->t_volatile) { |
1015 | if (sflag) { /* XXX oder better !tflag ? */ | | 1015 | if (sflag) { /* XXX oder better !tflag ? */ |
1016 | /* function cannot return const... */ | | 1016 | /* function cannot return const... */ |
1017 | warning(228); | | 1017 | warning(228); |
1018 | } | | 1018 | } |
1019 | } | | 1019 | } |
1020 | } if (to == ARRAY) { | | 1020 | } if (to == ARRAY) { |
1021 | if (t == FUNC) { | | 1021 | if (t == FUNC) { |
1022 | /* array of function is illegal */ | | 1022 | /* array of function is illegal */ |
1023 | error(16); | | 1023 | error(16); |
1024 | *tpp = gettyp(INT); | | 1024 | *tpp = gettyp(INT); |
1025 | return; | | 1025 | return; |
1026 | } else if (t == ARRAY && tp->t_dim == 0) { | | 1026 | } else if (t == ARRAY && tp->t_dim == 0) { |
1027 | /* null dimension */ | | 1027 | /* null dimension */ |
1028 | error(17); | | 1028 | error(17); |
1029 | return; | | 1029 | return; |
1030 | } else if (t == VOID) { | | 1030 | } else if (t == VOID) { |
1031 | /* illegal use of 'void' */ | | 1031 | /* illegal use of 'void' */ |
1032 | error(18); | | 1032 | error(18); |
1033 | *tpp = gettyp(INT); | | 1033 | *tpp = gettyp(INT); |
1034 | #if 0 /* errors are produced by length() */ | | 1034 | #if 0 /* errors are produced by length() */ |
1035 | } else if (incompl(tp)) { | | 1035 | } else if (incompl(tp)) { |
1036 | /* array of incomplete type */ | | 1036 | /* array of incomplete type */ |
1037 | if (sflag) { | | 1037 | if (sflag) { |
1038 | /* array of incomplete type */ | | 1038 | /* array of incomplete type */ |
1039 | error(301); | | 1039 | error(301); |
1040 | } else { | | 1040 | } else { |
1041 | /* array of incomplete type */ | | 1041 | /* array of incomplete type */ |
1042 | warning(301); | | 1042 | warning(301); |
1043 | } | | 1043 | } |
1044 | #endif | | 1044 | #endif |
1045 | } | | 1045 | } |
1046 | } else if (to == NOTSPEC && t == VOID) { | | 1046 | } else if (to == NOTSPEC && t == VOID) { |
1047 | if (dcs->d_ctx == PARG) { | | 1047 | if (dcs->d_ctx == PARG) { |
1048 | if (sym->s_scl != ABSTRACT) { | | 1048 | if (sym->s_scl != ABSTRACT) { |
1049 | lint_assert(sym->s_name != unnamed); | | 1049 | lint_assert(sym->s_name != unnamed); |
1050 | /* void param. cannot have name: %s */ | | 1050 | /* void param. cannot have name: %s */ |
1051 | error(61, sym->s_name); | | 1051 | error(61, sym->s_name); |
1052 | *tpp = gettyp(INT); | | 1052 | *tpp = gettyp(INT); |
1053 | } | | 1053 | } |
1054 | } else if (dcs->d_ctx == ABSTRACT) { | | 1054 | } else if (dcs->d_ctx == ABSTRACT) { |
1055 | /* ok */ | | 1055 | /* ok */ |
1056 | } else if (sym->s_scl != TYPEDEF) { | | 1056 | } else if (sym->s_scl != TYPEDEF) { |
1057 | /* void type for %s */ | | 1057 | /* void type for %s */ |
1058 | error(19, sym->s_name); | | 1058 | error(19, sym->s_name); |
1059 | *tpp = gettyp(INT); | | 1059 | *tpp = gettyp(INT); |
1060 | } | | 1060 | } |
1061 | } | | 1061 | } |
1062 | if (t == VOID && to != PTR) { | | 1062 | if (t == VOID && to != PTR) { |
1063 | if (tp->t_const || tp->t_volatile) { | | 1063 | if (tp->t_const || tp->t_volatile) { |
1064 | /* inappropriate qualifiers with 'void' */ | | 1064 | /* inappropriate qualifiers with 'void' */ |
1065 | warning(69); | | 1065 | warning(69); |
1066 | tp->t_const = tp->t_volatile = 0; | | 1066 | tp->t_const = tp->t_volatile = 0; |
1067 | } | | 1067 | } |
1068 | } | | 1068 | } |
1069 | tpp = &tp->t_subt; | | 1069 | tpp = &tp->t_subt; |
1070 | to = t; | | 1070 | to = t; |
1071 | } | | 1071 | } |
1072 | } | | 1072 | } |
1073 | | | 1073 | |
1074 | /* | | 1074 | /* |
1075 | * Process the declarator of a struct/union element. | | 1075 | * Process the declarator of a struct/union element. |
1076 | */ | | 1076 | */ |
1077 | sym_t * | | 1077 | sym_t * |
1078 | declarator_1_struct_union(sym_t *dsym) | | 1078 | declarator_1_struct_union(sym_t *dsym) |
1079 | { | | 1079 | { |
1080 | type_t *tp; | | 1080 | type_t *tp; |
1081 | tspec_t t; | | 1081 | tspec_t t; |
1082 | int sz, len; | | 1082 | int sz, len; |
1083 | int o = 0; /* Appease gcc */ | | 1083 | int o = 0; /* Appease gcc */ |
1084 | scl_t sc; | | 1084 | scl_t sc; |
1085 | | | 1085 | |
1086 | lint_assert((sc = dsym->s_scl) == MOS || sc == MOU); | | 1086 | lint_assert((sc = dsym->s_scl) == MOS || sc == MOU); |
1087 | | | 1087 | |
1088 | if (dcs->d_rdcsym != NULL) { | | 1088 | if (dcs->d_rdcsym != NULL) { |
1089 | /* should be ensured by storesym() */ | | 1089 | /* should be ensured by storesym() */ |
1090 | lint_assert((sc = dcs->d_rdcsym->s_scl) == MOS || sc == MOU); | | 1090 | lint_assert((sc = dcs->d_rdcsym->s_scl) == MOS || sc == MOU); |
1091 | if (dsym->s_styp == dcs->d_rdcsym->s_styp) { | | 1091 | if (dsym->s_styp == dcs->d_rdcsym->s_styp) { |
1092 | /* duplicate member name: %s */ | | 1092 | /* duplicate member name: %s */ |
1093 | error(33, dsym->s_name); | | 1093 | error(33, dsym->s_name); |
1094 | rmsym(dcs->d_rdcsym); | | 1094 | rmsym(dcs->d_rdcsym); |
1095 | } | | 1095 | } |
1096 | } | | 1096 | } |
1097 | | | 1097 | |
1098 | check_type(dsym); | | 1098 | check_type(dsym); |
1099 | | | 1099 | |
1100 | t = (tp = dsym->s_type)->t_tspec; | | 1100 | t = (tp = dsym->s_type)->t_tspec; |
1101 | | | 1101 | |
1102 | if (dsym->s_bitfield) { | | 1102 | if (dsym->s_bitfield) { |
1103 | /* | | 1103 | /* |
1104 | * only unsigned and signed int are portable bit-field types | | 1104 | * only unsigned and signed int are portable bit-field types |
1105 | *(at least in ANSI C, in traditional C only unsigned int) | | 1105 | *(at least in ANSI C, in traditional C only unsigned int) |
1106 | */ | | 1106 | */ |
1107 | if (t == CHAR || t == UCHAR || t == SCHAR || | | 1107 | if (t == CHAR || t == UCHAR || t == SCHAR || |
1108 | t == SHORT || t == USHORT || t == ENUM) { | | 1108 | t == SHORT || t == USHORT || t == ENUM) { |
1109 | if (bitfieldtype_ok == 0) { | | 1109 | if (bitfieldtype_ok == 0) { |
1110 | if (sflag) { | | 1110 | if (sflag) { |
1111 | /* bit-field type '%s' invalid ... */ | | 1111 | /* bit-field type '%s' invalid ... */ |
1112 | warning(273, type_name(tp)); | | 1112 | warning(273, type_name(tp)); |
1113 | } else if (pflag) { | | 1113 | } else if (pflag) { |
1114 | /* nonportable bit-field type */ | | 1114 | /* nonportable bit-field type */ |
1115 | warning(34); | | 1115 | warning(34); |
1116 | } | | 1116 | } |
1117 | } | | 1117 | } |
1118 | } else if (t == INT && dcs->d_smod == NOTSPEC) { | | 1118 | } else if (t == INT && dcs->d_smod == NOTSPEC) { |
1119 | if (pflag && bitfieldtype_ok == 0) { | | 1119 | if (pflag && bitfieldtype_ok == 0) { |
1120 | /* nonportable bit-field type */ | | 1120 | /* nonportable bit-field type */ |
1121 | warning(34); | | 1121 | warning(34); |
1122 | } | | 1122 | } |
1123 | } else if (t != INT && t != UINT && t != BOOL) { | | 1123 | } else if (t != INT && t != UINT && t != BOOL) { |
1124 | /* | | 1124 | /* |
1125 | * Non-integer types are always illegal for | | 1125 | * Non-integer types are always illegal for |
1126 | * bitfields, regardless of BITFIELDTYPE. | | 1126 | * bitfields, regardless of BITFIELDTYPE. |
1127 | * Integer types not dealt with above are | | 1127 | * Integer types not dealt with above are |
1128 | * okay only if BITFIELDTYPE is in effect. | | 1128 | * okay only if BITFIELDTYPE is in effect. |
1129 | */ | | 1129 | */ |
1130 | if (bitfieldtype_ok == 0 || tspec_is_int(t) == 0) { | | 1130 | if (bitfieldtype_ok == 0 || tspec_is_int(t) == 0) { |
1131 | /* illegal bit-field type */ | | 1131 | /* illegal bit-field type */ |
1132 | warning(35); | | 1132 | warning(35); |
1133 | sz = tp->t_flen; | | 1133 | sz = tp->t_flen; |
1134 | dsym->s_type = tp = duptyp(gettyp(t = INT)); | | 1134 | dsym->s_type = tp = duptyp(gettyp(t = INT)); |
1135 | if ((tp->t_flen = sz) > size(t)) | | 1135 | if ((tp->t_flen = sz) > size(t)) |
1136 | tp->t_flen = size(t); | | 1136 | tp->t_flen = size(t); |
1137 | } | | 1137 | } |
1138 | } | | 1138 | } |
1139 | if ((len = tp->t_flen) < 0 || len > (ssize_t)size(t)) { | | 1139 | if ((len = tp->t_flen) < 0 || len > (ssize_t)size(t)) { |
1140 | /* illegal bit-field size: %d */ | | 1140 | /* illegal bit-field size: %d */ |
1141 | error(36, len); | | 1141 | error(36, len); |
1142 | tp->t_flen = size(t); | | 1142 | tp->t_flen = size(t); |
1143 | } else if (len == 0 && dsym->s_name != unnamed) { | | 1143 | } else if (len == 0 && dsym->s_name != unnamed) { |
1144 | /* zero size bit-field */ | | 1144 | /* zero size bit-field */ |
1145 | error(37); | | 1145 | error(37); |
1146 | tp->t_flen = size(t); | | 1146 | tp->t_flen = size(t); |
1147 | } | | 1147 | } |
1148 | if (dsym->s_scl == MOU) { | | 1148 | if (dsym->s_scl == MOU) { |
1149 | /* illegal use of bit-field */ | | 1149 | /* illegal use of bit-field */ |
1150 | error(41); | | 1150 | error(41); |
1151 | dsym->s_type->t_isfield = 0; | | 1151 | dsym->s_type->t_isfield = 0; |
1152 | dsym->s_bitfield = 0; | | 1152 | dsym->s_bitfield = 0; |
1153 | } | | 1153 | } |
1154 | } else if (t == FUNC) { | | 1154 | } else if (t == FUNC) { |
1155 | /* function illegal in structure or union */ | | 1155 | /* function illegal in structure or union */ |
1156 | error(38); | | 1156 | error(38); |
1157 | dsym->s_type = tp = incref(tp, t = PTR); | | 1157 | dsym->s_type = tp = incref(tp, t = PTR); |
1158 | } | | 1158 | } |
1159 | | | 1159 | |
1160 | /* | | 1160 | /* |
1161 | * bit-fields of length 0 are not warned about because length() | | 1161 | * bit-fields of length 0 are not warned about because length() |
1162 | * does not return the length of the bit-field but the length | | 1162 | * does not return the length of the bit-field but the length |
1163 | * of the type the bit-field is packed in (it's ok) | | 1163 | * of the type the bit-field is packed in (it's ok) |
1164 | */ | | 1164 | */ |
1165 | if ((sz = length(dsym->s_type, dsym->s_name)) == 0) { | | 1165 | if ((sz = length(dsym->s_type, dsym->s_name)) == 0) { |
1166 | if (t == ARRAY && dsym->s_type->t_dim == 0) { | | 1166 | if (t == ARRAY && dsym->s_type->t_dim == 0) { |
1167 | /* zero sized array in struct is a C99 extension: %s */ | | 1167 | /* zero sized array in struct is a C99 extension: %s */ |
1168 | c99ism(39, dsym->s_name); | | 1168 | c99ism(39, dsym->s_name); |
1169 | } | | 1169 | } |
1170 | } | | 1170 | } |
1171 | | | 1171 | |
1172 | if (dcs->d_ctx == MOU) { | | 1172 | if (dcs->d_ctx == MOU) { |
1173 | o = dcs->d_offset; | | 1173 | o = dcs->d_offset; |
1174 | dcs->d_offset = 0; | | 1174 | dcs->d_offset = 0; |
1175 | } | | 1175 | } |
1176 | if (dsym->s_bitfield) { | | 1176 | if (dsym->s_bitfield) { |
1177 | align(getbound(tp), tp->t_flen); | | 1177 | align(getbound(tp), tp->t_flen); |
1178 | dsym->s_value.v_quad = (dcs->d_offset / size(t)) * size(t); | | 1178 | dsym->s_value.v_quad = (dcs->d_offset / size(t)) * size(t); |
1179 | tp->t_foffs = dcs->d_offset - (int)dsym->s_value.v_quad; | | 1179 | tp->t_foffs = dcs->d_offset - (int)dsym->s_value.v_quad; |
1180 | dcs->d_offset += tp->t_flen; | | 1180 | dcs->d_offset += tp->t_flen; |
1181 | } else { | | 1181 | } else { |
1182 | align(getbound(tp), 0); | | 1182 | align(getbound(tp), 0); |
1183 | dsym->s_value.v_quad = dcs->d_offset; | | 1183 | dsym->s_value.v_quad = dcs->d_offset; |
1184 | dcs->d_offset += sz; | | 1184 | dcs->d_offset += sz; |
1185 | } | | 1185 | } |
1186 | if (dcs->d_ctx == MOU) { | | 1186 | if (dcs->d_ctx == MOU) { |
1187 | if (o > dcs->d_offset) | | 1187 | if (o > dcs->d_offset) |
1188 | dcs->d_offset = o; | | 1188 | dcs->d_offset = o; |
1189 | } | | 1189 | } |
1190 | | | 1190 | |
1191 | check_function_definition(dsym, 0); | | 1191 | check_function_definition(dsym, 0); |
1192 | | | 1192 | |
1193 | /* | | 1193 | /* |
1194 | * Clear the BITFIELDTYPE indicator after processing each | | 1194 | * Clear the BITFIELDTYPE indicator after processing each |
1195 | * structure element. | | 1195 | * structure element. |
1196 | */ | | 1196 | */ |
1197 | bitfieldtype_ok = 0; | | 1197 | bitfieldtype_ok = 0; |
1198 | | | 1198 | |
1199 | return dsym; | | 1199 | return dsym; |
1200 | } | | 1200 | } |
1201 | | | 1201 | |
1202 | /* | | 1202 | /* |
1203 | * Aligns next structure element as required. | | 1203 | * Aligns next structure element as required. |
1204 | * | | 1204 | * |
1205 | * al contains the required alignment, len the length of a bit-field. | | 1205 | * al contains the required alignment, len the length of a bit-field. |
1206 | */ | | 1206 | */ |
1207 | static void | | 1207 | static void |
1208 | align(int al, int len) | | 1208 | align(int al, int len) |
1209 | { | | 1209 | { |
1210 | int no; | | 1210 | int no; |
1211 | | | 1211 | |
1212 | /* | | 1212 | /* |
1213 | * The alignment of the current element becomes the alignment of | | 1213 | * The alignment of the current element becomes the alignment of |
1214 | * the struct/union if it is larger than the current alignment | | 1214 | * the struct/union if it is larger than the current alignment |
1215 | * of the struct/union. | | 1215 | * of the struct/union. |
1216 | */ | | 1216 | */ |
1217 | if (al > dcs->d_stralign) | | 1217 | if (al > dcs->d_stralign) |
1218 | dcs->d_stralign = al; | | 1218 | dcs->d_stralign = al; |
1219 | | | 1219 | |
1220 | no = (dcs->d_offset + (al - 1)) & ~(al - 1); | | 1220 | no = (dcs->d_offset + (al - 1)) & ~(al - 1); |
1221 | if (len == 0 || dcs->d_offset + len > no) | | 1221 | if (len == 0 || dcs->d_offset + len > no) |
1222 | dcs->d_offset = no; | | 1222 | dcs->d_offset = no; |
1223 | } | | 1223 | } |
1224 | | | 1224 | |
1225 | /* | | 1225 | /* |
1226 | * Remember the width of the field in its type structure. | | 1226 | * Remember the width of the field in its type structure. |
1227 | */ | | 1227 | */ |
1228 | sym_t * | | 1228 | sym_t * |
1229 | bitfield(sym_t *dsym, int len) | | 1229 | bitfield(sym_t *dsym, int len) |
1230 | { | | 1230 | { |
1231 | | | 1231 | |
1232 | if (dsym == NULL) { | | 1232 | if (dsym == NULL) { |
1233 | dsym = getblk(sizeof (sym_t)); | | 1233 | dsym = getblk(sizeof (sym_t)); |
1234 | dsym->s_name = unnamed; | | 1234 | dsym->s_name = unnamed; |
1235 | dsym->s_kind = FMEMBER; | | 1235 | dsym->s_kind = FMEMBER; |
1236 | dsym->s_scl = MOS; | | 1236 | dsym->s_scl = MOS; |
1237 | dsym->s_type = gettyp(UINT); | | 1237 | dsym->s_type = gettyp(UINT); |
1238 | dsym->s_blklev = -1; | | 1238 | dsym->s_blklev = -1; |
1239 | } | | 1239 | } |
1240 | dsym->s_type = duptyp(dsym->s_type); | | 1240 | dsym->s_type = duptyp(dsym->s_type); |
1241 | dsym->s_type->t_isfield = 1; | | 1241 | dsym->s_type->t_isfield = 1; |
1242 | dsym->s_type->t_flen = len; | | 1242 | dsym->s_type->t_flen = len; |
1243 | dsym->s_bitfield = 1; | | 1243 | dsym->s_bitfield = 1; |
1244 | return dsym; | | 1244 | return dsym; |
1245 | } | | 1245 | } |
1246 | | | 1246 | |
1247 | /* | | 1247 | /* |
1248 | * Collect information about a sequence of asterisks and qualifiers in a | | 1248 | * Collect information about a sequence of asterisks and qualifiers in a |
1249 | * list of type pqinf_t. | | 1249 | * list of type pqinf_t. |
1250 | * Qualifiers always refer to the left asterisk. | | 1250 | * Qualifiers always refer to the left asterisk. |
1251 | * The rightmost asterisk will be at the top of the list. | | 1251 | * The rightmost asterisk will be at the top of the list. |
1252 | */ | | 1252 | */ |
1253 | pqinf_t * | | 1253 | pqinf_t * |
1254 | merge_pointers_and_qualifiers(pqinf_t *p1, pqinf_t *p2) | | 1254 | merge_pointers_and_qualifiers(pqinf_t *p1, pqinf_t *p2) |
1255 | { | | 1255 | { |
1256 | pqinf_t *p; | | 1256 | pqinf_t *p; |
1257 | | | 1257 | |
1258 | if (p2->p_pcnt != 0) { | | 1258 | if (p2->p_pcnt != 0) { |
1259 | /* left '*' at the end of the list */ | | 1259 | /* left '*' at the end of the list */ |
1260 | for (p = p2; p->p_next != NULL; p = p->p_next) | | 1260 | for (p = p2; p->p_next != NULL; p = p->p_next) |
1261 | continue; | | 1261 | continue; |
1262 | p->p_next = p1; | | 1262 | p->p_next = p1; |
1263 | return p2; | | 1263 | return p2; |
1264 | } else { | | 1264 | } else { |
1265 | if (p2->p_const) { | | 1265 | if (p2->p_const) { |
1266 | if (p1->p_const) { | | 1266 | if (p1->p_const) { |
1267 | /* duplicate '%s' */ | | 1267 | /* duplicate '%s' */ |
1268 | warning(10, "const"); | | 1268 | warning(10, "const"); |
1269 | } | | 1269 | } |
1270 | p1->p_const = 1; | | 1270 | p1->p_const = 1; |
1271 | } | | 1271 | } |
1272 | if (p2->p_volatile) { | | 1272 | if (p2->p_volatile) { |
1273 | if (p1->p_volatile) { | | 1273 | if (p1->p_volatile) { |
1274 | /* duplicate '%s' */ | | 1274 | /* duplicate '%s' */ |
1275 | warning(10, "volatile"); | | 1275 | warning(10, "volatile"); |
1276 | } | | 1276 | } |
1277 | p1->p_volatile = 1; | | 1277 | p1->p_volatile = 1; |
1278 | } | | 1278 | } |
1279 | free(p2); | | 1279 | free(p2); |
1280 | return p1; | | 1280 | return p1; |
1281 | } | | 1281 | } |
1282 | } | | 1282 | } |
1283 | | | 1283 | |
1284 | /* | | 1284 | /* |
1285 | * The following 3 functions extend the type of a declarator with | | 1285 | * The following 3 functions extend the type of a declarator with |
1286 | * pointer, function and array types. | | 1286 | * pointer, function and array types. |
1287 | * | | 1287 | * |
1288 | * The current type is the Type built by deftyp() (dcs->d_type) and | | 1288 | * The current type is the Type built by deftyp() (dcs->d_type) and |
1289 | * pointer, function and array types already added for this | | 1289 | * pointer, function and array types already added for this |
1290 | * declarator. The new type extension is inserted between both. | | 1290 | * declarator. The new type extension is inserted between both. |
1291 | */ | | 1291 | */ |
1292 | sym_t * | | 1292 | sym_t * |
1293 | add_pointer(sym_t *decl, pqinf_t *pi) | | 1293 | add_pointer(sym_t *decl, pqinf_t *pi) |
1294 | { | | 1294 | { |
1295 | type_t **tpp, *tp; | | 1295 | type_t **tpp, *tp; |
1296 | pqinf_t *npi; | | 1296 | pqinf_t *npi; |
1297 | | | 1297 | |
1298 | tpp = &decl->s_type; | | 1298 | tpp = &decl->s_type; |
1299 | while (*tpp && *tpp != dcs->d_type) | | 1299 | while (*tpp && *tpp != dcs->d_type) |
1300 | tpp = &(*tpp)->t_subt; | | 1300 | tpp = &(*tpp)->t_subt; |
1301 | if (*tpp == NULL) | | 1301 | if (*tpp == NULL) |
1302 | return decl; | | 1302 | return decl; |
1303 | | | 1303 | |
1304 | while (pi != NULL) { | | 1304 | while (pi != NULL) { |
1305 | *tpp = tp = getblk(sizeof (type_t)); | | 1305 | *tpp = tp = getblk(sizeof (type_t)); |
1306 | tp->t_tspec = PTR; | | 1306 | tp->t_tspec = PTR; |
1307 | tp->t_const = pi->p_const; | | 1307 | tp->t_const = pi->p_const; |
1308 | tp->t_volatile = pi->p_volatile; | | 1308 | tp->t_volatile = pi->p_volatile; |
1309 | *(tpp = &tp->t_subt) = dcs->d_type; | | 1309 | *(tpp = &tp->t_subt) = dcs->d_type; |
1310 | npi = pi->p_next; | | 1310 | npi = pi->p_next; |
1311 | free(pi); | | 1311 | free(pi); |
1312 | pi = npi; | | 1312 | pi = npi; |
1313 | } | | 1313 | } |
1314 | return decl; | | 1314 | return decl; |
1315 | } | | 1315 | } |
1316 | | | 1316 | |
1317 | /* | | 1317 | /* |
1318 | * If a dimension was specified, dim is 1, otherwise 0 | | 1318 | * If a dimension was specified, dim is 1, otherwise 0 |
1319 | * n is the specified dimension | | 1319 | * n is the specified dimension |
1320 | */ | | 1320 | */ |
1321 | sym_t * | | 1321 | sym_t * |
1322 | add_array(sym_t *decl, int dim, int n) | | 1322 | add_array(sym_t *decl, int dim, int n) |
1323 | { | | 1323 | { |
1324 | type_t **tpp, *tp; | | 1324 | type_t **tpp, *tp; |
1325 | | | 1325 | |
1326 | tpp = &decl->s_type; | | 1326 | tpp = &decl->s_type; |
1327 | while (*tpp && *tpp != dcs->d_type) | | 1327 | while (*tpp && *tpp != dcs->d_type) |
1328 | tpp = &(*tpp)->t_subt; | | 1328 | tpp = &(*tpp)->t_subt; |
1329 | if (*tpp == NULL) | | 1329 | if (*tpp == NULL) |
1330 | return decl; | | 1330 | return decl; |
1331 | | | 1331 | |
1332 | *tpp = tp = getblk(sizeof (type_t)); | | 1332 | *tpp = tp = getblk(sizeof (type_t)); |
1333 | tp->t_tspec = ARRAY; | | 1333 | tp->t_tspec = ARRAY; |
1334 | tp->t_subt = dcs->d_type; | | 1334 | tp->t_subt = dcs->d_type; |
1335 | tp->t_dim = n; | | 1335 | tp->t_dim = n; |
1336 | | | 1336 | |
1337 | if (n < 0) { | | 1337 | if (n < 0) { |
1338 | /* negative array dimension (%d) */ | | 1338 | /* negative array dimension (%d) */ |
1339 | error(20, n); | | 1339 | error(20, n); |
1340 | n = 0; | | 1340 | n = 0; |
1341 | } else if (n == 0 && dim) { | | 1341 | } else if (n == 0 && dim) { |
1342 | /* zero sized array is a C99 extension */ | | 1342 | /* zero sized array is a C99 extension */ |
1343 | c99ism(322); | | 1343 | c99ism(322); |
1344 | } else if (n == 0 && !dim) { | | 1344 | } else if (n == 0 && !dim) { |
1345 | setcomplete(tp, 0); | | 1345 | setcomplete(tp, 0); |
1346 | } | | 1346 | } |
1347 | | | 1347 | |
1348 | return decl; | | 1348 | return decl; |
1349 | } | | 1349 | } |
1350 | | | 1350 | |
1351 | sym_t * | | 1351 | sym_t * |
1352 | add_function(sym_t *decl, sym_t *args) | | 1352 | add_function(sym_t *decl, sym_t *args) |
1353 | { | | 1353 | { |
1354 | type_t **tpp, *tp; | | 1354 | type_t **tpp, *tp; |
1355 | | | 1355 | |
1356 | if (dcs->d_proto) { | | 1356 | if (dcs->d_proto) { |
1357 | if (tflag) | | 1357 | if (tflag) |
1358 | /* function prototypes are illegal in traditional C */ | | 1358 | /* function prototypes are illegal in traditional C */ |
1359 | warning(270); | | 1359 | warning(270); |
1360 | args = new_style_function(decl, args); | | 1360 | args = new_style_function(decl, args); |
1361 | } else { | | 1361 | } else { |
1362 | old_style_function(decl, args); | | 1362 | old_style_function(decl, args); |
1363 | } | | 1363 | } |
1364 | | | 1364 | |
1365 | /* | | 1365 | /* |
1366 | * The symbols are removed from the symbol table by popdecl() after | | 1366 | * The symbols are removed from the symbol table by popdecl() after |
1367 | * add_function(). To be able to restore them if this is a function | | 1367 | * add_function(). To be able to restore them if this is a function |
1368 | * definition, a pointer to the list of all symbols is stored in | | 1368 | * definition, a pointer to the list of all symbols is stored in |
1369 | * dcs->d_next->d_fpsyms. Also a list of the arguments (concatenated | | 1369 | * dcs->d_next->d_fpsyms. Also a list of the arguments (concatenated |
1370 | * by s_next) is stored in dcs->d_next->d_fargs. | | 1370 | * by s_next) is stored in dcs->d_next->d_fargs. |
1371 | * (dcs->d_next must be used because *dcs is the declaration stack | | 1371 | * (dcs->d_next must be used because *dcs is the declaration stack |
1372 | * element created for the list of params and is removed after | | 1372 | * element created for the list of params and is removed after |
1373 | * add_function()) | | 1373 | * add_function()) |
1374 | */ | | 1374 | */ |
1375 | if (dcs->d_next->d_ctx == EXTERN && | | 1375 | if (dcs->d_next->d_ctx == EXTERN && |
1376 | decl->s_type == dcs->d_next->d_type) { | | 1376 | decl->s_type == dcs->d_next->d_type) { |
1377 | dcs->d_next->d_fpsyms = dcs->d_dlsyms; | | 1377 | dcs->d_next->d_fpsyms = dcs->d_dlsyms; |
1378 | dcs->d_next->d_fargs = args; | | 1378 | dcs->d_next->d_fargs = args; |
1379 | } | | 1379 | } |
1380 | | | 1380 | |
1381 | tpp = &decl->s_type; | | 1381 | tpp = &decl->s_type; |
1382 | while (*tpp && *tpp != dcs->d_next->d_type) | | 1382 | while (*tpp && *tpp != dcs->d_next->d_type) |
1383 | tpp = &(*tpp)->t_subt; | | 1383 | tpp = &(*tpp)->t_subt; |
1384 | if (*tpp == NULL) | | 1384 | if (*tpp == NULL) |
1385 | return decl; | | 1385 | return decl; |
1386 | | | 1386 | |
1387 | *tpp = tp = getblk(sizeof (type_t)); | | 1387 | *tpp = tp = getblk(sizeof (type_t)); |
1388 | tp->t_tspec = FUNC; | | 1388 | tp->t_tspec = FUNC; |
1389 | tp->t_subt = dcs->d_next->d_type; | | 1389 | tp->t_subt = dcs->d_next->d_type; |
1390 | if ((tp->t_proto = dcs->d_proto) != 0) | | 1390 | if ((tp->t_proto = dcs->d_proto) != 0) |
1391 | tp->t_args = args; | | 1391 | tp->t_args = args; |
1392 | tp->t_vararg = dcs->d_vararg; | | 1392 | tp->t_vararg = dcs->d_vararg; |
1393 | | | 1393 | |
1394 | return decl; | | 1394 | return decl; |
1395 | } | | 1395 | } |
1396 | | | 1396 | |
1397 | /* | | 1397 | /* |
1398 | * Called for new style function declarations. | | 1398 | * Called for new style function declarations. |