lint: unabbreviate some fields in sym_t No functional change.diff -r1.247 -r1.248 src/usr.bin/xlint/lint1/decl.c
(rillig)
--- src/usr.bin/xlint/lint1/decl.c 2022/02/27 10:31:58 1.247
+++ src/usr.bin/xlint/lint1/decl.c 2022/02/27 10:44:45 1.248
@@ -1,3353 +1,3353 @@ | @@ -1,3353 +1,3353 @@ | |||
1 | /* $NetBSD: decl.c,v 1.247 2022/02/27 10:31:58 rillig Exp $ */ | 1 | /* $NetBSD: decl.c,v 1.248 2022/02/27 10:44:45 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.247 2022/02/27 10:31:58 rillig Exp $"); | 41 | __RCSID("$NetBSD: decl.c,v 1.248 2022/02/27 10:44:45 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 void align(unsigned int, unsigned int); | 67 | static void align(unsigned int, unsigned int); | |
68 | static sym_t *newtag(sym_t *, scl_t, bool, bool); | 68 | static sym_t *newtag(sym_t *, scl_t, bool, bool); | |
69 | static bool eqargs(const type_t *, const type_t *, bool *); | 69 | static bool eqargs(const type_t *, const type_t *, bool *); | |
70 | static bool mnoarg(const type_t *, bool *); | 70 | static bool mnoarg(const type_t *, bool *); | |
71 | static bool check_old_style_definition(sym_t *, sym_t *); | 71 | static bool check_old_style_definition(sym_t *, sym_t *); | |
72 | static bool check_prototype_declaration(sym_t *, sym_t *); | 72 | static bool check_prototype_declaration(sym_t *, sym_t *); | |
73 | static sym_t *new_style_function(sym_t *, sym_t *); | 73 | static sym_t *new_style_function(sym_t *, sym_t *); | |
74 | static void old_style_function(sym_t *, sym_t *); | 74 | static void old_style_function(sym_t *, sym_t *); | |
75 | static void declare_external_in_block(sym_t *); | 75 | static void declare_external_in_block(sym_t *); | |
76 | static bool check_init(sym_t *); | 76 | static bool check_init(sym_t *); | |
77 | static void check_argument_usage(bool, sym_t *); | 77 | static void check_argument_usage(bool, sym_t *); | |
78 | static void check_variable_usage(bool, sym_t *); | 78 | static void check_variable_usage(bool, sym_t *); | |
79 | static void check_label_usage(sym_t *); | 79 | static void check_label_usage(sym_t *); | |
80 | static void check_tag_usage(sym_t *); | 80 | static void check_tag_usage(sym_t *); | |
81 | static void check_global_variable(const sym_t *); | 81 | static void check_global_variable(const sym_t *); | |
82 | static void check_global_variable_size(const sym_t *); | 82 | static void check_global_variable_size(const sym_t *); | |
83 | 83 | |||
84 | /* | 84 | /* | |
85 | * initializes all global vars used in declarations | 85 | * initializes all global vars used in declarations | |
86 | */ | 86 | */ | |
87 | void | 87 | void | |
88 | #ifdef __sh3__ | 88 | #ifdef __sh3__ | |
89 | /* XXX port-sh3/56311 */ | 89 | /* XXX port-sh3/56311 */ | |
90 | __attribute__((optimize("O0"))) | 90 | __attribute__((optimize("O0"))) | |
91 | #endif | 91 | #endif | |
92 | initdecl(void) | 92 | initdecl(void) | |
93 | { | 93 | { | |
94 | int i; | 94 | int i; | |
95 | 95 | |||
96 | /* declaration stack */ | 96 | /* declaration stack */ | |
97 | dcs = xcalloc(1, sizeof(*dcs)); | 97 | dcs = xcalloc(1, sizeof(*dcs)); | |
98 | dcs->d_ctx = EXTERN; | 98 | dcs->d_ctx = EXTERN; | |
99 | dcs->d_ldlsym = &dcs->d_dlsyms; | 99 | dcs->d_ldlsym = &dcs->d_dlsyms; | |
100 | 100 | |||
101 | /* type information and classification */ | 101 | /* type information and classification */ | |
102 | inittyp(); | 102 | inittyp(); | |
103 | 103 | |||
104 | /* shared type structures */ | 104 | /* shared type structures */ | |
105 | typetab = xcalloc(NTSPEC, sizeof(*typetab)); | 105 | typetab = xcalloc(NTSPEC, sizeof(*typetab)); | |
106 | for (i = 0; i < NTSPEC; i++) | 106 | for (i = 0; i < NTSPEC; i++) | |
107 | typetab[i].t_tspec = NOTSPEC; | 107 | typetab[i].t_tspec = NOTSPEC; | |
108 | 108 | |||
109 | /* | 109 | /* | |
110 | * The following two are not real types. They are only used by the | 110 | * The following two are not real types. They are only used by the | |
111 | * parser to handle the keywords "signed" and "unsigned". | 111 | * parser to handle the keywords "signed" and "unsigned". | |
112 | */ | 112 | */ | |
113 | typetab[SIGNED].t_tspec = SIGNED; | 113 | typetab[SIGNED].t_tspec = SIGNED; | |
114 | typetab[UNSIGN].t_tspec = UNSIGN; | 114 | typetab[UNSIGN].t_tspec = UNSIGN; | |
115 | 115 | |||
116 | typetab[BOOL].t_tspec = BOOL; | 116 | typetab[BOOL].t_tspec = BOOL; | |
117 | typetab[CHAR].t_tspec = CHAR; | 117 | typetab[CHAR].t_tspec = CHAR; | |
118 | typetab[SCHAR].t_tspec = SCHAR; | 118 | typetab[SCHAR].t_tspec = SCHAR; | |
119 | typetab[UCHAR].t_tspec = UCHAR; | 119 | typetab[UCHAR].t_tspec = UCHAR; | |
120 | typetab[SHORT].t_tspec = SHORT; | 120 | typetab[SHORT].t_tspec = SHORT; | |
121 | typetab[USHORT].t_tspec = USHORT; | 121 | typetab[USHORT].t_tspec = USHORT; | |
122 | typetab[INT].t_tspec = INT; | 122 | typetab[INT].t_tspec = INT; | |
123 | typetab[UINT].t_tspec = UINT; | 123 | typetab[UINT].t_tspec = UINT; | |
124 | typetab[LONG].t_tspec = LONG; | 124 | typetab[LONG].t_tspec = LONG; | |
125 | typetab[ULONG].t_tspec = ULONG; | 125 | typetab[ULONG].t_tspec = ULONG; | |
126 | typetab[QUAD].t_tspec = QUAD; | 126 | typetab[QUAD].t_tspec = QUAD; | |
127 | typetab[UQUAD].t_tspec = UQUAD; | 127 | typetab[UQUAD].t_tspec = UQUAD; | |
128 | #ifdef INT128_SIZE | 128 | #ifdef INT128_SIZE | |
129 | typetab[INT128].t_tspec = INT128; | 129 | typetab[INT128].t_tspec = INT128; | |
130 | typetab[UINT128].t_tspec = UINT128; | 130 | typetab[UINT128].t_tspec = UINT128; | |
131 | #endif | 131 | #endif | |
132 | typetab[FLOAT].t_tspec = FLOAT; | 132 | typetab[FLOAT].t_tspec = FLOAT; | |
133 | typetab[DOUBLE].t_tspec = DOUBLE; | 133 | typetab[DOUBLE].t_tspec = DOUBLE; | |
134 | typetab[LDOUBLE].t_tspec = LDOUBLE; | 134 | typetab[LDOUBLE].t_tspec = LDOUBLE; | |
135 | typetab[VOID].t_tspec = VOID; | 135 | typetab[VOID].t_tspec = VOID; | |
136 | /* struct, union, enum, ptr, array and func are not shared. */ | 136 | /* struct, union, enum, ptr, array and func are not shared. */ | |
137 | typetab[COMPLEX].t_tspec = COMPLEX; | 137 | typetab[COMPLEX].t_tspec = COMPLEX; | |
138 | typetab[FCOMPLEX].t_tspec = FCOMPLEX; | 138 | typetab[FCOMPLEX].t_tspec = FCOMPLEX; | |
139 | typetab[DCOMPLEX].t_tspec = DCOMPLEX; | 139 | typetab[DCOMPLEX].t_tspec = DCOMPLEX; | |
140 | typetab[LCOMPLEX].t_tspec = LCOMPLEX; | 140 | typetab[LCOMPLEX].t_tspec = LCOMPLEX; | |
141 | } | 141 | } | |
142 | 142 | |||
143 | #ifdef DEBUG | 143 | #ifdef DEBUG | |
144 | /* Return the name of the "storage class" in the wider sense. */ | 144 | /* Return the name of the "storage class" in the wider sense. */ | |
145 | const char * | 145 | const char * | |
146 | scl_name(scl_t scl) | 146 | scl_name(scl_t scl) | |
147 | { | 147 | { | |
148 | static const char *const names[] = { | 148 | static const char *const names[] = { | |
149 | "none", "extern", "static", "auto", "register", "typedef", | 149 | "none", "extern", "static", "auto", "register", "typedef", | |
150 | "struct", "union", "enum", "member of struct", "member of union", | 150 | "struct", "union", "enum", "member of struct", "member of union", | |
151 | "compile-time constant", "abstract", | 151 | "compile-time constant", "abstract", | |
152 | "old-style function argument", "prototype argument", "inline" | 152 | "old-style function argument", "prototype argument", "inline" | |
153 | }; | 153 | }; | |
154 | 154 | |||
155 | return names[scl]; | 155 | return names[scl]; | |
156 | } | 156 | } | |
157 | #endif | 157 | #endif | |
158 | 158 | |||
159 | /* | 159 | /* | |
160 | * Returns a shared type structure for arithmetic types and void. | 160 | * Returns a shared type structure for arithmetic types and void. | |
161 | * | 161 | * | |
162 | * It's important to duplicate this structure using block_dup_type or | 162 | * It's important to duplicate this structure using block_dup_type or | |
163 | * expr_dup_type if it is to be modified (adding qualifiers or anything | 163 | * expr_dup_type if it is to be modified (adding qualifiers or anything | |
164 | * else). | 164 | * else). | |
165 | */ | 165 | */ | |
166 | type_t * | 166 | type_t * | |
167 | gettyp(tspec_t t) | 167 | gettyp(tspec_t t) | |
168 | { | 168 | { | |
169 | 169 | |||
170 | /* TODO: make the return type 'const' */ | 170 | /* TODO: make the return type 'const' */ | |
171 | return &typetab[t]; | 171 | return &typetab[t]; | |
172 | } | 172 | } | |
173 | 173 | |||
174 | type_t * | 174 | type_t * | |
175 | block_dup_type(const type_t *tp) | 175 | block_dup_type(const type_t *tp) | |
176 | { | 176 | { | |
177 | type_t *ntp; | 177 | type_t *ntp; | |
178 | 178 | |||
179 | ntp = block_zero_alloc(sizeof(*ntp)); | 179 | ntp = block_zero_alloc(sizeof(*ntp)); | |
180 | *ntp = *tp; | 180 | *ntp = *tp; | |
181 | return ntp; | 181 | return ntp; | |
182 | } | 182 | } | |
183 | 183 | |||
184 | /* Duplicate a type, free the allocated memory after the expression. */ | 184 | /* Duplicate a type, free the allocated memory after the expression. */ | |
185 | type_t * | 185 | type_t * | |
186 | expr_dup_type(const type_t *tp) | 186 | expr_dup_type(const type_t *tp) | |
187 | { | 187 | { | |
188 | type_t *ntp; | 188 | type_t *ntp; | |
189 | 189 | |||
190 | ntp = expr_zero_alloc(sizeof(*ntp)); | 190 | ntp = expr_zero_alloc(sizeof(*ntp)); | |
191 | *ntp = *tp; | 191 | *ntp = *tp; | |
192 | return ntp; | 192 | return ntp; | |
193 | } | 193 | } | |
194 | 194 | |||
195 | /* | 195 | /* | |
196 | * Return the unqualified version of the type. The returned type is freed at | 196 | * Return the unqualified version of the type. The returned type is freed at | |
197 | * the end of the current expression. | 197 | * the end of the current expression. | |
198 | * | 198 | * | |
199 | * See C99 6.2.5p25. | 199 | * See C99 6.2.5p25. | |
200 | */ | 200 | */ | |
201 | type_t * | 201 | type_t * | |
202 | expr_unqualified_type(const type_t *tp) | 202 | expr_unqualified_type(const type_t *tp) | |
203 | { | 203 | { | |
204 | type_t *ntp; | 204 | type_t *ntp; | |
205 | 205 | |||
206 | ntp = expr_zero_alloc(sizeof(*ntp)); | 206 | ntp = expr_zero_alloc(sizeof(*ntp)); | |
207 | *ntp = *tp; | 207 | *ntp = *tp; | |
208 | ntp->t_const = false; | 208 | ntp->t_const = false; | |
209 | ntp->t_volatile = false; | 209 | ntp->t_volatile = false; | |
210 | 210 | |||
211 | /* | 211 | /* | |
212 | * In case of a struct or union type, the members should lose their | 212 | * In case of a struct or union type, the members should lose their | |
213 | * qualifiers as well, but that would require a deep copy of the | 213 | * qualifiers as well, but that would require a deep copy of the | |
214 | * struct or union type. This in turn would defeat the type | 214 | * struct or union type. This in turn would defeat the type | |
215 | * comparison in eqtype, which simply tests whether tp1->t_str == | 215 | * comparison in eqtype, which simply tests whether tp1->t_str == | |
216 | * tp2->t_str. | 216 | * tp2->t_str. | |
217 | */ | 217 | */ | |
218 | 218 | |||
219 | return ntp; | 219 | return ntp; | |
220 | } | 220 | } | |
221 | 221 | |||
222 | /* | 222 | /* | |
223 | * Returns whether the argument is void or an incomplete array, | 223 | * Returns whether the argument is void or an incomplete array, | |
224 | * struct, union or enum type. | 224 | * struct, union or enum type. | |
225 | */ | 225 | */ | |
226 | bool | 226 | bool | |
227 | is_incomplete(const type_t *tp) | 227 | is_incomplete(const type_t *tp) | |
228 | { | 228 | { | |
229 | tspec_t t; | 229 | tspec_t t; | |
230 | 230 | |||
231 | if ((t = tp->t_tspec) == VOID) { | 231 | if ((t = tp->t_tspec) == VOID) { | |
232 | return true; | 232 | return true; | |
233 | } else if (t == ARRAY) { | 233 | } else if (t == ARRAY) { | |
234 | return tp->t_incomplete_array; | 234 | return tp->t_incomplete_array; | |
235 | } else if (t == STRUCT || t == UNION) { | 235 | } else if (t == STRUCT || t == UNION) { | |
236 | return tp->t_str->sou_incomplete; | 236 | return tp->t_str->sou_incomplete; | |
237 | } else if (t == ENUM) { | 237 | } else if (t == ENUM) { | |
238 | return tp->t_enum->en_incomplete; | 238 | return tp->t_enum->en_incomplete; | |
239 | } | 239 | } | |
240 | return false; | 240 | return false; | |
241 | } | 241 | } | |
242 | 242 | |||
243 | /* | 243 | /* | |
244 | * Mark an array, struct, union or enum type as complete or incomplete. | 244 | * Mark an array, struct, union or enum type as complete or incomplete. | |
245 | */ | 245 | */ | |
246 | void | 246 | void | |
247 | setcomplete(type_t *tp, bool complete) | 247 | setcomplete(type_t *tp, bool complete) | |
248 | { | 248 | { | |
249 | tspec_t t; | 249 | tspec_t t; | |
250 | 250 | |||
251 | lint_assert(tp != NULL); | 251 | lint_assert(tp != NULL); | |
252 | if ((t = tp->t_tspec) == ARRAY) { | 252 | if ((t = tp->t_tspec) == ARRAY) { | |
253 | tp->t_incomplete_array = !complete; | 253 | tp->t_incomplete_array = !complete; | |
254 | } else if (t == STRUCT || t == UNION) { | 254 | } else if (t == STRUCT || t == UNION) { | |
255 | tp->t_str->sou_incomplete = !complete; | 255 | tp->t_str->sou_incomplete = !complete; | |
256 | } else { | 256 | } else { | |
257 | lint_assert(t == ENUM); | 257 | lint_assert(t == ENUM); | |
258 | tp->t_enum->en_incomplete = !complete; | 258 | tp->t_enum->en_incomplete = !complete; | |
259 | } | 259 | } | |
260 | } | 260 | } | |
261 | 261 | |||
262 | /* | 262 | /* | |
263 | * Remember the storage class of the current declaration in dcs->d_scl | 263 | * Remember the storage class of the current declaration in dcs->d_scl | |
264 | * (the top element of the declaration stack) and detect multiple | 264 | * (the top element of the declaration stack) and detect multiple | |
265 | * storage classes. | 265 | * storage classes. | |
266 | */ | 266 | */ | |
267 | void | 267 | void | |
268 | add_storage_class(scl_t sc) | 268 | add_storage_class(scl_t sc) | |
269 | { | 269 | { | |
270 | 270 | |||
271 | if (sc == INLINE) { | 271 | if (sc == INLINE) { | |
272 | if (dcs->d_inline) | 272 | if (dcs->d_inline) | |
273 | /* duplicate '%s' */ | 273 | /* duplicate '%s' */ | |
274 | warning(10, "inline"); | 274 | warning(10, "inline"); | |
275 | dcs->d_inline = true; | 275 | dcs->d_inline = true; | |
276 | return; | 276 | return; | |
277 | } | 277 | } | |
278 | if (dcs->d_type != NULL || dcs->d_abstract_type != NOTSPEC || | 278 | if (dcs->d_type != NULL || dcs->d_abstract_type != NOTSPEC || | |
279 | dcs->d_sign_mod != NOTSPEC || dcs->d_rank_mod != NOTSPEC) { | 279 | dcs->d_sign_mod != NOTSPEC || dcs->d_rank_mod != NOTSPEC) { | |
280 | /* storage class after type is obsolescent */ | 280 | /* storage class after type is obsolescent */ | |
281 | warning(83); | 281 | warning(83); | |
282 | } | 282 | } | |
283 | if (dcs->d_scl == NOSCL) { | 283 | if (dcs->d_scl == NOSCL) { | |
284 | dcs->d_scl = sc; | 284 | dcs->d_scl = sc; | |
285 | } else { | 285 | } else { | |
286 | dcs->d_multiple_storage_classes = true; | 286 | dcs->d_multiple_storage_classes = true; | |
287 | } | 287 | } | |
288 | } | 288 | } | |
289 | 289 | |||
290 | /* | 290 | /* | |
291 | * Remember the type, modifier or typedef name returned by the parser | 291 | * Remember the type, modifier or typedef name returned by the parser | |
292 | * in *dcs (top element of decl stack). This information is used in | 292 | * in *dcs (top element of decl stack). This information is used in | |
293 | * end_type() to build the type used for all declarators in this | 293 | * end_type() to build the type used for all declarators in this | |
294 | * declaration. | 294 | * declaration. | |
295 | * | 295 | * | |
296 | * If tp->t_typedef is 1, the type comes from a previously defined typename. | 296 | * If tp->t_typedef is 1, the type comes from a previously defined typename. | |
297 | * Otherwise it comes from a type specifier (int, long, ...) or a | 297 | * Otherwise it comes from a type specifier (int, long, ...) or a | |
298 | * struct/union/enum tag. | 298 | * struct/union/enum tag. | |
299 | */ | 299 | */ | |
300 | void | 300 | void | |
301 | add_type(type_t *tp) | 301 | add_type(type_t *tp) | |
302 | { | 302 | { | |
303 | tspec_t t; | 303 | tspec_t t; | |
304 | 304 | |||
305 | debug_step("%s: %s", __func__, type_name(tp)); | 305 | debug_step("%s: %s", __func__, type_name(tp)); | |
306 | if (tp->t_typedef) { | 306 | if (tp->t_typedef) { | |
307 | /* | 307 | /* | |
308 | * something like "typedef int a; int a b;" | 308 | * something like "typedef int a; int a b;" | |
309 | * This should not happen with current grammar. | 309 | * This should not happen with current grammar. | |
310 | */ | 310 | */ | |
311 | lint_assert(dcs->d_type == NULL); | 311 | lint_assert(dcs->d_type == NULL); | |
312 | lint_assert(dcs->d_abstract_type == NOTSPEC); | 312 | lint_assert(dcs->d_abstract_type == NOTSPEC); | |
313 | lint_assert(dcs->d_sign_mod == NOTSPEC); | 313 | lint_assert(dcs->d_sign_mod == NOTSPEC); | |
314 | lint_assert(dcs->d_rank_mod == NOTSPEC); | 314 | lint_assert(dcs->d_rank_mod == NOTSPEC); | |
315 | 315 | |||
316 | dcs->d_type = tp; | 316 | dcs->d_type = tp; | |
317 | return; | 317 | return; | |
318 | } | 318 | } | |
319 | 319 | |||
320 | t = tp->t_tspec; | 320 | t = tp->t_tspec; | |
321 | 321 | |||
322 | if (t == STRUCT || t == UNION || t == ENUM) { | 322 | if (t == STRUCT || t == UNION || t == ENUM) { | |
323 | /* | 323 | /* | |
324 | * something like "int struct a ..." | 324 | * something like "int struct a ..." | |
325 | * struct/union/enum with anything else is not allowed | 325 | * struct/union/enum with anything else is not allowed | |
326 | */ | 326 | */ | |
327 | if (dcs->d_type != NULL || dcs->d_abstract_type != NOTSPEC || | 327 | if (dcs->d_type != NULL || dcs->d_abstract_type != NOTSPEC || | |
328 | dcs->d_rank_mod != NOTSPEC || dcs->d_sign_mod != NOTSPEC) { | 328 | dcs->d_rank_mod != NOTSPEC || dcs->d_sign_mod != NOTSPEC) { | |
329 | dcs->d_invalid_type_combination = true; | 329 | dcs->d_invalid_type_combination = true; | |
330 | dcs->d_abstract_type = NOTSPEC; | 330 | dcs->d_abstract_type = NOTSPEC; | |
331 | dcs->d_sign_mod = NOTSPEC; | 331 | dcs->d_sign_mod = NOTSPEC; | |
332 | dcs->d_rank_mod = NOTSPEC; | 332 | dcs->d_rank_mod = NOTSPEC; | |
333 | } | 333 | } | |
334 | dcs->d_type = tp; | 334 | dcs->d_type = tp; | |
335 | return; | 335 | return; | |
336 | } | 336 | } | |
337 | 337 | |||
338 | if (dcs->d_type != NULL && !dcs->d_type->t_typedef) { | 338 | if (dcs->d_type != NULL && !dcs->d_type->t_typedef) { | |
339 | /* | 339 | /* | |
340 | * something like "struct a int" | 340 | * something like "struct a int" | |
341 | * struct/union/enum with anything else is not allowed | 341 | * struct/union/enum with anything else is not allowed | |
342 | */ | 342 | */ | |
343 | dcs->d_invalid_type_combination = true; | 343 | dcs->d_invalid_type_combination = true; | |
344 | return; | 344 | return; | |
345 | } | 345 | } | |
346 | 346 | |||
347 | if (t == COMPLEX) { | 347 | if (t == COMPLEX) { | |
348 | if (dcs->d_complex_mod == FLOAT) | 348 | if (dcs->d_complex_mod == FLOAT) | |
349 | t = FCOMPLEX; | 349 | t = FCOMPLEX; | |
350 | else if (dcs->d_complex_mod == DOUBLE) | 350 | else if (dcs->d_complex_mod == DOUBLE) | |
351 | t = DCOMPLEX; | 351 | t = DCOMPLEX; | |
352 | else { | 352 | else { | |
353 | /* invalid type for _Complex */ | 353 | /* invalid type for _Complex */ | |
354 | error(308); | 354 | error(308); | |
355 | t = DCOMPLEX; /* just as a fallback */ | 355 | t = DCOMPLEX; /* just as a fallback */ | |
356 | } | 356 | } | |
357 | dcs->d_complex_mod = NOTSPEC; | 357 | dcs->d_complex_mod = NOTSPEC; | |
358 | } | 358 | } | |
359 | 359 | |||
360 | if (t == LONG && dcs->d_rank_mod == LONG) { | 360 | if (t == LONG && dcs->d_rank_mod == LONG) { | |
361 | /* "long long" or "long ... long" */ | 361 | /* "long long" or "long ... long" */ | |
362 | t = QUAD; | 362 | t = QUAD; | |
363 | dcs->d_rank_mod = NOTSPEC; | 363 | dcs->d_rank_mod = NOTSPEC; | |
364 | if (!quadflg) | 364 | if (!quadflg) | |
365 | /* %s does not support 'long long' */ | 365 | /* %s does not support 'long long' */ | |
366 | c99ism(265, tflag ? "traditional C" : "C90"); | 366 | c99ism(265, tflag ? "traditional C" : "C90"); | |
367 | } | 367 | } | |
368 | 368 | |||
369 | if (dcs->d_type != NULL && dcs->d_type->t_typedef) { | 369 | if (dcs->d_type != NULL && dcs->d_type->t_typedef) { | |
370 | /* something like "typedef int a; a long ..." */ | 370 | /* something like "typedef int a; a long ..." */ | |
371 | dcs->d_type = tdeferr(dcs->d_type, t); | 371 | dcs->d_type = tdeferr(dcs->d_type, t); | |
372 | return; | 372 | return; | |
373 | } | 373 | } | |
374 | 374 | |||
375 | /* now it can be only a combination of arithmetic types and void */ | 375 | /* now it can be only a combination of arithmetic types and void */ | |
376 | if (t == SIGNED || t == UNSIGN) { | 376 | if (t == SIGNED || t == UNSIGN) { | |
377 | /* | 377 | /* | |
378 | * remember specifiers "signed" & "unsigned" in | 378 | * remember specifiers "signed" & "unsigned" in | |
379 | * dcs->d_sign_mod | 379 | * dcs->d_sign_mod | |
380 | */ | 380 | */ | |
381 | if (dcs->d_sign_mod != NOTSPEC) | 381 | if (dcs->d_sign_mod != NOTSPEC) | |
382 | /* more than one "signed" and/or "unsigned" */ | 382 | /* more than one "signed" and/or "unsigned" */ | |
383 | dcs->d_invalid_type_combination = true; | 383 | dcs->d_invalid_type_combination = true; | |
384 | dcs->d_sign_mod = t; | 384 | dcs->d_sign_mod = t; | |
385 | } else if (t == SHORT || t == LONG || t == QUAD) { | 385 | } else if (t == SHORT || t == LONG || t == QUAD) { | |
386 | /* | 386 | /* | |
387 | * remember specifiers "short", "long" and "long long" in | 387 | * remember specifiers "short", "long" and "long long" in | |
388 | * dcs->d_rank_mod | 388 | * dcs->d_rank_mod | |
389 | */ | 389 | */ | |
390 | if (dcs->d_rank_mod != NOTSPEC) | 390 | if (dcs->d_rank_mod != NOTSPEC) | |
391 | dcs->d_invalid_type_combination = true; | 391 | dcs->d_invalid_type_combination = true; | |
392 | dcs->d_rank_mod = t; | 392 | dcs->d_rank_mod = t; | |
393 | } else if (t == FLOAT || t == DOUBLE) { | 393 | } else if (t == FLOAT || t == DOUBLE) { | |
394 | if (dcs->d_rank_mod == NOTSPEC || dcs->d_rank_mod == LONG) { | 394 | if (dcs->d_rank_mod == NOTSPEC || dcs->d_rank_mod == LONG) { | |
395 | if (dcs->d_complex_mod != NOTSPEC | 395 | if (dcs->d_complex_mod != NOTSPEC | |
396 | || (t == FLOAT && dcs->d_rank_mod == LONG)) | 396 | || (t == FLOAT && dcs->d_rank_mod == LONG)) | |
397 | dcs->d_invalid_type_combination = true; | 397 | dcs->d_invalid_type_combination = true; | |
398 | dcs->d_complex_mod = t; | 398 | dcs->d_complex_mod = t; | |
399 | } else { | 399 | } else { | |
400 | if (dcs->d_abstract_type != NOTSPEC) | 400 | if (dcs->d_abstract_type != NOTSPEC) | |
401 | dcs->d_invalid_type_combination = true; | 401 | dcs->d_invalid_type_combination = true; | |
402 | dcs->d_abstract_type = t; | 402 | dcs->d_abstract_type = t; | |
403 | } | 403 | } | |
404 | } else if (t == PTR) { | 404 | } else if (t == PTR) { | |
405 | dcs->d_type = tp; | 405 | dcs->d_type = tp; | |
406 | } else { | 406 | } else { | |
407 | /* | 407 | /* | |
408 | * remember specifiers "void", "char", "int", | 408 | * remember specifiers "void", "char", "int", | |
409 | * or "_Complex" in dcs->d_abstract_type | 409 | * or "_Complex" in dcs->d_abstract_type | |
410 | */ | 410 | */ | |
411 | if (dcs->d_abstract_type != NOTSPEC) | 411 | if (dcs->d_abstract_type != NOTSPEC) | |
412 | dcs->d_invalid_type_combination = true; | 412 | dcs->d_invalid_type_combination = true; | |
413 | dcs->d_abstract_type = t; | 413 | dcs->d_abstract_type = t; | |
414 | } | 414 | } | |
415 | } | 415 | } | |
416 | 416 | |||
417 | /* Merge the signedness into the abstract type. */ | 417 | /* Merge the signedness into the abstract type. */ | |
418 | static tspec_t | 418 | static tspec_t | |
419 | merge_signedness(tspec_t t, tspec_t s) | 419 | merge_signedness(tspec_t t, tspec_t s) | |
420 | { | 420 | { | |
421 | 421 | |||
422 | if (s == SIGNED) | 422 | if (s == SIGNED) | |
423 | return t == CHAR ? SCHAR : t; | 423 | return t == CHAR ? SCHAR : t; | |
424 | if (s != UNSIGN) | 424 | if (s != UNSIGN) | |
425 | return t; | 425 | return t; | |
426 | return t == CHAR ? UCHAR | 426 | return t == CHAR ? UCHAR | |
427 | : t == SHORT ? USHORT | 427 | : t == SHORT ? USHORT | |
428 | : t == INT ? UINT | 428 | : t == INT ? UINT | |
429 | : t == LONG ? ULONG | 429 | : t == LONG ? ULONG | |
430 | : t == QUAD ? UQUAD | 430 | : t == QUAD ? UQUAD | |
431 | : t; | 431 | : t; | |
432 | } | 432 | } | |
433 | 433 | |||
434 | /* | 434 | /* | |
435 | * called if a list of declaration specifiers contains a typedef name | 435 | * called if a list of declaration specifiers contains a typedef name | |
436 | * and other specifiers (except struct, union, enum, typedef name) | 436 | * and other specifiers (except struct, union, enum, typedef name) | |
437 | */ | 437 | */ | |
438 | static type_t * | 438 | static type_t * | |
439 | tdeferr(type_t *td, tspec_t t) | 439 | tdeferr(type_t *td, tspec_t t) | |
440 | { | 440 | { | |
441 | tspec_t t2; | 441 | tspec_t t2; | |
442 | 442 | |||
443 | t2 = td->t_tspec; | 443 | t2 = td->t_tspec; | |
444 | 444 | |||
445 | if ((t == SIGNED || t == UNSIGN) && | 445 | if ((t == SIGNED || t == UNSIGN) && | |
446 | (t2 == CHAR || t2 == SHORT || t2 == INT || | 446 | (t2 == CHAR || t2 == SHORT || t2 == INT || | |
447 | t2 == LONG || t2 == QUAD)) { | 447 | t2 == LONG || t2 == QUAD)) { | |
448 | if (!tflag) | 448 | if (!tflag) | |
449 | /* modifying typedef with '%s'; only qualifiers... */ | 449 | /* modifying typedef with '%s'; only qualifiers... */ | |
450 | warning(5, tspec_name(t)); | 450 | warning(5, tspec_name(t)); | |
451 | td = block_dup_type(gettyp(merge_signedness(t2, t))); | 451 | td = block_dup_type(gettyp(merge_signedness(t2, t))); | |
452 | td->t_typedef = true; | 452 | td->t_typedef = true; | |
453 | return td; | 453 | return td; | |
454 | } | 454 | } | |
455 | 455 | |||
456 | if (t == SHORT && (t2 == INT || t2 == UINT)) { | 456 | if (t == SHORT && (t2 == INT || t2 == UINT)) { | |
457 | /* modifying typedef with '%s'; only qualifiers allowed */ | 457 | /* modifying typedef with '%s'; only qualifiers allowed */ | |
458 | warning(5, "short"); | 458 | warning(5, "short"); | |
459 | td = block_dup_type(gettyp(t2 == INT ? SHORT : USHORT)); | 459 | td = block_dup_type(gettyp(t2 == INT ? SHORT : USHORT)); | |
460 | td->t_typedef = true; | 460 | td->t_typedef = true; | |
461 | return td; | 461 | return td; | |
462 | } | 462 | } | |
463 | 463 | |||
464 | if (t == LONG && | 464 | if (t == LONG && | |
465 | (t2 == INT || t2 == UINT || t2 == LONG || t2 == ULONG || | 465 | (t2 == INT || t2 == UINT || t2 == LONG || t2 == ULONG || | |
466 | t2 == FLOAT || t2 == DOUBLE || t2 == DCOMPLEX)) { | 466 | t2 == FLOAT || t2 == DOUBLE || t2 == DCOMPLEX)) { | |
467 | /* modifying typedef with '%s'; only qualifiers allowed */ | 467 | /* modifying typedef with '%s'; only qualifiers allowed */ | |
468 | warning(5, "long"); | 468 | warning(5, "long"); | |
469 | if (t2 == INT) { | 469 | if (t2 == INT) { | |
470 | td = gettyp(LONG); | 470 | td = gettyp(LONG); | |
471 | } else if (t2 == UINT) { | 471 | } else if (t2 == UINT) { | |
472 | td = gettyp(ULONG); | 472 | td = gettyp(ULONG); | |
473 | } else if (t2 == LONG) { | 473 | } else if (t2 == LONG) { | |
474 | td = gettyp(QUAD); | 474 | td = gettyp(QUAD); | |
475 | } else if (t2 == ULONG) { | 475 | } else if (t2 == ULONG) { | |
476 | td = gettyp(UQUAD); | 476 | td = gettyp(UQUAD); | |
477 | } else if (t2 == FLOAT) { | 477 | } else if (t2 == FLOAT) { | |
478 | td = gettyp(DOUBLE); | 478 | td = gettyp(DOUBLE); | |
479 | } else if (t2 == DOUBLE) { | 479 | } else if (t2 == DOUBLE) { | |
480 | td = gettyp(LDOUBLE); | 480 | td = gettyp(LDOUBLE); | |
481 | } else if (t2 == DCOMPLEX) { | 481 | } else if (t2 == DCOMPLEX) { | |
482 | td = gettyp(LCOMPLEX); | 482 | td = gettyp(LCOMPLEX); | |
483 | } | 483 | } | |
484 | td = block_dup_type(td); | 484 | td = block_dup_type(td); | |
485 | td->t_typedef = true; | 485 | td->t_typedef = true; | |
486 | return td; | 486 | return td; | |
487 | } | 487 | } | |
488 | 488 | |||
489 | /* Anything else is not accepted. */ | 489 | /* Anything else is not accepted. */ | |
490 | dcs->d_invalid_type_combination = true; | 490 | dcs->d_invalid_type_combination = true; | |
491 | return td; | 491 | return td; | |
492 | } | 492 | } | |
493 | 493 | |||
494 | /* | 494 | /* | |
495 | * Remember the symbol of a typedef name (2nd arg) in a struct, union | 495 | * Remember the symbol of a typedef name (2nd arg) in a struct, union | |
496 | * or enum tag if the typedef name is the first defined for this tag. | 496 | * or enum tag if the typedef name is the first defined for this tag. | |
497 | * | 497 | * | |
498 | * If the tag is unnamed, the typedef name is used for identification | 498 | * If the tag is unnamed, the typedef name is used for identification | |
499 | * of this tag in lint2. Although it's possible that more than one typedef | 499 | * of this tag in lint2. Although it's possible that more than one typedef | |
500 | * name is defined for one tag, the first name defined should be unique | 500 | * name is defined for one tag, the first name defined should be unique | |
501 | * if the tag is unnamed. | 501 | * if the tag is unnamed. | |
502 | */ | 502 | */ | |
503 | static void | 503 | static void | |
504 | settdsym(type_t *tp, sym_t *sym) | 504 | settdsym(type_t *tp, sym_t *sym) | |
505 | { | 505 | { | |
506 | tspec_t t; | 506 | tspec_t t; | |
507 | 507 | |||
508 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { | 508 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { | |
509 | if (tp->t_str->sou_first_typedef == NULL) | 509 | if (tp->t_str->sou_first_typedef == NULL) | |
510 | tp->t_str->sou_first_typedef = sym; | 510 | tp->t_str->sou_first_typedef = sym; | |
511 | } else if (t == ENUM) { | 511 | } else if (t == ENUM) { | |
512 | if (tp->t_enum->en_first_typedef == NULL) | 512 | if (tp->t_enum->en_first_typedef == NULL) | |
513 | tp->t_enum->en_first_typedef = sym; | 513 | tp->t_enum->en_first_typedef = sym; | |
514 | } | 514 | } | |
515 | } | 515 | } | |
516 | 516 | |||
517 | static unsigned int | 517 | static unsigned int | |
518 | bitfieldsize(sym_t **mem) | 518 | bitfieldsize(sym_t **mem) | |
519 | { | 519 | { | |
520 | unsigned int len = (*mem)->s_type->t_flen; | 520 | unsigned int len = (*mem)->s_type->t_flen; | |
521 | while (*mem != NULL && (*mem)->s_type->t_bitfield) { | 521 | while (*mem != NULL && (*mem)->s_type->t_bitfield) { | |
522 | len += (*mem)->s_type->t_flen; | 522 | len += (*mem)->s_type->t_flen; | |
523 | *mem = (*mem)->s_next; | 523 | *mem = (*mem)->s_next; | |
524 | } | 524 | } | |
525 | return len - len % INT_SIZE; | 525 | return len - len % INT_SIZE; | |
526 | } | 526 | } | |
527 | 527 | |||
528 | static void | 528 | static void | |
529 | setpackedsize(type_t *tp) | 529 | setpackedsize(type_t *tp) | |
530 | { | 530 | { | |
531 | struct_or_union *sp; | 531 | struct_or_union *sp; | |
532 | sym_t *mem; | 532 | sym_t *mem; | |
533 | 533 | |||
534 | switch (tp->t_tspec) { | 534 | switch (tp->t_tspec) { | |
535 | case STRUCT: | 535 | case STRUCT: | |
536 | case UNION: | 536 | case UNION: | |
537 | sp = tp->t_str; | 537 | sp = tp->t_str; | |
538 | sp->sou_size_in_bits = 0; | 538 | sp->sou_size_in_bits = 0; | |
539 | for (mem = sp->sou_first_member; | 539 | for (mem = sp->sou_first_member; | |
540 | mem != NULL; mem = mem->s_next) { | 540 | mem != NULL; mem = mem->s_next) { | |
541 | unsigned int x; | 541 | unsigned int x; | |
542 | 542 | |||
543 | if (mem->s_type->t_bitfield) { | 543 | if (mem->s_type->t_bitfield) { | |
544 | sp->sou_size_in_bits += bitfieldsize(&mem); | 544 | sp->sou_size_in_bits += bitfieldsize(&mem); | |
545 | if (mem == NULL) | 545 | if (mem == NULL) | |
546 | break; | 546 | break; | |
547 | } | 547 | } | |
548 | x = type_size_in_bits(mem->s_type); | 548 | x = type_size_in_bits(mem->s_type); | |
549 | if (tp->t_tspec == STRUCT) | 549 | if (tp->t_tspec == STRUCT) | |
550 | sp->sou_size_in_bits += x; | 550 | sp->sou_size_in_bits += x; | |
551 | else if (x > sp->sou_size_in_bits) | 551 | else if (x > sp->sou_size_in_bits) | |
552 | sp->sou_size_in_bits = x; | 552 | sp->sou_size_in_bits = x; | |
553 | } | 553 | } | |
554 | break; | 554 | break; | |
555 | default: | 555 | default: | |
556 | /* %s attribute ignored for %s */ | 556 | /* %s attribute ignored for %s */ | |
557 | warning(326, "packed", type_name(tp)); | 557 | warning(326, "packed", type_name(tp)); | |
558 | break; | 558 | break; | |
559 | } | 559 | } | |
560 | } | 560 | } | |
561 | 561 | |||
562 | void | 562 | void | |
563 | addpacked(void) | 563 | addpacked(void) | |
564 | { | 564 | { | |
565 | if (dcs->d_type == NULL) | 565 | if (dcs->d_type == NULL) | |
566 | dcs->d_packed = true; | 566 | dcs->d_packed = true; | |
567 | else | 567 | else | |
568 | setpackedsize(dcs->d_type); | 568 | setpackedsize(dcs->d_type); | |
569 | } | 569 | } | |
570 | 570 | |||
571 | void | 571 | void | |
572 | add_attr_used(void) | 572 | add_attr_used(void) | |
573 | { | 573 | { | |
574 | dcs->d_used = true; | 574 | dcs->d_used = true; | |
575 | } | 575 | } | |
576 | 576 | |||
577 | /* | 577 | /* | |
578 | * Remember a qualifier which is part of the declaration specifiers | 578 | * Remember a qualifier which is part of the declaration specifiers | |
579 | * (and not the declarator) in the top element of the declaration stack. | 579 | * (and not the declarator) in the top element of the declaration stack. | |
580 | * Also detect multiple qualifiers of the same kind. | 580 | * Also detect multiple qualifiers of the same kind. | |
581 | 581 | |||
582 | * The remembered qualifier is used by end_type() to construct the type | 582 | * The remembered qualifier is used by end_type() to construct the type | |
583 | * for all declarators. | 583 | * for all declarators. | |
584 | */ | 584 | */ | |
585 | void | 585 | void | |
586 | add_qualifier(tqual_t q) | 586 | add_qualifier(tqual_t q) | |
587 | { | 587 | { | |
588 | 588 | |||
589 | if (q == CONST) { | 589 | if (q == CONST) { | |
590 | if (dcs->d_const) { | 590 | if (dcs->d_const) { | |
591 | /* duplicate '%s' */ | 591 | /* duplicate '%s' */ | |
592 | warning(10, "const"); | 592 | warning(10, "const"); | |
593 | } | 593 | } | |
594 | dcs->d_const = true; | 594 | dcs->d_const = true; | |
595 | } else if (q == VOLATILE) { | 595 | } else if (q == VOLATILE) { | |
596 | if (dcs->d_volatile) { | 596 | if (dcs->d_volatile) { | |
597 | /* duplicate '%s' */ | 597 | /* duplicate '%s' */ | |
598 | warning(10, "volatile"); | 598 | warning(10, "volatile"); | |
599 | } | 599 | } | |
600 | dcs->d_volatile = true; | 600 | dcs->d_volatile = true; | |
601 | } else { | 601 | } else { | |
602 | lint_assert(q == RESTRICT || q == THREAD); | 602 | lint_assert(q == RESTRICT || q == THREAD); | |
603 | /* Silently ignore these qualifiers. */ | 603 | /* Silently ignore these qualifiers. */ | |
604 | } | 604 | } | |
605 | } | 605 | } | |
606 | 606 | |||
607 | /* | 607 | /* | |
608 | * Go to the next declaration level (structs, nested structs, blocks, | 608 | * Go to the next declaration level (structs, nested structs, blocks, | |
609 | * argument declaration lists ...) | 609 | * argument declaration lists ...) | |
610 | */ | 610 | */ | |
611 | void | 611 | void | |
612 | begin_declaration_level(scl_t sc) | 612 | begin_declaration_level(scl_t sc) | |
613 | { | 613 | { | |
614 | dinfo_t *di; | 614 | dinfo_t *di; | |
615 | 615 | |||
616 | /* put a new element on the declaration stack */ | 616 | /* put a new element on the declaration stack */ | |
617 | di = xcalloc(1, sizeof(*di)); | 617 | di = xcalloc(1, sizeof(*di)); | |
618 | di->d_next = dcs; | 618 | di->d_next = dcs; | |
619 | dcs = di; | 619 | dcs = di; | |
620 | di->d_ctx = sc; | 620 | di->d_ctx = sc; | |
621 | di->d_ldlsym = &di->d_dlsyms; | 621 | di->d_ldlsym = &di->d_dlsyms; | |
622 | debug_step("%s(%p %s)", __func__, dcs, scl_name(sc)); | 622 | debug_step("%s(%p %s)", __func__, dcs, scl_name(sc)); | |
623 | } | 623 | } | |
624 | 624 | |||
625 | /* | 625 | /* | |
626 | * Go back to previous declaration level | 626 | * Go back to previous declaration level | |
627 | */ | 627 | */ | |
628 | void | 628 | void | |
629 | end_declaration_level(void) | 629 | end_declaration_level(void) | |
630 | { | 630 | { | |
631 | dinfo_t *di; | 631 | dinfo_t *di; | |
632 | 632 | |||
633 | debug_step("%s(%p %s)", __func__, dcs, scl_name(dcs->d_ctx)); | 633 | debug_step("%s(%p %s)", __func__, dcs, scl_name(dcs->d_ctx)); | |
634 | 634 | |||
635 | lint_assert(dcs->d_next != NULL); | 635 | lint_assert(dcs->d_next != NULL); | |
636 | di = dcs; | 636 | di = dcs; | |
637 | dcs = di->d_next; | 637 | dcs = di->d_next; | |
638 | switch (di->d_ctx) { | 638 | switch (di->d_ctx) { | |
639 | case MOS: | 639 | case MOS: | |
640 | case MOU: | 640 | case MOU: | |
641 | case CTCONST: | 641 | case CTCONST: | |
642 | /* | 642 | /* | |
643 | * Symbols declared in (nested) structs or enums are | 643 | * Symbols declared in (nested) structs or enums are | |
644 | * part of the next level (they are removed from the | 644 | * part of the next level (they are removed from the | |
645 | * symbol table if the symbols of the outer level are | 645 | * symbol table if the symbols of the outer level are | |
646 | * removed). | 646 | * removed). | |
647 | */ | 647 | */ | |
648 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) | 648 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) | |
649 | dcs->d_ldlsym = di->d_ldlsym; | 649 | dcs->d_ldlsym = di->d_ldlsym; | |
650 | break; | 650 | break; | |
651 | case OLD_STYLE_ARG: | 651 | case OLD_STYLE_ARG: | |
652 | /* | 652 | /* | |
653 | * All symbols in dcs->d_dlsyms are introduced in old style | 653 | * All symbols in dcs->d_dlsyms are introduced in old style | |
654 | * argument declarations (it's not clean, but possible). | 654 | * argument declarations (it's not clean, but possible). | |
655 | * They are appended to the list of symbols declared in | 655 | * They are appended to the list of symbols declared in | |
656 | * an old style argument identifier list or a new style | 656 | * an old style argument identifier list or a new style | |
657 | * parameter type list. | 657 | * parameter type list. | |
658 | */ | 658 | */ | |
659 | if (di->d_dlsyms != NULL) { | 659 | if (di->d_dlsyms != NULL) { | |
660 | *di->d_ldlsym = dcs->d_func_proto_syms; | 660 | *di->d_ldlsym = dcs->d_func_proto_syms; | |
661 | dcs->d_func_proto_syms = di->d_dlsyms; | 661 | dcs->d_func_proto_syms = di->d_dlsyms; | |
662 | } | 662 | } | |
663 | break; | 663 | break; | |
664 | case ABSTRACT: | 664 | case ABSTRACT: | |
665 | /* | 665 | /* | |
666 | * casts and sizeof | 666 | * casts and sizeof | |
667 | * Append all symbols declared in the abstract declaration | 667 | * Append all symbols declared in the abstract declaration | |
668 | * to the list of symbols declared in the surrounding | 668 | * to the list of symbols declared in the surrounding | |
669 | * declaration or block. | 669 | * declaration or block. | |
670 | * XXX I'm not sure whether they should be removed from the | 670 | * XXX I'm not sure whether they should be removed from the | |
671 | * symbol table now or later. | 671 | * symbol table now or later. | |
672 | */ | 672 | */ | |
673 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) | 673 | if ((*dcs->d_ldlsym = di->d_dlsyms) != NULL) | |
674 | dcs->d_ldlsym = di->d_ldlsym; | 674 | dcs->d_ldlsym = di->d_ldlsym; | |
675 | break; | 675 | break; | |
676 | case AUTO: | 676 | case AUTO: | |
677 | /* check usage of local vars */ | 677 | /* check usage of local vars */ | |
678 | check_usage(di); | 678 | check_usage(di); | |
679 | /* FALLTHROUGH */ | 679 | /* FALLTHROUGH */ | |
680 | case PROTO_ARG: | 680 | case PROTO_ARG: | |
681 | /* usage of arguments will be checked by funcend() */ | 681 | /* usage of arguments will be checked by funcend() */ | |
682 | rmsyms(di->d_dlsyms); | 682 | rmsyms(di->d_dlsyms); | |
683 | break; | 683 | break; | |
684 | case EXTERN: | 684 | case EXTERN: | |
685 | /* there is nothing after external declarations */ | 685 | /* there is nothing after external declarations */ | |
686 | /* FALLTHROUGH */ | 686 | /* FALLTHROUGH */ | |
687 | default: | 687 | default: | |
688 | lint_assert(/*CONSTCOND*/false); | 688 | lint_assert(/*CONSTCOND*/false); | |
689 | } | 689 | } | |
690 | free(di); | 690 | free(di); | |
691 | } | 691 | } | |
692 | 692 | |||
693 | /* | 693 | /* | |
694 | * Set flag d_asm in all declaration stack elements up to the | 694 | * Set flag d_asm in all declaration stack elements up to the | |
695 | * outermost one. | 695 | * outermost one. | |
696 | * | 696 | * | |
697 | * This is used to mark compound statements which have, possibly in | 697 | * This is used to mark compound statements which have, possibly in | |
698 | * nested compound statements, asm statements. For these compound | 698 | * nested compound statements, asm statements. For these compound | |
699 | * statements no warnings about unused or uninitialized variables are | 699 | * statements no warnings about unused or uninitialized variables are | |
700 | * printed. | 700 | * printed. | |
701 | * | 701 | * | |
702 | * There is no need to clear d_asm in dinfo structs with context AUTO, | 702 | * There is no need to clear d_asm in dinfo structs with context AUTO, | |
703 | * because these structs are freed at the end of the compound statement. | 703 | * because these structs are freed at the end of the compound statement. | |
704 | * But it must be cleared in the outermost dinfo struct, which has | 704 | * But it must be cleared in the outermost dinfo struct, which has | |
705 | * context EXTERN. This could be done in begin_type() and would work for C90, | 705 | * context EXTERN. This could be done in begin_type() and would work for C90, | |
706 | * but not for C99 or C++ (due to mixed statements and declarations). Thus | 706 | * but not for C99 or C++ (due to mixed statements and declarations). Thus | |
707 | * we clear it in global_clean_up_decl(), which is used to do some cleanup | 707 | * we clear it in global_clean_up_decl(), which is used to do some cleanup | |
708 | * after global declarations/definitions. | 708 | * after global declarations/definitions. | |
709 | */ | 709 | */ | |
710 | void | 710 | void | |
711 | setasm(void) | 711 | setasm(void) | |
712 | { | 712 | { | |
713 | dinfo_t *di; | 713 | dinfo_t *di; | |
714 | 714 | |||
715 | for (di = dcs; di != NULL; di = di->d_next) | 715 | for (di = dcs; di != NULL; di = di->d_next) | |
716 | di->d_asm = true; | 716 | di->d_asm = true; | |
717 | } | 717 | } | |
718 | 718 | |||
719 | /* | 719 | /* | |
720 | * Clean all elements of the top element of declaration stack which | 720 | * Clean all elements of the top element of declaration stack which | |
721 | * will be used by the next declaration | 721 | * will be used by the next declaration | |
722 | */ | 722 | */ | |
723 | void | 723 | void | |
724 | begin_type(void) | 724 | begin_type(void) | |
725 | { | 725 | { | |
726 | 726 | |||
727 | dcs->d_abstract_type = NOTSPEC; | 727 | dcs->d_abstract_type = NOTSPEC; | |
728 | dcs->d_complex_mod = NOTSPEC; | 728 | dcs->d_complex_mod = NOTSPEC; | |
729 | dcs->d_sign_mod = NOTSPEC; | 729 | dcs->d_sign_mod = NOTSPEC; | |
730 | dcs->d_rank_mod = NOTSPEC; | 730 | dcs->d_rank_mod = NOTSPEC; | |
731 | dcs->d_scl = NOSCL; | 731 | dcs->d_scl = NOSCL; | |
732 | dcs->d_type = NULL; | 732 | dcs->d_type = NULL; | |
733 | dcs->d_const = false; | 733 | dcs->d_const = false; | |
734 | dcs->d_volatile = false; | 734 | dcs->d_volatile = false; | |
735 | dcs->d_inline = false; | 735 | dcs->d_inline = false; | |
736 | dcs->d_multiple_storage_classes = false; | 736 | dcs->d_multiple_storage_classes = false; | |
737 | dcs->d_invalid_type_combination = false; | 737 | dcs->d_invalid_type_combination = false; | |
738 | dcs->d_nonempty_decl = false; | 738 | dcs->d_nonempty_decl = false; | |
739 | dcs->d_notyp = false; | 739 | dcs->d_notyp = false; | |
740 | } | 740 | } | |
741 | 741 | |||
742 | static void | 742 | static void | |
743 | dcs_adjust_storage_class(void) | 743 | dcs_adjust_storage_class(void) | |
744 | { | 744 | { | |
745 | if (dcs->d_ctx == EXTERN) { | 745 | if (dcs->d_ctx == EXTERN) { | |
746 | if (dcs->d_scl == REG || dcs->d_scl == AUTO) { | 746 | if (dcs->d_scl == REG || dcs->d_scl == AUTO) { | |
747 | /* illegal storage class */ | 747 | /* illegal storage class */ | |
748 | error(8); | 748 | error(8); | |
749 | dcs->d_scl = NOSCL; | 749 | dcs->d_scl = NOSCL; | |
750 | } | 750 | } | |
751 | } else if (dcs->d_ctx == OLD_STYLE_ARG || dcs->d_ctx == PROTO_ARG) { | 751 | } else if (dcs->d_ctx == OLD_STYLE_ARG || dcs->d_ctx == PROTO_ARG) { | |
752 | if (dcs->d_scl != NOSCL && dcs->d_scl != REG) { | 752 | if (dcs->d_scl != NOSCL && dcs->d_scl != REG) { | |
753 | /* only register valid as formal parameter storage... */ | 753 | /* only register valid as formal parameter storage... */ | |
754 | error(9); | 754 | error(9); | |
755 | dcs->d_scl = NOSCL; | 755 | dcs->d_scl = NOSCL; | |
756 | } | 756 | } | |
757 | } | 757 | } | |
758 | } | 758 | } | |
759 | 759 | |||
760 | /* | 760 | /* | |
761 | * Merge the declaration specifiers from dcs into dcs->d_type. | 761 | * Merge the declaration specifiers from dcs into dcs->d_type. | |
762 | * | 762 | * | |
763 | * See C99 6.7.2 "Type specifiers". | 763 | * See C99 6.7.2 "Type specifiers". | |
764 | */ | 764 | */ | |
765 | static void | 765 | static void | |
766 | dcs_merge_declaration_specifiers(void) | 766 | dcs_merge_declaration_specifiers(void) | |
767 | { | 767 | { | |
768 | tspec_t t, s, l, c; | 768 | tspec_t t, s, l, c; | |
769 | type_t *tp; | 769 | type_t *tp; | |
770 | 770 | |||
771 | t = dcs->d_abstract_type; /* VOID, BOOL, CHAR, INT or COMPLEX */ | 771 | t = dcs->d_abstract_type; /* VOID, BOOL, CHAR, INT or COMPLEX */ | |
772 | c = dcs->d_complex_mod; /* FLOAT or DOUBLE */ | 772 | c = dcs->d_complex_mod; /* FLOAT or DOUBLE */ | |
773 | s = dcs->d_sign_mod; /* SIGNED or UNSIGN */ | 773 | s = dcs->d_sign_mod; /* SIGNED or UNSIGN */ | |
774 | l = dcs->d_rank_mod; /* SHORT, LONG or QUAD */ | 774 | l = dcs->d_rank_mod; /* SHORT, LONG or QUAD */ | |
775 | tp = dcs->d_type; | 775 | tp = dcs->d_type; | |
776 | 776 | |||
777 | debug_step("%s: %s", __func__, type_name(tp)); | 777 | debug_step("%s: %s", __func__, type_name(tp)); | |
778 | if (t == NOTSPEC && s == NOTSPEC && l == NOTSPEC && c == NOTSPEC && | 778 | if (t == NOTSPEC && s == NOTSPEC && l == NOTSPEC && c == NOTSPEC && | |
779 | tp == NULL) | 779 | tp == NULL) | |
780 | dcs->d_notyp = true; | 780 | dcs->d_notyp = true; | |
781 | if (t == NOTSPEC && s == NOTSPEC && (l == NOTSPEC || l == LONG) && | 781 | if (t == NOTSPEC && s == NOTSPEC && (l == NOTSPEC || l == LONG) && | |
782 | tp == NULL) | 782 | tp == NULL) | |
783 | t = c; | 783 | t = c; | |
784 | 784 | |||
785 | if (tp != NULL) { | 785 | if (tp != NULL) { | |
786 | lint_assert(t == NOTSPEC); | 786 | lint_assert(t == NOTSPEC); | |
787 | lint_assert(s == NOTSPEC); | 787 | lint_assert(s == NOTSPEC); | |
788 | lint_assert(l == NOTSPEC); | 788 | lint_assert(l == NOTSPEC); | |
789 | return; | 789 | return; | |
790 | } | 790 | } | |
791 | 791 | |||
792 | if (t == NOTSPEC) | 792 | if (t == NOTSPEC) | |
793 | t = INT; | 793 | t = INT; | |
794 | if (s == NOTSPEC && t == INT) | 794 | if (s == NOTSPEC && t == INT) | |
795 | s = SIGNED; | 795 | s = SIGNED; | |
796 | if (l != NOTSPEC && t == CHAR) { | 796 | if (l != NOTSPEC && t == CHAR) { | |
797 | dcs->d_invalid_type_combination = true; | 797 | dcs->d_invalid_type_combination = true; | |
798 | l = NOTSPEC; | 798 | l = NOTSPEC; | |
799 | } | 799 | } | |
800 | if (l == LONG && t == FLOAT) { | 800 | if (l == LONG && t == FLOAT) { | |
801 | l = NOTSPEC; | 801 | l = NOTSPEC; | |
802 | t = DOUBLE; | 802 | t = DOUBLE; | |
803 | if (!tflag) | 803 | if (!tflag) | |
804 | /* use 'double' instead of 'long float' */ | 804 | /* use 'double' instead of 'long float' */ | |
805 | warning(6); | 805 | warning(6); | |
806 | } | 806 | } | |
807 | if ((l == LONG && t == DOUBLE) || t == LDOUBLE) { | 807 | if ((l == LONG && t == DOUBLE) || t == LDOUBLE) { | |
808 | l = NOTSPEC; | 808 | l = NOTSPEC; | |
809 | t = LDOUBLE; | 809 | t = LDOUBLE; | |
810 | } | 810 | } | |
811 | if (t == LDOUBLE && tflag) { | 811 | if (t == LDOUBLE && tflag) { | |
812 | /* 'long double' is illegal in traditional C */ | 812 | /* 'long double' is illegal in traditional C */ | |
813 | warning(266); | 813 | warning(266); | |
814 | } | 814 | } | |
815 | if (l == LONG && t == DCOMPLEX) { | 815 | if (l == LONG && t == DCOMPLEX) { | |
816 | l = NOTSPEC; | 816 | l = NOTSPEC; | |
817 | t = LCOMPLEX; | 817 | t = LCOMPLEX; | |
818 | } | 818 | } | |
819 | 819 | |||
820 | if (t != INT && t != CHAR && (s != NOTSPEC || l != NOTSPEC)) { | 820 | if (t != INT && t != CHAR && (s != NOTSPEC || l != NOTSPEC)) { | |
821 | dcs->d_invalid_type_combination = true; | 821 | dcs->d_invalid_type_combination = true; | |
822 | l = s = NOTSPEC; | 822 | l = s = NOTSPEC; | |
823 | } | 823 | } | |
824 | if (l != NOTSPEC) | 824 | if (l != NOTSPEC) | |
825 | t = l; | 825 | t = l; | |
826 | dcs->d_type = gettyp(merge_signedness(t, s)); | 826 | dcs->d_type = gettyp(merge_signedness(t, s)); | |
827 | } | 827 | } | |
828 | 828 | |||
829 | /* | 829 | /* | |
830 | * Create a type structure from the information gathered in | 830 | * Create a type structure from the information gathered in | |
831 | * the declaration stack. | 831 | * the declaration stack. | |
832 | * Complain about storage classes which are not possible in current | 832 | * Complain about storage classes which are not possible in current | |
833 | * context. | 833 | * context. | |
834 | */ | 834 | */ | |
835 | void | 835 | void | |
836 | end_type(void) | 836 | end_type(void) | |
837 | { | 837 | { | |
838 | 838 | |||
839 | dcs_merge_declaration_specifiers(); | 839 | dcs_merge_declaration_specifiers(); | |
840 | 840 | |||
841 | if (dcs->d_multiple_storage_classes) { | 841 | if (dcs->d_multiple_storage_classes) { | |
842 | /* only one storage class allowed */ | 842 | /* only one storage class allowed */ | |
843 | error(7); | 843 | error(7); | |
844 | } | 844 | } | |
845 | if (dcs->d_invalid_type_combination) { | 845 | if (dcs->d_invalid_type_combination) { | |
846 | /* illegal type combination */ | 846 | /* illegal type combination */ | |
847 | error(4); | 847 | error(4); | |
848 | } | 848 | } | |
849 | 849 | |||
850 | dcs_adjust_storage_class(); | 850 | dcs_adjust_storage_class(); | |
851 | 851 | |||
852 | if (dcs->d_const && dcs->d_type->t_const) { | 852 | if (dcs->d_const && dcs->d_type->t_const) { | |
853 | lint_assert(dcs->d_type->t_typedef); | 853 | lint_assert(dcs->d_type->t_typedef); | |
854 | /* typedef already qualified with '%s' */ | 854 | /* typedef already qualified with '%s' */ | |
855 | warning(68, "const"); | 855 | warning(68, "const"); | |
856 | } | 856 | } | |
857 | if (dcs->d_volatile && dcs->d_type->t_volatile) { | 857 | if (dcs->d_volatile && dcs->d_type->t_volatile) { | |
858 | lint_assert(dcs->d_type->t_typedef); | 858 | lint_assert(dcs->d_type->t_typedef); | |
859 | /* typedef already qualified with '%s' */ | 859 | /* typedef already qualified with '%s' */ | |
860 | warning(68, "volatile"); | 860 | warning(68, "volatile"); | |
861 | } | 861 | } | |
862 | 862 | |||
863 | if (dcs->d_const || dcs->d_volatile) { | 863 | if (dcs->d_const || dcs->d_volatile) { | |
864 | dcs->d_type = block_dup_type(dcs->d_type); | 864 | dcs->d_type = block_dup_type(dcs->d_type); | |
865 | dcs->d_type->t_const |= dcs->d_const; | 865 | dcs->d_type->t_const |= dcs->d_const; | |
866 | dcs->d_type->t_volatile |= dcs->d_volatile; | 866 | dcs->d_type->t_volatile |= dcs->d_volatile; | |
867 | } | 867 | } | |
868 | } | 868 | } | |
869 | 869 | |||
870 | /* | 870 | /* | |
871 | * Return the length of a type in bits. | 871 | * Return the length of a type in bits. | |
872 | * | 872 | * | |
873 | * Printing a message if the outermost dimension of an array is 0 must | 873 | * Printing a message if the outermost dimension of an array is 0 must | |
874 | * be done by the caller. All other problems are reported by length() | 874 | * be done by the caller. All other problems are reported by length() | |
875 | * if name is not NULL. | 875 | * if name is not NULL. | |
876 | */ | 876 | */ | |
877 | int | 877 | int | |
878 | length(const type_t *tp, const char *name) | 878 | length(const type_t *tp, const char *name) | |
879 | { | 879 | { | |
880 | unsigned int elem, elsz; | 880 | unsigned int elem, elsz; | |
881 | 881 | |||
882 | elem = 1; | 882 | elem = 1; | |
883 | while (tp != NULL && tp->t_tspec == ARRAY) { | 883 | while (tp != NULL && tp->t_tspec == ARRAY) { | |
884 | elem *= tp->t_dim; | 884 | elem *= tp->t_dim; | |
885 | tp = tp->t_subt; | 885 | tp = tp->t_subt; | |
886 | } | 886 | } | |
887 | if (tp == NULL) | 887 | if (tp == NULL) | |
888 | return -1; | 888 | return -1; | |
889 | 889 | |||
890 | switch (tp->t_tspec) { | 890 | switch (tp->t_tspec) { | |
891 | case FUNC: | 891 | case FUNC: | |
892 | /* compiler takes size of function */ | 892 | /* compiler takes size of function */ | |
893 | INTERNAL_ERROR("%s", msgs[12]); | 893 | INTERNAL_ERROR("%s", msgs[12]); | |
894 | /* NOTREACHED */ | 894 | /* NOTREACHED */ | |
895 | case STRUCT: | 895 | case STRUCT: | |
896 | case UNION: | 896 | case UNION: | |
897 | if (is_incomplete(tp) && name != NULL) { | 897 | if (is_incomplete(tp) && name != NULL) { | |
898 | /* '%s' has incomplete type '%s' */ | 898 | /* '%s' has incomplete type '%s' */ | |
899 | error(31, name, type_name(tp)); | 899 | error(31, name, type_name(tp)); | |
900 | } | 900 | } | |
901 | elsz = tp->t_str->sou_size_in_bits; | 901 | elsz = tp->t_str->sou_size_in_bits; | |
902 | break; | 902 | break; | |
903 | case ENUM: | 903 | case ENUM: | |
904 | if (is_incomplete(tp) && name != NULL) { | 904 | if (is_incomplete(tp) && name != NULL) { | |
905 | /* incomplete enum type: %s */ | 905 | /* incomplete enum type: %s */ | |
906 | warning(13, name); | 906 | warning(13, name); | |
907 | } | 907 | } | |
908 | /* FALLTHROUGH */ | 908 | /* FALLTHROUGH */ | |
909 | default: | 909 | default: | |
910 | elsz = size_in_bits(tp->t_tspec); | 910 | elsz = size_in_bits(tp->t_tspec); | |
911 | lint_assert(elsz > 0); | 911 | lint_assert(elsz > 0); | |
912 | break; | 912 | break; | |
913 | } | 913 | } | |
914 | return (int)(elem * elsz); | 914 | return (int)(elem * elsz); | |
915 | } | 915 | } | |
916 | 916 | |||
917 | unsigned int | 917 | unsigned int | |
918 | alignment_in_bits(const type_t *tp) | 918 | alignment_in_bits(const type_t *tp) | |
919 | { | 919 | { | |
920 | unsigned int a; | 920 | unsigned int a; | |
921 | tspec_t t; | 921 | tspec_t t; | |
922 | 922 | |||
923 | while (tp->t_tspec == ARRAY) | 923 | while (tp->t_tspec == ARRAY) | |
924 | tp = tp->t_subt; | 924 | tp = tp->t_subt; | |
925 | 925 | |||
926 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { | 926 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { | |
927 | a = tp->t_str->sou_align_in_bits; | 927 | a = tp->t_str->sou_align_in_bits; | |
928 | } else if (t == FUNC) { | 928 | } else if (t == FUNC) { | |
929 | /* compiler takes alignment of function */ | 929 | /* compiler takes alignment of function */ | |
930 | error(14); | 930 | error(14); | |
931 | a = WORST_ALIGN(1) * CHAR_SIZE; | 931 | a = WORST_ALIGN(1) * CHAR_SIZE; | |
932 | } else { | 932 | } else { | |
933 | if ((a = size_in_bits(t)) == 0) { | 933 | if ((a = size_in_bits(t)) == 0) { | |
934 | a = CHAR_SIZE; | 934 | a = CHAR_SIZE; | |
935 | } else if (a > WORST_ALIGN(1) * CHAR_SIZE) { | 935 | } else if (a > WORST_ALIGN(1) * CHAR_SIZE) { | |
936 | a = WORST_ALIGN(1) * CHAR_SIZE; | 936 | a = WORST_ALIGN(1) * CHAR_SIZE; | |
937 | } | 937 | } | |
938 | } | 938 | } | |
939 | lint_assert(a >= CHAR_SIZE); | 939 | lint_assert(a >= CHAR_SIZE); | |
940 | lint_assert(a <= WORST_ALIGN(1) * CHAR_SIZE); | 940 | lint_assert(a <= WORST_ALIGN(1) * CHAR_SIZE); | |
941 | return a; | 941 | return a; | |
942 | } | 942 | } | |
943 | 943 | |||
944 | /* | 944 | /* | |
945 | * Concatenate two lists of symbols by s_next. Used by declarations of | 945 | * Concatenate two lists of symbols by s_next. Used by declarations of | |
946 | * struct/union/enum elements and parameters. | 946 | * struct/union/enum elements and parameters. | |
947 | */ | 947 | */ | |
948 | sym_t * | 948 | sym_t * | |
949 | lnklst(sym_t *l1, sym_t *l2) | 949 | lnklst(sym_t *l1, sym_t *l2) | |
950 | { | 950 | { | |
951 | sym_t *l; | 951 | sym_t *l; | |
952 | 952 | |||
953 | if ((l = l1) == NULL) | 953 | if ((l = l1) == NULL) | |
954 | return l2; | 954 | return l2; | |
955 | while (l1->s_next != NULL) | 955 | while (l1->s_next != NULL) | |
956 | l1 = l1->s_next; | 956 | l1 = l1->s_next; | |
957 | l1->s_next = l2; | 957 | l1->s_next = l2; | |
958 | return l; | 958 | return l; | |
959 | } | 959 | } | |
960 | 960 | |||
961 | /* | 961 | /* | |
962 | * Check if the type of the given symbol is valid and print an error | 962 | * Check if the type of the given symbol is valid and print an error | |
963 | * message if it is not. | 963 | * message if it is not. | |
964 | * | 964 | * | |
965 | * Invalid types are: | 965 | * Invalid types are: | |
966 | * - arrays of incomplete types or functions | 966 | * - arrays of incomplete types or functions | |
967 | * - functions returning arrays or functions | 967 | * - functions returning arrays or functions | |
968 | * - void types other than type of function or pointer | 968 | * - void types other than type of function or pointer | |
969 | */ | 969 | */ | |
970 | void | 970 | void | |
971 | check_type(sym_t *sym) | 971 | check_type(sym_t *sym) | |
972 | { | 972 | { | |
973 | tspec_t to, t; | 973 | tspec_t to, t; | |
974 | type_t **tpp, *tp; | 974 | type_t **tpp, *tp; | |
975 | 975 | |||
976 | tpp = &sym->s_type; | 976 | tpp = &sym->s_type; | |
977 | to = NOTSPEC; | 977 | to = NOTSPEC; | |
978 | while ((tp = *tpp) != NULL) { | 978 | while ((tp = *tpp) != NULL) { | |
979 | t = tp->t_tspec; | 979 | t = tp->t_tspec; | |
980 | /* | 980 | /* | |
981 | * If this is the type of an old style function definition, | 981 | * If this is the type of an old style function definition, | |
982 | * a better warning is printed in funcdef(). | 982 | * a better warning is printed in funcdef(). | |
983 | */ | 983 | */ | |
984 | if (t == FUNC && !tp->t_proto && | 984 | if (t == FUNC && !tp->t_proto && | |
985 | !(to == NOTSPEC && sym->s_osdef)) { | 985 | !(to == NOTSPEC && sym->s_osdef)) { | |
986 | if (sflag && hflag) | 986 | if (sflag && hflag) | |
987 | /* function declaration is not a prototype */ | 987 | /* function declaration is not a prototype */ | |
988 | warning(287); | 988 | warning(287); | |
989 | } | 989 | } | |
990 | if (to == FUNC) { | 990 | if (to == FUNC) { | |
991 | if (t == FUNC || t == ARRAY) { | 991 | if (t == FUNC || t == ARRAY) { | |
992 | /* function returns illegal type */ | 992 | /* function returns illegal type */ | |
993 | error(15); | 993 | error(15); | |
994 | if (t == FUNC) { | 994 | if (t == FUNC) { | |
995 | *tpp = block_derive_type(*tpp, PTR); | 995 | *tpp = block_derive_type(*tpp, PTR); | |
996 | } else { | 996 | } else { | |
997 | *tpp = block_derive_type( | 997 | *tpp = block_derive_type( | |
998 | (*tpp)->t_subt, PTR); | 998 | (*tpp)->t_subt, PTR); | |
999 | } | 999 | } | |
1000 | return; | 1000 | return; | |
1001 | } else if (tp->t_const || tp->t_volatile) { | 1001 | } else if (tp->t_const || tp->t_volatile) { | |
1002 | if (sflag) { /* XXX or better !tflag ? */ | 1002 | if (sflag) { /* XXX or better !tflag ? */ | |
1003 | /* function cannot return const... */ | 1003 | /* function cannot return const... */ | |
1004 | warning(228); | 1004 | warning(228); | |
1005 | } | 1005 | } | |
1006 | } | 1006 | } | |
1007 | } if (to == ARRAY) { | 1007 | } if (to == ARRAY) { | |
1008 | if (t == FUNC) { | 1008 | if (t == FUNC) { | |
1009 | /* array of function is illegal */ | 1009 | /* array of function is illegal */ | |
1010 | error(16); | 1010 | error(16); | |
1011 | *tpp = gettyp(INT); | 1011 | *tpp = gettyp(INT); | |
1012 | return; | 1012 | return; | |
1013 | } else if (t == ARRAY && tp->t_dim == 0) { | 1013 | } else if (t == ARRAY && tp->t_dim == 0) { | |
1014 | /* null dimension */ | 1014 | /* null dimension */ | |
1015 | error(17); | 1015 | error(17); | |
1016 | return; | 1016 | return; | |
1017 | } else if (t == VOID) { | 1017 | } else if (t == VOID) { | |
1018 | /* illegal use of 'void' */ | 1018 | /* illegal use of 'void' */ | |
1019 | error(18); | 1019 | error(18); | |
1020 | *tpp = gettyp(INT); | 1020 | *tpp = gettyp(INT); | |
1021 | #if 0 /* errors are produced by length() */ | 1021 | #if 0 /* errors are produced by length() */ | |
1022 | } else if (is_incomplete(tp)) { | 1022 | } else if (is_incomplete(tp)) { | |
1023 | /* array of incomplete type */ | 1023 | /* array of incomplete type */ | |
1024 | if (sflag) { | 1024 | if (sflag) { | |
1025 | /* array of incomplete type */ | 1025 | /* array of incomplete type */ | |
1026 | error(301); | 1026 | error(301); | |
1027 | } else { | 1027 | } else { | |
1028 | /* array of incomplete type */ | 1028 | /* array of incomplete type */ | |
1029 | warning(301); | 1029 | warning(301); | |
1030 | } | 1030 | } | |
1031 | #endif | 1031 | #endif | |
1032 | } | 1032 | } | |
1033 | } else if (to == NOTSPEC && t == VOID) { | 1033 | } else if (to == NOTSPEC && t == VOID) { | |
1034 | if (dcs->d_ctx == PROTO_ARG) { | 1034 | if (dcs->d_ctx == PROTO_ARG) { | |
1035 | if (sym->s_scl != ABSTRACT) { | 1035 | if (sym->s_scl != ABSTRACT) { | |
1036 | lint_assert(sym->s_name != unnamed); | 1036 | lint_assert(sym->s_name != unnamed); | |
1037 | /* void parameter cannot have ... */ | 1037 | /* void parameter cannot have ... */ | |
1038 | error(61, sym->s_name); | 1038 | error(61, sym->s_name); | |
1039 | *tpp = gettyp(INT); | 1039 | *tpp = gettyp(INT); | |
1040 | } | 1040 | } | |
1041 | } else if (dcs->d_ctx == ABSTRACT) { | 1041 | } else if (dcs->d_ctx == ABSTRACT) { | |
1042 | /* ok */ | 1042 | /* ok */ | |
1043 | } else if (sym->s_scl != TYPEDEF) { | 1043 | } else if (sym->s_scl != TYPEDEF) { | |
1044 | /* void type for '%s' */ | 1044 | /* void type for '%s' */ | |
1045 | error(19, sym->s_name); | 1045 | error(19, sym->s_name); | |
1046 | *tpp = gettyp(INT); | 1046 | *tpp = gettyp(INT); | |
1047 | } | 1047 | } | |
1048 | } | 1048 | } | |
1049 | if (t == VOID && to != PTR) { | 1049 | if (t == VOID && to != PTR) { | |
1050 | if (tp->t_const || tp->t_volatile) { | 1050 | if (tp->t_const || tp->t_volatile) { | |
1051 | /* inappropriate qualifiers with 'void' */ | 1051 | /* inappropriate qualifiers with 'void' */ | |
1052 | warning(69); | 1052 | warning(69); | |
1053 | tp->t_const = tp->t_volatile = false; | 1053 | tp->t_const = tp->t_volatile = false; | |
1054 | } | 1054 | } | |
1055 | } | 1055 | } | |
1056 | tpp = &tp->t_subt; | 1056 | tpp = &tp->t_subt; | |
1057 | to = t; | 1057 | to = t; | |
1058 | } | 1058 | } | |
1059 | } | 1059 | } | |
1060 | 1060 | |||
1061 | /* | 1061 | /* | |
1062 | * In traditional C, the only portable type for bit-fields is unsigned int. | 1062 | * In traditional C, the only portable type for bit-fields is unsigned int. | |
1063 | * | 1063 | * | |
1064 | * In C90, the only allowed types for bit-fields are int, signed int and | 1064 | * In C90, the only allowed types for bit-fields are int, signed int and | |
1065 | * unsigned int (3.5.2.1). There is no mention of implementation-defined | 1065 | * unsigned int (3.5.2.1). There is no mention of implementation-defined | |
1066 | * types. | 1066 | * types. | |
1067 | * | 1067 | * | |
1068 | * In C99, the only portable types for bit-fields are _Bool, signed int and | 1068 | * In C99, the only portable types for bit-fields are _Bool, signed int and | |
1069 | * unsigned int (6.7.2.1p4). In addition, C99 allows "or some other | 1069 | * unsigned int (6.7.2.1p4). In addition, C99 allows "or some other | |
1070 | * implementation-defined type". | 1070 | * implementation-defined type". | |
1071 | */ | 1071 | */ | |
1072 | static void | 1072 | static void | |
1073 | check_bit_field_type(sym_t *dsym, type_t **const inout_tp, tspec_t *inout_t) | 1073 | check_bit_field_type(sym_t *dsym, type_t **const inout_tp, tspec_t *inout_t) | |
1074 | { | 1074 | { | |
1075 | type_t *tp = *inout_tp; | 1075 | type_t *tp = *inout_tp; | |
1076 | tspec_t t = *inout_t; | 1076 | tspec_t t = *inout_t; | |
1077 | 1077 | |||
1078 | if (t == CHAR || t == UCHAR || t == SCHAR || | 1078 | if (t == CHAR || t == UCHAR || t == SCHAR || | |
1079 | t == SHORT || t == USHORT || t == ENUM) { | 1079 | t == SHORT || t == USHORT || t == ENUM) { | |
1080 | if (!bitfieldtype_ok) { | 1080 | if (!bitfieldtype_ok) { | |
1081 | if (sflag) { | 1081 | if (sflag) { | |
1082 | /* bit-field type '%s' invalid in ANSI C */ | 1082 | /* bit-field type '%s' invalid in ANSI C */ | |
1083 | warning(273, type_name(tp)); | 1083 | warning(273, type_name(tp)); | |
1084 | } else if (pflag) { | 1084 | } else if (pflag) { | |
1085 | /* nonportable bit-field type '%s' */ | 1085 | /* nonportable bit-field type '%s' */ | |
1086 | warning(34, type_name(tp)); | 1086 | warning(34, type_name(tp)); | |
1087 | } | 1087 | } | |
1088 | } | 1088 | } | |
1089 | } else if (t == INT && dcs->d_sign_mod == NOTSPEC) { | 1089 | } else if (t == INT && dcs->d_sign_mod == NOTSPEC) { | |
1090 | if (pflag && !bitfieldtype_ok) { | 1090 | if (pflag && !bitfieldtype_ok) { | |
1091 | /* bit-field of type plain 'int' has ... */ | 1091 | /* bit-field of type plain 'int' has ... */ | |
1092 | warning(344); | 1092 | warning(344); | |
1093 | } | 1093 | } | |
1094 | } else if (t != INT && t != UINT && t != BOOL) { | 1094 | } else if (t != INT && t != UINT && t != BOOL) { | |
1095 | /* | 1095 | /* | |
1096 | * Non-integer types are always illegal for bitfields, | 1096 | * Non-integer types are always illegal for bitfields, | |
1097 | * regardless of BITFIELDTYPE. Integer types not dealt with | 1097 | * regardless of BITFIELDTYPE. Integer types not dealt with | |
1098 | * above are okay only if BITFIELDTYPE is in effect. | 1098 | * above are okay only if BITFIELDTYPE is in effect. | |
1099 | */ | 1099 | */ | |
1100 | if (!(bitfieldtype_ok || gflag) || !is_integer(t)) { | 1100 | if (!(bitfieldtype_ok || gflag) || !is_integer(t)) { | |
1101 | unsigned int sz; | 1101 | unsigned int sz; | |
1102 | 1102 | |||
1103 | /* illegal bit-field type '%s' */ | 1103 | /* illegal bit-field type '%s' */ | |
1104 | warning(35, type_name(tp)); | 1104 | warning(35, type_name(tp)); | |
1105 | sz = tp->t_flen; | 1105 | sz = tp->t_flen; | |
1106 | dsym->s_type = tp = block_dup_type(gettyp(t = INT)); | 1106 | dsym->s_type = tp = block_dup_type(gettyp(t = INT)); | |
1107 | if ((tp->t_flen = sz) > size_in_bits(t)) | 1107 | if ((tp->t_flen = sz) > size_in_bits(t)) | |
1108 | tp->t_flen = size_in_bits(t); | 1108 | tp->t_flen = size_in_bits(t); | |
1109 | *inout_t = t; | 1109 | *inout_t = t; | |
1110 | *inout_tp = tp; | 1110 | *inout_tp = tp; | |
1111 | } | 1111 | } | |
1112 | } | 1112 | } | |
1113 | } | 1113 | } | |
1114 | 1114 | |||
1115 | static void | 1115 | static void | |
1116 | declare_bit_field(sym_t *dsym, tspec_t *inout_t, type_t **const inout_tp) | 1116 | declare_bit_field(sym_t *dsym, tspec_t *inout_t, type_t **const inout_tp) | |
1117 | { | 1117 | { | |
1118 | type_t *tp; | 1118 | type_t *tp; | |
1119 | tspec_t t; | 1119 | tspec_t t; | |
1120 | 1120 | |||
1121 | check_bit_field_type(dsym, inout_tp, inout_t); | 1121 | check_bit_field_type(dsym, inout_tp, inout_t); | |
1122 | 1122 | |||
1123 | tp = *inout_tp; | 1123 | tp = *inout_tp; | |
1124 | t = *inout_t; | 1124 | t = *inout_t; | |
1125 | if (tp->t_flen > size_in_bits(t)) { | 1125 | if (tp->t_flen > size_in_bits(t)) { | |
1126 | /* illegal bit-field size: %d */ | 1126 | /* illegal bit-field size: %d */ | |
1127 | error(36, tp->t_flen); | 1127 | error(36, tp->t_flen); | |
1128 | tp->t_flen = size_in_bits(t); | 1128 | tp->t_flen = size_in_bits(t); | |
1129 | } else if (tp->t_flen == 0 && dsym->s_name != unnamed) { | 1129 | } else if (tp->t_flen == 0 && dsym->s_name != unnamed) { | |
1130 | /* zero size bit-field */ | 1130 | /* zero size bit-field */ | |
1131 | error(37); | 1131 | error(37); | |
1132 | tp->t_flen = size_in_bits(t); | 1132 | tp->t_flen = size_in_bits(t); | |
1133 | } | 1133 | } | |
1134 | if (dsym->s_scl == MOU) { | 1134 | if (dsym->s_scl == MOU) { | |
1135 | /* bit-field in union is very unusual */ | 1135 | /* bit-field in union is very unusual */ | |
1136 | warning(41); | 1136 | warning(41); | |
1137 | dsym->s_type->t_bitfield = false; | 1137 | dsym->s_type->t_bitfield = false; | |
1138 | dsym->s_bitfield = false; | 1138 | dsym->s_bitfield = false; | |
1139 | } | 1139 | } | |
1140 | } | 1140 | } | |
1141 | 1141 | |||
1142 | /* | 1142 | /* | |
1143 | * Process the declarator of a struct/union element. | 1143 | * Process the declarator of a struct/union element. | |
1144 | */ | 1144 | */ | |
1145 | sym_t * | 1145 | sym_t * | |
1146 | declarator_1_struct_union(sym_t *dsym) | 1146 | declarator_1_struct_union(sym_t *dsym) | |
1147 | { | 1147 | { | |
1148 | type_t *tp; | 1148 | type_t *tp; | |
1149 | tspec_t t; | 1149 | tspec_t t; | |
1150 | int sz; | 1150 | int sz; | |
1151 | unsigned int o = 0; /* Appease GCC */ | 1151 | unsigned int o = 0; /* Appease GCC */ | |
1152 | 1152 | |||
1153 | lint_assert(dsym->s_scl == MOS || dsym->s_scl == MOU); | 1153 | lint_assert(dsym->s_scl == MOS || dsym->s_scl == MOU); | |
1154 | 1154 | |||
1155 | if (dcs->d_redeclared_symbol != NULL) { | 1155 | if (dcs->d_redeclared_symbol != NULL) { | |
1156 | /* should be ensured by storesym() */ | 1156 | /* should be ensured by storesym() */ | |
1157 | lint_assert(dcs->d_redeclared_symbol->s_scl == MOS || | 1157 | lint_assert(dcs->d_redeclared_symbol->s_scl == MOS || | |
1158 | dcs->d_redeclared_symbol->s_scl == MOU); | 1158 | dcs->d_redeclared_symbol->s_scl == MOU); | |
1159 | 1159 | |||
1160 | if (dsym->s_styp == dcs->d_redeclared_symbol->s_styp) { | 1160 | if (dsym->s_styp == dcs->d_redeclared_symbol->s_styp) { | |
1161 | /* duplicate member name: %s */ | 1161 | /* duplicate member name: %s */ | |
1162 | error(33, dsym->s_name); | 1162 | error(33, dsym->s_name); | |
1163 | rmsym(dcs->d_redeclared_symbol); | 1163 | rmsym(dcs->d_redeclared_symbol); | |
1164 | } | 1164 | } | |
1165 | } | 1165 | } | |
1166 | 1166 | |||
1167 | check_type(dsym); | 1167 | check_type(dsym); | |
1168 | 1168 | |||
1169 | t = (tp = dsym->s_type)->t_tspec; | 1169 | t = (tp = dsym->s_type)->t_tspec; | |
1170 | 1170 | |||
1171 | if (dsym->s_bitfield) { | 1171 | if (dsym->s_bitfield) { | |
1172 | declare_bit_field(dsym, &t, &tp); | 1172 | declare_bit_field(dsym, &t, &tp); | |
1173 | } else if (t == FUNC) { | 1173 | } else if (t == FUNC) { | |
1174 | /* function illegal in structure or union */ | 1174 | /* function illegal in structure or union */ | |
1175 | error(38); | 1175 | error(38); | |
1176 | dsym->s_type = tp = block_derive_type(tp, t = PTR); | 1176 | dsym->s_type = tp = block_derive_type(tp, t = PTR); | |
1177 | } | 1177 | } | |
1178 | 1178 | |||
1179 | /* | 1179 | /* | |
1180 | * bit-fields of length 0 are not warned about because length() | 1180 | * bit-fields of length 0 are not warned about because length() | |
1181 | * does not return the length of the bit-field but the length | 1181 | * does not return the length of the bit-field but the length | |
1182 | * of the type the bit-field is packed in (it's ok) | 1182 | * of the type the bit-field is packed in (it's ok) | |
1183 | */ | 1183 | */ | |
1184 | if ((sz = length(dsym->s_type, dsym->s_name)) == 0) { | 1184 | if ((sz = length(dsym->s_type, dsym->s_name)) == 0) { | |
1185 | if (t == ARRAY && dsym->s_type->t_dim == 0) { | 1185 | if (t == ARRAY && dsym->s_type->t_dim == 0) { | |
1186 | /* zero sized array in struct is a C99 extension: %s */ | 1186 | /* zero sized array in struct is a C99 extension: %s */ | |
1187 | c99ism(39, dsym->s_name); | 1187 | c99ism(39, dsym->s_name); | |
1188 | } | 1188 | } | |
1189 | } | 1189 | } | |
1190 | 1190 | |||
1191 | if (dcs->d_ctx == MOU) { | 1191 | if (dcs->d_ctx == MOU) { | |
1192 | o = dcs->d_offset; | 1192 | o = dcs->d_offset; | |
1193 | dcs->d_offset = 0; | 1193 | dcs->d_offset = 0; | |
1194 | } | 1194 | } | |
1195 | if (dsym->s_bitfield) { | 1195 | if (dsym->s_bitfield) { | |
1196 | align(alignment_in_bits(tp), tp->t_flen); | 1196 | align(alignment_in_bits(tp), tp->t_flen); | |
1197 | dsym->s_value.v_quad = | 1197 | dsym->s_value.v_quad = | |
1198 | dcs->d_offset - dcs->d_offset % size_in_bits(t); | 1198 | dcs->d_offset - dcs->d_offset % size_in_bits(t); | |
1199 | tp->t_foffs = dcs->d_offset - (int)dsym->s_value.v_quad; | 1199 | tp->t_foffs = dcs->d_offset - (int)dsym->s_value.v_quad; | |
1200 | dcs->d_offset += tp->t_flen; | 1200 | dcs->d_offset += tp->t_flen; | |
1201 | } else { | 1201 | } else { | |
1202 | align(alignment_in_bits(tp), 0); | 1202 | align(alignment_in_bits(tp), 0); | |
1203 | dsym->s_value.v_quad = dcs->d_offset; | 1203 | dsym->s_value.v_quad = dcs->d_offset; | |
1204 | dcs->d_offset += sz; | 1204 | dcs->d_offset += sz; | |
1205 | } | 1205 | } | |
1206 | if (dcs->d_ctx == MOU) { | 1206 | if (dcs->d_ctx == MOU) { | |
1207 | if (o > dcs->d_offset) | 1207 | if (o > dcs->d_offset) | |
1208 | dcs->d_offset = o; | 1208 | dcs->d_offset = o; | |
1209 | } | 1209 | } | |
1210 | 1210 | |||
1211 | check_function_definition(dsym, false); | 1211 | check_function_definition(dsym, false); | |
1212 | 1212 | |||
1213 | /* | 1213 | /* | |
1214 | * Clear the BITFIELDTYPE indicator after processing each | 1214 | * Clear the BITFIELDTYPE indicator after processing each | |
1215 | * structure element. | 1215 | * structure element. | |
1216 | */ | 1216 | */ | |
1217 | bitfieldtype_ok = false; | 1217 | bitfieldtype_ok = false; | |
1218 | 1218 | |||
1219 | return dsym; | 1219 | return dsym; | |
1220 | } | 1220 | } | |
1221 | 1221 | |||
1222 | /* | 1222 | /* | |
1223 | * Aligns next structure element as required. | 1223 | * Aligns next structure element as required. | |
1224 | * | 1224 | * | |
1225 | * al contains the required alignment, len the length of a bit-field. | 1225 | * al contains the required alignment, len the length of a bit-field. | |
1226 | */ | 1226 | */ | |
1227 | static void | 1227 | static void | |
1228 | align(unsigned int al, unsigned int len) | 1228 | align(unsigned int al, unsigned int len) | |
1229 | { | 1229 | { | |
1230 | unsigned int no; | 1230 | unsigned int no; | |
1231 | 1231 | |||
1232 | /* | 1232 | /* | |
1233 | * The alignment of the current element becomes the alignment of | 1233 | * The alignment of the current element becomes the alignment of | |
1234 | * the struct/union if it is larger than the current alignment | 1234 | * the struct/union if it is larger than the current alignment | |
1235 | * of the struct/union. | 1235 | * of the struct/union. | |
1236 | */ | 1236 | */ | |
1237 | if (al > dcs->d_sou_align_in_bits) | 1237 | if (al > dcs->d_sou_align_in_bits) | |
1238 | dcs->d_sou_align_in_bits = al; | 1238 | dcs->d_sou_align_in_bits = al; | |
1239 | 1239 | |||
1240 | no = (dcs->d_offset + (al - 1)) & ~(al - 1); | 1240 | no = (dcs->d_offset + (al - 1)) & ~(al - 1); | |
1241 | if (len == 0 || dcs->d_offset + len > no) | 1241 | if (len == 0 || dcs->d_offset + len > no) | |
1242 | dcs->d_offset = no; | 1242 | dcs->d_offset = no; | |
1243 | } | 1243 | } | |
1244 | 1244 | |||
1245 | /* | 1245 | /* | |
1246 | * Remember the width of the field in its type structure. | 1246 | * Remember the width of the field in its type structure. | |
1247 | */ | 1247 | */ | |
1248 | sym_t * | 1248 | sym_t * | |
1249 | bitfield(sym_t *dsym, int len) | 1249 | bitfield(sym_t *dsym, int len) | |
1250 | { | 1250 | { | |
1251 | 1251 | |||
1252 | if (dsym == NULL) { | 1252 | if (dsym == NULL) { | |
1253 | dsym = block_zero_alloc(sizeof(*dsym)); | 1253 | dsym = block_zero_alloc(sizeof(*dsym)); | |
1254 | dsym->s_name = unnamed; | 1254 | dsym->s_name = unnamed; | |
1255 | dsym->s_kind = FMEMBER; | 1255 | dsym->s_kind = FMEMBER; | |
1256 | dsym->s_scl = MOS; | 1256 | dsym->s_scl = MOS; | |
1257 | dsym->s_type = gettyp(UINT); | 1257 | dsym->s_type = gettyp(UINT); | |
1258 | dsym->s_block_level = -1; | 1258 | dsym->s_block_level = -1; | |
1259 | } | 1259 | } | |
1260 | dsym->s_type = block_dup_type(dsym->s_type); | 1260 | dsym->s_type = block_dup_type(dsym->s_type); | |
1261 | dsym->s_type->t_bitfield = true; | 1261 | dsym->s_type->t_bitfield = true; | |
1262 | dsym->s_type->t_flen = len; | 1262 | dsym->s_type->t_flen = len; | |
1263 | dsym->s_bitfield = true; | 1263 | dsym->s_bitfield = true; | |
1264 | return dsym; | 1264 | return dsym; | |
1265 | } | 1265 | } | |
1266 | 1266 | |||
1267 | /* | 1267 | /* | |
1268 | * A sequence of asterisks and qualifiers, from right to left. For example, | 1268 | * A sequence of asterisks and qualifiers, from right to left. For example, | |
1269 | * 'const ***volatile **const volatile' results in [cvp, p, vp, p, p]. The | 1269 | * 'const ***volatile **const volatile' results in [cvp, p, vp, p, p]. The | |
1270 | * leftmost 'const' is not included in this list, it is stored in dcs->d_const | 1270 | * leftmost 'const' is not included in this list, it is stored in dcs->d_const | |
1271 | * instead. | 1271 | * instead. | |
1272 | */ | 1272 | */ | |
1273 | qual_ptr * | 1273 | qual_ptr * | |
1274 | merge_qualified_pointer(qual_ptr *p1, qual_ptr *p2) | 1274 | merge_qualified_pointer(qual_ptr *p1, qual_ptr *p2) | |
1275 | { | 1275 | { | |
1276 | qual_ptr *tail; | 1276 | qual_ptr *tail; | |
1277 | 1277 | |||
1278 | if (p2 == NULL) | 1278 | if (p2 == NULL) | |
1279 | return p1; /* for optional qualifiers */ | 1279 | return p1; /* for optional qualifiers */ | |
1280 | 1280 | |||
1281 | if (p2->p_pointer) { | 1281 | if (p2->p_pointer) { | |
1282 | /* append p1 to p2, keeping p2 */ | 1282 | /* append p1 to p2, keeping p2 */ | |
1283 | for (tail = p2; tail->p_next != NULL; tail = tail->p_next) | 1283 | for (tail = p2; tail->p_next != NULL; tail = tail->p_next) | |
1284 | continue; | 1284 | continue; | |
1285 | tail->p_next = p1; | 1285 | tail->p_next = p1; | |
1286 | return p2; | 1286 | return p2; | |
1287 | } | 1287 | } | |
1288 | 1288 | |||
1289 | /* merge p2 into p1, keeping p1 */ | 1289 | /* merge p2 into p1, keeping p1 */ | |
1290 | if (p2->p_const) { | 1290 | if (p2->p_const) { | |
1291 | if (p1->p_const) { | 1291 | if (p1->p_const) { | |
1292 | /* duplicate '%s' */ | 1292 | /* duplicate '%s' */ | |
1293 | warning(10, "const"); | 1293 | warning(10, "const"); | |
1294 | } | 1294 | } | |
1295 | p1->p_const = true; | 1295 | p1->p_const = true; | |
1296 | } | 1296 | } | |
1297 | if (p2->p_volatile) { | 1297 | if (p2->p_volatile) { | |
1298 | if (p1->p_volatile) { | 1298 | if (p1->p_volatile) { | |
1299 | /* duplicate '%s' */ | 1299 | /* duplicate '%s' */ | |
1300 | warning(10, "volatile"); | 1300 | warning(10, "volatile"); | |
1301 | } | 1301 | } | |
1302 | p1->p_volatile = true; | 1302 | p1->p_volatile = true; | |
1303 | } | 1303 | } | |
1304 | free(p2); | 1304 | free(p2); | |
1305 | return p1; | 1305 | return p1; | |
1306 | } | 1306 | } | |
1307 | 1307 | |||
1308 | /* | 1308 | /* | |
1309 | * The following 3 functions extend the type of a declarator with | 1309 | * The following 3 functions extend the type of a declarator with | |
1310 | * pointer, function and array types. | 1310 | * pointer, function and array types. | |
1311 | * | 1311 | * | |
1312 | * The current type is the type built by end_type() (dcs->d_type) and | 1312 | * The current type is the type built by end_type() (dcs->d_type) and | |
1313 | * pointer, function and array types already added for this | 1313 | * pointer, function and array types already added for this | |
1314 | * declarator. The new type extension is inserted between both. | 1314 | * declarator. The new type extension is inserted between both. | |
1315 | */ | 1315 | */ | |
1316 | sym_t * | 1316 | sym_t * | |
1317 | add_pointer(sym_t *decl, qual_ptr *p) | 1317 | add_pointer(sym_t *decl, qual_ptr *p) | |
1318 | { | 1318 | { | |
1319 | type_t **tpp, *tp; | 1319 | type_t **tpp, *tp; | |
1320 | qual_ptr *next; | 1320 | qual_ptr *next; | |
1321 | 1321 | |||
1322 | tpp = &decl->s_type; | 1322 | tpp = &decl->s_type; | |
1323 | while (*tpp != NULL && *tpp != dcs->d_type) | 1323 | while (*tpp != NULL && *tpp != dcs->d_type) | |
1324 | tpp = &(*tpp)->t_subt; | 1324 | tpp = &(*tpp)->t_subt; | |
1325 | if (*tpp == NULL) | 1325 | if (*tpp == NULL) | |
1326 | return decl; | 1326 | return decl; | |
1327 | 1327 | |||
1328 | while (p != NULL) { | 1328 | while (p != NULL) { | |
1329 | *tpp = tp = block_zero_alloc(sizeof(*tp)); | 1329 | *tpp = tp = block_zero_alloc(sizeof(*tp)); | |
1330 | tp->t_tspec = PTR; | 1330 | tp->t_tspec = PTR; | |
1331 | tp->t_const = p->p_const; | 1331 | tp->t_const = p->p_const; | |
1332 | tp->t_volatile = p->p_volatile; | 1332 | tp->t_volatile = p->p_volatile; | |
1333 | *(tpp = &tp->t_subt) = dcs->d_type; | 1333 | *(tpp = &tp->t_subt) = dcs->d_type; | |
1334 | next = p->p_next; | 1334 | next = p->p_next; | |
1335 | free(p); | 1335 | free(p); | |
1336 | p = next; | 1336 | p = next; | |
1337 | } | 1337 | } | |
1338 | return decl; | 1338 | return decl; | |
1339 | } | 1339 | } | |
1340 | 1340 | |||
1341 | /* | 1341 | /* | |
1342 | * If a dimension was specified, dim is true, otherwise false | 1342 | * If a dimension was specified, dim is true, otherwise false | |
1343 | * n is the specified dimension | 1343 | * n is the specified dimension | |
1344 | */ | 1344 | */ | |
1345 | sym_t * | 1345 | sym_t * | |
1346 | add_array(sym_t *decl, bool dim, int n) | 1346 | add_array(sym_t *decl, bool dim, int n) | |
1347 | { | 1347 | { | |
1348 | type_t **tpp, *tp; | 1348 | type_t **tpp, *tp; | |
1349 | 1349 | |||
1350 | tpp = &decl->s_type; | 1350 | tpp = &decl->s_type; | |
1351 | while (*tpp != NULL && *tpp != dcs->d_type) | 1351 | while (*tpp != NULL && *tpp != dcs->d_type) | |
1352 | tpp = &(*tpp)->t_subt; | 1352 | tpp = &(*tpp)->t_subt; | |
1353 | if (*tpp == NULL) | 1353 | if (*tpp == NULL) | |
1354 | return decl; | 1354 | return decl; | |
1355 | 1355 | |||
1356 | *tpp = tp = block_zero_alloc(sizeof(*tp)); | 1356 | *tpp = tp = block_zero_alloc(sizeof(*tp)); | |
1357 | tp->t_tspec = ARRAY; | 1357 | tp->t_tspec = ARRAY; | |
1358 | tp->t_subt = dcs->d_type; | 1358 | tp->t_subt = dcs->d_type; | |
1359 | tp->t_dim = n; | 1359 | tp->t_dim = n; | |
1360 | 1360 | |||
1361 | if (n < 0) { | 1361 | if (n < 0) { | |
1362 | /* negative array dimension (%d) */ | 1362 | /* negative array dimension (%d) */ | |
1363 | error(20, n); | 1363 | error(20, n); | |
1364 | n = 0; | 1364 | n = 0; | |
1365 | } else if (n == 0 && dim) { | 1365 | } else if (n == 0 && dim) { | |
1366 | /* zero sized array is a C99 extension */ | 1366 | /* zero sized array is a C99 extension */ | |
1367 | c99ism(322); | 1367 | c99ism(322); | |
1368 | } else if (n == 0 && !dim) { | 1368 | } else if (n == 0 && !dim) { | |
1369 | setcomplete(tp, false); | 1369 | setcomplete(tp, false); | |
1370 | } | 1370 | } | |
1371 | 1371 | |||
1372 | return decl; | 1372 | return decl; | |
1373 | } | 1373 | } | |
1374 | 1374 | |||
1375 | sym_t * | 1375 | sym_t * | |
1376 | add_function(sym_t *decl, sym_t *args) | 1376 | add_function(sym_t *decl, sym_t *args) | |
1377 | { | 1377 | { | |
1378 | type_t **tpp, *tp; | 1378 | type_t **tpp, *tp; | |
1379 | 1379 | |||
1380 | if (dcs->d_proto) { | 1380 | if (dcs->d_proto) { | |
1381 | if (tflag) | 1381 | if (tflag) | |
1382 | /* function prototypes are illegal in traditional C */ | 1382 | /* function prototypes are illegal in traditional C */ | |
1383 | warning(270); | 1383 | warning(270); | |
1384 | args = new_style_function(decl, args); | 1384 | args = new_style_function(decl, args); | |
1385 | } else { | 1385 | } else { | |
1386 | old_style_function(decl, args); | 1386 | old_style_function(decl, args); | |
1387 | } | 1387 | } | |
1388 | 1388 | |||
1389 | /* | 1389 | /* | |
1390 | * The symbols are removed from the symbol table by | 1390 | * The symbols are removed from the symbol table by | |
1391 | * end_declaration_level after add_function. To be able to restore | 1391 | * end_declaration_level after add_function. To be able to restore | |
1392 | * them if this is a function definition, a pointer to the list of all | 1392 | * them if this is a function definition, a pointer to the list of all | |
1393 | * symbols is stored in dcs->d_next->d_func_proto_syms. Also a list of | 1393 | * symbols is stored in dcs->d_next->d_func_proto_syms. Also a list of | |
1394 | * the arguments (concatenated by s_next) is stored in | 1394 | * the arguments (concatenated by s_next) is stored in | |
1395 | * dcs->d_next->d_func_args. (dcs->d_next must be used because *dcs is | 1395 | * dcs->d_next->d_func_args. (dcs->d_next must be used because *dcs is | |
1396 | * the declaration stack element created for the list of params and is | 1396 | * the declaration stack element created for the list of params and is | |
1397 | * removed after add_function.) | 1397 | * removed after add_function.) | |
1398 | */ | 1398 | */ | |
1399 | if (dcs->d_next->d_ctx == EXTERN && | 1399 | if (dcs->d_next->d_ctx == EXTERN && | |
1400 | decl->s_type == dcs->d_next->d_type) { | 1400 | decl->s_type == dcs->d_next->d_type) { | |
1401 | dcs->d_next->d_func_proto_syms = dcs->d_dlsyms; | 1401 | dcs->d_next->d_func_proto_syms = dcs->d_dlsyms; | |
1402 | dcs->d_next->d_func_args = args; | 1402 | dcs->d_next->d_func_args = args; | |
1403 | } | 1403 | } | |
1404 | 1404 | |||
1405 | /* | 1405 | /* | |
1406 | * XXX: What is this code doing on a semantic level, and why? | 1406 | * XXX: What is this code doing on a semantic level, and why? | |
1407 | * Returning decl leads to the wrong function types in msg_347. | 1407 | * Returning decl leads to the wrong function types in msg_347. | |
1408 | */ | 1408 | */ | |
1409 | tpp = &decl->s_type; | 1409 | tpp = &decl->s_type; | |
1410 | while (*tpp != NULL && *tpp != dcs->d_next->d_type) | 1410 | while (*tpp != NULL && *tpp != dcs->d_next->d_type) | |
1411 | /* | 1411 | /* | |
1412 | * XXX: accessing INT->t_subt feels strange, even though it | 1412 | * XXX: accessing INT->t_subt feels strange, even though it | |
1413 | * may even be guaranteed to be NULL. | 1413 | * may even be guaranteed to be NULL. | |
1414 | */ | 1414 | */ | |
1415 | tpp = &(*tpp)->t_subt; | 1415 | tpp = &(*tpp)->t_subt; | |
1416 | if (*tpp == NULL) | 1416 | if (*tpp == NULL) | |
1417 | return decl; /* see msg_347 */ | 1417 | return decl; /* see msg_347 */ | |
1418 | 1418 | |||
1419 | *tpp = tp = block_zero_alloc(sizeof(*tp)); | 1419 | *tpp = tp = block_zero_alloc(sizeof(*tp)); | |
1420 | tp->t_tspec = FUNC; | 1420 | tp->t_tspec = FUNC; | |
1421 | tp->t_subt = dcs->d_next->d_type; | 1421 | tp->t_subt = dcs->d_next->d_type; | |
1422 | if ((tp->t_proto = dcs->d_proto) != false) | 1422 | if ((tp->t_proto = dcs->d_proto) != false) | |
1423 | tp->t_args = args; | 1423 | tp->t_args = args; | |
1424 | tp->t_vararg = dcs->d_vararg; | 1424 | tp->t_vararg = dcs->d_vararg; | |
1425 | 1425 | |||
1426 | return decl; | 1426 | return decl; | |
1427 | } | 1427 | } | |
1428 | 1428 | |||
1429 | /* | 1429 | /* | |
1430 | * Called for new style function declarations. | 1430 | * Called for new style function declarations. | |
1431 | */ | 1431 | */ | |
1432 | /* ARGSUSED */ | 1432 | /* ARGSUSED */ | |
1433 | static sym_t * | 1433 | static sym_t * | |
1434 | new_style_function(sym_t *decl, sym_t *args) | 1434 | new_style_function(sym_t *decl, sym_t *args) | |
1435 | { | 1435 | { | |
1436 | sym_t *arg, *sym; | 1436 | sym_t *arg, *sym; | |
1437 | scl_t sc; | 1437 | scl_t sc; | |
1438 | 1438 | |||
1439 | /* | 1439 | /* | |
1440 | * Declarations of structs/unions/enums in param lists are legal, | 1440 | * Declarations of structs/unions/enums in param lists are legal, | |
1441 | * but senseless. | 1441 | * but senseless. | |
1442 | */ | 1442 | */ | |
1443 | for (sym = dcs->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) { | 1443 | for (sym = dcs->d_dlsyms; sym != NULL; sym = sym->s_level_next) { | |
1444 | sc = sym->s_scl; | 1444 | sc = sym->s_scl; | |
1445 | if (sc == STRUCT_TAG || sc == UNION_TAG || sc == ENUM_TAG) { | 1445 | if (sc == STRUCT_TAG || sc == UNION_TAG || sc == ENUM_TAG) { | |
1446 | /* dubious tag declaration: %s %s */ | 1446 | /* dubious tag declaration: %s %s */ | |
1447 | warning(85, storage_class_name(sc), sym->s_name); | 1447 | warning(85, storage_class_name(sc), sym->s_name); | |
1448 | } | 1448 | } | |
1449 | } | 1449 | } | |
1450 | 1450 | |||
1451 | for (arg = args; arg != NULL; arg = arg->s_next) { | 1451 | for (arg = args; arg != NULL; arg = arg->s_next) { | |
1452 | if (arg->s_type->t_tspec == VOID && | 1452 | if (arg->s_type->t_tspec == VOID && | |
1453 | !(arg == args && arg->s_next == NULL)) { | 1453 | !(arg == args && arg->s_next == NULL)) { | |
1454 | /* void must be sole parameter */ | 1454 | /* void must be sole parameter */ | |
1455 | error(60); | 1455 | error(60); | |
1456 | arg->s_type = gettyp(INT); | 1456 | arg->s_type = gettyp(INT); | |
1457 | } | 1457 | } | |
1458 | } | 1458 | } | |
1459 | 1459 | |||
1460 | if (args == NULL || args->s_type->t_tspec == VOID) | 1460 | if (args == NULL || args->s_type->t_tspec == VOID) | |
1461 | return NULL; | 1461 | return NULL; | |
1462 | return args; | 1462 | return args; | |
1463 | } | 1463 | } | |
1464 | 1464 | |||
1465 | /* | 1465 | /* | |
1466 | * Called for old style function declarations. | 1466 | * Called for old style function declarations. | |
1467 | */ | 1467 | */ | |
1468 | static void | 1468 | static void | |
1469 | old_style_function(sym_t *decl, sym_t *args) | 1469 | old_style_function(sym_t *decl, sym_t *args) | |
1470 | { | 1470 | { | |
1471 | 1471 | |||
1472 | /* | 1472 | /* | |
1473 | * Remember list of params only if this is really seams to be | 1473 | * Remember list of params only if this is really seams to be | |
1474 | * a function definition. | 1474 | * a function definition. | |
1475 | */ | 1475 | */ | |
1476 | if (dcs->d_next->d_ctx == EXTERN && | 1476 | if (dcs->d_next->d_ctx == EXTERN && | |
1477 | decl->s_type == dcs->d_next->d_type) { | 1477 | decl->s_type == dcs->d_next->d_type) { | |
1478 | /* | 1478 | /* | |
1479 | * We assume that this becomes a function definition. If | 1479 | * We assume that this becomes a function definition. If | |
1480 | * we are wrong, it's corrected in check_function_definition(). | 1480 | * we are wrong, it's corrected in check_function_definition(). | |
1481 | */ | 1481 | */ | |
1482 | if (args != NULL) { | 1482 | if (args != NULL) { | |
1483 | decl->s_osdef = true; | 1483 | decl->s_osdef = true; | |
1484 | decl->s_args = args; | 1484 | decl->s_args = args; | |
1485 | } | 1485 | } | |
1486 | } else { | 1486 | } else { | |
1487 | if (args != NULL) | 1487 | if (args != NULL) | |
1488 | /* function prototype parameters must have types */ | 1488 | /* function prototype parameters must have types */ | |
1489 | warning(62); | 1489 | warning(62); | |
1490 | } | 1490 | } | |
1491 | } | 1491 | } | |
1492 | 1492 | |||
1493 | /* | 1493 | /* | |
1494 | * Lists of identifiers in functions declarations are allowed only if | 1494 | * Lists of identifiers in functions declarations are allowed only if | |
1495 | * it's also a function definition. If this is not the case, print an | 1495 | * it's also a function definition. If this is not the case, print an | |
1496 | * error message. | 1496 | * error message. | |
1497 | */ | 1497 | */ | |
1498 | void | 1498 | void | |
1499 | check_function_definition(sym_t *sym, bool msg) | 1499 | check_function_definition(sym_t *sym, bool msg) | |
1500 | { | 1500 | { | |
1501 | 1501 | |||
1502 | if (sym->s_osdef) { | 1502 | if (sym->s_osdef) { | |
1503 | if (msg) { | 1503 | if (msg) { | |
1504 | /* incomplete or misplaced function definition */ | 1504 | /* incomplete or misplaced function definition */ | |
1505 | error(22); | 1505 | error(22); | |
1506 | } | 1506 | } | |
1507 | sym->s_osdef = false; | 1507 | sym->s_osdef = false; | |
1508 | sym->s_args = NULL; | 1508 | sym->s_args = NULL; | |
1509 | } | 1509 | } | |
1510 | } | 1510 | } | |
1511 | 1511 | |||
1512 | /* | 1512 | /* | |
1513 | * Process the name in a declarator. | 1513 | * Process the name in a declarator. | |
1514 | * The symbol gets one of the storage classes EXTERN, STATIC, AUTO or | 1514 | * The symbol gets one of the storage classes EXTERN, STATIC, AUTO or | |
1515 | * TYPEDEF. | 1515 | * TYPEDEF. | |
1516 | * s_def and s_reg are valid after declarator_name(). | 1516 | * s_def and s_reg are valid after declarator_name(). | |
1517 | */ | 1517 | */ | |
1518 | sym_t * | 1518 | sym_t * | |
1519 | declarator_name(sym_t *sym) | 1519 | declarator_name(sym_t *sym) | |
1520 | { | 1520 | { | |
1521 | scl_t sc = NOSCL; | 1521 | scl_t sc = NOSCL; | |
1522 | 1522 | |||
1523 | if (sym->s_scl == NOSCL) { | 1523 | if (sym->s_scl == NOSCL) { | |
1524 | dcs->d_redeclared_symbol = NULL; | 1524 | dcs->d_redeclared_symbol = NULL; | |
1525 | } else if (sym->s_defarg) { | 1525 | } else if (sym->s_defarg) { | |
1526 | sym->s_defarg = false; | 1526 | sym->s_defarg = false; | |
1527 | dcs->d_redeclared_symbol = NULL; | 1527 | dcs->d_redeclared_symbol = NULL; | |
1528 | } else { | 1528 | } else { | |
1529 | dcs->d_redeclared_symbol = sym; | 1529 | dcs->d_redeclared_symbol = sym; | |
1530 | sym = pushdown(sym); | 1530 | sym = pushdown(sym); | |
1531 | } | 1531 | } | |
1532 | 1532 | |||
1533 | switch (dcs->d_ctx) { | 1533 | switch (dcs->d_ctx) { | |
1534 | case MOS: | 1534 | case MOS: | |
1535 | case MOU: | 1535 | case MOU: | |
1536 | /* Set parent */ | 1536 | /* Set parent */ | |
1537 | sym->s_styp = dcs->d_tagtyp->t_str; | 1537 | sym->s_styp = dcs->d_tagtyp->t_str; | |
1538 | sym->s_def = DEF; | 1538 | sym->s_def = DEF; | |
1539 | sym->s_value.v_tspec = INT; | 1539 | sym->s_value.v_tspec = INT; | |
1540 | sc = dcs->d_ctx; | 1540 | sc = dcs->d_ctx; | |
1541 | break; | 1541 | break; | |
1542 | case EXTERN: | 1542 | case EXTERN: | |
1543 | /* | 1543 | /* | |
1544 | * static and external symbols without "extern" are | 1544 | * static and external symbols without "extern" are | |
1545 | * considered to be tentative defined, external | 1545 | * considered to be tentative defined, external | |
1546 | * symbols with "extern" are declared, and typedef names | 1546 | * symbols with "extern" are declared, and typedef names | |
1547 | * are defined. Tentative defined and declared symbols | 1547 | * are defined. Tentative defined and declared symbols | |
1548 | * may become defined if an initializer is present or | 1548 | * may become defined if an initializer is present or | |
1549 | * this is a function definition. | 1549 | * this is a function definition. | |
1550 | */ | 1550 | */ | |
1551 | if ((sc = dcs->d_scl) == NOSCL) { | 1551 | if ((sc = dcs->d_scl) == NOSCL) { | |
1552 | sc = EXTERN; | 1552 | sc = EXTERN; | |
1553 | sym->s_def = TDEF; | 1553 | sym->s_def = TDEF; | |
1554 | } else if (sc == STATIC) { | 1554 | } else if (sc == STATIC) { | |
1555 | sym->s_def = TDEF; | 1555 | sym->s_def = TDEF; | |
1556 | } else if (sc == TYPEDEF) { | 1556 | } else if (sc == TYPEDEF) { | |
1557 | sym->s_def = DEF; | 1557 | sym->s_def = DEF; | |
1558 | } else { | 1558 | } else { | |
1559 | lint_assert(sc == EXTERN); | 1559 | lint_assert(sc == EXTERN); | |
1560 | sym->s_def = DECL; | 1560 | sym->s_def = DECL; | |
1561 | } | 1561 | } | |
1562 | break; | 1562 | break; | |
1563 | case PROTO_ARG: | 1563 | case PROTO_ARG: | |
1564 | sym->s_arg = true; | 1564 | sym->s_arg = true; | |
1565 | /* FALLTHROUGH */ | 1565 | /* FALLTHROUGH */ | |
1566 | case OLD_STYLE_ARG: | 1566 | case OLD_STYLE_ARG: | |
1567 | if ((sc = dcs->d_scl) == NOSCL) { | 1567 | if ((sc = dcs->d_scl) == NOSCL) { | |
1568 | sc = AUTO; | 1568 | sc = AUTO; | |
1569 | } else { | 1569 | } else { | |
1570 | lint_assert(sc == REG); | 1570 | lint_assert(sc == REG); | |
1571 | sym->s_reg = true; | 1571 | sym->s_reg = true; | |
1572 | sc = AUTO; | 1572 | sc = AUTO; | |
1573 | } | 1573 | } | |
1574 | sym->s_def = DEF; | 1574 | sym->s_def = DEF; | |
1575 | break; | 1575 | break; | |
1576 | case AUTO: | 1576 | case AUTO: | |
1577 | if ((sc = dcs->d_scl) == NOSCL) { | 1577 | if ((sc = dcs->d_scl) == NOSCL) { | |
1578 | /* | 1578 | /* | |
1579 | * XXX somewhat ugly because we dont know whether | 1579 | * XXX somewhat ugly because we dont know whether | |
1580 | * this is AUTO or EXTERN (functions). If we are | 1580 | * this is AUTO or EXTERN (functions). If we are | |
1581 | * wrong it must be corrected in declare_local(), | 1581 | * wrong it must be corrected in declare_local(), | |
1582 | * where we have the necessary type information. | 1582 | * where we have the necessary type information. | |
1583 | */ | 1583 | */ | |
1584 | sc = AUTO; | 1584 | sc = AUTO; | |
1585 | sym->s_def = DEF; | 1585 | sym->s_def = DEF; | |
1586 | } else if (sc == AUTO || sc == STATIC || sc == TYPEDEF) { | 1586 | } else if (sc == AUTO || sc == STATIC || sc == TYPEDEF) { | |
1587 | sym->s_def = DEF; | 1587 | sym->s_def = DEF; | |
1588 | } else if (sc == REG) { | 1588 | } else if (sc == REG) { | |
1589 | sym->s_reg = true; | 1589 | sym->s_reg = true; | |
1590 | sc = AUTO; | 1590 | sc = AUTO; | |
1591 | sym->s_def = DEF; | 1591 | sym->s_def = DEF; | |
1592 | } else { | 1592 | } else { | |
1593 | lint_assert(sc == EXTERN); | 1593 | lint_assert(sc == EXTERN); | |
1594 | sym->s_def = DECL; | 1594 | sym->s_def = DECL; | |
1595 | } | 1595 | } | |
1596 | break; | 1596 | break; | |
1597 | default: | 1597 | default: | |
1598 | lint_assert(/*CONSTCOND*/false); | 1598 | lint_assert(/*CONSTCOND*/false); | |
1599 | } | 1599 | } | |
1600 | sym->s_scl = sc; | 1600 | sym->s_scl = sc; | |
1601 | 1601 | |||
1602 | sym->s_type = dcs->d_type; | 1602 | sym->s_type = dcs->d_type; | |
1603 | 1603 | |||
1604 | dcs->d_func_proto_syms = NULL; | 1604 | dcs->d_func_proto_syms = NULL; | |
1605 | 1605 | |||
1606 | return sym; | 1606 | return sym; | |
1607 | } | 1607 | } | |
1608 | 1608 | |||
1609 | /* | 1609 | /* | |
1610 | * Process a name in the list of formal parameters in an old style function | 1610 | * Process a name in the list of formal parameters in an old style function | |
1611 | * definition. | 1611 | * definition. | |
1612 | */ | 1612 | */ | |
1613 | sym_t * | 1613 | sym_t * | |
1614 | old_style_function_name(sym_t *sym) | 1614 | old_style_function_name(sym_t *sym) | |
1615 | { | 1615 | { | |
1616 | 1616 | |||
1617 | if (sym->s_scl != NOSCL) { | 1617 | if (sym->s_scl != NOSCL) { | |
1618 | if (block_level == sym->s_block_level) { | 1618 | if (block_level == sym->s_block_level) { | |
1619 | /* redeclaration of formal parameter %s */ | 1619 | /* redeclaration of formal parameter %s */ | |
1620 | error(21, sym->s_name); | 1620 | error(21, sym->s_name); | |
1621 | lint_assert(sym->s_defarg); | 1621 | lint_assert(sym->s_defarg); | |
1622 | } | 1622 | } | |
1623 | sym = pushdown(sym); | 1623 | sym = pushdown(sym); | |
1624 | } | 1624 | } | |
1625 | sym->s_type = gettyp(INT); | 1625 | sym->s_type = gettyp(INT); | |
1626 | sym->s_scl = AUTO; | 1626 | sym->s_scl = AUTO; | |
1627 | sym->s_def = DEF; | 1627 | sym->s_def = DEF; | |
1628 | sym->s_defarg = sym->s_arg = true; | 1628 | sym->s_defarg = sym->s_arg = true; | |
1629 | return sym; | 1629 | return sym; | |
1630 | } | 1630 | } | |
1631 | 1631 | |||
1632 | /* | 1632 | /* | |
1633 | * Create the type of a tag. | 1633 | * Create the type of a tag. | |
1634 | * | 1634 | * | |
1635 | * tag points to the symbol table entry of the tag | 1635 | * tag points to the symbol table entry of the tag | |
1636 | * kind is the kind of the tag (STRUCT/UNION/ENUM) | 1636 | * kind is the kind of the tag (STRUCT/UNION/ENUM) | |
1637 | * decl is true if the type of the tag will be completed in this declaration | 1637 | * decl is true if the type of the tag will be completed in this declaration | |
1638 | * (the following token is T_LBRACE) | 1638 | * (the following token is T_LBRACE) | |
1639 | * semi is true if the following token is T_SEMI | 1639 | * semi is true if the following token is T_SEMI | |
1640 | */ | 1640 | */ | |
1641 | type_t * | 1641 | type_t * | |
1642 | mktag(sym_t *tag, tspec_t kind, bool decl, bool semi) | 1642 | mktag(sym_t *tag, tspec_t kind, bool decl, bool semi) | |
1643 | { | 1643 | { | |
1644 | scl_t scl; | 1644 | scl_t scl; | |
1645 | type_t *tp; | 1645 | type_t *tp; | |
1646 | 1646 | |||
1647 | if (kind == STRUCT) { | 1647 | if (kind == STRUCT) { | |
1648 | scl = STRUCT_TAG; | 1648 | scl = STRUCT_TAG; | |
1649 | } else if (kind == UNION) { | 1649 | } else if (kind == UNION) { | |
1650 | scl = UNION_TAG; | 1650 | scl = UNION_TAG; | |
1651 | } else { | 1651 | } else { | |
1652 | lint_assert(kind == ENUM); | 1652 | lint_assert(kind == ENUM); | |
1653 | scl = ENUM_TAG; | 1653 | scl = ENUM_TAG; | |
1654 | } | 1654 | } | |
1655 | 1655 | |||
1656 | if (tag != NULL) { | 1656 | if (tag != NULL) { | |
1657 | if (tag->s_scl != NOSCL) { | 1657 | if (tag->s_scl != NOSCL) { | |
1658 | tag = newtag(tag, scl, decl, semi); | 1658 | tag = newtag(tag, scl, decl, semi); | |
1659 | } else { | 1659 | } else { | |
1660 | /* a new tag, no empty declaration */ | 1660 | /* a new tag, no empty declaration */ | |
1661 | dcs->d_next->d_nonempty_decl = true; | 1661 | dcs->d_next->d_nonempty_decl = true; | |
1662 | if (scl == ENUM_TAG && !decl) { | 1662 | if (scl == ENUM_TAG && !decl) { | |
1663 | if (!tflag && (sflag || pflag)) | 1663 | if (!tflag && (sflag || pflag)) | |
1664 | /* forward reference to enum type */ | 1664 | /* forward reference to enum type */ | |
1665 | warning(42); | 1665 | warning(42); | |
1666 | } | 1666 | } | |
1667 | } | 1667 | } | |
1668 | if (tag->s_scl == NOSCL) { | 1668 | if (tag->s_scl == NOSCL) { | |
1669 | tag->s_scl = scl; | 1669 | tag->s_scl = scl; | |
1670 | tag->s_type = tp = block_zero_alloc(sizeof(*tp)); | 1670 | tag->s_type = tp = block_zero_alloc(sizeof(*tp)); | |
1671 | tp->t_packed = dcs->d_packed; | 1671 | tp->t_packed = dcs->d_packed; | |
1672 | } else { | 1672 | } else { | |
1673 | tp = tag->s_type; | 1673 | tp = tag->s_type; | |
1674 | } | 1674 | } | |
1675 | } else { | 1675 | } else { | |
1676 | tag = block_zero_alloc(sizeof(*tag)); | 1676 | tag = block_zero_alloc(sizeof(*tag)); | |
1677 | tag->s_name = unnamed; | 1677 | tag->s_name = unnamed; | |
1678 | UNIQUE_CURR_POS(tag->s_def_pos); | 1678 | UNIQUE_CURR_POS(tag->s_def_pos); | |
1679 | tag->s_kind = FTAG; | 1679 | tag->s_kind = FTAG; | |
1680 | tag->s_scl = scl; | 1680 | tag->s_scl = scl; | |
1681 | tag->s_block_level = -1; | 1681 | tag->s_block_level = -1; | |
1682 | tag->s_type = tp = block_zero_alloc(sizeof(*tp)); | 1682 | tag->s_type = tp = block_zero_alloc(sizeof(*tp)); | |
1683 | tp->t_packed = dcs->d_packed; | 1683 | tp->t_packed = dcs->d_packed; | |
1684 | dcs->d_next->d_nonempty_decl = true; | 1684 | dcs->d_next->d_nonempty_decl = true; | |
1685 | } | 1685 | } | |
1686 | 1686 | |||
1687 | if (tp->t_tspec == NOTSPEC) { | 1687 | if (tp->t_tspec == NOTSPEC) { | |
1688 | tp->t_tspec = kind; | 1688 | tp->t_tspec = kind; | |
1689 | if (kind != ENUM) { | 1689 | if (kind != ENUM) { | |
1690 | tp->t_str = block_zero_alloc(sizeof(*tp->t_str)); | 1690 | tp->t_str = block_zero_alloc(sizeof(*tp->t_str)); | |
1691 | tp->t_str->sou_align_in_bits = CHAR_SIZE; | 1691 | tp->t_str->sou_align_in_bits = CHAR_SIZE; | |
1692 | tp->t_str->sou_tag = tag; | 1692 | tp->t_str->sou_tag = tag; | |
1693 | } else { | 1693 | } else { | |
1694 | tp->t_is_enum = true; | 1694 | tp->t_is_enum = true; | |
1695 | tp->t_enum = block_zero_alloc(sizeof(*tp->t_enum)); | 1695 | tp->t_enum = block_zero_alloc(sizeof(*tp->t_enum)); | |
1696 | tp->t_enum->en_tag = tag; | 1696 | tp->t_enum->en_tag = tag; | |
1697 | } | 1697 | } | |
1698 | setcomplete(tp, false); | 1698 | setcomplete(tp, false); | |
1699 | } | 1699 | } | |
1700 | return tp; | 1700 | return tp; | |
1701 | } | 1701 | } | |
1702 | 1702 | |||
1703 | /* | 1703 | /* | |
1704 | * Checks all possible cases of tag redeclarations. | 1704 | * Checks all possible cases of tag redeclarations. | |
1705 | * decl is true if T_LBRACE follows | 1705 | * decl is true if T_LBRACE follows | |
1706 | * semi is true if T_SEMI follows | 1706 | * semi is true if T_SEMI follows | |
1707 | */ | 1707 | */ | |
1708 | static sym_t * | 1708 | static sym_t * | |
1709 | newtag(sym_t *tag, scl_t scl, bool decl, bool semi) | 1709 | newtag(sym_t *tag, scl_t scl, bool decl, bool semi) | |
1710 | { | 1710 | { | |
1711 | 1711 | |||
1712 | if (tag->s_block_level < block_level) { | 1712 | if (tag->s_block_level < block_level) { | |
1713 | if (semi) { | 1713 | if (semi) { | |
1714 | /* "struct a;" */ | 1714 | /* "struct a;" */ | |
1715 | if (!tflag) { | 1715 | if (!tflag) { | |
1716 | if (!sflag) | 1716 | if (!sflag) | |
1717 | /* declaration introduces new ... */ | 1717 | /* declaration introduces new ... */ | |
1718 | warning(44, storage_class_name(scl), | 1718 | warning(44, storage_class_name(scl), | |
1719 | tag->s_name); | 1719 | tag->s_name); | |
1720 | tag = pushdown(tag); | 1720 | tag = pushdown(tag); | |
1721 | } else if (tag->s_scl != scl) { | 1721 | } else if (tag->s_scl != scl) { | |
1722 | /* base type is really '%s %s' */ | 1722 | /* base type is really '%s %s' */ | |
1723 | warning(45, storage_class_name(tag->s_scl), | 1723 | warning(45, storage_class_name(tag->s_scl), | |
1724 | tag->s_name); | 1724 | tag->s_name); | |
1725 | } | 1725 | } | |
1726 | dcs->d_next->d_nonempty_decl = true; | 1726 | dcs->d_next->d_nonempty_decl = true; | |
1727 | } else if (decl) { | 1727 | } else if (decl) { | |
1728 | /* "struct a { ... } " */ | 1728 | /* "struct a { ... } " */ | |
1729 | if (hflag) | 1729 | if (hflag) | |
1730 | /* redefinition hides earlier one: %s */ | 1730 | /* redefinition hides earlier one: %s */ | |
1731 | warning(43, tag->s_name); | 1731 | warning(43, tag->s_name); | |
1732 | tag = pushdown(tag); | 1732 | tag = pushdown(tag); | |
1733 | dcs->d_next->d_nonempty_decl = true; | 1733 | dcs->d_next->d_nonempty_decl = true; | |
1734 | } else if (tag->s_scl != scl) { | 1734 | } else if (tag->s_scl != scl) { | |
1735 | /* base type is really '%s %s' */ | 1735 | /* base type is really '%s %s' */ | |
1736 | warning(45, storage_class_name(tag->s_scl), | 1736 | warning(45, storage_class_name(tag->s_scl), | |
1737 | tag->s_name); | 1737 | tag->s_name); | |
1738 | if (!sflag) { | 1738 | if (!sflag) { | |
1739 | /* declaration introduces new type in ... */ | 1739 | /* declaration introduces new type in ... */ | |
1740 | warning(44, storage_class_name(scl), | 1740 | warning(44, storage_class_name(scl), | |
1741 | tag->s_name); | 1741 | tag->s_name); | |
1742 | } | 1742 | } | |
1743 | tag = pushdown(tag); | 1743 | tag = pushdown(tag); | |
1744 | dcs->d_next->d_nonempty_decl = true; | 1744 | dcs->d_next->d_nonempty_decl = true; | |
1745 | } | 1745 | } | |
1746 | } else { | 1746 | } else { | |
1747 | if (tag->s_scl != scl || | 1747 | if (tag->s_scl != scl || | |
1748 | (decl && !is_incomplete(tag->s_type))) { | 1748 | (decl && !is_incomplete(tag->s_type))) { | |
1749 | /* %s tag '%s' redeclared as %s */ | 1749 | /* %s tag '%s' redeclared as %s */ | |
1750 | error(46, storage_class_name(tag->s_scl), | 1750 | error(46, storage_class_name(tag->s_scl), | |
1751 | tag->s_name, storage_class_name(scl)); | 1751 | tag->s_name, storage_class_name(scl)); | |
1752 | print_previous_declaration(-1, tag); | 1752 | print_previous_declaration(-1, tag); | |
1753 | tag = pushdown(tag); | 1753 | tag = pushdown(tag); | |
1754 | dcs->d_next->d_nonempty_decl = true; | 1754 | dcs->d_next->d_nonempty_decl = true; | |
1755 | } else if (semi || decl) { | 1755 | } else if (semi || decl) { | |
1756 | dcs->d_next->d_nonempty_decl = true; | 1756 | dcs->d_next->d_nonempty_decl = true; | |
1757 | } | 1757 | } | |
1758 | } | 1758 | } | |
1759 | return tag; | 1759 | return tag; | |
1760 | } | 1760 | } | |
1761 | 1761 | |||
1762 | const char * | 1762 | const char * | |
1763 | storage_class_name(scl_t sc) | 1763 | storage_class_name(scl_t sc) | |
1764 | { | 1764 | { | |
1765 | switch (sc) { | 1765 | switch (sc) { | |
1766 | case EXTERN: return "extern"; | 1766 | case EXTERN: return "extern"; | |
1767 | case STATIC: return "static"; | 1767 | case STATIC: return "static"; | |
1768 | case AUTO: return "auto"; | 1768 | case AUTO: return "auto"; | |
1769 | case REG: return "register"; | 1769 | case REG: return "register"; | |
1770 | case TYPEDEF: return "typedef"; | 1770 | case TYPEDEF: return "typedef"; | |
1771 | case STRUCT_TAG:return "struct"; | 1771 | case STRUCT_TAG:return "struct"; | |
1772 | case UNION_TAG: return "union"; | 1772 | case UNION_TAG: return "union"; | |
1773 | case ENUM_TAG: return "enum"; | 1773 | case ENUM_TAG: return "enum"; | |
1774 | default: lint_assert(/*CONSTCOND*/false); | 1774 | default: lint_assert(/*CONSTCOND*/false); | |
1775 | } | 1775 | } | |
1776 | /* NOTREACHED */ | 1776 | /* NOTREACHED */ | |
1777 | } | 1777 | } | |
1778 | 1778 | |||
1779 | /* | 1779 | /* | |
1780 | * tp points to the type of the tag, fmem to the list of members. | 1780 | * tp points to the type of the tag, fmem to the list of members. | |
1781 | */ | 1781 | */ | |
1782 | type_t * | 1782 | type_t * | |
1783 | complete_tag_struct_or_union(type_t *tp, sym_t *fmem) | 1783 | complete_tag_struct_or_union(type_t *tp, sym_t *fmem) | |
1784 | { | 1784 | { | |
1785 | tspec_t t; | 1785 | tspec_t t; | |
1786 | struct_or_union *sp; | 1786 | struct_or_union *sp; | |
1787 | int n; | 1787 | int n; | |
1788 | sym_t *mem; | 1788 | sym_t *mem; | |
1789 | 1789 | |||
1790 | if (tp == NULL) /* in case of syntax errors */ | 1790 | if (tp == NULL) /* in case of syntax errors */ | |
1791 | return gettyp(INT); | 1791 | return gettyp(INT); | |
1792 | 1792 | |||
1793 | setcomplete(tp, true); | 1793 | setcomplete(tp, true); | |
1794 | 1794 | |||
1795 | t = tp->t_tspec; | 1795 | t = tp->t_tspec; | |
1796 | align((u_int)dcs->d_sou_align_in_bits, 0); | 1796 | align((u_int)dcs->d_sou_align_in_bits, 0); | |
1797 | sp = tp->t_str; | 1797 | sp = tp->t_str; | |
1798 | sp->sou_align_in_bits = dcs->d_sou_align_in_bits; | 1798 | sp->sou_align_in_bits = dcs->d_sou_align_in_bits; | |
1799 | sp->sou_first_member = fmem; | 1799 | sp->sou_first_member = fmem; | |
1800 | if (tp->t_packed) | 1800 | if (tp->t_packed) | |
1801 | setpackedsize(tp); | 1801 | setpackedsize(tp); | |
1802 | else | 1802 | else | |
1803 | sp->sou_size_in_bits = dcs->d_offset; | 1803 | sp->sou_size_in_bits = dcs->d_offset; | |
1804 | 1804 | |||
1805 | if (sp->sou_size_in_bits == 0) { | 1805 | if (sp->sou_size_in_bits == 0) { | |
1806 | /* zero sized %s is a C9X feature */ | 1806 | /* zero sized %s is a C9X feature */ | |
1807 | c99ism(47, ttab[t].tt_name); | 1807 | c99ism(47, ttab[t].tt_name); | |
1808 | } | 1808 | } | |
1809 | 1809 | |||
1810 | n = 0; | 1810 | n = 0; | |
1811 | for (mem = fmem; mem != NULL; mem = mem->s_next) { | 1811 | for (mem = fmem; mem != NULL; mem = mem->s_next) { | |
1812 | /* bind anonymous members to the structure */ | 1812 | /* bind anonymous members to the structure */ | |
1813 | if (mem->s_styp == NULL) { | 1813 | if (mem->s_styp == NULL) { | |
1814 | mem->s_styp = sp; | 1814 | mem->s_styp = sp; | |
1815 | if (mem->s_type->t_bitfield) { | 1815 | if (mem->s_type->t_bitfield) { | |
1816 | sp->sou_size_in_bits += bitfieldsize(&mem); | 1816 | sp->sou_size_in_bits += bitfieldsize(&mem); | |
1817 | if (mem == NULL) | 1817 | if (mem == NULL) | |
1818 | break; | 1818 | break; | |
1819 | } | 1819 | } | |
1820 | sp->sou_size_in_bits += | 1820 | sp->sou_size_in_bits += | |
1821 | type_size_in_bits(mem->s_type); | 1821 | type_size_in_bits(mem->s_type); | |
1822 | } | 1822 | } | |
1823 | if (mem->s_name != unnamed) | 1823 | if (mem->s_name != unnamed) | |
1824 | n++; | 1824 | n++; | |
1825 | } | 1825 | } | |
1826 | 1826 | |||
1827 | if (n == 0 && sp->sou_size_in_bits != 0) { | 1827 | if (n == 0 && sp->sou_size_in_bits != 0) { | |
1828 | /* %s has no named members */ | 1828 | /* %s has no named members */ | |
1829 | warning(65, t == STRUCT ? "structure" : "union"); | 1829 | warning(65, t == STRUCT ? "structure" : "union"); | |
1830 | } | 1830 | } | |
1831 | return tp; | 1831 | return tp; | |
1832 | } | 1832 | } | |
1833 | 1833 | |||
1834 | type_t * | 1834 | type_t * | |
1835 | complete_tag_enum(type_t *tp, sym_t *fmem) | 1835 | complete_tag_enum(type_t *tp, sym_t *fmem) | |
1836 | { | 1836 | { | |
1837 | 1837 | |||
1838 | setcomplete(tp, true); | 1838 | setcomplete(tp, true); | |
1839 | tp->t_enum->en_first_enumerator = fmem; | 1839 | tp->t_enum->en_first_enumerator = fmem; | |
1840 | return tp; | 1840 | return tp; | |
1841 | } | 1841 | } | |
1842 | 1842 | |||
1843 | /* | 1843 | /* | |
1844 | * Processes the name of an enumerator in an enum declaration. | 1844 | * Processes the name of an enumerator in an enum declaration. | |
1845 | * | 1845 | * | |
1846 | * sym points to the enumerator | 1846 | * sym points to the enumerator | |
1847 | * val is the value of the enumerator | 1847 | * val is the value of the enumerator | |
1848 | * impl is true if the value of the enumerator was not explicitly specified. | 1848 | * impl is true if the value of the enumerator was not explicitly specified. | |
1849 | */ | 1849 | */ | |
1850 | sym_t * | 1850 | sym_t * | |
1851 | enumeration_constant(sym_t *sym, int val, bool impl) | 1851 | enumeration_constant(sym_t *sym, int val, bool impl) | |
1852 | { | 1852 | { | |
1853 | 1853 | |||
1854 | if (sym->s_scl != NOSCL) { | 1854 | if (sym->s_scl != NOSCL) { | |
1855 | if (sym->s_block_level == block_level) { | 1855 | if (sym->s_block_level == block_level) { | |
1856 | /* no hflag, because this is illegal!!! */ | 1856 | /* no hflag, because this is illegal!!! */ | |
1857 | if (sym->s_arg) { | 1857 | if (sym->s_arg) { | |
1858 | /* enumeration constant hides parameter: %s */ | 1858 | /* enumeration constant hides parameter: %s */ | |
1859 | warning(57, sym->s_name); | 1859 | warning(57, sym->s_name); | |
1860 | } else { | 1860 | } else { | |
1861 | /* redeclaration of %s */ | 1861 | /* redeclaration of %s */ | |
1862 | error(27, sym->s_name); | 1862 | error(27, sym->s_name); | |
1863 | /* | 1863 | /* | |
1864 | * inside blocks it should not be too | 1864 | * inside blocks it should not be too | |
1865 | * complicated to find the position of the | 1865 | * complicated to find the position of the | |
1866 | * previous declaration | 1866 | * previous declaration | |
1867 | */ | 1867 | */ | |
1868 | if (block_level == 0) | 1868 | if (block_level == 0) | |
1869 | print_previous_declaration(-1, sym); | 1869 | print_previous_declaration(-1, sym); | |
1870 | } | 1870 | } | |
1871 | } else { | 1871 | } else { | |
1872 | if (hflag) | 1872 | if (hflag) | |
1873 | /* redefinition hides earlier one: %s */ | 1873 | /* redefinition hides earlier one: %s */ | |
1874 | warning(43, sym->s_name); | 1874 | warning(43, sym->s_name); | |
1875 | } | 1875 | } | |
1876 | sym = pushdown(sym); | 1876 | sym = pushdown(sym); | |
1877 | } | 1877 | } | |
1878 | sym->s_scl = CTCONST; | 1878 | sym->s_scl = CTCONST; | |
1879 | sym->s_type = dcs->d_tagtyp; | 1879 | sym->s_type = dcs->d_tagtyp; | |
1880 | sym->s_value.v_tspec = INT; | 1880 | sym->s_value.v_tspec = INT; | |
1881 | sym->s_value.v_quad = val; | 1881 | sym->s_value.v_quad = val; | |
1882 | if (impl && val - 1 == TARG_INT_MAX) { | 1882 | if (impl && val - 1 == TARG_INT_MAX) { | |
1883 | /* overflow in enumeration values: %s */ | 1883 | /* overflow in enumeration values: %s */ | |
1884 | warning(48, sym->s_name); | 1884 | warning(48, sym->s_name); | |
1885 | } | 1885 | } | |
1886 | enumval = val + 1; | 1886 | enumval = val + 1; | |
1887 | return sym; | 1887 | return sym; | |
1888 | } | 1888 | } | |
1889 | 1889 | |||
1890 | /* | 1890 | /* | |
1891 | * Process a single external declarator. | 1891 | * Process a single external declarator. | |
1892 | */ | 1892 | */ | |
1893 | static void | 1893 | static void | |
1894 | declare_extern(sym_t *dsym, bool initflg, sbuf_t *renaming) | 1894 | declare_extern(sym_t *dsym, bool initflg, sbuf_t *renaming) | |
1895 | { | 1895 | { | |
1896 | bool dowarn, rval, redec; | 1896 | bool dowarn, rval, redec; | |
1897 | sym_t *rdsym; | 1897 | sym_t *rdsym; | |
1898 | char *s; | 1898 | char *s; | |
1899 | 1899 | |||
1900 | if (renaming != NULL) { | 1900 | if (renaming != NULL) { | |
1901 | lint_assert(dsym->s_rename == NULL); | 1901 | lint_assert(dsym->s_rename == NULL); | |
1902 | 1902 | |||
1903 | s = level_zero_alloc(1, renaming->sb_len + 1); | 1903 | s = level_zero_alloc(1, renaming->sb_len + 1); | |
1904 | (void)memcpy(s, renaming->sb_name, renaming->sb_len + 1); | 1904 | (void)memcpy(s, renaming->sb_name, renaming->sb_len + 1); | |
1905 | dsym->s_rename = s; | 1905 | dsym->s_rename = s; | |
1906 | } | 1906 | } | |
1907 | 1907 | |||
1908 | check_function_definition(dsym, true); | 1908 | check_function_definition(dsym, true); | |
1909 | 1909 | |||
1910 | check_type(dsym); | 1910 | check_type(dsym); | |
1911 | 1911 | |||
1912 | if (initflg && !check_init(dsym)) | 1912 | if (initflg && !check_init(dsym)) | |
1913 | dsym->s_def = DEF; | 1913 | dsym->s_def = DEF; | |
1914 | 1914 | |||
1915 | /* | 1915 | /* | |
1916 | * Declarations of functions are marked as "tentative" in | 1916 | * Declarations of functions are marked as "tentative" in | |
1917 | * declarator_name(). This is wrong because there are no | 1917 | * declarator_name(). This is wrong because there are no | |
1918 | * tentative function definitions. | 1918 | * tentative function definitions. | |
1919 | */ | 1919 | */ | |
1920 | if (dsym->s_type->t_tspec == FUNC && dsym->s_def == TDEF) | 1920 | if (dsym->s_type->t_tspec == FUNC && dsym->s_def == TDEF) | |
1921 | dsym->s_def = DECL; | 1921 | dsym->s_def = DECL; | |
1922 | 1922 | |||
1923 | if (dcs->d_inline) { | 1923 | if (dcs->d_inline) { | |
1924 | if (dsym->s_type->t_tspec == FUNC) { | 1924 | if (dsym->s_type->t_tspec == FUNC) { | |
1925 | dsym->s_inline = true; | 1925 | dsym->s_inline = true; | |
1926 | } else { | 1926 | } else { | |
1927 | /* variable declared inline: %s */ | 1927 | /* variable declared inline: %s */ | |
1928 | warning(268, dsym->s_name); | 1928 | warning(268, dsym->s_name); | |
1929 | } | 1929 | } | |
1930 | } | 1930 | } | |
1931 | 1931 | |||
1932 | /* Write the declaration into the output file */ | 1932 | /* Write the declaration into the output file */ | |
1933 | if (plibflg && llibflg && | 1933 | if (plibflg && llibflg && | |
1934 | dsym->s_type->t_tspec == FUNC && dsym->s_type->t_proto) { | 1934 | dsym->s_type->t_tspec == FUNC && dsym->s_type->t_proto) { | |
1935 | /* | 1935 | /* | |
1936 | * With both LINTLIBRARY and PROTOLIB the prototype is | 1936 | * With both LINTLIBRARY and PROTOLIB the prototype is | |
1937 | * written as a function definition to the output file. | 1937 | * written as a function definition to the output file. | |
1938 | */ | 1938 | */ | |
1939 | rval = dsym->s_type->t_subt->t_tspec != VOID; | 1939 | rval = dsym->s_type->t_subt->t_tspec != VOID; | |
1940 | outfdef(dsym, &dsym->s_def_pos, rval, false, NULL); | 1940 | outfdef(dsym, &dsym->s_def_pos, rval, false, NULL); | |
1941 | } else if (!is_compiler_builtin(dsym->s_name)) { | 1941 | } else if (!is_compiler_builtin(dsym->s_name)) { | |
1942 | outsym(dsym, dsym->s_scl, dsym->s_def); | 1942 | outsym(dsym, dsym->s_scl, dsym->s_def); | |
1943 | } | 1943 | } | |
1944 | 1944 | |||
1945 | if ((rdsym = dcs->d_redeclared_symbol) != NULL) { | 1945 | if ((rdsym = dcs->d_redeclared_symbol) != NULL) { | |
1946 | 1946 | |||
1947 | /* | 1947 | /* | |
1948 | * If the old symbol stems from an old style function | 1948 | * If the old symbol stems from an old style function | |
1949 | * definition, we have remembered the params in rdsmy->s_args | 1949 | * definition, we have remembered the params in rdsmy->s_args | |
1950 | * and compare them with the params of the prototype. | 1950 | * and compare them with the params of the prototype. | |
1951 | */ | 1951 | */ | |
1952 | if (rdsym->s_osdef && dsym->s_type->t_proto) { | 1952 | if (rdsym->s_osdef && dsym->s_type->t_proto) { | |
1953 | redec = check_old_style_definition(rdsym, dsym); | 1953 | redec = check_old_style_definition(rdsym, dsym); | |
1954 | } else { | 1954 | } else { | |
1955 | redec = false; | 1955 | redec = false; | |
1956 | } | 1956 | } | |
1957 | 1957 | |||
1958 | if (!redec && | 1958 | if (!redec && | |
1959 | !check_redeclaration(dsym, (dowarn = false, &dowarn))) { | 1959 | !check_redeclaration(dsym, (dowarn = false, &dowarn))) { | |
1960 | 1960 | |||
1961 | if (dowarn) { | 1961 | if (dowarn) { | |
1962 | if (sflag) | 1962 | if (sflag) | |
1963 | /* redeclaration of %s */ | 1963 | /* redeclaration of %s */ | |
1964 | error(27, dsym->s_name); | 1964 | error(27, dsym->s_name); | |
1965 | else | 1965 | else | |
1966 | /* redeclaration of %s */ | 1966 | /* redeclaration of %s */ | |
1967 | warning(27, dsym->s_name); | 1967 | warning(27, dsym->s_name); | |
1968 | print_previous_declaration(-1, rdsym); | 1968 | print_previous_declaration(-1, rdsym); | |
1969 | } | 1969 | } | |
1970 | 1970 | |||
1971 | /* | 1971 | /* | |
1972 | * Take over the remembered params if the new symbol | 1972 | * Take over the remembered params if the new symbol | |
1973 | * is not a prototype. | 1973 | * is not a prototype. | |
1974 | */ | 1974 | */ | |
1975 | if (rdsym->s_osdef && !dsym->s_type->t_proto) { | 1975 | if (rdsym->s_osdef && !dsym->s_type->t_proto) { | |
1976 | dsym->s_osdef = rdsym->s_osdef; | 1976 | dsym->s_osdef = rdsym->s_osdef; | |
1977 | dsym->s_args = rdsym->s_args; | 1977 | dsym->s_args = rdsym->s_args; | |
1978 | dsym->s_def_pos = rdsym->s_def_pos; | 1978 | dsym->s_def_pos = rdsym->s_def_pos; | |
1979 | } | 1979 | } | |
1980 | 1980 | |||
1981 | /* | 1981 | /* | |
1982 | * Remember the position of the declaration if the | 1982 | * Remember the position of the declaration if the | |
1983 | * old symbol was a prototype and the new is not. | 1983 | * old symbol was a prototype and the new is not. | |
1984 | * Also remember the position if the old symbol | 1984 | * Also remember the position if the old symbol | |
1985 | * was defined and the new is not. | 1985 | * was defined and the new is not. | |
1986 | */ | 1986 | */ | |
1987 | if (rdsym->s_type->t_proto && !dsym->s_type->t_proto) { | 1987 | if (rdsym->s_type->t_proto && !dsym->s_type->t_proto) { | |
1988 | dsym->s_def_pos = rdsym->s_def_pos; | 1988 | dsym->s_def_pos = rdsym->s_def_pos; | |
1989 | } else if (rdsym->s_def == DEF && dsym->s_def != DEF) { | 1989 | } else if (rdsym->s_def == DEF && dsym->s_def != DEF) { | |
1990 | dsym->s_def_pos = rdsym->s_def_pos; | 1990 | dsym->s_def_pos = rdsym->s_def_pos; | |
1991 | } | 1991 | } | |
1992 | 1992 | |||
1993 | /* | 1993 | /* | |
1994 | * Copy usage information of the name into the new | 1994 | * Copy usage information of the name into the new | |
1995 | * symbol. | 1995 | * symbol. | |
1996 | */ | 1996 | */ | |
1997 | copy_usage_info(dsym, rdsym); | 1997 | copy_usage_info(dsym, rdsym); | |
1998 | 1998 | |||
1999 | /* Once a name is defined, it remains defined. */ | 1999 | /* Once a name is defined, it remains defined. */ | |
2000 | if (rdsym->s_def == DEF) | 2000 | if (rdsym->s_def == DEF) | |
2001 | dsym->s_def = DEF; | 2001 | dsym->s_def = DEF; | |
2002 | 2002 | |||
2003 | /* once a function is inline, it remains inline */ | 2003 | /* once a function is inline, it remains inline */ | |
2004 | if (rdsym->s_inline) | 2004 | if (rdsym->s_inline) | |
2005 | dsym->s_inline = true; | 2005 | dsym->s_inline = true; | |
2006 | 2006 | |||
2007 | complete_type(dsym, rdsym); | 2007 | complete_type(dsym, rdsym); | |
2008 | 2008 | |||
2009 | } | 2009 | } | |
2010 | 2010 | |||
2011 | rmsym(rdsym); | 2011 | rmsym(rdsym); | |
2012 | } | 2012 | } | |
2013 | 2013 | |||
2014 | if (dsym->s_scl == TYPEDEF) { | 2014 | if (dsym->s_scl == TYPEDEF) { | |
2015 | dsym->s_type = block_dup_type(dsym->s_type); | 2015 | dsym->s_type = block_dup_type(dsym->s_type); | |
2016 | dsym->s_type->t_typedef = true; | 2016 | dsym->s_type->t_typedef = true; | |
2017 | settdsym(dsym->s_type, dsym); | 2017 | settdsym(dsym->s_type, dsym); | |
2018 | } | 2018 | } | |
2019 | 2019 | |||
2020 | } | 2020 | } | |
2021 | 2021 | |||
2022 | void | 2022 | void | |
2023 | declare(sym_t *decl, bool initflg, sbuf_t *renaming) | 2023 | declare(sym_t *decl, bool initflg, sbuf_t *renaming) | |
2024 | { | 2024 | { | |
2025 | 2025 | |||
2026 | if (dcs->d_ctx == EXTERN) { | 2026 | if (dcs->d_ctx == EXTERN) { | |
2027 | declare_extern(decl, initflg, renaming); | 2027 | declare_extern(decl, initflg, renaming); | |
2028 | } else if (dcs->d_ctx == OLD_STYLE_ARG || dcs->d_ctx == PROTO_ARG) { | 2028 | } else if (dcs->d_ctx == OLD_STYLE_ARG || dcs->d_ctx == PROTO_ARG) { | |
2029 | if (renaming != NULL) { | 2029 | if (renaming != NULL) { | |
2030 | /* symbol renaming can't be used on function arguments */ | 2030 | /* symbol renaming can't be used on function arguments */ | |
2031 | error(310); | 2031 | error(310); | |
2032 | } else | 2032 | } else | |
2033 | (void)declare_argument(decl, initflg); | 2033 | (void)declare_argument(decl, initflg); | |
2034 | } else { | 2034 | } else { | |
2035 | lint_assert(dcs->d_ctx == AUTO); | 2035 | lint_assert(dcs->d_ctx == AUTO); | |
2036 | if (renaming != NULL) { | 2036 | if (renaming != NULL) { | |
2037 | /* symbol renaming can't be used on automatic variables */ | 2037 | /* symbol renaming can't be used on automatic variables */ | |
2038 | error(311); | 2038 | error(311); | |
2039 | } else | 2039 | } else | |
2040 | declare_local(decl, initflg); | 2040 | declare_local(decl, initflg); | |
2041 | } | 2041 | } | |
2042 | } | 2042 | } | |
2043 | 2043 | |||
2044 | /* | 2044 | /* | |
2045 | * Copies information about usage into a new symbol table entry of | 2045 | * Copies information about usage into a new symbol table entry of | |
2046 | * the same symbol. | 2046 | * the same symbol. | |
2047 | */ | 2047 | */ | |
2048 | void | 2048 | void | |
2049 | copy_usage_info(sym_t *sym, sym_t *rdsym) | 2049 | copy_usage_info(sym_t *sym, sym_t *rdsym) | |
2050 | { | 2050 | { | |
2051 | 2051 | |||
2052 | sym->s_set_pos = rdsym->s_set_pos; | 2052 | sym->s_set_pos = rdsym->s_set_pos; | |
2053 | sym->s_use_pos = rdsym->s_use_pos; | 2053 | sym->s_use_pos = rdsym->s_use_pos; | |
2054 | sym->s_set = rdsym->s_set; | 2054 | sym->s_set = rdsym->s_set; | |
2055 | sym->s_used = rdsym->s_used; | 2055 | sym->s_used = rdsym->s_used; | |
2056 | } | 2056 | } | |
2057 | 2057 | |||
2058 | /* | 2058 | /* | |
2059 | * Prints an error and returns true if a symbol is redeclared/redefined. | 2059 | * Prints an error and returns true if a symbol is redeclared/redefined. | |
2060 | * Otherwise returns false and, in some cases of minor problems, prints | 2060 | * Otherwise returns false and, in some cases of minor problems, prints | |
2061 | * a warning. | 2061 | * a warning. | |
2062 | */ | 2062 | */ | |
2063 | bool | 2063 | bool | |
2064 | check_redeclaration(sym_t *dsym, bool *dowarn) | 2064 | check_redeclaration(sym_t *dsym, bool *dowarn) | |
2065 | { | 2065 | { | |
2066 | sym_t *rsym; | 2066 | sym_t *rsym; | |
2067 | 2067 | |||
2068 | if ((rsym = dcs->d_redeclared_symbol)->s_scl == CTCONST) { | 2068 | if ((rsym = dcs->d_redeclared_symbol)->s_scl == CTCONST) { | |
2069 | /* redeclaration of %s */ | 2069 | /* redeclaration of %s */ | |
2070 | error(27, dsym->s_name); | 2070 | error(27, dsym->s_name); | |
2071 | print_previous_declaration(-1, rsym); | 2071 | print_previous_declaration(-1, rsym); | |
2072 | return true; | 2072 | return true; | |
2073 | } | 2073 | } | |
2074 | if (rsym->s_scl == TYPEDEF) { | 2074 | if (rsym->s_scl == TYPEDEF) { | |
2075 | /* typedef redeclared: %s */ | 2075 | /* typedef redeclared: %s */ | |
2076 | error(89, dsym->s_name); | 2076 | error(89, dsym->s_name); | |
2077 | print_previous_declaration(-1, rsym); | 2077 | print_previous_declaration(-1, rsym); | |
2078 | return true; | 2078 | return true; | |
2079 | } | 2079 | } | |
2080 | if (dsym->s_scl == TYPEDEF) { | 2080 | if (dsym->s_scl == TYPEDEF) { | |
2081 | /* redeclaration of %s */ | 2081 | /* redeclaration of %s */ | |
2082 | error(27, dsym->s_name); | 2082 | error(27, dsym->s_name); | |
2083 | print_previous_declaration(-1, rsym); | 2083 | print_previous_declaration(-1, rsym); | |
2084 | return true; | 2084 | return true; | |
2085 | } | 2085 | } | |
2086 | if (rsym->s_def == DEF && dsym->s_def == DEF) { | 2086 | if (rsym->s_def == DEF && dsym->s_def == DEF) { | |
2087 | /* redefinition of %s */ | 2087 | /* redefinition of %s */ | |
2088 | error(28, dsym->s_name); | 2088 | error(28, dsym->s_name); | |
2089 | print_previous_declaration(-1, rsym); | 2089 | print_previous_declaration(-1, rsym); | |
2090 | return true; | 2090 | return true; | |
2091 | } | 2091 | } | |
2092 | if (!eqtype(rsym->s_type, dsym->s_type, false, false, dowarn)) { | 2092 | if (!eqtype(rsym->s_type, dsym->s_type, false, false, dowarn)) { | |
2093 | /* redeclaration of '%s' with type '%s', expected '%s' */ | 2093 | /* redeclaration of '%s' with type '%s', expected '%s' */ | |
2094 | error(347, dsym->s_name, | 2094 | error(347, dsym->s_name, | |
2095 | type_name(dsym->s_type), type_name(rsym->s_type)); | 2095 | type_name(dsym->s_type), type_name(rsym->s_type)); | |
2096 | print_previous_declaration(-1, rsym); | 2096 | print_previous_declaration(-1, rsym); | |
2097 | return true; | 2097 | return true; | |
2098 | } | 2098 | } | |
2099 | if (rsym->s_scl == EXTERN && dsym->s_scl == EXTERN) | 2099 | if (rsym->s_scl == EXTERN && dsym->s_scl == EXTERN) | |
2100 | return false; | 2100 | return false; | |
2101 | if (rsym->s_scl == STATIC && dsym->s_scl == STATIC) | 2101 | if (rsym->s_scl == STATIC && dsym->s_scl == STATIC) | |
2102 | return false; | 2102 | return false; | |
2103 | if (rsym->s_scl == STATIC && dsym->s_def == DECL) | 2103 | if (rsym->s_scl == STATIC && dsym->s_def == DECL) | |
2104 | return false; | 2104 | return false; | |
2105 | if (rsym->s_scl == EXTERN && rsym->s_def == DEF) { | 2105 | if (rsym->s_scl == EXTERN && rsym->s_def == DEF) { | |
2106 | /* | 2106 | /* | |
2107 | * All cases except "int a = 1; static int a;" are caught | 2107 | * All cases except "int a = 1; static int a;" are caught | |
2108 | * above with or without a warning | 2108 | * above with or without a warning | |
2109 | */ | 2109 | */ | |
2110 | /* redeclaration of %s */ | 2110 | /* redeclaration of %s */ | |
2111 | error(27, dsym->s_name); | 2111 | error(27, dsym->s_name); | |
2112 | print_previous_declaration(-1, rsym); | 2112 | print_previous_declaration(-1, rsym); | |
2113 | return true; | 2113 | return true; | |
2114 | } | 2114 | } | |
2115 | if (rsym->s_scl == EXTERN) { | 2115 | if (rsym->s_scl == EXTERN) { | |
2116 | /* previously declared extern, becomes static: %s */ | 2116 | /* previously declared extern, becomes static: %s */ | |
2117 | warning(29, dsym->s_name); | 2117 | warning(29, dsym->s_name); | |
2118 | print_previous_declaration(-1, rsym); | 2118 | print_previous_declaration(-1, rsym); | |
2119 | return false; | 2119 | return false; | |
2120 | } | 2120 | } | |
2121 | /* | 2121 | /* | |
2122 | * Now it's one of: | 2122 | * Now it's one of: | |
2123 | * "static a; int a;", "static a; int a = 1;", "static a = 1; int a;" | 2123 | * "static a; int a;", "static a; int a = 1;", "static a = 1; int a;" | |
2124 | */ | 2124 | */ | |
2125 | /* redeclaration of %s; ANSI C requires "static" */ | 2125 | /* redeclaration of %s; ANSI C requires "static" */ | |
2126 | if (sflag) { | 2126 | if (sflag) { | |
2127 | /* redeclaration of %s; ANSI C requires static */ | 2127 | /* redeclaration of %s; ANSI C requires static */ | |
2128 | warning(30, dsym->s_name); | 2128 | warning(30, dsym->s_name); | |
2129 | print_previous_declaration(-1, rsym); | 2129 | print_previous_declaration(-1, rsym); | |
2130 | } | 2130 | } | |
2131 | dsym->s_scl = STATIC; | 2131 | dsym->s_scl = STATIC; | |
2132 | return false; | 2132 | return false; | |
2133 | } | 2133 | } | |
2134 | 2134 | |||
2135 | static bool | 2135 | static bool | |
2136 | qualifiers_correspond(const type_t *tp1, const type_t *tp2, bool ignqual) | 2136 | qualifiers_correspond(const type_t *tp1, const type_t *tp2, bool ignqual) | |
2137 | { | 2137 | { | |
2138 | if (tp1->t_const != tp2->t_const && !ignqual && !tflag) | 2138 | if (tp1->t_const != tp2->t_const && !ignqual && !tflag) | |
2139 | return false; | 2139 | return false; | |
2140 | 2140 | |||
2141 | if (tp1->t_volatile != tp2->t_volatile && !ignqual && !tflag) | 2141 | if (tp1->t_volatile != tp2->t_volatile && !ignqual && !tflag) | |
2142 | return false; | 2142 | return false; | |
2143 | 2143 | |||
2144 | return true; | 2144 | return true; | |
2145 | } | 2145 | } | |
2146 | 2146 | |||
2147 | bool | 2147 | bool | |
2148 | eqptrtype(const type_t *tp1, const type_t *tp2, bool ignqual) | 2148 | eqptrtype(const type_t *tp1, const type_t *tp2, bool ignqual) | |
2149 | { | 2149 | { | |
2150 | if (tp1->t_tspec != VOID && tp2->t_tspec != VOID) | 2150 | if (tp1->t_tspec != VOID && tp2->t_tspec != VOID) | |
2151 | return false; | 2151 | return false; | |
2152 | 2152 | |||
2153 | if (!qualifiers_correspond(tp1, tp2, ignqual)) | 2153 | if (!qualifiers_correspond(tp1, tp2, ignqual)) | |
2154 | return false; | 2154 | return false; | |
2155 | 2155 | |||
2156 | return true; | 2156 | return true; | |
2157 | } | 2157 | } | |
2158 | 2158 | |||
2159 | 2159 | |||
2160 | /* | 2160 | /* | |
2161 | * Checks if two types are compatible. | 2161 | * Checks if two types are compatible. | |
2162 | * | 2162 | * | |
2163 | * ignqual ignore qualifiers of type; used for function params | 2163 | * ignqual ignore qualifiers of type; used for function params | |
2164 | * promot promote left type; used for comparison of params of | 2164 | * promot promote left type; used for comparison of params of | |
2165 | * old style function definitions with params of prototypes. | 2165 | * old style function definitions with params of prototypes. | |
2166 | * *dowarn set to true if an old style function declaration is not | 2166 | * *dowarn set to true if an old style function declaration is not | |
2167 | * compatible with a prototype | 2167 | * compatible with a prototype | |
2168 | */ | 2168 | */ | |
2169 | bool | 2169 | bool | |
2170 | eqtype(const type_t *tp1, const type_t *tp2, | 2170 | eqtype(const type_t *tp1, const type_t *tp2, | |
2171 | bool ignqual, bool promot, bool *dowarn) | 2171 | bool ignqual, bool promot, bool *dowarn) | |
2172 | { | 2172 | { | |
2173 | tspec_t t; | 2173 | tspec_t t; | |
2174 | 2174 | |||
2175 | while (tp1 != NULL && tp2 != NULL) { | 2175 | while (tp1 != NULL && tp2 != NULL) { | |
2176 | 2176 | |||
2177 | t = tp1->t_tspec; | 2177 | t = tp1->t_tspec; | |
2178 | if (promot) { | 2178 | if (promot) { | |
2179 | if (t == FLOAT) { | 2179 | if (t == FLOAT) { | |
2180 | t = DOUBLE; | 2180 | t = DOUBLE; | |
2181 | } else if (t == CHAR || t == SCHAR) { | 2181 | } else if (t == CHAR || t == SCHAR) { | |
2182 | t = INT; | 2182 | t = INT; | |
2183 | } else if (t == UCHAR) { | 2183 | } else if (t == UCHAR) { | |
2184 | t = tflag ? UINT : INT; | 2184 | t = tflag ? UINT : INT; | |
2185 | } else if (t == SHORT) { | 2185 | } else if (t == SHORT) { | |
2186 | t = INT; | 2186 | t = INT; | |
2187 | } else if (t == USHORT) { | 2187 | } else if (t == USHORT) { | |
2188 | /* CONSTCOND */ | 2188 | /* CONSTCOND */ | |
2189 | t = TARG_INT_MAX < TARG_USHRT_MAX || tflag ? UINT : INT; | 2189 | t = TARG_INT_MAX < TARG_USHRT_MAX || tflag ? UINT : INT; | |
2190 | } | 2190 | } | |
2191 | } | 2191 | } | |
2192 | 2192 | |||
2193 | if (t != tp2->t_tspec) | 2193 | if (t != tp2->t_tspec) | |
2194 | return false; | 2194 | return false; | |
2195 | 2195 | |||
2196 | if (!qualifiers_correspond(tp1, tp2, ignqual)) | 2196 | if (!qualifiers_correspond(tp1, tp2, ignqual)) | |
2197 | return false; | 2197 | return false; | |
2198 | 2198 | |||
2199 | if (t == STRUCT || t == UNION) | 2199 | if (t == STRUCT || t == UNION) | |
2200 | return tp1->t_str == tp2->t_str; | 2200 | return tp1->t_str == tp2->t_str; | |
2201 | 2201 | |||
2202 | if (t == ENUM && eflag) | 2202 | if (t == ENUM && eflag) | |
2203 | return tp1->t_enum == tp2->t_enum; | 2203 | return tp1->t_enum == tp2->t_enum; | |
2204 | 2204 | |||
2205 | if (t == ARRAY && tp1->t_dim != tp2->t_dim) { | 2205 | if (t == ARRAY && tp1->t_dim != tp2->t_dim) { | |
2206 | if (tp1->t_dim != 0 && tp2->t_dim != 0) | 2206 | if (tp1->t_dim != 0 && tp2->t_dim != 0) | |
2207 | return false; | 2207 | return false; | |
2208 | } | 2208 | } | |
2209 | 2209 | |||
2210 | /* don't check prototypes for traditional */ | 2210 | /* don't check prototypes for traditional */ | |
2211 | if (t == FUNC && !tflag) { | 2211 | if (t == FUNC && !tflag) { | |
2212 | if (tp1->t_proto && tp2->t_proto) { | 2212 | if (tp1->t_proto && tp2->t_proto) { | |
2213 | if (!eqargs(tp1, tp2, dowarn)) | 2213 | if (!eqargs(tp1, tp2, dowarn)) | |
2214 | return false; | 2214 | return false; | |
2215 | } else if (tp1->t_proto) { | 2215 | } else if (tp1->t_proto) { | |
2216 | if (!mnoarg(tp1, dowarn)) | 2216 | if (!mnoarg(tp1, dowarn)) | |
2217 | return false; | 2217 | return false; | |
2218 | } else if (tp2->t_proto) { | 2218 | } else if (tp2->t_proto) { | |
2219 | if (!mnoarg(tp2, dowarn)) | 2219 | if (!mnoarg(tp2, dowarn)) | |
2220 | return false; | 2220 | return false; | |
2221 | } | 2221 | } | |
2222 | } | 2222 | } | |
2223 | 2223 | |||
2224 | tp1 = tp1->t_subt; | 2224 | tp1 = tp1->t_subt; | |
2225 | tp2 = tp2->t_subt; | 2225 | tp2 = tp2->t_subt; | |
2226 | ignqual = promot = false; | 2226 | ignqual = promot = false; | |
2227 | 2227 | |||
2228 | } | 2228 | } | |
2229 | 2229 | |||
2230 | return tp1 == tp2; | 2230 | return tp1 == tp2; | |
2231 | } | 2231 | } | |
2232 | 2232 | |||
2233 | /* | 2233 | /* | |
2234 | * Compares the parameter types of two prototypes. | 2234 | * Compares the parameter types of two prototypes. | |
2235 | */ | 2235 | */ | |
2236 | static bool | 2236 | static bool | |
2237 | eqargs(const type_t *tp1, const type_t *tp2, bool *dowarn) | 2237 | eqargs(const type_t *tp1, const type_t *tp2, bool *dowarn) | |
2238 | { | 2238 | { | |
2239 | sym_t *a1, *a2; | 2239 | sym_t *a1, *a2; | |
2240 | 2240 | |||
2241 | if (tp1->t_vararg != tp2->t_vararg) | 2241 | if (tp1->t_vararg != tp2->t_vararg) | |
2242 | return false; | 2242 | return false; | |
2243 | 2243 | |||
2244 | a1 = tp1->t_args; | 2244 | a1 = tp1->t_args; | |
2245 | a2 = tp2->t_args; | 2245 | a2 = tp2->t_args; | |
2246 | 2246 | |||
2247 | while (a1 != NULL && a2 != NULL) { | 2247 | while (a1 != NULL && a2 != NULL) { | |
2248 | 2248 | |||
2249 | if (!eqtype(a1->s_type, a2->s_type, true, false, dowarn)) | 2249 | if (!eqtype(a1->s_type, a2->s_type, true, false, dowarn)) | |
2250 | return false; | 2250 | return false; | |
2251 | 2251 | |||
2252 | a1 = a1->s_next; | 2252 | a1 = a1->s_next; | |
2253 | a2 = a2->s_next; | 2253 | a2 = a2->s_next; | |
2254 | 2254 | |||
2255 | } | 2255 | } | |
2256 | 2256 | |||
2257 | return a1 == a2; | 2257 | return a1 == a2; | |
2258 | } | 2258 | } | |
2259 | 2259 | |||
2260 | /* | 2260 | /* | |
2261 | * mnoarg() (matches functions with no argument type information) | 2261 | * mnoarg() (matches functions with no argument type information) | |
2262 | * returns whether all parameters of a prototype are compatible with | 2262 | * returns whether all parameters of a prototype are compatible with | |
2263 | * an old style function declaration. | 2263 | * an old style function declaration. | |
2264 | * This is the case if the following conditions are met: | 2264 | * This is the case if the following conditions are met: | |
2265 | * 1. the prototype has a fixed number of parameters | 2265 | * 1. the prototype has a fixed number of parameters | |
2266 | * 2. no parameter is of type float | 2266 | * 2. no parameter is of type float | |
2267 | * 3. no parameter is converted to another type if integer promotion | 2267 | * 3. no parameter is converted to another type if integer promotion | |
2268 | * is applied on it | 2268 | * is applied on it | |
2269 | */ | 2269 | */ | |
2270 | static bool | 2270 | static bool | |
2271 | mnoarg(const type_t *tp, bool *dowarn) | 2271 | mnoarg(const type_t *tp, bool *dowarn) | |
2272 | { | 2272 | { | |
2273 | sym_t *arg; | 2273 | sym_t *arg; | |
2274 | tspec_t t; | 2274 | tspec_t t; | |
2275 | 2275 | |||
2276 | if (tp->t_vararg) { | 2276 | if (tp->t_vararg) { | |
2277 | if (dowarn != NULL) | 2277 | if (dowarn != NULL) | |
2278 | *dowarn = true; | 2278 | *dowarn = true; | |
2279 | } | 2279 | } | |
2280 | for (arg = tp->t_args; arg != NULL; arg = arg->s_next) { | 2280 | for (arg = tp->t_args; arg != NULL; arg = arg->s_next) { | |
2281 | if ((t = arg->s_type->t_tspec) == FLOAT || | 2281 | if ((t = arg->s_type->t_tspec) == FLOAT || | |
2282 | t == CHAR || t == SCHAR || t == UCHAR || | 2282 | t == CHAR || t == SCHAR || t == UCHAR || | |
2283 | t == SHORT || t == USHORT) { | 2283 | t == SHORT || t == USHORT) { | |
2284 | if (dowarn != NULL) | 2284 | if (dowarn != NULL) | |
2285 | *dowarn = true; | 2285 | *dowarn = true; | |
2286 | } | 2286 | } | |
2287 | } | 2287 | } | |
2288 | return true; | 2288 | return true; | |
2289 | } | 2289 | } | |
2290 | 2290 | |||
2291 | /* | 2291 | /* | |
2292 | * Compares a prototype declaration with the remembered arguments of | 2292 | * Compares a prototype declaration with the remembered arguments of | |
2293 | * a previous old style function definition. | 2293 | * a previous old style function definition. | |
2294 | */ | 2294 | */ | |
2295 | static bool | 2295 | static bool | |
2296 | check_old_style_definition(sym_t *rdsym, sym_t *dsym) | 2296 | check_old_style_definition(sym_t *rdsym, sym_t *dsym) | |
2297 | { | 2297 | { | |
2298 | sym_t *args, *pargs, *arg, *parg; | 2298 | sym_t *args, *pargs, *arg, *parg; | |
2299 | int narg, nparg, n; | 2299 | int narg, nparg, n; | |
2300 | bool dowarn, msg; | 2300 | bool dowarn, msg; | |
2301 | 2301 | |||
2302 | args = rdsym->s_args; | 2302 | args = rdsym->s_args; | |
2303 | pargs = dsym->s_type->t_args; | 2303 | pargs = dsym->s_type->t_args; | |
2304 | 2304 | |||
2305 | msg = false; | 2305 | msg = false; | |
2306 | 2306 | |||
2307 | narg = nparg = 0; | 2307 | narg = nparg = 0; | |
2308 | for (arg = args; arg != NULL; arg = arg->s_next) | 2308 | for (arg = args; arg != NULL; arg = arg->s_next) | |
2309 | narg++; | 2309 | narg++; | |
2310 | for (parg = pargs; parg != NULL; parg = parg->s_next) | 2310 | for (parg = pargs; parg != NULL; parg = parg->s_next) | |
2311 | nparg++; | 2311 | nparg++; | |
2312 | if (narg != nparg) { | 2312 | if (narg != nparg) { | |
2313 | /* prototype does not match old-style definition */ | 2313 | /* prototype does not match old-style definition */ | |
2314 | error(63); | 2314 | error(63); | |
2315 | msg = true; | 2315 | msg = true; | |
2316 | goto end; | 2316 | goto end; | |
2317 | } | 2317 | } | |
2318 | 2318 | |||
2319 | arg = args; | 2319 | arg = args; | |
2320 | parg = pargs; | 2320 | parg = pargs; | |
2321 | n = 1; | 2321 | n = 1; | |
2322 | while (narg-- > 0) { | 2322 | while (narg-- > 0) { | |
2323 | dowarn = false; | 2323 | dowarn = false; | |
2324 | /* | 2324 | /* | |
2325 | * If it does not match due to promotion and sflag is | 2325 | * If it does not match due to promotion and sflag is | |
2326 | * not set we print only a warning. | 2326 | * not set we print only a warning. | |
2327 | */ | 2327 | */ | |
2328 | if (!eqtype(arg->s_type, parg->s_type, true, true, &dowarn) || | 2328 | if (!eqtype(arg->s_type, parg->s_type, true, true, &dowarn) || | |
2329 | dowarn) { | 2329 | dowarn) { | |
2330 | /* prototype does not match old style ... */ | 2330 | /* prototype does not match old style ... */ | |
2331 | error(299, n); | 2331 | error(299, n); | |
2332 | msg = true; | 2332 | msg = true; | |
2333 | } | 2333 | } | |
2334 | arg = arg->s_next; | 2334 | arg = arg->s_next; | |
2335 | parg = parg->s_next; | 2335 | parg = parg->s_next; | |
2336 | n++; | 2336 | n++; | |
2337 | } | 2337 | } | |
2338 | 2338 | |||
2339 | end: | 2339 | end: | |
2340 | if (msg) | 2340 | if (msg) | |
2341 | /* old style definition */ | 2341 | /* old style definition */ | |
2342 | print_previous_declaration(300, rdsym); | 2342 | print_previous_declaration(300, rdsym); | |
2343 | 2343 | |||
2344 | return msg; | 2344 | return msg; | |
2345 | } | 2345 | } | |
2346 | 2346 | |||
2347 | /* | 2347 | /* | |
2348 | * Completes a type by copying the dimension and prototype information | 2348 | * Completes a type by copying the dimension and prototype information | |
2349 | * from a second compatible type. | 2349 | * from a second compatible type. | |
2350 | * | 2350 | * | |
2351 | * Following lines are legal: | 2351 | * Following lines are legal: | |
2352 | * "typedef a[]; a b; a b[10]; a c; a c[20];" | 2352 | * "typedef a[]; a b; a b[10]; a c; a c[20];" | |
2353 | * "typedef ft(); ft f; f(int); ft g; g(long);" | 2353 | * "typedef ft(); ft f; f(int); ft g; g(long);" | |
2354 | * This means that, if a type is completed, the type structure must | 2354 | * This means that, if a type is completed, the type structure must | |
2355 | * be duplicated. | 2355 | * be duplicated. | |
2356 | */ | 2356 | */ | |
2357 | void | 2357 | void | |
2358 | complete_type(sym_t *dsym, sym_t *ssym) | 2358 | complete_type(sym_t *dsym, sym_t *ssym) | |
2359 | { | 2359 | { | |
2360 | type_t **dstp, *src; | 2360 | type_t **dstp, *src; | |
2361 | type_t *dst; | 2361 | type_t *dst; | |
2362 | 2362 | |||
2363 | dstp = &dsym->s_type; | 2363 | dstp = &dsym->s_type; | |
2364 | src = ssym->s_type; | 2364 | src = ssym->s_type; | |
2365 | 2365 | |||
2366 | while ((dst = *dstp) != NULL) { | 2366 | while ((dst = *dstp) != NULL) { | |
2367 | lint_assert(src != NULL); | 2367 | lint_assert(src != NULL); | |
2368 | lint_assert(dst->t_tspec == src->t_tspec); | 2368 | lint_assert(dst->t_tspec == src->t_tspec); | |
2369 | if (dst->t_tspec == ARRAY) { | 2369 | if (dst->t_tspec == ARRAY) { | |
2370 | if (dst->t_dim == 0 && src->t_dim != 0) { | 2370 | if (dst->t_dim == 0 && src->t_dim != 0) { | |
2371 | *dstp = dst = block_dup_type(dst); | 2371 | *dstp = dst = block_dup_type(dst); | |
2372 | dst->t_dim = src->t_dim; | 2372 | dst->t_dim = src->t_dim; | |
2373 | setcomplete(dst, true); | 2373 | setcomplete(dst, true); | |
2374 | } | 2374 | } | |
2375 | } else if (dst->t_tspec == FUNC) { | 2375 | } else if (dst->t_tspec == FUNC) { | |
2376 | if (!dst->t_proto && src->t_proto) { | 2376 | if (!dst->t_proto && src->t_proto) { | |
2377 | *dstp = dst = block_dup_type(dst); | 2377 | *dstp = dst = block_dup_type(dst); | |
2378 | dst->t_proto = true; | 2378 | dst->t_proto = true; | |
2379 | dst->t_args = src->t_args; | 2379 | dst->t_args = src->t_args; | |
2380 | } | 2380 | } | |
2381 | } | 2381 | } | |
2382 | dstp = &dst->t_subt; | 2382 | dstp = &dst->t_subt; | |
2383 | src = src->t_subt; | 2383 | src = src->t_subt; | |
2384 | } | 2384 | } | |
2385 | } | 2385 | } | |
2386 | 2386 | |||
2387 | /* | 2387 | /* | |
2388 | * Completes the declaration of a single argument. | 2388 | * Completes the declaration of a single argument. | |
2389 | */ | 2389 | */ | |
2390 | sym_t * | 2390 | sym_t * | |
2391 | declare_argument(sym_t *sym, bool initflg) | 2391 | declare_argument(sym_t *sym, bool initflg) | |
2392 | { | 2392 | { | |
2393 | tspec_t t; | 2393 | tspec_t t; | |
2394 | 2394 | |||
2395 | check_function_definition(sym, true); | 2395 | check_function_definition(sym, true); | |
2396 | 2396 | |||
2397 | check_type(sym); | 2397 | check_type(sym); | |
2398 | 2398 | |||
2399 | if (dcs->d_redeclared_symbol != NULL && | 2399 | if (dcs->d_redeclared_symbol != NULL && | |
2400 | dcs->d_redeclared_symbol->s_block_level == block_level) { | 2400 | dcs->d_redeclared_symbol->s_block_level == block_level) { | |
2401 | /* redeclaration of formal parameter %s */ | 2401 | /* redeclaration of formal parameter %s */ | |
2402 | error(237, sym->s_name); | 2402 | error(237, sym->s_name); | |
2403 | rmsym(dcs->d_redeclared_symbol); | 2403 | rmsym(dcs->d_redeclared_symbol); | |
2404 | sym->s_arg = true; | 2404 | sym->s_arg = true; | |
2405 | } | 2405 | } | |
2406 | 2406 | |||
2407 | if (!sym->s_arg) { | 2407 | if (!sym->s_arg) { | |
2408 | /* declared argument %s is missing */ | 2408 | /* declared argument %s is missing */ | |
2409 | error(53, sym->s_name); | 2409 | error(53, sym->s_name); | |
2410 | sym->s_arg = true; | 2410 | sym->s_arg = true; | |
2411 | } | 2411 | } | |
2412 | 2412 | |||
2413 | if (initflg) { | 2413 | if (initflg) { | |
2414 | /* cannot initialize parameter: %s */ | 2414 | /* cannot initialize parameter: %s */ | |
2415 | error(52, sym->s_name); | 2415 | error(52, sym->s_name); | |
2416 | } | 2416 | } | |
2417 | 2417 | |||
2418 | if (sym->s_type == NULL) /* for c(void()) */ | 2418 | if (sym->s_type == NULL) /* for c(void()) */ | |
2419 | sym->s_type = gettyp(VOID); | 2419 | sym->s_type = gettyp(VOID); | |
2420 | 2420 | |||
2421 | if ((t = sym->s_type->t_tspec) == ARRAY) { | 2421 | if ((t = sym->s_type->t_tspec) == ARRAY) { | |
2422 | sym->s_type = block_derive_type(sym->s_type->t_subt, PTR); | 2422 | sym->s_type = block_derive_type(sym->s_type->t_subt, PTR); | |
2423 | } else if (t == FUNC) { | 2423 | } else if (t == FUNC) { | |
2424 | if (tflag) | 2424 | if (tflag) | |
2425 | /* a function is declared as an argument: %s */ | 2425 | /* a function is declared as an argument: %s */ | |
2426 | warning(50, sym->s_name); | 2426 | warning(50, sym->s_name); | |
2427 | sym->s_type = block_derive_type(sym->s_type, PTR); | 2427 | sym->s_type = block_derive_type(sym->s_type, PTR); | |
2428 | } else if (t == FLOAT) { | 2428 | } else if (t == FLOAT) { | |
2429 | if (tflag) | 2429 | if (tflag) | |
2430 | sym->s_type = gettyp(DOUBLE); | 2430 | sym->s_type = gettyp(DOUBLE); | |
2431 | } | 2431 | } | |
2432 | 2432 | |||
2433 | if (dcs->d_inline) | 2433 | if (dcs->d_inline) | |
2434 | /* argument declared inline: %s */ | 2434 | /* argument declared inline: %s */ | |
2435 | warning(269, sym->s_name); | 2435 | warning(269, sym->s_name); | |
2436 | 2436 | |||
2437 | /* | 2437 | /* | |
2438 | * Arguments must have complete types. length() prints the needed | 2438 | * Arguments must have complete types. length() prints the needed | |
2439 | * error messages (null dimension is impossible because arrays are | 2439 | * error messages (null dimension is impossible because arrays are | |
2440 | * converted to pointers). | 2440 | * converted to pointers). | |
2441 | */ | 2441 | */ | |
2442 | if (sym->s_type->t_tspec != VOID) | 2442 | if (sym->s_type->t_tspec != VOID) | |
2443 | (void)length(sym->s_type, sym->s_name); | 2443 | (void)length(sym->s_type, sym->s_name); | |
2444 | 2444 | |||
2445 | sym->s_used = dcs->d_used; | 2445 | sym->s_used = dcs->d_used; | |
2446 | mark_as_set(sym); | 2446 | mark_as_set(sym); | |
2447 | 2447 | |||
2448 | return sym; | 2448 | return sym; | |
2449 | } | 2449 | } | |
2450 | 2450 | |||
2451 | void | 2451 | void | |
2452 | check_func_lint_directives(void) | 2452 | check_func_lint_directives(void) | |
2453 | { | 2453 | { | |
2454 | sym_t *arg; | 2454 | sym_t *arg; | |
2455 | int narg, n; | 2455 | int narg, n; | |
2456 | tspec_t t; | 2456 | tspec_t t; | |
2457 | 2457 | |||
2458 | /* check for illegal combinations of lint directives */ | 2458 | /* check for illegal combinations of lint directives */ | |
2459 | if (printflike_argnum != -1 && scanflike_argnum != -1) { | 2459 | if (printflike_argnum != -1 && scanflike_argnum != -1) { | |
2460 | /* can't be used together: ** PRINTFLIKE ** ** SCANFLIKE ** */ | 2460 | /* can't be used together: ** PRINTFLIKE ** ** SCANFLIKE ** */ | |
2461 | warning(289); | 2461 | warning(289); | |
2462 | printflike_argnum = scanflike_argnum = -1; | 2462 | printflike_argnum = scanflike_argnum = -1; | |
2463 | } | 2463 | } | |
2464 | if (nvararg != -1 && | 2464 | if (nvararg != -1 && | |
2465 | (printflike_argnum != -1 || scanflike_argnum != -1)) { | 2465 | (printflike_argnum != -1 || scanflike_argnum != -1)) { | |
2466 | /* dubious use of ** VARARGS ** with ** %s ** */ | 2466 | /* dubious use of ** VARARGS ** with ** %s ** */ | |
2467 | warning(288, | 2467 | warning(288, | |
2468 | printflike_argnum != -1 ? "PRINTFLIKE" : "SCANFLIKE"); | 2468 | printflike_argnum != -1 ? "PRINTFLIKE" : "SCANFLIKE"); | |
2469 | nvararg = -1; | 2469 | nvararg = -1; | |
2470 | } | 2470 | } | |
2471 | 2471 | |||
2472 | /* | 2472 | /* | |
2473 | * check if the argument of a lint directive is compatible with the | 2473 | * check if the argument of a lint directive is compatible with the | |
2474 | * number of arguments. | 2474 | * number of arguments. | |
2475 | */ | 2475 | */ | |
2476 | narg = 0; | 2476 | narg = 0; | |
2477 | for (arg = dcs->d_func_args; arg != NULL; arg = arg->s_next) | 2477 | for (arg = dcs->d_func_args; arg != NULL; arg = arg->s_next) | |
2478 | narg++; | 2478 | narg++; | |
2479 | if (nargusg > narg) { | 2479 | if (nargusg > narg) { | |
2480 | /* argument number mismatch with directive: ** %s ** */ | 2480 | /* argument number mismatch with directive: ** %s ** */ | |
2481 | warning(283, "ARGSUSED"); | 2481 | warning(283, "ARGSUSED"); | |
2482 | nargusg = 0; | 2482 | nargusg = 0; | |
2483 | } | 2483 | } | |
2484 | if (nvararg > narg) { | 2484 | if (nvararg > narg) { | |
2485 | /* argument number mismatch with directive: ** %s ** */ | 2485 | /* argument number mismatch with directive: ** %s ** */ | |
2486 | warning(283, "VARARGS"); | 2486 | warning(283, "VARARGS"); | |
2487 | nvararg = 0; | 2487 | nvararg = 0; | |
2488 | } | 2488 | } | |
2489 | if (printflike_argnum > narg) { | 2489 | if (printflike_argnum > narg) { | |
2490 | /* argument number mismatch with directive: ** %s ** */ | 2490 | /* argument number mismatch with directive: ** %s ** */ | |
2491 | warning(283, "PRINTFLIKE"); | 2491 | warning(283, "PRINTFLIKE"); | |
2492 | printflike_argnum = -1; | 2492 | printflike_argnum = -1; | |
2493 | } else if (printflike_argnum == 0) { | 2493 | } else if (printflike_argnum == 0) { | |
2494 | printflike_argnum = -1; | 2494 | printflike_argnum = -1; | |
2495 | } | 2495 | } | |
2496 | if (scanflike_argnum > narg) { | 2496 | if (scanflike_argnum > narg) { | |
2497 | /* argument number mismatch with directive: ** %s ** */ | 2497 | /* argument number mismatch with directive: ** %s ** */ | |
2498 | warning(283, "SCANFLIKE"); | 2498 | warning(283, "SCANFLIKE"); | |
2499 | scanflike_argnum = -1; | 2499 | scanflike_argnum = -1; | |
2500 | } else if (scanflike_argnum == 0) { | 2500 | } else if (scanflike_argnum == 0) { | |
2501 | scanflike_argnum = -1; | 2501 | scanflike_argnum = -1; | |
2502 | } | 2502 | } | |
2503 | if (printflike_argnum != -1 || scanflike_argnum != -1) { | 2503 | if (printflike_argnum != -1 || scanflike_argnum != -1) { | |
2504 | narg = printflike_argnum != -1 | 2504 | narg = printflike_argnum != -1 | |
2505 | ? printflike_argnum : scanflike_argnum; | 2505 | ? printflike_argnum : scanflike_argnum; | |
2506 | arg = dcs->d_func_args; | 2506 | arg = dcs->d_func_args; | |
2507 | for (n = 1; n < narg; n++) | 2507 | for (n = 1; n < narg; n++) | |
2508 | arg = arg->s_next; | 2508 | arg = arg->s_next; | |
2509 | if (arg->s_type->t_tspec != PTR || | 2509 | if (arg->s_type->t_tspec != PTR || | |
2510 | ((t = arg->s_type->t_subt->t_tspec) != CHAR && | 2510 | ((t = arg->s_type->t_subt->t_tspec) != CHAR && | |
2511 | t != UCHAR && t != SCHAR)) { | 2511 | t != UCHAR && t != SCHAR)) { | |
2512 | /* argument %d must be 'char *' for PRINTFLIKE/... */ | 2512 | /* argument %d must be 'char *' for PRINTFLIKE/... */ | |
2513 | warning(293, narg); | 2513 | warning(293, narg); | |
2514 | printflike_argnum = scanflike_argnum = -1; | 2514 | printflike_argnum = scanflike_argnum = -1; | |
2515 | } | 2515 | } | |
2516 | } | 2516 | } | |
2517 | } | 2517 | } | |
2518 | 2518 | |||
2519 | /* | 2519 | /* | |
2520 | * Warn about arguments in old style function definitions that default to int. | 2520 | * Warn about arguments in old style function definitions that default to int. | |
2521 | * Check that an old style function definition is compatible to a previous | 2521 | * Check that an old style function definition is compatible to a previous | |
2522 | * prototype. | 2522 | * prototype. | |
2523 | */ | 2523 | */ | |
2524 | void | 2524 | void | |
2525 | check_func_old_style_arguments(void) | 2525 | check_func_old_style_arguments(void) | |
2526 | { | 2526 | { | |
2527 | sym_t *args, *arg, *pargs, *parg; | 2527 | sym_t *args, *arg, *pargs, *parg; | |
2528 | int narg, nparg; | 2528 | int narg, nparg; | |
2529 | bool msg; | 2529 | bool msg; | |
2530 | 2530 | |||
2531 | args = funcsym->s_args; | 2531 | args = funcsym->s_args; | |
2532 | pargs = funcsym->s_type->t_args; | 2532 | pargs = funcsym->s_type->t_args; | |
2533 | 2533 | |||
2534 | /* | 2534 | /* | |
2535 | * print a warning for each argument of an old style function | 2535 | * print a warning for each argument of an old style function | |
2536 | * definition which defaults to int | 2536 | * definition which defaults to int | |
2537 | */ | 2537 | */ | |
2538 | for (arg = args; arg != NULL; arg = arg->s_next) { | 2538 | for (arg = args; arg != NULL; arg = arg->s_next) { | |
2539 | if (arg->s_defarg) { | 2539 | if (arg->s_defarg) { | |
2540 | /* argument type defaults to 'int': %s */ | 2540 | /* argument type defaults to 'int': %s */ | |
2541 | warning(32, arg->s_name); | 2541 | warning(32, arg->s_name); | |
2542 | arg->s_defarg = false; | 2542 | arg->s_defarg = false; | |
2543 | mark_as_set(arg); | 2543 | mark_as_set(arg); | |
2544 | } | 2544 | } | |
2545 | } | 2545 | } | |
2546 | 2546 | |||
2547 | /* | 2547 | /* | |
2548 | * If this is an old style function definition and a prototype | 2548 | * If this is an old style function definition and a prototype | |
2549 | * exists, compare the types of arguments. | 2549 | * exists, compare the types of arguments. | |
2550 | */ | 2550 | */ | |
2551 | if (funcsym->s_osdef && funcsym->s_type->t_proto) { | 2551 | if (funcsym->s_osdef && funcsym->s_type->t_proto) { | |
2552 | /* | 2552 | /* | |
2553 | * If the number of arguments does not match, we need not | 2553 | * If the number of arguments does not match, we need not | |
2554 | * continue. | 2554 | * continue. | |
2555 | */ | 2555 | */ | |
2556 | narg = nparg = 0; | 2556 | narg = nparg = 0; | |
2557 | msg = false; | 2557 | msg = false; | |
2558 | for (parg = pargs; parg != NULL; parg = parg->s_next) | 2558 | for (parg = pargs; parg != NULL; parg = parg->s_next) | |
2559 | nparg++; | 2559 | nparg++; | |
2560 | for (arg = args; arg != NULL; arg = arg->s_next) | 2560 | for (arg = args; arg != NULL; arg = arg->s_next) | |
2561 | narg++; | 2561 | narg++; | |
2562 | if (narg != nparg) { | 2562 | if (narg != nparg) { | |
2563 | /* parameter mismatch: %d declared, %d defined */ | 2563 | /* parameter mismatch: %d declared, %d defined */ | |
2564 | error(51, nparg, narg); | 2564 | error(51, nparg, narg); | |
2565 | msg = true; | 2565 | msg = true; | |
2566 | } else { | 2566 | } else { | |
2567 | parg = pargs; | 2567 | parg = pargs; | |
2568 | arg = args; | 2568 | arg = args; | |
2569 | while (narg-- > 0) { | 2569 | while (narg-- > 0) { | |
2570 | msg |= check_prototype_declaration(arg, parg); | 2570 | msg |= check_prototype_declaration(arg, parg); | |
2571 | parg = parg->s_next; | 2571 | parg = parg->s_next; | |
2572 | arg = arg->s_next; | 2572 | arg = arg->s_next; | |
2573 | } | 2573 | } | |
2574 | } | 2574 | } | |
2575 | if (msg) | 2575 | if (msg) | |
2576 | /* prototype declaration */ | 2576 | /* prototype declaration */ | |
2577 | print_previous_declaration(285, | 2577 | print_previous_declaration(285, | |
2578 | dcs->d_redeclared_symbol); | 2578 | dcs->d_redeclared_symbol); | |
2579 | 2579 | |||
2580 | /* from now on the prototype is valid */ | 2580 | /* from now on the prototype is valid */ | |
2581 | funcsym->s_osdef = false; | 2581 | funcsym->s_osdef = false; | |
2582 | funcsym->s_args = NULL; | 2582 | funcsym->s_args = NULL; | |
2583 | } | 2583 | } | |
2584 | } | 2584 | } | |
2585 | 2585 | |||
2586 | /* | 2586 | /* | |
2587 | * Checks compatibility of an old style function definition with a previous | 2587 | * Checks compatibility of an old style function definition with a previous | |
2588 | * prototype declaration. | 2588 | * prototype declaration. | |
2589 | * Returns true if the position of the previous declaration should be reported. | 2589 | * Returns true if the position of the previous declaration should be reported. | |
2590 | */ | 2590 | */ | |
2591 | static bool | 2591 | static bool | |
2592 | check_prototype_declaration(sym_t *arg, sym_t *parg) | 2592 | check_prototype_declaration(sym_t *arg, sym_t *parg) | |
2593 | { | 2593 | { | |
2594 | type_t *tp, *ptp; | 2594 | type_t *tp, *ptp; | |
2595 | bool dowarn, msg; | 2595 | bool dowarn, msg; | |
2596 | 2596 | |||
2597 | tp = arg->s_type; | 2597 | tp = arg->s_type; | |
2598 | ptp = parg->s_type; | 2598 | ptp = parg->s_type; | |
2599 | 2599 | |||
2600 | msg = false; | 2600 | msg = false; | |
2601 | dowarn = false; | 2601 | dowarn = false; | |
2602 | 2602 | |||
2603 | if (!eqtype(tp, ptp, true, true, &dowarn)) { | 2603 | if (!eqtype(tp, ptp, true, true, &dowarn)) { | |
2604 | if (eqtype(tp, ptp, true, false, &dowarn)) { | 2604 | if (eqtype(tp, ptp, true, false, &dowarn)) { | |
2605 | /* type does not match prototype: %s */ | 2605 | /* type does not match prototype: %s */ | |
2606 | gnuism(58, arg->s_name); | 2606 | gnuism(58, arg->s_name); | |
2607 | msg = sflag || !gflag; | 2607 | msg = sflag || !gflag; | |
2608 | } else { | 2608 | } else { | |
2609 | /* type does not match prototype: %s */ | 2609 | /* type does not match prototype: %s */ | |
2610 | error(58, arg->s_name); | 2610 | error(58, arg->s_name); | |
2611 | msg = true; | 2611 | msg = true; | |
2612 | } | 2612 | } | |
2613 | } else if (dowarn) { | 2613 | } else if (dowarn) { | |
2614 | if (sflag) | 2614 | if (sflag) | |
2615 | /* type does not match prototype: %s */ | 2615 | /* type does not match prototype: %s */ | |
2616 | error(58, arg->s_name); | 2616 | error(58, arg->s_name); | |
2617 | else | 2617 | else | |
2618 | /* type does not match prototype: %s */ | 2618 | /* type does not match prototype: %s */ | |
2619 | warning(58, arg->s_name); | 2619 | warning(58, arg->s_name); | |
2620 | msg = true; | 2620 | msg = true; | |
2621 | } | 2621 | } | |
2622 | 2622 | |||
2623 | return msg; | 2623 | return msg; | |
2624 | } | 2624 | } | |
2625 | 2625 | |||
2626 | static void | 2626 | static void | |
2627 | check_local_hiding(const sym_t *dsym) | 2627 | check_local_hiding(const sym_t *dsym) | |
2628 | { | 2628 | { | |
2629 | switch (dsym->s_scl) { | 2629 | switch (dsym->s_scl) { | |
2630 | case AUTO: | 2630 | case AUTO: | |
2631 | /* automatic hides external declaration: %s */ | 2631 | /* automatic hides external declaration: %s */ | |
2632 | warning(86, dsym->s_name); | 2632 | warning(86, dsym->s_name); | |
2633 | break; | 2633 | break; | |
2634 | case STATIC: | 2634 | case STATIC: | |
2635 | /* static hides external declaration: %s */ | 2635 | /* static hides external declaration: %s */ | |
2636 | warning(87, dsym->s_name); | 2636 | warning(87, dsym->s_name); | |
2637 | break; | 2637 | break; | |
2638 | case TYPEDEF: | 2638 | case TYPEDEF: | |
2639 | /* typedef hides external declaration: %s */ | 2639 | /* typedef hides external declaration: %s */ | |
2640 | warning(88, dsym->s_name); | 2640 | warning(88, dsym->s_name); | |
2641 | break; | 2641 | break; | |
2642 | case EXTERN: | 2642 | case EXTERN: | |
2643 | /* Already checked in declare_external_in_block. */ | 2643 | /* Already checked in declare_external_in_block. */ | |
2644 | break; | 2644 | break; | |
2645 | default: | 2645 | default: | |
2646 | lint_assert(/*CONSTCOND*/false); | 2646 | lint_assert(/*CONSTCOND*/false); | |
2647 | } | 2647 | } | |
2648 | } | 2648 | } | |
2649 | 2649 | |||
2650 | static void | 2650 | static void | |
2651 | check_local_redeclaration(const sym_t *dsym, sym_t *rsym) | 2651 | check_local_redeclaration(const sym_t *dsym, sym_t *rsym) | |
2652 | { | 2652 | { | |
2653 | if (rsym->s_block_level == 0) { | 2653 | if (rsym->s_block_level == 0) { | |
2654 | if (hflag) | 2654 | if (hflag) | |
2655 | check_local_hiding(dsym); | 2655 | check_local_hiding(dsym); | |
2656 | 2656 | |||
2657 | } else if (rsym->s_block_level == block_level) { | 2657 | } else if (rsym->s_block_level == block_level) { | |
2658 | 2658 | |||
2659 | /* no hflag, because it's illegal! */ | 2659 | /* no hflag, because it's illegal! */ | |
2660 | if (rsym->s_arg) { | 2660 | if (rsym->s_arg) { | |
2661 | /* | 2661 | /* | |
2662 | * if !tflag, a "redeclaration of %s" error | 2662 | * if !tflag, a "redeclaration of %s" error | |
2663 | * is produced below | 2663 | * is produced below | |
2664 | */ | 2664 | */ | |
2665 | if (tflag) { | 2665 | if (tflag) { | |
2666 | if (hflag) | 2666 | if (hflag) | |
2667 | /* declaration hides parameter: %s */ | 2667 | /* declaration hides parameter: %s */ | |
2668 | warning(91, dsym->s_name); | 2668 | warning(91, dsym->s_name); | |
2669 | rmsym(rsym); | 2669 | rmsym(rsym); | |
2670 | } | 2670 | } | |
2671 | } | 2671 | } | |
2672 | 2672 | |||
2673 | } else if (rsym->s_block_level < block_level) { | 2673 | } else if (rsym->s_block_level < block_level) { | |
2674 | if (hflag) | 2674 | if (hflag) | |
2675 | /* declaration hides earlier one: %s */ | 2675 | /* declaration hides earlier one: %s */ | |
2676 | warning(95, dsym->s_name); | 2676 | warning(95, dsym->s_name); | |
2677 | } | 2677 | } | |
2678 | 2678 | |||
2679 | if (rsym->s_block_level == block_level) { | 2679 | if (rsym->s_block_level == block_level) { | |
2680 | /* redeclaration of %s */ | 2680 | /* redeclaration of %s */ | |
2681 | error(27, dsym->s_name); | 2681 | error(27, dsym->s_name); | |
2682 | rmsym(rsym); | 2682 | rmsym(rsym); | |
2683 | } | 2683 | } | |
2684 | } | 2684 | } | |
2685 | 2685 | |||
2686 | /* | 2686 | /* | |
2687 | * Completes a single local declaration/definition. | 2687 | * Completes a single local declaration/definition. | |
2688 | */ | 2688 | */ | |
2689 | void | 2689 | void | |
2690 | declare_local(sym_t *dsym, bool initflg) | 2690 | declare_local(sym_t *dsym, bool initflg) | |
2691 | { | 2691 | { | |
2692 | 2692 | |||
2693 | /* Correct a mistake done in declarator_name(). */ | 2693 | /* Correct a mistake done in declarator_name(). */ | |
2694 | if (dsym->s_type->t_tspec == FUNC) { | 2694 | if (dsym->s_type->t_tspec == FUNC) { | |
2695 | dsym->s_def = DECL; | 2695 | dsym->s_def = DECL; | |
2696 | if (dcs->d_scl == NOSCL) | 2696 | if (dcs->d_scl == NOSCL) | |
2697 | dsym->s_scl = EXTERN; | 2697 | dsym->s_scl = EXTERN; | |
2698 | } | 2698 | } | |
2699 | 2699 | |||
2700 | if (dsym->s_type->t_tspec == FUNC) { | 2700 | if (dsym->s_type->t_tspec == FUNC) { | |
2701 | if (dsym->s_scl == STATIC) { | 2701 | if (dsym->s_scl == STATIC) { | |
2702 | /* dubious static function at block level: %s */ | 2702 | /* dubious static function at block level: %s */ | |
2703 | warning(93, dsym->s_name); | 2703 | warning(93, dsym->s_name); | |
2704 | dsym->s_scl = EXTERN; | 2704 | dsym->s_scl = EXTERN; | |
2705 | } else if (dsym->s_scl != EXTERN && dsym->s_scl != TYPEDEF) { | 2705 | } else if (dsym->s_scl != EXTERN && dsym->s_scl != TYPEDEF) { | |
2706 | /* function has illegal storage class: %s */ | 2706 | /* function has illegal storage class: %s */ | |
2707 | error(94, dsym->s_name); | 2707 | error(94, dsym->s_name); | |
2708 | dsym->s_scl = EXTERN; | 2708 | dsym->s_scl = EXTERN; | |
2709 | } | 2709 | } | |
2710 | } | 2710 | } | |
2711 | 2711 | |||
2712 | /* | 2712 | /* | |
2713 | * functions may be declared inline at local scope, although | 2713 | * functions may be declared inline at local scope, although | |
2714 | * this has no effect for a later definition of the same | 2714 | * this has no effect for a later definition of the same | |
2715 | * function. | 2715 | * function. | |
2716 | * XXX it should have an effect if tflag is set. this would | 2716 | * XXX it should have an effect if tflag is set. this would | |
2717 | * also be the way gcc behaves. | 2717 | * also be the way gcc behaves. | |
2718 | */ | 2718 | */ | |
2719 | if (dcs->d_inline) { | 2719 | if (dcs->d_inline) { | |
2720 | if (dsym->s_type->t_tspec == FUNC) { | 2720 | if (dsym->s_type->t_tspec == FUNC) { | |
2721 | dsym->s_inline = true; | 2721 | dsym->s_inline = true; | |
2722 | } else { | 2722 | } else { | |
2723 | /* variable declared inline: %s */ | 2723 | /* variable declared inline: %s */ | |
2724 | warning(268, dsym->s_name); | 2724 | warning(268, dsym->s_name); | |
2725 | } | 2725 | } | |
2726 | } | 2726 | } | |
2727 | 2727 | |||
2728 | check_function_definition(dsym, true); | 2728 | check_function_definition(dsym, true); | |
2729 | 2729 | |||
2730 | check_type(dsym); | 2730 | check_type(dsym); | |
2731 | 2731 | |||
2732 | if (dcs->d_redeclared_symbol != NULL && dsym->s_scl == EXTERN) | 2732 | if (dcs->d_redeclared_symbol != NULL && dsym->s_scl == EXTERN) | |
2733 | declare_external_in_block(dsym); | 2733 | declare_external_in_block(dsym); | |
2734 | 2734 | |||
2735 | if (dsym->s_scl == EXTERN) { | 2735 | if (dsym->s_scl == EXTERN) { | |
2736 | /* | 2736 | /* | |
2737 | * XXX if the static variable at level 0 is only defined | 2737 | * XXX if the static variable at level 0 is only defined | |
2738 | * later, checking will be possible. | 2738 | * later, checking will be possible. | |
2739 | */ | 2739 | */ | |
2740 | if (dsym->s_ext_sym == NULL) { | 2740 | if (dsym->s_ext_sym == NULL) { | |
2741 | outsym(dsym, EXTERN, dsym->s_def); | 2741 | outsym(dsym, EXTERN, dsym->s_def); | |
2742 | } else { | 2742 | } else { | |
2743 | outsym(dsym, dsym->s_ext_sym->s_scl, dsym->s_def); | 2743 | outsym(dsym, dsym->s_ext_sym->s_scl, dsym->s_def); | |
2744 | } | 2744 | } | |
2745 | } | 2745 | } | |
2746 | 2746 | |||
2747 | if (dcs->d_redeclared_symbol != NULL) | 2747 | if (dcs->d_redeclared_symbol != NULL) | |
2748 | check_local_redeclaration(dsym, dcs->d_redeclared_symbol); | 2748 | check_local_redeclaration(dsym, dcs->d_redeclared_symbol); | |
2749 | 2749 | |||
2750 | if (initflg && !check_init(dsym)) { | 2750 | if (initflg && !check_init(dsym)) { | |
2751 | dsym->s_def = DEF; | 2751 | dsym->s_def = DEF; | |
2752 | mark_as_set(dsym); | 2752 | mark_as_set(dsym); | |
2753 | } | 2753 | } | |
2754 | 2754 | |||
2755 | if (dsym->s_scl == TYPEDEF) { | 2755 | if (dsym->s_scl == TYPEDEF) { | |
2756 | dsym->s_type = block_dup_type(dsym->s_type); | 2756 | dsym->s_type = block_dup_type(dsym->s_type); | |
2757 | dsym->s_type->t_typedef = true; | 2757 | dsym->s_type->t_typedef = true; | |
2758 | settdsym(dsym->s_type, dsym); | 2758 | settdsym(dsym->s_type, dsym); | |
2759 | } | 2759 | } | |
2760 | 2760 | |||
2761 | /* | 2761 | /* | |
2762 | * Before we can check the size we must wait for a initialization | 2762 | * Before we can check the size we must wait for a initialization | |
2763 | * which may follow. | 2763 | * which may follow. | |
2764 | */ | 2764 | */ | |
2765 | } | 2765 | } | |
2766 | 2766 | |||
2767 | /* | 2767 | /* | |
2768 | * Processes (re)declarations of external symbols inside blocks. | 2768 | * Processes (re)declarations of external symbols inside blocks. | |
2769 | */ | 2769 | */ | |
2770 | static void | 2770 | static void | |
2771 | declare_external_in_block(sym_t *dsym) | 2771 | declare_external_in_block(sym_t *dsym) | |
2772 | { | 2772 | { | |
2773 | bool eqt, dowarn; | 2773 | bool eqt, dowarn; | |
2774 | sym_t *esym; | 2774 | sym_t *esym; | |
2775 | 2775 | |||
2776 | /* look for a symbol with the same name */ | 2776 | /* look for a symbol with the same name */ | |
2777 | esym = dcs->d_redeclared_symbol; | 2777 | esym = dcs->d_redeclared_symbol; | |
2778 | while (esym != NULL && esym->s_block_level != 0) { | 2778 | while (esym != NULL && esym->s_block_level != 0) { | |
2779 | while ((esym = esym->s_link) != NULL) { | 2779 | while ((esym = esym->s_symtab_next) != NULL) { | |
2780 | if (esym->s_kind != FVFT) | 2780 | if (esym->s_kind != FVFT) | |
2781 | continue; | 2781 | continue; | |
2782 | if (strcmp(dsym->s_name, esym->s_name) == 0) | 2782 | if (strcmp(dsym->s_name, esym->s_name) == 0) | |
2783 | break; | 2783 | break; | |
2784 | } | 2784 | } | |
2785 | } | 2785 | } | |
2786 | if (esym == NULL) | 2786 | if (esym == NULL) | |
2787 | return; | 2787 | return; | |
2788 | if (esym->s_scl != EXTERN && esym->s_scl != STATIC) { | 2788 | if (esym->s_scl != EXTERN && esym->s_scl != STATIC) { | |
2789 | /* gcc accepts this without a warning, pcc prints an error. */ | 2789 | /* gcc accepts this without a warning, pcc prints an error. */ | |
2790 | /* redeclaration of %s */ | 2790 | /* redeclaration of %s */ | |
2791 | warning(27, dsym->s_name); | 2791 | warning(27, dsym->s_name); | |
2792 | print_previous_declaration(-1, esym); | 2792 | print_previous_declaration(-1, esym); | |
2793 | return; | 2793 | return; | |
2794 | } | 2794 | } | |
2795 | 2795 | |||
2796 | dowarn = false; | 2796 | dowarn = false; | |
2797 | eqt = eqtype(esym->s_type, dsym->s_type, false, false, &dowarn); | 2797 | eqt = eqtype(esym->s_type, dsym->s_type, false, false, &dowarn); | |
2798 | 2798 | |||
2799 | if (!eqt || dowarn) { | 2799 | if (!eqt || dowarn) { | |
2800 | if (esym->s_scl == EXTERN) { | 2800 | if (esym->s_scl == EXTERN) { | |
2801 | /* inconsistent redeclaration of extern: %s */ | 2801 | /* inconsistent redeclaration of extern: %s */ | |
2802 | warning(90, dsym->s_name); | 2802 | warning(90, dsym->s_name); | |
2803 | print_previous_declaration(-1, esym); | 2803 | print_previous_declaration(-1, esym); | |
2804 | } else { | 2804 | } else { | |
2805 | /* inconsistent redeclaration of static: %s */ | 2805 | /* inconsistent redeclaration of static: %s */ | |
2806 | warning(92, dsym->s_name); | 2806 | warning(92, dsym->s_name); | |
2807 | print_previous_declaration(-1, esym); | 2807 | print_previous_declaration(-1, esym); | |
2808 | } | 2808 | } | |
2809 | } | 2809 | } | |
2810 | 2810 | |||
2811 | if (eqt) { | 2811 | if (eqt) { | |
2812 | /* | 2812 | /* | |
2813 | * Remember the external symbol so we can update usage | 2813 | * Remember the external symbol so we can update usage | |
2814 | * information at the end of the block. | 2814 | * information at the end of the block. | |
2815 | */ | 2815 | */ | |
2816 | dsym->s_ext_sym = esym; | 2816 | dsym->s_ext_sym = esym; | |
2817 | } | 2817 | } | |
2818 | } | 2818 | } | |
2819 | 2819 | |||
2820 | /* | 2820 | /* | |
2821 | * Print an error or a warning if the symbol cannot be initialized due | 2821 | * Print an error or a warning if the symbol cannot be initialized due | |
2822 | * to type/storage class. Return whether an error has been detected. | 2822 | * to type/storage class. Return whether an error has been detected. | |
2823 | */ | 2823 | */ | |
2824 | static bool | 2824 | static bool | |
2825 | check_init(sym_t *sym) | 2825 | check_init(sym_t *sym) | |
2826 | { | 2826 | { | |
2827 | bool erred; | 2827 | bool erred; | |
2828 | 2828 | |||
2829 | erred = false; | 2829 | erred = false; | |
2830 | 2830 | |||
2831 | if (sym->s_type->t_tspec == FUNC) { | 2831 | if (sym->s_type->t_tspec == FUNC) { | |
2832 | /* cannot initialize function: %s */ | 2832 | /* cannot initialize function: %s */ | |
2833 | error(24, sym->s_name); | 2833 | error(24, sym->s_name); | |
2834 | erred = true; | 2834 | erred = true; | |
2835 | } else if (sym->s_scl == TYPEDEF) { | 2835 | } else if (sym->s_scl == TYPEDEF) { | |
2836 | /* cannot initialize typedef: %s */ | 2836 | /* cannot initialize typedef: %s */ | |
2837 | error(25, sym->s_name); | 2837 | error(25, sym->s_name); | |
2838 | erred = true; | 2838 | erred = true; | |
2839 | } else if (sym->s_scl == EXTERN && sym->s_def == DECL) { | 2839 | } else if (sym->s_scl == EXTERN && sym->s_def == DECL) { | |
2840 | /* cannot initialize "extern" declaration: %s */ | 2840 | /* cannot initialize "extern" declaration: %s */ | |
2841 | if (dcs->d_ctx == EXTERN) { | 2841 | if (dcs->d_ctx == EXTERN) { | |
2842 | /* cannot initialize extern declaration: %s */ | 2842 | /* cannot initialize extern declaration: %s */ | |
2843 | warning(26, sym->s_name); | 2843 | warning(26, sym->s_name); | |
2844 | } else { | 2844 | } else { | |
2845 | /* cannot initialize extern declaration: %s */ | 2845 | /* cannot initialize extern declaration: %s */ | |
2846 | error(26, sym->s_name); | 2846 | error(26, sym->s_name); | |
2847 | erred = true; | 2847 | erred = true; | |
2848 | } | 2848 | } | |
2849 | } | 2849 | } | |
2850 | 2850 | |||
2851 | return erred; | 2851 | return erred; | |
2852 | } | 2852 | } | |
2853 | 2853 | |||
2854 | /* | 2854 | /* | |
2855 | * Create a symbol for an abstract declaration. | 2855 | * Create a symbol for an abstract declaration. | |
2856 | */ | 2856 | */ | |
2857 | sym_t * | 2857 | sym_t * | |
2858 | abstract_name(void) | 2858 | abstract_name(void) | |
2859 | { | 2859 | { | |
2860 | sym_t *sym; | 2860 | sym_t *sym; | |
2861 | 2861 | |||
2862 | lint_assert(dcs->d_ctx == ABSTRACT || dcs->d_ctx == PROTO_ARG); | 2862 | lint_assert(dcs->d_ctx == ABSTRACT || dcs->d_ctx == PROTO_ARG); | |
2863 | 2863 | |||
2864 | sym = block_zero_alloc(sizeof(*sym)); | 2864 | sym = block_zero_alloc(sizeof(*sym)); | |
2865 | 2865 | |||
2866 | sym->s_name = unnamed; | 2866 | sym->s_name = unnamed; | |
2867 | sym->s_def = DEF; | 2867 | sym->s_def = DEF; | |
2868 | sym->s_scl = ABSTRACT; | 2868 | sym->s_scl = ABSTRACT; | |
2869 | sym->s_block_level = -1; | 2869 | sym->s_block_level = -1; | |
2870 | 2870 | |||
2871 | if (dcs->d_ctx == PROTO_ARG) | 2871 | if (dcs->d_ctx == PROTO_ARG) | |
2872 | sym->s_arg = true; | 2872 | sym->s_arg = true; | |
2873 | 2873 | |||
2874 | /* | 2874 | /* | |
2875 | * At this point, dcs->d_type contains only the basic type. That | 2875 | * At this point, dcs->d_type contains only the basic type. That | |
2876 | * type will be updated later, adding pointers, arrays and functions | 2876 | * type will be updated later, adding pointers, arrays and functions | |
2877 | * as necessary. | 2877 | * as necessary. | |
2878 | */ | 2878 | */ | |
2879 | /* | 2879 | /* | |
2880 | * XXX: This is not the correct type. For example in msg_347, it is | 2880 | * XXX: This is not the correct type. For example in msg_347, it is | |
2881 | * the type of the last prototype parameter, but it should rather be | 2881 | * the type of the last prototype parameter, but it should rather be | |
2882 | * the return type of the function. | 2882 | * the return type of the function. | |
2883 | */ | 2883 | */ | |
2884 | sym->s_type = dcs->d_type; | 2884 | sym->s_type = dcs->d_type; | |
2885 | dcs->d_redeclared_symbol = NULL; | 2885 | dcs->d_redeclared_symbol = NULL; | |
2886 | dcs->d_vararg = false; | 2886 | dcs->d_vararg = false; | |
2887 | 2887 | |||
2888 | return sym; | 2888 | return sym; | |
2889 | } | 2889 | } | |
2890 | 2890 | |||
2891 | /* | 2891 | /* | |
2892 | * Removes anything which has nothing to do on global level. | 2892 | * Removes anything which has nothing to do on global level. | |
2893 | */ | 2893 | */ | |
2894 | void | 2894 | void | |
2895 | global_clean_up(void) | 2895 | global_clean_up(void) | |
2896 | { | 2896 | { | |
2897 | 2897 | |||
2898 | while (dcs->d_next != NULL) | 2898 | while (dcs->d_next != NULL) | |
2899 | end_declaration_level(); | 2899 | end_declaration_level(); | |
2900 | 2900 | |||
2901 | cleanup(); | 2901 | cleanup(); | |
2902 | block_level = 0; | 2902 | block_level = 0; | |
2903 | mem_block_level = 0; | 2903 | mem_block_level = 0; | |
2904 | 2904 | |||
2905 | /* | 2905 | /* | |
2906 | * remove all information about pending lint directives without | 2906 | * remove all information about pending lint directives without | |
2907 | * warnings. | 2907 | * warnings. | |
2908 | */ | 2908 | */ | |
2909 | global_clean_up_decl(true); | 2909 | global_clean_up_decl(true); | |
2910 | } | 2910 | } | |
2911 | 2911 | |||
2912 | /* | 2912 | /* | |
2913 | * Process an abstract type declaration | 2913 | * Process an abstract type declaration | |
2914 | */ | 2914 | */ | |
2915 | sym_t * | 2915 | sym_t * | |
2916 | declare_1_abstract(sym_t *sym) | 2916 | declare_1_abstract(sym_t *sym) | |
2917 | { | 2917 | { | |
2918 | 2918 | |||
2919 | check_function_definition(sym, true); | 2919 | check_function_definition(sym, true); | |
2920 | check_type(sym); | 2920 | check_type(sym); | |
2921 | return sym; | 2921 | return sym; | |
2922 | } | 2922 | } | |
2923 | 2923 | |||
2924 | /* | 2924 | /* | |
2925 | * Checks size after declarations of variables and their initialization. | 2925 | * Checks size after declarations of variables and their initialization. | |
2926 | */ | 2926 | */ | |
2927 | void | 2927 | void | |
2928 | check_size(sym_t *dsym) | 2928 | check_size(sym_t *dsym) | |
2929 | { | 2929 | { | |
2930 | 2930 | |||
2931 | if (dsym->s_def != DEF) | 2931 | if (dsym->s_def != DEF) | |
2932 | return; | 2932 | return; | |
2933 | if (dsym->s_scl == TYPEDEF) | 2933 | if (dsym->s_scl == TYPEDEF) | |
2934 | return; | 2934 | return; | |
2935 | if (dsym->s_type->t_tspec == FUNC) | 2935 | if (dsym->s_type->t_tspec == FUNC) | |
2936 | return; | 2936 | return; | |
2937 | 2937 | |||
2938 | if (length(dsym->s_type, dsym->s_name) == 0 && | 2938 | if (length(dsym->s_type, dsym->s_name) == 0 && | |
2939 | dsym->s_type->t_tspec == ARRAY && dsym->s_type->t_dim == 0) { | 2939 | dsym->s_type->t_tspec == ARRAY && dsym->s_type->t_dim == 0) { | |
2940 | if (tflag) { | 2940 | if (tflag) { | |
2941 | /* empty array declaration: %s */ | 2941 | /* empty array declaration: %s */ | |
2942 | warning(190, dsym->s_name); | 2942 | warning(190, dsym->s_name); | |
2943 | } else { | 2943 | } else { | |
2944 | /* empty array declaration: %s */ | 2944 | /* empty array declaration: %s */ | |
2945 | error(190, dsym->s_name); | 2945 | error(190, dsym->s_name); | |
2946 | } | 2946 | } | |
2947 | } | 2947 | } | |
2948 | } | 2948 | } | |
2949 | 2949 | |||
2950 | /* | 2950 | /* | |
2951 | * Mark an object as set if it is not already | 2951 | * Mark an object as set if it is not already | |
2952 | */ | 2952 | */ | |
2953 | void | 2953 | void | |
2954 | mark_as_set(sym_t *sym) | 2954 | mark_as_set(sym_t *sym) | |
2955 | { | 2955 | { | |
2956 | 2956 | |||
2957 | if (!sym->s_set) { | 2957 | if (!sym->s_set) { | |
2958 | sym->s_set = true; | 2958 | sym->s_set = true; | |
2959 | UNIQUE_CURR_POS(sym->s_set_pos); | 2959 | UNIQUE_CURR_POS(sym->s_set_pos); | |
2960 | } | 2960 | } | |
2961 | } | 2961 | } | |
2962 | 2962 | |||
2963 | /* | 2963 | /* | |
2964 | * Mark an object as used if it is not already | 2964 | * Mark an object as used if it is not already | |
2965 | */ | 2965 | */ | |
2966 | void | 2966 | void | |
2967 | mark_as_used(sym_t *sym, bool fcall, bool szof) | 2967 | mark_as_used(sym_t *sym, bool fcall, bool szof) | |
2968 | { | 2968 | { | |
2969 | 2969 | |||
2970 | if (!sym->s_used) { | 2970 | if (!sym->s_used) { | |
2971 | sym->s_used = true; | 2971 | sym->s_used = true; | |
2972 | UNIQUE_CURR_POS(sym->s_use_pos); | 2972 | UNIQUE_CURR_POS(sym->s_use_pos); | |
2973 | } | 2973 | } | |
2974 | /* | 2974 | /* | |
2975 | * for function calls another record is written | 2975 | * for function calls another record is written | |
2976 | * | 2976 | * | |
2977 | * XXX Should symbols used in sizeof() be treated as used or not? | 2977 | * XXX Should symbols used in sizeof() be treated as used or not? | |
2978 | * Probably not, because there is no sense to declare an | 2978 | * Probably not, because there is no sense to declare an | |
2979 | * external variable only to get their size. | 2979 | * external variable only to get their size. | |
2980 | */ | 2980 | */ | |
2981 | if (!fcall && !szof && sym->s_kind == FVFT && sym->s_scl == EXTERN) | 2981 | if (!fcall && !szof && sym->s_kind == FVFT && sym->s_scl == EXTERN) | |
2982 | outusg(sym); | 2982 | outusg(sym); | |
2983 | } | 2983 | } | |
2984 | 2984 | |||
2985 | /* | 2985 | /* | |
2986 | * Prints warnings for a list of variables and labels (concatenated | 2986 | * Prints warnings for a list of variables and labels (concatenated | |
2987 | * with s_dlnxt) if these are not used or only set. | 2987 | * with s_level_next) if these are not used or only set. | |
2988 | */ | 2988 | */ | |
2989 | void | 2989 | void | |
2990 | check_usage(dinfo_t *di) | 2990 | check_usage(dinfo_t *di) | |
2991 | { | 2991 | { | |
2992 | sym_t *sym; | 2992 | sym_t *sym; | |
2993 | int mklwarn; | 2993 | int mklwarn; | |
2994 | 2994 | |||
2995 | /* for this warning LINTED has no effect */ | 2995 | /* for this warning LINTED has no effect */ | |
2996 | mklwarn = lwarn; | 2996 | mklwarn = lwarn; | |
2997 | lwarn = LWARN_ALL; | 2997 | lwarn = LWARN_ALL; | |
2998 | 2998 | |||
2999 | debug_step("begin lwarn %d", lwarn); | 2999 | debug_step("begin lwarn %d", lwarn); | |
3000 | for (sym = di->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) | 3000 | for (sym = di->d_dlsyms; sym != NULL; sym = sym->s_level_next) | |
3001 | check_usage_sym(di->d_asm, sym); | 3001 | check_usage_sym(di->d_asm, sym); | |
3002 | lwarn = mklwarn; | 3002 | lwarn = mklwarn; | |
3003 | debug_step("end lwarn %d", lwarn); | 3003 | debug_step("end lwarn %d", lwarn); | |
3004 | } | 3004 | } | |
3005 | 3005 | |||
3006 | /* | 3006 | /* | |
3007 | * Prints a warning for a single variable or label if it is not used or | 3007 | * Prints a warning for a single variable or label if it is not used or | |
3008 | * only set. | 3008 | * only set. | |
3009 | */ | 3009 | */ | |
3010 | void | 3010 | void | |
3011 | check_usage_sym(bool novar, sym_t *sym) | 3011 | check_usage_sym(bool novar, sym_t *sym) | |
3012 | { | 3012 | { | |
3013 | 3013 | |||
3014 | if (sym->s_block_level == -1) | 3014 | if (sym->s_block_level == -1) | |
3015 | return; | 3015 | return; | |
3016 | 3016 | |||
3017 | if (sym->s_kind == FVFT && sym->s_arg) | 3017 | if (sym->s_kind == FVFT && sym->s_arg) | |
3018 | check_argument_usage(novar, sym); | 3018 | check_argument_usage(novar, sym); | |
3019 | else if (sym->s_kind == FVFT) | 3019 | else if (sym->s_kind == FVFT) | |
3020 | check_variable_usage(novar, sym); | 3020 | check_variable_usage(novar, sym); | |
3021 | else if (sym->s_kind == FLABEL) | 3021 | else if (sym->s_kind == FLABEL) | |
3022 | check_label_usage(sym); | 3022 | check_label_usage(sym); | |
3023 | else if (sym->s_kind == FTAG) | 3023 | else if (sym->s_kind == FTAG) | |
3024 | check_tag_usage(sym); | 3024 | check_tag_usage(sym); | |
3025 | } | 3025 | } | |
3026 | 3026 | |||
3027 | static void | 3027 | static void | |
3028 | check_argument_usage(bool novar, sym_t *arg) | 3028 | check_argument_usage(bool novar, sym_t *arg) | |
3029 | { | 3029 | { | |
3030 | 3030 | |||
3031 | lint_assert(arg->s_set); | 3031 | lint_assert(arg->s_set); | |
3032 | 3032 | |||
3033 | if (novar) | 3033 | if (novar) | |
3034 | return; | 3034 | return; | |
3035 | 3035 | |||
3036 | if (!arg->s_used && vflag) { | 3036 | if (!arg->s_used && vflag) { | |
3037 | /* argument '%s' unused in function '%s' */ | 3037 | /* argument '%s' unused in function '%s' */ | |
3038 | warning_at(231, &arg->s_def_pos, arg->s_name, funcsym->s_name); | 3038 | warning_at(231, &arg->s_def_pos, arg->s_name, funcsym->s_name); | |
3039 | } | 3039 | } | |
3040 | } | 3040 | } | |
3041 | 3041 | |||
3042 | static void | 3042 | static void | |
3043 | check_variable_usage(bool novar, sym_t *sym) | 3043 | check_variable_usage(bool novar, sym_t *sym) | |
3044 | { | 3044 | { | |
3045 | scl_t sc; | 3045 | scl_t sc; | |
3046 | sym_t *xsym; | 3046 | sym_t *xsym; | |
3047 | 3047 | |||
3048 | lint_assert(block_level != 0); | 3048 | lint_assert(block_level != 0); | |
3049 | 3049 | |||
3050 | /* example at file scope: int c = ({ return 3; }); */ | 3050 | /* example at file scope: int c = ({ return 3; }); */ | |
3051 | if (sym->s_block_level == 0 && ch_isdigit(sym->s_name[0])) | 3051 | if (sym->s_block_level == 0 && ch_isdigit(sym->s_name[0])) | |
3052 | return; | 3052 | return; | |
3053 | 3053 | |||
3054 | /* errors in expressions easily cause lots of these warnings */ | 3054 | /* errors in expressions easily cause lots of these warnings */ | |
3055 | if (nerr != 0) | 3055 | if (nerr != 0) | |
3056 | return; | 3056 | return; | |
3057 | 3057 | |||
3058 | /* | 3058 | /* | |
3059 | * XXX Only variables are checked, although types should | 3059 | * XXX Only variables are checked, although types should | |
3060 | * probably also be checked | 3060 | * probably also be checked | |
3061 | */ | 3061 | */ | |
3062 | if ((sc = sym->s_scl) != EXTERN && sc != STATIC && | 3062 | if ((sc = sym->s_scl) != EXTERN && sc != STATIC && | |
3063 | sc != AUTO && sc != REG) { | 3063 | sc != AUTO && sc != REG) { | |
3064 | return; | 3064 | return; | |
3065 | } | 3065 | } | |
3066 | 3066 | |||
3067 | if (novar) | 3067 | if (novar) | |
3068 | return; | 3068 | return; | |
3069 | 3069 | |||
3070 | if (sc == EXTERN) { | 3070 | if (sc == EXTERN) { | |
3071 | if (!sym->s_used && !sym->s_set) { | 3071 | if (!sym->s_used && !sym->s_set) { | |
3072 | /* '%s' unused in function '%s' */ | 3072 | /* '%s' unused in function '%s' */ | |
3073 | warning_at(192, &sym->s_def_pos, | 3073 | warning_at(192, &sym->s_def_pos, | |
3074 | sym->s_name, funcsym->s_name); | 3074 | sym->s_name, funcsym->s_name); | |
3075 | } | 3075 | } | |
3076 | } else { | 3076 | } else { | |
3077 | if (sym->s_set && !sym->s_used) { | 3077 | if (sym->s_set && !sym->s_used) { | |
3078 | /* '%s' set but not used in function '%s' */ | 3078 | /* '%s' set but not used in function '%s' */ | |
3079 | warning_at(191, &sym->s_set_pos, | 3079 | warning_at(191, &sym->s_set_pos, | |
3080 | sym->s_name, funcsym->s_name); | 3080 | sym->s_name, funcsym->s_name); | |
3081 | } else if (!sym->s_used) { | 3081 | } else if (!sym->s_used) { | |
3082 | /* '%s' unused in function '%s' */ | 3082 | /* '%s' unused in function '%s' */ | |
3083 | warning_at(192, &sym->s_def_pos, | 3083 | warning_at(192, &sym->s_def_pos, | |
3084 | sym->s_name, funcsym->s_name); | 3084 | sym->s_name, funcsym->s_name); | |
3085 | } | 3085 | } | |
3086 | } | 3086 | } | |
3087 | 3087 | |||
3088 | if (sc == EXTERN) { | 3088 | if (sc == EXTERN) { | |
3089 | /* | 3089 | /* | |
3090 | * information about usage is taken over into the symbol | 3090 | * information about usage is taken over into the symbol | |
3091 | * table entry at level 0 if the symbol was locally declared | 3091 | * table entry at level 0 if the symbol was locally declared | |
3092 | * as an external symbol. | 3092 | * as an external symbol. | |
3093 | * | 3093 | * | |
3094 | * XXX This is wrong for symbols declared static at level 0 | 3094 | * XXX This is wrong for symbols declared static at level 0 | |
3095 | * if the usage information stems from sizeof(). This is | 3095 | * if the usage information stems from sizeof(). This is | |
3096 | * because symbols at level 0 only used in sizeof() are | 3096 | * because symbols at level 0 only used in sizeof() are | |
3097 | * considered to not be used. | 3097 | * considered to not be used. | |
3098 | */ | 3098 | */ | |
3099 | if ((xsym = sym->s_ext_sym) != NULL) { | 3099 | if ((xsym = sym->s_ext_sym) != NULL) { | |
3100 | if (sym->s_used && !xsym->s_used) { | 3100 | if (sym->s_used && !xsym->s_used) { | |
3101 | xsym->s_used = true; | 3101 | xsym->s_used = true; | |
3102 | xsym->s_use_pos = sym->s_use_pos; | 3102 | xsym->s_use_pos = sym->s_use_pos; | |
3103 | } | 3103 | } | |
3104 | if (sym->s_set && !xsym->s_set) { | 3104 | if (sym->s_set && !xsym->s_set) { | |
3105 | xsym->s_set = true; | 3105 | xsym->s_set = true; | |
3106 | xsym->s_set_pos = sym->s_set_pos; | 3106 | xsym->s_set_pos = sym->s_set_pos; | |
3107 | } | 3107 | } | |
3108 | } | 3108 | } | |
3109 | } | 3109 | } | |
3110 | } | 3110 | } | |
3111 | 3111 | |||
3112 | static void | 3112 | static void | |
3113 | check_label_usage(sym_t *lab) | 3113 | check_label_usage(sym_t *lab) | |
3114 | { | 3114 | { | |
3115 | 3115 | |||
3116 | lint_assert(block_level == 1); | 3116 | lint_assert(block_level == 1); | |
3117 | lint_assert(lab->s_block_level == 1); | 3117 | lint_assert(lab->s_block_level == 1); | |
3118 | 3118 | |||
3119 | if (lab->s_set && !lab->s_used) { | 3119 | if (lab->s_set && !lab->s_used) { | |
3120 | /* label '%s' unused in function '%s' */ | 3120 | /* label '%s' unused in function '%s' */ | |
3121 | warning_at(232, &lab->s_set_pos, lab->s_name, funcsym->s_name); | 3121 | warning_at(232, &lab->s_set_pos, lab->s_name, funcsym->s_name); | |
3122 | } else if (!lab->s_set) { | 3122 | } else if (!lab->s_set) { | |
3123 | /* undefined label '%s' */ | 3123 | /* undefined label '%s' */ | |
3124 | warning_at(23, &lab->s_use_pos, lab->s_name); | 3124 | warning_at(23, &lab->s_use_pos, lab->s_name); | |
3125 | } | 3125 | } | |
3126 | } | 3126 | } | |
3127 | 3127 | |||
3128 | static void | 3128 | static void | |
3129 | check_tag_usage(sym_t *sym) | 3129 | check_tag_usage(sym_t *sym) | |
3130 | { | 3130 | { | |
3131 | 3131 | |||
3132 | if (!is_incomplete(sym->s_type)) | 3132 | if (!is_incomplete(sym->s_type)) | |
3133 | return; | 3133 | return; | |
3134 | 3134 | |||
3135 | /* always complain about incomplete tags declared inside blocks */ | 3135 | /* always complain about incomplete tags declared inside blocks */ | |
3136 | if (!zflag || dcs->d_ctx != EXTERN) | 3136 | if (!zflag || dcs->d_ctx != EXTERN) | |
3137 | return; | 3137 | return; | |
3138 | 3138 | |||
3139 | switch (sym->s_type->t_tspec) { | 3139 | switch (sym->s_type->t_tspec) { | |
3140 | case STRUCT: | 3140 | case STRUCT: | |
3141 | /* struct %s never defined */ | 3141 | /* struct %s never defined */ | |
3142 | warning_at(233, &sym->s_def_pos, sym->s_name); | 3142 | warning_at(233, &sym->s_def_pos, sym->s_name); | |
3143 | break; | 3143 | break; | |
3144 | case UNION: | 3144 | case UNION: | |
3145 | /* union %s never defined */ | 3145 | /* union %s never defined */ | |
3146 | warning_at(234, &sym->s_def_pos, sym->s_name); | 3146 | warning_at(234, &sym->s_def_pos, sym->s_name); | |
3147 | break; | 3147 | break; | |
3148 | case ENUM: | 3148 | case ENUM: | |
3149 | /* enum %s never defined */ | 3149 | /* enum %s never defined */ | |
3150 | warning_at(235, &sym->s_def_pos, sym->s_name); | 3150 | warning_at(235, &sym->s_def_pos, sym->s_name); | |
3151 | break; | 3151 | break; | |
3152 | default: | 3152 | default: | |
3153 | lint_assert(/*CONSTCOND*/false); | 3153 | lint_assert(/*CONSTCOND*/false); | |
3154 | } | 3154 | } | |
3155 | } | 3155 | } | |
3156 | 3156 | |||
3157 | /* | 3157 | /* | |
3158 | * Called after the entire translation unit has been parsed. | 3158 | * Called after the entire translation unit has been parsed. | |
3159 | * Changes tentative definitions into definitions. | 3159 | * Changes tentative definitions into definitions. | |
3160 | * Performs some tests on global symbols. Detected problems are: | 3160 | * Performs some tests on global symbols. Detected problems are: | |
3161 | * - defined variables of incomplete type | 3161 | * - defined variables of incomplete type | |
3162 | * - constant variables which are not initialized | 3162 | * - constant variables which are not initialized | |
3163 | * - static symbols which are never used | 3163 | * - static symbols which are never used | |
3164 | */ | 3164 | */ | |
3165 | void | 3165 | void | |
3166 | check_global_symbols(void) | 3166 | check_global_symbols(void) | |
3167 | { | 3167 | { | |
3168 | sym_t *sym; | 3168 | sym_t *sym; | |
3169 | 3169 | |||
3170 | if (block_level != 0 || dcs->d_next != NULL) | 3170 | if (block_level != 0 || dcs->d_next != NULL) | |
3171 | norecover(); | 3171 | norecover(); | |
3172 | 3172 | |||
3173 | for (sym = dcs->d_dlsyms; sym != NULL; sym = sym->s_dlnxt) { | 3173 | for (sym = dcs->d_dlsyms; sym != NULL; sym = sym->s_level_next) { | |
3174 | if (sym->s_block_level == -1) | 3174 | if (sym->s_block_level == -1) | |
3175 | continue; | 3175 | continue; | |
3176 | if (sym->s_kind == FVFT) { | 3176 | if (sym->s_kind == FVFT) { | |
3177 | check_global_variable(sym); | 3177 | check_global_variable(sym); | |
3178 | } else if (sym->s_kind == FTAG) { | 3178 | } else if (sym->s_kind == FTAG) { | |
3179 | check_tag_usage(sym); | 3179 | check_tag_usage(sym); | |
3180 | } else { | 3180 | } else { | |
3181 | lint_assert(sym->s_kind == FMEMBER); | 3181 | lint_assert(sym->s_kind == FMEMBER); | |
3182 | } | 3182 | } | |
3183 | } | 3183 | } | |
3184 | } | 3184 | } | |
3185 | 3185 | |||
3186 | static void | 3186 | static void | |
3187 | check_unused_static_global_variable(const sym_t *sym) | 3187 | check_unused_static_global_variable(const sym_t *sym) | |
3188 | { | 3188 | { | |
3189 | if (sym->s_type->t_tspec == FUNC) { | 3189 | if (sym->s_type->t_tspec == FUNC) { | |
3190 | if (sym->s_def == DEF) { | 3190 | if (sym->s_def == DEF) { | |
3191 | if (!sym->s_inline) | 3191 | if (!sym->s_inline) | |
3192 | /* static function %s unused */ | 3192 | /* static function %s unused */ | |
3193 | warning_at(236, &sym->s_def_pos, sym->s_name); | 3193 | warning_at(236, &sym->s_def_pos, sym->s_name); | |
3194 | } else { | 3194 | } else { | |
3195 | /* static function %s declared but not defined */ | 3195 | /* static function %s declared but not defined */ | |
3196 | warning_at(290, &sym->s_def_pos, sym->s_name); | 3196 | warning_at(290, &sym->s_def_pos, sym->s_name); | |
3197 | } | 3197 | } | |
3198 | } else if (!sym->s_set) { | 3198 | } else if (!sym->s_set) { | |
3199 | /* static variable %s unused */ | 3199 | /* static variable %s unused */ | |
3200 | warning_at(226, &sym->s_def_pos, sym->s_name); | 3200 | warning_at(226, &sym->s_def_pos, sym->s_name); | |
3201 | } else { | 3201 | } else { | |
3202 | /* static variable %s set but not used */ | 3202 | /* static variable %s set but not used */ | |
3203 | warning_at(307, &sym->s_def_pos, sym->s_name); | 3203 | warning_at(307, &sym->s_def_pos, sym->s_name); | |
3204 | } | 3204 | } | |
3205 | } | 3205 | } | |
3206 | 3206 | |||
3207 | static void | 3207 | static void | |
3208 | check_static_global_variable(const sym_t *sym) | 3208 | check_static_global_variable(const sym_t *sym) | |
3209 | { | 3209 | { | |
3210 | if (sym->s_type->t_tspec == FUNC && sym->s_used && sym->s_def != DEF) { | 3210 | if (sym->s_type->t_tspec == FUNC && sym->s_used && sym->s_def != DEF) { | |
3211 | /* static function called but not defined: %s() */ | 3211 | /* static function called but not defined: %s() */ | |
3212 | error_at(225, &sym->s_use_pos, sym->s_name); | 3212 | error_at(225, &sym->s_use_pos, sym->s_name); | |
3213 | } | 3213 | } | |
3214 | 3214 | |||
3215 | if (!sym->s_used) | 3215 | if (!sym->s_used) | |
3216 | check_unused_static_global_variable(sym); | 3216 | check_unused_static_global_variable(sym); | |
3217 | 3217 | |||
3218 | if (!tflag && sym->s_def == TDEF && sym->s_type->t_const) { | 3218 | if (!tflag && sym->s_def == TDEF && sym->s_type->t_const) { | |
3219 | /* const object %s should have initializer */ | 3219 | /* const object %s should have initializer */ | |
3220 | warning_at(227, &sym->s_def_pos, sym->s_name); | 3220 | warning_at(227, &sym->s_def_pos, sym->s_name); | |
3221 | } | 3221 | } | |
3222 | } | 3222 | } | |
3223 | 3223 | |||
3224 | static void | 3224 | static void | |
3225 | check_global_variable(const sym_t *sym) | 3225 | check_global_variable(const sym_t *sym) | |
3226 | { | 3226 | { | |
3227 | 3227 | |||
3228 | if (sym->s_scl == TYPEDEF || sym->s_scl == CTCONST) | 3228 | if (sym->s_scl == TYPEDEF || sym->s_scl == CTCONST) | |
3229 | return; | 3229 | return; | |
3230 | 3230 | |||
3231 | if (sym->s_scl == NOSCL) | 3231 | if (sym->s_scl == NOSCL) | |
3232 | return; /* May be caused by a syntax error. */ | 3232 | return; /* May be caused by a syntax error. */ | |
3233 | 3233 | |||
3234 | lint_assert(sym->s_scl == EXTERN || sym->s_scl == STATIC); | 3234 | lint_assert(sym->s_scl == EXTERN || sym->s_scl == STATIC); | |
3235 | 3235 | |||
3236 | check_global_variable_size(sym); | 3236 | check_global_variable_size(sym); | |
3237 | 3237 | |||
3238 | if (sym->s_scl == STATIC) | 3238 | if (sym->s_scl == STATIC) | |
3239 | check_static_global_variable(sym); | 3239 | check_static_global_variable(sym); | |
3240 | } | 3240 | } | |
3241 | 3241 | |||
3242 | static void | 3242 | static void | |
3243 | check_global_variable_size(const sym_t *sym) | 3243 | check_global_variable_size(const sym_t *sym) | |
3244 | { | 3244 | { | |
3245 | pos_t cpos; | 3245 | pos_t cpos; | |
3246 | int length_in_bits; | 3246 | int length_in_bits; | |
3247 | 3247 | |||
3248 | if (sym->s_def != TDEF) | 3248 | if (sym->s_def != TDEF) | |
3249 | return; | 3249 | return; | |
3250 | if (sym->s_type->t_tspec == FUNC) | 3250 | if (sym->s_type->t_tspec == FUNC) | |
3251 | /* | 3251 | /* | |
3252 | * this can happen if a syntax error occurred after a | 3252 | * this can happen if a syntax error occurred after a | |
3253 | * function declaration | 3253 | * function declaration | |
3254 | */ | 3254 | */ | |
3255 | return; | 3255 | return; | |
3256 | if (sym->s_def == TDEF && sym->s_type->t_tspec == VOID) | 3256 | if (sym->s_def == TDEF && sym->s_type->t_tspec == VOID) | |
3257 | return; /* prevent internal error in length() below */ | 3257 | return; /* prevent internal error in length() below */ | |
3258 | 3258 | |||
3259 | cpos = curr_pos; | 3259 | cpos = curr_pos; | |
3260 | curr_pos = sym->s_def_pos; | 3260 | curr_pos = sym->s_def_pos; | |
3261 | length_in_bits = length(sym->s_type, sym->s_name); | 3261 | length_in_bits = length(sym->s_type, sym->s_name); | |
3262 | curr_pos = cpos; | 3262 | curr_pos = cpos; | |
3263 | 3263 | |||
3264 | if (length_in_bits == 0 && | 3264 | if (length_in_bits == 0 && | |
3265 | sym->s_type->t_tspec == ARRAY && sym->s_type->t_dim == 0) { | 3265 | sym->s_type->t_tspec == ARRAY && sym->s_type->t_dim == 0) { | |
3266 | if (tflag || (sym->s_scl == EXTERN && !sflag)) { | 3266 | if (tflag || (sym->s_scl == EXTERN && !sflag)) { | |
3267 | /* empty array declaration: %s */ | 3267 | /* empty array declaration: %s */ | |
3268 | warning_at(190, &sym->s_def_pos, sym->s_name); | 3268 | warning_at(190, &sym->s_def_pos, sym->s_name); | |
3269 | } else { | 3269 | } else { | |
3270 | /* empty array declaration: %s */ | 3270 | /* empty array declaration: %s */ | |
3271 | error_at(190, &sym->s_def_pos, sym->s_name); | 3271 | error_at(190, &sym->s_def_pos, sym->s_name); | |
3272 | } | 3272 | } | |
3273 | } | 3273 | } | |
3274 | } | 3274 | } | |
3275 | 3275 | |||
3276 | /* | 3276 | /* | |
3277 | * Prints information about location of previous definition/declaration. | 3277 | * Prints information about location of previous definition/declaration. | |
3278 | */ | 3278 | */ | |
3279 | void | 3279 | void | |
3280 | print_previous_declaration(int msg, const sym_t *psym) | 3280 | print_previous_declaration(int msg, const sym_t *psym) | |
3281 | { | 3281 | { | |
3282 | 3282 | |||
3283 | if (!rflag) | 3283 | if (!rflag) | |
3284 | return; | 3284 | return; | |
3285 | 3285 | |||
3286 | if (msg != -1) { | 3286 | if (msg != -1) { | |
3287 | (message_at)(msg, &psym->s_def_pos); | 3287 | (message_at)(msg, &psym->s_def_pos); | |
3288 | } else if (psym->s_def == DEF || psym->s_def == TDEF) { | 3288 | } else if (psym->s_def == DEF || psym->s_def == TDEF) { | |
3289 | /* previous definition of %s */ | 3289 | /* previous definition of %s */ | |
3290 | message_at(261, &psym->s_def_pos, psym->s_name); | 3290 | message_at(261, &psym->s_def_pos, psym->s_name); | |
3291 | } else { | 3291 | } else { | |
3292 | /* previous declaration of %s */ | 3292 | /* previous declaration of %s */ | |
3293 | message_at(260, &psym->s_def_pos, psym->s_name); | 3293 | message_at(260, &psym->s_def_pos, psym->s_name); | |
3294 | } | 3294 | } | |
3295 | } | 3295 | } | |
3296 | 3296 | |||
3297 | /* | 3297 | /* | |
3298 | * Gets a node for a constant and returns the value of this constant | 3298 | * Gets a node for a constant and returns the value of this constant | |
3299 | * as integer. | 3299 | * as integer. | |
3300 | * | 3300 | * | |
3301 | * If the node is not constant or too large for int or of type float, | 3301 | * If the node is not constant or too large for int or of type float, | |
3302 | * a warning will be printed. | 3302 | * a warning will be printed. | |
3303 | * | 3303 | * | |
3304 | * to_int_constant() should be used only inside declarations. If it is used in | 3304 | * to_int_constant() should be used only inside declarations. If it is used in | |
3305 | * expressions, it frees the memory used for the expression. | 3305 | * expressions, it frees the memory used for the expression. | |
3306 | */ | 3306 | */ | |
3307 | int | 3307 | int | |
3308 | to_int_constant(tnode_t *tn, bool required) | 3308 | to_int_constant(tnode_t *tn, bool required) | |
3309 | { | 3309 | { | |
3310 | int i; | 3310 | int i; | |
3311 | tspec_t t; | 3311 | tspec_t t; | |
3312 | val_t *v; | 3312 | val_t *v; | |
3313 | 3313 | |||
3314 | v = constant(tn, required); | 3314 | v = constant(tn, required); | |
3315 | 3315 | |||
3316 | if (tn == NULL) { | 3316 | if (tn == NULL) { | |
3317 | i = 1; | 3317 | i = 1; | |
3318 | goto done; | 3318 | goto done; | |
3319 | } | 3319 | } | |
3320 | 3320 | |||
3321 | /* | 3321 | /* | |
3322 | * Abstract declarations are used inside expression. To free | 3322 | * Abstract declarations are used inside expression. To free | |
3323 | * the memory would be a fatal error. | 3323 | * the memory would be a fatal error. | |
3324 | * We don't free blocks that are inside casts because these | 3324 | * We don't free blocks that are inside casts because these | |
3325 | * will be used later to match types. | 3325 | * will be used later to match types. | |
3326 | */ | 3326 | */ | |
3327 | if (tn->tn_op != CON && dcs->d_ctx != ABSTRACT) | 3327 | if (tn->tn_op != CON && dcs->d_ctx != ABSTRACT) | |
3328 | expr_free_all(); | 3328 | expr_free_all(); | |
3329 | 3329 | |||
3330 | if ((t = v->v_tspec) == FLOAT || t == DOUBLE || t == LDOUBLE) { | 3330 | if ((t = v->v_tspec) == FLOAT || t == DOUBLE || t == LDOUBLE) { | |
3331 | i = (int)v->v_ldbl; | 3331 | i = (int)v->v_ldbl; | |
3332 | /* integral constant expression expected */ | 3332 | /* integral constant expression expected */ | |
3333 | error(55); | 3333 | error(55); | |
3334 | } else { | 3334 | } else { | |
3335 | i = (int)v->v_quad; | 3335 | i = (int)v->v_quad; | |
3336 | if (is_uinteger(t)) { | 3336 | if (is_uinteger(t)) { | |
3337 | if ((uint64_t)v->v_quad > (uint64_t)TARG_INT_MAX) { | 3337 | if ((uint64_t)v->v_quad > (uint64_t)TARG_INT_MAX) { | |
3338 | /* integral constant too large */ | 3338 | /* integral constant too large */ | |
3339 | warning(56); | 3339 | warning(56); | |
3340 | } | 3340 | } | |
3341 | } else { | 3341 | } else { | |
3342 | if (v->v_quad > (int64_t)TARG_INT_MAX || | 3342 | if (v->v_quad > (int64_t)TARG_INT_MAX || | |
3343 | v->v_quad < (int64_t)TARG_INT_MIN) { | 3343 | v->v_quad < (int64_t)TARG_INT_MIN) { | |
3344 | /* integral constant too large */ | 3344 | /* integral constant too large */ | |
3345 | warning(56); | 3345 | warning(56); | |
3346 | } | 3346 | } | |
3347 | } | 3347 | } | |
3348 | } | 3348 | } | |
3349 | 3349 | |||
3350 | done: | 3350 | done: | |
3351 | free(v); | 3351 | free(v); | |
3352 | return i; | 3352 | return i; | |
3353 | } | 3353 | } |
--- src/usr.bin/xlint/lint1/func.c 2022/02/27 08:31:26 1.127
+++ src/usr.bin/xlint/lint1/func.c 2022/02/27 10:44:45 1.128
@@ -1,1237 +1,1238 @@ | @@ -1,1237 +1,1238 @@ | |||
1 | /* $NetBSD: func.c,v 1.127 2022/02/27 08:31:26 rillig Exp $ */ | 1 | /* $NetBSD: func.c,v 1.128 2022/02/27 10:44:45 rillig Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1994, 1995 Jochen Pohl | 4 | * Copyright (c) 1994, 1995 Jochen Pohl | |
5 | * All Rights Reserved. | 5 | * All Rights Reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. All advertising materials mentioning features or use of this software | 15 | * 3. All advertising materials mentioning features or use of this software | |
16 | * must display the following acknowledgement: | 16 | * must display the following acknowledgement: | |
17 | * This product includes software developed by Jochen Pohl for | 17 | * This product includes software developed by Jochen Pohl for | |
18 | * The NetBSD Project. | 18 | * The NetBSD Project. | |
19 | * 4. The name of the author may not be used to endorse or promote products | 19 | * 4. The name of the author may not be used to endorse or promote products | |
20 | * derived from this software without specific prior written permission. | 20 | * derived from this software without specific prior written permission. | |
21 | * | 21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #if HAVE_NBTOOL_CONFIG_H | 34 | #if HAVE_NBTOOL_CONFIG_H | |
35 | #include "nbtool_config.h" | 35 | #include "nbtool_config.h" | |
36 | #endif | 36 | #endif | |
37 | 37 | |||
38 | #include <sys/cdefs.h> | 38 | #include <sys/cdefs.h> | |
39 | #if defined(__RCSID) && !defined(lint) | 39 | #if defined(__RCSID) && !defined(lint) | |
40 | __RCSID("$NetBSD: func.c,v 1.127 2022/02/27 08:31:26 rillig Exp $"); | 40 | __RCSID("$NetBSD: func.c,v 1.128 2022/02/27 10:44:45 rillig Exp $"); | |
41 | #endif | 41 | #endif | |
42 | 42 | |||
43 | #include <stdlib.h> | 43 | #include <stdlib.h> | |
44 | #include <string.h> | 44 | #include <string.h> | |
45 | 45 | |||
46 | #include "lint1.h" | 46 | #include "lint1.h" | |
47 | #include "cgram.h" | 47 | #include "cgram.h" | |
48 | 48 | |||
49 | /* | 49 | /* | |
50 | * Contains a pointer to the symbol table entry of the current function | 50 | * Contains a pointer to the symbol table entry of the current function | |
51 | * definition. | 51 | * definition. | |
52 | */ | 52 | */ | |
53 | sym_t *funcsym; | 53 | sym_t *funcsym; | |
54 | 54 | |||
55 | /* Is set as long as a statement can be reached. Must be set at level 0. */ | 55 | /* Is set as long as a statement can be reached. Must be set at level 0. */ | |
56 | bool reached = true; | 56 | bool reached = true; | |
57 | 57 | |||
58 | /* | 58 | /* | |
59 | * Is true by default, can be cleared by NOTREACHED. | 59 | * Is true by default, can be cleared by NOTREACHED. | |
60 | * Is reset to true whenever 'reached' changes. | 60 | * Is reset to true whenever 'reached' changes. | |
61 | */ | 61 | */ | |
62 | bool warn_about_unreachable; | 62 | bool warn_about_unreachable; | |
63 | 63 | |||
64 | /* | 64 | /* | |
65 | * In conjunction with 'reached', controls printing of "fallthrough on ..." | 65 | * In conjunction with 'reached', controls printing of "fallthrough on ..." | |
66 | * warnings. | 66 | * warnings. | |
67 | * Reset by each statement and set by FALLTHROUGH, switch (switch1()) | 67 | * Reset by each statement and set by FALLTHROUGH, switch (switch1()) | |
68 | * and case (label()). | 68 | * and case (label()). | |
69 | * | 69 | * | |
70 | * Control statements if, for, while and switch do not reset seen_fallthrough | 70 | * Control statements if, for, while and switch do not reset seen_fallthrough | |
71 | * because this must be done by the controlled statement. At least for if this | 71 | * because this must be done by the controlled statement. At least for if this | |
72 | * is important because ** FALLTHROUGH ** after "if (expr) statement" is | 72 | * is important because ** FALLTHROUGH ** after "if (expr) statement" is | |
73 | * evaluated before the following token, which causes reduction of above. | 73 | * evaluated before the following token, which causes reduction of above. | |
74 | * This means that ** FALLTHROUGH ** after "if ..." would always be ignored. | 74 | * This means that ** FALLTHROUGH ** after "if ..." would always be ignored. | |
75 | */ | 75 | */ | |
76 | bool seen_fallthrough; | 76 | bool seen_fallthrough; | |
77 | 77 | |||
78 | /* The innermost control statement */ | 78 | /* The innermost control statement */ | |
79 | control_statement *cstmt; | 79 | control_statement *cstmt; | |
80 | 80 | |||
81 | /* | 81 | /* | |
82 | * Number of arguments which will be checked for usage in following | 82 | * Number of arguments which will be checked for usage in following | |
83 | * function definition. -1 stands for all arguments. | 83 | * function definition. -1 stands for all arguments. | |
84 | * | 84 | * | |
85 | * The position of the last ARGSUSED comment is stored in argsused_pos. | 85 | * The position of the last ARGSUSED comment is stored in argsused_pos. | |
86 | */ | 86 | */ | |
87 | int nargusg = -1; | 87 | int nargusg = -1; | |
88 | pos_t argsused_pos; | 88 | pos_t argsused_pos; | |
89 | 89 | |||
90 | /* | 90 | /* | |
91 | * Number of arguments of the following function definition whose types | 91 | * Number of arguments of the following function definition whose types | |
92 | * shall be checked by lint2. -1 stands for all arguments. | 92 | * shall be checked by lint2. -1 stands for all arguments. | |
93 | * | 93 | * | |
94 | * The position of the last VARARGS comment is stored in vapos. | 94 | * The position of the last VARARGS comment is stored in vapos. | |
95 | */ | 95 | */ | |
96 | int nvararg = -1; | 96 | int nvararg = -1; | |
97 | pos_t vapos; | 97 | pos_t vapos; | |
98 | 98 | |||
99 | /* | 99 | /* | |
100 | * Both printflike_argnum and scanflike_argnum contain the 1-based number | 100 | * Both printflike_argnum and scanflike_argnum contain the 1-based number | |
101 | * of the string argument which shall be used to check the types of remaining | 101 | * of the string argument which shall be used to check the types of remaining | |
102 | * arguments (for PRINTFLIKE and SCANFLIKE). | 102 | * arguments (for PRINTFLIKE and SCANFLIKE). | |
103 | * | 103 | * | |
104 | * printflike_pos and scanflike_pos are the positions of the last PRINTFLIKE | 104 | * printflike_pos and scanflike_pos are the positions of the last PRINTFLIKE | |
105 | * or SCANFLIKE comment. | 105 | * or SCANFLIKE comment. | |
106 | */ | 106 | */ | |
107 | int printflike_argnum = -1; | 107 | int printflike_argnum = -1; | |
108 | int scanflike_argnum = -1; | 108 | int scanflike_argnum = -1; | |
109 | pos_t printflike_pos; | 109 | pos_t printflike_pos; | |
110 | pos_t scanflike_pos; | 110 | pos_t scanflike_pos; | |
111 | 111 | |||
112 | /* | 112 | /* | |
113 | * If both plibflg and llibflg are set, prototypes are written as function | 113 | * If both plibflg and llibflg are set, prototypes are written as function | |
114 | * definitions to the output file. | 114 | * definitions to the output file. | |
115 | */ | 115 | */ | |
116 | bool plibflg; | 116 | bool plibflg; | |
117 | 117 | |||
118 | /* | 118 | /* | |
119 | * True means that no warnings about constants in conditional | 119 | * True means that no warnings about constants in conditional | |
120 | * context are printed. | 120 | * context are printed. | |
121 | */ | 121 | */ | |
122 | bool constcond_flag; | 122 | bool constcond_flag; | |
123 | 123 | |||
124 | /* | 124 | /* | |
125 | * llibflg is set if a lint library shall be created. The effect of | 125 | * llibflg is set if a lint library shall be created. The effect of | |
126 | * llibflg is that all defined symbols are treated as used. | 126 | * llibflg is that all defined symbols are treated as used. | |
127 | * (The LINTLIBRARY comment also resets vflag.) | 127 | * (The LINTLIBRARY comment also resets vflag.) | |
128 | */ | 128 | */ | |
129 | bool llibflg; | 129 | bool llibflg; | |
130 | 130 | |||
131 | /* | 131 | /* | |
132 | * Nonzero if warnings are suppressed by a LINTED directive | 132 | * Nonzero if warnings are suppressed by a LINTED directive | |
133 | * LWARN_BAD: error | 133 | * LWARN_BAD: error | |
134 | * LWARN_ALL: warnings on | 134 | * LWARN_ALL: warnings on | |
135 | * LWARN_NONE: all warnings ignored | 135 | * LWARN_NONE: all warnings ignored | |
136 | * 0..n: warning n ignored | 136 | * 0..n: warning n ignored | |
137 | */ | 137 | */ | |
138 | int lwarn = LWARN_ALL; | 138 | int lwarn = LWARN_ALL; | |
139 | 139 | |||
140 | /* | 140 | /* | |
141 | * Whether bitfield type errors are suppressed by a BITFIELDTYPE | 141 | * Whether bitfield type errors are suppressed by a BITFIELDTYPE | |
142 | * directive. | 142 | * directive. | |
143 | */ | 143 | */ | |
144 | bool bitfieldtype_ok; | 144 | bool bitfieldtype_ok; | |
145 | 145 | |||
146 | /* | 146 | /* | |
147 | * Whether complaints about use of "long long" are suppressed in | 147 | * Whether complaints about use of "long long" are suppressed in | |
148 | * the next statement or declaration. | 148 | * the next statement or declaration. | |
149 | */ | 149 | */ | |
150 | bool quadflg; | 150 | bool quadflg; | |
151 | 151 | |||
152 | /* | 152 | /* | |
153 | * Puts a new element at the top of the stack used for control statements. | 153 | * Puts a new element at the top of the stack used for control statements. | |
154 | */ | 154 | */ | |
155 | void | 155 | void | |
156 | begin_control_statement(control_statement_kind kind) | 156 | begin_control_statement(control_statement_kind kind) | |
157 | { | 157 | { | |
158 | control_statement *cs; | 158 | control_statement *cs; | |
159 | 159 | |||
160 | cs = xcalloc(1, sizeof(*cs)); | 160 | cs = xcalloc(1, sizeof(*cs)); | |
161 | cs->c_kind = kind; | 161 | cs->c_kind = kind; | |
162 | cs->c_surrounding = cstmt; | 162 | cs->c_surrounding = cstmt; | |
163 | cstmt = cs; | 163 | cstmt = cs; | |
164 | } | 164 | } | |
165 | 165 | |||
166 | /* | 166 | /* | |
167 | * Removes the top element of the stack used for control statements. | 167 | * Removes the top element of the stack used for control statements. | |
168 | */ | 168 | */ | |
169 | void | 169 | void | |
170 | end_control_statement(control_statement_kind kind) | 170 | end_control_statement(control_statement_kind kind) | |
171 | { | 171 | { | |
172 | control_statement *cs; | 172 | control_statement *cs; | |
173 | case_label_t *cl, *next; | 173 | case_label_t *cl, *next; | |
174 | 174 | |||
175 | lint_assert(cstmt != NULL); | 175 | lint_assert(cstmt != NULL); | |
176 | 176 | |||
177 | while (cstmt->c_kind != kind) | 177 | while (cstmt->c_kind != kind) | |
178 | cstmt = cstmt->c_surrounding; | 178 | cstmt = cstmt->c_surrounding; | |
179 | 179 | |||
180 | cs = cstmt; | 180 | cs = cstmt; | |
181 | cstmt = cs->c_surrounding; | 181 | cstmt = cs->c_surrounding; | |
182 | 182 | |||
183 | for (cl = cs->c_case_labels; cl != NULL; cl = next) { | 183 | for (cl = cs->c_case_labels; cl != NULL; cl = next) { | |
184 | next = cl->cl_next; | 184 | next = cl->cl_next; | |
185 | free(cl); | 185 | free(cl); | |
186 | } | 186 | } | |
187 | 187 | |||
188 | free(cs->c_switch_type); | 188 | free(cs->c_switch_type); | |
189 | free(cs); | 189 | free(cs); | |
190 | } | 190 | } | |
191 | 191 | |||
192 | static void | 192 | static void | |
193 | set_reached(bool new_reached) | 193 | set_reached(bool new_reached) | |
194 | { | 194 | { | |
195 | debug_step("%s -> %s", | 195 | debug_step("%s -> %s", | |
196 | reached ? "reachable" : "unreachable", | 196 | reached ? "reachable" : "unreachable", | |
197 | new_reached ? "reachable" : "unreachable"); | 197 | new_reached ? "reachable" : "unreachable"); | |
198 | reached = new_reached; | 198 | reached = new_reached; | |
199 | warn_about_unreachable = true; | 199 | warn_about_unreachable = true; | |
200 | } | 200 | } | |
201 | 201 | |||
202 | /* | 202 | /* | |
203 | * Prints a warning if a statement cannot be reached. | 203 | * Prints a warning if a statement cannot be reached. | |
204 | */ | 204 | */ | |
205 | void | 205 | void | |
206 | check_statement_reachable(void) | 206 | check_statement_reachable(void) | |
207 | { | 207 | { | |
208 | if (!reached && warn_about_unreachable) { | 208 | if (!reached && warn_about_unreachable) { | |
209 | /* statement not reached */ | 209 | /* statement not reached */ | |
210 | warning(193); | 210 | warning(193); | |
211 | warn_about_unreachable = false; | 211 | warn_about_unreachable = false; | |
212 | } | 212 | } | |
213 | } | 213 | } | |
214 | 214 | |||
215 | /* | 215 | /* | |
216 | * Called after a function declaration which introduces a function definition | 216 | * Called after a function declaration which introduces a function definition | |
217 | * and before an (optional) old style argument declaration list. | 217 | * and before an (optional) old style argument declaration list. | |
218 | * | 218 | * | |
219 | * Puts all symbols declared in the prototype or in an old style argument | 219 | * Puts all symbols declared in the prototype or in an old style argument | |
220 | * list back to the symbol table. | 220 | * list back to the symbol table. | |
221 | * | 221 | * | |
222 | * Does the usual checking of storage class, type (return value), | 222 | * Does the usual checking of storage class, type (return value), | |
223 | * redeclaration, etc. | 223 | * redeclaration, etc. | |
224 | */ | 224 | */ | |
225 | void | 225 | void | |
226 | funcdef(sym_t *fsym) | 226 | funcdef(sym_t *fsym) | |
227 | { | 227 | { | |
228 | int n; | 228 | int n; | |
229 | bool dowarn; | 229 | bool dowarn; | |
230 | sym_t *arg, *sym, *rdsym; | 230 | sym_t *arg, *sym, *rdsym; | |
231 | 231 | |||
232 | funcsym = fsym; | 232 | funcsym = fsym; | |
233 | 233 | |||
234 | /* | 234 | /* | |
235 | * Put all symbols declared in the argument list back to the | 235 | * Put all symbols declared in the argument list back to the | |
236 | * symbol table. | 236 | * symbol table. | |
237 | */ | 237 | */ | |
238 | for (sym = dcs->d_func_proto_syms; sym != NULL; sym = sym->s_dlnxt) { | 238 | for (sym = dcs->d_func_proto_syms; sym != NULL; | |
239 | sym = sym->s_level_next) { | |||
239 | if (sym->s_block_level != -1) { | 240 | if (sym->s_block_level != -1) { | |
240 | lint_assert(sym->s_block_level == 1); | 241 | lint_assert(sym->s_block_level == 1); | |
241 | inssym(1, sym); | 242 | inssym(1, sym); | |
242 | } | 243 | } | |
243 | } | 244 | } | |
244 | 245 | |||
245 | /* | 246 | /* | |
246 | * In old_style_function() we did not know whether it is an old | 247 | * In old_style_function() we did not know whether it is an old | |
247 | * style function definition or only an old style declaration, | 248 | * style function definition or only an old style declaration, | |
248 | * if there are no arguments inside the argument list ("f()"). | 249 | * if there are no arguments inside the argument list ("f()"). | |
249 | */ | 250 | */ | |
250 | if (!fsym->s_type->t_proto && fsym->s_args == NULL) | 251 | if (!fsym->s_type->t_proto && fsym->s_args == NULL) | |
251 | fsym->s_osdef = true; | 252 | fsym->s_osdef = true; | |
252 | 253 | |||
253 | check_type(fsym); | 254 | check_type(fsym); | |
254 | 255 | |||
255 | /* | 256 | /* | |
256 | * check_type() checks for almost all possible errors, but not for | 257 | * check_type() checks for almost all possible errors, but not for | |
257 | * incomplete return values (these are allowed in declarations) | 258 | * incomplete return values (these are allowed in declarations) | |
258 | */ | 259 | */ | |
259 | if (fsym->s_type->t_subt->t_tspec != VOID && | 260 | if (fsym->s_type->t_subt->t_tspec != VOID && | |
260 | is_incomplete(fsym->s_type->t_subt)) { | 261 | is_incomplete(fsym->s_type->t_subt)) { | |
261 | /* cannot return incomplete type */ | 262 | /* cannot return incomplete type */ | |
262 | error(67); | 263 | error(67); | |
263 | } | 264 | } | |
264 | 265 | |||
265 | fsym->s_def = DEF; | 266 | fsym->s_def = DEF; | |
266 | 267 | |||
267 | if (fsym->s_scl == TYPEDEF) { | 268 | if (fsym->s_scl == TYPEDEF) { | |
268 | fsym->s_scl = EXTERN; | 269 | fsym->s_scl = EXTERN; | |
269 | /* illegal storage class */ | 270 | /* illegal storage class */ | |
270 | error(8); | 271 | error(8); | |
271 | } | 272 | } | |
272 | 273 | |||
273 | if (dcs->d_inline) | 274 | if (dcs->d_inline) | |
274 | fsym->s_inline = true; | 275 | fsym->s_inline = true; | |
275 | 276 | |||
276 | /* | 277 | /* | |
277 | * Arguments in new style function declarations need a name. | 278 | * Arguments in new style function declarations need a name. | |
278 | * (void is already removed from the list of arguments) | 279 | * (void is already removed from the list of arguments) | |
279 | */ | 280 | */ | |
280 | n = 1; | 281 | n = 1; | |
281 | for (arg = fsym->s_type->t_args; arg != NULL; arg = arg->s_next) { | 282 | for (arg = fsym->s_type->t_args; arg != NULL; arg = arg->s_next) { | |
282 | if (arg->s_scl == ABSTRACT) { | 283 | if (arg->s_scl == ABSTRACT) { | |
283 | lint_assert(arg->s_name == unnamed); | 284 | lint_assert(arg->s_name == unnamed); | |
284 | /* formal parameter lacks name: param #%d */ | 285 | /* formal parameter lacks name: param #%d */ | |
285 | error(59, n); | 286 | error(59, n); | |
286 | } else { | 287 | } else { | |
287 | lint_assert(arg->s_name != unnamed); | 288 | lint_assert(arg->s_name != unnamed); | |
288 | } | 289 | } | |
289 | n++; | 290 | n++; | |
290 | } | 291 | } | |
291 | 292 | |||
292 | /* | 293 | /* | |
293 | * We must also remember the position. s_def_pos is overwritten | 294 | * We must also remember the position. s_def_pos is overwritten | |
294 | * if this is an old style definition and we had already a | 295 | * if this is an old style definition and we had already a | |
295 | * prototype. | 296 | * prototype. | |
296 | */ | 297 | */ | |
297 | dcs->d_func_def_pos = fsym->s_def_pos; | 298 | dcs->d_func_def_pos = fsym->s_def_pos; | |
298 | 299 | |||
299 | if ((rdsym = dcs->d_redeclared_symbol) != NULL) { | 300 | if ((rdsym = dcs->d_redeclared_symbol) != NULL) { | |
300 | 301 | |||
301 | if (!check_redeclaration(fsym, (dowarn = false, &dowarn))) { | 302 | if (!check_redeclaration(fsym, (dowarn = false, &dowarn))) { | |
302 | 303 | |||
303 | /* | 304 | /* | |
304 | * Print nothing if the newly defined function | 305 | * Print nothing if the newly defined function | |
305 | * is defined in old style. A better warning will | 306 | * is defined in old style. A better warning will | |
306 | * be printed in check_func_lint_directives(). | 307 | * be printed in check_func_lint_directives(). | |
307 | */ | 308 | */ | |
308 | if (dowarn && !fsym->s_osdef) { | 309 | if (dowarn && !fsym->s_osdef) { | |
309 | if (sflag) | 310 | if (sflag) | |
310 | /* redeclaration of %s */ | 311 | /* redeclaration of %s */ | |
311 | error(27, fsym->s_name); | 312 | error(27, fsym->s_name); | |
312 | else | 313 | else | |
313 | /* redeclaration of %s */ | 314 | /* redeclaration of %s */ | |
314 | warning(27, fsym->s_name); | 315 | warning(27, fsym->s_name); | |
315 | print_previous_declaration(-1, rdsym); | 316 | print_previous_declaration(-1, rdsym); | |
316 | } | 317 | } | |
317 | 318 | |||
318 | copy_usage_info(fsym, rdsym); | 319 | copy_usage_info(fsym, rdsym); | |
319 | 320 | |||
320 | /* | 321 | /* | |
321 | * If the old symbol was a prototype and the new | 322 | * If the old symbol was a prototype and the new | |
322 | * one is none, overtake the position of the | 323 | * one is none, overtake the position of the | |
323 | * declaration of the prototype. | 324 | * declaration of the prototype. | |
324 | */ | 325 | */ | |
325 | if (fsym->s_osdef && rdsym->s_type->t_proto) | 326 | if (fsym->s_osdef && rdsym->s_type->t_proto) | |
326 | fsym->s_def_pos = rdsym->s_def_pos; | 327 | fsym->s_def_pos = rdsym->s_def_pos; | |
327 | 328 | |||
328 | complete_type(fsym, rdsym); | 329 | complete_type(fsym, rdsym); | |
329 | 330 | |||
330 | if (rdsym->s_inline) | 331 | if (rdsym->s_inline) | |
331 | fsym->s_inline = true; | 332 | fsym->s_inline = true; | |
332 | 333 | |||
333 | } | 334 | } | |
334 | 335 | |||
335 | /* remove the old symbol from the symbol table */ | 336 | /* remove the old symbol from the symbol table */ | |
336 | rmsym(rdsym); | 337 | rmsym(rdsym); | |
337 | 338 | |||
338 | } | 339 | } | |
339 | 340 | |||
340 | if (fsym->s_osdef && !fsym->s_type->t_proto) { | 341 | if (fsym->s_osdef && !fsym->s_type->t_proto) { | |
341 | if (sflag && hflag && strcmp(fsym->s_name, "main") != 0) | 342 | if (sflag && hflag && strcmp(fsym->s_name, "main") != 0) | |
342 | /* function definition is not a prototype */ | 343 | /* function definition is not a prototype */ | |
343 | warning(286); | 344 | warning(286); | |
344 | } | 345 | } | |
345 | 346 | |||
346 | if (dcs->d_notyp) | 347 | if (dcs->d_notyp) | |
347 | fsym->s_return_type_implicit_int = true; | 348 | fsym->s_return_type_implicit_int = true; | |
348 | 349 | |||
349 | set_reached(true); | 350 | set_reached(true); | |
350 | } | 351 | } | |
351 | 352 | |||
352 | static void | 353 | static void | |
353 | check_missing_return_value(void) | 354 | check_missing_return_value(void) | |
354 | { | 355 | { | |
355 | if (funcsym->s_type->t_subt->t_tspec == VOID) | 356 | if (funcsym->s_type->t_subt->t_tspec == VOID) | |
356 | return; | 357 | return; | |
357 | if (funcsym->s_return_type_implicit_int) | 358 | if (funcsym->s_return_type_implicit_int) | |
358 | return; | 359 | return; | |
359 | 360 | |||
360 | /* C99 5.1.2.2.3 "Program termination" p1 */ | 361 | /* C99 5.1.2.2.3 "Program termination" p1 */ | |
361 | if (Sflag && strcmp(funcsym->s_name, "main") == 0) | 362 | if (Sflag && strcmp(funcsym->s_name, "main") == 0) | |
362 | return; | 363 | return; | |
363 | 364 | |||
364 | /* function %s falls off bottom without returning value */ | 365 | /* function %s falls off bottom without returning value */ | |
365 | warning(217, funcsym->s_name); | 366 | warning(217, funcsym->s_name); | |
366 | } | 367 | } | |
367 | 368 | |||
368 | /* | 369 | /* | |
369 | * Called at the end of a function definition. | 370 | * Called at the end of a function definition. | |
370 | */ | 371 | */ | |
371 | void | 372 | void | |
372 | funcend(void) | 373 | funcend(void) | |
373 | { | 374 | { | |
374 | sym_t *arg; | 375 | sym_t *arg; | |
375 | int n; | 376 | int n; | |
376 | 377 | |||
377 | if (reached) { | 378 | if (reached) { | |
378 | cstmt->c_had_return_noval = true; | 379 | cstmt->c_had_return_noval = true; | |
379 | check_missing_return_value(); | 380 | check_missing_return_value(); | |
380 | } | 381 | } | |
381 | 382 | |||
382 | /* | 383 | /* | |
383 | * This warning is printed only if the return value was implicitly | 384 | * This warning is printed only if the return value was implicitly | |
384 | * declared to be int. Otherwise the wrong return statement | 385 | * declared to be int. Otherwise the wrong return statement | |
385 | * has already printed a warning. | 386 | * has already printed a warning. | |
386 | */ | 387 | */ | |
387 | if (cstmt->c_had_return_noval && cstmt->c_had_return_value && | 388 | if (cstmt->c_had_return_noval && cstmt->c_had_return_value && | |
388 | funcsym->s_return_type_implicit_int) | 389 | funcsym->s_return_type_implicit_int) | |
389 | /* function %s has return (e); and return; */ | 390 | /* function %s has return (e); and return; */ | |
390 | warning(216, funcsym->s_name); | 391 | warning(216, funcsym->s_name); | |
391 | 392 | |||
392 | /* Print warnings for unused arguments */ | 393 | /* Print warnings for unused arguments */ | |
393 | arg = dcs->d_func_args; | 394 | arg = dcs->d_func_args; | |
394 | n = 0; | 395 | n = 0; | |
395 | while (arg != NULL && (nargusg == -1 || n < nargusg)) { | 396 | while (arg != NULL && (nargusg == -1 || n < nargusg)) { | |
396 | check_usage_sym(dcs->d_asm, arg); | 397 | check_usage_sym(dcs->d_asm, arg); | |
397 | arg = arg->s_next; | 398 | arg = arg->s_next; | |
398 | n++; | 399 | n++; | |
399 | } | 400 | } | |
400 | nargusg = -1; | 401 | nargusg = -1; | |
401 | 402 | |||
402 | /* | 403 | /* | |
403 | * write the information about the function definition to the | 404 | * write the information about the function definition to the | |
404 | * output file | 405 | * output file | |
405 | * inline functions explicitly declared extern are written as | 406 | * inline functions explicitly declared extern are written as | |
406 | * declarations only. | 407 | * declarations only. | |
407 | */ | 408 | */ | |
408 | if (dcs->d_scl == EXTERN && funcsym->s_inline) { | 409 | if (dcs->d_scl == EXTERN && funcsym->s_inline) { | |
409 | outsym(funcsym, funcsym->s_scl, DECL); | 410 | outsym(funcsym, funcsym->s_scl, DECL); | |
410 | } else { | 411 | } else { | |
411 | outfdef(funcsym, &dcs->d_func_def_pos, | 412 | outfdef(funcsym, &dcs->d_func_def_pos, | |
412 | cstmt->c_had_return_value, funcsym->s_osdef, | 413 | cstmt->c_had_return_value, funcsym->s_osdef, | |
413 | dcs->d_func_args); | 414 | dcs->d_func_args); | |
414 | } | 415 | } | |
415 | 416 | |||
416 | /* clean up after syntax errors, see test stmt_for.c. */ | 417 | /* clean up after syntax errors, see test stmt_for.c. */ | |
417 | while (dcs->d_next != NULL) | 418 | while (dcs->d_next != NULL) | |
418 | dcs = dcs->d_next; | 419 | dcs = dcs->d_next; | |
419 | 420 | |||
420 | /* | 421 | /* | |
421 | * remove all symbols declared during argument declaration from | 422 | * remove all symbols declared during argument declaration from | |
422 | * the symbol table | 423 | * the symbol table | |
423 | */ | 424 | */ | |
424 | lint_assert(dcs->d_next == NULL); | 425 | lint_assert(dcs->d_next == NULL); | |
425 | lint_assert(dcs->d_ctx == EXTERN); | 426 | lint_assert(dcs->d_ctx == EXTERN); | |
426 | rmsyms(dcs->d_func_proto_syms); | 427 | rmsyms(dcs->d_func_proto_syms); | |
427 | 428 | |||
428 | /* must be set on level 0 */ | 429 | /* must be set on level 0 */ | |
429 | set_reached(true); | 430 | set_reached(true); | |
430 | } | 431 | } | |
431 | 432 | |||
432 | void | 433 | void | |
433 | named_label(sym_t *sym) | 434 | named_label(sym_t *sym) | |
434 | { | 435 | { | |
435 | 436 | |||
436 | if (sym->s_set) { | 437 | if (sym->s_set) { | |
437 | /* label %s redefined */ | 438 | /* label %s redefined */ | |
438 | error(194, sym->s_name); | 439 | error(194, sym->s_name); | |
439 | } else { | 440 | } else { | |
440 | mark_as_set(sym); | 441 | mark_as_set(sym); | |
441 | } | 442 | } | |
442 | 443 | |||
443 | set_reached(true); | 444 | set_reached(true); | |
444 | } | 445 | } | |
445 | 446 | |||
446 | static void | 447 | static void | |
447 | check_case_label_bitand(const tnode_t *case_expr, const tnode_t *switch_expr) | 448 | check_case_label_bitand(const tnode_t *case_expr, const tnode_t *switch_expr) | |
448 | { | 449 | { | |
449 | uint64_t case_value, mask; | 450 | uint64_t case_value, mask; | |
450 | 451 | |||
451 | if (switch_expr->tn_op != BITAND || | 452 | if (switch_expr->tn_op != BITAND || | |
452 | switch_expr->tn_right->tn_op != CON) | 453 | switch_expr->tn_right->tn_op != CON) | |
453 | return; | 454 | return; | |
454 | 455 | |||
455 | lint_assert(case_expr->tn_op == CON); | 456 | lint_assert(case_expr->tn_op == CON); | |
456 | case_value = case_expr->tn_val->v_quad; | 457 | case_value = case_expr->tn_val->v_quad; | |
457 | mask = switch_expr->tn_right->tn_val->v_quad; | 458 | mask = switch_expr->tn_right->tn_val->v_quad; | |
458 | 459 | |||
459 | if ((case_value & ~mask) != 0) { | 460 | if ((case_value & ~mask) != 0) { | |
460 | /* statement not reached */ | 461 | /* statement not reached */ | |
461 | warning(193); | 462 | warning(193); | |
462 | } | 463 | } | |
463 | } | 464 | } | |
464 | 465 | |||
465 | static void | 466 | static void | |
466 | check_case_label_enum(const tnode_t *tn, const control_statement *cs) | 467 | check_case_label_enum(const tnode_t *tn, const control_statement *cs) | |
467 | { | 468 | { | |
468 | /* similar to typeok_enum in tree.c */ | 469 | /* similar to typeok_enum in tree.c */ | |
469 | 470 | |||
470 | if (!(tn->tn_type->t_is_enum || cs->c_switch_type->t_is_enum)) | 471 | if (!(tn->tn_type->t_is_enum || cs->c_switch_type->t_is_enum)) | |
471 | return; | 472 | return; | |
472 | if (tn->tn_type->t_is_enum && cs->c_switch_type->t_is_enum && | 473 | if (tn->tn_type->t_is_enum && cs->c_switch_type->t_is_enum && | |
473 | tn->tn_type->t_enum == cs->c_switch_type->t_enum) | 474 | tn->tn_type->t_enum == cs->c_switch_type->t_enum) | |
474 | return; | 475 | return; | |
475 | 476 | |||
476 | #if 0 /* not yet ready, see msg_130.c */ | 477 | #if 0 /* not yet ready, see msg_130.c */ | |
477 | /* enum type mismatch: '%s' '%s' '%s' */ | 478 | /* enum type mismatch: '%s' '%s' '%s' */ | |
478 | warning(130, type_name(cs->c_switch_type), op_name(EQ), | 479 | warning(130, type_name(cs->c_switch_type), op_name(EQ), | |
479 | type_name(tn->tn_type)); | 480 | type_name(tn->tn_type)); | |
480 | #endif | 481 | #endif | |
481 | } | 482 | } | |
482 | 483 | |||
483 | static void | 484 | static void | |
484 | check_case_label(tnode_t *tn, control_statement *cs) | 485 | check_case_label(tnode_t *tn, control_statement *cs) | |
485 | { | 486 | { | |
486 | case_label_t *cl; | 487 | case_label_t *cl; | |
487 | val_t *v; | 488 | val_t *v; | |
488 | val_t nv; | 489 | val_t nv; | |
489 | tspec_t t; | 490 | tspec_t t; | |
490 | 491 | |||
491 | if (cs == NULL) { | 492 | if (cs == NULL) { | |
492 | /* case not in switch */ | 493 | /* case not in switch */ | |
493 | error(195); | 494 | error(195); | |
494 | return; | 495 | return; | |
495 | } | 496 | } | |
496 | 497 | |||
497 | if (tn != NULL && tn->tn_op != CON) { | 498 | if (tn != NULL && tn->tn_op != CON) { | |
498 | /* non-constant case expression */ | 499 | /* non-constant case expression */ | |
499 | error(197); | 500 | error(197); | |
500 | return; | 501 | return; | |
501 | } | 502 | } | |
502 | 503 | |||
503 | if (tn != NULL && !is_integer(tn->tn_type->t_tspec)) { | 504 | if (tn != NULL && !is_integer(tn->tn_type->t_tspec)) { | |
504 | /* non-integral case expression */ | 505 | /* non-integral case expression */ | |
505 | error(198); | 506 | error(198); | |
506 | return; | 507 | return; | |
507 | } | 508 | } | |
508 | 509 | |||
509 | check_case_label_bitand(tn, cs->c_switch_expr); | 510 | check_case_label_bitand(tn, cs->c_switch_expr); | |
510 | check_case_label_enum(tn, cs); | 511 | check_case_label_enum(tn, cs); | |
511 | 512 | |||
512 | lint_assert(cs->c_switch_type != NULL); | 513 | lint_assert(cs->c_switch_type != NULL); | |
513 | 514 | |||
514 | if (reached && !seen_fallthrough) { | 515 | if (reached && !seen_fallthrough) { | |
515 | if (hflag) | 516 | if (hflag) | |
516 | /* fallthrough on case statement */ | 517 | /* fallthrough on case statement */ | |
517 | warning(220); | 518 | warning(220); | |
518 | } | 519 | } | |
519 | 520 | |||
520 | t = tn->tn_type->t_tspec; | 521 | t = tn->tn_type->t_tspec; | |
521 | if (t == LONG || t == ULONG || | 522 | if (t == LONG || t == ULONG || | |
522 | t == QUAD || t == UQUAD) { | 523 | t == QUAD || t == UQUAD) { | |
523 | if (tflag) | 524 | if (tflag) | |
524 | /* case label must be of type 'int' in traditional C */ | 525 | /* case label must be of type 'int' in traditional C */ | |
525 | warning(203); | 526 | warning(203); | |
526 | } | 527 | } | |
527 | 528 | |||
528 | /* | 529 | /* | |
529 | * get the value of the expression and convert it | 530 | * get the value of the expression and convert it | |
530 | * to the type of the switch expression | 531 | * to the type of the switch expression | |
531 | */ | 532 | */ | |
532 | v = constant(tn, true); | 533 | v = constant(tn, true); | |
533 | (void)memset(&nv, 0, sizeof(nv)); | 534 | (void)memset(&nv, 0, sizeof(nv)); | |
534 | convert_constant(CASE, 0, cs->c_switch_type, &nv, v); | 535 | convert_constant(CASE, 0, cs->c_switch_type, &nv, v); | |
535 | free(v); | 536 | free(v); | |
536 | 537 | |||
537 | /* look if we had this value already */ | 538 | /* look if we had this value already */ | |
538 | for (cl = cs->c_case_labels; cl != NULL; cl = cl->cl_next) { | 539 | for (cl = cs->c_case_labels; cl != NULL; cl = cl->cl_next) { | |
539 | if (cl->cl_val.v_quad == nv.v_quad) | 540 | if (cl->cl_val.v_quad == nv.v_quad) | |
540 | break; | 541 | break; | |
541 | } | 542 | } | |
542 | if (cl != NULL && is_uinteger(nv.v_tspec)) { | 543 | if (cl != NULL && is_uinteger(nv.v_tspec)) { | |
543 | /* duplicate case in switch: %lu */ | 544 | /* duplicate case in switch: %lu */ | |
544 | error(200, (unsigned long)nv.v_quad); | 545 | error(200, (unsigned long)nv.v_quad); | |
545 | } else if (cl != NULL) { | 546 | } else if (cl != NULL) { | |
546 | /* duplicate case in switch: %ld */ | 547 | /* duplicate case in switch: %ld */ | |
547 | error(199, (long)nv.v_quad); | 548 | error(199, (long)nv.v_quad); | |
548 | } else { | 549 | } else { | |
549 | check_getopt_case_label(nv.v_quad); | 550 | check_getopt_case_label(nv.v_quad); | |
550 | 551 | |||
551 | /* append the value to the list of case values */ | 552 | /* append the value to the list of case values */ | |
552 | cl = xcalloc(1, sizeof(*cl)); | 553 | cl = xcalloc(1, sizeof(*cl)); | |
553 | cl->cl_val = nv; | 554 | cl->cl_val = nv; | |
554 | cl->cl_next = cs->c_case_labels; | 555 | cl->cl_next = cs->c_case_labels; | |
555 | cs->c_case_labels = cl; | 556 | cs->c_case_labels = cl; | |
556 | } | 557 | } | |
557 | } | 558 | } | |
558 | 559 | |||
559 | void | 560 | void | |
560 | case_label(tnode_t *tn) | 561 | case_label(tnode_t *tn) | |
561 | { | 562 | { | |
562 | control_statement *cs; | 563 | control_statement *cs; | |
563 | 564 | |||
564 | /* find the innermost switch statement */ | 565 | /* find the innermost switch statement */ | |
565 | for (cs = cstmt; cs != NULL && !cs->c_switch; cs = cs->c_surrounding) | 566 | for (cs = cstmt; cs != NULL && !cs->c_switch; cs = cs->c_surrounding) | |
566 | continue; | 567 | continue; | |
567 | 568 | |||
568 | check_case_label(tn, cs); | 569 | check_case_label(tn, cs); | |
569 | 570 | |||
570 | expr_free_all(); | 571 | expr_free_all(); | |
571 | 572 | |||
572 | set_reached(true); | 573 | set_reached(true); | |
573 | } | 574 | } | |
574 | 575 | |||
575 | void | 576 | void | |
576 | default_label(void) | 577 | default_label(void) | |
577 | { | 578 | { | |
578 | control_statement *cs; | 579 | control_statement *cs; | |
579 | 580 | |||
580 | /* find the innermost switch statement */ | 581 | /* find the innermost switch statement */ | |
581 | for (cs = cstmt; cs != NULL && !cs->c_switch; cs = cs->c_surrounding) | 582 | for (cs = cstmt; cs != NULL && !cs->c_switch; cs = cs->c_surrounding) | |
582 | continue; | 583 | continue; | |
583 | 584 | |||
584 | if (cs == NULL) { | 585 | if (cs == NULL) { | |
585 | /* default outside switch */ | 586 | /* default outside switch */ | |
586 | error(201); | 587 | error(201); | |
587 | } else if (cs->c_default) { | 588 | } else if (cs->c_default) { | |
588 | /* duplicate default in switch */ | 589 | /* duplicate default in switch */ | |
589 | error(202); | 590 | error(202); | |
590 | } else { | 591 | } else { | |
591 | if (reached && !seen_fallthrough) { | 592 | if (reached && !seen_fallthrough) { | |
592 | if (hflag) | 593 | if (hflag) | |
593 | /* fallthrough on default statement */ | 594 | /* fallthrough on default statement */ | |
594 | warning(284); | 595 | warning(284); | |
595 | } | 596 | } | |
596 | cs->c_default = true; | 597 | cs->c_default = true; | |
597 | } | 598 | } | |
598 | 599 | |||
599 | set_reached(true); | 600 | set_reached(true); | |
600 | } | 601 | } | |
601 | 602 | |||
602 | static tnode_t * | 603 | static tnode_t * | |
603 | check_controlling_expression(tnode_t *tn) | 604 | check_controlling_expression(tnode_t *tn) | |
604 | { | 605 | { | |
605 | 606 | |||
606 | tn = cconv(tn); | 607 | tn = cconv(tn); | |
607 | if (tn != NULL) | 608 | if (tn != NULL) | |
608 | tn = promote(NOOP, false, tn); | 609 | tn = promote(NOOP, false, tn); | |
609 | 610 | |||
610 | if (tn != NULL && !is_scalar(tn->tn_type->t_tspec)) { | 611 | if (tn != NULL && !is_scalar(tn->tn_type->t_tspec)) { | |
611 | /* C99 6.5.15p4 for the ?: operator; see typeok:QUEST */ | 612 | /* C99 6.5.15p4 for the ?: operator; see typeok:QUEST */ | |
612 | /* C99 6.8.4.1p1 for if statements */ | 613 | /* C99 6.8.4.1p1 for if statements */ | |
613 | /* C99 6.8.5p2 for while, do and for loops */ | 614 | /* C99 6.8.5p2 for while, do and for loops */ | |
614 | /* controlling expressions must have scalar type */ | 615 | /* controlling expressions must have scalar type */ | |
615 | error(204); | 616 | error(204); | |
616 | return NULL; | 617 | return NULL; | |
617 | } | 618 | } | |
618 | 619 | |||
619 | if (tn != NULL && Tflag && !is_typeok_bool_operand(tn)) { | 620 | if (tn != NULL && Tflag && !is_typeok_bool_operand(tn)) { | |
620 | /* controlling expression must be bool, not '%s' */ | 621 | /* controlling expression must be bool, not '%s' */ | |
621 | error(333, tspec_name(tn->tn_type->t_tspec)); | 622 | error(333, tspec_name(tn->tn_type->t_tspec)); | |
622 | } | 623 | } | |
623 | 624 | |||
624 | return tn; | 625 | return tn; | |
625 | } | 626 | } | |
626 | 627 | |||
627 | /* | 628 | /* | |
628 | * T_IF T_LPAREN expr T_RPAREN | 629 | * T_IF T_LPAREN expr T_RPAREN | |
629 | */ | 630 | */ | |
630 | void | 631 | void | |
631 | if1(tnode_t *tn) | 632 | if1(tnode_t *tn) | |
632 | { | 633 | { | |
633 | 634 | |||
634 | if (tn != NULL) | 635 | if (tn != NULL) | |
635 | tn = check_controlling_expression(tn); | 636 | tn = check_controlling_expression(tn); | |
636 | if (tn != NULL) | 637 | if (tn != NULL) | |
637 | expr(tn, false, true, false, false); | 638 | expr(tn, false, true, false, false); | |
638 | begin_control_statement(CS_IF); | 639 | begin_control_statement(CS_IF); | |
639 | 640 | |||
640 | if (tn != NULL && tn->tn_op == CON && !tn->tn_system_dependent) { | 641 | if (tn != NULL && tn->tn_op == CON && !tn->tn_system_dependent) { | |
641 | /* XXX: what if inside 'if (0)'? */ | 642 | /* XXX: what if inside 'if (0)'? */ | |
642 | set_reached(constant_is_nonzero(tn)); | 643 | set_reached(constant_is_nonzero(tn)); | |
643 | /* XXX: what about always_else? */ | 644 | /* XXX: what about always_else? */ | |
644 | cstmt->c_always_then = reached; | 645 | cstmt->c_always_then = reached; | |
645 | } | 646 | } | |
646 | } | 647 | } | |
647 | 648 | |||
648 | /* | 649 | /* | |
649 | * if_without_else | 650 | * if_without_else | |
650 | * if_without_else T_ELSE | 651 | * if_without_else T_ELSE | |
651 | */ | 652 | */ | |
652 | void | 653 | void | |
653 | if2(void) | 654 | if2(void) | |
654 | { | 655 | { | |
655 | 656 | |||
656 | cstmt->c_reached_end_of_then = reached; | 657 | cstmt->c_reached_end_of_then = reached; | |
657 | /* XXX: what if inside 'if (0)'? */ | 658 | /* XXX: what if inside 'if (0)'? */ | |
658 | set_reached(!cstmt->c_always_then); | 659 | set_reached(!cstmt->c_always_then); | |
659 | } | 660 | } | |
660 | 661 | |||
661 | /* | 662 | /* | |
662 | * if_without_else | 663 | * if_without_else | |
663 | * if_without_else T_ELSE statement | 664 | * if_without_else T_ELSE statement | |
664 | */ | 665 | */ | |
665 | void | 666 | void | |
666 | if3(bool els) | 667 | if3(bool els) | |
667 | { | 668 | { | |
668 | if (cstmt->c_reached_end_of_then) | 669 | if (cstmt->c_reached_end_of_then) | |
669 | set_reached(true); | 670 | set_reached(true); | |
670 | else if (cstmt->c_always_then) | 671 | else if (cstmt->c_always_then) | |
671 | set_reached(false); | 672 | set_reached(false); | |
672 | else if (!els) | 673 | else if (!els) | |
673 | set_reached(true); | 674 | set_reached(true); | |
674 | 675 | |||
675 | end_control_statement(CS_IF); | 676 | end_control_statement(CS_IF); | |
676 | } | 677 | } | |
677 | 678 | |||
678 | /* | 679 | /* | |
679 | * T_SWITCH T_LPAREN expr T_RPAREN | 680 | * T_SWITCH T_LPAREN expr T_RPAREN | |
680 | */ | 681 | */ | |
681 | void | 682 | void | |
682 | switch1(tnode_t *tn) | 683 | switch1(tnode_t *tn) | |
683 | { | 684 | { | |
684 | tspec_t t; | 685 | tspec_t t; | |
685 | type_t *tp; | 686 | type_t *tp; | |
686 | 687 | |||
687 | if (tn != NULL) | 688 | if (tn != NULL) | |
688 | tn = cconv(tn); | 689 | tn = cconv(tn); | |
689 | if (tn != NULL) | 690 | if (tn != NULL) | |
690 | tn = promote(NOOP, false, tn); | 691 | tn = promote(NOOP, false, tn); | |
691 | if (tn != NULL && !is_integer(tn->tn_type->t_tspec)) { | 692 | if (tn != NULL && !is_integer(tn->tn_type->t_tspec)) { | |
692 | /* switch expression must have integral type */ | 693 | /* switch expression must have integral type */ | |
693 | error(205); | 694 | error(205); | |
694 | tn = NULL; | 695 | tn = NULL; | |
695 | } | 696 | } | |
696 | if (tn != NULL && tflag) { | 697 | if (tn != NULL && tflag) { | |
697 | t = tn->tn_type->t_tspec; | 698 | t = tn->tn_type->t_tspec; | |
698 | if (t == LONG || t == ULONG || t == QUAD || t == UQUAD) { | 699 | if (t == LONG || t == ULONG || t == QUAD || t == UQUAD) { | |
699 | /* switch expression must be of type 'int' in ... */ | 700 | /* switch expression must be of type 'int' in ... */ | |
700 | warning(271); | 701 | warning(271); | |
701 | } | 702 | } | |
702 | } | 703 | } | |
703 | 704 | |||
704 | /* | 705 | /* | |
705 | * Remember the type of the expression. Because it's possible | 706 | * Remember the type of the expression. Because it's possible | |
706 | * that (*tp) is allocated on tree memory, the type must be | 707 | * that (*tp) is allocated on tree memory, the type must be | |
707 | * duplicated. This is not too complicated because it is | 708 | * duplicated. This is not too complicated because it is | |
708 | * only an integer type. | 709 | * only an integer type. | |
709 | */ | 710 | */ | |
710 | tp = xcalloc(1, sizeof(*tp)); | 711 | tp = xcalloc(1, sizeof(*tp)); | |
711 | if (tn != NULL) { | 712 | if (tn != NULL) { | |
712 | tp->t_tspec = tn->tn_type->t_tspec; | 713 | tp->t_tspec = tn->tn_type->t_tspec; | |
713 | if ((tp->t_is_enum = tn->tn_type->t_is_enum) != false) | 714 | if ((tp->t_is_enum = tn->tn_type->t_is_enum) != false) | |
714 | tp->t_enum = tn->tn_type->t_enum; | 715 | tp->t_enum = tn->tn_type->t_enum; | |
715 | } else { | 716 | } else { | |
716 | tp->t_tspec = INT; | 717 | tp->t_tspec = INT; | |
717 | } | 718 | } | |
718 | 719 | |||
719 | /* leak the memory, for check_case_label_bitand */ | 720 | /* leak the memory, for check_case_label_bitand */ | |
720 | (void)expr_save_memory(); | 721 | (void)expr_save_memory(); | |
721 | 722 | |||
722 | check_getopt_begin_switch(); | 723 | check_getopt_begin_switch(); | |
723 | expr(tn, true, false, false, false); | 724 | expr(tn, true, false, false, false); | |
724 | 725 | |||
725 | begin_control_statement(CS_SWITCH); | 726 | begin_control_statement(CS_SWITCH); | |
726 | cstmt->c_switch = true; | 727 | cstmt->c_switch = true; | |
727 | cstmt->c_switch_type = tp; | 728 | cstmt->c_switch_type = tp; | |
728 | cstmt->c_switch_expr = tn; | 729 | cstmt->c_switch_expr = tn; | |
729 | 730 | |||
730 | set_reached(false); | 731 | set_reached(false); | |
731 | seen_fallthrough = true; | 732 | seen_fallthrough = true; | |
732 | } | 733 | } | |
733 | 734 | |||
734 | /* | 735 | /* | |
735 | * switch_expr statement | 736 | * switch_expr statement | |
736 | */ | 737 | */ | |
737 | void | 738 | void | |
738 | switch2(void) | 739 | switch2(void) | |
739 | { | 740 | { | |
740 | int nenum = 0, nclab = 0; | 741 | int nenum = 0, nclab = 0; | |
741 | sym_t *esym; | 742 | sym_t *esym; | |
742 | case_label_t *cl; | 743 | case_label_t *cl; | |
743 | 744 | |||
744 | lint_assert(cstmt->c_switch_type != NULL); | 745 | lint_assert(cstmt->c_switch_type != NULL); | |
745 | 746 | |||
746 | if (cstmt->c_switch_type->t_is_enum) { | 747 | if (cstmt->c_switch_type->t_is_enum) { | |
747 | /* | 748 | /* | |
748 | * Warn if the number of case labels is different from the | 749 | * Warn if the number of case labels is different from the | |
749 | * number of enumerators. | 750 | * number of enumerators. | |
750 | */ | 751 | */ | |
751 | nenum = nclab = 0; | 752 | nenum = nclab = 0; | |
752 | lint_assert(cstmt->c_switch_type->t_enum != NULL); | 753 | lint_assert(cstmt->c_switch_type->t_enum != NULL); | |
753 | for (esym = cstmt->c_switch_type->t_enum->en_first_enumerator; | 754 | for (esym = cstmt->c_switch_type->t_enum->en_first_enumerator; | |
754 | esym != NULL; esym = esym->s_next) { | 755 | esym != NULL; esym = esym->s_next) { | |
755 | nenum++; | 756 | nenum++; | |
756 | } | 757 | } | |
757 | for (cl = cstmt->c_case_labels; cl != NULL; cl = cl->cl_next) | 758 | for (cl = cstmt->c_case_labels; cl != NULL; cl = cl->cl_next) | |
758 | nclab++; | 759 | nclab++; | |
759 | if (hflag && eflag && nenum != nclab && !cstmt->c_default) { | 760 | if (hflag && eflag && nenum != nclab && !cstmt->c_default) { | |
760 | /* enumeration value(s) not handled in switch */ | 761 | /* enumeration value(s) not handled in switch */ | |
761 | warning(206); | 762 | warning(206); | |
762 | } | 763 | } | |
763 | } | 764 | } | |
764 | 765 | |||
765 | check_getopt_end_switch(); | 766 | check_getopt_end_switch(); | |
766 | 767 | |||
767 | if (cstmt->c_break) { | 768 | if (cstmt->c_break) { | |
768 | /* | 769 | /* | |
769 | * The end of the switch statement is always reached since | 770 | * The end of the switch statement is always reached since | |
770 | * c_break is only set if a break statement can actually | 771 | * c_break is only set if a break statement can actually | |
771 | * be reached. | 772 | * be reached. | |
772 | */ | 773 | */ | |
773 | set_reached(true); | 774 | set_reached(true); | |
774 | } else if (cstmt->c_default || | 775 | } else if (cstmt->c_default || | |
775 | (hflag && cstmt->c_switch_type->t_is_enum && | 776 | (hflag && cstmt->c_switch_type->t_is_enum && | |
776 | nenum == nclab)) { | 777 | nenum == nclab)) { | |
777 | /* | 778 | /* | |
778 | * The end of the switch statement is reached if the end | 779 | * The end of the switch statement is reached if the end | |
779 | * of the last statement inside it is reached. | 780 | * of the last statement inside it is reached. | |
780 | */ | 781 | */ | |
781 | } else { | 782 | } else { | |
782 | /* | 783 | /* | |
783 | * There are possible values that are not handled in the | 784 | * There are possible values that are not handled in the | |
784 | * switch statement. | 785 | * switch statement. | |
785 | */ | 786 | */ | |
786 | set_reached(true); | 787 | set_reached(true); | |
787 | } | 788 | } | |
788 | 789 | |||
789 | end_control_statement(CS_SWITCH); | 790 | end_control_statement(CS_SWITCH); | |
790 | } | 791 | } | |
791 | 792 | |||
792 | /* | 793 | /* | |
793 | * T_WHILE T_LPAREN expr T_RPAREN | 794 | * T_WHILE T_LPAREN expr T_RPAREN | |
794 | */ | 795 | */ | |
795 | void | 796 | void | |
796 | while1(tnode_t *tn) | 797 | while1(tnode_t *tn) | |
797 | { | 798 | { | |
798 | bool body_reached; | 799 | bool body_reached; | |
799 | 800 | |||
800 | if (!reached) { | 801 | if (!reached) { | |
801 | /* loop not entered at top */ | 802 | /* loop not entered at top */ | |
802 | warning(207); | 803 | warning(207); | |
803 | /* FIXME: that's plain wrong. */ | 804 | /* FIXME: that's plain wrong. */ | |
804 | set_reached(true); | 805 | set_reached(true); | |
805 | } | 806 | } | |
806 | 807 | |||
807 | if (tn != NULL) | 808 | if (tn != NULL) | |
808 | tn = check_controlling_expression(tn); | 809 | tn = check_controlling_expression(tn); | |
809 | 810 | |||
810 | begin_control_statement(CS_WHILE); | 811 | begin_control_statement(CS_WHILE); | |
811 | cstmt->c_loop = true; | 812 | cstmt->c_loop = true; | |
812 | cstmt->c_maybe_endless = is_nonzero(tn); | 813 | cstmt->c_maybe_endless = is_nonzero(tn); | |
813 | body_reached = !is_zero(tn); | 814 | body_reached = !is_zero(tn); | |
814 | 815 | |||
815 | check_getopt_begin_while(tn); | 816 | check_getopt_begin_while(tn); | |
816 | expr(tn, false, true, true, false); | 817 | expr(tn, false, true, true, false); | |
817 | 818 | |||
818 | set_reached(body_reached); | 819 | set_reached(body_reached); | |
819 | } | 820 | } | |
820 | 821 | |||
821 | /* | 822 | /* | |
822 | * while_expr statement | 823 | * while_expr statement | |
823 | * while_expr error | 824 | * while_expr error | |
824 | */ | 825 | */ | |
825 | void | 826 | void | |
826 | while2(void) | 827 | while2(void) | |
827 | { | 828 | { | |
828 | 829 | |||
829 | /* | 830 | /* | |
830 | * The end of the loop can be reached if it is no endless loop | 831 | * The end of the loop can be reached if it is no endless loop | |
831 | * or there was a break statement which was reached. | 832 | * or there was a break statement which was reached. | |
832 | */ | 833 | */ | |
833 | set_reached(!cstmt->c_maybe_endless || cstmt->c_break); | 834 | set_reached(!cstmt->c_maybe_endless || cstmt->c_break); | |
834 | 835 | |||
835 | check_getopt_end_while(); | 836 | check_getopt_end_while(); | |
836 | end_control_statement(CS_WHILE); | 837 | end_control_statement(CS_WHILE); | |
837 | } | 838 | } | |
838 | 839 | |||
839 | /* | 840 | /* | |
840 | * T_DO | 841 | * T_DO | |
841 | */ | 842 | */ | |
842 | void | 843 | void | |
843 | do1(void) | 844 | do1(void) | |
844 | { | 845 | { | |
845 | 846 | |||
846 | if (!reached) { | 847 | if (!reached) { | |
847 | /* loop not entered at top */ | 848 | /* loop not entered at top */ | |
848 | warning(207); | 849 | warning(207); | |
849 | set_reached(true); | 850 | set_reached(true); | |
850 | } | 851 | } | |
851 | 852 | |||
852 | begin_control_statement(CS_DO_WHILE); | 853 | begin_control_statement(CS_DO_WHILE); | |
853 | cstmt->c_loop = true; | 854 | cstmt->c_loop = true; | |
854 | } | 855 | } | |
855 | 856 | |||
856 | /* | 857 | /* | |
857 | * do statement do_while_expr | 858 | * do statement do_while_expr | |
858 | * do error | 859 | * do error | |
859 | */ | 860 | */ | |
860 | void | 861 | void | |
861 | do2(tnode_t *tn) | 862 | do2(tnode_t *tn) | |
862 | { | 863 | { | |
863 | 864 | |||
864 | /* | 865 | /* | |
865 | * If there was a continue statement, the expression controlling the | 866 | * If there was a continue statement, the expression controlling the | |
866 | * loop is reached. | 867 | * loop is reached. | |
867 | */ | 868 | */ | |
868 | if (cstmt->c_continue) | 869 | if (cstmt->c_continue) | |
869 | set_reached(true); | 870 | set_reached(true); | |
870 | 871 | |||
871 | if (tn != NULL) | 872 | if (tn != NULL) | |
872 | tn = check_controlling_expression(tn); | 873 | tn = check_controlling_expression(tn); | |
873 | 874 | |||
874 | if (tn != NULL && tn->tn_op == CON) { | 875 | if (tn != NULL && tn->tn_op == CON) { | |
875 | cstmt->c_maybe_endless = constant_is_nonzero(tn); | 876 | cstmt->c_maybe_endless = constant_is_nonzero(tn); | |
876 | if (!cstmt->c_maybe_endless && cstmt->c_continue) | 877 | if (!cstmt->c_maybe_endless && cstmt->c_continue) | |
877 | /* continue in 'do ... while (0)' loop */ | 878 | /* continue in 'do ... while (0)' loop */ | |
878 | error(323); | 879 | error(323); | |
879 | } | 880 | } | |
880 | 881 | |||
881 | expr(tn, false, true, true, true); | 882 | expr(tn, false, true, true, true); | |
882 | 883 | |||
883 | if (cstmt->c_maybe_endless) | 884 | if (cstmt->c_maybe_endless) | |
884 | set_reached(false); | 885 | set_reached(false); | |
885 | if (cstmt->c_break) | 886 | if (cstmt->c_break) | |
886 | set_reached(true); | 887 | set_reached(true); | |
887 | 888 | |||
888 | end_control_statement(CS_DO_WHILE); | 889 | end_control_statement(CS_DO_WHILE); | |
889 | } | 890 | } | |
890 | 891 | |||
891 | /* | 892 | /* | |
892 | * T_FOR T_LPAREN opt_expr T_SEMI opt_expr T_SEMI opt_expr T_RPAREN | 893 | * T_FOR T_LPAREN opt_expr T_SEMI opt_expr T_SEMI opt_expr T_RPAREN | |
893 | */ | 894 | */ | |
894 | void | 895 | void | |
895 | for1(tnode_t *tn1, tnode_t *tn2, tnode_t *tn3) | 896 | for1(tnode_t *tn1, tnode_t *tn2, tnode_t *tn3) | |
896 | { | 897 | { | |
897 | 898 | |||
898 | /* | 899 | /* | |
899 | * If there is no initialization expression it is possible that | 900 | * If there is no initialization expression it is possible that | |
900 | * it is intended not to enter the loop at top. | 901 | * it is intended not to enter the loop at top. | |
901 | */ | 902 | */ | |
902 | if (tn1 != NULL && !reached) { | 903 | if (tn1 != NULL && !reached) { | |
903 | /* loop not entered at top */ | 904 | /* loop not entered at top */ | |
904 | warning(207); | 905 | warning(207); | |
905 | set_reached(true); | 906 | set_reached(true); | |
906 | } | 907 | } | |
907 | 908 | |||
908 | begin_control_statement(CS_FOR); | 909 | begin_control_statement(CS_FOR); | |
909 | cstmt->c_loop = true; | 910 | cstmt->c_loop = true; | |
910 | 911 | |||
911 | /* | 912 | /* | |
912 | * Store the tree memory for the reinitialization expression. | 913 | * Store the tree memory for the reinitialization expression. | |
913 | * Also remember this expression itself. We must check it at | 914 | * Also remember this expression itself. We must check it at | |
914 | * the end of the loop to get "used but not set" warnings correct. | 915 | * the end of the loop to get "used but not set" warnings correct. | |
915 | */ | 916 | */ | |
916 | cstmt->c_for_expr3_mem = expr_save_memory(); | 917 | cstmt->c_for_expr3_mem = expr_save_memory(); | |
917 | cstmt->c_for_expr3 = tn3; | 918 | cstmt->c_for_expr3 = tn3; | |
918 | cstmt->c_for_expr3_pos = curr_pos; | 919 | cstmt->c_for_expr3_pos = curr_pos; | |
919 | cstmt->c_for_expr3_csrc_pos = csrc_pos; | 920 | cstmt->c_for_expr3_csrc_pos = csrc_pos; | |
920 | 921 | |||
921 | if (tn1 != NULL) | 922 | if (tn1 != NULL) | |
922 | expr(tn1, false, false, true, false); | 923 | expr(tn1, false, false, true, false); | |
923 | 924 | |||
924 | if (tn2 != NULL) | 925 | if (tn2 != NULL) | |
925 | tn2 = check_controlling_expression(tn2); | 926 | tn2 = check_controlling_expression(tn2); | |
926 | if (tn2 != NULL) | 927 | if (tn2 != NULL) | |
927 | expr(tn2, false, true, true, false); | 928 | expr(tn2, false, true, true, false); | |
928 | 929 | |||
929 | cstmt->c_maybe_endless = tn2 == NULL || is_nonzero(tn2); | 930 | cstmt->c_maybe_endless = tn2 == NULL || is_nonzero(tn2); | |
930 | 931 | |||
931 | /* Checking the reinitialization expression is done in for2() */ | 932 | /* Checking the reinitialization expression is done in for2() */ | |
932 | 933 | |||
933 | set_reached(!is_zero(tn2)); | 934 | set_reached(!is_zero(tn2)); | |
934 | } | 935 | } | |
935 | 936 | |||
936 | /* | 937 | /* | |
937 | * for_exprs statement | 938 | * for_exprs statement | |
938 | * for_exprs error | 939 | * for_exprs error | |
939 | */ | 940 | */ | |
940 | void | 941 | void | |
941 | for2(void) | 942 | for2(void) | |
942 | { | 943 | { | |
943 | pos_t cpos, cspos; | 944 | pos_t cpos, cspos; | |
944 | tnode_t *tn3; | 945 | tnode_t *tn3; | |
945 | 946 | |||
946 | if (cstmt->c_continue) | 947 | if (cstmt->c_continue) | |
947 | set_reached(true); | 948 | set_reached(true); | |
948 | 949 | |||
949 | cpos = curr_pos; | 950 | cpos = curr_pos; | |
950 | cspos = csrc_pos; | 951 | cspos = csrc_pos; | |
951 | 952 | |||
952 | /* Restore the tree memory for the reinitialization expression */ | 953 | /* Restore the tree memory for the reinitialization expression */ | |
953 | expr_restore_memory(cstmt->c_for_expr3_mem); | 954 | expr_restore_memory(cstmt->c_for_expr3_mem); | |
954 | tn3 = cstmt->c_for_expr3; | 955 | tn3 = cstmt->c_for_expr3; | |
955 | curr_pos = cstmt->c_for_expr3_pos; | 956 | curr_pos = cstmt->c_for_expr3_pos; | |
956 | csrc_pos = cstmt->c_for_expr3_csrc_pos; | 957 | csrc_pos = cstmt->c_for_expr3_csrc_pos; | |
957 | 958 | |||
958 | /* simply "statement not reached" would be confusing */ | 959 | /* simply "statement not reached" would be confusing */ | |
959 | if (!reached && warn_about_unreachable) { | 960 | if (!reached && warn_about_unreachable) { | |
960 | /* end-of-loop code not reached */ | 961 | /* end-of-loop code not reached */ | |
961 | warning(223); | 962 | warning(223); | |
962 | set_reached(true); | 963 | set_reached(true); | |
963 | } | 964 | } | |
964 | 965 | |||
965 | if (tn3 != NULL) { | 966 | if (tn3 != NULL) { | |
966 | expr(tn3, false, false, true, false); | 967 | expr(tn3, false, false, true, false); | |
967 | } else { | 968 | } else { | |
968 | expr_free_all(); | 969 | expr_free_all(); | |
969 | } | 970 | } | |
970 | 971 | |||
971 | curr_pos = cpos; | 972 | curr_pos = cpos; | |
972 | csrc_pos = cspos; | 973 | csrc_pos = cspos; | |
973 | 974 | |||
974 | /* An endless loop without break will never terminate */ | 975 | /* An endless loop without break will never terminate */ | |
975 | /* TODO: What if the loop contains a 'return'? */ | 976 | /* TODO: What if the loop contains a 'return'? */ | |
976 | set_reached(cstmt->c_break || !cstmt->c_maybe_endless); | 977 | set_reached(cstmt->c_break || !cstmt->c_maybe_endless); | |
977 | 978 | |||
978 | end_control_statement(CS_FOR); | 979 | end_control_statement(CS_FOR); | |
979 | } | 980 | } | |
980 | 981 | |||
981 | /* | 982 | /* | |
982 | * T_GOTO identifier T_SEMI | 983 | * T_GOTO identifier T_SEMI | |
983 | */ | 984 | */ | |
984 | void | 985 | void | |
985 | do_goto(sym_t *lab) | 986 | do_goto(sym_t *lab) | |
986 | { | 987 | { | |
987 | 988 | |||
988 | mark_as_used(lab, false, false); | 989 | mark_as_used(lab, false, false); | |
989 | 990 | |||
990 | check_statement_reachable(); | 991 | check_statement_reachable(); | |
991 | 992 | |||
992 | set_reached(false); | 993 | set_reached(false); | |
993 | } | 994 | } | |
994 | 995 | |||
995 | /* | 996 | /* | |
996 | * T_BREAK T_SEMI | 997 | * T_BREAK T_SEMI | |
997 | */ | 998 | */ | |
998 | void | 999 | void | |
999 | do_break(void) | 1000 | do_break(void) | |
1000 | { | 1001 | { | |
1001 | control_statement *cs; | 1002 | control_statement *cs; | |
1002 | 1003 | |||
1003 | cs = cstmt; | 1004 | cs = cstmt; | |
1004 | while (cs != NULL && !cs->c_loop && !cs->c_switch) | 1005 | while (cs != NULL && !cs->c_loop && !cs->c_switch) | |
1005 | cs = cs->c_surrounding; | 1006 | cs = cs->c_surrounding; | |
1006 | 1007 | |||
1007 | if (cs == NULL) { | 1008 | if (cs == NULL) { | |
1008 | /* break outside loop or switch */ | 1009 | /* break outside loop or switch */ | |
1009 | error(208); | 1010 | error(208); | |
1010 | } else { | 1011 | } else { | |
1011 | if (reached) | 1012 | if (reached) | |
1012 | cs->c_break = true; | 1013 | cs->c_break = true; | |
1013 | } | 1014 | } | |
1014 | 1015 | |||
1015 | if (bflag) | 1016 | if (bflag) | |
1016 | check_statement_reachable(); | 1017 | check_statement_reachable(); | |
1017 | 1018 | |||
1018 | set_reached(false); | 1019 | set_reached(false); | |
1019 | } | 1020 | } | |
1020 | 1021 | |||
1021 | /* | 1022 | /* | |
1022 | * T_CONTINUE T_SEMI | 1023 | * T_CONTINUE T_SEMI | |
1023 | */ | 1024 | */ | |
1024 | void | 1025 | void | |
1025 | do_continue(void) | 1026 | do_continue(void) | |
1026 | { | 1027 | { | |
1027 | control_statement *cs; | 1028 | control_statement *cs; | |
1028 | 1029 | |||
1029 | for (cs = cstmt; cs != NULL && !cs->c_loop; cs = cs->c_surrounding) | 1030 | for (cs = cstmt; cs != NULL && !cs->c_loop; cs = cs->c_surrounding) | |
1030 | continue; | 1031 | continue; | |
1031 | 1032 | |||
1032 | if (cs == NULL) { | 1033 | if (cs == NULL) { | |
1033 | /* continue outside loop */ | 1034 | /* continue outside loop */ | |
1034 | error(209); | 1035 | error(209); | |
1035 | } else { | 1036 | } else { | |
1036 | /* TODO: only if reachable, for symmetry with c_break */ | 1037 | /* TODO: only if reachable, for symmetry with c_break */ | |
1037 | cs->c_continue = true; | 1038 | cs->c_continue = true; | |
1038 | } | 1039 | } | |
1039 | 1040 | |||
1040 | check_statement_reachable(); | 1041 | check_statement_reachable(); | |
1041 | 1042 | |||
1042 | set_reached(false); | 1043 | set_reached(false); | |
1043 | } | 1044 | } | |
1044 | 1045 | |||
1045 | /* | 1046 | /* | |
1046 | * T_RETURN T_SEMI | 1047 | * T_RETURN T_SEMI | |
1047 | * T_RETURN expr T_SEMI | 1048 | * T_RETURN expr T_SEMI | |
1048 | */ | 1049 | */ | |
1049 | void | 1050 | void | |
1050 | do_return(bool sys, tnode_t *tn) | 1051 | do_return(bool sys, tnode_t *tn) | |
1051 | { | 1052 | { | |
1052 | tnode_t *ln, *rn; | 1053 | tnode_t *ln, *rn; | |
1053 | control_statement *cs; | 1054 | control_statement *cs; | |
1054 | op_t op; | 1055 | op_t op; | |
1055 | 1056 | |||
1056 | cs = cstmt; | 1057 | cs = cstmt; | |
1057 | if (cs == NULL) { | 1058 | if (cs == NULL) { | |
1058 | /* syntax error '%s' */ | 1059 | /* syntax error '%s' */ | |
1059 | error(249, "return outside function"); | 1060 | error(249, "return outside function"); | |
1060 | return; | 1061 | return; | |
1061 | } | 1062 | } | |
1062 | 1063 | |||
1063 | for (; cs->c_surrounding != NULL; cs = cs->c_surrounding) | 1064 | for (; cs->c_surrounding != NULL; cs = cs->c_surrounding) | |
1064 | continue; | 1065 | continue; | |
1065 | 1066 | |||
1066 | if (tn != NULL) | 1067 | if (tn != NULL) | |
1067 | cs->c_had_return_value = true; | 1068 | cs->c_had_return_value = true; | |
1068 | else | 1069 | else | |
1069 | cs->c_had_return_noval = true; | 1070 | cs->c_had_return_noval = true; | |
1070 | 1071 | |||
1071 | if (tn != NULL && funcsym->s_type->t_subt->t_tspec == VOID) { | 1072 | if (tn != NULL && funcsym->s_type->t_subt->t_tspec == VOID) { | |
1072 | /* void function %s cannot return value */ | 1073 | /* void function %s cannot return value */ | |
1073 | error(213, funcsym->s_name); | 1074 | error(213, funcsym->s_name); | |
1074 | expr_free_all(); | 1075 | expr_free_all(); | |
1075 | tn = NULL; | 1076 | tn = NULL; | |
1076 | } else if (tn == NULL && funcsym->s_type->t_subt->t_tspec != VOID) { | 1077 | } else if (tn == NULL && funcsym->s_type->t_subt->t_tspec != VOID) { | |
1077 | /* | 1078 | /* | |
1078 | * Assume that the function has a return value only if it | 1079 | * Assume that the function has a return value only if it | |
1079 | * is explicitly declared. | 1080 | * is explicitly declared. | |
1080 | */ | 1081 | */ | |
1081 | if (!funcsym->s_return_type_implicit_int) | 1082 | if (!funcsym->s_return_type_implicit_int) | |
1082 | /* function '%s' expects to return value */ | 1083 | /* function '%s' expects to return value */ | |
1083 | warning(214, funcsym->s_name); | 1084 | warning(214, funcsym->s_name); | |
1084 | } | 1085 | } | |
1085 | 1086 | |||
1086 | if (tn != NULL) { | 1087 | if (tn != NULL) { | |
1087 | 1088 | |||
1088 | /* Create a temporary node for the left side */ | 1089 | /* Create a temporary node for the left side */ | |
1089 | ln = expr_zero_alloc(sizeof(*ln)); | 1090 | ln = expr_zero_alloc(sizeof(*ln)); | |
1090 | ln->tn_op = NAME; | 1091 | ln->tn_op = NAME; | |
1091 | ln->tn_type = expr_unqualified_type(funcsym->s_type->t_subt); | 1092 | ln->tn_type = expr_unqualified_type(funcsym->s_type->t_subt); | |
1092 | ln->tn_lvalue = true; | 1093 | ln->tn_lvalue = true; | |
1093 | ln->tn_sym = funcsym; /* better than nothing */ | 1094 | ln->tn_sym = funcsym; /* better than nothing */ | |
1094 | 1095 | |||
1095 | tn = build_binary(ln, RETURN, sys, tn); | 1096 | tn = build_binary(ln, RETURN, sys, tn); | |
1096 | 1097 | |||
1097 | if (tn != NULL) { | 1098 | if (tn != NULL) { | |
1098 | rn = tn->tn_right; | 1099 | rn = tn->tn_right; | |
1099 | while ((op = rn->tn_op) == CVT || op == PLUS) | 1100 | while ((op = rn->tn_op) == CVT || op == PLUS) | |
1100 | rn = rn->tn_left; | 1101 | rn = rn->tn_left; | |
1101 | if (rn->tn_op == ADDR && rn->tn_left->tn_op == NAME && | 1102 | if (rn->tn_op == ADDR && rn->tn_left->tn_op == NAME && | |
1102 | rn->tn_left->tn_sym->s_scl == AUTO) { | 1103 | rn->tn_left->tn_sym->s_scl == AUTO) { | |
1103 | /* %s returns pointer to automatic object */ | 1104 | /* %s returns pointer to automatic object */ | |
1104 | warning(302, funcsym->s_name); | 1105 | warning(302, funcsym->s_name); | |
1105 | } | 1106 | } | |
1106 | } | 1107 | } | |
1107 | 1108 | |||
1108 | expr(tn, true, false, true, false); | 1109 | expr(tn, true, false, true, false); | |
1109 | 1110 | |||
1110 | } else { | 1111 | } else { | |
1111 | 1112 | |||
1112 | check_statement_reachable(); | 1113 | check_statement_reachable(); | |
1113 | 1114 | |||
1114 | } | 1115 | } | |
1115 | 1116 | |||
1116 | set_reached(false); | 1117 | set_reached(false); | |
1117 | } | 1118 | } | |
1118 | 1119 | |||
1119 | /* | 1120 | /* | |
1120 | * Do some cleanup after a global declaration or definition. | 1121 | * Do some cleanup after a global declaration or definition. | |
1121 | * Especially remove information about unused lint comments. | 1122 | * Especially remove information about unused lint comments. | |
1122 | */ | 1123 | */ | |
1123 | void | 1124 | void | |
1124 | global_clean_up_decl(bool silent) | 1125 | global_clean_up_decl(bool silent) | |
1125 | { | 1126 | { | |
1126 | 1127 | |||
1127 | if (nargusg != -1) { | 1128 | if (nargusg != -1) { | |
1128 | if (!silent) { | 1129 | if (!silent) { | |
1129 | /* must precede function definition: ** %s ** */ | 1130 | /* must precede function definition: ** %s ** */ | |
1130 | warning_at(282, &argsused_pos, "ARGSUSED"); | 1131 | warning_at(282, &argsused_pos, "ARGSUSED"); | |
1131 | } | 1132 | } | |
1132 | nargusg = -1; | 1133 | nargusg = -1; | |
1133 | } | 1134 | } | |
1134 | if (nvararg != -1) { | 1135 | if (nvararg != -1) { | |
1135 | if (!silent) { | 1136 | if (!silent) { | |
1136 | /* must precede function definition: ** %s ** */ | 1137 | /* must precede function definition: ** %s ** */ | |
1137 | warning_at(282, &vapos, "VARARGS"); | 1138 | warning_at(282, &vapos, "VARARGS"); | |
1138 | } | 1139 | } | |
1139 | nvararg = -1; | 1140 | nvararg = -1; | |
1140 | } | 1141 | } | |
1141 | if (printflike_argnum != -1) { | 1142 | if (printflike_argnum != -1) { | |
1142 | if (!silent) { | 1143 | if (!silent) { | |
1143 | /* must precede function definition: ** %s ** */ | 1144 | /* must precede function definition: ** %s ** */ | |
1144 | warning_at(282, &printflike_pos, "PRINTFLIKE"); | 1145 | warning_at(282, &printflike_pos, "PRINTFLIKE"); | |
1145 | } | 1146 | } | |
1146 | printflike_argnum = -1; | 1147 | printflike_argnum = -1; | |
1147 | } | 1148 | } | |
1148 | if (scanflike_argnum != -1) { | 1149 | if (scanflike_argnum != -1) { | |
1149 | if (!silent) { | 1150 | if (!silent) { | |
1150 | /* must precede function definition: ** %s ** */ | 1151 | /* must precede function definition: ** %s ** */ | |
1151 | warning_at(282, &scanflike_pos, "SCANFLIKE"); | 1152 | warning_at(282, &scanflike_pos, "SCANFLIKE"); | |
1152 | } | 1153 | } | |
1153 | scanflike_argnum = -1; | 1154 | scanflike_argnum = -1; | |
1154 | } | 1155 | } | |
1155 | 1156 | |||
1156 | dcs->d_asm = false; | 1157 | dcs->d_asm = false; | |
1157 | 1158 | |||
1158 | /* | 1159 | /* | |
1159 | * Needed for BSD yacc in case of parse errors; GNU Bison 3.0.4 is | 1160 | * Needed for BSD yacc in case of parse errors; GNU Bison 3.0.4 is | |
1160 | * fine. See test gcc_attribute.c, function_with_unknown_attribute. | 1161 | * fine. See test gcc_attribute.c, function_with_unknown_attribute. | |
1161 | */ | 1162 | */ | |
1162 | in_gcc_attribute = false; | 1163 | in_gcc_attribute = false; | |
1163 | } | 1164 | } | |
1164 | 1165 | |||
1165 | /* | 1166 | /* | |
1166 | * ARGSUSED comment | 1167 | * ARGSUSED comment | |
1167 | * | 1168 | * | |
1168 | * Only the first n arguments of the following function are checked | 1169 | * Only the first n arguments of the following function are checked | |
1169 | * for usage. A missing argument is taken to be 0. | 1170 | * for usage. A missing argument is taken to be 0. | |
1170 | */ | 1171 | */ | |
1171 | void | 1172 | void | |
1172 | argsused(int n) | 1173 | argsused(int n) | |
1173 | { | 1174 | { | |
1174 | 1175 | |||
1175 | if (n == -1) | 1176 | if (n == -1) | |
1176 | n = 0; | 1177 | n = 0; | |
1177 | 1178 | |||
1178 | if (dcs->d_ctx != EXTERN) { | 1179 | if (dcs->d_ctx != EXTERN) { | |
1179 | /* must be outside function: ** %s ** */ | 1180 | /* must be outside function: ** %s ** */ | |
1180 | warning(280, "ARGSUSED"); | 1181 | warning(280, "ARGSUSED"); | |
1181 | return; | 1182 | return; | |
1182 | } | 1183 | } | |
1183 | if (nargusg != -1) { | 1184 | if (nargusg != -1) { | |
1184 | /* duplicate use of ** %s ** */ | 1185 | /* duplicate use of ** %s ** */ | |
1185 | warning(281, "ARGSUSED"); | 1186 | warning(281, "ARGSUSED"); | |
1186 | } | 1187 | } | |
1187 | nargusg = n; | 1188 | nargusg = n; | |
1188 | argsused_pos = curr_pos; | 1189 | argsused_pos = curr_pos; | |
1189 | } | 1190 | } | |
1190 | 1191 | |||
1191 | /* | 1192 | /* | |
1192 | * VARARGS comment | 1193 | * VARARGS comment | |
1193 | * | 1194 | * | |
1194 | * Causes lint2 to check only the first n arguments for compatibility | 1195 | * Causes lint2 to check only the first n arguments for compatibility | |
1195 | * with the function definition. A missing argument is taken to be 0. | 1196 | * with the function definition. A missing argument is taken to be 0. | |
1196 | */ | 1197 | */ | |
1197 | void | 1198 | void | |
1198 | varargs(int n) | 1199 | varargs(int n) | |
1199 | { | 1200 | { | |
1200 | 1201 | |||
1201 | if (n == -1) | 1202 | if (n == -1) | |
1202 | n = 0; | 1203 | n = 0; | |
1203 | 1204 | |||
1204 | if (dcs->d_ctx != EXTERN) { | 1205 | if (dcs->d_ctx != EXTERN) { | |
1205 | /* must be outside function: ** %s ** */ | 1206 | /* must be outside function: ** %s ** */ | |
1206 | warning(280, "VARARGS"); | 1207 | warning(280, "VARARGS"); | |
1207 | return; | 1208 | return; | |
1208 | } | 1209 | } | |
1209 | if (nvararg != -1) { | 1210 | if (nvararg != -1) { | |
1210 | /* duplicate use of ** %s ** */ | 1211 | /* duplicate use of ** %s ** */ | |
1211 | warning(281, "VARARGS"); | 1212 | warning(281, "VARARGS"); | |
1212 | } | 1213 | } | |
1213 | nvararg = n; | 1214 | nvararg = n; | |
1214 | vapos = curr_pos; | 1215 | vapos = curr_pos; | |
1215 | } | 1216 | } | |
1216 | 1217 | |||
1217 | /* | 1218 | /* | |
1218 | * PRINTFLIKE comment | 1219 | * PRINTFLIKE comment | |
1219 | * | 1220 | * | |
1220 | * Check all arguments until the (n-1)-th as usual. The n-th argument is | 1221 | * Check all arguments until the (n-1)-th as usual. The n-th argument is | |
1221 | * used the check the types of remaining arguments. | 1222 | * used the check the types of remaining arguments. | |
1222 | */ | 1223 | */ | |
1223 | void | 1224 | void | |
1224 | printflike(int n) | 1225 | printflike(int n) | |
1225 | { | 1226 | { | |
1226 | 1227 | |||
1227 | if (n == -1) | 1228 | if (n == -1) | |
1228 | n = 0; | 1229 | n = 0; | |
1229 | 1230 | |||
1230 | if (dcs->d_ctx != EXTERN) { | 1231 | if (dcs->d_ctx != EXTERN) { | |
1231 | /* must be outside function: ** %s ** */ | 1232 | /* must be outside function: ** %s ** */ | |
1232 | warning(280, "PRINTFLIKE"); | 1233 | warning(280, "PRINTFLIKE"); | |
1233 | return; | 1234 | return; | |
1234 | } | 1235 | } | |
1235 | if (printflike_argnum != -1) { | 1236 | if (printflike_argnum != -1) { | |
1236 | /* duplicate use of ** %s ** */ | 1237 | /* duplicate use of ** %s ** */ | |
1237 | warning(281, "PRINTFLIKE"); | 1238 | warning(281, "PRINTFLIKE"); |
--- src/usr.bin/xlint/lint1/lex.c 2022/02/27 08:31:26 1.101
+++ src/usr.bin/xlint/lint1/lex.c 2022/02/27 10:44:45 1.102
@@ -1,1542 +1,1542 @@ | @@ -1,1542 +1,1542 @@ | |||
1 | /* $NetBSD: lex.c,v 1.101 2022/02/27 08:31:26 rillig Exp $ */ | 1 | /* $NetBSD: lex.c,v 1.102 2022/02/27 10:44:45 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: lex.c,v 1.101 2022/02/27 08:31:26 rillig Exp $"); | 41 | __RCSID("$NetBSD: lex.c,v 1.102 2022/02/27 10:44:45 rillig Exp $"); | |
42 | #endif | 42 | #endif | |
43 | 43 | |||
44 | #include <ctype.h> | 44 | #include <ctype.h> | |
45 | #include <errno.h> | 45 | #include <errno.h> | |
46 | #include <float.h> | 46 | #include <float.h> | |
47 | #include <limits.h> | 47 | #include <limits.h> | |
48 | #include <math.h> | 48 | #include <math.h> | |
49 | #include <stdlib.h> | 49 | #include <stdlib.h> | |
50 | #include <string.h> | 50 | #include <string.h> | |
51 | 51 | |||
52 | #include "lint1.h" | 52 | #include "lint1.h" | |
53 | #include "cgram.h" | 53 | #include "cgram.h" | |
54 | 54 | |||
55 | #define CHAR_MASK ((1U << CHAR_SIZE) - 1) | 55 | #define CHAR_MASK ((1U << CHAR_SIZE) - 1) | |
56 | 56 | |||
57 | 57 | |||
58 | /* Current position (it's also updated when an included file is parsed) */ | 58 | /* Current position (it's also updated when an included file is parsed) */ | |
59 | pos_t curr_pos = { "", 1, 0 }; | 59 | pos_t curr_pos = { "", 1, 0 }; | |
60 | 60 | |||
61 | /* | 61 | /* | |
62 | * Current position in C source (not updated when an included file is | 62 | * Current position in C source (not updated when an included file is | |
63 | * parsed). | 63 | * parsed). | |
64 | */ | 64 | */ | |
65 | pos_t csrc_pos = { "", 1, 0 }; | 65 | pos_t csrc_pos = { "", 1, 0 }; | |
66 | 66 | |||
67 | bool in_gcc_attribute; | 67 | bool in_gcc_attribute; | |
68 | bool in_system_header; | 68 | bool in_system_header; | |
69 | 69 | |||
70 | static int inpc(void); | 70 | static int inpc(void); | |
71 | static unsigned int hash(const char *); | 71 | static unsigned int hash(const char *); | |
72 | static sym_t * search(sbuf_t *); | 72 | static sym_t * search(sbuf_t *); | |
73 | static int keyw(sym_t *); | 73 | static int keyw(sym_t *); | |
74 | static int get_escaped_char(int); | 74 | static int get_escaped_char(int); | |
75 | 75 | |||
76 | void | 76 | void | |
77 | lex_next_line(void) | 77 | lex_next_line(void) | |
78 | { | 78 | { | |
79 | curr_pos.p_line++; | 79 | curr_pos.p_line++; | |
80 | curr_pos.p_uniq = 0; | 80 | curr_pos.p_uniq = 0; | |
81 | debug_step("parsing %s:%d", curr_pos.p_file, curr_pos.p_line); | 81 | debug_step("parsing %s:%d", curr_pos.p_file, curr_pos.p_line); | |
82 | if (curr_pos.p_file == csrc_pos.p_file) { | 82 | if (curr_pos.p_file == csrc_pos.p_file) { | |
83 | csrc_pos.p_line++; | 83 | csrc_pos.p_line++; | |
84 | csrc_pos.p_uniq = 0; | 84 | csrc_pos.p_uniq = 0; | |
85 | } | 85 | } | |
86 | } | 86 | } | |
87 | 87 | |||
88 | void | 88 | void | |
89 | lex_unknown_character(int c) | 89 | lex_unknown_character(int c) | |
90 | { | 90 | { | |
91 | 91 | |||
92 | /* unknown character \%o */ | 92 | /* unknown character \%o */ | |
93 | error(250, c); | 93 | error(250, c); | |
94 | } | 94 | } | |
95 | 95 | |||
96 | #define kwdef(name, token, scl, tspec, tqual, c90, c99, gcc, attr, deco) \ | 96 | #define kwdef(name, token, scl, tspec, tqual, c90, c99, gcc, attr, deco) \ | |
97 | { \ | 97 | { \ | |
98 | name, token, scl, tspec, tqual, \ | 98 | name, token, scl, tspec, tqual, \ | |
99 | (c90) > 0, (c99) > 0, (gcc) > 0, (attr) > 0, \ | 99 | (c90) > 0, (c99) > 0, (gcc) > 0, (attr) > 0, \ | |
100 | ((deco) & 1) != 0, ((deco) & 2) != 0, ((deco) & 4) != 0, \ | 100 | ((deco) & 1) != 0, ((deco) & 2) != 0, ((deco) & 4) != 0, \ | |
101 | } | 101 | } | |
102 | #define kwdef_token(name, token, c90, c99, gcc, attr, deco) \ | 102 | #define kwdef_token(name, token, c90, c99, gcc, attr, deco) \ | |
103 | kwdef(name, token, 0, 0, 0, c90, c99, gcc, attr, deco) | 103 | kwdef(name, token, 0, 0, 0, c90, c99, gcc, attr, deco) | |
104 | #define kwdef_sclass(name, sclass, c90, c99, gcc, attr, deco) \ | 104 | #define kwdef_sclass(name, sclass, c90, c99, gcc, attr, deco) \ | |
105 | kwdef(name, T_SCLASS, sclass, 0, 0, c90, c99, gcc, attr, deco) | 105 | kwdef(name, T_SCLASS, sclass, 0, 0, c90, c99, gcc, attr, deco) | |
106 | #define kwdef_type(name, tspec, c90, c99, gcc, attr, deco) \ | 106 | #define kwdef_type(name, tspec, c90, c99, gcc, attr, deco) \ | |
107 | kwdef(name, T_TYPE, 0, tspec, 0, c90, c99, gcc, attr, deco) | 107 | kwdef(name, T_TYPE, 0, tspec, 0, c90, c99, gcc, attr, deco) | |
108 | #define kwdef_tqual(name, tqual, c90, c99, gcc, attr, deco) \ | 108 | #define kwdef_tqual(name, tqual, c90, c99, gcc, attr, deco) \ | |
109 | kwdef(name, T_QUAL, 0, 0, tqual, c90, c99, gcc, attr, deco) | 109 | kwdef(name, T_QUAL, 0, 0, tqual, c90, c99, gcc, attr, deco) | |
110 | #define kwdef_keyword(name, token) \ | 110 | #define kwdef_keyword(name, token) \ | |
111 | kwdef(name, token, 0, 0, 0, 0, 0, 0, 0, 1) | 111 | kwdef(name, token, 0, 0, 0, 0, 0, 0, 0, 1) | |
112 | #define kwdef_gcc_attr(name, token) \ | 112 | #define kwdef_gcc_attr(name, token) \ | |
113 | kwdef(name, token, 0, 0, 0, 0, 0, 1, 1, 5) | 113 | kwdef(name, token, 0, 0, 0, 0, 0, 1, 1, 5) | |
114 | 114 | |||
115 | /* During initialization, these keywords are written to the symbol table. */ | 115 | /* During initialization, these keywords are written to the symbol table. */ | |
116 | static struct keyword { | 116 | static struct keyword { | |
117 | const char *kw_name; /* keyword */ | 117 | const char *kw_name; /* keyword */ | |
118 | int kw_token; /* token returned by yylex() */ | 118 | int kw_token; /* token returned by yylex() */ | |
119 | scl_t kw_scl; /* storage class if kw_token T_SCLASS */ | 119 | scl_t kw_scl; /* storage class if kw_token T_SCLASS */ | |
120 | tspec_t kw_tspec; /* type spec. if kw_token | 120 | tspec_t kw_tspec; /* type spec. if kw_token | |
121 | * T_TYPE or T_STRUCT_OR_UNION */ | 121 | * T_TYPE or T_STRUCT_OR_UNION */ | |
122 | tqual_t kw_tqual; /* type qual. if kw_token T_QUAL */ | 122 | tqual_t kw_tqual; /* type qual. if kw_token T_QUAL */ | |
123 | bool kw_c90:1; /* C90 keyword */ | 123 | bool kw_c90:1; /* C90 keyword */ | |
124 | bool kw_c99:1; /* C99 keyword */ | 124 | bool kw_c99:1; /* C99 keyword */ | |
125 | bool kw_gcc:1; /* GCC keyword */ | 125 | bool kw_gcc:1; /* GCC keyword */ | |
126 | bool kw_attr:1; /* GCC attribute, keyword */ | 126 | bool kw_attr:1; /* GCC attribute, keyword */ | |
127 | bool kw_plain:1; /* 'name' */ | 127 | bool kw_plain:1; /* 'name' */ | |
128 | bool kw_leading:1; /* '__name' */ | 128 | bool kw_leading:1; /* '__name' */ | |
129 | bool kw_both:1; /* '__name__' */ | 129 | bool kw_both:1; /* '__name__' */ | |
130 | } keywords[] = { | 130 | } keywords[] = { | |
131 | kwdef_gcc_attr( "alias", T_AT_ALIAS), | 131 | kwdef_gcc_attr( "alias", T_AT_ALIAS), | |
132 | kwdef_keyword( "_Alignas", T_ALIGNAS), | 132 | kwdef_keyword( "_Alignas", T_ALIGNAS), | |
133 | kwdef_keyword( "_Alignof", T_ALIGNOF), | 133 | kwdef_keyword( "_Alignof", T_ALIGNOF), | |
134 | kwdef_gcc_attr( "aligned", T_AT_ALIGNED), | 134 | kwdef_gcc_attr( "aligned", T_AT_ALIGNED), | |
135 | kwdef_token( "__alignof__", T_ALIGNOF, 0,0,0,0,1), | 135 | kwdef_token( "__alignof__", T_ALIGNOF, 0,0,0,0,1), | |
136 | kwdef_gcc_attr( "alloc_size", T_AT_ALLOC_SIZE), | 136 | kwdef_gcc_attr( "alloc_size", T_AT_ALLOC_SIZE), | |
137 | kwdef_gcc_attr( "always_inline",T_AT_ALWAYS_INLINE), | 137 | kwdef_gcc_attr( "always_inline",T_AT_ALWAYS_INLINE), | |
138 | kwdef_token( "asm", T_ASM, 0,0,1,0,7), | 138 | kwdef_token( "asm", T_ASM, 0,0,1,0,7), | |
139 | kwdef_token( "attribute", T_ATTRIBUTE, 0,0,1,0,6), | 139 | kwdef_token( "attribute", T_ATTRIBUTE, 0,0,1,0,6), | |
140 | kwdef_sclass( "auto", AUTO, 0,0,0,0,1), | 140 | kwdef_sclass( "auto", AUTO, 0,0,0,0,1), | |
141 | kwdef_type( "_Bool", BOOL, 0,1,0,0,1), | 141 | kwdef_type( "_Bool", BOOL, 0,1,0,0,1), | |
142 | kwdef_gcc_attr( "bounded", T_AT_BOUNDED), | 142 | kwdef_gcc_attr( "bounded", T_AT_BOUNDED), | |
143 | kwdef_keyword( "break", T_BREAK), | 143 | kwdef_keyword( "break", T_BREAK), | |
144 | kwdef_gcc_attr( "buffer", T_AT_BUFFER), | 144 | kwdef_gcc_attr( "buffer", T_AT_BUFFER), | |
145 | kwdef_token( "__builtin_offsetof", T_BUILTIN_OFFSETOF, 0,0,1,0,1), | 145 | kwdef_token( "__builtin_offsetof", T_BUILTIN_OFFSETOF, 0,0,1,0,1), | |
146 | kwdef_keyword( "case", T_CASE), | 146 | kwdef_keyword( "case", T_CASE), | |
147 | kwdef_type( "char", CHAR, 0,0,0,0,1), | 147 | kwdef_type( "char", CHAR, 0,0,0,0,1), | |
148 | kwdef_gcc_attr( "cold", T_AT_COLD), | 148 | kwdef_gcc_attr( "cold", T_AT_COLD), | |
149 | kwdef_gcc_attr( "common", T_AT_COMMON), | 149 | kwdef_gcc_attr( "common", T_AT_COMMON), | |
150 | kwdef_type( "_Complex", COMPLEX, 0,1,0,0,1), | 150 | kwdef_type( "_Complex", COMPLEX, 0,1,0,0,1), | |
151 | kwdef_tqual( "const", CONST, 1,0,0,0,7), | 151 | kwdef_tqual( "const", CONST, 1,0,0,0,7), | |
152 | kwdef_gcc_attr( "constructor", T_AT_CONSTRUCTOR), | 152 | kwdef_gcc_attr( "constructor", T_AT_CONSTRUCTOR), | |
153 | kwdef_keyword( "continue", T_CONTINUE), | 153 | kwdef_keyword( "continue", T_CONTINUE), | |
154 | kwdef_keyword( "default", T_DEFAULT), | 154 | kwdef_keyword( "default", T_DEFAULT), | |
155 | kwdef_gcc_attr( "deprecated", T_AT_DEPRECATED), | 155 | kwdef_gcc_attr( "deprecated", T_AT_DEPRECATED), | |
156 | kwdef_gcc_attr( "destructor", T_AT_DESTRUCTOR), | 156 | kwdef_gcc_attr( "destructor", T_AT_DESTRUCTOR), | |
157 | kwdef_gcc_attr( "disable_sanitizer_instrumentation", | 157 | kwdef_gcc_attr( "disable_sanitizer_instrumentation", | |
158 | T_AT_DISABLE_SANITIZER_INSTRUMENTATION), | 158 | T_AT_DISABLE_SANITIZER_INSTRUMENTATION), | |
159 | kwdef_keyword( "do", T_DO), | 159 | kwdef_keyword( "do", T_DO), | |
160 | kwdef_type( "double", DOUBLE, 0,0,0,0,1), | 160 | kwdef_type( "double", DOUBLE, 0,0,0,0,1), | |
161 | kwdef_keyword( "else", T_ELSE), | 161 | kwdef_keyword( "else", T_ELSE), | |
162 | kwdef_keyword( "enum", T_ENUM), | 162 | kwdef_keyword( "enum", T_ENUM), | |
163 | kwdef_token( "__extension__",T_EXTENSION, 0,0,1,0,1), | 163 | kwdef_token( "__extension__",T_EXTENSION, 0,0,1,0,1), | |
164 | kwdef_sclass( "extern", EXTERN, 0,0,0,0,1), | 164 | kwdef_sclass( "extern", EXTERN, 0,0,0,0,1), | |
165 | kwdef_gcc_attr( "fallthrough", T_AT_FALLTHROUGH), | 165 | kwdef_gcc_attr( "fallthrough", T_AT_FALLTHROUGH), | |
166 | kwdef_type( "float", FLOAT, 0,0,0,0,1), | 166 | kwdef_type( "float", FLOAT, 0,0,0,0,1), | |
167 | kwdef_keyword( "for", T_FOR), | 167 | kwdef_keyword( "for", T_FOR), | |
168 | kwdef_gcc_attr( "format", T_AT_FORMAT), | 168 | kwdef_gcc_attr( "format", T_AT_FORMAT), | |
169 | kwdef_gcc_attr( "format_arg", T_AT_FORMAT_ARG), | 169 | kwdef_gcc_attr( "format_arg", T_AT_FORMAT_ARG), | |
170 | kwdef_token( "_Generic", T_GENERIC, 0,1,0,0,1), | 170 | kwdef_token( "_Generic", T_GENERIC, 0,1,0,0,1), | |
171 | kwdef_gcc_attr( "gnu_inline", T_AT_GNU_INLINE), | 171 | kwdef_gcc_attr( "gnu_inline", T_AT_GNU_INLINE), | |
172 | kwdef_gcc_attr( "gnu_printf", T_AT_FORMAT_GNU_PRINTF), | 172 | kwdef_gcc_attr( "gnu_printf", T_AT_FORMAT_GNU_PRINTF), | |
173 | kwdef_keyword( "goto", T_GOTO), | 173 | kwdef_keyword( "goto", T_GOTO), | |
174 | kwdef_gcc_attr( "hot", T_AT_HOT), | 174 | kwdef_gcc_attr( "hot", T_AT_HOT), | |
175 | kwdef_keyword( "if", T_IF), | 175 | kwdef_keyword( "if", T_IF), | |
176 | kwdef_token( "__imag__", T_IMAG, 0,0,1,0,1), | 176 | kwdef_token( "__imag__", T_IMAG, 0,0,1,0,1), | |
177 | kwdef_sclass( "inline", INLINE, 0,1,0,0,7), | 177 | kwdef_sclass( "inline", INLINE, 0,1,0,0,7), | |
178 | kwdef_type( "int", INT, 0,0,0,0,1), | 178 | kwdef_type( "int", INT, 0,0,0,0,1), | |
179 | #ifdef INT128_SIZE | 179 | #ifdef INT128_SIZE | |
180 | kwdef_type( "__int128_t", INT128, 0,1,0,0,1), | 180 | kwdef_type( "__int128_t", INT128, 0,1,0,0,1), | |
181 | #endif | 181 | #endif | |
182 | kwdef_type( "long", LONG, 0,0,0,0,1), | 182 | kwdef_type( "long", LONG, 0,0,0,0,1), | |
183 | kwdef_gcc_attr( "malloc", T_AT_MALLOC), | 183 | kwdef_gcc_attr( "malloc", T_AT_MALLOC), | |
184 | kwdef_gcc_attr( "may_alias", T_AT_MAY_ALIAS), | 184 | kwdef_gcc_attr( "may_alias", T_AT_MAY_ALIAS), | |
185 | kwdef_gcc_attr( "minbytes", T_AT_MINBYTES), | 185 | kwdef_gcc_attr( "minbytes", T_AT_MINBYTES), | |
186 | kwdef_gcc_attr( "mode", T_AT_MODE), | 186 | kwdef_gcc_attr( "mode", T_AT_MODE), | |
187 | kwdef_gcc_attr("no_instrument_function", | 187 | kwdef_gcc_attr("no_instrument_function", | |
188 | T_AT_NO_INSTRUMENT_FUNCTION), | 188 | T_AT_NO_INSTRUMENT_FUNCTION), | |
189 | kwdef_gcc_attr( "no_sanitize", T_AT_NO_SANITIZE), | 189 | kwdef_gcc_attr( "no_sanitize", T_AT_NO_SANITIZE), | |
190 | kwdef_gcc_attr( "no_sanitize_thread", T_AT_NO_SANITIZE_THREAD), | 190 | kwdef_gcc_attr( "no_sanitize_thread", T_AT_NO_SANITIZE_THREAD), | |
191 | kwdef_gcc_attr( "noinline", T_AT_NOINLINE), | 191 | kwdef_gcc_attr( "noinline", T_AT_NOINLINE), | |
192 | kwdef_gcc_attr( "nonnull", T_AT_NONNULL), | 192 | kwdef_gcc_attr( "nonnull", T_AT_NONNULL), | |
193 | kwdef_gcc_attr( "nonstring", T_AT_NONSTRING), | 193 | kwdef_gcc_attr( "nonstring", T_AT_NONSTRING), | |
194 | kwdef_token( "_Noreturn", T_NORETURN, 0,1,0,0,1), | 194 | kwdef_token( "_Noreturn", T_NORETURN, 0,1,0,0,1), | |
195 | kwdef_gcc_attr( "noreturn", T_AT_NORETURN), | 195 | kwdef_gcc_attr( "noreturn", T_AT_NORETURN), | |
196 | kwdef_gcc_attr( "nothrow", T_AT_NOTHROW), | 196 | kwdef_gcc_attr( "nothrow", T_AT_NOTHROW), | |
197 | kwdef_gcc_attr( "optimize", T_AT_OPTIMIZE), | 197 | kwdef_gcc_attr( "optimize", T_AT_OPTIMIZE), | |
198 | kwdef_gcc_attr( "optnone", T_AT_OPTNONE), | 198 | kwdef_gcc_attr( "optnone", T_AT_OPTNONE), | |
199 | kwdef_gcc_attr( "packed", T_AT_PACKED), | 199 | kwdef_gcc_attr( "packed", T_AT_PACKED), | |
200 | kwdef_token( "__packed", T_PACKED, 0,0,0,0,1), | 200 | kwdef_token( "__packed", T_PACKED, 0,0,0,0,1), | |
201 | kwdef_gcc_attr( "pcs", T_AT_PCS), | 201 | kwdef_gcc_attr( "pcs", T_AT_PCS), | |
202 | kwdef_gcc_attr( "printf", T_AT_FORMAT_PRINTF), | 202 | kwdef_gcc_attr( "printf", T_AT_FORMAT_PRINTF), | |
203 | kwdef_gcc_attr( "pure", T_AT_PURE), | 203 | kwdef_gcc_attr( "pure", T_AT_PURE), | |
204 | kwdef_token( "__real__", T_REAL, 0,0,1,0,1), | 204 | kwdef_token( "__real__", T_REAL, 0,0,1,0,1), | |
205 | kwdef_sclass( "register", REG, 0,0,0,0,1), | 205 | kwdef_sclass( "register", REG, 0,0,0,0,1), | |
206 | kwdef_gcc_attr( "regparm", T_AT_REGPARM), | 206 | kwdef_gcc_attr( "regparm", T_AT_REGPARM), | |
207 | kwdef_tqual( "restrict", RESTRICT, 0,1,0,0,7), | 207 | kwdef_tqual( "restrict", RESTRICT, 0,1,0,0,7), | |
208 | kwdef_keyword( "return", T_RETURN), | 208 | kwdef_keyword( "return", T_RETURN), | |
209 | kwdef_gcc_attr( "returns_nonnull",T_AT_RETURNS_NONNULL), | 209 | kwdef_gcc_attr( "returns_nonnull",T_AT_RETURNS_NONNULL), | |
210 | kwdef_gcc_attr( "returns_twice",T_AT_RETURNS_TWICE), | 210 | kwdef_gcc_attr( "returns_twice",T_AT_RETURNS_TWICE), | |
211 | kwdef_gcc_attr( "scanf", T_AT_FORMAT_SCANF), | 211 | kwdef_gcc_attr( "scanf", T_AT_FORMAT_SCANF), | |
212 | kwdef_token( "section", T_AT_SECTION, 0,0,1,1,7), | 212 | kwdef_token( "section", T_AT_SECTION, 0,0,1,1,7), | |
213 | kwdef_gcc_attr( "sentinel", T_AT_SENTINEL), | 213 | kwdef_gcc_attr( "sentinel", T_AT_SENTINEL), | |
214 | kwdef_type( "short", SHORT, 0,0,0,0,1), | 214 | kwdef_type( "short", SHORT, 0,0,0,0,1), | |
215 | kwdef_type( "signed", SIGNED, 1,0,0,0,3), | 215 | kwdef_type( "signed", SIGNED, 1,0,0,0,3), | |
216 | kwdef_keyword( "sizeof", T_SIZEOF), | 216 | kwdef_keyword( "sizeof", T_SIZEOF), | |
217 | kwdef_sclass( "static", STATIC, 0,0,0,0,1), | 217 | kwdef_sclass( "static", STATIC, 0,0,0,0,1), | |
218 | kwdef_keyword( "_Static_assert", T_STATIC_ASSERT), | 218 | kwdef_keyword( "_Static_assert", T_STATIC_ASSERT), | |
219 | kwdef_gcc_attr( "strfmon", T_AT_FORMAT_STRFMON), | 219 | kwdef_gcc_attr( "strfmon", T_AT_FORMAT_STRFMON), | |
220 | kwdef_gcc_attr( "strftime", T_AT_FORMAT_STRFTIME), | 220 | kwdef_gcc_attr( "strftime", T_AT_FORMAT_STRFTIME), | |
221 | kwdef_gcc_attr( "string", T_AT_STRING), | 221 | kwdef_gcc_attr( "string", T_AT_STRING), | |
222 | kwdef("struct", T_STRUCT_OR_UNION, 0, STRUCT, 0, 0,0,0,0,1), | 222 | kwdef("struct", T_STRUCT_OR_UNION, 0, STRUCT, 0, 0,0,0,0,1), | |
223 | kwdef_keyword( "switch", T_SWITCH), | 223 | kwdef_keyword( "switch", T_SWITCH), | |
224 | kwdef_token( "__symbolrename", T_SYMBOLRENAME, 0,0,0,0,1), | 224 | kwdef_token( "__symbolrename", T_SYMBOLRENAME, 0,0,0,0,1), | |
225 | kwdef_gcc_attr( "syslog", T_AT_FORMAT_SYSLOG), | 225 | kwdef_gcc_attr( "syslog", T_AT_FORMAT_SYSLOG), | |
226 | kwdef_gcc_attr( "target", T_AT_TARGET), | 226 | kwdef_gcc_attr( "target", T_AT_TARGET), | |
227 | kwdef_tqual( "__thread", THREAD, 0,0,1,0,1), | 227 | kwdef_tqual( "__thread", THREAD, 0,0,1,0,1), | |
228 | kwdef_tqual( "_Thread_local", THREAD, 0,1,0,0,1), | 228 | kwdef_tqual( "_Thread_local", THREAD, 0,1,0,0,1), | |
229 | kwdef_gcc_attr( "tls_model", T_AT_TLS_MODEL), | 229 | kwdef_gcc_attr( "tls_model", T_AT_TLS_MODEL), | |
230 | kwdef_gcc_attr( "transparent_union", T_AT_TUNION), | 230 | kwdef_gcc_attr( "transparent_union", T_AT_TUNION), | |
231 | kwdef_sclass( "typedef", TYPEDEF, 0,0,0,0,1), | 231 | kwdef_sclass( "typedef", TYPEDEF, 0,0,0,0,1), | |
232 | kwdef_token( "typeof", T_TYPEOF, 0,0,1,0,7), | 232 | kwdef_token( "typeof", T_TYPEOF, 0,0,1,0,7), | |
233 | #ifdef INT128_SIZE | 233 | #ifdef INT128_SIZE | |
234 | kwdef_type( "__uint128_t", UINT128, 0,1,0,0,1), | 234 | kwdef_type( "__uint128_t", UINT128, 0,1,0,0,1), | |
235 | #endif | 235 | #endif | |
236 | kwdef("union", T_STRUCT_OR_UNION, 0, UNION, 0, 0,0,0,0,1), | 236 | kwdef("union", T_STRUCT_OR_UNION, 0, UNION, 0, 0,0,0,0,1), | |
237 | kwdef_type( "unsigned", UNSIGN, 0,0,0,0,1), | 237 | kwdef_type( "unsigned", UNSIGN, 0,0,0,0,1), | |
238 | kwdef_gcc_attr( "unused", T_AT_UNUSED), | 238 | kwdef_gcc_attr( "unused", T_AT_UNUSED), | |
239 | kwdef_gcc_attr( "used", T_AT_USED), | 239 | kwdef_gcc_attr( "used", T_AT_USED), | |
240 | kwdef_gcc_attr( "visibility", T_AT_VISIBILITY), | 240 | kwdef_gcc_attr( "visibility", T_AT_VISIBILITY), | |
241 | kwdef_type( "void", VOID, 0,0,0,0,1), | 241 | kwdef_type( "void", VOID, 0,0,0,0,1), | |
242 | kwdef_tqual( "volatile", VOLATILE, 1,0,0,0,7), | 242 | kwdef_tqual( "volatile", VOLATILE, 1,0,0,0,7), | |
243 | kwdef_gcc_attr( "warn_unused_result", T_AT_WARN_UNUSED_RESULT), | 243 | kwdef_gcc_attr( "warn_unused_result", T_AT_WARN_UNUSED_RESULT), | |
244 | kwdef_gcc_attr( "weak", T_AT_WEAK), | 244 | kwdef_gcc_attr( "weak", T_AT_WEAK), | |
245 | kwdef_keyword( "while", T_WHILE), | 245 | kwdef_keyword( "while", T_WHILE), | |
246 | kwdef(NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0), | 246 | kwdef(NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0), | |
247 | #undef kwdef | 247 | #undef kwdef | |
248 | #undef kwdef_token | 248 | #undef kwdef_token | |
249 | #undef kwdef_sclass | 249 | #undef kwdef_sclass | |
250 | #undef kwdef_type | 250 | #undef kwdef_type | |
251 | #undef kwdef_tqual | 251 | #undef kwdef_tqual | |
252 | #undef kwdef_keyword | 252 | #undef kwdef_keyword | |
253 | #undef kwdef_gcc_attr | 253 | #undef kwdef_gcc_attr | |
254 | }; | 254 | }; | |
255 | 255 | |||
256 | /* Symbol table */ | 256 | /* Symbol table */ | |
257 | static sym_t *symtab[HSHSIZ1]; | 257 | static sym_t *symtab[HSHSIZ1]; | |
258 | 258 | |||
259 | /* type of next expected symbol */ | 259 | /* type of next expected symbol */ | |
260 | symt_t symtyp; | 260 | symt_t symtyp; | |
261 | 261 | |||
262 | 262 | |||
263 | static void | 263 | static void | |
264 | symtab_add(sym_t *sym) | 264 | symtab_add(sym_t *sym) | |
265 | { | 265 | { | |
266 | size_t h; | 266 | size_t h; | |
267 | 267 | |||
268 | h = hash(sym->s_name); | 268 | h = hash(sym->s_name); | |
269 | if ((sym->s_link = symtab[h]) != NULL) | 269 | if ((sym->s_symtab_next = symtab[h]) != NULL) | |
270 | symtab[h]->s_rlink = &sym->s_link; | 270 | symtab[h]->s_symtab_ref = &sym->s_symtab_next; | |
271 | sym->s_rlink = &symtab[h]; | 271 | sym->s_symtab_ref = &symtab[h]; | |
272 | symtab[h] = sym; | 272 | symtab[h] = sym; | |
273 | } | 273 | } | |
274 | 274 | |||
275 | static void | 275 | static void | |
276 | symtab_remove(sym_t *sym) | 276 | symtab_remove(sym_t *sym) | |
277 | { | 277 | { | |
278 | 278 | |||
279 | if ((*sym->s_rlink = sym->s_link) != NULL) | 279 | if ((*sym->s_symtab_ref = sym->s_symtab_next) != NULL) | |
280 | sym->s_link->s_rlink = sym->s_rlink; | 280 | sym->s_symtab_next->s_symtab_ref = sym->s_symtab_ref; | |
281 | sym->s_link = NULL; | 281 | sym->s_symtab_next = NULL; | |
282 | } | 282 | } | |
283 | 283 | |||
284 | 284 | |||
285 | static void | 285 | static void | |
286 | add_keyword(const struct keyword *kw, bool leading, bool trailing) | 286 | add_keyword(const struct keyword *kw, bool leading, bool trailing) | |
287 | { | 287 | { | |
288 | sym_t *sym; | 288 | sym_t *sym; | |
289 | char buf[256]; | 289 | char buf[256]; | |
290 | const char *name; | 290 | const char *name; | |
291 | 291 | |||
292 | if (!leading && !trailing) { | 292 | if (!leading && !trailing) { | |
293 | name = kw->kw_name; | 293 | name = kw->kw_name; | |
294 | } else { | 294 | } else { | |
295 | (void)snprintf(buf, sizeof(buf), "%s%s%s", | 295 | (void)snprintf(buf, sizeof(buf), "%s%s%s", | |
296 | leading ? "__" : "", kw->kw_name, trailing ? "__" : ""); | 296 | leading ? "__" : "", kw->kw_name, trailing ? "__" : ""); | |
297 | name = xstrdup(buf); | 297 | name = xstrdup(buf); | |
298 | } | 298 | } | |
299 | 299 | |||
300 | sym = block_zero_alloc(sizeof(*sym)); | 300 | sym = block_zero_alloc(sizeof(*sym)); | |
301 | sym->s_name = name; | 301 | sym->s_name = name; | |
302 | sym->s_keyword = kw; | 302 | sym->s_keyword = kw; | |
303 | sym->s_value.v_quad = kw->kw_token; | 303 | sym->s_value.v_quad = kw->kw_token; | |
304 | if (kw->kw_token == T_TYPE || kw->kw_token == T_STRUCT_OR_UNION) { | 304 | if (kw->kw_token == T_TYPE || kw->kw_token == T_STRUCT_OR_UNION) { | |
305 | sym->s_tspec = kw->kw_tspec; | 305 | sym->s_tspec = kw->kw_tspec; | |
306 | } else if (kw->kw_token == T_SCLASS) { | 306 | } else if (kw->kw_token == T_SCLASS) { | |
307 | sym->s_scl = kw->kw_scl; | 307 | sym->s_scl = kw->kw_scl; | |
308 | } else if (kw->kw_token == T_QUAL) { | 308 | } else if (kw->kw_token == T_QUAL) { | |
309 | sym->s_tqual = kw->kw_tqual; | 309 | sym->s_tqual = kw->kw_tqual; | |
310 | } | 310 | } | |
311 | 311 | |||
312 | symtab_add(sym); | 312 | symtab_add(sym); | |
313 | } | 313 | } | |
314 | 314 | |||
315 | /* | 315 | /* | |
316 | * All keywords are written to the symbol table. This saves us looking | 316 | * All keywords are written to the symbol table. This saves us looking | |
317 | * in an extra table for each name we found. | 317 | * in an extra table for each name we found. | |
318 | */ | 318 | */ | |
319 | void | 319 | void | |
320 | initscan(void) | 320 | initscan(void) | |
321 | { | 321 | { | |
322 | struct keyword *kw; | 322 | struct keyword *kw; | |
323 | 323 | |||
324 | for (kw = keywords; kw->kw_name != NULL; kw++) { | 324 | for (kw = keywords; kw->kw_name != NULL; kw++) { | |
325 | if ((kw->kw_c90 || kw->kw_c99) && tflag) | 325 | if ((kw->kw_c90 || kw->kw_c99) && tflag) | |
326 | continue; | 326 | continue; | |
327 | if (kw->kw_c99 && !(Sflag || gflag)) | 327 | if (kw->kw_c99 && !(Sflag || gflag)) | |
328 | continue; | 328 | continue; | |
329 | if (kw->kw_gcc && !gflag) | 329 | if (kw->kw_gcc && !gflag) | |
330 | continue; | 330 | continue; | |
331 | if (kw->kw_plain) | 331 | if (kw->kw_plain) | |
332 | add_keyword(kw, false, false); | 332 | add_keyword(kw, false, false); | |
333 | if (kw->kw_leading) | 333 | if (kw->kw_leading) | |
334 | add_keyword(kw, true, false); | 334 | add_keyword(kw, true, false); | |
335 | if (kw->kw_both) | 335 | if (kw->kw_both) | |
336 | add_keyword(kw, true, true); | 336 | add_keyword(kw, true, true); | |
337 | } | 337 | } | |
338 | } | 338 | } | |
339 | 339 | |||
340 | /* | 340 | /* | |
341 | * Read a character and ensure that it is positive (except EOF). | 341 | * Read a character and ensure that it is positive (except EOF). | |
342 | * Increment line count(s) if necessary. | 342 | * Increment line count(s) if necessary. | |
343 | */ | 343 | */ | |
344 | static int | 344 | static int | |
345 | inpc(void) | 345 | inpc(void) | |
346 | { | 346 | { | |
347 | int c; | 347 | int c; | |
348 | 348 | |||
349 | if ((c = lex_input()) == EOF) | 349 | if ((c = lex_input()) == EOF) | |
350 | return c; | 350 | return c; | |
351 | c &= CHAR_MASK; | 351 | c &= CHAR_MASK; | |
352 | if (c == '\0') | 352 | if (c == '\0') | |
353 | return EOF; /* lex returns 0 on EOF. */ | 353 | return EOF; /* lex returns 0 on EOF. */ | |
354 | if (c == '\n') | 354 | if (c == '\n') | |
355 | lex_next_line(); | 355 | lex_next_line(); | |
356 | return c; | 356 | return c; | |
357 | } | 357 | } | |
358 | 358 | |||
359 | static unsigned int | 359 | static unsigned int | |
360 | hash(const char *s) | 360 | hash(const char *s) | |
361 | { | 361 | { | |
362 | unsigned int v; | 362 | unsigned int v; | |
363 | const char *p; | 363 | const char *p; | |
364 | 364 | |||
365 | v = 0; | 365 | v = 0; | |
366 | for (p = s; *p != '\0'; p++) { | 366 | for (p = s; *p != '\0'; p++) { | |
367 | v = (v << 4) + (unsigned char)*p; | 367 | v = (v << 4) + (unsigned char)*p; | |
368 | v ^= v >> 28; | 368 | v ^= v >> 28; | |
369 | } | 369 | } | |
370 | return v % HSHSIZ1; | 370 | return v % HSHSIZ1; | |
371 | } | 371 | } | |
372 | 372 | |||
373 | /* | 373 | /* | |
374 | * Lex has found a letter followed by zero or more letters or digits. | 374 | * Lex has found a letter followed by zero or more letters or digits. | |
375 | * It looks for a symbol in the symbol table with the same name. This | 375 | * It looks for a symbol in the symbol table with the same name. This | |
376 | * symbol must either be a keyword or a symbol of the type required by | 376 | * symbol must either be a keyword or a symbol of the type required by | |
377 | * symtyp (label, member, tag, ...). | 377 | * symtyp (label, member, tag, ...). | |
378 | * | 378 | * | |
379 | * If it is a keyword, the token is returned. In some cases it is described | 379 | * If it is a keyword, the token is returned. In some cases it is described | |
380 | * more deeply by data written to yylval. | 380 | * more deeply by data written to yylval. | |
381 | * | 381 | * | |
382 | * If it is a symbol, T_NAME is returned and the name is stored in yylval. | 382 | * If it is a symbol, T_NAME is returned and the name is stored in yylval. | |
383 | * If there is already a symbol of the same name and type in the symbol | 383 | * If there is already a symbol of the same name and type in the symbol | |
384 | * table, yylval.y_name->sb_sym points there. | 384 | * table, yylval.y_name->sb_sym points there. | |
385 | */ | 385 | */ | |
386 | extern int | 386 | extern int | |
387 | lex_name(const char *yytext, size_t yyleng) | 387 | lex_name(const char *yytext, size_t yyleng) | |
388 | { | 388 | { | |
389 | char *s; | 389 | char *s; | |
390 | sbuf_t *sb; | 390 | sbuf_t *sb; | |
391 | sym_t *sym; | 391 | sym_t *sym; | |
392 | int tok; | 392 | int tok; | |
393 | 393 | |||
394 | sb = xmalloc(sizeof(*sb)); | 394 | sb = xmalloc(sizeof(*sb)); | |
395 | sb->sb_name = yytext; | 395 | sb->sb_name = yytext; | |
396 | sb->sb_len = yyleng; | 396 | sb->sb_len = yyleng; | |
397 | if ((sym = search(sb)) != NULL && sym->s_keyword != NULL) { | 397 | if ((sym = search(sb)) != NULL && sym->s_keyword != NULL) { | |
398 | free(sb); | 398 | free(sb); | |
399 | return keyw(sym); | 399 | return keyw(sym); | |
400 | } | 400 | } | |
401 | 401 | |||
402 | sb->sb_sym = sym; | 402 | sb->sb_sym = sym; | |
403 | 403 | |||
404 | if (sym != NULL) { | 404 | if (sym != NULL) { | |
405 | lint_assert(block_level >= sym->s_block_level); | 405 | lint_assert(block_level >= sym->s_block_level); | |
406 | sb->sb_name = sym->s_name; | 406 | sb->sb_name = sym->s_name; | |
407 | sb->sb_len = strlen(sym->s_name); | 407 | sb->sb_len = strlen(sym->s_name); | |
408 | tok = sym->s_scl == TYPEDEF ? T_TYPENAME : T_NAME; | 408 | tok = sym->s_scl == TYPEDEF ? T_TYPENAME : T_NAME; | |
409 | } else { | 409 | } else { | |
410 | s = block_zero_alloc(yyleng + 1); | 410 | s = block_zero_alloc(yyleng + 1); | |
411 | (void)memcpy(s, yytext, yyleng + 1); | 411 | (void)memcpy(s, yytext, yyleng + 1); | |
412 | sb->sb_name = s; | 412 | sb->sb_name = s; | |
413 | sb->sb_len = yyleng; | 413 | sb->sb_len = yyleng; | |
414 | tok = T_NAME; | 414 | tok = T_NAME; | |
415 | } | 415 | } | |
416 | 416 | |||
417 | yylval.y_name = sb; | 417 | yylval.y_name = sb; | |
418 | return tok; | 418 | return tok; | |
419 | } | 419 | } | |
420 | 420 | |||
421 | static sym_t * | 421 | static sym_t * | |
422 | search(sbuf_t *sb) | 422 | search(sbuf_t *sb) | |
423 | { | 423 | { | |
424 | unsigned int h; | 424 | unsigned int h; | |
425 | sym_t *sym; | 425 | sym_t *sym; | |
426 | const struct keyword *kw; | 426 | const struct keyword *kw; | |
427 | 427 | |||
428 | h = hash(sb->sb_name); | 428 | h = hash(sb->sb_name); | |
429 | for (sym = symtab[h]; sym != NULL; sym = sym->s_link) { | 429 | for (sym = symtab[h]; sym != NULL; sym = sym->s_symtab_next) { | |
430 | if (strcmp(sym->s_name, sb->sb_name) != 0) | 430 | if (strcmp(sym->s_name, sb->sb_name) != 0) | |
431 | continue; | 431 | continue; | |
432 | kw = sym->s_keyword; | 432 | kw = sym->s_keyword; | |
433 | 433 | |||
434 | if (kw != NULL && !kw->kw_attr) | 434 | if (kw != NULL && !kw->kw_attr) | |
435 | return sym; | 435 | return sym; | |
436 | if (kw != NULL && in_gcc_attribute) | 436 | if (kw != NULL && in_gcc_attribute) | |
437 | return sym; | 437 | return sym; | |
438 | if (kw == NULL && !in_gcc_attribute && sym->s_kind == symtyp) | 438 | if (kw == NULL && !in_gcc_attribute && sym->s_kind == symtyp) | |
439 | return sym; | 439 | return sym; | |
440 | } | 440 | } | |
441 | 441 | |||
442 | return NULL; | 442 | return NULL; | |
443 | } | 443 | } | |
444 | 444 | |||
445 | static int | 445 | static int | |
446 | keyw(sym_t *sym) | 446 | keyw(sym_t *sym) | |
447 | { | 447 | { | |
448 | int t; | 448 | int t; | |
449 | 449 | |||
450 | if ((t = (int)sym->s_value.v_quad) == T_SCLASS) { | 450 | if ((t = (int)sym->s_value.v_quad) == T_SCLASS) { | |
451 | yylval.y_scl = sym->s_scl; | 451 | yylval.y_scl = sym->s_scl; | |
452 | } else if (t == T_TYPE || t == T_STRUCT_OR_UNION) { | 452 | } else if (t == T_TYPE || t == T_STRUCT_OR_UNION) { | |
453 | yylval.y_tspec = sym->s_tspec; | 453 | yylval.y_tspec = sym->s_tspec; | |
454 | } else if (t == T_QUAL) { | 454 | } else if (t == T_QUAL) { | |
455 | yylval.y_tqual = sym->s_tqual; | 455 | yylval.y_tqual = sym->s_tqual; | |
456 | } | 456 | } | |
457 | return t; | 457 | return t; | |
458 | } | 458 | } | |
459 | 459 | |||
460 | /* | 460 | /* | |
461 | * Convert a string representing an integer into internal representation. | 461 | * Convert a string representing an integer into internal representation. | |
462 | * Return T_CON, storing the numeric value in yylval, for yylex. | 462 | * Return T_CON, storing the numeric value in yylval, for yylex. | |
463 | */ | 463 | */ | |
464 | int | 464 | int | |
465 | lex_integer_constant(const char *yytext, size_t yyleng, int base) | 465 | lex_integer_constant(const char *yytext, size_t yyleng, int base) | |
466 | { | 466 | { | |
467 | int l_suffix, u_suffix; | 467 | int l_suffix, u_suffix; | |
468 | size_t len; | 468 | size_t len; | |
469 | const char *cp; | 469 | const char *cp; | |
470 | char c, *eptr; | 470 | char c, *eptr; | |
471 | tspec_t typ; | 471 | tspec_t typ; | |
472 | bool ansiu; | 472 | bool ansiu; | |
473 | bool warned = false; | 473 | bool warned = false; | |
474 | uint64_t uq = 0; | 474 | uint64_t uq = 0; | |
475 | 475 | |||
476 | /* C11 6.4.4.1p5 */ | 476 | /* C11 6.4.4.1p5 */ | |
477 | static const tspec_t suffix_type[2][3] = { | 477 | static const tspec_t suffix_type[2][3] = { | |
478 | { INT, LONG, QUAD, }, | 478 | { INT, LONG, QUAD, }, | |
479 | { UINT, ULONG, UQUAD, } | 479 | { UINT, ULONG, UQUAD, } | |
480 | }; | 480 | }; | |
481 | 481 | |||
482 | cp = yytext; | 482 | cp = yytext; | |
483 | len = yyleng; | 483 | len = yyleng; | |
484 | 484 | |||
485 | /* skip 0[xX] or 0[bB] */ | 485 | /* skip 0[xX] or 0[bB] */ | |
486 | if (base == 16 || base == 2) { | 486 | if (base == 16 || base == 2) { | |
487 | cp += 2; | 487 | cp += 2; | |
488 | len -= 2; | 488 | len -= 2; | |
489 | } | 489 | } | |
490 | 490 | |||
491 | /* read suffixes */ | 491 | /* read suffixes */ | |
492 | l_suffix = u_suffix = 0; | 492 | l_suffix = u_suffix = 0; | |
493 | for (;;) { | 493 | for (;;) { | |
494 | if ((c = cp[len - 1]) == 'l' || c == 'L') { | 494 | if ((c = cp[len - 1]) == 'l' || c == 'L') { | |
495 | l_suffix++; | 495 | l_suffix++; | |
496 | } else if (c == 'u' || c == 'U') { | 496 | } else if (c == 'u' || c == 'U') { | |
497 | u_suffix++; | 497 | u_suffix++; | |
498 | } else { | 498 | } else { | |
499 | break; | 499 | break; | |
500 | } | 500 | } | |
501 | len--; | 501 | len--; | |
502 | } | 502 | } | |
503 | if (l_suffix > 2 || u_suffix > 1) { | 503 | if (l_suffix > 2 || u_suffix > 1) { | |
504 | /* malformed integer constant */ | 504 | /* malformed integer constant */ | |
505 | warning(251); | 505 | warning(251); | |
506 | if (l_suffix > 2) | 506 | if (l_suffix > 2) | |
507 | l_suffix = 2; | 507 | l_suffix = 2; | |
508 | if (u_suffix > 1) | 508 | if (u_suffix > 1) | |
509 | u_suffix = 1; | 509 | u_suffix = 1; | |
510 | } | 510 | } | |
511 | if (tflag && u_suffix != 0) { | 511 | if (tflag && u_suffix != 0) { | |
512 | /* suffix U is illegal in traditional C */ | 512 | /* suffix U is illegal in traditional C */ | |
513 | warning(97); | 513 | warning(97); | |
514 | } | 514 | } | |
515 | typ = suffix_type[u_suffix][l_suffix]; | 515 | typ = suffix_type[u_suffix][l_suffix]; | |
516 | 516 | |||
517 | errno = 0; | 517 | errno = 0; | |
518 | 518 | |||
519 | uq = (uint64_t)strtoull(cp, &eptr, base); | 519 | uq = (uint64_t)strtoull(cp, &eptr, base); | |
520 | lint_assert(eptr == cp + len); | 520 | lint_assert(eptr == cp + len); | |
521 | if (errno != 0) { | 521 | if (errno != 0) { | |
522 | /* integer constant out of range */ | 522 | /* integer constant out of range */ | |
523 | warning(252); | 523 | warning(252); | |
524 | warned = true; | 524 | warned = true; | |
525 | } | 525 | } | |
526 | 526 | |||
527 | /* | 527 | /* | |
528 | * If the value is too big for the current type, we must choose | 528 | * If the value is too big for the current type, we must choose | |
529 | * another type. | 529 | * another type. | |
530 | */ | 530 | */ | |
531 | ansiu = false; | 531 | ansiu = false; | |
532 | switch (typ) { | 532 | switch (typ) { | |
533 | case INT: | 533 | case INT: | |
534 | if (uq <= TARG_INT_MAX) { | 534 | if (uq <= TARG_INT_MAX) { | |
535 | /* ok */ | 535 | /* ok */ | |
536 | } else if (uq <= TARG_UINT_MAX && base != 10) { | 536 | } else if (uq <= TARG_UINT_MAX && base != 10) { | |
537 | typ = UINT; | 537 | typ = UINT; | |
538 | } else if (uq <= TARG_LONG_MAX) { | 538 | } else if (uq <= TARG_LONG_MAX) { | |
539 | typ = LONG; | 539 | typ = LONG; | |
540 | } else { | 540 | } else { | |
541 | typ = ULONG; | 541 | typ = ULONG; | |
542 | if (uq > TARG_ULONG_MAX && !warned) { | 542 | if (uq > TARG_ULONG_MAX && !warned) { | |
543 | /* integer constant out of range */ | 543 | /* integer constant out of range */ | |
544 | warning(252); | 544 | warning(252); | |
545 | } | 545 | } | |
546 | } | 546 | } | |
547 | if (typ == UINT || typ == ULONG) { | 547 | if (typ == UINT || typ == ULONG) { | |
548 | if (tflag) { | 548 | if (tflag) { | |
549 | typ = LONG; | 549 | typ = LONG; | |
550 | } else if (!sflag) { | 550 | } else if (!sflag) { | |
551 | /* | 551 | /* | |
552 | * Remember that the constant is unsigned | 552 | * Remember that the constant is unsigned | |
553 | * only in ANSI C | 553 | * only in ANSI C | |
554 | */ | 554 | */ | |
555 | ansiu = true; | 555 | ansiu = true; | |
556 | } | 556 | } | |
557 | } | 557 | } | |
558 | break; | 558 | break; | |
559 | case UINT: | 559 | case UINT: | |
560 | if (uq > TARG_UINT_MAX) { | 560 | if (uq > TARG_UINT_MAX) { | |
561 | typ = ULONG; | 561 | typ = ULONG; | |
562 | if (uq > TARG_ULONG_MAX && !warned) { | 562 | if (uq > TARG_ULONG_MAX && !warned) { | |
563 | /* integer constant out of range */ | 563 | /* integer constant out of range */ | |
564 | warning(252); | 564 | warning(252); | |
565 | } | 565 | } | |
566 | } | 566 | } | |
567 | break; | 567 | break; | |
568 | case LONG: | 568 | case LONG: | |
569 | if (uq > TARG_LONG_MAX && !tflag) { | 569 | if (uq > TARG_LONG_MAX && !tflag) { | |
570 | typ = ULONG; | 570 | typ = ULONG; | |
571 | if (!sflag) | 571 | if (!sflag) | |
572 | ansiu = true; | 572 | ansiu = true; | |
573 | if (uq > TARG_ULONG_MAX && !warned) { | 573 | if (uq > TARG_ULONG_MAX && !warned) { | |
574 | /* integer constant out of range */ | 574 | /* integer constant out of range */ | |
575 | warning(252); | 575 | warning(252); | |
576 | } | 576 | } | |
577 | } | 577 | } | |
578 | break; | 578 | break; | |
579 | case ULONG: | 579 | case ULONG: | |
580 | if (uq > TARG_ULONG_MAX && !warned) { | 580 | if (uq > TARG_ULONG_MAX && !warned) { | |
581 | /* integer constant out of range */ | 581 | /* integer constant out of range */ | |
582 | warning(252); | 582 | warning(252); | |
583 | } | 583 | } | |
584 | break; | 584 | break; | |
585 | case QUAD: | 585 | case QUAD: | |
586 | if (uq > TARG_QUAD_MAX && !tflag) { | 586 | if (uq > TARG_QUAD_MAX && !tflag) { | |
587 | typ = UQUAD; | 587 | typ = UQUAD; | |
588 | if (!sflag) | 588 | if (!sflag) | |
589 | ansiu = true; | 589 | ansiu = true; | |
590 | } | 590 | } | |
591 | break; | 591 | break; | |
592 | case UQUAD: | 592 | case UQUAD: | |
593 | if (uq > TARG_UQUAD_MAX && !warned) { | 593 | if (uq > TARG_UQUAD_MAX && !warned) { | |
594 | /* integer constant out of range */ | 594 | /* integer constant out of range */ | |
595 | warning(252); | 595 | warning(252); | |
596 | } | 596 | } | |
597 | break; | 597 | break; | |
598 | default: | 598 | default: | |
599 | break; | 599 | break; | |
600 | } | 600 | } | |
601 | 601 | |||
602 | uq = (uint64_t)convert_integer((int64_t)uq, typ, 0); | 602 | uq = (uint64_t)convert_integer((int64_t)uq, typ, 0); | |
603 | 603 | |||
604 | yylval.y_val = xcalloc(1, sizeof(*yylval.y_val)); | 604 | yylval.y_val = xcalloc(1, sizeof(*yylval.y_val)); | |
605 | yylval.y_val->v_tspec = typ; | 605 | yylval.y_val->v_tspec = typ; | |
606 | yylval.y_val->v_unsigned_since_c90 = ansiu; | 606 | yylval.y_val->v_unsigned_since_c90 = ansiu; | |
607 | yylval.y_val->v_quad = (int64_t)uq; | 607 | yylval.y_val->v_quad = (int64_t)uq; | |
608 | 608 | |||
609 | return T_CON; | 609 | return T_CON; | |
610 | } | 610 | } | |
611 | 611 | |||
612 | /* | 612 | /* | |
613 | * Extend or truncate q to match t. If t is signed, sign-extend. | 613 | * Extend or truncate q to match t. If t is signed, sign-extend. | |
614 | * | 614 | * | |
615 | * len is the number of significant bits. If len is -1, len is set | 615 | * len is the number of significant bits. If len is -1, len is set | |
616 | * to the width of type t. | 616 | * to the width of type t. | |
617 | */ | 617 | */ | |
618 | int64_t | 618 | int64_t | |
619 | convert_integer(int64_t q, tspec_t t, unsigned int len) | 619 | convert_integer(int64_t q, tspec_t t, unsigned int len) | |
620 | { | 620 | { | |
621 | uint64_t vbits; | 621 | uint64_t vbits; | |
622 | 622 | |||
623 | if (len == 0) | 623 | if (len == 0) | |
624 | len = size_in_bits(t); | 624 | len = size_in_bits(t); | |
625 | 625 | |||
626 | vbits = value_bits(len); | 626 | vbits = value_bits(len); | |
627 | return t == PTR || is_uinteger(t) || ((q & bit(len - 1)) == 0) | 627 | return t == PTR || is_uinteger(t) || ((q & bit(len - 1)) == 0) | |
628 | ? (int64_t)(q & vbits) | 628 | ? (int64_t)(q & vbits) | |
629 | : (int64_t)(q | ~vbits); | 629 | : (int64_t)(q | ~vbits); | |
630 | } | 630 | } | |
631 | 631 | |||
632 | /* | 632 | /* | |
633 | * Convert a string representing a floating point value into its numerical | 633 | * Convert a string representing a floating point value into its numerical | |
634 | * representation. Type and value are returned in yylval. | 634 | * representation. Type and value are returned in yylval. | |
635 | * | 635 | * | |
636 | * XXX Currently it is not possible to convert constants of type | 636 | * XXX Currently it is not possible to convert constants of type | |
637 | * long double which are greater than DBL_MAX. | 637 | * long double which are greater than DBL_MAX. | |
638 | */ | 638 | */ | |
639 | int | 639 | int | |
640 | lex_floating_constant(const char *yytext, size_t yyleng) | 640 | lex_floating_constant(const char *yytext, size_t yyleng) | |
641 | { | 641 | { | |
642 | const char *cp; | 642 | const char *cp; | |
643 | size_t len; | 643 | size_t len; | |
644 | tspec_t typ; | 644 | tspec_t typ; | |
645 | char c, *eptr; | 645 | char c, *eptr; | |
646 | double d; | 646 | double d; | |
647 | float f = 0; | 647 | float f = 0; | |
648 | 648 | |||
649 | cp = yytext; | 649 | cp = yytext; | |
650 | len = yyleng; | 650 | len = yyleng; | |
651 | 651 | |||
652 | if (cp[len - 1] == 'i') | 652 | if (cp[len - 1] == 'i') | |
653 | len--; /* imaginary, do nothing for now */ | 653 | len--; /* imaginary, do nothing for now */ | |
654 | 654 | |||
655 | if ((c = cp[len - 1]) == 'f' || c == 'F') { | 655 | if ((c = cp[len - 1]) == 'f' || c == 'F') { | |
656 | typ = FLOAT; | 656 | typ = FLOAT; | |
657 | len--; | 657 | len--; | |
658 | } else if (c == 'l' || c == 'L') { | 658 | } else if (c == 'l' || c == 'L') { | |
659 | typ = LDOUBLE; | 659 | typ = LDOUBLE; | |
660 | len--; | 660 | len--; | |
661 | } else { | 661 | } else { | |
662 | if (c == 'd' || c == 'D') | 662 | if (c == 'd' || c == 'D') | |
663 | len--; | 663 | len--; | |
664 | typ = DOUBLE; | 664 | typ = DOUBLE; | |
665 | } | 665 | } | |
666 | 666 | |||
667 | if (tflag && typ != DOUBLE) { | 667 | if (tflag && typ != DOUBLE) { | |
668 | /* suffixes F and L are illegal in traditional C */ | 668 | /* suffixes F and L are illegal in traditional C */ | |
669 | warning(98); | 669 | warning(98); | |
670 | } | 670 | } | |
671 | 671 | |||
672 | errno = 0; | 672 | errno = 0; | |
673 | d = strtod(cp, &eptr); | 673 | d = strtod(cp, &eptr); | |
674 | if (eptr != cp + len) { | 674 | if (eptr != cp + len) { | |
675 | switch (*eptr) { | 675 | switch (*eptr) { | |
676 | /* | 676 | /* | |
677 | * XXX: non-native non-current strtod() may not handle hex | 677 | * XXX: non-native non-current strtod() may not handle hex | |
678 | * floats, ignore the rest if we find traces of hex float | 678 | * floats, ignore the rest if we find traces of hex float | |
679 | * syntax... | 679 | * syntax... | |
680 | */ | 680 | */ | |
681 | case 'p': | 681 | case 'p': | |
682 | case 'P': | 682 | case 'P': | |
683 | case 'x': | 683 | case 'x': | |
684 | case 'X': | 684 | case 'X': | |
685 | d = 0; | 685 | d = 0; | |
686 | errno = 0; | 686 | errno = 0; | |
687 | break; | 687 | break; | |
688 | default: | 688 | default: | |
689 | INTERNAL_ERROR("lex_floating_constant(%s->%s)", | 689 | INTERNAL_ERROR("lex_floating_constant(%s->%s)", | |
690 | cp, eptr); | 690 | cp, eptr); | |
691 | } | 691 | } | |
692 | } | 692 | } | |
693 | if (errno != 0) | 693 | if (errno != 0) | |
694 | /* floating-point constant out of range */ | 694 | /* floating-point constant out of range */ | |
695 | warning(248); | 695 | warning(248); | |
696 | 696 | |||
697 | if (typ == FLOAT) { | 697 | if (typ == FLOAT) { | |
698 | f = (float)d; | 698 | f = (float)d; | |
699 | if (isfinite(f) == 0) { | 699 | if (isfinite(f) == 0) { | |
700 | /* floating-point constant out of range */ | 700 | /* floating-point constant out of range */ | |
701 | warning(248); | 701 | warning(248); | |
702 | f = f > 0 ? FLT_MAX : -FLT_MAX; | 702 | f = f > 0 ? FLT_MAX : -FLT_MAX; | |
703 | } | 703 | } | |
704 | } | 704 | } | |
705 | 705 | |||
706 | yylval.y_val = xcalloc(1, sizeof(*yylval.y_val)); | 706 | yylval.y_val = xcalloc(1, sizeof(*yylval.y_val)); | |
707 | yylval.y_val->v_tspec = typ; | 707 | yylval.y_val->v_tspec = typ; | |
708 | if (typ == FLOAT) { | 708 | if (typ == FLOAT) { | |
709 | yylval.y_val->v_ldbl = f; | 709 | yylval.y_val->v_ldbl = f; | |
710 | } else { | 710 | } else { | |
711 | yylval.y_val->v_ldbl = d; | 711 | yylval.y_val->v_ldbl = d; | |
712 | } | 712 | } | |
713 | 713 | |||
714 | return T_CON; | 714 | return T_CON; | |
715 | } | 715 | } | |
716 | 716 | |||
717 | int | 717 | int | |
718 | lex_operator(int t, op_t o) | 718 | lex_operator(int t, op_t o) | |
719 | { | 719 | { | |
720 | 720 | |||
721 | yylval.y_op = o; | 721 | yylval.y_op = o; | |
722 | return t; | 722 | return t; | |
723 | } | 723 | } | |
724 | 724 | |||
725 | /* | 725 | /* | |
726 | * Called if lex found a leading \'. | 726 | * Called if lex found a leading \'. | |
727 | */ | 727 | */ | |
728 | int | 728 | int | |
729 | lex_character_constant(void) | 729 | lex_character_constant(void) | |
730 | { | 730 | { | |
731 | size_t n; | 731 | size_t n; | |
732 | int val, c; | 732 | int val, c; | |
733 | 733 | |||
734 | n = 0; | 734 | n = 0; | |
735 | val = 0; | 735 | val = 0; | |
736 | while ((c = get_escaped_char('\'')) >= 0) { | 736 | while ((c = get_escaped_char('\'')) >= 0) { | |
737 | val = (val << CHAR_SIZE) + c; | 737 | val = (val << CHAR_SIZE) + c; | |
738 | n++; | 738 | n++; | |
739 | } | 739 | } | |
740 | if (c == -2) { | 740 | if (c == -2) { | |
741 | /* unterminated character constant */ | 741 | /* unterminated character constant */ | |
742 | error(253); | 742 | error(253); | |
743 | } else if (n > sizeof(int) || (n > 1 && (pflag || hflag))) { | 743 | } else if (n > sizeof(int) || (n > 1 && (pflag || hflag))) { | |
744 | /* XXX: should rather be sizeof(TARG_INT) */ | 744 | /* XXX: should rather be sizeof(TARG_INT) */ | |
745 | 745 | |||
746 | /* too many characters in character constant */ | 746 | /* too many characters in character constant */ | |
747 | error(71); | 747 | error(71); | |
748 | } else if (n > 1) { | 748 | } else if (n > 1) { | |
749 | /* multi-character character constant */ | 749 | /* multi-character character constant */ | |
750 | warning(294); | 750 | warning(294); | |
751 | } else if (n == 0) { | 751 | } else if (n == 0) { | |
752 | /* empty character constant */ | 752 | /* empty character constant */ | |
753 | error(73); | 753 | error(73); | |
754 | } | 754 | } | |
755 | if (n == 1) | 755 | if (n == 1) | |
756 | val = (int)convert_integer(val, CHAR, CHAR_SIZE); | 756 | val = (int)convert_integer(val, CHAR, CHAR_SIZE); | |
757 | 757 | |||
758 | yylval.y_val = xcalloc(1, sizeof(*yylval.y_val)); | 758 | yylval.y_val = xcalloc(1, sizeof(*yylval.y_val)); | |
759 | yylval.y_val->v_tspec = INT; | 759 | yylval.y_val->v_tspec = INT; | |
760 | yylval.y_val->v_quad = val; | 760 | yylval.y_val->v_quad = val; | |
761 | 761 | |||
762 | return T_CON; | 762 | return T_CON; | |
763 | } | 763 | } | |
764 | 764 | |||
765 | /* | 765 | /* | |
766 | * Called if lex found a leading L\' | 766 | * Called if lex found a leading L\' | |
767 | */ | 767 | */ | |
768 | int | 768 | int | |
769 | lex_wide_character_constant(void) | 769 | lex_wide_character_constant(void) | |
770 | { | 770 | { | |
771 | static char buf[MB_LEN_MAX + 1]; | 771 | static char buf[MB_LEN_MAX + 1]; | |
772 | size_t n, nmax; | 772 | size_t n, nmax; | |
773 | int c; | 773 | int c; | |
774 | wchar_t wc; | 774 | wchar_t wc; | |
775 | 775 | |||
776 | nmax = MB_CUR_MAX; | 776 | nmax = MB_CUR_MAX; | |
777 | 777 | |||
778 | n = 0; | 778 | n = 0; | |
779 | while ((c = get_escaped_char('\'')) >= 0) { | 779 | while ((c = get_escaped_char('\'')) >= 0) { | |
780 | if (n < nmax) | 780 | if (n < nmax) | |
781 | buf[n] = (char)c; | 781 | buf[n] = (char)c; | |
782 | n++; | 782 | n++; | |
783 | } | 783 | } | |
784 | 784 | |||
785 | wc = 0; | 785 | wc = 0; | |
786 | 786 | |||
787 | if (c == -2) { | 787 | if (c == -2) { | |
788 | /* unterminated character constant */ | 788 | /* unterminated character constant */ | |
789 | error(253); | 789 | error(253); | |
790 | } else if (n == 0) { | 790 | } else if (n == 0) { | |
791 | /* empty character constant */ | 791 | /* empty character constant */ | |
792 | error(73); | 792 | error(73); | |
793 | } else if (n > nmax) { | 793 | } else if (n > nmax) { | |
794 | n = nmax; | 794 | n = nmax; | |
795 | /* too many characters in character constant */ | 795 | /* too many characters in character constant */ | |
796 | error(71); | 796 | error(71); | |
797 | } else { | 797 | } else { | |
798 | buf[n] = '\0'; | 798 | buf[n] = '\0'; | |
799 | (void)mbtowc(NULL, NULL, 0); | 799 | (void)mbtowc(NULL, NULL, 0); | |
800 | if (mbtowc(&wc, buf, nmax) < 0) | 800 | if (mbtowc(&wc, buf, nmax) < 0) | |
801 | /* invalid multibyte character */ | 801 | /* invalid multibyte character */ | |
802 | error(291); | 802 | error(291); | |
803 | } | 803 | } | |
804 | 804 | |||
805 | yylval.y_val = xcalloc(1, sizeof(*yylval.y_val)); | 805 | yylval.y_val = xcalloc(1, sizeof(*yylval.y_val)); | |
806 | yylval.y_val->v_tspec = WCHAR; | 806 | yylval.y_val->v_tspec = WCHAR; | |
807 | yylval.y_val->v_quad = wc; | 807 | yylval.y_val->v_quad = wc; | |
808 | 808 | |||
809 | return T_CON; | 809 | return T_CON; | |
810 | } | 810 | } | |
811 | 811 | |||
812 | /* | 812 | /* | |
813 | * Read a character which is part of a character constant or of a string | 813 | * Read a character which is part of a character constant or of a string | |
814 | * and handle escapes. | 814 | * and handle escapes. | |
815 | * | 815 | * | |
816 | * The argument is the character which delimits the character constant or | 816 | * The argument is the character which delimits the character constant or | |
817 | * string. | 817 | * string. | |
818 | * | 818 | * | |
819 | * Returns -1 if the end of the character constant or string is reached, | 819 | * Returns -1 if the end of the character constant or string is reached, | |
820 | * -2 if the EOF is reached, and the character otherwise. | 820 | * -2 if the EOF is reached, and the character otherwise. | |
821 | */ | 821 | */ | |
822 | static int | 822 | static int | |
823 | get_escaped_char(int delim) | 823 | get_escaped_char(int delim) | |
824 | { | 824 | { | |
825 | static int pbc = -1; | 825 | static int pbc = -1; | |
826 | int n, c, v; | 826 | int n, c, v; | |
827 | 827 | |||
828 | if (pbc == -1) { | 828 | if (pbc == -1) { | |
829 | c = inpc(); | 829 | c = inpc(); | |
830 | } else { | 830 | } else { | |
831 | c = pbc; | 831 | c = pbc; | |
832 | pbc = -1; | 832 | pbc = -1; | |
833 | } | 833 | } | |
834 | if (c == delim) | 834 | if (c == delim) | |
835 | return -1; | 835 | return -1; | |
836 | switch (c) { | 836 | switch (c) { | |
837 | case '\n': | 837 | case '\n': | |
838 | if (tflag) { | 838 | if (tflag) { | |
839 | /* newline in string or char constant */ | 839 | /* newline in string or char constant */ | |
840 | error(254); | 840 | error(254); | |
841 | return -2; | 841 | return -2; | |
842 | } | 842 | } | |
843 | return c; | 843 | return c; | |
844 | case 0: | 844 | case 0: | |
845 | /* syntax error '%s' */ | 845 | /* syntax error '%s' */ | |
846 | error(249, "EOF or null byte in literal"); | 846 | error(249, "EOF or null byte in literal"); | |
847 | return -2; | 847 | return -2; | |
848 | case EOF: | 848 | case EOF: | |
849 | return -2; | 849 | return -2; | |
850 | case '\\': | 850 | case '\\': | |
851 | switch (c = inpc()) { | 851 | switch (c = inpc()) { | |
852 | case '"': | 852 | case '"': | |
853 | if (tflag && delim == '\'') | 853 | if (tflag && delim == '\'') | |
854 | /* \" inside character constants undef... */ | 854 | /* \" inside character constants undef... */ | |
855 | warning(262); | 855 | warning(262); | |
856 | return '"'; | 856 | return '"'; | |
857 | case '\'': | 857 | case '\'': | |
858 | return '\''; | 858 | return '\''; | |
859 | case '?': | 859 | case '?': | |
860 | if (tflag) | 860 | if (tflag) | |
861 | /* \? undefined in traditional C */ | 861 | /* \? undefined in traditional C */ | |
862 | warning(263); | 862 | warning(263); | |
863 | return '?'; | 863 | return '?'; | |
864 | case '\\': | 864 | case '\\': | |
865 | return '\\'; | 865 | return '\\'; | |
866 | case 'a': | 866 | case 'a': | |
867 | if (tflag) | 867 | if (tflag) | |
868 | /* \a undefined in traditional C */ | 868 | /* \a undefined in traditional C */ | |
869 | warning(81); | 869 | warning(81); | |
870 | return '\a'; | 870 | return '\a'; | |
871 | case 'b': | 871 | case 'b': | |
872 | return '\b'; | 872 | return '\b'; | |
873 | case 'f': | 873 | case 'f': | |
874 | return '\f'; | 874 | return '\f'; | |
875 | case 'n': | 875 | case 'n': | |
876 | return '\n'; | 876 | return '\n'; | |
877 | case 'r': | 877 | case 'r': | |
878 | return '\r'; | 878 | return '\r'; | |
879 | case 't': | 879 | case 't': | |
880 | return '\t'; | 880 | return '\t'; | |
881 | case 'v': | 881 | case 'v': | |
882 | if (tflag) | 882 | if (tflag) | |
883 | /* \v undefined in traditional C */ | 883 | /* \v undefined in traditional C */ | |
884 | warning(264); | 884 | warning(264); | |
885 | return '\v'; | 885 | return '\v'; | |
886 | case '8': case '9': | 886 | case '8': case '9': | |
887 | /* bad octal digit %c */ | 887 | /* bad octal digit %c */ | |
888 | warning(77, c); | 888 | warning(77, c); | |
889 | /* FALLTHROUGH */ | 889 | /* FALLTHROUGH */ | |
890 | case '0': case '1': case '2': case '3': | 890 | case '0': case '1': case '2': case '3': | |
891 | case '4': case '5': case '6': case '7': | 891 | case '4': case '5': case '6': case '7': | |
892 | n = 3; | 892 | n = 3; | |
893 | v = 0; | 893 | v = 0; | |
894 | do { | 894 | do { | |
895 | v = (v << 3) + (c - '0'); | 895 | v = (v << 3) + (c - '0'); | |
896 | c = inpc(); | 896 | c = inpc(); | |
897 | } while (--n > 0 && '0' <= c && c <= '7'); | 897 | } while (--n > 0 && '0' <= c && c <= '7'); | |
898 | pbc = c; | 898 | pbc = c; | |
899 | if (v > TARG_UCHAR_MAX) { | 899 | if (v > TARG_UCHAR_MAX) { | |
900 | /* character escape does not fit in character */ | 900 | /* character escape does not fit in character */ | |
901 | warning(76); | 901 | warning(76); | |
902 | v &= CHAR_MASK; | 902 | v &= CHAR_MASK; | |
903 | } | 903 | } | |
904 | return v; | 904 | return v; | |
905 | case 'x': | 905 | case 'x': | |
906 | if (tflag) | 906 | if (tflag) | |
907 | /* \x undefined in traditional C */ | 907 | /* \x undefined in traditional C */ | |
908 | warning(82); | 908 | warning(82); | |
909 | v = 0; | 909 | v = 0; | |
910 | n = 0; | 910 | n = 0; | |
911 | while (c = inpc(), isxdigit(c)) { | 911 | while (c = inpc(), isxdigit(c)) { | |
912 | c = isdigit(c) ? | 912 | c = isdigit(c) ? | |
913 | c - '0' : toupper(c) - 'A' + 10; | 913 | c - '0' : toupper(c) - 'A' + 10; | |
914 | v = (v << 4) + c; | 914 | v = (v << 4) + c; | |
915 | if (n >= 0) { | 915 | if (n >= 0) { | |
916 | if ((v & ~CHAR_MASK) != 0) { | 916 | if ((v & ~CHAR_MASK) != 0) { | |
917 | /* overflow in hex escape */ | 917 | /* overflow in hex escape */ | |
918 | warning(75); | 918 | warning(75); | |
919 | n = -1; | 919 | n = -1; | |
920 | } else { | 920 | } else { | |
921 | n++; | 921 | n++; | |
922 | } | 922 | } | |
923 | } | 923 | } | |
924 | } | 924 | } | |
925 | pbc = c; | 925 | pbc = c; | |
926 | if (n == 0) { | 926 | if (n == 0) { | |
927 | /* no hex digits follow \x */ | 927 | /* no hex digits follow \x */ | |
928 | error(74); | 928 | error(74); | |
929 | } if (n == -1) { | 929 | } if (n == -1) { | |
930 | v &= CHAR_MASK; | 930 | v &= CHAR_MASK; | |
931 | } | 931 | } | |
932 | return v; | 932 | return v; | |
933 | case '\n': | 933 | case '\n': | |
934 | return get_escaped_char(delim); | 934 | return get_escaped_char(delim); | |
935 | case EOF: | 935 | case EOF: | |
936 | return -2; | 936 | return -2; | |
937 | default: | 937 | default: | |
938 | if (isprint(c)) { | 938 | if (isprint(c)) { | |
939 | /* dubious escape \%c */ | 939 | /* dubious escape \%c */ | |
940 | warning(79, c); | 940 | warning(79, c); | |
941 | } else { | 941 | } else { | |
942 | /* dubious escape \%o */ | 942 | /* dubious escape \%o */ | |
943 | warning(80, c); | 943 | warning(80, c); | |
944 | } | 944 | } | |
945 | } | 945 | } | |
946 | } | 946 | } | |
947 | return c; | 947 | return c; | |
948 | } | 948 | } | |
949 | 949 | |||
950 | /* See https://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html */ | 950 | /* See https://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html */ | |
951 | static void | 951 | static void | |
952 | parse_line_directive_flags(const char *p, | 952 | parse_line_directive_flags(const char *p, | |
953 | bool *is_begin, bool *is_end, bool *is_system) | 953 | bool *is_begin, bool *is_end, bool *is_system) | |
954 | { | 954 | { | |
955 | 955 | |||
956 | *is_begin = false; | 956 | *is_begin = false; | |
957 | *is_end = false; | 957 | *is_end = false; | |
958 | *is_system = false; | 958 | *is_system = false; | |
959 | 959 | |||
960 | while (*p != '\0') { | 960 | while (*p != '\0') { | |
961 | const char *word_start, *word_end; | 961 | const char *word_start, *word_end; | |
962 | 962 | |||
963 | while (ch_isspace(*p)) | 963 | while (ch_isspace(*p)) | |
964 | p++; | 964 | p++; | |
965 | 965 | |||
966 | word_start = p; | 966 | word_start = p; | |
967 | while (*p != '\0' && !ch_isspace(*p)) | 967 | while (*p != '\0' && !ch_isspace(*p)) | |
968 | p++; | 968 | p++; | |
969 | word_end = p; | 969 | word_end = p; | |
970 | 970 | |||
971 | if (word_end - word_start == 1 && word_start[0] == '1') | 971 | if (word_end - word_start == 1 && word_start[0] == '1') | |
972 | *is_begin = true; | 972 | *is_begin = true; | |
973 | if (word_end - word_start == 1 && word_start[0] == '2') | 973 | if (word_end - word_start == 1 && word_start[0] == '2') | |
974 | *is_end = true; | 974 | *is_end = true; | |
975 | if (word_end - word_start == 1 && word_start[0] == '3') | 975 | if (word_end - word_start == 1 && word_start[0] == '3') | |
976 | *is_system = true; | 976 | *is_system = true; | |
977 | /* Flag '4' is only interesting for C++. */ | 977 | /* Flag '4' is only interesting for C++. */ | |
978 | } | 978 | } | |
979 | } | 979 | } | |
980 | 980 | |||
981 | /* | 981 | /* | |
982 | * Called for preprocessor directives. Currently implemented are: | 982 | * Called for preprocessor directives. Currently implemented are: | |
983 | * # pragma [argument...] | 983 | * # pragma [argument...] | |
984 | * # lineno | 984 | * # lineno | |
985 | * # lineno "filename" | 985 | * # lineno "filename" | |
986 | * # lineno "filename" GCC-flag... | 986 | * # lineno "filename" GCC-flag... | |
987 | */ | 987 | */ | |
988 | void | 988 | void | |
989 | lex_directive(const char *yytext) | 989 | lex_directive(const char *yytext) | |
990 | { | 990 | { | |
991 | const char *cp, *fn; | 991 | const char *cp, *fn; | |
992 | char c, *eptr; | 992 | char c, *eptr; | |
993 | size_t fnl; | 993 | size_t fnl; | |
994 | long ln; | 994 | long ln; | |
995 | bool is_begin, is_end, is_system; | 995 | bool is_begin, is_end, is_system; | |
996 | 996 | |||
997 | static bool first = true; | 997 | static bool first = true; | |
998 | 998 | |||
999 | /* Go to first non-whitespace after # */ | 999 | /* Go to first non-whitespace after # */ | |
1000 | for (cp = yytext + 1; (c = *cp) == ' ' || c == '\t'; cp++) | 1000 | for (cp = yytext + 1; (c = *cp) == ' ' || c == '\t'; cp++) | |
1001 | continue; | 1001 | continue; | |
1002 | 1002 | |||
1003 | if (!ch_isdigit(c)) { | 1003 | if (!ch_isdigit(c)) { | |
1004 | if (strncmp(cp, "pragma", 6) == 0 && ch_isspace(cp[6])) | 1004 | if (strncmp(cp, "pragma", 6) == 0 && ch_isspace(cp[6])) | |
1005 | return; | 1005 | return; | |
1006 | error: | 1006 | error: | |
1007 | /* undefined or invalid # directive */ | 1007 | /* undefined or invalid # directive */ | |
1008 | warning(255); | 1008 | warning(255); | |
1009 | return; | 1009 | return; | |
1010 | } | 1010 | } | |
1011 | ln = strtol(--cp, &eptr, 10); | 1011 | ln = strtol(--cp, &eptr, 10); | |
1012 | if (eptr == cp) | 1012 | if (eptr == cp) | |
1013 | goto error; | 1013 | goto error; | |
1014 | if ((c = *(cp = eptr)) != ' ' && c != '\t' && c != '\0') | 1014 | if ((c = *(cp = eptr)) != ' ' && c != '\t' && c != '\0') | |
1015 | goto error; | 1015 | goto error; | |
1016 | while ((c = *cp++) == ' ' || c == '\t') | 1016 | while ((c = *cp++) == ' ' || c == '\t') | |
1017 | continue; | 1017 | continue; | |
1018 | if (c != '\0') { | 1018 | if (c != '\0') { | |
1019 | if (c != '"') | 1019 | if (c != '"') | |
1020 | goto error; | 1020 | goto error; | |
1021 | fn = cp; | 1021 | fn = cp; | |
1022 | while ((c = *cp) != '"' && c != '\0') | 1022 | while ((c = *cp) != '"' && c != '\0') | |
1023 | cp++; | 1023 | cp++; | |
1024 | if (c != '"') | 1024 | if (c != '"') | |
1025 | goto error; | 1025 | goto error; | |
1026 | if ((fnl = cp++ - fn) > PATH_MAX) | 1026 | if ((fnl = cp++ - fn) > PATH_MAX) | |
1027 | goto error; | 1027 | goto error; | |
1028 | /* empty string means stdin */ | 1028 | /* empty string means stdin */ | |
1029 | if (fnl == 0) { | 1029 | if (fnl == 0) { | |
1030 | fn = "{standard input}"; | 1030 | fn = "{standard input}"; | |
1031 | fnl = 16; /* strlen (fn) */ | 1031 | fnl = 16; /* strlen (fn) */ | |
1032 | } | 1032 | } | |
1033 | curr_pos.p_file = record_filename(fn, fnl); | 1033 | curr_pos.p_file = record_filename(fn, fnl); | |
1034 | /* | 1034 | /* | |
1035 | * If this is the first directive, the name is the name | 1035 | * If this is the first directive, the name is the name | |
1036 | * of the C source file as specified at the command line. | 1036 | * of the C source file as specified at the command line. | |
1037 | * It is written to the output file. | 1037 | * It is written to the output file. | |
1038 | */ | 1038 | */ | |
1039 | if (first) { | 1039 | if (first) { | |
1040 | csrc_pos.p_file = curr_pos.p_file; | 1040 | csrc_pos.p_file = curr_pos.p_file; | |
1041 | outsrc(transform_filename(curr_pos.p_file, | 1041 | outsrc(transform_filename(curr_pos.p_file, | |
1042 | strlen(curr_pos.p_file))); | 1042 | strlen(curr_pos.p_file))); | |
1043 | first = false; | 1043 | first = false; | |
1044 | } | 1044 | } | |
1045 | 1045 | |||
1046 | parse_line_directive_flags(cp, &is_begin, &is_end, &is_system); | 1046 | parse_line_directive_flags(cp, &is_begin, &is_end, &is_system); | |
1047 | update_location(curr_pos.p_file, (int)ln, is_begin, is_end); | 1047 | update_location(curr_pos.p_file, (int)ln, is_begin, is_end); | |
1048 | in_system_header = is_system; | 1048 | in_system_header = is_system; | |
1049 | } | 1049 | } | |
1050 | curr_pos.p_line = (int)ln - 1; | 1050 | curr_pos.p_line = (int)ln - 1; | |
1051 | curr_pos.p_uniq = 0; | 1051 | curr_pos.p_uniq = 0; | |
1052 | if (curr_pos.p_file == csrc_pos.p_file) { | 1052 | if (curr_pos.p_file == csrc_pos.p_file) { | |
1053 | csrc_pos.p_line = (int)ln - 1; | 1053 | csrc_pos.p_line = (int)ln - 1; | |
1054 | csrc_pos.p_uniq = 0; | 1054 | csrc_pos.p_uniq = 0; | |
1055 | } | 1055 | } | |
1056 | } | 1056 | } | |
1057 | 1057 | |||
1058 | /* | 1058 | /* | |
1059 | * Handle lint comments such as ARGSUSED. | 1059 | * Handle lint comments such as ARGSUSED. | |
1060 | * | 1060 | * | |
1061 | * If one of these comments is recognized, the argument, if any, is | 1061 | * If one of these comments is recognized, the argument, if any, is | |
1062 | * parsed and a function which handles this comment is called. | 1062 | * parsed and a function which handles this comment is called. | |
1063 | */ | 1063 | */ | |
1064 | void | 1064 | void | |
1065 | lex_comment(void) | 1065 | lex_comment(void) | |
1066 | { | 1066 | { | |
1067 | int c, lc; | 1067 | int c, lc; | |
1068 | static const struct { | 1068 | static const struct { | |
1069 | const char *keywd; | 1069 | const char *keywd; | |
1070 | bool arg; | 1070 | bool arg; | |
1071 | void (*func)(int); | 1071 | void (*func)(int); | |
1072 | } keywtab[] = { | 1072 | } keywtab[] = { | |
1073 | { "ARGSUSED", true, argsused }, | 1073 | { "ARGSUSED", true, argsused }, | |
1074 | { "BITFIELDTYPE", false, bitfieldtype }, | 1074 | { "BITFIELDTYPE", false, bitfieldtype }, | |
1075 | { "CONSTCOND", false, constcond }, | 1075 | { "CONSTCOND", false, constcond }, | |
1076 | { "CONSTANTCOND", false, constcond }, | 1076 | { "CONSTANTCOND", false, constcond }, | |
1077 | { "CONSTANTCONDITION", false, constcond }, | 1077 | { "CONSTANTCONDITION", false, constcond }, | |
1078 | { "FALLTHRU", false, fallthru }, | 1078 | { "FALLTHRU", false, fallthru }, | |
1079 | { "FALLTHROUGH", false, fallthru }, | 1079 | { "FALLTHROUGH", false, fallthru }, | |
1080 | { "FALL THROUGH", false, fallthru }, | 1080 | { "FALL THROUGH", false, fallthru }, | |
1081 | { "fallthrough", false, fallthru }, | 1081 | { "fallthrough", false, fallthru }, | |
1082 | { "LINTLIBRARY", false, lintlib }, | 1082 | { "LINTLIBRARY", false, lintlib }, | |
1083 | { "LINTED", true, linted }, | 1083 | { "LINTED", true, linted }, | |
1084 | { "LONGLONG", false, longlong }, | 1084 | { "LONGLONG", false, longlong }, | |
1085 | { "NOSTRICT", true, linted }, | 1085 | { "NOSTRICT", true, linted }, | |
1086 | { "NOTREACHED", false, not_reached }, | 1086 | { "NOTREACHED", false, not_reached }, | |
1087 | { "PRINTFLIKE", true, printflike }, | 1087 | { "PRINTFLIKE", true, printflike }, | |
1088 | { "PROTOLIB", true, protolib }, | 1088 | { "PROTOLIB", true, protolib }, | |
1089 | { "SCANFLIKE", true, scanflike }, | 1089 | { "SCANFLIKE", true, scanflike }, | |
1090 | { "VARARGS", true, varargs }, | 1090 | { "VARARGS", true, varargs }, | |
1091 | }; | 1091 | }; | |
1092 | char keywd[32]; | 1092 | char keywd[32]; | |
1093 | char arg[32]; | 1093 | char arg[32]; | |
1094 | size_t l, i; | 1094 | size_t l, i; | |
1095 | int a; | 1095 | int a; | |
1096 | bool eoc; | 1096 | bool eoc; | |
1097 | 1097 | |||
1098 | eoc = false; | 1098 | eoc = false; | |
1099 | 1099 | |||
1100 | /* Skip whitespace after the start of the comment */ | 1100 | /* Skip whitespace after the start of the comment */ | |
1101 | while (c = inpc(), isspace(c)) | 1101 | while (c = inpc(), isspace(c)) | |
1102 | continue; | 1102 | continue; | |
1103 | 1103 | |||
1104 | /* Read the potential keyword to keywd */ | 1104 | /* Read the potential keyword to keywd */ | |
1105 | l = 0; | 1105 | l = 0; | |
1106 | while (c != EOF && l < sizeof(keywd) - 1 && | 1106 | while (c != EOF && l < sizeof(keywd) - 1 && | |
1107 | (isalpha(c) || isspace(c))) { | 1107 | (isalpha(c) || isspace(c))) { | |
1108 | if (islower(c) && l > 0 && ch_isupper(keywd[0])) | 1108 | if (islower(c) && l > 0 && ch_isupper(keywd[0])) | |
1109 | break; | 1109 | break; | |
1110 | keywd[l++] = (char)c; | 1110 | keywd[l++] = (char)c; | |
1111 | c = inpc(); | 1111 | c = inpc(); | |
1112 | } | 1112 | } | |
1113 | while (l > 0 && ch_isspace(keywd[l - 1])) | 1113 | while (l > 0 && ch_isspace(keywd[l - 1])) | |
1114 | l--; | 1114 | l--; | |
1115 | keywd[l] = '\0'; | 1115 | keywd[l] = '\0'; | |
1116 | 1116 | |||
1117 | /* look for the keyword */ | 1117 | /* look for the keyword */ | |
1118 | for (i = 0; i < sizeof(keywtab) / sizeof(keywtab[0]); i++) { | 1118 | for (i = 0; i < sizeof(keywtab) / sizeof(keywtab[0]); i++) { | |
1119 | if (strcmp(keywtab[i].keywd, keywd) == 0) | 1119 | if (strcmp(keywtab[i].keywd, keywd) == 0) | |
1120 | break; | 1120 | break; | |
1121 | } | 1121 | } | |
1122 | if (i == sizeof(keywtab) / sizeof(keywtab[0])) | 1122 | if (i == sizeof(keywtab) / sizeof(keywtab[0])) | |
1123 | goto skip_rest; | 1123 | goto skip_rest; | |
1124 | 1124 | |||
1125 | /* skip whitespace after the keyword */ | 1125 | /* skip whitespace after the keyword */ | |
1126 | while (isspace(c)) | 1126 | while (isspace(c)) | |
1127 | c = inpc(); | 1127 | c = inpc(); | |
1128 | 1128 | |||
1129 | /* read the argument, if the keyword accepts one and there is one */ | 1129 | /* read the argument, if the keyword accepts one and there is one */ | |
1130 | l = 0; | 1130 | l = 0; | |
1131 | if (keywtab[i].arg) { | 1131 | if (keywtab[i].arg) { | |
1132 | while (isdigit(c) && l < sizeof(arg) - 1) { | 1132 | while (isdigit(c) && l < sizeof(arg) - 1) { | |
1133 | arg[l++] = (char)c; | 1133 | arg[l++] = (char)c; | |
1134 | c = inpc(); | 1134 | c = inpc(); | |
1135 | } | 1135 | } | |
1136 | } | 1136 | } | |
1137 | arg[l] = '\0'; | 1137 | arg[l] = '\0'; | |
1138 | a = l != 0 ? atoi(arg) : -1; | 1138 | a = l != 0 ? atoi(arg) : -1; | |
1139 | 1139 | |||
1140 | /* skip whitespace after the argument */ | 1140 | /* skip whitespace after the argument */ | |
1141 | while (isspace(c)) | 1141 | while (isspace(c)) | |
1142 | c = inpc(); | 1142 | c = inpc(); | |
1143 | 1143 | |||
1144 | if (c != '*' || (c = inpc()) != '/') { | 1144 | if (c != '*' || (c = inpc()) != '/') { | |
1145 | if (keywtab[i].func != linted) | 1145 | if (keywtab[i].func != linted) | |
1146 | /* extra characters in lint comment */ | 1146 | /* extra characters in lint comment */ | |
1147 | warning(257); | 1147 | warning(257); | |
1148 | } else { | 1148 | } else { | |
1149 | /* | 1149 | /* | |
1150 | * remember that we have already found the end of the | 1150 | * remember that we have already found the end of the | |
1151 | * comment | 1151 | * comment | |
1152 | */ | 1152 | */ | |
1153 | eoc = true; | 1153 | eoc = true; | |
1154 | } | 1154 | } | |
1155 | 1155 | |||
1156 | if (keywtab[i].func != NULL) | 1156 | if (keywtab[i].func != NULL) | |
1157 | (*keywtab[i].func)(a); | 1157 | (*keywtab[i].func)(a); | |
1158 | 1158 | |||
1159 | skip_rest: | 1159 | skip_rest: | |
1160 | while (!eoc) { | 1160 | while (!eoc) { | |
1161 | lc = c; | 1161 | lc = c; | |
1162 | if ((c = inpc()) == EOF) { | 1162 | if ((c = inpc()) == EOF) { | |
1163 | /* unterminated comment */ | 1163 | /* unterminated comment */ | |
1164 | error(256); | 1164 | error(256); | |
1165 | break; | 1165 | break; | |
1166 | } | 1166 | } | |
1167 | if (lc == '*' && c == '/') | 1167 | if (lc == '*' && c == '/') | |
1168 | eoc = true; | 1168 | eoc = true; | |
1169 | } | 1169 | } | |
1170 | } | 1170 | } | |
1171 | 1171 | |||
1172 | /* | 1172 | /* | |
1173 | * Handle // style comments | 1173 | * Handle // style comments | |
1174 | */ | 1174 | */ | |
1175 | void | 1175 | void | |
1176 | lex_slash_slash_comment(void) | 1176 | lex_slash_slash_comment(void) | |
1177 | { | 1177 | { | |
1178 | int c; | 1178 | int c; | |
1179 | 1179 | |||
1180 | if (!Sflag && !gflag) | 1180 | if (!Sflag && !gflag) | |
1181 | /* %s does not support // comments */ | 1181 | /* %s does not support // comments */ | |
1182 | gnuism(312, tflag ? "traditional C" : "C90"); | 1182 | gnuism(312, tflag ? "traditional C" : "C90"); | |
1183 | 1183 | |||
1184 | while ((c = inpc()) != EOF && c != '\n') | 1184 | while ((c = inpc()) != EOF && c != '\n') | |
1185 | continue; | 1185 | continue; | |
1186 | } | 1186 | } | |
1187 | 1187 | |||
1188 | /* | 1188 | /* | |
1189 | * Clear flags for lint comments LINTED, LONGLONG and CONSTCOND. | 1189 | * Clear flags for lint comments LINTED, LONGLONG and CONSTCOND. | |
1190 | * clear_warn_flags is called after function definitions and global and | 1190 | * clear_warn_flags is called after function definitions and global and | |
1191 | * local declarations and definitions. It is also called between | 1191 | * local declarations and definitions. It is also called between | |
1192 | * the controlling expression and the body of control statements | 1192 | * the controlling expression and the body of control statements | |
1193 | * (if, switch, for, while). | 1193 | * (if, switch, for, while). | |
1194 | */ | 1194 | */ | |
1195 | void | 1195 | void | |
1196 | clear_warn_flags(void) | 1196 | clear_warn_flags(void) | |
1197 | { | 1197 | { | |
1198 | 1198 | |||
1199 | lwarn = LWARN_ALL; | 1199 | lwarn = LWARN_ALL; | |
1200 | quadflg = false; | 1200 | quadflg = false; | |
1201 | constcond_flag = false; | 1201 | constcond_flag = false; | |
1202 | } | 1202 | } | |
1203 | 1203 | |||
1204 | /* | 1204 | /* | |
1205 | * Strings are stored in a dynamically allocated buffer and passed | 1205 | * Strings are stored in a dynamically allocated buffer and passed | |
1206 | * in yylval.y_string to the parser. The parser or the routines called | 1206 | * in yylval.y_string to the parser. The parser or the routines called | |
1207 | * by the parser are responsible for freeing this buffer. | 1207 | * by the parser are responsible for freeing this buffer. | |
1208 | */ | 1208 | */ | |
1209 | int | 1209 | int | |
1210 | lex_string(void) | 1210 | lex_string(void) | |
1211 | { | 1211 | { | |
1212 | unsigned char *s; | 1212 | unsigned char *s; | |
1213 | int c; | 1213 | int c; | |
1214 | size_t len, max; | 1214 | size_t len, max; | |
1215 | strg_t *strg; | 1215 | strg_t *strg; | |
1216 | 1216 | |||
1217 | s = xmalloc(max = 64); | 1217 | s = xmalloc(max = 64); | |
1218 | 1218 | |||
1219 | len = 0; | 1219 | len = 0; | |
1220 | while ((c = get_escaped_char('"')) >= 0) { | 1220 | while ((c = get_escaped_char('"')) >= 0) { | |
1221 | /* +1 to reserve space for a trailing NUL character */ | 1221 | /* +1 to reserve space for a trailing NUL character */ | |
1222 | if (len + 1 == max) | 1222 | if (len + 1 == max) | |
1223 | s = xrealloc(s, max *= 2); | 1223 | s = xrealloc(s, max *= 2); | |
1224 | s[len++] = (char)c; | 1224 | s[len++] = (char)c; | |
1225 | } | 1225 | } | |
1226 | s[len] = '\0'; | 1226 | s[len] = '\0'; | |
1227 | if (c == -2) | 1227 | if (c == -2) | |
1228 | /* unterminated string constant */ | 1228 | /* unterminated string constant */ | |
1229 | error(258); | 1229 | error(258); | |
1230 | 1230 | |||
1231 | strg = xcalloc(1, sizeof(*strg)); | 1231 | strg = xcalloc(1, sizeof(*strg)); | |
1232 | strg->st_tspec = CHAR; | 1232 | strg->st_tspec = CHAR; | |
1233 | strg->st_len = len; | 1233 | strg->st_len = len; | |
1234 | strg->st_cp = s; | 1234 | strg->st_cp = s; | |
1235 | 1235 | |||
1236 | yylval.y_string = strg; | 1236 | yylval.y_string = strg; | |
1237 | return T_STRING; | 1237 | return T_STRING; | |
1238 | } | 1238 | } | |
1239 | 1239 | |||
1240 | int | 1240 | int | |
1241 | lex_wide_string(void) | 1241 | lex_wide_string(void) | |
1242 | { | 1242 | { | |
1243 | char *s; | 1243 | char *s; | |
1244 | int c, n; | 1244 | int c, n; | |
1245 | size_t i, wi; | 1245 | size_t i, wi; | |
1246 | size_t len, max, wlen; | 1246 | size_t len, max, wlen; | |
1247 | wchar_t *ws; | 1247 | wchar_t *ws; | |
1248 | strg_t *strg; | 1248 | strg_t *strg; | |
1249 | 1249 | |||
1250 | s = xmalloc(max = 64); | 1250 | s = xmalloc(max = 64); | |
1251 | len = 0; | 1251 | len = 0; | |
1252 | while ((c = get_escaped_char('"')) >= 0) { | 1252 | while ((c = get_escaped_char('"')) >= 0) { | |
1253 | /* +1 to save space for a trailing NUL character */ | 1253 | /* +1 to save space for a trailing NUL character */ | |
1254 | if (len + 1 >= max) | 1254 | if (len + 1 >= max) | |
1255 | s = xrealloc(s, max *= 2); | 1255 | s = xrealloc(s, max *= 2); | |
1256 | s[len++] = (char)c; | 1256 | s[len++] = (char)c; | |
1257 | } | 1257 | } | |
1258 | s[len] = '\0'; | 1258 | s[len] = '\0'; | |
1259 | if (c == -2) | 1259 | if (c == -2) | |
1260 | /* unterminated string constant */ | 1260 | /* unterminated string constant */ | |
1261 | error(258); | 1261 | error(258); | |
1262 | 1262 | |||
1263 | /* get length of wide-character string */ | 1263 | /* get length of wide-character string */ | |
1264 | (void)mblen(NULL, 0); | 1264 | (void)mblen(NULL, 0); | |
1265 | for (i = 0, wlen = 0; i < len; i += n, wlen++) { | 1265 | for (i = 0, wlen = 0; i < len; i += n, wlen++) { | |
1266 | if ((n = mblen(&s[i], MB_CUR_MAX)) == -1) { | 1266 | if ((n = mblen(&s[i], MB_CUR_MAX)) == -1) { | |
1267 | /* invalid multibyte character */ | 1267 | /* invalid multibyte character */ | |
1268 | error(291); | 1268 | error(291); | |
1269 | break; | 1269 | break; | |
1270 | } | 1270 | } | |
1271 | if (n == 0) | 1271 | if (n == 0) | |
1272 | n = 1; | 1272 | n = 1; | |
1273 | } | 1273 | } | |
1274 | 1274 | |||
1275 | ws = xmalloc((wlen + 1) * sizeof(*ws)); | 1275 | ws = xmalloc((wlen + 1) * sizeof(*ws)); | |
1276 | 1276 | |||
1277 | /* convert from multibyte to wide char */ | 1277 | /* convert from multibyte to wide char */ | |
1278 | (void)mbtowc(NULL, NULL, 0); | 1278 | (void)mbtowc(NULL, NULL, 0); | |
1279 | for (i = 0, wi = 0; i < len; i += n, wi++) { | 1279 | for (i = 0, wi = 0; i < len; i += n, wi++) { | |
1280 | if ((n = mbtowc(&ws[wi], &s[i], MB_CUR_MAX)) == -1) | 1280 | if ((n = mbtowc(&ws[wi], &s[i], MB_CUR_MAX)) == -1) | |
1281 | break; | 1281 | break; | |
1282 | if (n == 0) | 1282 | if (n == 0) | |
1283 | n = 1; | 1283 | n = 1; | |
1284 | } | 1284 | } | |
1285 | ws[wi] = 0; | 1285 | ws[wi] = 0; | |
1286 | free(s); | 1286 | free(s); | |
1287 | 1287 | |||
1288 | strg = xcalloc(1, sizeof(*strg)); | 1288 | strg = xcalloc(1, sizeof(*strg)); | |
1289 | strg->st_tspec = WCHAR; | 1289 | strg->st_tspec = WCHAR; | |
1290 | strg->st_len = wlen; | 1290 | strg->st_len = wlen; | |
1291 | strg->st_wcp = ws; | 1291 | strg->st_wcp = ws; | |
1292 | 1292 | |||
1293 | yylval.y_string = strg; | 1293 | yylval.y_string = strg; | |
1294 | return T_STRING; | 1294 | return T_STRING; | |
1295 | } | 1295 | } | |
1296 | 1296 | |||
1297 | #ifdef DEBUG | 1297 | #ifdef DEBUG | |
1298 | static const char * | 1298 | static const char * | |
1299 | symt_name(symt_t kind) | 1299 | symt_name(symt_t kind) | |
1300 | { | 1300 | { | |
1301 | static const char *name[] = { | 1301 | static const char *name[] = { | |
1302 | "var-func-type", | 1302 | "var-func-type", | |
1303 | "member", | 1303 | "member", | |
1304 | "tag", | 1304 | "tag", | |
1305 | "label", | 1305 | "label", | |
1306 | }; | 1306 | }; | |
1307 | return name[kind]; | 1307 | return name[kind]; | |
1308 | } | 1308 | } | |
1309 | #endif | 1309 | #endif | |
1310 | 1310 | |||
1311 | /* | 1311 | /* | |
1312 | * As noted above, the scanner does not create new symbol table entries | 1312 | * As noted above, the scanner does not create new symbol table entries | |
1313 | * for symbols it cannot find in the symbol table. This is to avoid | 1313 | * for symbols it cannot find in the symbol table. This is to avoid | |
1314 | * putting undeclared symbols into the symbol table if a syntax error | 1314 | * putting undeclared symbols into the symbol table if a syntax error | |
1315 | * occurs. | 1315 | * occurs. | |
1316 | * | 1316 | * | |
1317 | * getsym() is called as soon as it is probably ok to put the symbol in the | 1317 | * getsym() is called as soon as it is probably ok to put the symbol in the | |
1318 | * symbol table. It is still possible that symbols are put in the symbol | 1318 | * symbol table. It is still possible that symbols are put in the symbol | |
1319 | * table that are not completely declared due to syntax errors. To avoid too | 1319 | * table that are not completely declared due to syntax errors. To avoid too | |
1320 | * many problems in this case, symbols get type 'int' in getsym(). | 1320 | * many problems in this case, symbols get type 'int' in getsym(). | |
1321 | * | 1321 | * | |
1322 | * XXX calls to getsym() should be delayed until decl1*() is called. | 1322 | * XXX calls to getsym() should be delayed until decl1*() is called. | |
1323 | */ | 1323 | */ | |
1324 | sym_t * | 1324 | sym_t * | |
1325 | getsym(sbuf_t *sb) | 1325 | getsym(sbuf_t *sb) | |
1326 | { | 1326 | { | |
1327 | dinfo_t *di; | 1327 | dinfo_t *di; | |
1328 | char *s; | 1328 | char *s; | |
1329 | sym_t *sym; | 1329 | sym_t *sym; | |
1330 | 1330 | |||
1331 | sym = sb->sb_sym; | 1331 | sym = sb->sb_sym; | |
1332 | 1332 | |||
1333 | /* | 1333 | /* | |
1334 | * During member declaration it is possible that name() looked | 1334 | * During member declaration it is possible that name() looked | |
1335 | * for symbols of type FVFT, although it should have looked for | 1335 | * for symbols of type FVFT, although it should have looked for | |
1336 | * symbols of type FTAG. Same can happen for labels. Both cases | 1336 | * symbols of type FTAG. Same can happen for labels. Both cases | |
1337 | * are compensated here. | 1337 | * are compensated here. | |
1338 | */ | 1338 | */ | |
1339 | if (symtyp == FMEMBER || symtyp == FLABEL) { | 1339 | if (symtyp == FMEMBER || symtyp == FLABEL) { | |
1340 | if (sym == NULL || sym->s_kind == FVFT) | 1340 | if (sym == NULL || sym->s_kind == FVFT) | |
1341 | sym = search(sb); | 1341 | sym = search(sb); | |
1342 | } | 1342 | } | |
1343 | 1343 | |||
1344 | if (sym != NULL) { | 1344 | if (sym != NULL) { | |
1345 | lint_assert(sym->s_kind == symtyp); | 1345 | lint_assert(sym->s_kind == symtyp); | |
1346 | symtyp = FVFT; | 1346 | symtyp = FVFT; | |
1347 | free(sb); | 1347 | free(sb); | |
1348 | return sym; | 1348 | return sym; | |
1349 | } | 1349 | } | |
1350 | 1350 | |||
1351 | /* create a new symbol table entry */ | 1351 | /* create a new symbol table entry */ | |
1352 | 1352 | |||
1353 | /* labels must always be allocated at level 1 (outermost block) */ | 1353 | /* labels must always be allocated at level 1 (outermost block) */ | |
1354 | if (symtyp == FLABEL) { | 1354 | if (symtyp == FLABEL) { | |
1355 | sym = level_zero_alloc(1, sizeof(*sym)); | 1355 | sym = level_zero_alloc(1, sizeof(*sym)); | |
1356 | s = level_zero_alloc(1, sb->sb_len + 1); | 1356 | s = level_zero_alloc(1, sb->sb_len + 1); | |
1357 | (void)memcpy(s, sb->sb_name, sb->sb_len + 1); | 1357 | (void)memcpy(s, sb->sb_name, sb->sb_len + 1); | |
1358 | sym->s_name = s; | 1358 | sym->s_name = s; | |
1359 | sym->s_block_level = 1; | 1359 | sym->s_block_level = 1; | |
1360 | di = dcs; | 1360 | di = dcs; | |
1361 | while (di->d_next != NULL && di->d_next->d_next != NULL) | 1361 | while (di->d_next != NULL && di->d_next->d_next != NULL) | |
1362 | di = di->d_next; | 1362 | di = di->d_next; | |
1363 | lint_assert(di->d_ctx == AUTO); | 1363 | lint_assert(di->d_ctx == AUTO); | |
1364 | } else { | 1364 | } else { | |
1365 | sym = block_zero_alloc(sizeof(*sym)); | 1365 | sym = block_zero_alloc(sizeof(*sym)); | |
1366 | sym->s_name = sb->sb_name; | 1366 | sym->s_name = sb->sb_name; | |
1367 | sym->s_block_level = block_level; | 1367 | sym->s_block_level = block_level; | |
1368 | di = dcs; | 1368 | di = dcs; | |
1369 | } | 1369 | } | |
1370 | 1370 | |||
1371 | UNIQUE_CURR_POS(sym->s_def_pos); | 1371 | UNIQUE_CURR_POS(sym->s_def_pos); | |
1372 | if ((sym->s_kind = symtyp) != FLABEL) | 1372 | if ((sym->s_kind = symtyp) != FLABEL) | |
1373 | sym->s_type = gettyp(INT); | 1373 | sym->s_type = gettyp(INT); | |
1374 | 1374 | |||
1375 | symtyp = FVFT; | 1375 | symtyp = FVFT; | |
1376 | 1376 | |||
1377 | symtab_add(sym); | 1377 | symtab_add(sym); | |
1378 | 1378 | |||
1379 | *di->d_ldlsym = sym; | 1379 | *di->d_ldlsym = sym; | |
1380 | di->d_ldlsym = &sym->s_dlnxt; | 1380 | di->d_ldlsym = &sym->s_level_next; | |
1381 | 1381 | |||
1382 | free(sb); | 1382 | free(sb); | |
1383 | return sym; | 1383 | return sym; | |
1384 | } | 1384 | } | |
1385 | 1385 | |||
1386 | /* | 1386 | /* | |
1387 | * Construct a temporary symbol. The symbol name starts with a digit, making | 1387 | * Construct a temporary symbol. The symbol name starts with a digit, making | |
1388 | * the name illegal. | 1388 | * the name illegal. | |
1389 | */ | 1389 | */ | |
1390 | sym_t * | 1390 | sym_t * | |
1391 | mktempsym(type_t *t) | 1391 | mktempsym(type_t *t) | |
1392 | { | 1392 | { | |
1393 | static int n = 0; | 1393 | static int n = 0; | |
1394 | char *s = level_zero_alloc(block_level, 64); | 1394 | char *s = level_zero_alloc(block_level, 64); | |
1395 | sym_t *sym = block_zero_alloc(sizeof(*sym)); | 1395 | sym_t *sym = block_zero_alloc(sizeof(*sym)); | |
1396 | scl_t scl; | 1396 | scl_t scl; | |
1397 | 1397 | |||
1398 | (void)snprintf(s, 64, "%.8d_tmp", n++); | 1398 | (void)snprintf(s, 64, "%.8d_tmp", n++); | |
1399 | 1399 | |||
1400 | scl = dcs->d_scl; | 1400 | scl = dcs->d_scl; | |
1401 | if (scl == NOSCL) | 1401 | if (scl == NOSCL) | |
1402 | scl = block_level > 0 ? AUTO : EXTERN; | 1402 | scl = block_level > 0 ? AUTO : EXTERN; | |
1403 | 1403 | |||
1404 | sym->s_name = s; | 1404 | sym->s_name = s; | |
1405 | sym->s_type = t; | 1405 | sym->s_type = t; | |
1406 | sym->s_block_level = block_level; | 1406 | sym->s_block_level = block_level; | |
1407 | sym->s_scl = scl; | 1407 | sym->s_scl = scl; | |
1408 | sym->s_kind = FVFT; | 1408 | sym->s_kind = FVFT; | |
1409 | sym->s_used = true; | 1409 | sym->s_used = true; | |
1410 | sym->s_set = true; | 1410 | sym->s_set = true; | |
1411 | 1411 | |||
1412 | symtab_add(sym); | 1412 | symtab_add(sym); | |
1413 | 1413 | |||
1414 | *dcs->d_ldlsym = sym; | 1414 | *dcs->d_ldlsym = sym; | |
1415 | dcs->d_ldlsym = &sym->s_dlnxt; | 1415 | dcs->d_ldlsym = &sym->s_level_next; | |
1416 | 1416 | |||
1417 | return sym; | 1417 | return sym; | |
1418 | } | 1418 | } | |
1419 | 1419 | |||
1420 | /* Remove a symbol forever from the symbol table. */ | 1420 | /* Remove a symbol forever from the symbol table. */ | |
1421 | void | 1421 | void | |
1422 | rmsym(sym_t *sym) | 1422 | rmsym(sym_t *sym) | |
1423 | { | 1423 | { | |
1424 | 1424 | |||
1425 | debug_step("rmsym '%s' %s '%s'", | 1425 | debug_step("rmsym '%s' %s '%s'", | |
1426 | sym->s_name, symt_name(sym->s_kind), type_name(sym->s_type)); | 1426 | sym->s_name, symt_name(sym->s_kind), type_name(sym->s_type)); | |
1427 | symtab_remove(sym); | 1427 | symtab_remove(sym); | |
1428 | 1428 | |||
1429 | /* avoid that the symbol will later be put back to the symbol table */ | 1429 | /* avoid that the symbol will later be put back to the symbol table */ | |
1430 | sym->s_block_level = -1; | 1430 | sym->s_block_level = -1; | |
1431 | } | 1431 | } | |
1432 | 1432 | |||
1433 | /* | 1433 | /* | |
1434 | * Remove a list of symbols declared at one level from the symbol | 1434 | * Remove a list of symbols declared at one level from the symbol | |
1435 | * table. | 1435 | * table. | |
1436 | */ | 1436 | */ | |
1437 | void | 1437 | void | |
1438 | rmsyms(sym_t *syms) | 1438 | rmsyms(sym_t *syms) | |
1439 | { | 1439 | { | |
1440 | sym_t *sym; | 1440 | sym_t *sym; | |
1441 | 1441 | |||
1442 | for (sym = syms; sym != NULL; sym = sym->s_dlnxt) { | 1442 | for (sym = syms; sym != NULL; sym = sym->s_level_next) { | |
1443 | if (sym->s_block_level != -1) { | 1443 | if (sym->s_block_level != -1) { | |
1444 | debug_step("rmsyms '%s' %s '%s'", | 1444 | debug_step("rmsyms '%s' %s '%s'", | |
1445 | sym->s_name, symt_name(sym->s_kind), | 1445 | sym->s_name, symt_name(sym->s_kind), | |
1446 | type_name(sym->s_type)); | 1446 | type_name(sym->s_type)); | |
1447 | symtab_remove(sym); | 1447 | symtab_remove(sym); | |
1448 | sym->s_rlink = NULL; | 1448 | sym->s_symtab_ref = NULL; | |
1449 | } | 1449 | } | |
1450 | } | 1450 | } | |
1451 | } | 1451 | } | |
1452 | 1452 | |||
1453 | /* | 1453 | /* | |
1454 | * Put a symbol into the symbol table. | 1454 | * Put a symbol into the symbol table. | |
1455 | */ | 1455 | */ | |
1456 | void | 1456 | void | |
1457 | inssym(int bl, sym_t *sym) | 1457 | inssym(int bl, sym_t *sym) | |
1458 | { | 1458 | { | |
1459 | 1459 | |||
1460 | debug_step("inssym '%s' %s '%s'", | 1460 | debug_step("inssym '%s' %s '%s'", | |
1461 | sym->s_name, symt_name(sym->s_kind), type_name(sym->s_type)); | 1461 | sym->s_name, symt_name(sym->s_kind), type_name(sym->s_type)); | |
1462 | symtab_add(sym); | 1462 | symtab_add(sym); | |
1463 | sym->s_block_level = bl; | 1463 | sym->s_block_level = bl; | |
1464 | lint_assert(sym->s_link == NULL || | 1464 | lint_assert(sym->s_symtab_next == NULL || | |
1465 | sym->s_block_level >= sym->s_link->s_block_level); | 1465 | sym->s_block_level >= sym->s_symtab_next->s_block_level); | |
1466 | } | 1466 | } | |
1467 | 1467 | |||
1468 | /* | 1468 | /* | |
1469 | * Called at level 0 after syntax errors. | 1469 | * Called at level 0 after syntax errors. | |
1470 | * | 1470 | * | |
1471 | * Removes all symbols which are not declared at level 0 from the | 1471 | * Removes all symbols which are not declared at level 0 from the | |
1472 | * symbol table. Also frees all memory which is not associated with | 1472 | * symbol table. Also frees all memory which is not associated with | |
1473 | * level 0. | 1473 | * level 0. | |
1474 | */ | 1474 | */ | |
1475 | void | 1475 | void | |
1476 | cleanup(void) | 1476 | cleanup(void) | |
1477 | { | 1477 | { | |
1478 | sym_t *sym, *nsym; | 1478 | sym_t *sym, *nsym; | |
1479 | size_t i; | 1479 | size_t i; | |
1480 | 1480 | |||
1481 | for (i = 0; i < HSHSIZ1; i++) { | 1481 | for (i = 0; i < HSHSIZ1; i++) { | |
1482 | for (sym = symtab[i]; sym != NULL; sym = nsym) { | 1482 | for (sym = symtab[i]; sym != NULL; sym = nsym) { | |
1483 | nsym = sym->s_link; | 1483 | nsym = sym->s_symtab_next; | |
1484 | if (sym->s_block_level >= 1) | 1484 | if (sym->s_block_level >= 1) | |
1485 | symtab_remove(sym); | 1485 | symtab_remove(sym); | |
1486 | } | 1486 | } | |
1487 | } | 1487 | } | |
1488 | 1488 | |||
1489 | for (i = mem_block_level; i > 0; i--) | 1489 | for (i = mem_block_level; i > 0; i--) | |
1490 | level_free_all(i); | 1490 | level_free_all(i); | |
1491 | } | 1491 | } | |
1492 | 1492 | |||
1493 | /* | 1493 | /* | |
1494 | * Create a new symbol with the name of an existing symbol. | 1494 | * Create a new symbol with the name of an existing symbol. | |
1495 | */ | 1495 | */ | |
1496 | sym_t * | 1496 | sym_t * | |
1497 | pushdown(const sym_t *sym) | 1497 | pushdown(const sym_t *sym) | |
1498 | { | 1498 | { | |
1499 | sym_t *nsym; | 1499 | sym_t *nsym; | |
1500 | 1500 | |||
1501 | debug_step("pushdown '%s' %s '%s'", | 1501 | debug_step("pushdown '%s' %s '%s'", | |
1502 | sym->s_name, symt_name(sym->s_kind), type_name(sym->s_type)); | 1502 | sym->s_name, symt_name(sym->s_kind), type_name(sym->s_type)); | |
1503 | nsym = block_zero_alloc(sizeof(*nsym)); | 1503 | nsym = block_zero_alloc(sizeof(*nsym)); | |
1504 | lint_assert(sym->s_block_level <= block_level); | 1504 | lint_assert(sym->s_block_level <= block_level); | |
1505 | nsym->s_name = sym->s_name; | 1505 | nsym->s_name = sym->s_name; | |
1506 | UNIQUE_CURR_POS(nsym->s_def_pos); | 1506 | UNIQUE_CURR_POS(nsym->s_def_pos); | |
1507 | nsym->s_kind = sym->s_kind; | 1507 | nsym->s_kind = sym->s_kind; | |
1508 | nsym->s_block_level = block_level; | 1508 | nsym->s_block_level = block_level; | |
1509 | 1509 | |||
1510 | symtab_add(nsym); | 1510 | symtab_add(nsym); | |
1511 | 1511 | |||
1512 | *dcs->d_ldlsym = nsym; | 1512 | *dcs->d_ldlsym = nsym; | |
1513 | dcs->d_ldlsym = &nsym->s_dlnxt; | 1513 | dcs->d_ldlsym = &nsym->s_level_next; | |
1514 | 1514 | |||
1515 | return nsym; | 1515 | return nsym; | |
1516 | } | 1516 | } | |
1517 | 1517 | |||
1518 | /* | 1518 | /* | |
1519 | * Free any dynamically allocated memory referenced by | 1519 | * Free any dynamically allocated memory referenced by | |
1520 | * the value stack or yylval. | 1520 | * the value stack or yylval. | |
1521 | * The type of information in yylval is described by tok. | 1521 | * The type of information in yylval is described by tok. | |
1522 | */ | 1522 | */ | |
1523 | void | 1523 | void | |
1524 | freeyyv(void *sp, int tok) | 1524 | freeyyv(void *sp, int tok) | |
1525 | { | 1525 | { | |
1526 | if (tok == T_NAME || tok == T_TYPENAME) { | 1526 | if (tok == T_NAME || tok == T_TYPENAME) { | |
1527 | sbuf_t *sb = *(sbuf_t **)sp; | 1527 | sbuf_t *sb = *(sbuf_t **)sp; | |
1528 | free(sb); | 1528 | free(sb); | |
1529 | } else if (tok == T_CON) { | 1529 | } else if (tok == T_CON) { | |
1530 | val_t *val = *(val_t **)sp; | 1530 | val_t *val = *(val_t **)sp; | |
1531 | free(val); | 1531 | free(val); | |
1532 | } else if (tok == T_STRING) { | 1532 | } else if (tok == T_STRING) { | |
1533 | strg_t *strg = *(strg_t **)sp; | 1533 | strg_t *strg = *(strg_t **)sp; | |
1534 | if (strg->st_tspec == CHAR) { | 1534 | if (strg->st_tspec == CHAR) { | |
1535 | free(strg->st_cp); | 1535 | free(strg->st_cp); | |
1536 | } else { | 1536 | } else { | |
1537 | lint_assert(strg->st_tspec == WCHAR); | 1537 | lint_assert(strg->st_tspec == WCHAR); | |
1538 | free(strg->st_wcp); | 1538 | free(strg->st_wcp); | |
1539 | } | 1539 | } | |
1540 | free(strg); | 1540 | free(strg); | |
1541 | } | 1541 | } | |
1542 | } | 1542 | } |
--- src/usr.bin/xlint/lint1/lint1.h 2022/02/27 07:50:09 1.138
+++ src/usr.bin/xlint/lint1/lint1.h 2022/02/27 10:44:45 1.139
@@ -1,601 +1,603 @@ | @@ -1,601 +1,603 @@ | |||
1 | /* $NetBSD: lint1.h,v 1.138 2022/02/27 07:50:09 rillig Exp $ */ | 1 | /* $NetBSD: lint1.h,v 1.139 2022/02/27 10:44:45 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 | #include "lint.h" | 35 | #include "lint.h" | |
36 | #include "err-msgs.h" | 36 | #include "err-msgs.h" | |
37 | #include "op.h" | 37 | #include "op.h" | |
38 | 38 | |||
39 | /* | 39 | /* | |
40 | * XXX - Super conservative so that works for most systems, but we should | 40 | * XXX - Super conservative so that works for most systems, but we should | |
41 | * not depend on the host settings but the target settings in determining | 41 | * not depend on the host settings but the target settings in determining | |
42 | * the alignment. The only valid use for this is in mem1.c; uses in decl.c | 42 | * the alignment. The only valid use for this is in mem1.c; uses in decl.c | |
43 | * are bogus. | 43 | * are bogus. | |
44 | */ | 44 | */ | |
45 | #ifndef WORST_ALIGN | 45 | #ifndef WORST_ALIGN | |
46 | #ifdef _LP64 | 46 | #ifdef _LP64 | |
47 | # define AVAL 15 | 47 | # define AVAL 15 | |
48 | #else | 48 | #else | |
49 | # define AVAL 7 | 49 | # define AVAL 7 | |
50 | #endif | 50 | #endif | |
51 | #define WORST_ALIGN(x) (((x) + AVAL) & ~AVAL) | 51 | #define WORST_ALIGN(x) (((x) + AVAL) & ~AVAL) | |
52 | #endif | 52 | #endif | |
53 | 53 | |||
54 | #define LWARN_BAD (-3) | 54 | #define LWARN_BAD (-3) | |
55 | #define LWARN_ALL (-2) | 55 | #define LWARN_ALL (-2) | |
56 | #define LWARN_NONE (-1) | 56 | #define LWARN_NONE (-1) | |
57 | 57 | |||
58 | /* | 58 | /* | |
59 | * Describes the position of a declaration or anything else. | 59 | * Describes the position of a declaration or anything else. | |
60 | * | 60 | * | |
61 | * FIXME: Just a single file:lineno pair is not enough to accurately describe | 61 | * FIXME: Just a single file:lineno pair is not enough to accurately describe | |
62 | * the position of a symbol. The whole inclusion path at that point must be | 62 | * the position of a symbol. The whole inclusion path at that point must be | |
63 | * stored as well. This makes a difference for symbols from included | 63 | * stored as well. This makes a difference for symbols from included | |
64 | * headers, see print_stack_trace. | 64 | * headers, see print_stack_trace. | |
65 | */ | 65 | */ | |
66 | typedef struct { | 66 | typedef struct { | |
67 | const char *p_file; | 67 | const char *p_file; | |
68 | int p_line; | 68 | int p_line; | |
69 | int p_uniq; /* uniquifier */ | 69 | int p_uniq; /* uniquifier */ | |
70 | } pos_t; | 70 | } pos_t; | |
71 | 71 | |||
72 | /* Copies curr_pos, keeping things unique. */ | 72 | /* Copies curr_pos, keeping things unique. */ | |
73 | #define UNIQUE_CURR_POS(pos) \ | 73 | #define UNIQUE_CURR_POS(pos) \ | |
74 | do { \ | 74 | do { \ | |
75 | (pos) = curr_pos; \ | 75 | (pos) = curr_pos; \ | |
76 | curr_pos.p_uniq++; \ | 76 | curr_pos.p_uniq++; \ | |
77 | if (curr_pos.p_file == csrc_pos.p_file) \ | 77 | if (curr_pos.p_file == csrc_pos.p_file) \ | |
78 | csrc_pos.p_uniq++; \ | 78 | csrc_pos.p_uniq++; \ | |
79 | } while (false) | 79 | } while (false) | |
80 | 80 | |||
81 | /* | 81 | /* | |
82 | * Strings cannot be referenced simply by a pointer to their first | 82 | * Strings cannot be referenced simply by a pointer to their first | |
83 | * char. This is because strings can contain NUL characters other than the | 83 | * char. This is because strings can contain NUL characters other than the | |
84 | * trailing NUL. | 84 | * trailing NUL. | |
85 | * | 85 | * | |
86 | * Strings are stored with a trailing NUL. | 86 | * Strings are stored with a trailing NUL. | |
87 | */ | 87 | */ | |
88 | typedef struct strg { | 88 | typedef struct strg { | |
89 | tspec_t st_tspec; /* CHAR or WCHAR */ | 89 | tspec_t st_tspec; /* CHAR or WCHAR */ | |
90 | size_t st_len; /* length without trailing NUL */ | 90 | size_t st_len; /* length without trailing NUL */ | |
91 | union { | 91 | union { | |
92 | unsigned char *_st_cp; | 92 | unsigned char *_st_cp; | |
93 | wchar_t *_st_wcp; | 93 | wchar_t *_st_wcp; | |
94 | } st_u; | 94 | } st_u; | |
95 | } strg_t; | 95 | } strg_t; | |
96 | 96 | |||
97 | #define st_cp st_u._st_cp | 97 | #define st_cp st_u._st_cp | |
98 | #define st_wcp st_u._st_wcp | 98 | #define st_wcp st_u._st_wcp | |
99 | 99 | |||
100 | /* | 100 | /* | |
101 | * qualifiers (only for lex/yacc interface) | 101 | * qualifiers (only for lex/yacc interface) | |
102 | */ | 102 | */ | |
103 | typedef enum { | 103 | typedef enum { | |
104 | CONST, VOLATILE, RESTRICT, THREAD | 104 | CONST, VOLATILE, RESTRICT, THREAD | |
105 | } tqual_t; | 105 | } tqual_t; | |
106 | 106 | |||
107 | /* An integer or floating-point value. */ | 107 | /* An integer or floating-point value. */ | |
108 | typedef struct { | 108 | typedef struct { | |
109 | tspec_t v_tspec; | 109 | tspec_t v_tspec; | |
110 | /* | 110 | /* | |
111 | * Set if an integer constant is unsigned only in C90 and later, but | 111 | * Set if an integer constant is unsigned only in C90 and later, but | |
112 | * not in traditional C. | 112 | * not in traditional C. | |
113 | * | 113 | * | |
114 | * See the operators table in ops.def, columns "l r". | 114 | * See the operators table in ops.def, columns "l r". | |
115 | */ | 115 | */ | |
116 | bool v_unsigned_since_c90; | 116 | bool v_unsigned_since_c90; | |
117 | union { | 117 | union { | |
118 | int64_t _v_quad; /* integers */ | 118 | int64_t _v_quad; /* integers */ | |
119 | ldbl_t _v_ldbl; /* floats */ | 119 | ldbl_t _v_ldbl; /* floats */ | |
120 | } v_u; | 120 | } v_u; | |
121 | } val_t; | 121 | } val_t; | |
122 | 122 | |||
123 | #define v_quad v_u._v_quad | 123 | #define v_quad v_u._v_quad | |
124 | #define v_ldbl v_u._v_ldbl | 124 | #define v_ldbl v_u._v_ldbl | |
125 | 125 | |||
126 | /* | 126 | /* | |
127 | * Structures of type struct_or_union uniquely identify structures. This can't | 127 | * Structures of type struct_or_union uniquely identify structures. This can't | |
128 | * be done in structures of type type_t, because these are copied | 128 | * be done in structures of type type_t, because these are copied | |
129 | * if they must be modified. So it would not be possible to check | 129 | * if they must be modified. So it would not be possible to check | |
130 | * if two structures are identical by comparing the pointers to | 130 | * if two structures are identical by comparing the pointers to | |
131 | * the type structures. | 131 | * the type structures. | |
132 | * | 132 | * | |
133 | * The typename is used if the structure is unnamed to identify | 133 | * The typename is used if the structure is unnamed to identify | |
134 | * the structure type in pass 2. | 134 | * the structure type in pass 2. | |
135 | */ | 135 | */ | |
136 | typedef struct { | 136 | typedef struct { | |
137 | unsigned int sou_size_in_bits; | 137 | unsigned int sou_size_in_bits; | |
138 | unsigned short sou_align_in_bits; | 138 | unsigned short sou_align_in_bits; | |
139 | bool sou_incomplete:1; | 139 | bool sou_incomplete:1; | |
140 | struct sym *sou_first_member; | 140 | struct sym *sou_first_member; | |
141 | struct sym *sou_tag; | 141 | struct sym *sou_tag; | |
142 | struct sym *sou_first_typedef; | 142 | struct sym *sou_first_typedef; | |
143 | } struct_or_union; | 143 | } struct_or_union; | |
144 | 144 | |||
145 | /* | 145 | /* | |
146 | * same as above for enums | 146 | * same as above for enums | |
147 | */ | 147 | */ | |
148 | typedef struct { | 148 | typedef struct { | |
149 | bool en_incomplete:1; | 149 | bool en_incomplete:1; | |
150 | struct sym *en_first_enumerator; | 150 | struct sym *en_first_enumerator; | |
151 | struct sym *en_tag; | 151 | struct sym *en_tag; | |
152 | struct sym *en_first_typedef; | 152 | struct sym *en_first_typedef; | |
153 | } enumeration; | 153 | } enumeration; | |
154 | 154 | |||
155 | /* | 155 | /* | |
156 | * The type of an expression or object. Complex types are formed via t_subt | 156 | * The type of an expression or object. Complex types are formed via t_subt | |
157 | * (for arrays, pointers and functions), as well as t_str. | 157 | * (for arrays, pointers and functions), as well as t_str. | |
158 | */ | 158 | */ | |
159 | struct lint1_type { | 159 | struct lint1_type { | |
160 | tspec_t t_tspec; /* type specifier */ | 160 | tspec_t t_tspec; /* type specifier */ | |
161 | bool t_incomplete_array:1; | 161 | bool t_incomplete_array:1; | |
162 | bool t_const:1; /* const modifier */ | 162 | bool t_const:1; /* const modifier */ | |
163 | bool t_volatile:1; /* volatile modifier */ | 163 | bool t_volatile:1; /* volatile modifier */ | |
164 | bool t_proto:1; /* function prototype (t_args valid) */ | 164 | bool t_proto:1; /* function prototype (t_args valid) */ | |
165 | bool t_vararg:1; /* prototype with '...' */ | 165 | bool t_vararg:1; /* prototype with '...' */ | |
166 | bool t_typedef:1; /* type defined with typedef */ | 166 | bool t_typedef:1; /* type defined with typedef */ | |
167 | bool t_bitfield:1; | 167 | bool t_bitfield:1; | |
168 | /* | 168 | /* | |
169 | * Either the type is currently an enum (having t_tspec ENUM), or | 169 | * Either the type is currently an enum (having t_tspec ENUM), or | |
170 | * it is an integer type (typically INT) that has been implicitly | 170 | * it is an integer type (typically INT) that has been implicitly | |
171 | * converted from an enum type. In both cases, t_enum is valid. | 171 | * converted from an enum type. In both cases, t_enum is valid. | |
172 | * | 172 | * | |
173 | * The information about a former enum type is retained to allow | 173 | * The information about a former enum type is retained to allow | |
174 | * type checks in expressions such as ((var1 & 0x0001) == var2), to | 174 | * type checks in expressions such as ((var1 & 0x0001) == var2), to | |
175 | * detect when var1 and var2 are from incompatible enum types. | 175 | * detect when var1 and var2 are from incompatible enum types. | |
176 | */ | 176 | */ | |
177 | bool t_is_enum:1; | 177 | bool t_is_enum:1; | |
178 | bool t_packed:1; | 178 | bool t_packed:1; | |
179 | union { | 179 | union { | |
180 | int _t_dim; /* dimension (if ARRAY) */ | 180 | int _t_dim; /* dimension (if ARRAY) */ | |
181 | struct_or_union *_t_str; | 181 | struct_or_union *_t_str; | |
182 | enumeration *_t_enum; | 182 | enumeration *_t_enum; | |
183 | struct sym *_t_args; /* arguments (if t_proto) */ | 183 | struct sym *_t_args; /* arguments (if t_proto) */ | |
184 | } t_u; | 184 | } t_u; | |
185 | struct { | 185 | struct { | |
186 | unsigned int _t_flen:8; /* length of bit-field */ | 186 | unsigned int _t_flen:8; /* length of bit-field */ | |
187 | unsigned int _t_foffs:24; /* offset of bit-field */ | 187 | unsigned int _t_foffs:24; /* offset of bit-field */ | |
188 | } t_b; | 188 | } t_b; | |
189 | struct lint1_type *t_subt; /* element type (if ARRAY), | 189 | struct lint1_type *t_subt; /* element type (if ARRAY), | |
190 | * return value (if FUNC), | 190 | * return value (if FUNC), | |
191 | * target type (if PTR) */ | 191 | * target type (if PTR) */ | |
192 | }; | 192 | }; | |
193 | 193 | |||
194 | #define t_dim t_u._t_dim | 194 | #define t_dim t_u._t_dim | |
195 | /* TODO: rename t_str to t_sou, to avoid confusing it with strings. */ | 195 | /* TODO: rename t_str to t_sou, to avoid confusing it with strings. */ | |
196 | #define t_str t_u._t_str | 196 | #define t_str t_u._t_str | |
197 | #define t_enum t_u._t_enum | 197 | #define t_enum t_u._t_enum | |
198 | #define t_args t_u._t_args | 198 | #define t_args t_u._t_args | |
199 | #define t_flen t_b._t_flen | 199 | #define t_flen t_b._t_flen | |
200 | #define t_foffs t_b._t_foffs | 200 | #define t_foffs t_b._t_foffs | |
201 | 201 | |||
202 | /* | 202 | /* | |
203 | * types of symbols | 203 | * types of symbols | |
204 | */ | 204 | */ | |
205 | typedef enum { | 205 | typedef enum { | |
206 | FVFT, /* variables, functions, type names, enums */ | 206 | FVFT, /* variables, functions, type names, enums */ | |
207 | FMEMBER, /* members of structs or unions */ | 207 | FMEMBER, /* members of structs or unions */ | |
208 | FTAG, /* tags */ | 208 | FTAG, /* tags */ | |
209 | FLABEL /* labels */ | 209 | FLABEL /* labels */ | |
210 | } symt_t; | 210 | } symt_t; | |
211 | 211 | |||
212 | /* | 212 | /* | |
213 | * storage classes and related things | 213 | * storage classes and related things | |
214 | */ | 214 | */ | |
215 | typedef enum { | 215 | typedef enum { | |
216 | NOSCL, | 216 | NOSCL, | |
217 | EXTERN, /* external symbols (independent of decl_t) */ | 217 | EXTERN, /* external symbols (independent of decl_t) */ | |
218 | STATIC, /* static symbols (local and global) */ | 218 | STATIC, /* static symbols (local and global) */ | |
219 | AUTO, /* automatic symbols (except register) */ | 219 | AUTO, /* automatic symbols (except register) */ | |
220 | REG, /* register */ | 220 | REG, /* register */ | |
221 | TYPEDEF, /* typedef */ | 221 | TYPEDEF, /* typedef */ | |
222 | STRUCT_TAG, | 222 | STRUCT_TAG, | |
223 | UNION_TAG, | 223 | UNION_TAG, | |
224 | ENUM_TAG, | 224 | ENUM_TAG, | |
225 | MOS, /* member of struct */ | 225 | MOS, /* member of struct */ | |
226 | MOU, /* member of union */ | 226 | MOU, /* member of union */ | |
227 | CTCONST, /* enumerator, enum constant or bool constant */ | 227 | CTCONST, /* enumerator, enum constant or bool constant */ | |
228 | ABSTRACT, /* abstract symbol (sizeof, casts, unnamed argument) */ | 228 | ABSTRACT, /* abstract symbol (sizeof, casts, unnamed argument) */ | |
229 | OLD_STYLE_ARG, /* old-style function argument declarations */ | 229 | OLD_STYLE_ARG, /* old-style function argument declarations */ | |
230 | PROTO_ARG, /* used in declaration stack during prototype | 230 | PROTO_ARG, /* used in declaration stack during prototype | |
231 | declaration */ | 231 | declaration */ | |
232 | INLINE /* only used by the parser */ | 232 | INLINE /* only used by the parser */ | |
233 | } scl_t; | 233 | } scl_t; | |
234 | 234 | |||
235 | /* | 235 | /* | |
236 | * symbol table entry | 236 | * symbol table entry | |
237 | */ | 237 | */ | |
238 | typedef struct sym { | 238 | typedef struct sym { | |
239 | const char *s_name; | 239 | const char *s_name; | |
240 | const char *s_rename; /* renamed symbol's given name */ | 240 | const char *s_rename; /* renamed symbol's given name */ | |
241 | pos_t s_def_pos; /* position of last (prototype) definition, | 241 | pos_t s_def_pos; /* position of last (prototype) definition, | |
242 | prototype declaration, no-prototype-def., | 242 | prototype declaration, no-prototype-def., | |
243 | tentative definition or declaration, | 243 | tentative definition or declaration, | |
244 | in this order */ | 244 | in this order */ | |
245 | pos_t s_set_pos; /* position of first initialization */ | 245 | pos_t s_set_pos; /* position of first initialization */ | |
246 | pos_t s_use_pos; /* position of first use */ | 246 | pos_t s_use_pos; /* position of first use */ | |
247 | symt_t s_kind; /* type of symbol */ | 247 | symt_t s_kind; /* type of symbol */ | |
248 | const struct keyword *s_keyword; | 248 | const struct keyword *s_keyword; | |
249 | bool s_bitfield:1; | 249 | bool s_bitfield:1; | |
250 | bool s_set:1; /* variable set, label defined */ | 250 | bool s_set:1; /* variable set, label defined */ | |
251 | bool s_used:1; /* variable/label used */ | 251 | bool s_used:1; /* variable/label used */ | |
252 | bool s_arg:1; /* symbol is function argument */ | 252 | bool s_arg:1; /* symbol is function argument */ | |
253 | bool s_reg:1; /* symbol is register variable */ | 253 | bool s_reg:1; /* symbol is register variable */ | |
254 | bool s_defarg:1; /* undefined symbol in old style function | 254 | bool s_defarg:1; /* undefined symbol in old style function | |
255 | definition */ | 255 | definition */ | |
256 | bool s_return_type_implicit_int:1; | 256 | bool s_return_type_implicit_int:1; | |
257 | bool s_osdef:1; /* symbol stems from old style function def. */ | 257 | bool s_osdef:1; /* symbol stems from old style function def. */ | |
258 | bool s_inline:1; /* true if this is an inline function */ | 258 | bool s_inline:1; /* true if this is an inline function */ | |
259 | struct sym *s_ext_sym; /* for local declared external symbols pointer | 259 | struct sym *s_ext_sym; /* for local declared external symbols pointer | |
260 | to external symbol with same name */ | 260 | to external symbol with same name */ | |
261 | def_t s_def; /* declared, tentative defined, defined */ | 261 | def_t s_def; /* declared, tentative defined, defined */ | |
262 | scl_t s_scl; /* storage class */ | 262 | scl_t s_scl; /* storage class */ | |
263 | int s_block_level; /* level of declaration, -1 if not in symbol | 263 | int s_block_level; /* level of declaration, -1 if not in symbol | |
264 | table */ | 264 | table */ | |
265 | type_t *s_type; | 265 | type_t *s_type; | |
266 | val_t s_value; /* value (if enum or bool constant) */ | 266 | val_t s_value; /* value (if enum or bool constant) */ | |
267 | union { | 267 | union { | |
268 | /* XXX: what is the difference to s_type->t_str? */ | 268 | /* XXX: what is the difference to s_type->t_str? */ | |
269 | struct_or_union *_s_st; | 269 | struct_or_union *_s_st; | |
270 | enumeration *_s_et; | 270 | enumeration *_s_et; | |
271 | tspec_t _s_tsp; /* type (only for keywords) */ | 271 | tspec_t _s_tsp; /* type (only for keywords) */ | |
272 | tqual_t _s_tqu; /* qualifier (only for keywords) */ | 272 | tqual_t _s_tqu; /* qualifier (only for keywords) */ | |
273 | struct sym *_s_args; /* arguments in old style function | 273 | struct sym *_s_args; /* arguments in old style function | |
274 | definitions */ | 274 | definitions */ | |
275 | } u; | 275 | } u; | |
276 | struct sym *s_link; /* next symbol with same hash value */ | 276 | struct sym *s_symtab_next; /* next symbol with same hash value */ | |
277 | struct sym **s_rlink; /* pointer to s_link of prev. symbol */ | 277 | struct sym **s_symtab_ref; /* pointer to s_symtab_next of the | |
278 | * previous symbol */ | |||
278 | struct sym *s_next; /* next struct/union member, enumerator, | 279 | struct sym *s_next; /* next struct/union member, enumerator, | |
279 | argument */ | 280 | argument */ | |
280 | struct sym *s_dlnxt; /* next symbol declared on same level */ | 281 | struct sym *s_level_next; /* next symbol declared on the same | |
282 | * level */ | |||
281 | } sym_t; | 283 | } sym_t; | |
282 | 284 | |||
283 | #define s_styp u._s_st | 285 | #define s_styp u._s_st | |
284 | #define s_etyp u._s_et | 286 | #define s_etyp u._s_et | |
285 | #define s_tspec u._s_tsp | 287 | #define s_tspec u._s_tsp | |
286 | #define s_tqual u._s_tqu | 288 | #define s_tqual u._s_tqu | |
287 | #define s_args u._s_args | 289 | #define s_args u._s_args | |
288 | 290 | |||
289 | /* | 291 | /* | |
290 | * Used to keep some information about symbols before they are entered | 292 | * Used to keep some information about symbols before they are entered | |
291 | * into the symbol table. | 293 | * into the symbol table. | |
292 | */ | 294 | */ | |
293 | typedef struct sbuf { | 295 | typedef struct sbuf { | |
294 | const char *sb_name; /* name of symbol */ | 296 | const char *sb_name; /* name of symbol */ | |
295 | size_t sb_len; /* length (without '\0') */ | 297 | size_t sb_len; /* length (without '\0') */ | |
296 | sym_t *sb_sym; /* symbol table entry */ | 298 | sym_t *sb_sym; /* symbol table entry */ | |
297 | } sbuf_t; | 299 | } sbuf_t; | |
298 | 300 | |||
299 | 301 | |||
300 | /* | 302 | /* | |
301 | * tree node | 303 | * tree node | |
302 | */ | 304 | */ | |
303 | typedef struct tnode { | 305 | typedef struct tnode { | |
304 | op_t tn_op; /* operator */ | 306 | op_t tn_op; /* operator */ | |
305 | type_t *tn_type; /* type */ | 307 | type_t *tn_type; /* type */ | |
306 | bool tn_lvalue:1; /* node is lvalue */ | 308 | bool tn_lvalue:1; /* node is lvalue */ | |
307 | bool tn_cast:1; /* if tn_op == CVT, it's an explicit cast */ | 309 | bool tn_cast:1; /* if tn_op == CVT, it's an explicit cast */ | |
308 | bool tn_parenthesized:1; | 310 | bool tn_parenthesized:1; | |
309 | bool tn_sys:1; /* in strict bool mode, allow mixture between | 311 | bool tn_sys:1; /* in strict bool mode, allow mixture between | |
310 | * bool and scalar, for code from system | 312 | * bool and scalar, for code from system | |
311 | * headers that may be a mixture between | 313 | * headers that may be a mixture between | |
312 | * scalar types and bool | 314 | * scalar types and bool | |
313 | */ | 315 | */ | |
314 | bool tn_system_dependent:1; /* depends on sizeof or offsetof */ | 316 | bool tn_system_dependent:1; /* depends on sizeof or offsetof */ | |
315 | union { | 317 | union { | |
316 | struct { | 318 | struct { | |
317 | struct tnode *_tn_left; /* (left) operand */ | 319 | struct tnode *_tn_left; /* (left) operand */ | |
318 | struct tnode *_tn_right; /* right operand */ | 320 | struct tnode *_tn_right; /* right operand */ | |
319 | } tn_s; | 321 | } tn_s; | |
320 | sym_t *_tn_sym; /* symbol if op == NAME */ | 322 | sym_t *_tn_sym; /* symbol if op == NAME */ | |
321 | val_t *_tn_val; /* value if op == CON */ | 323 | val_t *_tn_val; /* value if op == CON */ | |
322 | strg_t *_tn_string; /* string if op == STRING */ | 324 | strg_t *_tn_string; /* string if op == STRING */ | |
323 | } tn_u; | 325 | } tn_u; | |
324 | } tnode_t; | 326 | } tnode_t; | |
325 | 327 | |||
326 | #define tn_left tn_u.tn_s._tn_left | 328 | #define tn_left tn_u.tn_s._tn_left | |
327 | #define tn_right tn_u.tn_s._tn_right | 329 | #define tn_right tn_u.tn_s._tn_right | |
328 | #define tn_sym tn_u._tn_sym | 330 | #define tn_sym tn_u._tn_sym | |
329 | #define tn_val tn_u._tn_val | 331 | #define tn_val tn_u._tn_val | |
330 | #define tn_string tn_u._tn_string | 332 | #define tn_string tn_u._tn_string | |
331 | 333 | |||
332 | struct generic_association { | 334 | struct generic_association { | |
333 | type_t *ga_arg; /* NULL means default or error */ | 335 | type_t *ga_arg; /* NULL means default or error */ | |
334 | tnode_t *ga_result; /* NULL means error */ | 336 | tnode_t *ga_result; /* NULL means error */ | |
335 | struct generic_association *ga_prev; | 337 | struct generic_association *ga_prev; | |
336 | }; | 338 | }; | |
337 | 339 | |||
338 | struct array_size { | 340 | struct array_size { | |
339 | bool has_dim; | 341 | bool has_dim; | |
340 | int dim; | 342 | int dim; | |
341 | }; | 343 | }; | |
342 | 344 | |||
343 | /* | 345 | /* | |
344 | * For nested declarations there is a stack that holds all information | 346 | * For nested declarations there is a stack that holds all information | |
345 | * needed for the current level. dcs points to the innermost element of this | 347 | * needed for the current level. dcs points to the innermost element of this | |
346 | * stack. | 348 | * stack. | |
347 | * | 349 | * | |
348 | * d_ctx describes the context of the current declaration. Its value is | 350 | * d_ctx describes the context of the current declaration. Its value is | |
349 | * one of | 351 | * one of | |
350 | * EXTERN global declarations | 352 | * EXTERN global declarations | |
351 | * MOS or MOU declarations of struct or union members | 353 | * MOS or MOU declarations of struct or union members | |
352 | * CTCONST declarations of enums or boolean constants | 354 | * CTCONST declarations of enums or boolean constants | |
353 | * OLD_STYLE_ARG declaration of arguments in old-style function | 355 | * OLD_STYLE_ARG declaration of arguments in old-style function | |
354 | * definitions | 356 | * definitions | |
355 | * PROTO_ARG declaration of arguments in function prototypes | 357 | * PROTO_ARG declaration of arguments in function prototypes | |
356 | * AUTO declaration of local symbols | 358 | * AUTO declaration of local symbols | |
357 | * ABSTRACT abstract declarations (sizeof, casts) | 359 | * ABSTRACT abstract declarations (sizeof, casts) | |
358 | * | 360 | * | |
359 | */ | 361 | */ | |
360 | typedef struct dinfo { | 362 | typedef struct dinfo { | |
361 | tspec_t d_abstract_type;/* VOID, BOOL, CHAR, INT or COMPLEX */ | 363 | tspec_t d_abstract_type;/* VOID, BOOL, CHAR, INT or COMPLEX */ | |
362 | tspec_t d_complex_mod; /* FLOAT or DOUBLE */ | 364 | tspec_t d_complex_mod; /* FLOAT or DOUBLE */ | |
363 | tspec_t d_sign_mod; /* SIGNED or UNSIGN */ | 365 | tspec_t d_sign_mod; /* SIGNED or UNSIGN */ | |
364 | tspec_t d_rank_mod; /* SHORT, LONG or QUAD */ | 366 | tspec_t d_rank_mod; /* SHORT, LONG or QUAD */ | |
365 | scl_t d_scl; /* storage class */ | 367 | scl_t d_scl; /* storage class */ | |
366 | type_t *d_type; /* after end_type() pointer to the type used | 368 | type_t *d_type; /* after end_type() pointer to the type used | |
367 | for all declarators */ | 369 | for all declarators */ | |
368 | sym_t *d_redeclared_symbol; | 370 | sym_t *d_redeclared_symbol; | |
369 | unsigned int d_offset; /* offset of next structure member */ | 371 | unsigned int d_offset; /* offset of next structure member */ | |
370 | unsigned short d_sou_align_in_bits; /* alignment required for current | 372 | unsigned short d_sou_align_in_bits; /* alignment required for current | |
371 | * structure */ | 373 | * structure */ | |
372 | scl_t d_ctx; /* context of declaration */ | 374 | scl_t d_ctx; /* context of declaration */ | |
373 | bool d_const:1; /* const in declaration specifiers */ | 375 | bool d_const:1; /* const in declaration specifiers */ | |
374 | bool d_volatile:1; /* volatile in declaration specifiers */ | 376 | bool d_volatile:1; /* volatile in declaration specifiers */ | |
375 | bool d_inline:1; /* inline in declaration specifiers */ | 377 | bool d_inline:1; /* inline in declaration specifiers */ | |
376 | bool d_multiple_storage_classes:1; /* reported in end_type */ | 378 | bool d_multiple_storage_classes:1; /* reported in end_type */ | |
377 | bool d_invalid_type_combination:1; | 379 | bool d_invalid_type_combination:1; | |
378 | bool d_nonempty_decl:1; /* if at least one tag is declared | 380 | bool d_nonempty_decl:1; /* if at least one tag is declared | |
379 | * ... in the current function decl. */ | 381 | * ... in the current function decl. */ | |
380 | bool d_vararg:1; | 382 | bool d_vararg:1; | |
381 | bool d_proto:1; /* current function decl. is prototype */ | 383 | bool d_proto:1; /* current function decl. is prototype */ | |
382 | bool d_notyp:1; /* set if no type specifier was present */ | 384 | bool d_notyp:1; /* set if no type specifier was present */ | |
383 | bool d_asm:1; /* set if d_ctx == AUTO and asm() present */ | 385 | bool d_asm:1; /* set if d_ctx == AUTO and asm() present */ | |
384 | bool d_packed:1; | 386 | bool d_packed:1; | |
385 | bool d_used:1; | 387 | bool d_used:1; | |
386 | type_t *d_tagtyp; /* tag during member declaration */ | 388 | type_t *d_tagtyp; /* tag during member declaration */ | |
387 | sym_t *d_func_args; /* list of arguments during function def. */ | 389 | sym_t *d_func_args; /* list of arguments during function def. */ | |
388 | pos_t d_func_def_pos; /* position of function definition */ | 390 | pos_t d_func_def_pos; /* position of function definition */ | |
389 | sym_t *d_dlsyms; /* first symbol declared at this level */ | 391 | sym_t *d_dlsyms; /* first symbol declared at this level */ | |
390 | sym_t **d_ldlsym; /* points to s_dlnxt in last symbol decl. | 392 | sym_t **d_ldlsym; /* points to s_level_next in the last symbol | |
391 | at this level */ | 393 | declaration at this level */ | |
392 | sym_t *d_func_proto_syms; /* symbols defined in prototype */ | 394 | sym_t *d_func_proto_syms; /* symbols defined in prototype */ | |
393 | struct dinfo *d_next; /* next level */ | 395 | struct dinfo *d_next; /* next level */ | |
394 | } dinfo_t; | 396 | } dinfo_t; | |
395 | 397 | |||
396 | /* One level of pointer indirection in declarators, including qualifiers. */ | 398 | /* One level of pointer indirection in declarators, including qualifiers. */ | |
397 | typedef struct qual_ptr { | 399 | typedef struct qual_ptr { | |
398 | bool p_const: 1; | 400 | bool p_const: 1; | |
399 | bool p_volatile: 1; | 401 | bool p_volatile: 1; | |
400 | bool p_pointer: 1; | 402 | bool p_pointer: 1; | |
401 | struct qual_ptr *p_next; | 403 | struct qual_ptr *p_next; | |
402 | } qual_ptr; | 404 | } qual_ptr; | |
403 | 405 | |||
404 | /* | 406 | /* | |
405 | * The values of the 'case' labels, linked via cl_next in reverse order of | 407 | * The values of the 'case' labels, linked via cl_next in reverse order of | |
406 | * appearance in the code, that is from bottom to top. | 408 | * appearance in the code, that is from bottom to top. | |
407 | */ | 409 | */ | |
408 | typedef struct case_label { | 410 | typedef struct case_label { | |
409 | val_t cl_val; | 411 | val_t cl_val; | |
410 | struct case_label *cl_next; | 412 | struct case_label *cl_next; | |
411 | } case_label_t; | 413 | } case_label_t; | |
412 | 414 | |||
413 | typedef enum { | 415 | typedef enum { | |
414 | CS_DO_WHILE, | 416 | CS_DO_WHILE, | |
415 | CS_FOR, | 417 | CS_FOR, | |
416 | CS_FUNCTION_BODY, | 418 | CS_FUNCTION_BODY, | |
417 | CS_IF, | 419 | CS_IF, | |
418 | CS_SWITCH, | 420 | CS_SWITCH, | |
419 | CS_WHILE | 421 | CS_WHILE | |
420 | } control_statement_kind; | 422 | } control_statement_kind; | |
421 | 423 | |||
422 | /* | 424 | /* | |
423 | * Used to keep information about nested control statements. | 425 | * Used to keep information about nested control statements. | |
424 | */ | 426 | */ | |
425 | typedef struct control_statement { | 427 | typedef struct control_statement { | |
426 | control_statement_kind c_kind; /* to ensure proper nesting */ | 428 | control_statement_kind c_kind; /* to ensure proper nesting */ | |
427 | bool c_loop:1; /* 'continue' and 'break' are valid */ | 429 | bool c_loop:1; /* 'continue' and 'break' are valid */ | |
428 | bool c_switch:1; /* 'case' and 'break' are valid */ | 430 | bool c_switch:1; /* 'case' and 'break' are valid */ | |
429 | bool c_break:1; /* the loop/switch has a reachable | 431 | bool c_break:1; /* the loop/switch has a reachable | |
430 | * 'break' statement */ | 432 | * 'break' statement */ | |
431 | bool c_continue:1; /* the loop has a reachable 'continue' | 433 | bool c_continue:1; /* the loop has a reachable 'continue' | |
432 | * statement */ | 434 | * statement */ | |
433 | bool c_default:1; /* the switch has a 'default' label */ | 435 | bool c_default:1; /* the switch has a 'default' label */ | |
434 | bool c_maybe_endless:1; /* the controlling expression is | 436 | bool c_maybe_endless:1; /* the controlling expression is | |
435 | * always true (as in 'for (;;)' or | 437 | * always true (as in 'for (;;)' or | |
436 | * 'while (1)'), there may be break | 438 | * 'while (1)'), there may be break | |
437 | * statements though */ | 439 | * statements though */ | |
438 | bool c_always_then:1; | 440 | bool c_always_then:1; | |
439 | bool c_reached_end_of_then:1; | 441 | bool c_reached_end_of_then:1; | |
440 | bool c_had_return_noval:1; /* had "return;" */ | 442 | bool c_had_return_noval:1; /* had "return;" */ | |
441 | bool c_had_return_value:1; /* had "return expr;" */ | 443 | bool c_had_return_value:1; /* had "return expr;" */ | |
442 | 444 | |||
443 | type_t *c_switch_type; /* type of switch expression */ | 445 | type_t *c_switch_type; /* type of switch expression */ | |
444 | tnode_t *c_switch_expr; | 446 | tnode_t *c_switch_expr; | |
445 | case_label_t *c_case_labels; /* list of case values */ | 447 | case_label_t *c_case_labels; /* list of case values */ | |
446 | 448 | |||
447 | struct memory_block *c_for_expr3_mem; /* saved memory for end of loop | 449 | struct memory_block *c_for_expr3_mem; /* saved memory for end of loop | |
448 | * expression in for() */ | 450 | * expression in for() */ | |
449 | tnode_t *c_for_expr3; /* end of loop expr in for() */ | 451 | tnode_t *c_for_expr3; /* end of loop expr in for() */ | |
450 | pos_t c_for_expr3_pos; /* position of end of loop expr */ | 452 | pos_t c_for_expr3_pos; /* position of end of loop expr */ | |
451 | pos_t c_for_expr3_csrc_pos; /* same for csrc_pos */ | 453 | pos_t c_for_expr3_csrc_pos; /* same for csrc_pos */ | |
452 | 454 | |||
453 | struct control_statement *c_surrounding; | 455 | struct control_statement *c_surrounding; | |
454 | } control_statement; | 456 | } control_statement; | |
455 | 457 | |||
456 | typedef struct { | 458 | typedef struct { | |
457 | size_t lo; /* inclusive */ | 459 | size_t lo; /* inclusive */ | |
458 | size_t hi; /* inclusive */ | 460 | size_t hi; /* inclusive */ | |
459 | } range_t; | 461 | } range_t; | |
460 | 462 | |||
461 | #include "externs1.h" | 463 | #include "externs1.h" | |
462 | 464 | |||
463 | #define ERR_SETSIZE 1024 | 465 | #define ERR_SETSIZE 1024 | |
464 | #define __NERRBITS (sizeof(unsigned int)) | 466 | #define __NERRBITS (sizeof(unsigned int)) | |
465 | 467 | |||
466 | typedef struct err_set { | 468 | typedef struct err_set { | |
467 | unsigned int errs_bits[(ERR_SETSIZE + __NERRBITS-1) / __NERRBITS]; | 469 | unsigned int errs_bits[(ERR_SETSIZE + __NERRBITS-1) / __NERRBITS]; | |
468 | } err_set; | 470 | } err_set; | |
469 | 471 | |||
470 | #define ERR_SET(n, p) \ | 472 | #define ERR_SET(n, p) \ | |
471 | ((p)->errs_bits[(n)/__NERRBITS] |= (1 << ((n) % __NERRBITS))) | 473 | ((p)->errs_bits[(n)/__NERRBITS] |= (1 << ((n) % __NERRBITS))) | |
472 | #define ERR_CLR(n, p) \ | 474 | #define ERR_CLR(n, p) \ | |
473 | ((p)->errs_bits[(n)/__NERRBITS] &= ~(1 << ((n) % __NERRBITS))) | 475 | ((p)->errs_bits[(n)/__NERRBITS] &= ~(1 << ((n) % __NERRBITS))) | |
474 | #define ERR_ISSET(n, p) \ | 476 | #define ERR_ISSET(n, p) \ | |
475 | (((p)->errs_bits[(n)/__NERRBITS] & (1 << ((n) % __NERRBITS))) != 0) | 477 | (((p)->errs_bits[(n)/__NERRBITS] & (1 << ((n) % __NERRBITS))) != 0) | |
476 | #define ERR_ZERO(p) (void)memset((p), 0, sizeof(*(p))) | 478 | #define ERR_ZERO(p) (void)memset((p), 0, sizeof(*(p))) | |
477 | 479 | |||
478 | #define INTERNAL_ERROR(fmt, args...) \ | 480 | #define INTERNAL_ERROR(fmt, args...) \ | |
479 | internal_error(__FILE__, __LINE__, fmt, ##args) | 481 | internal_error(__FILE__, __LINE__, fmt, ##args) | |
480 | 482 | |||
481 | #define lint_assert(cond) \ | 483 | #define lint_assert(cond) \ | |
482 | do { \ | 484 | do { \ | |
483 | if (!(cond)) \ | 485 | if (!(cond)) \ | |
484 | assert_failed(__FILE__, __LINE__, __func__, #cond); \ | 486 | assert_failed(__FILE__, __LINE__, __func__, #cond); \ | |
485 | } while (false) | 487 | } while (false) | |
486 | 488 | |||
487 | extern err_set msgset; | 489 | extern err_set msgset; | |
488 | 490 | |||
489 | 491 | |||
490 | #ifdef DEBUG | 492 | #ifdef DEBUG | |
491 | # include "err-msgs.h" | 493 | # include "err-msgs.h" | |
492 | 494 | |||
493 | /* ARGSUSED */ | 495 | /* ARGSUSED */ | |
494 | static inline void __attribute__((format(printf, 1, 2))) | 496 | static inline void __attribute__((format(printf, 1, 2))) | |
495 | check_printf(const char *fmt, ...) | 497 | check_printf(const char *fmt, ...) | |
496 | { | 498 | { | |
497 | } | 499 | } | |
498 | 500 | |||
499 | # define wrap_check_printf_at(func, msgid, pos, args...) \ | 501 | # define wrap_check_printf_at(func, msgid, pos, args...) \ | |
500 | do { \ | 502 | do { \ | |
501 | check_printf(__CONCAT(MSG_, msgid), ##args); \ | 503 | check_printf(__CONCAT(MSG_, msgid), ##args); \ | |
502 | (func)(msgid, pos, ##args); \ | 504 | (func)(msgid, pos, ##args); \ | |
503 | } while (false) | 505 | } while (false) | |
504 | 506 | |||
505 | # define error_at(msgid, pos, args...) \ | 507 | # define error_at(msgid, pos, args...) \ | |
506 | wrap_check_printf_at(error_at, msgid, pos, ##args) | 508 | wrap_check_printf_at(error_at, msgid, pos, ##args) | |
507 | # define warning_at(msgid, pos, args...) \ | 509 | # define warning_at(msgid, pos, args...) \ | |
508 | wrap_check_printf_at(warning_at, msgid, pos, ##args) | 510 | wrap_check_printf_at(warning_at, msgid, pos, ##args) | |
509 | # define message_at(msgid, pos, args...) \ | 511 | # define message_at(msgid, pos, args...) \ | |
510 | wrap_check_printf_at(message_at, msgid, pos, ##args) | 512 | wrap_check_printf_at(message_at, msgid, pos, ##args) | |
511 | 513 | |||
512 | # define wrap_check_printf(func, msgid, args...) \ | 514 | # define wrap_check_printf(func, msgid, args...) \ | |
513 | do { \ | 515 | do { \ | |
514 | check_printf(__CONCAT(MSG_, msgid), ##args); \ | 516 | check_printf(__CONCAT(MSG_, msgid), ##args); \ | |
515 | (func)(msgid, ##args); \ | 517 | (func)(msgid, ##args); \ | |
516 | } while (false) | 518 | } while (false) | |
517 | 519 | |||
518 | # define error(msgid, args...) wrap_check_printf(error, msgid, ##args) | 520 | # define error(msgid, args...) wrap_check_printf(error, msgid, ##args) | |
519 | # define warning(msgid, args...) wrap_check_printf(warning, msgid, ##args) | 521 | # define warning(msgid, args...) wrap_check_printf(warning, msgid, ##args) | |
520 | # define gnuism(msgid, args...) wrap_check_printf(gnuism, msgid, ##args) | 522 | # define gnuism(msgid, args...) wrap_check_printf(gnuism, msgid, ##args) | |
521 | # define c99ism(msgid, args...) wrap_check_printf(c99ism, msgid, ##args) | 523 | # define c99ism(msgid, args...) wrap_check_printf(c99ism, msgid, ##args) | |
522 | # define c11ism(msgid, args...) wrap_check_printf(c11ism, msgid, ##args) | 524 | # define c11ism(msgid, args...) wrap_check_printf(c11ism, msgid, ##args) | |
523 | #endif | 525 | #endif | |
524 | 526 | |||
525 | static inline bool | 527 | static inline bool | |
526 | is_nonzero_val(const val_t *val) | 528 | is_nonzero_val(const val_t *val) | |
527 | { | 529 | { | |
528 | return is_floating(val->v_tspec) | 530 | return is_floating(val->v_tspec) | |
529 | ? val->v_ldbl != 0.0 | 531 | ? val->v_ldbl != 0.0 | |
530 | : val->v_quad != 0; | 532 | : val->v_quad != 0; | |
531 | } | 533 | } | |
532 | 534 | |||
533 | static inline bool | 535 | static inline bool | |
534 | constant_is_nonzero(const tnode_t *tn) | 536 | constant_is_nonzero(const tnode_t *tn) | |
535 | { | 537 | { | |
536 | lint_assert(tn->tn_op == CON); | 538 | lint_assert(tn->tn_op == CON); | |
537 | lint_assert(tn->tn_type->t_tspec == tn->tn_val->v_tspec); | 539 | lint_assert(tn->tn_type->t_tspec == tn->tn_val->v_tspec); | |
538 | return is_nonzero_val(tn->tn_val); | 540 | return is_nonzero_val(tn->tn_val); | |
539 | } | 541 | } | |
540 | 542 | |||
541 | static inline bool | 543 | static inline bool | |
542 | is_zero(const tnode_t *tn) | 544 | is_zero(const tnode_t *tn) | |
543 | { | 545 | { | |
544 | return tn != NULL && tn->tn_op == CON && !is_nonzero_val(tn->tn_val); | 546 | return tn != NULL && tn->tn_op == CON && !is_nonzero_val(tn->tn_val); | |
545 | } | 547 | } | |
546 | 548 | |||
547 | static inline bool | 549 | static inline bool | |
548 | is_nonzero(const tnode_t *tn) | 550 | is_nonzero(const tnode_t *tn) | |
549 | { | 551 | { | |
550 | return tn != NULL && tn->tn_op == CON && is_nonzero_val(tn->tn_val); | 552 | return tn != NULL && tn->tn_op == CON && is_nonzero_val(tn->tn_val); | |
551 | } | 553 | } | |
552 | 554 | |||
553 | static inline bool | 555 | static inline bool | |
554 | is_binary(const tnode_t *tn) | 556 | is_binary(const tnode_t *tn) | |
555 | { | 557 | { | |
556 | return modtab[tn->tn_op].m_binary; | 558 | return modtab[tn->tn_op].m_binary; | |
557 | } | 559 | } | |
558 | 560 | |||
559 | static inline uint64_t | 561 | static inline uint64_t | |
560 | bit(unsigned i) | 562 | bit(unsigned i) | |
561 | { | 563 | { | |
562 | /* | 564 | /* | |
563 | * TODO: Add proper support for INT128. | 565 | * TODO: Add proper support for INT128. | |
564 | * This involves changing val_t to 128 bits. | 566 | * This involves changing val_t to 128 bits. | |
565 | */ | 567 | */ | |
566 | if (i >= 64) | 568 | if (i >= 64) | |
567 | return 0; /* XXX: not correct for INT128 and UINT128 */ | 569 | return 0; /* XXX: not correct for INT128 and UINT128 */ | |
568 | 570 | |||
569 | lint_assert(i < 64); | 571 | lint_assert(i < 64); | |
570 | return (uint64_t)1 << i; | 572 | return (uint64_t)1 << i; | |
571 | } | 573 | } | |
572 | 574 | |||
573 | static inline bool | 575 | static inline bool | |
574 | msb(int64_t q, tspec_t t) | 576 | msb(int64_t q, tspec_t t) | |
575 | { | 577 | { | |
576 | return (q & bit((unsigned int)size_in_bits(t) - 1)) != 0; | 578 | return (q & bit((unsigned int)size_in_bits(t) - 1)) != 0; | |
577 | } | 579 | } | |
578 | 580 | |||
579 | static inline uint64_t | 581 | static inline uint64_t | |
580 | value_bits(unsigned bitsize) | 582 | value_bits(unsigned bitsize) | |
581 | { | 583 | { | |
582 | lint_assert(bitsize > 0); | 584 | lint_assert(bitsize > 0); | |
583 | 585 | |||
584 | /* for long double (80 or 128), double _Complex (128) */ | 586 | /* for long double (80 or 128), double _Complex (128) */ | |
585 | /* | 587 | /* | |
586 | * XXX: double _Complex does not have 128 bits of precision, | 588 | * XXX: double _Complex does not have 128 bits of precision, | |
587 | * therefore it should never be necessary to query the value bits | 589 | * therefore it should never be necessary to query the value bits | |
588 | * of such a type; see d_c99_complex_split.c to trigger this case. | 590 | * of such a type; see d_c99_complex_split.c to trigger this case. | |
589 | */ | 591 | */ | |
590 | if (bitsize >= 64) | 592 | if (bitsize >= 64) | |
591 | return ~((uint64_t)0); | 593 | return ~((uint64_t)0); | |
592 | 594 | |||
593 | return ~(~(uint64_t)0 << bitsize); | 595 | return ~(~(uint64_t)0 << bitsize); | |
594 | } | 596 | } | |
595 | 597 | |||
596 | /* C99 6.7.8p7 */ | 598 | /* C99 6.7.8p7 */ | |
597 | static inline bool | 599 | static inline bool | |
598 | is_struct_or_union(tspec_t t) | 600 | is_struct_or_union(tspec_t t) | |
599 | { | 601 | { | |
600 | return t == STRUCT || t == UNION; | 602 | return t == STRUCT || t == UNION; | |
601 | } | 603 | } |
--- src/usr.bin/xlint/lint1/tree.c 2022/02/27 10:31:58 1.406
+++ src/usr.bin/xlint/lint1/tree.c 2022/02/27 10:44:45 1.407
@@ -1,1402 +1,1403 @@ | @@ -1,1402 +1,1403 @@ | |||
1 | /* $NetBSD: tree.c,v 1.406 2022/02/27 10:31:58 rillig Exp $ */ | 1 | /* $NetBSD: tree.c,v 1.407 2022/02/27 10:44:45 rillig Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1994, 1995 Jochen Pohl | 4 | * Copyright (c) 1994, 1995 Jochen Pohl | |
5 | * All Rights Reserved. | 5 | * All Rights Reserved. | |
6 | * | 6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | 7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | 8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | 9 | * are met: | |
10 | * 1. Redistributions of source code must retain the above copyright | 10 | * 1. Redistributions of source code must retain the above copyright | |
11 | * notice, this list of conditions and the following disclaimer. | 11 | * notice, this list of conditions and the following disclaimer. | |
12 | * 2. Redistributions in binary form must reproduce the above copyright | 12 | * 2. Redistributions in binary form must reproduce the above copyright | |
13 | * notice, this list of conditions and the following disclaimer in the | 13 | * notice, this list of conditions and the following disclaimer in the | |
14 | * documentation and/or other materials provided with the distribution. | 14 | * documentation and/or other materials provided with the distribution. | |
15 | * 3. All advertising materials mentioning features or use of this software | 15 | * 3. All advertising materials mentioning features or use of this software | |
16 | * must display the following acknowledgement: | 16 | * must display the following acknowledgement: | |
17 | * This product includes software developed by Jochen Pohl for | 17 | * This product includes software developed by Jochen Pohl for | |
18 | * The NetBSD Project. | 18 | * The NetBSD Project. | |
19 | * 4. The name of the author may not be used to endorse or promote products | 19 | * 4. The name of the author may not be used to endorse or promote products | |
20 | * derived from this software without specific prior written permission. | 20 | * derived from this software without specific prior written permission. | |
21 | * | 21 | * | |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | |
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | |
25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | 25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | |
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | 32 | */ | |
33 | 33 | |||
34 | #if HAVE_NBTOOL_CONFIG_H | 34 | #if HAVE_NBTOOL_CONFIG_H | |
35 | #include "nbtool_config.h" | 35 | #include "nbtool_config.h" | |
36 | #endif | 36 | #endif | |
37 | 37 | |||
38 | #include <sys/cdefs.h> | 38 | #include <sys/cdefs.h> | |
39 | #if defined(__RCSID) && !defined(lint) | 39 | #if defined(__RCSID) && !defined(lint) | |
40 | __RCSID("$NetBSD: tree.c,v 1.406 2022/02/27 10:31:58 rillig Exp $"); | 40 | __RCSID("$NetBSD: tree.c,v 1.407 2022/02/27 10:44:45 rillig Exp $"); | |
41 | #endif | 41 | #endif | |
42 | 42 | |||
43 | #include <float.h> | 43 | #include <float.h> | |
44 | #include <limits.h> | 44 | #include <limits.h> | |
45 | #include <math.h> | 45 | #include <math.h> | |
46 | #include <signal.h> | 46 | #include <signal.h> | |
47 | #include <stdlib.h> | 47 | #include <stdlib.h> | |
48 | #include <string.h> | 48 | #include <string.h> | |
49 | 49 | |||
50 | #include "lint1.h" | 50 | #include "lint1.h" | |
51 | #include "cgram.h" | 51 | #include "cgram.h" | |
52 | 52 | |||
53 | static tnode_t *build_integer_constant(tspec_t, int64_t); | 53 | static tnode_t *build_integer_constant(tspec_t, int64_t); | |
54 | static void check_pointer_comparison(op_t, | 54 | static void check_pointer_comparison(op_t, | |
55 | const tnode_t *, const tnode_t *); | 55 | const tnode_t *, const tnode_t *); | |
56 | static bool check_assign_types_compatible(op_t, int, | 56 | static bool check_assign_types_compatible(op_t, int, | |
57 | const tnode_t *, const tnode_t *); | 57 | const tnode_t *, const tnode_t *); | |
58 | static void check_bad_enum_operation(op_t, | 58 | static void check_bad_enum_operation(op_t, | |
59 | const tnode_t *, const tnode_t *); | 59 | const tnode_t *, const tnode_t *); | |
60 | static void check_enum_type_mismatch(op_t, int, | 60 | static void check_enum_type_mismatch(op_t, int, | |
61 | const tnode_t *, const tnode_t *); | 61 | const tnode_t *, const tnode_t *); | |
62 | static void check_enum_int_mismatch(op_t, int, | 62 | static void check_enum_int_mismatch(op_t, int, | |
63 | const tnode_t *, const tnode_t *); | 63 | const tnode_t *, const tnode_t *); | |
64 | static tnode_t *new_tnode(op_t, bool, type_t *, tnode_t *, tnode_t *); | 64 | static tnode_t *new_tnode(op_t, bool, type_t *, tnode_t *, tnode_t *); | |
65 | static void balance(op_t, tnode_t **, tnode_t **); | 65 | static void balance(op_t, tnode_t **, tnode_t **); | |
66 | static void warn_incompatible_types(op_t, const type_t *, tspec_t, | 66 | static void warn_incompatible_types(op_t, const type_t *, tspec_t, | |
67 | const type_t *, tspec_t); | 67 | const type_t *, tspec_t); | |
68 | static void warn_incompatible_pointers(const mod_t *, | 68 | static void warn_incompatible_pointers(const mod_t *, | |
69 | const type_t *, const type_t *); | 69 | const type_t *, const type_t *); | |
70 | static bool has_constant_member(const type_t *); | 70 | static bool has_constant_member(const type_t *); | |
71 | static void check_prototype_conversion(int, tspec_t, tspec_t, type_t *, | 71 | static void check_prototype_conversion(int, tspec_t, tspec_t, type_t *, | |
72 | tnode_t *); | 72 | tnode_t *); | |
73 | static void check_integer_conversion(op_t, int, tspec_t, tspec_t, type_t *, | 73 | static void check_integer_conversion(op_t, int, tspec_t, tspec_t, type_t *, | |
74 | tnode_t *); | 74 | tnode_t *); | |
75 | static void check_pointer_integer_conversion(op_t, tspec_t, type_t *, | 75 | static void check_pointer_integer_conversion(op_t, tspec_t, type_t *, | |
76 | tnode_t *); | 76 | tnode_t *); | |
77 | static void check_pointer_conversion(tnode_t *, type_t *); | 77 | static void check_pointer_conversion(tnode_t *, type_t *); | |
78 | static tnode_t *build_struct_access(op_t, bool, tnode_t *, tnode_t *); | 78 | static tnode_t *build_struct_access(op_t, bool, tnode_t *, tnode_t *); | |
79 | static tnode_t *build_prepost_incdec(op_t, bool, tnode_t *); | 79 | static tnode_t *build_prepost_incdec(op_t, bool, tnode_t *); | |
80 | static tnode_t *build_real_imag(op_t, bool, tnode_t *); | 80 | static tnode_t *build_real_imag(op_t, bool, tnode_t *); | |
81 | static tnode_t *build_address(bool, tnode_t *, bool); | 81 | static tnode_t *build_address(bool, tnode_t *, bool); | |
82 | static tnode_t *build_plus_minus(op_t, bool, tnode_t *, tnode_t *); | 82 | static tnode_t *build_plus_minus(op_t, bool, tnode_t *, tnode_t *); | |
83 | static tnode_t *build_bit_shift(op_t, bool, tnode_t *, tnode_t *); | 83 | static tnode_t *build_bit_shift(op_t, bool, tnode_t *, tnode_t *); | |
84 | static tnode_t *build_colon(bool, tnode_t *, tnode_t *); | 84 | static tnode_t *build_colon(bool, tnode_t *, tnode_t *); | |
85 | static tnode_t *build_assignment(op_t, bool, tnode_t *, tnode_t *); | 85 | static tnode_t *build_assignment(op_t, bool, tnode_t *, tnode_t *); | |
86 | static tnode_t *plength(type_t *); | 86 | static tnode_t *plength(type_t *); | |
87 | static tnode_t *fold(tnode_t *); | 87 | static tnode_t *fold(tnode_t *); | |
88 | static tnode_t *fold_test(tnode_t *); | 88 | static tnode_t *fold_test(tnode_t *); | |
89 | static tnode_t *fold_float(tnode_t *); | 89 | static tnode_t *fold_float(tnode_t *); | |
90 | static tnode_t *check_function_arguments(type_t *, tnode_t *); | 90 | static tnode_t *check_function_arguments(type_t *, tnode_t *); | |
91 | static tnode_t *check_prototype_argument(int, type_t *, tnode_t *); | 91 | static tnode_t *check_prototype_argument(int, type_t *, tnode_t *); | |
92 | static void check_null_effect(const tnode_t *); | 92 | static void check_null_effect(const tnode_t *); | |
93 | static void check_array_index(tnode_t *, bool); | 93 | static void check_array_index(tnode_t *, bool); | |
94 | static void check_integer_comparison(op_t, tnode_t *, tnode_t *); | 94 | static void check_integer_comparison(op_t, tnode_t *, tnode_t *); | |
95 | static void check_precedence_confusion(tnode_t *); | 95 | static void check_precedence_confusion(tnode_t *); | |
96 | 96 | |||
97 | extern sig_atomic_t fpe; | 97 | extern sig_atomic_t fpe; | |
98 | 98 | |||
99 | static const char * | 99 | static const char * | |
100 | op_name(op_t op) | 100 | op_name(op_t op) | |
101 | { | 101 | { | |
102 | return modtab[op].m_name; | 102 | return modtab[op].m_name; | |
103 | } | 103 | } | |
104 | 104 | |||
105 | /* Build 'pointer to tp', 'array of tp' or 'function returning tp'. */ | 105 | /* Build 'pointer to tp', 'array of tp' or 'function returning tp'. */ | |
106 | type_t * | 106 | type_t * | |
107 | block_derive_type(type_t *tp, tspec_t t) | 107 | block_derive_type(type_t *tp, tspec_t t) | |
108 | { | 108 | { | |
109 | type_t *tp2; | 109 | type_t *tp2; | |
110 | 110 | |||
111 | tp2 = block_zero_alloc(sizeof(*tp2)); | 111 | tp2 = block_zero_alloc(sizeof(*tp2)); | |
112 | tp2->t_tspec = t; | 112 | tp2->t_tspec = t; | |
113 | tp2->t_subt = tp; | 113 | tp2->t_subt = tp; | |
114 | return tp2; | 114 | return tp2; | |
115 | } | 115 | } | |
116 | 116 | |||
117 | /* | 117 | /* | |
118 | * Derive 'pointer to tp' or 'function returning tp'. | 118 | * Derive 'pointer to tp' or 'function returning tp'. | |
119 | * The memory is freed at the end of the current expression. | 119 | * The memory is freed at the end of the current expression. | |
120 | */ | 120 | */ | |
121 | type_t * | 121 | type_t * | |
122 | expr_derive_type(type_t *tp, tspec_t t) | 122 | expr_derive_type(type_t *tp, tspec_t t) | |
123 | { | 123 | { | |
124 | type_t *tp2; | 124 | type_t *tp2; | |
125 | 125 | |||
126 | tp2 = expr_zero_alloc(sizeof(*tp2)); | 126 | tp2 = expr_zero_alloc(sizeof(*tp2)); | |
127 | tp2->t_tspec = t; | 127 | tp2->t_tspec = t; | |
128 | tp2->t_subt = tp; | 128 | tp2->t_subt = tp; | |
129 | return tp2; | 129 | return tp2; | |
130 | } | 130 | } | |
131 | 131 | |||
132 | /* | 132 | /* | |
133 | * Create a node for a constant. | 133 | * Create a node for a constant. | |
134 | */ | 134 | */ | |
135 | tnode_t * | 135 | tnode_t * | |
136 | build_constant(type_t *tp, val_t *v) | 136 | build_constant(type_t *tp, val_t *v) | |
137 | { | 137 | { | |
138 | tnode_t *n; | 138 | tnode_t *n; | |
139 | 139 | |||
140 | n = expr_alloc_tnode(); | 140 | n = expr_alloc_tnode(); | |
141 | n->tn_op = CON; | 141 | n->tn_op = CON; | |
142 | n->tn_type = tp; | 142 | n->tn_type = tp; | |
143 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); | 143 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); | |
144 | n->tn_val->v_tspec = tp->t_tspec; | 144 | n->tn_val->v_tspec = tp->t_tspec; | |
145 | n->tn_val->v_unsigned_since_c90 = v->v_unsigned_since_c90; | 145 | n->tn_val->v_unsigned_since_c90 = v->v_unsigned_since_c90; | |
146 | n->tn_val->v_u = v->v_u; | 146 | n->tn_val->v_u = v->v_u; | |
147 | free(v); | 147 | free(v); | |
148 | return n; | 148 | return n; | |
149 | } | 149 | } | |
150 | 150 | |||
151 | static tnode_t * | 151 | static tnode_t * | |
152 | build_integer_constant(tspec_t t, int64_t q) | 152 | build_integer_constant(tspec_t t, int64_t q) | |
153 | { | 153 | { | |
154 | tnode_t *n; | 154 | tnode_t *n; | |
155 | 155 | |||
156 | n = expr_alloc_tnode(); | 156 | n = expr_alloc_tnode(); | |
157 | n->tn_op = CON; | 157 | n->tn_op = CON; | |
158 | n->tn_type = gettyp(t); | 158 | n->tn_type = gettyp(t); | |
159 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); | 159 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); | |
160 | n->tn_val->v_tspec = t; | 160 | n->tn_val->v_tspec = t; | |
161 | n->tn_val->v_quad = q; | 161 | n->tn_val->v_quad = q; | |
162 | return n; | 162 | return n; | |
163 | } | 163 | } | |
164 | 164 | |||
165 | static void | 165 | static void | |
166 | fallback_symbol(sym_t *sym) | 166 | fallback_symbol(sym_t *sym) | |
167 | { | 167 | { | |
168 | 168 | |||
169 | if (fallback_symbol_strict_bool(sym)) | 169 | if (fallback_symbol_strict_bool(sym)) | |
170 | return; | 170 | return; | |
171 | 171 | |||
172 | if (block_level > 0 && (strcmp(sym->s_name, "__FUNCTION__") == 0 || | 172 | if (block_level > 0 && (strcmp(sym->s_name, "__FUNCTION__") == 0 || | |
173 | strcmp(sym->s_name, "__PRETTY_FUNCTION__") == 0)) { | 173 | strcmp(sym->s_name, "__PRETTY_FUNCTION__") == 0)) { | |
174 | /* __FUNCTION__/__PRETTY_FUNCTION__ is a GCC extension */ | 174 | /* __FUNCTION__/__PRETTY_FUNCTION__ is a GCC extension */ | |
175 | gnuism(316); | 175 | gnuism(316); | |
176 | sym->s_type = block_derive_type(gettyp(CHAR), PTR); | 176 | sym->s_type = block_derive_type(gettyp(CHAR), PTR); | |
177 | sym->s_type->t_const = true; | 177 | sym->s_type->t_const = true; | |
178 | return; | 178 | return; | |
179 | } | 179 | } | |
180 | 180 | |||
181 | if (block_level > 0 && strcmp(sym->s_name, "__func__") == 0) { | 181 | if (block_level > 0 && strcmp(sym->s_name, "__func__") == 0) { | |
182 | if (!Sflag) | 182 | if (!Sflag) | |
183 | /* __func__ is a C9X feature */ | 183 | /* __func__ is a C9X feature */ | |
184 | warning(317); | 184 | warning(317); | |
185 | sym->s_type = block_derive_type(gettyp(CHAR), PTR); | 185 | sym->s_type = block_derive_type(gettyp(CHAR), PTR); | |
186 | sym->s_type->t_const = true; | 186 | sym->s_type->t_const = true; | |
187 | return; | 187 | return; | |
188 | } | 188 | } | |
189 | 189 | |||
190 | /* '%s' undefined */ | 190 | /* '%s' undefined */ | |
191 | error(99, sym->s_name); | 191 | error(99, sym->s_name); | |
192 | } | 192 | } | |
193 | 193 | |||
194 | /* | 194 | /* | |
195 | * Functions that are predeclared by GCC or other compilers can be called | 195 | * Functions that are predeclared by GCC or other compilers can be called | |
196 | * with arbitrary arguments. Since lint usually runs after a successful | 196 | * with arbitrary arguments. Since lint usually runs after a successful | |
197 | * compilation, it's the compiler's job to catch any errors. | 197 | * compilation, it's the compiler's job to catch any errors. | |
198 | */ | 198 | */ | |
199 | bool | 199 | bool | |
200 | is_compiler_builtin(const char *name) | 200 | is_compiler_builtin(const char *name) | |
201 | { | 201 | { | |
202 | /* https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html */ | 202 | /* https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html */ | |
203 | if (gflag) { | 203 | if (gflag) { | |
204 | if (strncmp(name, "__atomic_", 9) == 0 || | 204 | if (strncmp(name, "__atomic_", 9) == 0 || | |
205 | strncmp(name, "__builtin_", 10) == 0 || | 205 | strncmp(name, "__builtin_", 10) == 0 || | |
206 | strcmp(name, "alloca") == 0 || | 206 | strcmp(name, "alloca") == 0 || | |
207 | /* obsolete but still in use, as of 2021 */ | 207 | /* obsolete but still in use, as of 2021 */ | |
208 | strncmp(name, "__sync_", 7) == 0) | 208 | strncmp(name, "__sync_", 7) == 0) | |
209 | return true; | 209 | return true; | |
210 | } | 210 | } | |
211 | 211 | |||
212 | /* https://software.intel.com/sites/landingpage/IntrinsicsGuide/ */ | 212 | /* https://software.intel.com/sites/landingpage/IntrinsicsGuide/ */ | |
213 | if (strncmp(name, "_mm_", 4) == 0) | 213 | if (strncmp(name, "_mm_", 4) == 0) | |
214 | return true; | 214 | return true; | |
215 | 215 | |||
216 | return false; | 216 | return false; | |
217 | } | 217 | } | |
218 | 218 | |||
219 | static bool | 219 | static bool | |
220 | str_endswith(const char *haystack, const char *needle) | 220 | str_endswith(const char *haystack, const char *needle) | |
221 | { | 221 | { | |
222 | size_t hlen = strlen(haystack); | 222 | size_t hlen = strlen(haystack); | |
223 | size_t nlen = strlen(needle); | 223 | size_t nlen = strlen(needle); | |
224 | 224 | |||
225 | return nlen <= hlen && | 225 | return nlen <= hlen && | |
226 | memcmp(haystack + hlen - nlen, needle, nlen) == 0; | 226 | memcmp(haystack + hlen - nlen, needle, nlen) == 0; | |
227 | } | 227 | } | |
228 | 228 | |||
229 | /* https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html */ | 229 | /* https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html */ | |
230 | static bool | 230 | static bool | |
231 | is_gcc_bool_builtin(const char *name) | 231 | is_gcc_bool_builtin(const char *name) | |
232 | { | 232 | { | |
233 | return strncmp(name, "__builtin_", 10) == 0 && | 233 | return strncmp(name, "__builtin_", 10) == 0 && | |
234 | (str_endswith(name, "_overflow") || | 234 | (str_endswith(name, "_overflow") || | |
235 | str_endswith(name, "_overflow_p")); | 235 | str_endswith(name, "_overflow_p")); | |
236 | } | 236 | } | |
237 | 237 | |||
238 | static void | 238 | static void | |
239 | build_name_call(sym_t *sym) | 239 | build_name_call(sym_t *sym) | |
240 | { | 240 | { | |
241 | 241 | |||
242 | if (is_compiler_builtin(sym->s_name)) { | 242 | if (is_compiler_builtin(sym->s_name)) { | |
243 | /* | 243 | /* | |
244 | * Do not warn about these, just assume that | 244 | * Do not warn about these, just assume that | |
245 | * they are regular functions compatible with | 245 | * they are regular functions compatible with | |
246 | * non-prototype calling conventions. | 246 | * non-prototype calling conventions. | |
247 | */ | 247 | */ | |
248 | if (gflag && is_gcc_bool_builtin(sym->s_name)) | 248 | if (gflag && is_gcc_bool_builtin(sym->s_name)) | |
249 | sym->s_type = gettyp(BOOL); | 249 | sym->s_type = gettyp(BOOL); | |
250 | 250 | |||
251 | } else if (Sflag) { | 251 | } else if (Sflag) { | |
252 | /* function '%s' implicitly declared to return int */ | 252 | /* function '%s' implicitly declared to return int */ | |
253 | error(215, sym->s_name); | 253 | error(215, sym->s_name); | |
254 | } else if (sflag) { | 254 | } else if (sflag) { | |
255 | /* function '%s' implicitly declared to return int */ | 255 | /* function '%s' implicitly declared to return int */ | |
256 | warning(215, sym->s_name); | 256 | warning(215, sym->s_name); | |
257 | } | 257 | } | |
258 | 258 | |||
259 | /* XXX if tflag is set, the symbol should be exported to level 0 */ | 259 | /* XXX if tflag is set, the symbol should be exported to level 0 */ | |
260 | sym->s_type = block_derive_type(sym->s_type, FUNC); | 260 | sym->s_type = block_derive_type(sym->s_type, FUNC); | |
261 | } | 261 | } | |
262 | 262 | |||
263 | /* Create a node for a name (symbol table entry). */ | 263 | /* Create a node for a name (symbol table entry). */ | |
264 | tnode_t * | 264 | tnode_t * | |
265 | build_name(sym_t *sym, bool is_funcname) | 265 | build_name(sym_t *sym, bool is_funcname) | |
266 | { | 266 | { | |
267 | tnode_t *n; | 267 | tnode_t *n; | |
268 | 268 | |||
269 | if (sym->s_scl == NOSCL) { | 269 | if (sym->s_scl == NOSCL) { | |
270 | sym->s_scl = EXTERN; | 270 | sym->s_scl = EXTERN; | |
271 | sym->s_def = DECL; | 271 | sym->s_def = DECL; | |
272 | if (is_funcname) | 272 | if (is_funcname) | |
273 | build_name_call(sym); | 273 | build_name_call(sym); | |
274 | else | 274 | else | |
275 | fallback_symbol(sym); | 275 | fallback_symbol(sym); | |
276 | } | 276 | } | |
277 | 277 | |||
278 | lint_assert(sym->s_kind == FVFT || sym->s_kind == FMEMBER); | 278 | lint_assert(sym->s_kind == FVFT || sym->s_kind == FMEMBER); | |
279 | 279 | |||
280 | n = expr_alloc_tnode(); | 280 | n = expr_alloc_tnode(); | |
281 | n->tn_type = sym->s_type; | 281 | n->tn_type = sym->s_type; | |
282 | if (sym->s_scl == CTCONST) { | 282 | if (sym->s_scl == CTCONST) { | |
283 | n->tn_op = CON; | 283 | n->tn_op = CON; | |
284 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); | 284 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); | |
285 | *n->tn_val = sym->s_value; | 285 | *n->tn_val = sym->s_value; | |
286 | } else { | 286 | } else { | |
287 | n->tn_op = NAME; | 287 | n->tn_op = NAME; | |
288 | n->tn_sym = sym; | 288 | n->tn_sym = sym; | |
289 | if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC) | 289 | if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC) | |
290 | n->tn_lvalue = true; | 290 | n->tn_lvalue = true; | |
291 | } | 291 | } | |
292 | 292 | |||
293 | return n; | 293 | return n; | |
294 | } | 294 | } | |
295 | 295 | |||
296 | tnode_t * | 296 | tnode_t * | |
297 | build_string(strg_t *strg) | 297 | build_string(strg_t *strg) | |
298 | { | 298 | { | |
299 | size_t len; | 299 | size_t len; | |
300 | tnode_t *n; | 300 | tnode_t *n; | |
301 | type_t *tp; | 301 | type_t *tp; | |
302 | 302 | |||
303 | len = strg->st_len; | 303 | len = strg->st_len; | |
304 | 304 | |||
305 | n = expr_alloc_tnode(); | 305 | n = expr_alloc_tnode(); | |
306 | 306 | |||
307 | tp = expr_zero_alloc(sizeof(*tp)); | 307 | tp = expr_zero_alloc(sizeof(*tp)); | |
308 | tp->t_tspec = ARRAY; | 308 | tp->t_tspec = ARRAY; | |
309 | tp->t_subt = gettyp(strg->st_tspec); | 309 | tp->t_subt = gettyp(strg->st_tspec); | |
310 | tp->t_dim = (int)(len + 1); | 310 | tp->t_dim = (int)(len + 1); | |
311 | 311 | |||
312 | n->tn_op = STRING; | 312 | n->tn_op = STRING; | |
313 | n->tn_type = tp; | 313 | n->tn_type = tp; | |
314 | n->tn_lvalue = true; | 314 | n->tn_lvalue = true; | |
315 | 315 | |||
316 | n->tn_string = expr_zero_alloc(sizeof(*n->tn_string)); | 316 | n->tn_string = expr_zero_alloc(sizeof(*n->tn_string)); | |
317 | n->tn_string->st_tspec = strg->st_tspec; | 317 | n->tn_string->st_tspec = strg->st_tspec; | |
318 | n->tn_string->st_len = len; | 318 | n->tn_string->st_len = len; | |
319 | 319 | |||
320 | if (strg->st_tspec == CHAR) { | 320 | if (strg->st_tspec == CHAR) { | |
321 | n->tn_string->st_cp = expr_zero_alloc(len + 1); | 321 | n->tn_string->st_cp = expr_zero_alloc(len + 1); | |
322 | (void)memcpy(n->tn_string->st_cp, strg->st_cp, len + 1); | 322 | (void)memcpy(n->tn_string->st_cp, strg->st_cp, len + 1); | |
323 | free(strg->st_cp); | 323 | free(strg->st_cp); | |
324 | } else { | 324 | } else { | |
325 | size_t size = (len + 1) * sizeof(*n->tn_string->st_wcp); | 325 | size_t size = (len + 1) * sizeof(*n->tn_string->st_wcp); | |
326 | n->tn_string->st_wcp = expr_zero_alloc(size); | 326 | n->tn_string->st_wcp = expr_zero_alloc(size); | |
327 | (void)memcpy(n->tn_string->st_wcp, strg->st_wcp, size); | 327 | (void)memcpy(n->tn_string->st_wcp, strg->st_wcp, size); | |
328 | free(strg->st_wcp); | 328 | free(strg->st_wcp); | |
329 | } | 329 | } | |
330 | free(strg); | 330 | free(strg); | |
331 | 331 | |||
332 | return n; | 332 | return n; | |
333 | } | 333 | } | |
334 | 334 | |||
335 | /* | 335 | /* | |
336 | * Returns a symbol which has the same name as the msym argument and is a | 336 | * Returns a symbol which has the same name as the msym argument and is a | |
337 | * member of the struct or union specified by the tn argument. | 337 | * member of the struct or union specified by the tn argument. | |
338 | */ | 338 | */ | |
339 | static sym_t * | 339 | static sym_t * | |
340 | struct_or_union_member(tnode_t *tn, op_t op, sym_t *msym) | 340 | struct_or_union_member(tnode_t *tn, op_t op, sym_t *msym) | |
341 | { | 341 | { | |
342 | struct_or_union *str; | 342 | struct_or_union *str; | |
343 | type_t *tp; | 343 | type_t *tp; | |
344 | sym_t *sym, *csym; | 344 | sym_t *sym, *csym; | |
345 | bool eq; | 345 | bool eq; | |
346 | tspec_t t; | 346 | tspec_t t; | |
347 | 347 | |||
348 | /* | 348 | /* | |
349 | * Remove the member if it was unknown until now, which means | 349 | * Remove the member if it was unknown until now, which means | |
350 | * that no defined struct or union has a member with the same name. | 350 | * that no defined struct or union has a member with the same name. | |
351 | */ | 351 | */ | |
352 | if (msym->s_scl == NOSCL) { | 352 | if (msym->s_scl == NOSCL) { | |
353 | /* type '%s' does not have member '%s' */ | 353 | /* type '%s' does not have member '%s' */ | |
354 | error(101, type_name(tn->tn_type), msym->s_name); | 354 | error(101, type_name(tn->tn_type), msym->s_name); | |
355 | rmsym(msym); | 355 | rmsym(msym); | |
356 | msym->s_kind = FMEMBER; | 356 | msym->s_kind = FMEMBER; | |
357 | msym->s_scl = MOS; | 357 | msym->s_scl = MOS; | |
358 | msym->s_styp = expr_zero_alloc(sizeof(*msym->s_styp)); | 358 | msym->s_styp = expr_zero_alloc(sizeof(*msym->s_styp)); | |
359 | msym->s_styp->sou_tag = expr_zero_alloc( | 359 | msym->s_styp->sou_tag = expr_zero_alloc( | |
360 | sizeof(*msym->s_styp->sou_tag)); | 360 | sizeof(*msym->s_styp->sou_tag)); | |
361 | msym->s_styp->sou_tag->s_name = unnamed; | 361 | msym->s_styp->sou_tag->s_name = unnamed; | |
362 | msym->s_value.v_tspec = INT; | 362 | msym->s_value.v_tspec = INT; | |
363 | return msym; | 363 | return msym; | |
364 | } | 364 | } | |
365 | 365 | |||
366 | /* Set str to the tag of which msym is expected to be a member. */ | 366 | /* Set str to the tag of which msym is expected to be a member. */ | |
367 | str = NULL; | 367 | str = NULL; | |
368 | t = (tp = tn->tn_type)->t_tspec; | 368 | t = (tp = tn->tn_type)->t_tspec; | |
369 | if (op == POINT) { | 369 | if (op == POINT) { | |
370 | if (t == STRUCT || t == UNION) | 370 | if (t == STRUCT || t == UNION) | |
371 | str = tp->t_str; | 371 | str = tp->t_str; | |
372 | } else if (op == ARROW && t == PTR) { | 372 | } else if (op == ARROW && t == PTR) { | |
373 | t = (tp = tp->t_subt)->t_tspec; | 373 | t = (tp = tp->t_subt)->t_tspec; | |
374 | if (t == STRUCT || t == UNION) | 374 | if (t == STRUCT || t == UNION) | |
375 | str = tp->t_str; | 375 | str = tp->t_str; | |
376 | } | 376 | } | |
377 | 377 | |||
378 | /* | 378 | /* | |
379 | * If this struct/union has a member with the name of msym, return it. | 379 | * If this struct/union has a member with the name of msym, return it. | |
380 | */ | 380 | */ | |
381 | if (str != NULL) { | 381 | if (str != NULL) { | |
382 | for (sym = msym; sym != NULL; sym = sym->s_link) { | 382 | for (sym = msym; sym != NULL; sym = sym->s_symtab_next) { | |
383 | if (sym->s_scl != MOS && sym->s_scl != MOU) | 383 | if (sym->s_scl != MOS && sym->s_scl != MOU) | |
384 | continue; | 384 | continue; | |
385 | if (sym->s_styp != str) | 385 | if (sym->s_styp != str) | |
386 | continue; | 386 | continue; | |
387 | if (strcmp(sym->s_name, msym->s_name) != 0) | 387 | if (strcmp(sym->s_name, msym->s_name) != 0) | |
388 | continue; | 388 | continue; | |
389 | return sym; | 389 | return sym; | |
390 | } | 390 | } | |
391 | } | 391 | } | |
392 | 392 | |||
393 | /* | 393 | /* | |
394 | * Set eq to false if there are struct/union members with the same | 394 | * Set eq to false if there are struct/union members with the same | |
395 | * name and different types and/or offsets. | 395 | * name and different types and/or offsets. | |
396 | */ | 396 | */ | |
397 | eq = true; | 397 | eq = true; | |
398 | for (csym = msym; csym != NULL; csym = csym->s_link) { | 398 | for (csym = msym; csym != NULL; csym = csym->s_symtab_next) { | |
399 | if (csym->s_scl != MOS && csym->s_scl != MOU) | 399 | if (csym->s_scl != MOS && csym->s_scl != MOU) | |
400 | continue; | 400 | continue; | |
401 | if (strcmp(msym->s_name, csym->s_name) != 0) | 401 | if (strcmp(msym->s_name, csym->s_name) != 0) | |
402 | continue; | 402 | continue; | |
403 | for (sym = csym->s_link; sym != NULL; sym = sym->s_link) { | 403 | for (sym = csym->s_symtab_next; sym != NULL; | |
404 | sym = sym->s_symtab_next) { | |||
404 | bool w; | 405 | bool w; | |
405 | 406 | |||
406 | if (sym->s_scl != MOS && sym->s_scl != MOU) | 407 | if (sym->s_scl != MOS && sym->s_scl != MOU) | |
407 | continue; | 408 | continue; | |
408 | if (strcmp(csym->s_name, sym->s_name) != 0) | 409 | if (strcmp(csym->s_name, sym->s_name) != 0) | |
409 | continue; | 410 | continue; | |
410 | if (csym->s_value.v_quad != sym->s_value.v_quad) { | 411 | if (csym->s_value.v_quad != sym->s_value.v_quad) { | |
411 | eq = false; | 412 | eq = false; | |
412 | break; | 413 | break; | |
413 | } | 414 | } | |
414 | w = false; | 415 | w = false; | |
415 | eq = eqtype(csym->s_type, sym->s_type, | 416 | eq = eqtype(csym->s_type, sym->s_type, | |
416 | false, false, &w) && !w; | 417 | false, false, &w) && !w; | |
417 | if (!eq) | 418 | if (!eq) | |
418 | break; | 419 | break; | |
419 | if (csym->s_bitfield != sym->s_bitfield) { | 420 | if (csym->s_bitfield != sym->s_bitfield) { | |
420 | eq = false; | 421 | eq = false; | |
421 | break; | 422 | break; | |
422 | } | 423 | } | |
423 | if (csym->s_bitfield) { | 424 | if (csym->s_bitfield) { | |
424 | type_t *tp1, *tp2; | 425 | type_t *tp1, *tp2; | |
425 | 426 | |||
426 | tp1 = csym->s_type; | 427 | tp1 = csym->s_type; | |
427 | tp2 = sym->s_type; | 428 | tp2 = sym->s_type; | |
428 | if (tp1->t_flen != tp2->t_flen) { | 429 | if (tp1->t_flen != tp2->t_flen) { | |
429 | eq = false; | 430 | eq = false; | |
430 | break; | 431 | break; | |
431 | } | 432 | } | |
432 | if (tp1->t_foffs != tp2->t_foffs) { | 433 | if (tp1->t_foffs != tp2->t_foffs) { | |
433 | eq = false; | 434 | eq = false; | |
434 | break; | 435 | break; | |
435 | } | 436 | } | |
436 | } | 437 | } | |
437 | } | 438 | } | |
438 | if (!eq) | 439 | if (!eq) | |
439 | break; | 440 | break; | |
440 | } | 441 | } | |
441 | 442 | |||
442 | /* | 443 | /* | |
443 | * Now handle the case in which the left operand refers really | 444 | * Now handle the case in which the left operand refers really | |
444 | * to a struct/union, but the right operand is not member of it. | 445 | * to a struct/union, but the right operand is not member of it. | |
445 | */ | 446 | */ | |
446 | if (str != NULL) { | 447 | if (str != NULL) { | |
447 | if (eq && tflag) { | 448 | if (eq && tflag) { | |
448 | /* illegal member use: %s */ | 449 | /* illegal member use: %s */ | |
449 | warning(102, msym->s_name); | 450 | warning(102, msym->s_name); | |
450 | } else { | 451 | } else { | |
451 | /* illegal member use: %s */ | 452 | /* illegal member use: %s */ | |
452 | error(102, msym->s_name); | 453 | error(102, msym->s_name); | |
453 | } | 454 | } | |
454 | return msym; | 455 | return msym; | |
455 | } | 456 | } | |
456 | 457 | |||
457 | /* | 458 | /* | |
458 | * Now the left operand of ARROW does not point to a struct/union | 459 | * Now the left operand of ARROW does not point to a struct/union | |
459 | * or the left operand of POINT is no struct/union. | 460 | * or the left operand of POINT is no struct/union. | |
460 | */ | 461 | */ | |
461 | if (eq) { | 462 | if (eq) { | |
462 | if (op == POINT) { | 463 | if (op == POINT) { | |
463 | if (tflag) { | 464 | if (tflag) { | |
464 | /* left operand of '.' must be struct ... */ | 465 | /* left operand of '.' must be struct ... */ | |
465 | warning(103, type_name(tn->tn_type)); | 466 | warning(103, type_name(tn->tn_type)); | |
466 | } else { | 467 | } else { | |
467 | /* left operand of '.' must be struct ... */ | 468 | /* left operand of '.' must be struct ... */ | |
468 | error(103, type_name(tn->tn_type)); | 469 | error(103, type_name(tn->tn_type)); | |
469 | } | 470 | } | |
470 | } else { | 471 | } else { | |
471 | if (tflag && tn->tn_type->t_tspec == PTR) { | 472 | if (tflag && tn->tn_type->t_tspec == PTR) { | |
472 | /* left operand of '->' must be pointer ... */ | 473 | /* left operand of '->' must be pointer ... */ | |
473 | warning(104, type_name(tn->tn_type)); | 474 | warning(104, type_name(tn->tn_type)); | |
474 | } else { | 475 | } else { | |
475 | /* left operand of '->' must be pointer ... */ | 476 | /* left operand of '->' must be pointer ... */ | |
476 | error(104, type_name(tn->tn_type)); | 477 | error(104, type_name(tn->tn_type)); | |
477 | } | 478 | } | |
478 | } | 479 | } | |
479 | } else { | 480 | } else { | |
480 | if (tflag) { | 481 | if (tflag) { | |
481 | /* non-unique member requires struct/union %s */ | 482 | /* non-unique member requires struct/union %s */ | |
482 | error(105, op == POINT ? "object" : "pointer"); | 483 | error(105, op == POINT ? "object" : "pointer"); | |
483 | } else { | 484 | } else { | |
484 | /* unacceptable operand of '%s' */ | 485 | /* unacceptable operand of '%s' */ | |
485 | error(111, op_name(op)); | 486 | error(111, op_name(op)); | |
486 | } | 487 | } | |
487 | } | 488 | } | |
488 | 489 | |||
489 | return msym; | 490 | return msym; | |
490 | } | 491 | } | |
491 | 492 | |||
492 | tnode_t * | 493 | tnode_t * | |
493 | build_generic_selection(const tnode_t *expr, | 494 | build_generic_selection(const tnode_t *expr, | |
494 | struct generic_association *sel) | 495 | struct generic_association *sel) | |
495 | { | 496 | { | |
496 | tnode_t *default_result = NULL; | 497 | tnode_t *default_result = NULL; | |
497 | 498 | |||
498 | for (; sel != NULL; sel = sel->ga_prev) | 499 | for (; sel != NULL; sel = sel->ga_prev) | |
499 | if (expr != NULL && | 500 | if (expr != NULL && | |
500 | eqtype(sel->ga_arg, expr->tn_type, false, false, NULL)) | 501 | eqtype(sel->ga_arg, expr->tn_type, false, false, NULL)) | |
501 | return sel->ga_result; | 502 | return sel->ga_result; | |
502 | else if (sel->ga_arg == NULL) | 503 | else if (sel->ga_arg == NULL) | |
503 | default_result = sel->ga_result; | 504 | default_result = sel->ga_result; | |
504 | return default_result; | 505 | return default_result; | |
505 | } | 506 | } | |
506 | 507 | |||
507 | /* | 508 | /* | |
508 | * Create a tree node for a binary operator and its two operands. Also called | 509 | * Create a tree node for a binary operator and its two operands. Also called | |
509 | * for unary operators; in that case rn is NULL. | 510 | * for unary operators; in that case rn is NULL. | |
510 | * | 511 | * | |
511 | * Function calls, sizeof and casts are handled elsewhere. | 512 | * Function calls, sizeof and casts are handled elsewhere. | |
512 | */ | 513 | */ | |
513 | tnode_t * | 514 | tnode_t * | |
514 | build_binary(tnode_t *ln, op_t op, bool sys, tnode_t *rn) | 515 | build_binary(tnode_t *ln, op_t op, bool sys, tnode_t *rn) | |
515 | { | 516 | { | |
516 | const mod_t *mp; | 517 | const mod_t *mp; | |
517 | tnode_t *ntn; | 518 | tnode_t *ntn; | |
518 | type_t *rettp; | 519 | type_t *rettp; | |
519 | 520 | |||
520 | mp = &modtab[op]; | 521 | mp = &modtab[op]; | |
521 | 522 | |||
522 | /* If there was an error in one of the operands, return. */ | 523 | /* If there was an error in one of the operands, return. */ | |
523 | if (ln == NULL || (mp->m_binary && rn == NULL)) | 524 | if (ln == NULL || (mp->m_binary && rn == NULL)) | |
524 | return NULL; | 525 | return NULL; | |
525 | 526 | |||
526 | /* | 527 | /* | |
527 | * Apply class conversions to the left operand, but only if its | 528 | * Apply class conversions to the left operand, but only if its | |
528 | * value is needed or it is compared with null. | 529 | * value is needed or it is compared with null. | |
529 | */ | 530 | */ | |
530 | if (mp->m_left_value_context || mp->m_left_test_context) | 531 | if (mp->m_left_value_context || mp->m_left_test_context) | |
531 | ln = cconv(ln); | 532 | ln = cconv(ln); | |
532 | /* | 533 | /* | |
533 | * The right operand is almost always in a test or value context, | 534 | * The right operand is almost always in a test or value context, | |
534 | * except if it is a struct or union member. | 535 | * except if it is a struct or union member. | |
535 | */ | 536 | */ | |
536 | if (mp->m_binary && op != ARROW && op != POINT) | 537 | if (mp->m_binary && op != ARROW && op != POINT) | |
537 | rn = cconv(rn); | 538 | rn = cconv(rn); | |
538 | 539 | |||
539 | /* | 540 | /* | |
540 | * Print some warnings for comparisons of unsigned values with | 541 | * Print some warnings for comparisons of unsigned values with | |
541 | * constants lower than or equal to null. This must be done | 542 | * constants lower than or equal to null. This must be done | |
542 | * before promote() because otherwise unsigned char and unsigned | 543 | * before promote() because otherwise unsigned char and unsigned | |
543 | * short would be promoted to int. Also types are tested to be | 544 | * short would be promoted to int. Also types are tested to be | |
544 | * CHAR, which would also become int. | 545 | * CHAR, which would also become int. | |
545 | */ | 546 | */ | |
546 | if (mp->m_comparison) | 547 | if (mp->m_comparison) | |
547 | check_integer_comparison(op, ln, rn); | 548 | check_integer_comparison(op, ln, rn); | |
548 | 549 | |||
549 | /* | 550 | /* | |
550 | * Promote the left operand if it is in a test or value context | 551 | * Promote the left operand if it is in a test or value context | |
551 | */ | 552 | */ | |
552 | if (mp->m_left_value_context || mp->m_left_test_context) | 553 | if (mp->m_left_value_context || mp->m_left_test_context) | |
553 | ln = promote(op, false, ln); | 554 | ln = promote(op, false, ln); | |
554 | /* | 555 | /* | |
555 | * Promote the right operand, but only if it is no struct or | 556 | * Promote the right operand, but only if it is no struct or | |
556 | * union member, or if it is not to be assigned to the left operand | 557 | * union member, or if it is not to be assigned to the left operand | |
557 | */ | 558 | */ | |
558 | if (mp->m_binary && op != ARROW && op != POINT && | 559 | if (mp->m_binary && op != ARROW && op != POINT && | |
559 | op != ASSIGN && op != RETURN && op != INIT) { | 560 | op != ASSIGN && op != RETURN && op != INIT) { | |
560 | rn = promote(op, false, rn); | 561 | rn = promote(op, false, rn); | |
561 | } | 562 | } | |
562 | 563 | |||
563 | /* | 564 | /* | |
564 | * If the result of the operation is different for signed or | 565 | * If the result of the operation is different for signed or | |
565 | * unsigned operands and one of the operands is signed only in | 566 | * unsigned operands and one of the operands is signed only in | |
566 | * ANSI C, print a warning. | 567 | * ANSI C, print a warning. | |
567 | */ | 568 | */ | |
568 | if (mp->m_warn_if_left_unsigned_in_c90 && | 569 | if (mp->m_warn_if_left_unsigned_in_c90 && | |
569 | ln->tn_op == CON && ln->tn_val->v_unsigned_since_c90) { | 570 | ln->tn_op == CON && ln->tn_val->v_unsigned_since_c90) { | |
570 | /* ANSI C treats constant as unsigned, op %s */ | 571 | /* ANSI C treats constant as unsigned, op %s */ | |
571 | warning(218, mp->m_name); | 572 | warning(218, mp->m_name); | |
572 | ln->tn_val->v_unsigned_since_c90 = false; | 573 | ln->tn_val->v_unsigned_since_c90 = false; | |
573 | } | 574 | } | |
574 | if (mp->m_warn_if_right_unsigned_in_c90 && | 575 | if (mp->m_warn_if_right_unsigned_in_c90 && | |
575 | rn->tn_op == CON && rn->tn_val->v_unsigned_since_c90) { | 576 | rn->tn_op == CON && rn->tn_val->v_unsigned_since_c90) { | |
576 | /* ANSI C treats constant as unsigned, op %s */ | 577 | /* ANSI C treats constant as unsigned, op %s */ | |
577 | warning(218, mp->m_name); | 578 | warning(218, mp->m_name); | |
578 | rn->tn_val->v_unsigned_since_c90 = false; | 579 | rn->tn_val->v_unsigned_since_c90 = false; | |
579 | } | 580 | } | |
580 | 581 | |||
581 | /* Make sure both operands are of the same type */ | 582 | /* Make sure both operands are of the same type */ | |
582 | if (mp->m_balance_operands || (tflag && (op == SHL || op == SHR))) | 583 | if (mp->m_balance_operands || (tflag && (op == SHL || op == SHR))) | |
583 | balance(op, &ln, &rn); | 584 | balance(op, &ln, &rn); | |
584 | 585 | |||
585 | /* | 586 | /* | |
586 | * Check types for compatibility with the operation and mutual | 587 | * Check types for compatibility with the operation and mutual | |
587 | * compatibility. Return if there are serious problems. | 588 | * compatibility. Return if there are serious problems. | |
588 | */ | 589 | */ | |
589 | if (!typeok(op, 0, ln, rn)) | 590 | if (!typeok(op, 0, ln, rn)) | |
590 | return NULL; | 591 | return NULL; | |
591 | 592 | |||
592 | /* And now create the node. */ | 593 | /* And now create the node. */ | |
593 | switch (op) { | 594 | switch (op) { | |
594 | case POINT: | 595 | case POINT: | |
595 | case ARROW: | 596 | case ARROW: | |
596 | ntn = build_struct_access(op, sys, ln, rn); | 597 | ntn = build_struct_access(op, sys, ln, rn); | |
597 | break; | 598 | break; | |
598 | case INCAFT: | 599 | case INCAFT: | |
599 | case DECAFT: | 600 | case DECAFT: | |
600 | case INCBEF: | 601 | case INCBEF: | |
601 | case DECBEF: | 602 | case DECBEF: | |
602 | ntn = build_prepost_incdec(op, sys, ln); | 603 | ntn = build_prepost_incdec(op, sys, ln); | |
603 | break; | 604 | break; | |
604 | case ADDR: | 605 | case ADDR: | |
605 | ntn = build_address(sys, ln, false); | 606 | ntn = build_address(sys, ln, false); | |
606 | break; | 607 | break; | |
607 | case INDIR: | 608 | case INDIR: | |
608 | ntn = new_tnode(INDIR, sys, ln->tn_type->t_subt, ln, NULL); | 609 | ntn = new_tnode(INDIR, sys, ln->tn_type->t_subt, ln, NULL); | |
609 | break; | 610 | break; | |
610 | case PLUS: | 611 | case PLUS: | |
611 | case MINUS: | 612 | case MINUS: | |
612 | ntn = build_plus_minus(op, sys, ln, rn); | 613 | ntn = build_plus_minus(op, sys, ln, rn); | |
613 | break; | 614 | break; | |
614 | case SHL: | 615 | case SHL: | |
615 | case SHR: | 616 | case SHR: | |
616 | ntn = build_bit_shift(op, sys, ln, rn); | 617 | ntn = build_bit_shift(op, sys, ln, rn); | |
617 | break; | 618 | break; | |
618 | case COLON: | 619 | case COLON: | |
619 | ntn = build_colon(sys, ln, rn); | 620 | ntn = build_colon(sys, ln, rn); | |
620 | break; | 621 | break; | |
621 | case ASSIGN: | 622 | case ASSIGN: | |
622 | case MULASS: | 623 | case MULASS: | |
623 | case DIVASS: | 624 | case DIVASS: | |
624 | case MODASS: | 625 | case MODASS: | |
625 | case ADDASS: | 626 | case ADDASS: | |
626 | case SUBASS: | 627 | case SUBASS: | |
627 | case SHLASS: | 628 | case SHLASS: | |
628 | case SHRASS: | 629 | case SHRASS: | |
629 | case ANDASS: | 630 | case ANDASS: | |
630 | case XORASS: | 631 | case XORASS: | |
631 | case ORASS: | 632 | case ORASS: | |
632 | case RETURN: | 633 | case RETURN: | |
633 | case INIT: | 634 | case INIT: | |
634 | ntn = build_assignment(op, sys, ln, rn); | 635 | ntn = build_assignment(op, sys, ln, rn); | |
635 | break; | 636 | break; | |
636 | case COMMA: | 637 | case COMMA: | |
637 | case QUEST: | 638 | case QUEST: | |
638 | ntn = new_tnode(op, sys, rn->tn_type, ln, rn); | 639 | ntn = new_tnode(op, sys, rn->tn_type, ln, rn); | |
639 | break; | 640 | break; | |
640 | case REAL: | 641 | case REAL: | |
641 | case IMAG: | 642 | case IMAG: | |
642 | ntn = build_real_imag(op, sys, ln); | 643 | ntn = build_real_imag(op, sys, ln); | |
643 | break; | 644 | break; | |
644 | default: | 645 | default: | |
645 | rettp = mp->m_returns_bool | 646 | rettp = mp->m_returns_bool | |
646 | ? gettyp(Tflag ? BOOL : INT) : ln->tn_type; | 647 | ? gettyp(Tflag ? BOOL : INT) : ln->tn_type; | |
647 | lint_assert(mp->m_binary || rn == NULL); | 648 | lint_assert(mp->m_binary || rn == NULL); | |
648 | ntn = new_tnode(op, sys, rettp, ln, rn); | 649 | ntn = new_tnode(op, sys, rettp, ln, rn); | |
649 | break; | 650 | break; | |
650 | } | 651 | } | |
651 | 652 | |||
652 | /* Return if an error occurred. */ | 653 | /* Return if an error occurred. */ | |
653 | if (ntn == NULL) | 654 | if (ntn == NULL) | |
654 | return NULL; | 655 | return NULL; | |
655 | 656 | |||
656 | /* Print a warning if precedence confusion is possible */ | 657 | /* Print a warning if precedence confusion is possible */ | |
657 | if (mp->m_possible_precedence_confusion) | 658 | if (mp->m_possible_precedence_confusion) | |
658 | check_precedence_confusion(ntn); | 659 | check_precedence_confusion(ntn); | |
659 | 660 | |||
660 | /* | 661 | /* | |
661 | * Print a warning if one of the operands is in a context where | 662 | * Print a warning if one of the operands is in a context where | |
662 | * it is compared with null and if this operand is a constant. | 663 | * it is compared with null and if this operand is a constant. | |
663 | */ | 664 | */ | |
664 | if (mp->m_left_test_context) { | 665 | if (mp->m_left_test_context) { | |
665 | if (ln->tn_op == CON || | 666 | if (ln->tn_op == CON || | |
666 | ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) { | 667 | ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) { | |
667 | if (hflag && !constcond_flag && | 668 | if (hflag && !constcond_flag && | |
668 | !ln->tn_system_dependent) | 669 | !ln->tn_system_dependent) | |
669 | /* constant in conditional context */ | 670 | /* constant in conditional context */ | |
670 | warning(161); | 671 | warning(161); | |
671 | } | 672 | } | |
672 | } | 673 | } | |
673 | 674 | |||
674 | /* Fold if the operator requires it */ | 675 | /* Fold if the operator requires it */ | |
675 | if (mp->m_fold_constant_operands) { | 676 | if (mp->m_fold_constant_operands) { | |
676 | if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { | 677 | if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { | |
677 | if (mp->m_left_test_context) { | 678 | if (mp->m_left_test_context) { | |
678 | ntn = fold_test(ntn); | 679 | ntn = fold_test(ntn); | |
679 | } else if (is_floating(ntn->tn_type->t_tspec)) { | 680 | } else if (is_floating(ntn->tn_type->t_tspec)) { | |
680 | ntn = fold_float(ntn); | 681 | ntn = fold_float(ntn); | |
681 | } else { | 682 | } else { | |
682 | ntn = fold(ntn); | 683 | ntn = fold(ntn); | |
683 | } | 684 | } | |
684 | } else if (op == QUEST && ln->tn_op == CON) { | 685 | } else if (op == QUEST && ln->tn_op == CON) { | |
685 | ntn = ln->tn_val->v_quad != 0 | 686 | ntn = ln->tn_val->v_quad != 0 | |
686 | ? rn->tn_left : rn->tn_right; | 687 | ? rn->tn_left : rn->tn_right; | |
687 | } | 688 | } | |
688 | } | 689 | } | |
689 | 690 | |||
690 | return ntn; | 691 | return ntn; | |
691 | } | 692 | } | |
692 | 693 | |||
693 | tnode_t * | 694 | tnode_t * | |
694 | build_unary(op_t op, bool sys, tnode_t *tn) | 695 | build_unary(op_t op, bool sys, tnode_t *tn) | |
695 | { | 696 | { | |
696 | return build_binary(tn, op, sys, NULL); | 697 | return build_binary(tn, op, sys, NULL); | |
697 | } | 698 | } | |
698 | 699 | |||
699 | tnode_t * | 700 | tnode_t * | |
700 | build_member_access(tnode_t *ln, op_t op, bool sys, sbuf_t *member) | 701 | build_member_access(tnode_t *ln, op_t op, bool sys, sbuf_t *member) | |
701 | { | 702 | { | |
702 | sym_t *msym; | 703 | sym_t *msym; | |
703 | 704 | |||
704 | if (ln == NULL) | 705 | if (ln == NULL) | |
705 | return NULL; | 706 | return NULL; | |
706 | 707 | |||
707 | if (op == ARROW) { | 708 | if (op == ARROW) { | |
708 | /* must do this before struct_or_union_member is called */ | 709 | /* must do this before struct_or_union_member is called */ | |
709 | ln = cconv(ln); | 710 | ln = cconv(ln); | |
710 | } | 711 | } | |
711 | msym = struct_or_union_member(ln, op, getsym(member)); | 712 | msym = struct_or_union_member(ln, op, getsym(member)); | |
712 | return build_binary(ln, op, sys, build_name(msym, false)); | 713 | return build_binary(ln, op, sys, build_name(msym, false)); | |
713 | } | 714 | } | |
714 | 715 | |||
715 | /* | 716 | /* | |
716 | * Perform class conversions. | 717 | * Perform class conversions. | |
717 | * | 718 | * | |
718 | * Arrays of type T are converted into pointers to type T. | 719 | * Arrays of type T are converted into pointers to type T. | |
719 | * Functions are converted to pointers to functions. | 720 | * Functions are converted to pointers to functions. | |
720 | * Lvalues are converted to rvalues. | 721 | * Lvalues are converted to rvalues. | |
721 | * | 722 | * | |
722 | * C99 6.3 "Conversions" | 723 | * C99 6.3 "Conversions" | |
723 | * C99 6.3.2 "Other operands" | 724 | * C99 6.3.2 "Other operands" | |
724 | * C99 6.3.2.1 "Lvalues, arrays, and function designators" | 725 | * C99 6.3.2.1 "Lvalues, arrays, and function designators" | |
725 | */ | 726 | */ | |
726 | tnode_t * | 727 | tnode_t * | |
727 | cconv(tnode_t *tn) | 728 | cconv(tnode_t *tn) | |
728 | { | 729 | { | |
729 | type_t *tp; | 730 | type_t *tp; | |
730 | 731 | |||
731 | /* | 732 | /* | |
732 | * Array-lvalue (array of type T) is converted into rvalue | 733 | * Array-lvalue (array of type T) is converted into rvalue | |
733 | * (pointer to type T) | 734 | * (pointer to type T) | |
734 | */ | 735 | */ | |
735 | if (tn->tn_type->t_tspec == ARRAY) { | 736 | if (tn->tn_type->t_tspec == ARRAY) { | |
736 | if (!tn->tn_lvalue) { | 737 | if (!tn->tn_lvalue) { | |
737 | /* XXX print correct operator */ | 738 | /* XXX print correct operator */ | |
738 | /* %soperand of '%s' must be lvalue */ | 739 | /* %soperand of '%s' must be lvalue */ | |
739 | gnuism(114, "", op_name(ADDR)); | 740 | gnuism(114, "", op_name(ADDR)); | |
740 | } | 741 | } | |
741 | tn = new_tnode(ADDR, tn->tn_sys, | 742 | tn = new_tnode(ADDR, tn->tn_sys, | |
742 | expr_derive_type(tn->tn_type->t_subt, PTR), tn, NULL); | 743 | expr_derive_type(tn->tn_type->t_subt, PTR), tn, NULL); | |
743 | } | 744 | } | |
744 | 745 | |||
745 | /* | 746 | /* | |
746 | * Expression of type function (function with return value of type T) | 747 | * Expression of type function (function with return value of type T) | |
747 | * in rvalue-expression (pointer to function with return value | 748 | * in rvalue-expression (pointer to function with return value | |
748 | * of type T) | 749 | * of type T) | |
749 | */ | 750 | */ | |
750 | if (tn->tn_type->t_tspec == FUNC) | 751 | if (tn->tn_type->t_tspec == FUNC) | |
751 | tn = build_address(tn->tn_sys, tn, true); | 752 | tn = build_address(tn->tn_sys, tn, true); | |
752 | 753 | |||
753 | /* lvalue to rvalue */ | 754 | /* lvalue to rvalue */ | |
754 | if (tn->tn_lvalue) { | 755 | if (tn->tn_lvalue) { | |
755 | tp = expr_dup_type(tn->tn_type); | 756 | tp = expr_dup_type(tn->tn_type); | |
756 | /* C99 6.3.2.1p2 sentence 2 says to remove the qualifiers. */ | 757 | /* C99 6.3.2.1p2 sentence 2 says to remove the qualifiers. */ | |
757 | tp->t_const = tp->t_volatile = false; | 758 | tp->t_const = tp->t_volatile = false; | |
758 | tn = new_tnode(LOAD, tn->tn_sys, tp, tn, NULL); | 759 | tn = new_tnode(LOAD, tn->tn_sys, tp, tn, NULL); | |
759 | } | 760 | } | |
760 | 761 | |||
761 | return tn; | 762 | return tn; | |
762 | } | 763 | } | |
763 | 764 | |||
764 | const tnode_t * | 765 | const tnode_t * | |
765 | before_conversion(const tnode_t *tn) | 766 | before_conversion(const tnode_t *tn) | |
766 | { | 767 | { | |
767 | while (tn->tn_op == CVT && !tn->tn_cast) | 768 | while (tn->tn_op == CVT && !tn->tn_cast) | |
768 | tn = tn->tn_left; | 769 | tn = tn->tn_left; | |
769 | return tn; | 770 | return tn; | |
770 | } | 771 | } | |
771 | 772 | |||
772 | static bool | 773 | static bool | |
773 | is_null_pointer(const tnode_t *tn) | 774 | is_null_pointer(const tnode_t *tn) | |
774 | { | 775 | { | |
775 | tspec_t t = tn->tn_type->t_tspec; | 776 | tspec_t t = tn->tn_type->t_tspec; | |
776 | 777 | |||
777 | return ((t == PTR && tn->tn_type->t_subt->t_tspec == VOID) || | 778 | return ((t == PTR && tn->tn_type->t_subt->t_tspec == VOID) || | |
778 | is_integer(t)) | 779 | is_integer(t)) | |
779 | && (tn->tn_op == CON && tn->tn_val->v_quad == 0); | 780 | && (tn->tn_op == CON && tn->tn_val->v_quad == 0); | |
780 | } | 781 | } | |
781 | 782 | |||
782 | /* | 783 | /* | |
783 | * Most errors required by ANSI C are reported in struct_or_union_member(). | 784 | * Most errors required by ANSI C are reported in struct_or_union_member(). | |
784 | * Here we only check for totally wrong things. | 785 | * Here we only check for totally wrong things. | |
785 | */ | 786 | */ | |
786 | static bool | 787 | static bool | |
787 | typeok_point(const tnode_t *ln, const type_t *ltp, tspec_t lt) | 788 | typeok_point(const tnode_t *ln, const type_t *ltp, tspec_t lt) | |
788 | { | 789 | { | |
789 | if (lt == FUNC || lt == VOID || ltp->t_bitfield || | 790 | if (lt == FUNC || lt == VOID || ltp->t_bitfield || | |
790 | ((lt != STRUCT && lt != UNION) && !ln->tn_lvalue)) { | 791 | ((lt != STRUCT && lt != UNION) && !ln->tn_lvalue)) { | |
791 | /* Without tflag we got already an error */ | 792 | /* Without tflag we got already an error */ | |
792 | if (tflag) | 793 | if (tflag) | |
793 | /* unacceptable operand of '%s' */ | 794 | /* unacceptable operand of '%s' */ | |
794 | error(111, op_name(POINT)); | 795 | error(111, op_name(POINT)); | |
795 | return false; | 796 | return false; | |
796 | } | 797 | } | |
797 | return true; | 798 | return true; | |
798 | } | 799 | } | |
799 | 800 | |||
800 | static bool | 801 | static bool | |
801 | typeok_arrow(tspec_t lt) | 802 | typeok_arrow(tspec_t lt) | |
802 | { | 803 | { | |
803 | if (lt == PTR || (tflag && is_integer(lt))) | 804 | if (lt == PTR || (tflag && is_integer(lt))) | |
804 | return true; | 805 | return true; | |
805 | 806 | |||
806 | /* Without tflag we got already an error */ | 807 | /* Without tflag we got already an error */ | |
807 | if (tflag) | 808 | if (tflag) | |
808 | /* unacceptable operand of '%s' */ | 809 | /* unacceptable operand of '%s' */ | |
809 | error(111, op_name(ARROW)); | 810 | error(111, op_name(ARROW)); | |
810 | return false; | 811 | return false; | |
811 | } | 812 | } | |
812 | 813 | |||
813 | static bool | 814 | static bool | |
814 | typeok_incdec(op_t op, const tnode_t *tn, const type_t *tp) | 815 | typeok_incdec(op_t op, const tnode_t *tn, const type_t *tp) | |
815 | { | 816 | { | |
816 | /* operand has scalar type (checked in typeok) */ | 817 | /* operand has scalar type (checked in typeok) */ | |
817 | if (!tn->tn_lvalue) { | 818 | if (!tn->tn_lvalue) { | |
818 | if (tn->tn_op == CVT && tn->tn_cast && | 819 | if (tn->tn_op == CVT && tn->tn_cast && | |
819 | tn->tn_left->tn_op == LOAD) { | 820 | tn->tn_left->tn_op == LOAD) { | |
820 | /* a cast does not yield an lvalue */ | 821 | /* a cast does not yield an lvalue */ | |
821 | error(163); | 822 | error(163); | |
822 | } | 823 | } | |
823 | /* %soperand of '%s' must be lvalue */ | 824 | /* %soperand of '%s' must be lvalue */ | |
824 | error(114, "", op_name(op)); | 825 | error(114, "", op_name(op)); | |
825 | return false; | 826 | return false; | |
826 | } else if (tp->t_const) { | 827 | } else if (tp->t_const) { | |
827 | if (!tflag) | 828 | if (!tflag) | |
828 | /* %soperand of '%s' must be modifiable lvalue */ | 829 | /* %soperand of '%s' must be modifiable lvalue */ | |
829 | warning(115, "", op_name(op)); | 830 | warning(115, "", op_name(op)); | |
830 | } | 831 | } | |
831 | return true; | 832 | return true; | |
832 | } | 833 | } | |
833 | 834 | |||
834 | static bool | 835 | static bool | |
835 | typeok_address(const mod_t *mp, | 836 | typeok_address(const mod_t *mp, | |
836 | const tnode_t *tn, const type_t *tp, tspec_t t) | 837 | const tnode_t *tn, const type_t *tp, tspec_t t) | |
837 | { | 838 | { | |
838 | if (t == ARRAY || t == FUNC) { | 839 | if (t == ARRAY || t == FUNC) { | |
839 | /* ok, a warning comes later (in build_address()) */ | 840 | /* ok, a warning comes later (in build_address()) */ | |
840 | } else if (!tn->tn_lvalue) { | 841 | } else if (!tn->tn_lvalue) { | |
841 | if (tn->tn_op == CVT && tn->tn_cast && | 842 | if (tn->tn_op == CVT && tn->tn_cast && | |
842 | tn->tn_left->tn_op == LOAD) { | 843 | tn->tn_left->tn_op == LOAD) { | |
843 | /* a cast does not yield an lvalue */ | 844 | /* a cast does not yield an lvalue */ | |
844 | error(163); | 845 | error(163); | |
845 | } | 846 | } | |
846 | /* %soperand of '%s' must be lvalue */ | 847 | /* %soperand of '%s' must be lvalue */ | |
847 | error(114, "", mp->m_name); | 848 | error(114, "", mp->m_name); | |
848 | return false; | 849 | return false; | |
849 | } else if (is_scalar(t)) { | 850 | } else if (is_scalar(t)) { | |
850 | if (tp->t_bitfield) { | 851 | if (tp->t_bitfield) { | |
851 | /* cannot take address of bit-field */ | 852 | /* cannot take address of bit-field */ | |
852 | error(112); | 853 | error(112); | |
853 | return false; | 854 | return false; | |
854 | } | 855 | } | |
855 | } else if (t != STRUCT && t != UNION) { | 856 | } else if (t != STRUCT && t != UNION) { | |
856 | /* unacceptable operand of '%s' */ | 857 | /* unacceptable operand of '%s' */ | |
857 | error(111, mp->m_name); | 858 | error(111, mp->m_name); | |
858 | return false; | 859 | return false; | |
859 | } | 860 | } | |
860 | if (tn->tn_op == NAME && tn->tn_sym->s_reg) { | 861 | if (tn->tn_op == NAME && tn->tn_sym->s_reg) { | |
861 | /* cannot take address of register %s */ | 862 | /* cannot take address of register %s */ | |
862 | error(113, tn->tn_sym->s_name); | 863 | error(113, tn->tn_sym->s_name); | |
863 | return false; | 864 | return false; | |
864 | } | 865 | } | |
865 | return true; | 866 | return true; | |
866 | } | 867 | } | |
867 | 868 | |||
868 | static bool | 869 | static bool | |
869 | typeok_indir(tspec_t t) | 870 | typeok_indir(tspec_t t) | |
870 | { | 871 | { | |
871 | /* until now there were no type checks for this operator */ | 872 | /* until now there were no type checks for this operator */ | |
872 | if (t != PTR) { | 873 | if (t != PTR) { | |
873 | /* cannot dereference non-pointer type */ | 874 | /* cannot dereference non-pointer type */ | |
874 | error(96); | 875 | error(96); | |
875 | return false; | 876 | return false; | |
876 | } | 877 | } | |
877 | return true; | 878 | return true; | |
878 | } | 879 | } | |
879 | 880 | |||
880 | static bool | 881 | static bool | |
881 | typeok_plus(op_t op, | 882 | typeok_plus(op_t op, | |
882 | const type_t *ltp, tspec_t lt, | 883 | const type_t *ltp, tspec_t lt, | |
883 | const type_t *rtp, tspec_t rt) | 884 | const type_t *rtp, tspec_t rt) | |
884 | { | 885 | { | |
885 | /* operands have scalar types (checked above) */ | 886 | /* operands have scalar types (checked above) */ | |
886 | if ((lt == PTR && !is_integer(rt)) || (rt == PTR && !is_integer(lt))) { | 887 | if ((lt == PTR && !is_integer(rt)) || (rt == PTR && !is_integer(lt))) { | |
887 | warn_incompatible_types(op, ltp, lt, rtp, rt); | 888 | warn_incompatible_types(op, ltp, lt, rtp, rt); | |
888 | return false; | 889 | return false; | |
889 | } | 890 | } | |
890 | return true; | 891 | return true; | |
891 | } | 892 | } | |
892 | 893 | |||
893 | static bool | 894 | static bool | |
894 | typeok_minus(op_t op, | 895 | typeok_minus(op_t op, | |
895 | const type_t *ltp, tspec_t lt, | 896 | const type_t *ltp, tspec_t lt, | |
896 | const type_t *rtp, tspec_t rt) | 897 | const type_t *rtp, tspec_t rt) | |
897 | { | 898 | { | |
898 | /* operands have scalar types (checked above) */ | 899 | /* operands have scalar types (checked above) */ | |
899 | if (lt == PTR && (!is_integer(rt) && rt != PTR)) { | 900 | if (lt == PTR && (!is_integer(rt) && rt != PTR)) { | |
900 | warn_incompatible_types(op, ltp, lt, rtp, rt); | 901 | warn_incompatible_types(op, ltp, lt, rtp, rt); | |
901 | return false; | 902 | return false; | |
902 | } else if (rt == PTR && lt != PTR) { | 903 | } else if (rt == PTR && lt != PTR) { | |
903 | warn_incompatible_types(op, ltp, lt, rtp, rt); | 904 | warn_incompatible_types(op, ltp, lt, rtp, rt); | |
904 | return false; | 905 | return false; | |
905 | } | 906 | } | |
906 | if (lt == PTR && rt == PTR) { | 907 | if (lt == PTR && rt == PTR) { | |
907 | if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) { | 908 | if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) { | |
908 | /* illegal pointer subtraction */ | 909 | /* illegal pointer subtraction */ | |
909 | error(116); | 910 | error(116); | |
910 | } | 911 | } | |
911 | } | 912 | } | |
912 | return true; | 913 | return true; | |
913 | } | 914 | } | |
914 | 915 | |||
915 | static void | 916 | static void | |
916 | typeok_shr(const mod_t *mp, | 917 | typeok_shr(const mod_t *mp, | |
917 | const tnode_t *ln, tspec_t lt, | 918 | const tnode_t *ln, tspec_t lt, | |
918 | const tnode_t *rn, tspec_t rt) | 919 | const tnode_t *rn, tspec_t rt) | |
919 | { | 920 | { | |
920 | tspec_t olt, ort; | 921 | tspec_t olt, ort; | |
921 | 922 | |||
922 | olt = before_conversion(ln)->tn_type->t_tspec; | 923 | olt = before_conversion(ln)->tn_type->t_tspec; | |
923 | ort = before_conversion(rn)->tn_type->t_tspec; | 924 | ort = before_conversion(rn)->tn_type->t_tspec; | |
924 | 925 | |||
925 | /* operands have integer types (checked above) */ | 926 | /* operands have integer types (checked above) */ | |
926 | if (pflag && !is_uinteger(olt)) { | 927 | if (pflag && !is_uinteger(olt)) { | |
927 | /* | 928 | /* | |
928 | * The left operand is signed. This means that | 929 | * The left operand is signed. This means that | |
929 | * the operation is (possibly) nonportable. | 930 | * the operation is (possibly) nonportable. | |
930 | */ | 931 | */ | |
931 | if (ln->tn_op != CON) { | 932 | if (ln->tn_op != CON) { | |
932 | /* bitwise '%s' on signed value possibly nonportable */ | 933 | /* bitwise '%s' on signed value possibly nonportable */ | |
933 | warning(117, mp->m_name); | 934 | warning(117, mp->m_name); | |
934 | } else if (ln->tn_val->v_quad < 0) { | 935 | } else if (ln->tn_val->v_quad < 0) { | |
935 | /* bitwise '%s' on signed value nonportable */ | 936 | /* bitwise '%s' on signed value nonportable */ | |
936 | warning(120, mp->m_name); | 937 | warning(120, mp->m_name); | |
937 | } | 938 | } | |
938 | } else if (!tflag && !sflag && !is_uinteger(olt) && is_uinteger(ort)) { | 939 | } else if (!tflag && !sflag && !is_uinteger(olt) && is_uinteger(ort)) { | |
939 | /* | 940 | /* | |
940 | * The left operand would become unsigned in | 941 | * The left operand would become unsigned in | |
941 | * traditional C. | 942 | * traditional C. | |
942 | */ | 943 | */ | |
943 | if (hflag && !Sflag && | 944 | if (hflag && !Sflag && | |
944 | (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { | 945 | (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { | |
945 | /* semantics of '%s' change in ANSI C; use ... */ | 946 | /* semantics of '%s' change in ANSI C; use ... */ | |
946 | warning(118, mp->m_name); | 947 | warning(118, mp->m_name); | |
947 | } | 948 | } | |
948 | } else if (!tflag && !sflag && !is_uinteger(olt) && !is_uinteger(ort) && | 949 | } else if (!tflag && !sflag && !is_uinteger(olt) && !is_uinteger(ort) && | |
949 | portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | 950 | portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | |
950 | /* | 951 | /* | |
951 | * In traditional C the left operand would be extended, | 952 | * In traditional C the left operand would be extended, | |
952 | * possibly with 1, and then shifted. | 953 | * possibly with 1, and then shifted. | |
953 | */ | 954 | */ | |
954 | if (hflag && !Sflag && | 955 | if (hflag && !Sflag && | |
955 | (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { | 956 | (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { | |
956 | /* semantics of '%s' change in ANSI C; use ... */ | 957 | /* semantics of '%s' change in ANSI C; use ... */ | |
957 | warning(118, mp->m_name); | 958 | warning(118, mp->m_name); | |
958 | } | 959 | } | |
959 | } | 960 | } | |
960 | } | 961 | } | |
961 | 962 | |||
962 | static void | 963 | static void | |
963 | typeok_shl(const mod_t *mp, tspec_t lt, tspec_t rt) | 964 | typeok_shl(const mod_t *mp, tspec_t lt, tspec_t rt) | |
964 | { | 965 | { | |
965 | /* | 966 | /* | |
966 | * C90 does not perform balancing for shift operations, | 967 | * C90 does not perform balancing for shift operations, | |
967 | * but traditional C does. If the width of the right operand | 968 | * but traditional C does. If the width of the right operand | |
968 | * is greater than the width of the left operand, then in | 969 | * is greater than the width of the left operand, then in | |
969 | * traditional C the left operand would be extended to the | 970 | * traditional C the left operand would be extended to the | |
970 | * width of the right operand. For SHL this may result in | 971 | * width of the right operand. For SHL this may result in | |
971 | * different results. | 972 | * different results. | |
972 | */ | 973 | */ | |
973 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | 974 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | |
974 | /* | 975 | /* | |
975 | * XXX If both operands are constant, make sure | 976 | * XXX If both operands are constant, make sure | |
976 | * that there is really a difference between | 977 | * that there is really a difference between | |
977 | * ANSI C and traditional C. | 978 | * ANSI C and traditional C. | |
978 | */ | 979 | */ | |
979 | if (hflag && !Sflag) | 980 | if (hflag && !Sflag) | |
980 | /* semantics of '%s' change in ANSI C; use ... */ | 981 | /* semantics of '%s' change in ANSI C; use ... */ | |
981 | warning(118, mp->m_name); | 982 | warning(118, mp->m_name); | |
982 | } | 983 | } | |
983 | } | 984 | } | |
984 | 985 | |||
985 | static void | 986 | static void | |
986 | typeok_shift(tspec_t lt, const tnode_t *rn, tspec_t rt) | 987 | typeok_shift(tspec_t lt, const tnode_t *rn, tspec_t rt) | |
987 | { | 988 | { | |
988 | if (rn->tn_op != CON) | 989 | if (rn->tn_op != CON) | |
989 | return; | 990 | return; | |
990 | 991 | |||
991 | if (!is_uinteger(rt) && rn->tn_val->v_quad < 0) { | 992 | if (!is_uinteger(rt) && rn->tn_val->v_quad < 0) { | |
992 | /* negative shift */ | 993 | /* negative shift */ | |
993 | warning(121); | 994 | warning(121); | |
994 | } else if ((uint64_t)rn->tn_val->v_quad == | 995 | } else if ((uint64_t)rn->tn_val->v_quad == | |
995 | (uint64_t)size_in_bits(lt)) { | 996 | (uint64_t)size_in_bits(lt)) { | |
996 | /* shift equal to size of object */ | 997 | /* shift equal to size of object */ | |
997 | warning(267); | 998 | warning(267); | |
998 | } else if ((uint64_t)rn->tn_val->v_quad > (uint64_t)size_in_bits(lt)) { | 999 | } else if ((uint64_t)rn->tn_val->v_quad > (uint64_t)size_in_bits(lt)) { | |
999 | /* shift amount %llu is greater than bit-size %llu of '%s' */ | 1000 | /* shift amount %llu is greater than bit-size %llu of '%s' */ | |
1000 | warning(122, (unsigned long long)rn->tn_val->v_quad, | 1001 | warning(122, (unsigned long long)rn->tn_val->v_quad, | |
1001 | (unsigned long long)size_in_bits(lt), | 1002 | (unsigned long long)size_in_bits(lt), | |
1002 | tspec_name(lt)); | 1003 | tspec_name(lt)); | |
1003 | } | 1004 | } | |
1004 | } | 1005 | } | |
1005 | 1006 | |||
1006 | static bool | 1007 | static bool | |
1007 | is_typeok_eq(const tnode_t *ln, tspec_t lt, const tnode_t *rn, tspec_t rt) | 1008 | is_typeok_eq(const tnode_t *ln, tspec_t lt, const tnode_t *rn, tspec_t rt) | |
1008 | { | 1009 | { | |
1009 | if (lt == PTR && is_null_pointer(rn)) | 1010 | if (lt == PTR && is_null_pointer(rn)) | |
1010 | return true; | 1011 | return true; | |
1011 | if (rt == PTR && is_null_pointer(ln)) | 1012 | if (rt == PTR && is_null_pointer(ln)) | |
1012 | return true; | 1013 | return true; | |
1013 | return false; | 1014 | return false; | |
1014 | } | 1015 | } | |
1015 | 1016 | |||
1016 | static bool | 1017 | static bool | |
1017 | typeok_compare(op_t op, | 1018 | typeok_compare(op_t op, | |
1018 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | 1019 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | |
1019 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | 1020 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | |
1020 | { | 1021 | { | |
1021 | const char *lx, *rx; | 1022 | const char *lx, *rx; | |
1022 | 1023 | |||
1023 | if (lt == PTR && rt == PTR) { | 1024 | if (lt == PTR && rt == PTR) { | |
1024 | check_pointer_comparison(op, ln, rn); | 1025 | check_pointer_comparison(op, ln, rn); | |
1025 | return true; | 1026 | return true; | |
1026 | } | 1027 | } | |
1027 | 1028 | |||
1028 | if (lt != PTR && rt != PTR) | 1029 | if (lt != PTR && rt != PTR) | |
1029 | return true; | 1030 | return true; | |
1030 | 1031 | |||
1031 | if (!is_integer(lt) && !is_integer(rt)) { | 1032 | if (!is_integer(lt) && !is_integer(rt)) { | |
1032 | warn_incompatible_types(op, ltp, lt, rtp, rt); | 1033 | warn_incompatible_types(op, ltp, lt, rtp, rt); | |
1033 | return false; | 1034 | return false; | |
1034 | } | 1035 | } | |
1035 | 1036 | |||
1036 | lx = lt == PTR ? "pointer" : "integer"; | 1037 | lx = lt == PTR ? "pointer" : "integer"; | |
1037 | rx = rt == PTR ? "pointer" : "integer"; | 1038 | rx = rt == PTR ? "pointer" : "integer"; | |
1038 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ | 1039 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ | |
1039 | warning(123, lx, type_name(ltp), rx, type_name(rtp), op_name(op)); | 1040 | warning(123, lx, type_name(ltp), rx, type_name(rtp), op_name(op)); | |
1040 | return true; | 1041 | return true; | |
1041 | } | 1042 | } | |
1042 | 1043 | |||
1043 | static bool | 1044 | static bool | |
1044 | typeok_quest(tspec_t lt, const tnode_t *rn) | 1045 | typeok_quest(tspec_t lt, const tnode_t *rn) | |
1045 | { | 1046 | { | |
1046 | if (!is_scalar(lt)) { | 1047 | if (!is_scalar(lt)) { | |
1047 | /* first operand must have scalar type, op ? : */ | 1048 | /* first operand must have scalar type, op ? : */ | |
1048 | error(170); | 1049 | error(170); | |
1049 | return false; | 1050 | return false; | |
1050 | } | 1051 | } | |
1051 | lint_assert(before_conversion(rn)->tn_op == COLON); | 1052 | lint_assert(before_conversion(rn)->tn_op == COLON); | |
1052 | return true; | 1053 | return true; | |
1053 | } | 1054 | } | |
1054 | 1055 | |||
1055 | static void | 1056 | static void | |
1056 | typeok_colon_pointer(const mod_t *mp, const type_t *ltp, const type_t *rtp) | 1057 | typeok_colon_pointer(const mod_t *mp, const type_t *ltp, const type_t *rtp) | |
1057 | { | 1058 | { | |
1058 | type_t *lstp = ltp->t_subt; | 1059 | type_t *lstp = ltp->t_subt; | |
1059 | type_t *rstp = rtp->t_subt; | 1060 | type_t *rstp = rtp->t_subt; | |
1060 | tspec_t lst = lstp->t_tspec; | 1061 | tspec_t lst = lstp->t_tspec; | |
1061 | tspec_t rst = rstp->t_tspec; | 1062 | tspec_t rst = rstp->t_tspec; | |
1062 | 1063 | |||
1063 | if ((lst == VOID && rst == FUNC) || (lst == FUNC && rst == VOID)) { | 1064 | if ((lst == VOID && rst == FUNC) || (lst == FUNC && rst == VOID)) { | |
1064 | /* (void *)0 handled above */ | 1065 | /* (void *)0 handled above */ | |
1065 | if (sflag) | 1066 | if (sflag) | |
1066 | /* ANSI C forbids conversion of %s to %s, op %s */ | 1067 | /* ANSI C forbids conversion of %s to %s, op %s */ | |
1067 | warning(305, "function pointer", "'void *'", | 1068 | warning(305, "function pointer", "'void *'", | |
1068 | mp->m_name); | 1069 | mp->m_name); | |
1069 | return; | 1070 | return; | |
1070 | } | 1071 | } | |
1071 | 1072 | |||
1072 | if (eqptrtype(lstp, rstp, true)) | 1073 | if (eqptrtype(lstp, rstp, true)) | |
1073 | return; | 1074 | return; | |
1074 | if (!eqtype(lstp, rstp, true, false, NULL)) | 1075 | if (!eqtype(lstp, rstp, true, false, NULL)) | |
1075 | warn_incompatible_pointers(mp, ltp, rtp); | 1076 | warn_incompatible_pointers(mp, ltp, rtp); | |
1076 | } | 1077 | } | |
1077 | 1078 | |||
1078 | static bool | 1079 | static bool | |
1079 | typeok_colon(const mod_t *mp, | 1080 | typeok_colon(const mod_t *mp, | |
1080 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | 1081 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | |
1081 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | 1082 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | |
1082 | { | 1083 | { | |
1083 | 1084 | |||
1084 | if (is_arithmetic(lt) && is_arithmetic(rt)) | 1085 | if (is_arithmetic(lt) && is_arithmetic(rt)) | |
1085 | return true; | 1086 | return true; | |
1086 | if (lt == BOOL && rt == BOOL) | 1087 | if (lt == BOOL && rt == BOOL) | |
1087 | return true; | 1088 | return true; | |
1088 | 1089 | |||
1089 | if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) | 1090 | if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) | |
1090 | return true; | 1091 | return true; | |
1091 | if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) | 1092 | if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) | |
1092 | return true; | 1093 | return true; | |
1093 | 1094 | |||
1094 | if (lt == PTR && is_null_pointer(rn)) | 1095 | if (lt == PTR && is_null_pointer(rn)) | |
1095 | return true; | 1096 | return true; | |
1096 | if (rt == PTR && is_null_pointer(ln)) | 1097 | if (rt == PTR && is_null_pointer(ln)) | |
1097 | return true; | 1098 | return true; | |
1098 | 1099 | |||
1099 | if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { | 1100 | if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { | |
1100 | const char *lx = lt == PTR ? "pointer" : "integer"; | 1101 | const char *lx = lt == PTR ? "pointer" : "integer"; | |
1101 | const char *rx = rt == PTR ? "pointer" : "integer"; | 1102 | const char *rx = rt == PTR ? "pointer" : "integer"; | |
1102 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ | 1103 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ | |
1103 | warning(123, lx, type_name(ltp), | 1104 | warning(123, lx, type_name(ltp), | |
1104 | rx, type_name(rtp), mp->m_name); | 1105 | rx, type_name(rtp), mp->m_name); | |
1105 | return true; | 1106 | return true; | |
1106 | } | 1107 | } | |
1107 | 1108 | |||
1108 | if (lt == VOID || rt == VOID) { | 1109 | if (lt == VOID || rt == VOID) { | |
1109 | if (lt != VOID || rt != VOID) | 1110 | if (lt != VOID || rt != VOID) | |
1110 | /* incompatible types '%s' and '%s' in conditional */ | 1111 | /* incompatible types '%s' and '%s' in conditional */ | |
1111 | warning(126, type_name(ltp), type_name(rtp)); | 1112 | warning(126, type_name(ltp), type_name(rtp)); | |
1112 | return true; | 1113 | return true; | |
1113 | } | 1114 | } | |
1114 | 1115 | |||
1115 | if (lt == PTR && rt == PTR) { | 1116 | if (lt == PTR && rt == PTR) { | |
1116 | typeok_colon_pointer(mp, ltp, rtp); | 1117 | typeok_colon_pointer(mp, ltp, rtp); | |
1117 | return true; | 1118 | return true; | |
1118 | } | 1119 | } | |
1119 | 1120 | |||
1120 | /* incompatible types '%s' and '%s' in conditional */ | 1121 | /* incompatible types '%s' and '%s' in conditional */ | |
1121 | error(126, type_name(ltp), type_name(rtp)); | 1122 | error(126, type_name(ltp), type_name(rtp)); | |
1122 | return false; | 1123 | return false; | |
1123 | } | 1124 | } | |
1124 | 1125 | |||
1125 | static bool | 1126 | static bool | |
1126 | typeok_assign(op_t op, const tnode_t *ln, const type_t *ltp, tspec_t lt) | 1127 | typeok_assign(op_t op, const tnode_t *ln, const type_t *ltp, tspec_t lt) | |
1127 | { | 1128 | { | |
1128 | if (op == RETURN || op == INIT || op == FARG) | 1129 | if (op == RETURN || op == INIT || op == FARG) | |
1129 | return true; | 1130 | return true; | |
1130 | 1131 | |||
1131 | if (!ln->tn_lvalue) { | 1132 | if (!ln->tn_lvalue) { | |
1132 | if (ln->tn_op == CVT && ln->tn_cast && | 1133 | if (ln->tn_op == CVT && ln->tn_cast && | |
1133 | ln->tn_left->tn_op == LOAD) { | 1134 | ln->tn_left->tn_op == LOAD) { | |
1134 | /* a cast does not yield an lvalue */ | 1135 | /* a cast does not yield an lvalue */ | |
1135 | error(163); | 1136 | error(163); | |
1136 | } | 1137 | } | |
1137 | /* %soperand of '%s' must be lvalue */ | 1138 | /* %soperand of '%s' must be lvalue */ | |
1138 | error(114, "left ", op_name(op)); | 1139 | error(114, "left ", op_name(op)); | |
1139 | return false; | 1140 | return false; | |
1140 | } else if (ltp->t_const || ((lt == STRUCT || lt == UNION) && | 1141 | } else if (ltp->t_const || ((lt == STRUCT || lt == UNION) && | |
1141 | has_constant_member(ltp))) { | 1142 | has_constant_member(ltp))) { | |
1142 | if (!tflag) | 1143 | if (!tflag) | |
1143 | /* %soperand of '%s' must be modifiable lvalue */ | 1144 | /* %soperand of '%s' must be modifiable lvalue */ | |
1144 | warning(115, "left ", op_name(op)); | 1145 | warning(115, "left ", op_name(op)); | |
1145 | } | 1146 | } | |
1146 | return true; | 1147 | return true; | |
1147 | } | 1148 | } | |
1148 | 1149 | |||
1149 | /* Check the types using the information from modtab[]. */ | 1150 | /* Check the types using the information from modtab[]. */ | |
1150 | static bool | 1151 | static bool | |
1151 | typeok_scalar(op_t op, const mod_t *mp, | 1152 | typeok_scalar(op_t op, const mod_t *mp, | |
1152 | const type_t *ltp, tspec_t lt, | 1153 | const type_t *ltp, tspec_t lt, | |
1153 | const type_t *rtp, tspec_t rt) | 1154 | const type_t *rtp, tspec_t rt) | |
1154 | { | 1155 | { | |
1155 | if (mp->m_takes_bool && lt == BOOL && rt == BOOL) | 1156 | if (mp->m_takes_bool && lt == BOOL && rt == BOOL) | |
1156 | return true; | 1157 | return true; | |
1157 | if (mp->m_requires_integer) { | 1158 | if (mp->m_requires_integer) { | |
1158 | if (!is_integer(lt) || (mp->m_binary && !is_integer(rt))) { | 1159 | if (!is_integer(lt) || (mp->m_binary && !is_integer(rt))) { | |
1159 | warn_incompatible_types(op, ltp, lt, rtp, rt); | 1160 | warn_incompatible_types(op, ltp, lt, rtp, rt); | |
1160 | return false; | 1161 | return false; | |
1161 | } | 1162 | } | |
1162 | } else if (mp->m_requires_integer_or_complex) { | 1163 | } else if (mp->m_requires_integer_or_complex) { | |
1163 | if ((!is_integer(lt) && !is_complex(lt)) || | 1164 | if ((!is_integer(lt) && !is_complex(lt)) || | |
1164 | (mp->m_binary && (!is_integer(rt) && !is_complex(rt)))) { | 1165 | (mp->m_binary && (!is_integer(rt) && !is_complex(rt)))) { | |
1165 | warn_incompatible_types(op, ltp, lt, rtp, rt); | 1166 | warn_incompatible_types(op, ltp, lt, rtp, rt); | |
1166 | return false; | 1167 | return false; | |
1167 | } | 1168 | } | |
1168 | } else if (mp->m_requires_scalar) { | 1169 | } else if (mp->m_requires_scalar) { | |
1169 | if (!is_scalar(lt) || (mp->m_binary && !is_scalar(rt))) { | 1170 | if (!is_scalar(lt) || (mp->m_binary && !is_scalar(rt))) { | |
1170 | warn_incompatible_types(op, ltp, lt, rtp, rt); | 1171 | warn_incompatible_types(op, ltp, lt, rtp, rt); | |
1171 | return false; | 1172 | return false; | |
1172 | } | 1173 | } | |
1173 | } else if (mp->m_requires_arith) { | 1174 | } else if (mp->m_requires_arith) { | |
1174 | if (!is_arithmetic(lt) || | 1175 | if (!is_arithmetic(lt) || | |
1175 | (mp->m_binary && !is_arithmetic(rt))) { | 1176 | (mp->m_binary && !is_arithmetic(rt))) { | |
1176 | warn_incompatible_types(op, ltp, lt, rtp, rt); | 1177 | warn_incompatible_types(op, ltp, lt, rtp, rt); | |
1177 | return false; | 1178 | return false; | |
1178 | } | 1179 | } | |
1179 | } | 1180 | } | |
1180 | return true; | 1181 | return true; | |
1181 | } | 1182 | } | |
1182 | 1183 | |||
1183 | /* | 1184 | /* | |
1184 | * Check the types for specific operators and type combinations. | 1185 | * Check the types for specific operators and type combinations. | |
1185 | * | 1186 | * | |
1186 | * At this point, the operands already conform to the type requirements of | 1187 | * At this point, the operands already conform to the type requirements of | |
1187 | * the operator, such as being integer, floating or scalar. | 1188 | * the operator, such as being integer, floating or scalar. | |
1188 | */ | 1189 | */ | |
1189 | static bool | 1190 | static bool | |
1190 | typeok_op(op_t op, const mod_t *mp, int arg, | 1191 | typeok_op(op_t op, const mod_t *mp, int arg, | |
1191 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | 1192 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | |
1192 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | 1193 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | |
1193 | { | 1194 | { | |
1194 | switch (op) { | 1195 | switch (op) { | |
1195 | case ARROW: | 1196 | case ARROW: | |
1196 | return typeok_arrow(lt); | 1197 | return typeok_arrow(lt); | |
1197 | case POINT: | 1198 | case POINT: | |
1198 | return typeok_point(ln, ltp, lt); | 1199 | return typeok_point(ln, ltp, lt); | |
1199 | case INCBEF: | 1200 | case INCBEF: | |
1200 | case DECBEF: | 1201 | case DECBEF: | |
1201 | case INCAFT: | 1202 | case INCAFT: | |
1202 | case DECAFT: | 1203 | case DECAFT: | |
1203 | return typeok_incdec(op, ln, ltp); | 1204 | return typeok_incdec(op, ln, ltp); | |
1204 | case INDIR: | 1205 | case INDIR: | |
1205 | return typeok_indir(lt); | 1206 | return typeok_indir(lt); | |
1206 | case ADDR: | 1207 | case ADDR: | |
1207 | return typeok_address(mp, ln, ltp, lt); | 1208 | return typeok_address(mp, ln, ltp, lt); | |
1208 | case PLUS: | 1209 | case PLUS: | |
1209 | return typeok_plus(op, ltp, lt, rtp, rt); | 1210 | return typeok_plus(op, ltp, lt, rtp, rt); | |
1210 | case MINUS: | 1211 | case MINUS: | |
1211 | return typeok_minus(op, ltp, lt, rtp, rt); | 1212 | return typeok_minus(op, ltp, lt, rtp, rt); | |
1212 | case SHL: | 1213 | case SHL: | |
1213 | typeok_shl(mp, lt, rt); | 1214 | typeok_shl(mp, lt, rt); | |
1214 | goto shift; | 1215 | goto shift; | |
1215 | case SHR: | 1216 | case SHR: | |
1216 | typeok_shr(mp, ln, lt, rn, rt); | 1217 | typeok_shr(mp, ln, lt, rn, rt); | |
1217 | shift: | 1218 | shift: | |
1218 | typeok_shift(lt, rn, rt); | 1219 | typeok_shift(lt, rn, rt); | |
1219 | break; | 1220 | break; | |
1220 | case LT: | 1221 | case LT: | |
1221 | case LE: | 1222 | case LE: | |
1222 | case GT: | 1223 | case GT: | |
1223 | case GE: | 1224 | case GE: | |
1224 | compare: | 1225 | compare: | |
1225 | return typeok_compare(op, ln, ltp, lt, rn, rtp, rt); | 1226 | return typeok_compare(op, ln, ltp, lt, rn, rtp, rt); | |
1226 | case EQ: | 1227 | case EQ: | |
1227 | case NE: | 1228 | case NE: | |
1228 | if (is_typeok_eq(ln, lt, rn, rt)) | 1229 | if (is_typeok_eq(ln, lt, rn, rt)) | |
1229 | break; | 1230 | break; | |
1230 | goto compare; | 1231 | goto compare; | |
1231 | case QUEST: | 1232 | case QUEST: | |
1232 | return typeok_quest(lt, rn); | 1233 | return typeok_quest(lt, rn); | |
1233 | case COLON: | 1234 | case COLON: | |
1234 | return typeok_colon(mp, ln, ltp, lt, rn, rtp, rt); | 1235 | return typeok_colon(mp, ln, ltp, lt, rn, rtp, rt); | |
1235 | case ASSIGN: | 1236 | case ASSIGN: | |
1236 | case INIT: | 1237 | case INIT: | |
1237 | case FARG: | 1238 | case FARG: | |
1238 | case RETURN: | 1239 | case RETURN: | |
1239 | if (!check_assign_types_compatible(op, arg, ln, rn)) | 1240 | if (!check_assign_types_compatible(op, arg, ln, rn)) | |
1240 | return false; | 1241 | return false; | |
1241 | goto assign; | 1242 | goto assign; | |
1242 | case MULASS: | 1243 | case MULASS: | |
1243 | case DIVASS: | 1244 | case DIVASS: | |
1244 | case MODASS: | 1245 | case MODASS: | |
1245 | goto assign; | 1246 | goto assign; | |
1246 | case ADDASS: | 1247 | case ADDASS: | |
1247 | case SUBASS: | 1248 | case SUBASS: | |
1248 | if ((lt == PTR && !is_integer(rt)) || rt == PTR) { | 1249 | if ((lt == PTR && !is_integer(rt)) || rt == PTR) { | |
1249 | warn_incompatible_types(op, ltp, lt, rtp, rt); | 1250 | warn_incompatible_types(op, ltp, lt, rtp, rt); | |
1250 | return false; | 1251 | return false; | |
1251 | } | 1252 | } | |
1252 | goto assign; | 1253 | goto assign; | |
1253 | case SHLASS: | 1254 | case SHLASS: | |
1254 | goto assign; | 1255 | goto assign; | |
1255 | case SHRASS: | 1256 | case SHRASS: | |
1256 | if (pflag && !is_uinteger(lt) && !(tflag && is_uinteger(rt))) { | 1257 | if (pflag && !is_uinteger(lt) && !(tflag && is_uinteger(rt))) { | |
1257 | /* bitwise '%s' on signed value possibly nonportable */ | 1258 | /* bitwise '%s' on signed value possibly nonportable */ | |
1258 | warning(117, mp->m_name); | 1259 | warning(117, mp->m_name); | |
1259 | } | 1260 | } | |
1260 | goto assign; | 1261 | goto assign; | |
1261 | case ANDASS: | 1262 | case ANDASS: | |
1262 | case XORASS: | 1263 | case XORASS: | |
1263 | case ORASS: | 1264 | case ORASS: | |
1264 | assign: | 1265 | assign: | |
1265 | return typeok_assign(op, ln, ltp, lt); | 1266 | return typeok_assign(op, ln, ltp, lt); | |
1266 | case COMMA: | 1267 | case COMMA: | |
1267 | if (!modtab[ln->tn_op].m_has_side_effect) | 1268 | if (!modtab[ln->tn_op].m_has_side_effect) | |
1268 | check_null_effect(ln); | 1269 | check_null_effect(ln); | |
1269 | break; | 1270 | break; | |
1270 | default: | 1271 | default: | |
1271 | break; | 1272 | break; | |
1272 | } | 1273 | } | |
1273 | return true; | 1274 | return true; | |
1274 | } | 1275 | } | |
1275 | 1276 | |||
1276 | static void | 1277 | static void | |
1277 | typeok_enum(op_t op, const mod_t *mp, int arg, | 1278 | typeok_enum(op_t op, const mod_t *mp, int arg, | |
1278 | const tnode_t *ln, const type_t *ltp, | 1279 | const tnode_t *ln, const type_t *ltp, | |
1279 | const tnode_t *rn, const type_t *rtp) | 1280 | const tnode_t *rn, const type_t *rtp) | |
1280 | { | 1281 | { | |
1281 | if (mp->m_bad_on_enum && | 1282 | if (mp->m_bad_on_enum && | |
1282 | (ltp->t_is_enum || (mp->m_binary && rtp->t_is_enum))) { | 1283 | (ltp->t_is_enum || (mp->m_binary && rtp->t_is_enum))) { | |
1283 | check_bad_enum_operation(op, ln, rn); | 1284 | check_bad_enum_operation(op, ln, rn); | |
1284 | } else if (mp->m_valid_on_enum && | 1285 | } else if (mp->m_valid_on_enum && | |
1285 | (ltp->t_is_enum && rtp != NULL && rtp->t_is_enum)) { | 1286 | (ltp->t_is_enum && rtp != NULL && rtp->t_is_enum)) { | |
1286 | check_enum_type_mismatch(op, arg, ln, rn); | 1287 | check_enum_type_mismatch(op, arg, ln, rn); | |
1287 | } else if (mp->m_valid_on_enum && | 1288 | } else if (mp->m_valid_on_enum && | |
1288 | (ltp->t_is_enum || (rtp != NULL && rtp->t_is_enum))) { | 1289 | (ltp->t_is_enum || (rtp != NULL && rtp->t_is_enum))) { | |
1289 | check_enum_int_mismatch(op, arg, ln, rn); | 1290 | check_enum_int_mismatch(op, arg, ln, rn); | |
1290 | } | 1291 | } | |
1291 | } | 1292 | } | |
1292 | 1293 | |||
1293 | /* Perform most type checks. Return whether the types are ok. */ | 1294 | /* Perform most type checks. Return whether the types are ok. */ | |
1294 | bool | 1295 | bool | |
1295 | typeok(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) | 1296 | typeok(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) | |
1296 | { | 1297 | { | |
1297 | const mod_t *mp; | 1298 | const mod_t *mp; | |
1298 | tspec_t lt, rt; | 1299 | tspec_t lt, rt; | |
1299 | type_t *ltp, *rtp; | 1300 | type_t *ltp, *rtp; | |
1300 | 1301 | |||
1301 | mp = &modtab[op]; | 1302 | mp = &modtab[op]; | |
1302 | 1303 | |||
1303 | lint_assert((ltp = ln->tn_type) != NULL); | 1304 | lint_assert((ltp = ln->tn_type) != NULL); | |
1304 | lt = ltp->t_tspec; | 1305 | lt = ltp->t_tspec; | |
1305 | 1306 | |||
1306 | if (mp->m_binary) { | 1307 | if (mp->m_binary) { | |
1307 | lint_assert((rtp = rn->tn_type) != NULL); | 1308 | lint_assert((rtp = rn->tn_type) != NULL); | |
1308 | rt = rtp->t_tspec; | 1309 | rt = rtp->t_tspec; | |
1309 | } else { | 1310 | } else { | |
1310 | rtp = NULL; | 1311 | rtp = NULL; | |
1311 | rt = NOTSPEC; | 1312 | rt = NOTSPEC; | |
1312 | } | 1313 | } | |
1313 | 1314 | |||
1314 | if (Tflag && !typeok_scalar_strict_bool(op, mp, arg, ln, rn)) | 1315 | if (Tflag && !typeok_scalar_strict_bool(op, mp, arg, ln, rn)) | |
1315 | return false; | 1316 | return false; | |
1316 | if (!typeok_scalar(op, mp, ltp, lt, rtp, rt)) | 1317 | if (!typeok_scalar(op, mp, ltp, lt, rtp, rt)) | |
1317 | return false; | 1318 | return false; | |
1318 | 1319 | |||
1319 | if (!typeok_op(op, mp, arg, ln, ltp, lt, rn, rtp, rt)) | 1320 | if (!typeok_op(op, mp, arg, ln, ltp, lt, rn, rtp, rt)) | |
1320 | return false; | 1321 | return false; | |
1321 | 1322 | |||
1322 | typeok_enum(op, mp, arg, ln, ltp, rn, rtp); | 1323 | typeok_enum(op, mp, arg, ln, ltp, rn, rtp); | |
1323 | return true; | 1324 | return true; | |
1324 | } | 1325 | } | |
1325 | 1326 | |||
1326 | static void | 1327 | static void | |
1327 | check_pointer_comparison(op_t op, const tnode_t *ln, const tnode_t *rn) | 1328 | check_pointer_comparison(op_t op, const tnode_t *ln, const tnode_t *rn) | |
1328 | { | 1329 | { | |
1329 | type_t *ltp, *rtp; | 1330 | type_t *ltp, *rtp; | |
1330 | tspec_t lst, rst; | 1331 | tspec_t lst, rst; | |
1331 | const char *lsts, *rsts; | 1332 | const char *lsts, *rsts; | |
1332 | 1333 | |||
1333 | lst = (ltp = ln->tn_type)->t_subt->t_tspec; | 1334 | lst = (ltp = ln->tn_type)->t_subt->t_tspec; | |
1334 | rst = (rtp = rn->tn_type)->t_subt->t_tspec; | 1335 | rst = (rtp = rn->tn_type)->t_subt->t_tspec; | |
1335 | 1336 | |||
1336 | if (lst == VOID || rst == VOID) { | 1337 | if (lst == VOID || rst == VOID) { | |
1337 | if (sflag && (lst == FUNC || rst == FUNC)) { | 1338 | if (sflag && (lst == FUNC || rst == FUNC)) { | |
1338 | /* (void *)0 already handled in typeok() */ | 1339 | /* (void *)0 already handled in typeok() */ | |
1339 | *(lst == FUNC ? &lsts : &rsts) = "function pointer"; | 1340 | *(lst == FUNC ? &lsts : &rsts) = "function pointer"; | |
1340 | *(lst == VOID ? &lsts : &rsts) = "'void *'"; | 1341 | *(lst == VOID ? &lsts : &rsts) = "'void *'"; | |
1341 | /* ANSI C forbids comparison of %s with %s */ | 1342 | /* ANSI C forbids comparison of %s with %s */ | |
1342 | warning(274, lsts, rsts); | 1343 | warning(274, lsts, rsts); | |
1343 | } | 1344 | } | |
1344 | return; | 1345 | return; | |
1345 | } | 1346 | } | |
1346 | 1347 | |||
1347 | if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) { | 1348 | if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) { | |
1348 | warn_incompatible_pointers(&modtab[op], ltp, rtp); | 1349 | warn_incompatible_pointers(&modtab[op], ltp, rtp); | |
1349 | return; | 1350 | return; | |
1350 | } | 1351 | } | |
1351 | 1352 | |||
1352 | if (lst == FUNC && rst == FUNC) { | 1353 | if (lst == FUNC && rst == FUNC) { | |
1353 | if (sflag && op != EQ && op != NE) | 1354 | if (sflag && op != EQ && op != NE) | |
1354 | /* ANSI C forbids ordered comparisons of ... */ | 1355 | /* ANSI C forbids ordered comparisons of ... */ | |
1355 | warning(125); | 1356 | warning(125); | |
1356 | } | 1357 | } | |
1357 | } | 1358 | } | |
1358 | 1359 | |||
1359 | static bool | 1360 | static bool | |
1360 | is_direct_function_call(const tnode_t *tn, const char **out_name) | 1361 | is_direct_function_call(const tnode_t *tn, const char **out_name) | |
1361 | { | 1362 | { | |
1362 | 1363 | |||
1363 | if (!(tn->tn_op == CALL && | 1364 | if (!(tn->tn_op == CALL && | |
1364 | tn->tn_left->tn_op == ADDR && | 1365 | tn->tn_left->tn_op == ADDR && | |
1365 | tn->tn_left->tn_left->tn_op == NAME)) | 1366 | tn->tn_left->tn_left->tn_op == NAME)) | |
1366 | return false; | 1367 | return false; | |
1367 | 1368 | |||
1368 | *out_name = tn->tn_left->tn_left->tn_sym->s_name; | 1369 | *out_name = tn->tn_left->tn_left->tn_sym->s_name; | |
1369 | return true; | 1370 | return true; | |
1370 | } | 1371 | } | |
1371 | 1372 | |||
1372 | static bool | 1373 | static bool | |
1373 | is_unconst_function(const char *name) | 1374 | is_unconst_function(const char *name) | |
1374 | { | 1375 | { | |
1375 | 1376 | |||
1376 | return strcmp(name, "memchr") == 0 || | 1377 | return strcmp(name, "memchr") == 0 || | |
1377 | strcmp(name, "strchr") == 0 || | 1378 | strcmp(name, "strchr") == 0 || | |
1378 | strcmp(name, "strpbrk") == 0 || | 1379 | strcmp(name, "strpbrk") == 0 || | |
1379 | strcmp(name, "strrchr") == 0 || | 1380 | strcmp(name, "strrchr") == 0 || | |
1380 | strcmp(name, "strstr") == 0; | 1381 | strcmp(name, "strstr") == 0; | |
1381 | } | 1382 | } | |
1382 | 1383 | |||
1383 | static bool | 1384 | static bool | |
1384 | is_const_char_pointer(const tnode_t *tn) | 1385 | is_const_char_pointer(const tnode_t *tn) | |
1385 | { | 1386 | { | |
1386 | const type_t *tp; | 1387 | const type_t *tp; | |
1387 | 1388 | |||
1388 | /* | 1389 | /* | |
1389 | * For traditional reasons, C99 6.4.5p5 defines that string literals | 1390 | * For traditional reasons, C99 6.4.5p5 defines that string literals | |
1390 | * have type 'char[]'. They are often implicitly converted to | 1391 | * have type 'char[]'. They are often implicitly converted to | |
1391 | * 'char *', for example when they are passed as function arguments. | 1392 | * 'char *', for example when they are passed as function arguments. | |
1392 | * | 1393 | * | |
1393 | * C99 6.4.5p6 further defines that modifying a string that is | 1394 | * C99 6.4.5p6 further defines that modifying a string that is | |
1394 | * constructed from a string literal invokes undefined behavior. | 1395 | * constructed from a string literal invokes undefined behavior. | |
1395 | * | 1396 | * | |
1396 | * Out of these reasons, string literals are treated as 'effectively | 1397 | * Out of these reasons, string literals are treated as 'effectively | |
1397 | * const' here. | 1398 | * const' here. | |
1398 | */ | 1399 | */ | |
1399 | if (tn->tn_op == CVT && | 1400 | if (tn->tn_op == CVT && | |
1400 | tn->tn_left->tn_op == ADDR && | 1401 | tn->tn_left->tn_op == ADDR && | |
1401 | tn->tn_left->tn_left->tn_op == STRING) | 1402 | tn->tn_left->tn_left->tn_op == STRING) | |
1402 | return true; | 1403 | return true; |