| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: decl.c,v 1.363 2023/07/28 21:50:03 rillig Exp $ */ | | 1 | /* $NetBSD: decl.c,v 1.364 2023/07/29 07:03:19 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 |
| @@ -28,69 +28,51 @@ | | | @@ -28,69 +28,51 @@ |
28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #if HAVE_NBTOOL_CONFIG_H | | 35 | #if HAVE_NBTOOL_CONFIG_H |
36 | #include "nbtool_config.h" | | 36 | #include "nbtool_config.h" |
37 | #endif | | 37 | #endif |
38 | | | 38 | |
39 | #include <sys/cdefs.h> | | 39 | #include <sys/cdefs.h> |
40 | #if defined(__RCSID) | | 40 | #if defined(__RCSID) |
41 | __RCSID("$NetBSD: decl.c,v 1.363 2023/07/28 21:50:03 rillig Exp $"); | | 41 | __RCSID("$NetBSD: decl.c,v 1.364 2023/07/29 07:03:19 rillig Exp $"); |
42 | #endif | | 42 | #endif |
43 | | | 43 | |
44 | #include <sys/param.h> | | 44 | #include <sys/param.h> |
45 | #include <limits.h> | | 45 | #include <limits.h> |
46 | #include <stdlib.h> | | 46 | #include <stdlib.h> |
47 | #include <string.h> | | 47 | #include <string.h> |
48 | | | 48 | |
49 | #include "lint1.h" | | 49 | #include "lint1.h" |
50 | | | 50 | |
51 | const char unnamed[] = "<unnamed>"; | | 51 | const char unnamed[] = "<unnamed>"; |
52 | | | 52 | |
53 | /* shared type structures for arithmetic types and void */ | | 53 | /* shared type structures for arithmetic types and void */ |
54 | static type_t typetab[NTSPEC]; | | 54 | static type_t typetab[NTSPEC]; |
55 | | | 55 | |
56 | /* value of next enumerator during declaration of enum types */ | | 56 | /* value of next enumerator during declaration of enum types */ |
57 | int enumval; | | 57 | int enumval; |
58 | | | 58 | |
59 | /* | | 59 | /* |
60 | * Points to the innermost element of a stack that contains information about | | 60 | * Points to the innermost element of a stack that contains information about |
61 | * nested declarations, such as struct declarations, function prototypes, | | 61 | * nested declarations, such as struct declarations, function prototypes, |
62 | * local variables. | | 62 | * local variables. |
63 | */ | | 63 | */ |
64 | decl_level *dcs; | | 64 | decl_level *dcs; |
65 | | | 65 | |
66 | static type_t *typedef_error(type_t *, tspec_t); | | | |
67 | static void set_first_typedef(type_t *, sym_t *); | | | |
68 | static void dcs_align(unsigned int, unsigned int); | | | |
69 | static sym_t *new_tag(sym_t *, scl_t, bool, bool); | | | |
70 | static bool prototypes_compatible(const type_t *, const type_t *, bool *); | | | |
71 | static bool matches_no_arg_function(const type_t *, bool *); | | | |
72 | static bool check_old_style_definition(sym_t *, sym_t *); | | | |
73 | static bool check_prototype_declaration(sym_t *, sym_t *); | | | |
74 | static void check_prototype_parameters(sym_t *); | | | |
75 | static void old_style_function(sym_t *, sym_t *); | | | |
76 | static void declare_external_in_block(sym_t *); | | | |
77 | static bool check_init(sym_t *); | | | |
78 | static void check_argument_usage(bool, sym_t *); | | | |
79 | static void check_variable_usage(bool, sym_t *); | | | |
80 | static void check_label_usage(sym_t *); | | | |
81 | static void check_tag_usage(sym_t *); | | | |
82 | static void check_global_variable(const sym_t *); | | | |
83 | static void check_global_variable_size(const sym_t *); | | | |
84 | | | 66 | |
85 | /* | | 67 | /* |
86 | * initializes all global vars used in declarations | | 68 | * initializes all global vars used in declarations |
87 | */ | | 69 | */ |
88 | void | | 70 | void |
89 | initdecl(void) | | 71 | initdecl(void) |
90 | { | | 72 | { |
91 | | | 73 | |
92 | /* declaration stack */ | | 74 | /* declaration stack */ |
93 | dcs = xcalloc(1, sizeof(*dcs)); | | 75 | dcs = xcalloc(1, sizeof(*dcs)); |
94 | dcs->d_kind = DLK_EXTERN; | | 76 | dcs->d_kind = DLK_EXTERN; |
95 | dcs->d_last_dlsym = &dcs->d_first_dlsym; | | 77 | dcs->d_last_dlsym = &dcs->d_first_dlsym; |
96 | | | 78 | |
| @@ -223,26 +205,104 @@ dcs_add_storage_class(scl_t sc) | | | @@ -223,26 +205,104 @@ dcs_add_storage_class(scl_t sc) |
223 | | | 205 | |
224 | if (dcs->d_scl == NOSCL) | | 206 | if (dcs->d_scl == NOSCL) |
225 | dcs->d_scl = sc; | | 207 | dcs->d_scl = sc; |
226 | else if ((dcs->d_scl == EXTERN && sc == THREAD_LOCAL) | | 208 | else if ((dcs->d_scl == EXTERN && sc == THREAD_LOCAL) |
227 | || (dcs->d_scl == THREAD_LOCAL && sc == EXTERN)) | | 209 | || (dcs->d_scl == THREAD_LOCAL && sc == EXTERN)) |
228 | dcs->d_scl = EXTERN; /* ignore thread_local */ | | 210 | dcs->d_scl = EXTERN; /* ignore thread_local */ |
229 | else if ((dcs->d_scl == STATIC && sc == THREAD_LOCAL) | | 211 | else if ((dcs->d_scl == STATIC && sc == THREAD_LOCAL) |
230 | || (dcs->d_scl == THREAD_LOCAL && sc == STATIC)) | | 212 | || (dcs->d_scl == THREAD_LOCAL && sc == STATIC)) |
231 | dcs->d_scl = STATIC; /* ignore thread_local */ | | 213 | dcs->d_scl = STATIC; /* ignore thread_local */ |
232 | else | | 214 | else |
233 | dcs->d_multiple_storage_classes = true; | | 215 | dcs->d_multiple_storage_classes = true; |
234 | } | | 216 | } |
235 | | | 217 | |
| | | 218 | /* Merge the signedness into the abstract type. */ |
| | | 219 | static tspec_t |
| | | 220 | merge_signedness(tspec_t t, tspec_t s) |
| | | 221 | { |
| | | 222 | |
| | | 223 | if (s == SIGNED) |
| | | 224 | return t == CHAR ? SCHAR : t; |
| | | 225 | if (s != UNSIGN) |
| | | 226 | return t; |
| | | 227 | return t == CHAR ? UCHAR |
| | | 228 | : t == SHORT ? USHORT |
| | | 229 | : t == INT ? UINT |
| | | 230 | : t == LONG ? ULONG |
| | | 231 | : t == LLONG ? ULLONG |
| | | 232 | : t; |
| | | 233 | } |
| | | 234 | |
| | | 235 | /* |
| | | 236 | * Called if a list of declaration specifiers contains a typedef name |
| | | 237 | * and other specifiers (except struct, union, enum, typedef name). |
| | | 238 | */ |
| | | 239 | static type_t * |
| | | 240 | typedef_error(type_t *td, tspec_t t) |
| | | 241 | { |
| | | 242 | |
| | | 243 | tspec_t t2 = td->t_tspec; |
| | | 244 | |
| | | 245 | if ((t == SIGNED || t == UNSIGN) && |
| | | 246 | (t2 == CHAR || t2 == SHORT || t2 == INT || |
| | | 247 | t2 == LONG || t2 == LLONG)) { |
| | | 248 | if (allow_c90) |
| | | 249 | /* modifying typedef with '%s'; only qualifiers... */ |
| | | 250 | warning(5, tspec_name(t)); |
| | | 251 | td = block_dup_type(gettyp(merge_signedness(t2, t))); |
| | | 252 | td->t_typedef = true; |
| | | 253 | return td; |
| | | 254 | } |
| | | 255 | |
| | | 256 | if (t == SHORT && (t2 == INT || t2 == UINT)) { |
| | | 257 | /* modifying typedef with '%s'; only qualifiers allowed */ |
| | | 258 | warning(5, "short"); |
| | | 259 | td = block_dup_type(gettyp(t2 == INT ? SHORT : USHORT)); |
| | | 260 | td->t_typedef = true; |
| | | 261 | return td; |
| | | 262 | } |
| | | 263 | |
| | | 264 | if (t != LONG) |
| | | 265 | goto invalid; |
| | | 266 | |
| | | 267 | if (t2 == INT) |
| | | 268 | td = gettyp(LONG); |
| | | 269 | else if (t2 == UINT) |
| | | 270 | td = gettyp(ULONG); |
| | | 271 | else if (t2 == LONG) |
| | | 272 | td = gettyp(LLONG); |
| | | 273 | else if (t2 == ULONG) |
| | | 274 | td = gettyp(ULLONG); |
| | | 275 | else if (t2 == FLOAT) |
| | | 276 | td = gettyp(DOUBLE); |
| | | 277 | else if (t2 == DOUBLE) |
| | | 278 | td = gettyp(LDOUBLE); |
| | | 279 | else if (t2 == DCOMPLEX) |
| | | 280 | td = gettyp(LCOMPLEX); |
| | | 281 | else |
| | | 282 | goto invalid; |
| | | 283 | |
| | | 284 | /* modifying typedef with '%s'; only qualifiers allowed */ |
| | | 285 | warning(5, "long"); |
| | | 286 | td = block_dup_type(td); |
| | | 287 | td->t_typedef = true; |
| | | 288 | return td; |
| | | 289 | |
| | | 290 | invalid: |
| | | 291 | /* Anything else is not accepted. */ |
| | | 292 | dcs->d_invalid_type_combination = true; |
| | | 293 | return td; |
| | | 294 | } |
| | | 295 | |
236 | /* | | 296 | /* |
237 | * Remember the type, modifier or typedef name returned by the parser in the | | 297 | * Remember the type, modifier or typedef name returned by the parser in the |
238 | * top element of the declaration stack. This information is used in | | 298 | * top element of the declaration stack. This information is used in |
239 | * dcs_end_type to build the type used for all declarators in this declaration. | | 299 | * dcs_end_type to build the type used for all declarators in this declaration. |
240 | * | | 300 | * |
241 | * If tp->t_typedef is true, the type comes from a previously defined typename. | | 301 | * If tp->t_typedef is true, the type comes from a previously defined typename. |
242 | * Otherwise, it comes from a type specifier (int, long, ...) or a | | 302 | * Otherwise, it comes from a type specifier (int, long, ...) or a |
243 | * struct/union/enum tag. | | 303 | * struct/union/enum tag. |
244 | */ | | 304 | */ |
245 | void | | 305 | void |
246 | dcs_add_type(type_t *tp) | | 306 | dcs_add_type(type_t *tp) |
247 | { | | 307 | { |
248 | | | 308 | |
| @@ -334,104 +394,26 @@ dcs_add_type(type_t *tp) | | | @@ -334,104 +394,26 @@ dcs_add_type(type_t *tp) |
334 | if (dcs->d_abstract_type != NO_TSPEC) | | 394 | if (dcs->d_abstract_type != NO_TSPEC) |
335 | dcs->d_invalid_type_combination = true; | | 395 | dcs->d_invalid_type_combination = true; |
336 | dcs->d_abstract_type = t; | | 396 | dcs->d_abstract_type = t; |
337 | } | | 397 | } |
338 | } else if (t == PTR) { | | 398 | } else if (t == PTR) { |
339 | dcs->d_type = tp; | | 399 | dcs->d_type = tp; |
340 | } else { | | 400 | } else { |
341 | if (dcs->d_abstract_type != NO_TSPEC) | | 401 | if (dcs->d_abstract_type != NO_TSPEC) |
342 | dcs->d_invalid_type_combination = true; | | 402 | dcs->d_invalid_type_combination = true; |
343 | dcs->d_abstract_type = t; | | 403 | dcs->d_abstract_type = t; |
344 | } | | 404 | } |
345 | } | | 405 | } |
346 | | | 406 | |
347 | /* Merge the signedness into the abstract type. */ | | | |
348 | static tspec_t | | | |
349 | merge_signedness(tspec_t t, tspec_t s) | | | |
350 | { | | | |
351 | | | | |
352 | if (s == SIGNED) | | | |
353 | return t == CHAR ? SCHAR : t; | | | |
354 | if (s != UNSIGN) | | | |
355 | return t; | | | |
356 | return t == CHAR ? UCHAR | | | |
357 | : t == SHORT ? USHORT | | | |
358 | : t == INT ? UINT | | | |
359 | : t == LONG ? ULONG | | | |
360 | : t == LLONG ? ULLONG | | | |
361 | : t; | | | |
362 | } | | | |
363 | | | | |
364 | /* | | | |
365 | * Called if a list of declaration specifiers contains a typedef name | | | |
366 | * and other specifiers (except struct, union, enum, typedef name). | | | |
367 | */ | | | |
368 | static type_t * | | | |
369 | typedef_error(type_t *td, tspec_t t) | | | |
370 | { | | | |
371 | | | | |
372 | tspec_t t2 = td->t_tspec; | | | |
373 | | | | |
374 | if ((t == SIGNED || t == UNSIGN) && | | | |
375 | (t2 == CHAR || t2 == SHORT || t2 == INT || | | | |
376 | t2 == LONG || t2 == LLONG)) { | | | |
377 | if (allow_c90) | | | |
378 | /* modifying typedef with '%s'; only qualifiers... */ | | | |
379 | warning(5, tspec_name(t)); | | | |
380 | td = block_dup_type(gettyp(merge_signedness(t2, t))); | | | |
381 | td->t_typedef = true; | | | |
382 | return td; | | | |
383 | } | | | |
384 | | | | |
385 | if (t == SHORT && (t2 == INT || t2 == UINT)) { | | | |
386 | /* modifying typedef with '%s'; only qualifiers allowed */ | | | |
387 | warning(5, "short"); | | | |
388 | td = block_dup_type(gettyp(t2 == INT ? SHORT : USHORT)); | | | |
389 | td->t_typedef = true; | | | |
390 | return td; | | | |
391 | } | | | |
392 | | | | |
393 | if (t != LONG) | | | |
394 | goto invalid; | | | |
395 | | | | |
396 | if (t2 == INT) | | | |
397 | td = gettyp(LONG); | | | |
398 | else if (t2 == UINT) | | | |
399 | td = gettyp(ULONG); | | | |
400 | else if (t2 == LONG) | | | |
401 | td = gettyp(LLONG); | | | |
402 | else if (t2 == ULONG) | | | |
403 | td = gettyp(ULLONG); | | | |
404 | else if (t2 == FLOAT) | | | |
405 | td = gettyp(DOUBLE); | | | |
406 | else if (t2 == DOUBLE) | | | |
407 | td = gettyp(LDOUBLE); | | | |
408 | else if (t2 == DCOMPLEX) | | | |
409 | td = gettyp(LCOMPLEX); | | | |
410 | else | | | |
411 | goto invalid; | | | |
412 | | | | |
413 | /* modifying typedef with '%s'; only qualifiers allowed */ | | | |
414 | warning(5, "long"); | | | |
415 | td = block_dup_type(td); | | | |
416 | td->t_typedef = true; | | | |
417 | return td; | | | |
418 | | | | |
419 | invalid: | | | |
420 | /* Anything else is not accepted. */ | | | |
421 | dcs->d_invalid_type_combination = true; | | | |
422 | return td; | | | |
423 | } | | | |
424 | | | | |
425 | static void | | 407 | static void |
426 | set_first_typedef(type_t *tp, sym_t *sym) | | 408 | set_first_typedef(type_t *tp, sym_t *sym) |
427 | { | | 409 | { |
428 | | | 410 | |
429 | tspec_t t = tp->t_tspec; | | 411 | tspec_t t = tp->t_tspec; |
430 | if (is_struct_or_union(t) && tp->t_sou->sou_first_typedef == NULL) | | 412 | if (is_struct_or_union(t) && tp->t_sou->sou_first_typedef == NULL) |
431 | tp->t_sou->sou_first_typedef = sym; | | 413 | tp->t_sou->sou_first_typedef = sym; |
432 | if (t == ENUM && tp->t_enum->en_first_typedef == NULL) | | 414 | if (t == ENUM && tp->t_enum->en_first_typedef == NULL) |
433 | tp->t_enum->en_first_typedef = sym; | | 415 | tp->t_enum->en_first_typedef = sym; |
434 | } | | 416 | } |
435 | | | 417 | |
436 | static unsigned int | | 418 | static unsigned int |
437 | bit_fields_width(const sym_t **mem, bool *named) | | 419 | bit_fields_width(const sym_t **mem, bool *named) |
| @@ -1000,26 +982,41 @@ check_bit_field(sym_t *dsym, tspec_t *in | | | @@ -1000,26 +982,41 @@ check_bit_field(sym_t *dsym, tspec_t *in |
1000 | } else if (tp->t_bit_field_width == 0 && dsym->s_name != unnamed) { | | 982 | } else if (tp->t_bit_field_width == 0 && dsym->s_name != unnamed) { |
1001 | /* zero size bit-field */ | | 983 | /* zero size bit-field */ |
1002 | error(37); | | 984 | error(37); |
1003 | tp->t_bit_field_width = t_width; | | 985 | tp->t_bit_field_width = t_width; |
1004 | } | | 986 | } |
1005 | if (dsym->s_scl == UNION_MEMBER) { | | 987 | if (dsym->s_scl == UNION_MEMBER) { |
1006 | /* bit-field in union is very unusual */ | | 988 | /* bit-field in union is very unusual */ |
1007 | warning(41); | | 989 | warning(41); |
1008 | dsym->s_type->t_bitfield = false; | | 990 | dsym->s_type->t_bitfield = false; |
1009 | dsym->s_bitfield = false; | | 991 | dsym->s_bitfield = false; |
1010 | } | | 992 | } |
1011 | } | | 993 | } |
1012 | | | 994 | |
| | | 995 | /* Aligns the next structure element as required. */ |
| | | 996 | static void |
| | | 997 | dcs_align(unsigned int member_alignment, unsigned int bit_field_width) |
| | | 998 | { |
| | | 999 | |
| | | 1000 | if (member_alignment > dcs->d_sou_align_in_bits) |
| | | 1001 | dcs->d_sou_align_in_bits = member_alignment; |
| | | 1002 | |
| | | 1003 | unsigned int offset = (dcs->d_sou_size_in_bits + member_alignment - 1) |
| | | 1004 | & ~(member_alignment - 1); |
| | | 1005 | if (bit_field_width == 0 |
| | | 1006 | || dcs->d_sou_size_in_bits + bit_field_width > offset) |
| | | 1007 | dcs->d_sou_size_in_bits = offset; |
| | | 1008 | } |
| | | 1009 | |
1013 | /* Add a member to the struct or union type that is being built in 'dcs'. */ | | 1010 | /* Add a member to the struct or union type that is being built in 'dcs'. */ |
1014 | static void | | 1011 | static void |
1015 | dcs_add_member(sym_t *mem) | | 1012 | dcs_add_member(sym_t *mem) |
1016 | { | | 1013 | { |
1017 | type_t *tp = mem->s_type; | | 1014 | type_t *tp = mem->s_type; |
1018 | | | 1015 | |
1019 | unsigned int union_size = 0; | | 1016 | unsigned int union_size = 0; |
1020 | if (dcs->d_kind == DLK_UNION) { | | 1017 | if (dcs->d_kind == DLK_UNION) { |
1021 | union_size = dcs->d_sou_size_in_bits; | | 1018 | union_size = dcs->d_sou_size_in_bits; |
1022 | dcs->d_sou_size_in_bits = 0; | | 1019 | dcs->d_sou_size_in_bits = 0; |
1023 | } | | 1020 | } |
1024 | | | 1021 | |
1025 | if (mem->s_bitfield) { | | 1022 | if (mem->s_bitfield) { |
| @@ -1096,41 +1093,26 @@ declare_member(sym_t *dsym) | | | @@ -1096,41 +1093,26 @@ declare_member(sym_t *dsym) |
1096 | /* zero-sized array '%s' in struct is a C99 extension */ | | 1093 | /* zero-sized array '%s' in struct is a C99 extension */ |
1097 | c99ism(39, dsym->s_name); | | 1094 | c99ism(39, dsym->s_name); |
1098 | } | | 1095 | } |
1099 | | | 1096 | |
1100 | dcs_add_member(dsym); | | 1097 | dcs_add_member(dsym); |
1101 | | | 1098 | |
1102 | check_function_definition(dsym, false); | | 1099 | check_function_definition(dsym, false); |
1103 | | | 1100 | |
1104 | suppress_bitfieldtype = false; | | 1101 | suppress_bitfieldtype = false; |
1105 | | | 1102 | |
1106 | return dsym; | | 1103 | return dsym; |
1107 | } | | 1104 | } |
1108 | | | 1105 | |
1109 | /* Aligns the next structure element as required. */ | | | |
1110 | static void | | | |
1111 | dcs_align(unsigned int member_alignment, unsigned int bit_field_width) | | | |
1112 | { | | | |
1113 | | | | |
1114 | if (member_alignment > dcs->d_sou_align_in_bits) | | | |
1115 | dcs->d_sou_align_in_bits = member_alignment; | | | |
1116 | | | | |
1117 | unsigned int offset = (dcs->d_sou_size_in_bits + member_alignment - 1) | | | |
1118 | & ~(member_alignment - 1); | | | |
1119 | if (bit_field_width == 0 | | | |
1120 | || dcs->d_sou_size_in_bits + bit_field_width > offset) | | | |
1121 | dcs->d_sou_size_in_bits = offset; | | | |
1122 | } | | | |
1123 | | | | |
1124 | sym_t * | | 1106 | sym_t * |
1125 | set_bit_field_width(sym_t *dsym, int bit_field_width) | | 1107 | set_bit_field_width(sym_t *dsym, int bit_field_width) |
1126 | { | | 1108 | { |
1127 | | | 1109 | |
1128 | if (dsym == NULL) { | | 1110 | if (dsym == NULL) { |
1129 | dsym = block_zero_alloc(sizeof(*dsym), "sym"); | | 1111 | dsym = block_zero_alloc(sizeof(*dsym), "sym"); |
1130 | dsym->s_name = unnamed; | | 1112 | dsym->s_name = unnamed; |
1131 | dsym->s_kind = FMEMBER; | | 1113 | dsym->s_kind = FMEMBER; |
1132 | dsym->s_scl = STRUCT_MEMBER; | | 1114 | dsym->s_scl = STRUCT_MEMBER; |
1133 | dsym->s_type = gettyp(UINT); | | 1115 | dsym->s_type = gettyp(UINT); |
1134 | dsym->s_block_level = -1; | | 1116 | dsym->s_block_level = -1; |
1135 | } | | 1117 | } |
1136 | dsym->s_type = block_dup_type(dsym->s_type); | | 1118 | dsym->s_type = block_dup_type(dsym->s_type); |
| @@ -1279,26 +1261,74 @@ add_array(sym_t *decl, bool dim, int n) | | | @@ -1279,26 +1261,74 @@ add_array(sym_t *decl, bool dim, int n) |
1279 | | | 1261 | |
1280 | static type_t * | | 1262 | static type_t * |
1281 | block_derive_function(type_t *ret, bool proto, sym_t *args, bool vararg) | | 1263 | block_derive_function(type_t *ret, bool proto, sym_t *args, bool vararg) |
1282 | { | | 1264 | { |
1283 | | | 1265 | |
1284 | type_t *tp = block_derive_type(ret, FUNC); | | 1266 | type_t *tp = block_derive_type(ret, FUNC); |
1285 | tp->t_proto = proto; | | 1267 | tp->t_proto = proto; |
1286 | if (proto) | | 1268 | if (proto) |
1287 | tp->t_args = args; | | 1269 | tp->t_args = args; |
1288 | tp->t_vararg = vararg; | | 1270 | tp->t_vararg = vararg; |
1289 | return tp; | | 1271 | return tp; |
1290 | } | | 1272 | } |
1291 | | | 1273 | |
| | | 1274 | static void |
| | | 1275 | check_prototype_parameters(sym_t *args) |
| | | 1276 | { |
| | | 1277 | |
| | | 1278 | for (sym_t *sym = dcs->d_first_dlsym; |
| | | 1279 | sym != NULL; sym = sym->s_level_next) { |
| | | 1280 | scl_t sc = sym->s_scl; |
| | | 1281 | if (sc == STRUCT_TAG || sc == UNION_TAG || sc == ENUM_TAG) { |
| | | 1282 | /* dubious tag declaration '%s %s' */ |
| | | 1283 | warning(85, storage_class_name(sc), sym->s_name); |
| | | 1284 | } |
| | | 1285 | } |
| | | 1286 | |
| | | 1287 | for (sym_t *arg = args; arg != NULL; arg = arg->s_next) { |
| | | 1288 | if (arg->s_type->t_tspec == VOID && |
| | | 1289 | !(arg == args && arg->s_next == NULL)) { |
| | | 1290 | /* void must be sole parameter */ |
| | | 1291 | error(60); |
| | | 1292 | arg->s_type = gettyp(INT); |
| | | 1293 | } |
| | | 1294 | } |
| | | 1295 | } |
| | | 1296 | |
| | | 1297 | static void |
| | | 1298 | old_style_function(sym_t *decl, sym_t *args) |
| | | 1299 | { |
| | | 1300 | |
| | | 1301 | /* |
| | | 1302 | * Remember the list of parameters only if this really seems to be a |
| | | 1303 | * function definition. |
| | | 1304 | */ |
| | | 1305 | if (dcs->d_enclosing->d_kind == DLK_EXTERN && |
| | | 1306 | decl->s_type == dcs->d_enclosing->d_type) { |
| | | 1307 | /* |
| | | 1308 | * Assume that this becomes a function definition. If not, it |
| | | 1309 | * will be corrected in check_function_definition. |
| | | 1310 | */ |
| | | 1311 | if (args != NULL) { |
| | | 1312 | decl->s_osdef = true; |
| | | 1313 | decl->u.s_old_style_args = args; |
| | | 1314 | } |
| | | 1315 | } else { |
| | | 1316 | if (args != NULL) |
| | | 1317 | /* function prototype parameters must have types */ |
| | | 1318 | warning(62); |
| | | 1319 | } |
| | | 1320 | } |
| | | 1321 | |
1292 | sym_t * | | 1322 | sym_t * |
1293 | add_function(sym_t *decl, struct parameter_list params) | | 1323 | add_function(sym_t *decl, struct parameter_list params) |
1294 | { | | 1324 | { |
1295 | | | 1325 | |
1296 | debug_enter(); | | 1326 | debug_enter(); |
1297 | debug_dcs(true); | | 1327 | debug_dcs(true); |
1298 | debug_sym("decl: ", decl, "\n"); | | 1328 | debug_sym("decl: ", decl, "\n"); |
1299 | #ifdef DEBUG | | 1329 | #ifdef DEBUG |
1300 | for (const sym_t *arg = params.first; arg != NULL; arg = arg->s_next) | | 1330 | for (const sym_t *arg = params.first; arg != NULL; arg = arg->s_next) |
1301 | debug_sym("arg: ", arg, "\n"); | | 1331 | debug_sym("arg: ", arg, "\n"); |
1302 | #endif | | 1332 | #endif |
1303 | | | 1333 | |
1304 | if (params.prototype) { | | 1334 | if (params.prototype) { |
| @@ -1347,91 +1377,43 @@ add_function(sym_t *decl, struct paramet | | | @@ -1347,91 +1377,43 @@ add_function(sym_t *decl, struct paramet |
1347 | debug_leave(); | | 1377 | debug_leave(); |
1348 | return decl; /* see msg_347 */ | | 1378 | return decl; /* see msg_347 */ |
1349 | } | | 1379 | } |
1350 | | | 1380 | |
1351 | *tpp = block_derive_function(dcs->d_enclosing->d_type, | | 1381 | *tpp = block_derive_function(dcs->d_enclosing->d_type, |
1352 | params.prototype, params.first, params.vararg); | | 1382 | params.prototype, params.first, params.vararg); |
1353 | | | 1383 | |
1354 | debug_step("add_function: '%s'", type_name(decl->s_type)); | | 1384 | debug_step("add_function: '%s'", type_name(decl->s_type)); |
1355 | debug_dcs(true); | | 1385 | debug_dcs(true); |
1356 | debug_leave(); | | 1386 | debug_leave(); |
1357 | return decl; | | 1387 | return decl; |
1358 | } | | 1388 | } |
1359 | | | 1389 | |
1360 | static void | | 1390 | /* |
1361 | check_prototype_parameters(sym_t *args) | | 1391 | * In a function declaration, a list of identifiers (as opposed to a list of |
| | | 1392 | * types) is allowed only if it's also a function definition. |
| | | 1393 | */ |
| | | 1394 | void |
| | | 1395 | check_function_definition(sym_t *sym, bool msg) |
1362 | { | | 1396 | { |
1363 | | | 1397 | |
1364 | for (sym_t *sym = dcs->d_first_dlsym; | | 1398 | if (sym->s_osdef) { |
1365 | sym != NULL; sym = sym->s_level_next) { | | 1399 | if (msg) { |
1366 | scl_t sc = sym->s_scl; | | 1400 | /* incomplete or misplaced function definition */ |
1367 | if (sc == STRUCT_TAG || sc == UNION_TAG || sc == ENUM_TAG) { | | 1401 | error(22); |
1368 | /* dubious tag declaration '%s %s' */ | | | |
1369 | warning(85, storage_class_name(sc), sym->s_name); | | | |
1370 | } | | 1402 | } |
| | | 1403 | sym->s_osdef = false; |
| | | 1404 | sym->u.s_old_style_args = NULL; |
1371 | } | | 1405 | } |
1372 | | | 1406 | } |
1373 | for (sym_t *arg = args; arg != NULL; arg = arg->s_next) { | | | |
1374 | if (arg->s_type->t_tspec == VOID && | | | |
1375 | !(arg == args && arg->s_next == NULL)) { | | | |
1376 | /* void must be sole parameter */ | | | |
1377 | error(60); | | | |
1378 | arg->s_type = gettyp(INT); | | | |
1379 | } | | | |
1380 | } | | | |
1381 | } | | | |
1382 | | | | |
1383 | static void | | | |
1384 | old_style_function(sym_t *decl, sym_t *args) | | | |
1385 | { | | | |
1386 | | | | |
1387 | /* | | | |
1388 | * Remember the list of parameters only if this really seems to be a | | | |
1389 | * function definition. | | | |
1390 | */ | | | |
1391 | if (dcs->d_enclosing->d_kind == DLK_EXTERN && | | | |
1392 | decl->s_type == dcs->d_enclosing->d_type) { | | | |
1393 | /* | | | |
1394 | * Assume that this becomes a function definition. If not, it | | | |
1395 | * will be corrected in check_function_definition. | | | |
1396 | */ | | | |
1397 | if (args != NULL) { | | | |
1398 | decl->s_osdef = true; | | | |
1399 | decl->u.s_old_style_args = args; | | | |
1400 | } | | | |
1401 | } else { | | | |
1402 | if (args != NULL) | | | |
1403 | /* function prototype parameters must have types */ | | | |
1404 | warning(62); | | | |
1405 | } | | | |
1406 | } | | | |
1407 | | | | |
1408 | /* | | | |
1409 | * In a function declaration, a list of identifiers (as opposed to a list of | | | |
1410 | * types) is allowed only if it's also a function definition. | | | |
1411 | */ | | | |
1412 | void | | | |
1413 | check_function_definition(sym_t *sym, bool msg) | | | |
1414 | { | | | |
1415 | | | | |
1416 | if (sym->s_osdef) { | | | |
1417 | if (msg) { | | | |
1418 | /* incomplete or misplaced function definition */ | | | |
1419 | error(22); | | | |
1420 | } | | | |
1421 | sym->s_osdef = false; | | | |
1422 | sym->u.s_old_style_args = NULL; | | | |
1423 | } | | | |
1424 | } | | | |
1425 | | | 1407 | |
1426 | /* The symbol gets a storage class and a definedness. */ | | 1408 | /* The symbol gets a storage class and a definedness. */ |
1427 | sym_t * | | 1409 | sym_t * |
1428 | declarator_name(sym_t *sym) | | 1410 | declarator_name(sym_t *sym) |
1429 | { | | 1411 | { |
1430 | scl_t sc = NOSCL; | | 1412 | scl_t sc = NOSCL; |
1431 | | | 1413 | |
1432 | if (sym->s_scl == NOSCL) | | 1414 | if (sym->s_scl == NOSCL) |
1433 | dcs->d_redeclared_symbol = NULL; | | 1415 | dcs->d_redeclared_symbol = NULL; |
1434 | else if (sym->s_defarg) { | | 1416 | else if (sym->s_defarg) { |
1435 | sym->s_defarg = false; | | 1417 | sym->s_defarg = false; |
1436 | dcs->d_redeclared_symbol = NULL; | | 1418 | dcs->d_redeclared_symbol = NULL; |
1437 | } else { | | 1419 | } else { |
| @@ -1525,26 +1507,87 @@ old_style_function_parameter_name(sym_t | | | @@ -1525,26 +1507,87 @@ old_style_function_parameter_name(sym_t |
1525 | error(21, sym->s_name); | | 1507 | error(21, sym->s_name); |
1526 | lint_assert(sym->s_defarg); | | 1508 | lint_assert(sym->s_defarg); |
1527 | } | | 1509 | } |
1528 | sym = pushdown(sym); | | 1510 | sym = pushdown(sym); |
1529 | } | | 1511 | } |
1530 | sym->s_type = gettyp(INT); | | 1512 | sym->s_type = gettyp(INT); |
1531 | sym->s_scl = AUTO; | | 1513 | sym->s_scl = AUTO; |
1532 | sym->s_def = DEF; | | 1514 | sym->s_def = DEF; |
1533 | sym->s_defarg = sym->s_arg = true; | | 1515 | sym->s_defarg = sym->s_arg = true; |
1534 | return sym; | | 1516 | return sym; |
1535 | } | | 1517 | } |
1536 | | | 1518 | |
1537 | /*- | | 1519 | /*- |
| | | 1520 | * Checks all possible cases of tag redeclarations. |
| | | 1521 | * |
| | | 1522 | * decl whether T_LBRACE follows |
| | | 1523 | * semi whether T_SEMI follows |
| | | 1524 | */ |
| | | 1525 | static sym_t * |
| | | 1526 | new_tag(sym_t *tag, scl_t scl, bool decl, bool semi) |
| | | 1527 | { |
| | | 1528 | |
| | | 1529 | if (tag->s_block_level < block_level) { |
| | | 1530 | if (semi) { |
| | | 1531 | /* "struct a;" */ |
| | | 1532 | if (allow_c90) { |
| | | 1533 | /* XXX: Why is this warning suppressed in C90 mode? */ |
| | | 1534 | if (allow_trad || allow_c99) |
| | | 1535 | /* declaration of '%s %s' intro... */ |
| | | 1536 | warning(44, storage_class_name(scl), |
| | | 1537 | tag->s_name); |
| | | 1538 | tag = pushdown(tag); |
| | | 1539 | } else if (tag->s_scl != scl) { |
| | | 1540 | /* base type is really '%s %s' */ |
| | | 1541 | warning(45, storage_class_name(tag->s_scl), |
| | | 1542 | tag->s_name); |
| | | 1543 | } |
| | | 1544 | dcs->d_enclosing->d_nonempty_decl = true; |
| | | 1545 | } else if (decl) { |
| | | 1546 | /* "struct a { ... } " */ |
| | | 1547 | if (hflag) |
| | | 1548 | /* redefinition of '%s' hides earlier one */ |
| | | 1549 | warning(43, tag->s_name); |
| | | 1550 | tag = pushdown(tag); |
| | | 1551 | dcs->d_enclosing->d_nonempty_decl = true; |
| | | 1552 | } else if (tag->s_scl != scl) { |
| | | 1553 | /* base type is really '%s %s' */ |
| | | 1554 | warning(45, storage_class_name(tag->s_scl), |
| | | 1555 | tag->s_name); |
| | | 1556 | /* XXX: Why is this warning suppressed in C90 mode? */ |
| | | 1557 | if (allow_trad || allow_c99) { |
| | | 1558 | /* declaration of '%s %s' introduces ... */ |
| | | 1559 | warning(44, storage_class_name(scl), |
| | | 1560 | tag->s_name); |
| | | 1561 | } |
| | | 1562 | tag = pushdown(tag); |
| | | 1563 | dcs->d_enclosing->d_nonempty_decl = true; |
| | | 1564 | } |
| | | 1565 | } else { |
| | | 1566 | if (tag->s_scl != scl || |
| | | 1567 | (decl && !is_incomplete(tag->s_type))) { |
| | | 1568 | /* %s tag '%s' redeclared as %s */ |
| | | 1569 | error(46, storage_class_name(tag->s_scl), |
| | | 1570 | tag->s_name, storage_class_name(scl)); |
| | | 1571 | print_previous_declaration(tag); |
| | | 1572 | tag = pushdown(tag); |
| | | 1573 | dcs->d_enclosing->d_nonempty_decl = true; |
| | | 1574 | } else if (semi || decl) |
| | | 1575 | dcs->d_enclosing->d_nonempty_decl = true; |
| | | 1576 | } |
| | | 1577 | return tag; |
| | | 1578 | } |
| | | 1579 | |
| | | 1580 | /*- |
1538 | * tag the symbol table entry of the tag | | 1581 | * tag the symbol table entry of the tag |
1539 | * kind the kind of the tag (STRUCT/UNION/ENUM) | | 1582 | * kind the kind of the tag (STRUCT/UNION/ENUM) |
1540 | * decl whether the tag type will be completed in this declaration | | 1583 | * decl whether the tag type will be completed in this declaration |
1541 | * (when the following token is T_LBRACE) | | 1584 | * (when the following token is T_LBRACE) |
1542 | * semi whether the following token is T_SEMI | | 1585 | * semi whether the following token is T_SEMI |
1543 | */ | | 1586 | */ |
1544 | type_t * | | 1587 | type_t * |
1545 | make_tag_type(sym_t *tag, tspec_t kind, bool decl, bool semi) | | 1588 | make_tag_type(sym_t *tag, tspec_t kind, bool decl, bool semi) |
1546 | { | | 1589 | { |
1547 | scl_t scl; | | 1590 | scl_t scl; |
1548 | type_t *tp; | | 1591 | type_t *tp; |
1549 | | | 1592 | |
1550 | if (kind == STRUCT) | | 1593 | if (kind == STRUCT) |
| @@ -1599,87 +1642,26 @@ make_tag_type(sym_t *tag, tspec_t kind, | | | @@ -1599,87 +1642,26 @@ make_tag_type(sym_t *tag, tspec_t kind, |
1599 | tp->t_sou->sou_tag = tag; | | 1642 | tp->t_sou->sou_tag = tag; |
1600 | tp->t_sou->sou_incomplete = true; | | 1643 | tp->t_sou->sou_incomplete = true; |
1601 | } else { | | 1644 | } else { |
1602 | tp->t_is_enum = true; | | 1645 | tp->t_is_enum = true; |
1603 | tp->t_enum = block_zero_alloc(sizeof(*tp->t_enum), | | 1646 | tp->t_enum = block_zero_alloc(sizeof(*tp->t_enum), |
1604 | "enumeration"); | | 1647 | "enumeration"); |
1605 | tp->t_enum->en_tag = tag; | | 1648 | tp->t_enum->en_tag = tag; |
1606 | tp->t_enum->en_incomplete = true; | | 1649 | tp->t_enum->en_incomplete = true; |
1607 | } | | 1650 | } |
1608 | } | | 1651 | } |
1609 | return tp; | | 1652 | return tp; |
1610 | } | | 1653 | } |
1611 | | | 1654 | |
1612 | /*- | | | |
1613 | * Checks all possible cases of tag redeclarations. | | | |
1614 | * | | | |
1615 | * decl whether T_LBRACE follows | | | |
1616 | * semi whether T_SEMI follows | | | |
1617 | */ | | | |
1618 | static sym_t * | | | |
1619 | new_tag(sym_t *tag, scl_t scl, bool decl, bool semi) | | | |
1620 | { | | | |
1621 | | | | |
1622 | if (tag->s_block_level < block_level) { | | | |
1623 | if (semi) { | | | |
1624 | /* "struct a;" */ | | | |
1625 | if (allow_c90) { | | | |
1626 | /* XXX: Why is this warning suppressed in C90 mode? */ | | | |
1627 | if (allow_trad || allow_c99) | | | |
1628 | /* declaration of '%s %s' intro... */ | | | |
1629 | warning(44, storage_class_name(scl), | | | |
1630 | tag->s_name); | | | |
1631 | tag = pushdown(tag); | | | |
1632 | } else if (tag->s_scl != scl) { | | | |
1633 | /* base type is really '%s %s' */ | | | |
1634 | warning(45, storage_class_name(tag->s_scl), | | | |
1635 | tag->s_name); | | | |
1636 | } | | | |
1637 | dcs->d_enclosing->d_nonempty_decl = true; | | | |
1638 | } else if (decl) { | | | |
1639 | /* "struct a { ... } " */ | | | |
1640 | if (hflag) | | | |
1641 | /* redefinition of '%s' hides earlier one */ | | | |
1642 | warning(43, tag->s_name); | | | |
1643 | tag = pushdown(tag); | | | |
1644 | dcs->d_enclosing->d_nonempty_decl = true; | | | |
1645 | } else if (tag->s_scl != scl) { | | | |
1646 | /* base type is really '%s %s' */ | | | |
1647 | warning(45, storage_class_name(tag->s_scl), | | | |
1648 | tag->s_name); | | | |
1649 | /* XXX: Why is this warning suppressed in C90 mode? */ | | | |
1650 | if (allow_trad || allow_c99) { | | | |
1651 | /* declaration of '%s %s' introduces ... */ | | | |
1652 | warning(44, storage_class_name(scl), | | | |
1653 | tag->s_name); | | | |
1654 | } | | | |
1655 | tag = pushdown(tag); | | | |
1656 | dcs->d_enclosing->d_nonempty_decl = true; | | | |
1657 | } | | | |
1658 | } else { | | | |
1659 | if (tag->s_scl != scl || | | | |
1660 | (decl && !is_incomplete(tag->s_type))) { | | | |
1661 | /* %s tag '%s' redeclared as %s */ | | | |
1662 | error(46, storage_class_name(tag->s_scl), | | | |
1663 | tag->s_name, storage_class_name(scl)); | | | |
1664 | print_previous_declaration(tag); | | | |
1665 | tag = pushdown(tag); | | | |
1666 | dcs->d_enclosing->d_nonempty_decl = true; | | | |
1667 | } else if (semi || decl) | | | |
1668 | dcs->d_enclosing->d_nonempty_decl = true; | | | |
1669 | } | | | |
1670 | return tag; | | | |
1671 | } | | | |
1672 | | | | |
1673 | const char * | | 1655 | const char * |
1674 | storage_class_name(scl_t sc) | | 1656 | storage_class_name(scl_t sc) |
1675 | { | | 1657 | { |
1676 | switch (sc) { | | 1658 | switch (sc) { |
1677 | case EXTERN: return "extern"; | | 1659 | case EXTERN: return "extern"; |
1678 | case STATIC: return "static"; | | 1660 | case STATIC: return "static"; |
1679 | case AUTO: return "auto"; | | 1661 | case AUTO: return "auto"; |
1680 | case REG: return "register"; | | 1662 | case REG: return "register"; |
1681 | case TYPEDEF: return "typedef"; | | 1663 | case TYPEDEF: return "typedef"; |
1682 | case STRUCT_TAG:return "struct"; | | 1664 | case STRUCT_TAG:return "struct"; |
1683 | case UNION_TAG: return "union"; | | 1665 | case UNION_TAG: return "union"; |
1684 | case ENUM_TAG: return "enum"; | | 1666 | case ENUM_TAG: return "enum"; |
1685 | default: lint_assert(/*CONSTCOND*/false); | | 1667 | default: lint_assert(/*CONSTCOND*/false); |
| @@ -1812,26 +1794,116 @@ check_extern_declaration(const sym_t *sy | | | @@ -1812,26 +1794,116 @@ check_extern_declaration(const sym_t *sy |
1812 | warning(351, sym->s_type->t_tspec == FUNC ? "" : " 'extern'", | | 1794 | warning(351, sym->s_type->t_tspec == FUNC ? "" : " 'extern'", |
1813 | sym->s_name); | | 1795 | sym->s_name); |
1814 | } | | 1796 | } |
1815 | if (any_query_enabled && | | 1797 | if (any_query_enabled && |
1816 | sym->s_type->t_tspec == FUNC && | | 1798 | sym->s_type->t_tspec == FUNC && |
1817 | sym->s_scl == EXTERN && | | 1799 | sym->s_scl == EXTERN && |
1818 | sym->s_def == DECL && | | 1800 | sym->s_def == DECL && |
1819 | !in_system_header) { | | 1801 | !in_system_header) { |
1820 | /* redundant 'extern' in function declaration of '%s' */ | | 1802 | /* redundant 'extern' in function declaration of '%s' */ |
1821 | query_message(13, sym->s_name); | | 1803 | query_message(13, sym->s_name); |
1822 | } | | 1804 | } |
1823 | } | | 1805 | } |
1824 | | | 1806 | |
| | | 1807 | /* |
| | | 1808 | * Check whether the symbol cannot be initialized due to type/storage class. |
| | | 1809 | * Return whether an error has been detected. |
| | | 1810 | */ |
| | | 1811 | static bool |
| | | 1812 | check_init(sym_t *sym) |
| | | 1813 | { |
| | | 1814 | |
| | | 1815 | if (sym->s_type->t_tspec == FUNC) { |
| | | 1816 | /* cannot initialize function '%s' */ |
| | | 1817 | error(24, sym->s_name); |
| | | 1818 | return true; |
| | | 1819 | } |
| | | 1820 | if (sym->s_scl == TYPEDEF) { |
| | | 1821 | /* cannot initialize typedef '%s' */ |
| | | 1822 | error(25, sym->s_name); |
| | | 1823 | return true; |
| | | 1824 | } |
| | | 1825 | if (sym->s_scl == EXTERN && sym->s_def == DECL) { |
| | | 1826 | if (dcs->d_kind == DLK_EXTERN) { |
| | | 1827 | /* cannot initialize extern declaration '%s' */ |
| | | 1828 | warning(26, sym->s_name); |
| | | 1829 | } else { |
| | | 1830 | /* cannot initialize extern declaration '%s' */ |
| | | 1831 | error(26, sym->s_name); |
| | | 1832 | return true; |
| | | 1833 | } |
| | | 1834 | } |
| | | 1835 | |
| | | 1836 | return false; |
| | | 1837 | } |
| | | 1838 | |
| | | 1839 | /* |
| | | 1840 | * Compares a prototype declaration with the remembered arguments of a previous |
| | | 1841 | * old-style function definition. |
| | | 1842 | */ |
| | | 1843 | static bool |
| | | 1844 | check_old_style_definition(sym_t *rdsym, sym_t *dsym) |
| | | 1845 | { |
| | | 1846 | |
| | | 1847 | sym_t *args = rdsym->u.s_old_style_args; |
| | | 1848 | sym_t *pargs = dsym->s_type->t_args; |
| | | 1849 | |
| | | 1850 | bool msg = false; |
| | | 1851 | |
| | | 1852 | int narg = 0; |
| | | 1853 | for (sym_t *arg = args; arg != NULL; arg = arg->s_next) |
| | | 1854 | narg++; |
| | | 1855 | int nparg = 0; |
| | | 1856 | for (sym_t *parg = pargs; parg != NULL; parg = parg->s_next) |
| | | 1857 | nparg++; |
| | | 1858 | if (narg != nparg) { |
| | | 1859 | /* prototype does not match old-style definition */ |
| | | 1860 | error(63); |
| | | 1861 | msg = true; |
| | | 1862 | goto end; |
| | | 1863 | } |
| | | 1864 | |
| | | 1865 | sym_t *arg = args; |
| | | 1866 | sym_t *parg = pargs; |
| | | 1867 | int n = 1; |
| | | 1868 | while (narg-- > 0) { |
| | | 1869 | bool dowarn = false; |
| | | 1870 | /* |
| | | 1871 | * If it does not match due to promotion and lint runs in |
| | | 1872 | * "traditional to C90" migration mode, print only a warning. |
| | | 1873 | * |
| | | 1874 | * XXX: Where is this "only a warning"? |
| | | 1875 | */ |
| | | 1876 | if (!types_compatible(arg->s_type, parg->s_type, |
| | | 1877 | true, true, &dowarn) || |
| | | 1878 | dowarn) { |
| | | 1879 | /* prototype does not match old-style ... */ |
| | | 1880 | error(299, n); |
| | | 1881 | msg = true; |
| | | 1882 | } |
| | | 1883 | arg = arg->s_next; |
| | | 1884 | parg = parg->s_next; |
| | | 1885 | n++; |
| | | 1886 | } |
| | | 1887 | |
| | | 1888 | end: |
| | | 1889 | if (msg && rflag) { |
| | | 1890 | /* old-style definition */ |
| | | 1891 | message_at(300, &rdsym->s_def_pos); |
| | | 1892 | } |
| | | 1893 | |
| | | 1894 | return msg; |
| | | 1895 | } |
| | | 1896 | |
1825 | /* Process a single external or 'static' declarator. */ | | 1897 | /* Process a single external or 'static' declarator. */ |
1826 | static void | | 1898 | static void |
1827 | declare_extern(sym_t *dsym, bool has_initializer, sbuf_t *renaming) | | 1899 | declare_extern(sym_t *dsym, bool has_initializer, sbuf_t *renaming) |
1828 | { | | 1900 | { |
1829 | | | 1901 | |
1830 | if (renaming != NULL) { | | 1902 | if (renaming != NULL) { |
1831 | lint_assert(dsym->s_rename == NULL); | | 1903 | lint_assert(dsym->s_rename == NULL); |
1832 | | | 1904 | |
1833 | char *s = level_zero_alloc(1, renaming->sb_len + 1, "string"); | | 1905 | char *s = level_zero_alloc(1, renaming->sb_len + 1, "string"); |
1834 | (void)memcpy(s, renaming->sb_name, renaming->sb_len + 1); | | 1906 | (void)memcpy(s, renaming->sb_name, renaming->sb_len + 1); |
1835 | dsym->s_rename = s; | | 1907 | dsym->s_rename = s; |
1836 | } | | 1908 | } |
1837 | | | 1909 | |
| @@ -2063,26 +2135,73 @@ qualifiers_correspond(const type_t *tp1, | | | @@ -2063,26 +2135,73 @@ qualifiers_correspond(const type_t *tp1, |
2063 | if (tp1->t_volatile != tp2->t_volatile && !ignqual && allow_c90) | | 2135 | if (tp1->t_volatile != tp2->t_volatile && !ignqual && allow_c90) |
2064 | return false; | | 2136 | return false; |
2065 | return true; | | 2137 | return true; |
2066 | } | | 2138 | } |
2067 | | | 2139 | |
2068 | bool | | 2140 | bool |
2069 | pointer_types_are_compatible(const type_t *tp1, const type_t *tp2, bool ignqual) | | 2141 | pointer_types_are_compatible(const type_t *tp1, const type_t *tp2, bool ignqual) |
2070 | { | | 2142 | { |
2071 | | | 2143 | |
2072 | return tp1->t_tspec == VOID || tp2->t_tspec == VOID || | | 2144 | return tp1->t_tspec == VOID || tp2->t_tspec == VOID || |
2073 | qualifiers_correspond(tp1, tp2, ignqual); | | 2145 | qualifiers_correspond(tp1, tp2, ignqual); |
2074 | } | | 2146 | } |
2075 | | | 2147 | |
| | | 2148 | static bool |
| | | 2149 | prototypes_compatible(const type_t *tp1, const type_t *tp2, bool *dowarn) |
| | | 2150 | { |
| | | 2151 | |
| | | 2152 | if (tp1->t_vararg != tp2->t_vararg) |
| | | 2153 | return false; |
| | | 2154 | |
| | | 2155 | sym_t *a1 = tp1->t_args; |
| | | 2156 | sym_t *a2 = tp2->t_args; |
| | | 2157 | |
| | | 2158 | for (; a1 != NULL && a2 != NULL; a1 = a1->s_next, a2 = a2->s_next) { |
| | | 2159 | if (!types_compatible(a1->s_type, a2->s_type, |
| | | 2160 | true, false, dowarn)) |
| | | 2161 | return false; |
| | | 2162 | } |
| | | 2163 | return a1 == a2; |
| | | 2164 | } |
| | | 2165 | |
| | | 2166 | /* |
| | | 2167 | * Returns whether all parameters of a prototype are compatible with an |
| | | 2168 | * old-style function declaration. |
| | | 2169 | * |
| | | 2170 | * This is the case if the following conditions are met: |
| | | 2171 | * 1. the prototype has a fixed number of parameters |
| | | 2172 | * 2. no parameter is of type float |
| | | 2173 | * 3. no parameter is converted to another type if integer promotion |
| | | 2174 | * is applied on it |
| | | 2175 | */ |
| | | 2176 | static bool |
| | | 2177 | matches_no_arg_function(const type_t *tp, bool *dowarn) |
| | | 2178 | { |
| | | 2179 | |
| | | 2180 | if (tp->t_vararg && dowarn != NULL) |
| | | 2181 | *dowarn = true; |
| | | 2182 | for (sym_t *arg = tp->t_args; arg != NULL; arg = arg->s_next) { |
| | | 2183 | tspec_t t = arg->s_type->t_tspec; |
| | | 2184 | if (t == FLOAT || |
| | | 2185 | t == CHAR || t == SCHAR || t == UCHAR || |
| | | 2186 | t == SHORT || t == USHORT) { |
| | | 2187 | if (dowarn != NULL) |
| | | 2188 | *dowarn = true; |
| | | 2189 | } |
| | | 2190 | } |
| | | 2191 | /* FIXME: Always returning true cannot be correct. */ |
| | | 2192 | return true; |
| | | 2193 | } |
| | | 2194 | |
2076 | /*- | | 2195 | /*- |
2077 | * ignqual ignore type qualifiers; used for function parameters | | 2196 | * ignqual ignore type qualifiers; used for function parameters |
2078 | * promot promote the left type; used for comparison of parameters of | | 2197 | * promot promote the left type; used for comparison of parameters of |
2079 | * old-style function definitions with parameters of prototypes. | | 2198 | * old-style function definitions with parameters of prototypes. |
2080 | * *dowarn is set to true if an old-style function declaration is not | | 2199 | * *dowarn is set to true if an old-style function declaration is not |
2081 | * compatible with a prototype | | 2200 | * compatible with a prototype |
2082 | */ | | 2201 | */ |
2083 | bool | | 2202 | bool |
2084 | types_compatible(const type_t *tp1, const type_t *tp2, | | 2203 | types_compatible(const type_t *tp1, const type_t *tp2, |
2085 | bool ignqual, bool promot, bool *dowarn) | | 2204 | bool ignqual, bool promot, bool *dowarn) |
2086 | { | | 2205 | { |
2087 | | | 2206 | |
2088 | while (tp1 != NULL && tp2 != NULL) { | | 2207 | while (tp1 != NULL && tp2 != NULL) { |
| @@ -2132,131 +2251,26 @@ types_compatible(const type_t *tp1, cons | | | @@ -2132,131 +2251,26 @@ types_compatible(const type_t *tp1, cons |
2132 | if (!matches_no_arg_function(tp2, dowarn)) | | 2251 | if (!matches_no_arg_function(tp2, dowarn)) |
2133 | return false; | | 2252 | return false; |
2134 | } | | 2253 | } |
2135 | } | | 2254 | } |
2136 | | | 2255 | |
2137 | tp1 = tp1->t_subt; | | 2256 | tp1 = tp1->t_subt; |
2138 | tp2 = tp2->t_subt; | | 2257 | tp2 = tp2->t_subt; |
2139 | ignqual = promot = false; | | 2258 | ignqual = promot = false; |
2140 | } | | 2259 | } |
2141 | | | 2260 | |
2142 | return tp1 == tp2; | | 2261 | return tp1 == tp2; |
2143 | } | | 2262 | } |
2144 | | | 2263 | |
2145 | static bool | | | |
2146 | prototypes_compatible(const type_t *tp1, const type_t *tp2, bool *dowarn) | | | |
2147 | { | | | |
2148 | | | | |
2149 | if (tp1->t_vararg != tp2->t_vararg) | | | |
2150 | return false; | | | |
2151 | | | | |
2152 | sym_t *a1 = tp1->t_args; | | | |
2153 | sym_t *a2 = tp2->t_args; | | | |
2154 | | | | |
2155 | for (; a1 != NULL && a2 != NULL; a1 = a1->s_next, a2 = a2->s_next) { | | | |
2156 | if (!types_compatible(a1->s_type, a2->s_type, | | | |
2157 | true, false, dowarn)) | | | |
2158 | return false; | | | |
2159 | } | | | |
2160 | return a1 == a2; | | | |
2161 | } | | | |
2162 | | | | |
2163 | /* | | | |
2164 | * Returns whether all parameters of a prototype are compatible with an | | | |
2165 | * old-style function declaration. | | | |
2166 | * | | | |
2167 | * This is the case if the following conditions are met: | | | |
2168 | * 1. the prototype has a fixed number of parameters | | | |
2169 | * 2. no parameter is of type float | | | |
2170 | * 3. no parameter is converted to another type if integer promotion | | | |
2171 | * is applied on it | | | |
2172 | */ | | | |
2173 | static bool | | | |
2174 | matches_no_arg_function(const type_t *tp, bool *dowarn) | | | |
2175 | { | | | |
2176 | | | | |
2177 | if (tp->t_vararg && dowarn != NULL) | | | |
2178 | *dowarn = true; | | | |
2179 | for (sym_t *arg = tp->t_args; arg != NULL; arg = arg->s_next) { | | | |
2180 | tspec_t t = arg->s_type->t_tspec; | | | |
2181 | if (t == FLOAT || | | | |
2182 | t == CHAR || t == SCHAR || t == UCHAR || | | | |
2183 | t == SHORT || t == USHORT) { | | | |
2184 | if (dowarn != NULL) | | | |
2185 | *dowarn = true; | | | |
2186 | } | | | |
2187 | } | | | |
2188 | /* FIXME: Always returning true cannot be correct. */ | | | |
2189 | return true; | | | |
2190 | } | | | |
2191 | | | | |
2192 | /* | | | |
2193 | * Compares a prototype declaration with the remembered arguments of a previous | | | |
2194 | * old-style function definition. | | | |
2195 | */ | | | |
2196 | static bool | | | |
2197 | check_old_style_definition(sym_t *rdsym, sym_t *dsym) | | | |
2198 | { | | | |
2199 | | | | |
2200 | sym_t *args = rdsym->u.s_old_style_args; | | | |
2201 | sym_t *pargs = dsym->s_type->t_args; | | | |
2202 | | | | |
2203 | bool msg = false; | | | |
2204 | | | | |
2205 | int narg = 0; | | | |
2206 | for (sym_t *arg = args; arg != NULL; arg = arg->s_next) | | | |
2207 | narg++; | | | |
2208 | int nparg = 0; | | | |
2209 | for (sym_t *parg = pargs; parg != NULL; parg = parg->s_next) | | | |
2210 | nparg++; | | | |
2211 | if (narg != nparg) { | | | |
2212 | /* prototype does not match old-style definition */ | | | |
2213 | error(63); | | | |
2214 | msg = true; | | | |
2215 | goto end; | | | |
2216 | } | | | |
2217 | | | | |
2218 | sym_t *arg = args; | | | |
2219 | sym_t *parg = pargs; | | | |
2220 | int n = 1; | | | |
2221 | while (narg-- > 0) { | | | |
2222 | bool dowarn = false; | | | |
2223 | /* | | | |
2224 | * If it does not match due to promotion and lint runs in | | | |
2225 | * "traditional to C90" migration mode, print only a warning. | | | |
2226 | * | | | |
2227 | * XXX: Where is this "only a warning"? | | | |
2228 | */ | | | |
2229 | if (!types_compatible(arg->s_type, parg->s_type, | | | |
2230 | true, true, &dowarn) || | | | |
2231 | dowarn) { | | | |
2232 | /* prototype does not match old-style ... */ | | | |
2233 | error(299, n); | | | |
2234 | msg = true; | | | |
2235 | } | | | |
2236 | arg = arg->s_next; | | | |
2237 | parg = parg->s_next; | | | |
2238 | n++; | | | |
2239 | } | | | |
2240 | | | | |
2241 | end: | | | |
2242 | if (msg && rflag) { | | | |
2243 | /* old-style definition */ | | | |
2244 | message_at(300, &rdsym->s_def_pos); | | | |
2245 | } | | | |
2246 | | | | |
2247 | return msg; | | | |
2248 | } | | | |
2249 | | | | |
2250 | /* | | 2264 | /* |
2251 | * Completes a type by copying the dimension and prototype information from a | | 2265 | * Completes a type by copying the dimension and prototype information from a |
2252 | * second compatible type. | | 2266 | * second compatible type. |
2253 | * | | 2267 | * |
2254 | * Following lines are legal: | | 2268 | * Following lines are legal: |
2255 | * "typedef a[]; a b; a b[10]; a c; a c[20];" | | 2269 | * "typedef a[]; a b; a b[10]; a c; a c[20];" |
2256 | * "typedef ft(); ft f; f(int); ft g; g(long);" | | 2270 | * "typedef ft(); ft f; f(int); ft g; g(long);" |
2257 | * This means that, if a type is completed, the type structure must be | | 2271 | * This means that, if a type is completed, the type structure must be |
2258 | * duplicated. | | 2272 | * duplicated. |
2259 | */ | | 2273 | */ |
2260 | void | | 2274 | void |
2261 | complete_type(sym_t *dsym, sym_t *ssym) | | 2275 | complete_type(sym_t *dsym, sym_t *ssym) |
2262 | { | | 2276 | { |
| @@ -2412,26 +2426,62 @@ check_func_lint_directives(void) | | | @@ -2412,26 +2426,62 @@ check_func_lint_directives(void) |
2412 | ? printflike_argnum : scanflike_argnum; | | 2426 | ? printflike_argnum : scanflike_argnum; |
2413 | sym_t *arg = dcs->d_func_args; | | 2427 | sym_t *arg = dcs->d_func_args; |
2414 | for (int n = 1; n < narg; n++) | | 2428 | for (int n = 1; n < narg; n++) |
2415 | arg = arg->s_next; | | 2429 | arg = arg->s_next; |
2416 | if (!is_character_pointer(arg->s_type)) { | | 2430 | if (!is_character_pointer(arg->s_type)) { |
2417 | /* argument %d must be 'char *' for PRINTFLIKE/... */ | | 2431 | /* argument %d must be 'char *' for PRINTFLIKE/... */ |
2418 | warning(293, narg); | | 2432 | warning(293, narg); |
2419 | printflike_argnum = scanflike_argnum = -1; | | 2433 | printflike_argnum = scanflike_argnum = -1; |
2420 | } | | 2434 | } |
2421 | } | | 2435 | } |
2422 | } | | 2436 | } |
2423 | | | 2437 | |
2424 | /* | | 2438 | /* |
| | | 2439 | * Checks compatibility of an old-style function definition with a previous |
| | | 2440 | * prototype declaration. |
| | | 2441 | * Returns true if the position of the previous declaration should be reported. |
| | | 2442 | */ |
| | | 2443 | static bool |
| | | 2444 | check_prototype_declaration(sym_t *arg, sym_t *parg) |
| | | 2445 | { |
| | | 2446 | type_t *tp = arg->s_type; |
| | | 2447 | type_t *ptp = parg->s_type; |
| | | 2448 | bool dowarn = false; |
| | | 2449 | |
| | | 2450 | if (!types_compatible(tp, ptp, true, true, &dowarn)) { |
| | | 2451 | if (types_compatible(tp, ptp, true, false, &dowarn)) { |
| | | 2452 | /* type of '%s' does not match prototype */ |
| | | 2453 | return gnuism(58, arg->s_name); |
| | | 2454 | } else { |
| | | 2455 | /* type of '%s' does not match prototype */ |
| | | 2456 | error(58, arg->s_name); |
| | | 2457 | return true; |
| | | 2458 | } |
| | | 2459 | } |
| | | 2460 | if (dowarn) { |
| | | 2461 | /* TODO: Make this an error in C99 mode as well. */ |
| | | 2462 | if (!allow_trad && !allow_c99) |
| | | 2463 | /* type of '%s' does not match prototype */ |
| | | 2464 | error(58, arg->s_name); |
| | | 2465 | else |
| | | 2466 | /* type of '%s' does not match prototype */ |
| | | 2467 | warning(58, arg->s_name); |
| | | 2468 | return true; |
| | | 2469 | } |
| | | 2470 | |
| | | 2471 | return false; |
| | | 2472 | } |
| | | 2473 | |
| | | 2474 | /* |
2425 | * Warn about arguments in old-style function definitions that default to int. | | 2475 | * Warn about arguments in old-style function definitions that default to int. |
2426 | * Check that an old-style function definition is compatible to a previous | | 2476 | * Check that an old-style function definition is compatible to a previous |
2427 | * prototype. | | 2477 | * prototype. |
2428 | */ | | 2478 | */ |
2429 | void | | 2479 | void |
2430 | check_func_old_style_arguments(void) | | 2480 | check_func_old_style_arguments(void) |
2431 | { | | 2481 | { |
2432 | int narg; | | 2482 | int narg; |
2433 | int nparg; | | 2483 | int nparg; |
2434 | bool msg; | | 2484 | bool msg; |
2435 | | | 2485 | |
2436 | sym_t *args = funcsym->u.s_old_style_args; | | 2486 | sym_t *args = funcsym->u.s_old_style_args; |
2437 | sym_t *pargs = funcsym->s_type->t_args; | | 2487 | sym_t *pargs = funcsym->s_type->t_args; |
| @@ -2478,62 +2528,26 @@ check_func_old_style_arguments(void) | | | @@ -2478,62 +2528,26 @@ check_func_old_style_arguments(void) |
2478 | } | | 2528 | } |
2479 | } | | 2529 | } |
2480 | if (msg && rflag) { | | 2530 | if (msg && rflag) { |
2481 | /* prototype declaration */ | | 2531 | /* prototype declaration */ |
2482 | message_at(285, &dcs->d_redeclared_symbol->s_def_pos); | | 2532 | message_at(285, &dcs->d_redeclared_symbol->s_def_pos); |
2483 | } | | 2533 | } |
2484 | | | 2534 | |
2485 | /* from now on the prototype is valid */ | | 2535 | /* from now on the prototype is valid */ |
2486 | funcsym->s_osdef = false; | | 2536 | funcsym->s_osdef = false; |
2487 | funcsym->u.s_old_style_args = NULL; | | 2537 | funcsym->u.s_old_style_args = NULL; |
2488 | } | | 2538 | } |
2489 | } | | 2539 | } |
2490 | | | 2540 | |
2491 | /* | | | |
2492 | * Checks compatibility of an old-style function definition with a previous | | | |
2493 | * prototype declaration. | | | |
2494 | * Returns true if the position of the previous declaration should be reported. | | | |
2495 | */ | | | |
2496 | static bool | | | |
2497 | check_prototype_declaration(sym_t *arg, sym_t *parg) | | | |
2498 | { | | | |
2499 | type_t *tp = arg->s_type; | | | |
2500 | type_t *ptp = parg->s_type; | | | |
2501 | bool dowarn = false; | | | |
2502 | | | | |
2503 | if (!types_compatible(tp, ptp, true, true, &dowarn)) { | | | |
2504 | if (types_compatible(tp, ptp, true, false, &dowarn)) { | | | |
2505 | /* type of '%s' does not match prototype */ | | | |
2506 | return gnuism(58, arg->s_name); | | | |
2507 | } else { | | | |
2508 | /* type of '%s' does not match prototype */ | | | |
2509 | error(58, arg->s_name); | | | |
2510 | return true; | | | |
2511 | } | | | |
2512 | } | | | |
2513 | if (dowarn) { | | | |
2514 | /* TODO: Make this an error in C99 mode as well. */ | | | |
2515 | if (!allow_trad && !allow_c99) | | | |
2516 | /* type of '%s' does not match prototype */ | | | |
2517 | error(58, arg->s_name); | | | |
2518 | else | | | |
2519 | /* type of '%s' does not match prototype */ | | | |
2520 | warning(58, arg->s_name); | | | |
2521 | return true; | | | |
2522 | } | | | |
2523 | | | | |
2524 | return false; | | | |
2525 | } | | | |
2526 | | | | |
2527 | static void | | 2541 | static void |
2528 | check_local_hiding(const sym_t *dsym) | | 2542 | check_local_hiding(const sym_t *dsym) |
2529 | { | | 2543 | { |
2530 | switch (dsym->s_scl) { | | 2544 | switch (dsym->s_scl) { |
2531 | case AUTO: | | 2545 | case AUTO: |
2532 | /* automatic '%s' hides external declaration */ | | 2546 | /* automatic '%s' hides external declaration */ |
2533 | warning(86, dsym->s_name); | | 2547 | warning(86, dsym->s_name); |
2534 | break; | | 2548 | break; |
2535 | case STATIC: | | 2549 | case STATIC: |
2536 | /* static '%s' hides external declaration */ | | 2550 | /* static '%s' hides external declaration */ |
2537 | warning(87, dsym->s_name); | | 2551 | warning(87, dsym->s_name); |
2538 | break; | | 2552 | break; |
2539 | case TYPEDEF: | | 2553 | case TYPEDEF: |
| @@ -2562,37 +2576,87 @@ check_local_redeclaration(const sym_t *d | | | @@ -2562,37 +2576,87 @@ check_local_redeclaration(const sym_t *d |
2562 | /* | | 2576 | /* |
2563 | * if allow_c90, a "redeclaration of '%s'" error | | 2577 | * if allow_c90, a "redeclaration of '%s'" error |
2564 | * is produced below | | 2578 | * is produced below |
2565 | */ | | 2579 | */ |
2566 | if (!allow_c90) { | | 2580 | if (!allow_c90) { |
2567 | if (hflag) { | | 2581 | if (hflag) { |
2568 | /* declaration of '%s' hides ... */ | | 2582 | /* declaration of '%s' hides ... */ |
2569 | warning(91, dsym->s_name); | | 2583 | warning(91, dsym->s_name); |
2570 | } | | 2584 | } |
2571 | rmsym(rdsym); | | 2585 | rmsym(rdsym); |
2572 | } | | 2586 | } |
2573 | } | | 2587 | } |
2574 | | | 2588 | |
2575 | } else if (rdsym->s_block_level < block_level) { | | 2589 | } else if (rdsym->s_block_level < block_level) { |
2576 | if (hflag) { | | 2590 | if (hflag) { |
2577 | /* declaration of '%s' hides earlier one */ | | 2591 | /* declaration of '%s' hides earlier one */ |
2578 | warning(95, dsym->s_name); | | 2592 | warning(95, dsym->s_name); |
| | | 2593 | } |
| | | 2594 | } |
| | | 2595 | |
| | | 2596 | if (rdsym->s_block_level == block_level) { |
| | | 2597 | /* redeclaration of '%s' */ |
| | | 2598 | error(27, dsym->s_name); |
| | | 2599 | rmsym(rdsym); |
| | | 2600 | } |
| | | 2601 | } |
| | | 2602 | |
| | | 2603 | /* Processes (re)declarations of external symbols inside blocks. */ |
| | | 2604 | static void |
| | | 2605 | declare_external_in_block(sym_t *dsym) |
| | | 2606 | { |
| | | 2607 | |
| | | 2608 | /* look for a symbol with the same name */ |
| | | 2609 | sym_t *esym = dcs->d_redeclared_symbol; |
| | | 2610 | while (esym != NULL && esym->s_block_level != 0) { |
| | | 2611 | while ((esym = esym->s_symtab_next) != NULL) { |
| | | 2612 | if (esym->s_kind != FVFT) |
| | | 2613 | continue; |
| | | 2614 | if (strcmp(dsym->s_name, esym->s_name) == 0) |
| | | 2615 | break; |
| | | 2616 | } |
| | | 2617 | } |
| | | 2618 | if (esym == NULL) |
| | | 2619 | return; |
| | | 2620 | if (esym->s_scl != EXTERN && esym->s_scl != STATIC) { |
| | | 2621 | /* gcc accepts this without a warning, pcc prints an error. */ |
| | | 2622 | /* redeclaration of '%s' */ |
| | | 2623 | warning(27, dsym->s_name); |
| | | 2624 | print_previous_declaration(esym); |
| | | 2625 | return; |
| | | 2626 | } |
| | | 2627 | |
| | | 2628 | bool dowarn = false; |
| | | 2629 | bool compatible = types_compatible(esym->s_type, dsym->s_type, |
| | | 2630 | false, false, &dowarn); |
| | | 2631 | |
| | | 2632 | if (!compatible || dowarn) { |
| | | 2633 | if (esym->s_scl == EXTERN) { |
| | | 2634 | /* inconsistent redeclaration of extern '%s' */ |
| | | 2635 | warning(90, dsym->s_name); |
| | | 2636 | print_previous_declaration(esym); |
| | | 2637 | } else { |
| | | 2638 | /* inconsistent redeclaration of static '%s' */ |
| | | 2639 | warning(92, dsym->s_name); |
| | | 2640 | print_previous_declaration(esym); |
2579 | } | | 2641 | } |
2580 | } | | 2642 | } |
2581 | | | 2643 | |
2582 | if (rdsym->s_block_level == block_level) { | | 2644 | if (compatible) { |
2583 | /* redeclaration of '%s' */ | | 2645 | /* |
2584 | error(27, dsym->s_name); | | 2646 | * Remember the external symbol, so we can update usage |
2585 | rmsym(rdsym); | | 2647 | * information at the end of the block. |
| | | 2648 | */ |
| | | 2649 | dsym->s_ext_sym = esym; |
2586 | } | | 2650 | } |
2587 | } | | 2651 | } |
2588 | | | 2652 | |
2589 | /* | | 2653 | /* |
2590 | * Completes a single local declaration/definition. | | 2654 | * Completes a single local declaration/definition. |
2591 | */ | | 2655 | */ |
2592 | void | | 2656 | void |
2593 | declare_local(sym_t *dsym, bool has_initializer) | | 2657 | declare_local(sym_t *dsym, bool has_initializer) |
2594 | { | | 2658 | { |
2595 | | | 2659 | |
2596 | /* Correct a mistake done in declarator_name(). */ | | 2660 | /* Correct a mistake done in declarator_name(). */ |
2597 | if (dsym->s_type->t_tspec == FUNC) { | | 2661 | if (dsym->s_type->t_tspec == FUNC) { |
2598 | dsym->s_def = DECL; | | 2662 | dsym->s_def = DECL; |
| @@ -2661,108 +2725,26 @@ declare_local(sym_t *dsym, bool has_init | | | @@ -2661,108 +2725,26 @@ declare_local(sym_t *dsym, bool has_init |
2661 | | | 2725 | |
2662 | if (dsym->s_scl == TYPEDEF) { | | 2726 | if (dsym->s_scl == TYPEDEF) { |
2663 | dsym->s_type = block_dup_type(dsym->s_type); | | 2727 | dsym->s_type = block_dup_type(dsym->s_type); |
2664 | dsym->s_type->t_typedef = true; | | 2728 | dsym->s_type->t_typedef = true; |
2665 | set_first_typedef(dsym->s_type, dsym); | | 2729 | set_first_typedef(dsym->s_type, dsym); |
2666 | } | | 2730 | } |
2667 | | | 2731 | |
2668 | if (dsym->s_scl == STATIC && any_query_enabled) { | | 2732 | if (dsym->s_scl == STATIC && any_query_enabled) { |
2669 | /* static variable '%s' in function */ | | 2733 | /* static variable '%s' in function */ |
2670 | query_message(11, dsym->s_name); | | 2734 | query_message(11, dsym->s_name); |
2671 | } | | 2735 | } |
2672 | } | | 2736 | } |
2673 | | | 2737 | |
2674 | /* Processes (re)declarations of external symbols inside blocks. */ | | | |
2675 | static void | | | |
2676 | declare_external_in_block(sym_t *dsym) | | | |
2677 | { | | | |
2678 | | | | |
2679 | /* look for a symbol with the same name */ | | | |
2680 | sym_t *esym = dcs->d_redeclared_symbol; | | | |
2681 | while (esym != NULL && esym->s_block_level != 0) { | | | |
2682 | while ((esym = esym->s_symtab_next) != NULL) { | | | |
2683 | if (esym->s_kind != FVFT) | | | |
2684 | continue; | | | |
2685 | if (strcmp(dsym->s_name, esym->s_name) == 0) | | | |
2686 | break; | | | |
2687 | } | | | |
2688 | } | | | |
2689 | if (esym == NULL) | | | |
2690 | return; | | | |
2691 | if (esym->s_scl != EXTERN && esym->s_scl != STATIC) { | | | |
2692 | /* gcc accepts this without a warning, pcc prints an error. */ | | | |
2693 | /* redeclaration of '%s' */ | | | |
2694 | warning(27, dsym->s_name); | | | |
2695 | print_previous_declaration(esym); | | | |
2696 | return; | | | |
2697 | } | | | |
2698 | | | | |
2699 | bool dowarn = false; | | | |
2700 | bool compatible = types_compatible(esym->s_type, dsym->s_type, | | | |
2701 | false, false, &dowarn); | | | |
2702 | | | | |
2703 | if (!compatible || dowarn) { | | | |
2704 | if (esym->s_scl == EXTERN) { | | | |
2705 | /* inconsistent redeclaration of extern '%s' */ | | | |
2706 | warning(90, dsym->s_name); | | | |
2707 | print_previous_declaration(esym); | | | |
2708 | } else { | | | |
2709 | /* inconsistent redeclaration of static '%s' */ | | | |
2710 | warning(92, dsym->s_name); | | | |
2711 | print_previous_declaration(esym); | | | |
2712 | } | | | |
2713 | } | | | |
2714 | | | | |
2715 | if (compatible) { | | | |
2716 | /* | | | |
2717 | * Remember the external symbol, so we can update usage | | | |
2718 | * information at the end of the block. | | | |
2719 | */ | | | |
2720 | dsym->s_ext_sym = esym; | | | |
2721 | } | | | |
2722 | } | | | |
2723 | | | | |
2724 | /* | | | |
2725 | * Check whether the symbol cannot be initialized due to type/storage class. | | | |
2726 | * Return whether an error has been detected. | | | |
2727 | */ | | | |
2728 | static bool | | | |
2729 | check_init(sym_t *sym) | | | |
2730 | { | | | |
2731 | | | | |
2732 | if (sym->s_type->t_tspec == FUNC) { | | | |
2733 | /* cannot initialize function '%s' */ | | | |
2734 | error(24, sym->s_name); | | | |
2735 | return true; | | | |
2736 | } | | | |
2737 | if (sym->s_scl == TYPEDEF) { | | | |
2738 | /* cannot initialize typedef '%s' */ | | | |
2739 | error(25, sym->s_name); | | | |
2740 | return true; | | | |
2741 | } | | | |
2742 | if (sym->s_scl == EXTERN && sym->s_def == DECL) { | | | |
2743 | if (dcs->d_kind == DLK_EXTERN) { | | | |
2744 | /* cannot initialize extern declaration '%s' */ | | | |
2745 | warning(26, sym->s_name); | | | |
2746 | } else { | | | |
2747 | /* cannot initialize extern declaration '%s' */ | | | |
2748 | error(26, sym->s_name); | | | |
2749 | return true; | | | |
2750 | } | | | |
2751 | } | | | |
2752 | | | | |
2753 | return false; | | | |
2754 | } | | | |
2755 | | | | |
2756 | /* Create a symbol for an abstract declaration. */ | | 2738 | /* Create a symbol for an abstract declaration. */ |
2757 | sym_t * | | 2739 | sym_t * |
2758 | abstract_name(void) | | 2740 | abstract_name(void) |
2759 | { | | 2741 | { |
2760 | | | 2742 | |
2761 | lint_assert(dcs->d_kind == DLK_ABSTRACT | | 2743 | lint_assert(dcs->d_kind == DLK_ABSTRACT |
2762 | || dcs->d_kind == DLK_PROTO_PARAMS); | | 2744 | || dcs->d_kind == DLK_PROTO_PARAMS); |
2763 | | | 2745 | |
2764 | sym_t *sym = block_zero_alloc(sizeof(*sym), "sym"); | | 2746 | sym_t *sym = block_zero_alloc(sizeof(*sym), "sym"); |
2765 | sym->s_name = unnamed; | | 2747 | sym->s_name = unnamed; |
2766 | sym->s_def = DEF; | | 2748 | sym->s_def = DEF; |
2767 | sym->s_scl = ABSTRACT; | | 2749 | sym->s_scl = ABSTRACT; |
2768 | sym->s_block_level = -1; | | 2750 | sym->s_block_level = -1; |
| @@ -2865,44 +2847,26 @@ check_usage(decl_level *dl) | | | @@ -2865,44 +2847,26 @@ check_usage(decl_level *dl) |
2865 | { | | 2847 | { |
2866 | /* for this warning LINTED has no effect */ | | 2848 | /* for this warning LINTED has no effect */ |
2867 | int saved_lwarn = lwarn; | | 2849 | int saved_lwarn = lwarn; |
2868 | lwarn = LWARN_ALL; | | 2850 | lwarn = LWARN_ALL; |
2869 | | | 2851 | |
2870 | debug_step("begin lwarn %d", lwarn); | | 2852 | debug_step("begin lwarn %d", lwarn); |
2871 | for (sym_t *sym = dl->d_first_dlsym; | | 2853 | for (sym_t *sym = dl->d_first_dlsym; |
2872 | sym != NULL; sym = sym->s_level_next) | | 2854 | sym != NULL; sym = sym->s_level_next) |
2873 | check_usage_sym(dl->d_asm, sym); | | 2855 | check_usage_sym(dl->d_asm, sym); |
2874 | lwarn = saved_lwarn; | | 2856 | lwarn = saved_lwarn; |
2875 | debug_step("end lwarn %d", lwarn); | | 2857 | debug_step("end lwarn %d", lwarn); |
2876 | } | | 2858 | } |
2877 | | | 2859 | |
2878 | /* Warns about a variable or a label that is not used or only set. */ | | | |
2879 | void | | | |
2880 | check_usage_sym(bool novar, sym_t *sym) | | | |
2881 | { | | | |
2882 | | | | |
2883 | if (sym->s_block_level == -1) | | | |
2884 | return; | | | |
2885 | | | | |
2886 | if (sym->s_kind == FVFT && sym->s_arg) | | | |
2887 | check_argument_usage(novar, sym); | | | |
2888 | else if (sym->s_kind == FVFT) | | | |
2889 | check_variable_usage(novar, sym); | | | |
2890 | else if (sym->s_kind == FLABEL) | | | |
2891 | check_label_usage(sym); | | | |
2892 | else if (sym->s_kind == FTAG) | | | |
2893 | check_tag_usage(sym); | | | |
2894 | } | | | |
2895 | | | | |
2896 | static void | | 2860 | static void |
2897 | check_argument_usage(bool novar, sym_t *arg) | | 2861 | check_argument_usage(bool novar, sym_t *arg) |
2898 | { | | 2862 | { |
2899 | | | 2863 | |
2900 | lint_assert(arg->s_set); | | 2864 | lint_assert(arg->s_set); |
2901 | | | 2865 | |
2902 | if (novar) | | 2866 | if (novar) |
2903 | return; | | 2867 | return; |
2904 | | | 2868 | |
2905 | if (!arg->s_used && !vflag) { | | 2869 | if (!arg->s_used && !vflag) { |
2906 | /* parameter '%s' unused in function '%s' */ | | 2870 | /* parameter '%s' unused in function '%s' */ |
2907 | warning_at(231, &arg->s_def_pos, arg->s_name, funcsym->s_name); | | 2871 | warning_at(231, &arg->s_def_pos, arg->s_name, funcsym->s_name); |
2908 | } | | 2872 | } |
| @@ -3012,51 +2976,75 @@ check_tag_usage(sym_t *sym) | | | @@ -3012,51 +2976,75 @@ check_tag_usage(sym_t *sym) |
3012 | break; | | 2976 | break; |
3013 | case UNION: | | 2977 | case UNION: |
3014 | /* union '%s' never defined */ | | 2978 | /* union '%s' never defined */ |
3015 | warning_at(234, &sym->s_def_pos, sym->s_name); | | 2979 | warning_at(234, &sym->s_def_pos, sym->s_name); |
3016 | break; | | 2980 | break; |
3017 | default: | | 2981 | default: |
3018 | lint_assert(sym->s_type->t_tspec == ENUM); | | 2982 | lint_assert(sym->s_type->t_tspec == ENUM); |
3019 | /* enum '%s' never defined */ | | 2983 | /* enum '%s' never defined */ |
3020 | warning_at(235, &sym->s_def_pos, sym->s_name); | | 2984 | warning_at(235, &sym->s_def_pos, sym->s_name); |
3021 | break; | | 2985 | break; |
3022 | } | | 2986 | } |
3023 | } | | 2987 | } |
3024 | | | 2988 | |
3025 | /* | | 2989 | /* Warns about a variable or a label that is not used or only set. */ |
3026 | * Called after the entire translation unit has been parsed. | | | |
3027 | * Changes tentative definitions into definitions. | | | |
3028 | * Performs some tests on global symbols. Detected problems are: | | | |
3029 | * - defined variables of incomplete type | | | |
3030 | * - constant variables which are not initialized | | | |
3031 | * - static symbols which are never used | | | |
3032 | */ | | | |
3033 | void | | 2990 | void |
3034 | check_global_symbols(void) | | 2991 | check_usage_sym(bool novar, sym_t *sym) |
3035 | { | | 2992 | { |
3036 | sym_t *sym; | | | |
3037 | | | 2993 | |
3038 | if (block_level != 0 || dcs->d_enclosing != NULL) | | 2994 | if (sym->s_block_level == -1) |
3039 | norecover(); | | 2995 | return; |
3040 | | | 2996 | |
3041 | for (sym = dcs->d_first_dlsym; sym != NULL; sym = sym->s_level_next) { | | 2997 | if (sym->s_kind == FVFT && sym->s_arg) |
3042 | if (sym->s_block_level == -1) | | 2998 | check_argument_usage(novar, sym); |
3043 | continue; | | 2999 | else if (sym->s_kind == FVFT) |
3044 | if (sym->s_kind == FVFT) | | 3000 | check_variable_usage(novar, sym); |
3045 | check_global_variable(sym); | | 3001 | else if (sym->s_kind == FLABEL) |
3046 | else if (sym->s_kind == FTAG) | | 3002 | check_label_usage(sym); |
3047 | check_tag_usage(sym); | | 3003 | else if (sym->s_kind == FTAG) |
3048 | else | | 3004 | check_tag_usage(sym); |
3049 | lint_assert(sym->s_kind == FMEMBER); | | 3005 | } |
| | | 3006 | |
| | | 3007 | static void |
| | | 3008 | check_global_variable_size(const sym_t *sym) |
| | | 3009 | { |
| | | 3010 | |
| | | 3011 | if (sym->s_def != TDEF) |
| | | 3012 | return; |
| | | 3013 | if (sym->s_type->t_tspec == FUNC) { |
| | | 3014 | /* Maybe a syntax error after a function declaration. */ |
| | | 3015 | return; |
| | | 3016 | } |
| | | 3017 | if (sym->s_def == TDEF && sym->s_type->t_tspec == VOID) { |
| | | 3018 | /* Prevent an internal error in length_in_bits below. */ |
| | | 3019 | return; |
| | | 3020 | } |
| | | 3021 | |
| | | 3022 | pos_t cpos = curr_pos; |
| | | 3023 | curr_pos = sym->s_def_pos; |
| | | 3024 | int len_in_bits = length_in_bits(sym->s_type, sym->s_name); |
| | | 3025 | curr_pos = cpos; |
| | | 3026 | |
| | | 3027 | if (len_in_bits == 0 && |
| | | 3028 | sym->s_type->t_tspec == ARRAY && sym->s_type->t_dim == 0) { |
| | | 3029 | /* TODO: C99 6.7.5.2p1 defines this as an error as well. */ |
| | | 3030 | if (!allow_c90 || |
| | | 3031 | (sym->s_scl == EXTERN && (allow_trad || allow_c99))) { |
| | | 3032 | /* empty array declaration for '%s' */ |
| | | 3033 | warning_at(190, &sym->s_def_pos, sym->s_name); |
| | | 3034 | } else { |
| | | 3035 | /* empty array declaration for '%s' */ |
| | | 3036 | error_at(190, &sym->s_def_pos, sym->s_name); |
| | | 3037 | } |
3050 | } | | 3038 | } |
3051 | } | | 3039 | } |
3052 | | | 3040 | |
3053 | static void | | 3041 | static void |
3054 | check_unused_static_global_variable(const sym_t *sym) | | 3042 | check_unused_static_global_variable(const sym_t *sym) |
3055 | { | | 3043 | { |
3056 | if (sym->s_type->t_tspec == FUNC) { | | 3044 | if (sym->s_type->t_tspec == FUNC) { |
3057 | if (sym->s_def == DEF) { | | 3045 | if (sym->s_def == DEF) { |
3058 | if (!sym->s_inline) | | 3046 | if (!sym->s_inline) |
3059 | /* static function '%s' unused */ | | 3047 | /* static function '%s' unused */ |
3060 | warning_at(236, &sym->s_def_pos, sym->s_name); | | 3048 | warning_at(236, &sym->s_def_pos, sym->s_name); |
3061 | } else { | | 3049 | } else { |
3062 | /* static function '%s' declared but not defined */ | | 3050 | /* static function '%s' declared but not defined */ |
| @@ -3097,57 +3085,51 @@ check_global_variable(const sym_t *sym) | | | @@ -3097,57 +3085,51 @@ check_global_variable(const sym_t *sym) |
3097 | return; | | 3085 | return; |
3098 | | | 3086 | |
3099 | if (scl == NOSCL) | | 3087 | if (scl == NOSCL) |
3100 | return; /* May be caused by a syntax error. */ | | 3088 | return; /* May be caused by a syntax error. */ |
3101 | | | 3089 | |
3102 | lint_assert(scl == EXTERN || scl == STATIC); | | 3090 | lint_assert(scl == EXTERN || scl == STATIC); |
3103 | | | 3091 | |
3104 | check_global_variable_size(sym); | | 3092 | check_global_variable_size(sym); |
3105 | | | 3093 | |
3106 | if (scl == STATIC) | | 3094 | if (scl == STATIC) |
3107 | check_static_global_variable(sym); | | 3095 | check_static_global_variable(sym); |
3108 | } | | 3096 | } |
3109 | | | 3097 | |
3110 | static void | | 3098 | /* |
3111 | check_global_variable_size(const sym_t *sym) | | 3099 | * Called after the entire translation unit has been parsed. |
| | | 3100 | * Changes tentative definitions into definitions. |
| | | 3101 | * Performs some tests on global symbols. Detected problems are: |
| | | 3102 | * - defined variables of incomplete type |
| | | 3103 | * - constant variables which are not initialized |
| | | 3104 | * - static symbols which are never used |
| | | 3105 | */ |
| | | 3106 | void |
| | | 3107 | check_global_symbols(void) |
3112 | { | | 3108 | { |
| | | 3109 | sym_t *sym; |
3113 | | | 3110 | |
3114 | if (sym->s_def != TDEF) | | 3111 | if (block_level != 0 || dcs->d_enclosing != NULL) |
3115 | return; | | 3112 | norecover(); |
3116 | if (sym->s_type->t_tspec == FUNC) { | | | |
3117 | /* Maybe a syntax error after a function declaration. */ | | | |
3118 | return; | | | |
3119 | } | | | |
3120 | if (sym->s_def == TDEF && sym->s_type->t_tspec == VOID) { | | | |
3121 | /* Prevent an internal error in length_in_bits below. */ | | | |
3122 | return; | | | |
3123 | } | | | |
3124 | | | | |
3125 | pos_t cpos = curr_pos; | | | |
3126 | curr_pos = sym->s_def_pos; | | | |
3127 | int len_in_bits = length_in_bits(sym->s_type, sym->s_name); | | | |
3128 | curr_pos = cpos; | | | |
3129 | | | 3113 | |
3130 | if (len_in_bits == 0 && | | 3114 | for (sym = dcs->d_first_dlsym; sym != NULL; sym = sym->s_level_next) { |
3131 | sym->s_type->t_tspec == ARRAY && sym->s_type->t_dim == 0) { | | 3115 | if (sym->s_block_level == -1) |
3132 | /* TODO: C99 6.7.5.2p1 defines this as an error as well. */ | | 3116 | continue; |
3133 | if (!allow_c90 || | | 3117 | if (sym->s_kind == FVFT) |
3134 | (sym->s_scl == EXTERN && (allow_trad || allow_c99))) { | | 3118 | check_global_variable(sym); |
3135 | /* empty array declaration for '%s' */ | | 3119 | else if (sym->s_kind == FTAG) |
3136 | warning_at(190, &sym->s_def_pos, sym->s_name); | | 3120 | check_tag_usage(sym); |
3137 | } else { | | 3121 | else |
3138 | /* empty array declaration for '%s' */ | | 3122 | lint_assert(sym->s_kind == FMEMBER); |
3139 | error_at(190, &sym->s_def_pos, sym->s_name); | | | |
3140 | } | | | |
3141 | } | | 3123 | } |
3142 | } | | 3124 | } |
3143 | | | 3125 | |
3144 | /* | | 3126 | /* |
3145 | * Prints information about location of previous definition/declaration. | | 3127 | * Prints information about location of previous definition/declaration. |
3146 | */ | | 3128 | */ |
3147 | void | | 3129 | void |
3148 | print_previous_declaration(const sym_t *psym) | | 3130 | print_previous_declaration(const sym_t *psym) |
3149 | { | | 3131 | { |
3150 | | | 3132 | |
3151 | if (!rflag) | | 3133 | if (!rflag) |
3152 | return; | | 3134 | return; |
3153 | | | 3135 | |