Annotation of src/usr.bin/xlint/lint1/func.c, Revision 1.142
1.142 ! rillig 1: /* $NetBSD: func.c,v 1.141 2022/06/20 21:13:35 rillig Exp $ */
1.2 cgd 2:
1.1 cgd 3: /*
4: * Copyright (c) 1994, 1995 Jochen Pohl
5: * All Rights Reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Jochen Pohl for
18: * The NetBSD Project.
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.
21: *
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
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
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
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
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
1.21 jmc 34: #if HAVE_NBTOOL_CONFIG_H
35: #include "nbtool_config.h"
36: #endif
37:
1.8 christos 38: #include <sys/cdefs.h>
1.136 rillig 39: #if defined(__RCSID)
1.142 ! rillig 40: __RCSID("$NetBSD: func.c,v 1.141 2022/06/20 21:13:35 rillig Exp $");
1.1 cgd 41: #endif
42:
43: #include <stdlib.h>
44: #include <string.h>
45:
46: #include "lint1.h"
1.10 tv 47: #include "cgram.h"
1.1 cgd 48:
49: /*
50: * Contains a pointer to the symbol table entry of the current function
51: * definition.
52: */
53: sym_t *funcsym;
54:
55: /* Is set as long as a statement can be reached. Must be set at level 0. */
1.59 rillig 56: bool reached = true;
1.1 cgd 57:
58: /*
1.94 rillig 59: * Is true by default, can be cleared by NOTREACHED.
60: * Is reset to true whenever 'reached' changes.
1.1 cgd 61: */
1.94 rillig 62: bool warn_about_unreachable;
1.1 cgd 63:
64: /*
1.63 rillig 65: * In conjunction with 'reached', controls printing of "fallthrough on ..."
1.1 cgd 66: * warnings.
67: * Reset by each statement and set by FALLTHROUGH, switch (switch1())
68: * and case (label()).
69: *
1.78 rillig 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
72: * is important because ** FALLTHROUGH ** after "if (expr) statement" is
1.54 rillig 73: * evaluated before the following token, which causes reduction of above.
1.1 cgd 74: * This means that ** FALLTHROUGH ** after "if ..." would always be ignored.
75: */
1.78 rillig 76: bool seen_fallthrough;
1.1 cgd 77:
1.48 rillig 78: /* The innermost control statement */
1.115 rillig 79: control_statement *cstmt;
1.1 cgd 80:
81: /*
82: * Number of arguments which will be checked for usage in following
83: * function definition. -1 stands for all arguments.
84: *
1.31 rillig 85: * The position of the last ARGSUSED comment is stored in argsused_pos.
1.1 cgd 86: */
87: int nargusg = -1;
1.31 rillig 88: pos_t argsused_pos;
1.1 cgd 89:
90: /*
91: * Number of arguments of the following function definition whose types
92: * shall be checked by lint2. -1 stands for all arguments.
93: *
94: * The position of the last VARARGS comment is stored in vapos.
95: */
96: int nvararg = -1;
97: pos_t vapos;
98:
99: /*
1.49 rillig 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
102: * arguments (for PRINTFLIKE and SCANFLIKE).
1.1 cgd 103: *
1.31 rillig 104: * printflike_pos and scanflike_pos are the positions of the last PRINTFLIKE
105: * or SCANFLIKE comment.
1.1 cgd 106: */
1.49 rillig 107: int printflike_argnum = -1;
108: int scanflike_argnum = -1;
1.31 rillig 109: pos_t printflike_pos;
110: pos_t scanflike_pos;
1.1 cgd 111:
112: /*
1.28 rillig 113: * If both plibflg and llibflg are set, prototypes are written as function
1.1 cgd 114: * definitions to the output file.
115: */
1.59 rillig 116: bool plibflg;
1.1 cgd 117:
118: /*
1.59 rillig 119: * True means that no warnings about constants in conditional
1.6 jpo 120: * context are printed.
1.1 cgd 121: */
1.59 rillig 122: bool constcond_flag;
1.1 cgd 123:
124: /*
1.138 rillig 125: * Whether a lint library shall be created. The effect of this flag is that
126: * all defined symbols are treated as used.
1.1 cgd 127: * (The LINTLIBRARY comment also resets vflag.)
128: */
1.59 rillig 129: bool llibflg;
1.1 cgd 130:
131: /*
1.138 rillig 132: * Determines the warnings that are suppressed by a LINTED directive. For
133: * globally suppressed warnings, see 'msgset'.
134: *
135: * LWARN_ALL: all warnings are enabled
136: * LWARN_NONE: all warnings are suppressed
137: * n >= 0: warning n is ignored, the others are active
1.1 cgd 138: */
1.25 christos 139: int lwarn = LWARN_ALL;
1.6 jpo 140:
141: /*
1.47 rillig 142: * Whether bitfield type errors are suppressed by a BITFIELDTYPE
1.16 thorpej 143: * directive.
144: */
1.47 rillig 145: bool bitfieldtype_ok;
1.16 thorpej 146:
147: /*
1.59 rillig 148: * Whether complaints about use of "long long" are suppressed in
1.6 jpo 149: * the next statement or declaration.
150: */
1.59 rillig 151: bool quadflg;
1.1 cgd 152:
153: /*
154: * Puts a new element at the top of the stack used for control statements.
155: */
156: void
1.96 rillig 157: begin_control_statement(control_statement_kind kind)
1.1 cgd 158: {
1.115 rillig 159: control_statement *cs;
1.1 cgd 160:
1.115 rillig 161: cs = xcalloc(1, sizeof(*cs));
162: cs->c_kind = kind;
163: cs->c_surrounding = cstmt;
164: cstmt = cs;
1.1 cgd 165: }
166:
167: /*
168: * Removes the top element of the stack used for control statements.
169: */
170: void
1.96 rillig 171: end_control_statement(control_statement_kind kind)
1.1 cgd 172: {
1.115 rillig 173: control_statement *cs;
1.79 rillig 174: case_label_t *cl, *next;
1.1 cgd 175:
1.48 rillig 176: lint_assert(cstmt != NULL);
1.110 rillig 177:
178: while (cstmt->c_kind != kind)
179: cstmt = cstmt->c_surrounding;
1.1 cgd 180:
1.115 rillig 181: cs = cstmt;
182: cstmt = cs->c_surrounding;
1.1 cgd 183:
1.115 rillig 184: for (cl = cs->c_case_labels; cl != NULL; cl = next) {
1.63 rillig 185: next = cl->cl_next;
1.1 cgd 186: free(cl);
187: }
188:
1.115 rillig 189: free(cs->c_switch_type);
190: free(cs);
1.1 cgd 191: }
192:
1.93 rillig 193: static void
194: set_reached(bool new_reached)
195: {
1.118 rillig 196: debug_step("%s -> %s",
1.106 rillig 197: reached ? "reachable" : "unreachable",
198: new_reached ? "reachable" : "unreachable");
1.93 rillig 199: reached = new_reached;
1.94 rillig 200: warn_about_unreachable = true;
1.93 rillig 201: }
202:
1.1 cgd 203: /*
204: * Prints a warning if a statement cannot be reached.
205: */
206: void
1.31 rillig 207: check_statement_reachable(void)
1.1 cgd 208: {
1.94 rillig 209: if (!reached && warn_about_unreachable) {
1.1 cgd 210: /* statement not reached */
211: warning(193);
1.95 rillig 212: warn_about_unreachable = false;
1.1 cgd 213: }
214: }
215:
216: /*
217: * Called after a function declaration which introduces a function definition
218: * and before an (optional) old style argument declaration list.
219: *
1.28 rillig 220: * Puts all symbols declared in the prototype or in an old style argument
1.1 cgd 221: * list back to the symbol table.
222: *
223: * Does the usual checking of storage class, type (return value),
1.28 rillig 224: * redeclaration, etc.
1.1 cgd 225: */
226: void
1.14 lukem 227: funcdef(sym_t *fsym)
1.1 cgd 228: {
1.59 rillig 229: int n;
230: bool dowarn;
1.1 cgd 231: sym_t *arg, *sym, *rdsym;
232:
233: funcsym = fsym;
234:
235: /*
236: * Put all symbols declared in the argument list back to the
237: * symbol table.
238: */
1.128 rillig 239: for (sym = dcs->d_func_proto_syms; sym != NULL;
240: sym = sym->s_level_next) {
1.77 rillig 241: if (sym->s_block_level != -1) {
242: lint_assert(sym->s_block_level == 1);
1.1 cgd 243: inssym(1, sym);
244: }
245: }
246:
247: /*
1.29 rillig 248: * In old_style_function() we did not know whether it is an old
249: * style function definition or only an old style declaration,
250: * if there are no arguments inside the argument list ("f()").
1.1 cgd 251: */
1.131 rillig 252: if (!fsym->s_type->t_proto && fsym->u.s_old_style_args == NULL)
1.59 rillig 253: fsym->s_osdef = true;
1.1 cgd 254:
1.29 rillig 255: check_type(fsym);
1.1 cgd 256:
257: /*
1.29 rillig 258: * check_type() checks for almost all possible errors, but not for
1.1 cgd 259: * incomplete return values (these are allowed in declarations)
260: */
261: if (fsym->s_type->t_subt->t_tspec != VOID &&
1.66 rillig 262: is_incomplete(fsym->s_type->t_subt)) {
1.1 cgd 263: /* cannot return incomplete type */
264: error(67);
265: }
266:
1.4 jpo 267: fsym->s_def = DEF;
1.1 cgd 268:
269: if (fsym->s_scl == TYPEDEF) {
270: fsym->s_scl = EXTERN;
271: /* illegal storage class */
272: error(8);
273: }
274:
1.4 jpo 275: if (dcs->d_inline)
1.59 rillig 276: fsym->s_inline = true;
1.4 jpo 277:
1.1 cgd 278: /*
279: * Arguments in new style function declarations need a name.
280: * (void is already removed from the list of arguments)
281: */
282: n = 1;
1.32 rillig 283: for (arg = fsym->s_type->t_args; arg != NULL; arg = arg->s_next) {
1.1 cgd 284: if (arg->s_scl == ABSTRACT) {
1.41 rillig 285: lint_assert(arg->s_name == unnamed);
1.141 rillig 286: /* formal parameter #%d lacks name */
1.1 cgd 287: error(59, n);
288: } else {
1.41 rillig 289: lint_assert(arg->s_name != unnamed);
1.1 cgd 290: }
291: n++;
292: }
293:
294: /*
1.35 rillig 295: * We must also remember the position. s_def_pos is overwritten
1.1 cgd 296: * if this is an old style definition and we had already a
297: * prototype.
298: */
1.81 rillig 299: dcs->d_func_def_pos = fsym->s_def_pos;
1.1 cgd 300:
1.80 rillig 301: if ((rdsym = dcs->d_redeclared_symbol) != NULL) {
1.1 cgd 302:
1.59 rillig 303: if (!check_redeclaration(fsym, (dowarn = false, &dowarn))) {
1.1 cgd 304:
305: /*
1.5 jpo 306: * Print nothing if the newly defined function
1.1 cgd 307: * is defined in old style. A better warning will
1.38 rillig 308: * be printed in check_func_lint_directives().
1.1 cgd 309: */
1.24 dholland 310: if (dowarn && !fsym->s_osdef) {
1.135 rillig 311: /* TODO: error in C99 mode as well? */
312: if (!allow_trad && !allow_c99)
1.139 rillig 313: /* redeclaration of '%s' */
1.50 rillig 314: error(27, fsym->s_name);
315: else
1.139 rillig 316: /* redeclaration of '%s' */
1.50 rillig 317: warning(27, fsym->s_name);
1.29 rillig 318: print_previous_declaration(-1, rdsym);
1.1 cgd 319: }
320:
1.29 rillig 321: copy_usage_info(fsym, rdsym);
1.1 cgd 322:
323: /*
324: * If the old symbol was a prototype and the new
325: * one is none, overtake the position of the
326: * declaration of the prototype.
327: */
328: if (fsym->s_osdef && rdsym->s_type->t_proto)
1.36 rillig 329: fsym->s_def_pos = rdsym->s_def_pos;
1.1 cgd 330:
1.29 rillig 331: complete_type(fsym, rdsym);
1.1 cgd 332:
1.4 jpo 333: if (rdsym->s_inline)
1.59 rillig 334: fsym->s_inline = true;
1.4 jpo 335:
1.1 cgd 336: }
337:
338: /* remove the old symbol from the symbol table */
339: rmsym(rdsym);
340:
341: }
342:
343: if (fsym->s_osdef && !fsym->s_type->t_proto) {
1.135 rillig 344: /* TODO: Make this an error in C99 mode as well. */
345: if ((!allow_trad && !allow_c99) && hflag &&
346: strcmp(fsym->s_name, "main") != 0)
1.28 rillig 347: /* function definition is not a prototype */
1.1 cgd 348: warning(286);
349: }
350:
1.3 jpo 351: if (dcs->d_notyp)
1.69 rillig 352: fsym->s_return_type_implicit_int = true;
1.1 cgd 353:
1.93 rillig 354: set_reached(true);
1.1 cgd 355: }
356:
1.72 rillig 357: static void
358: check_missing_return_value(void)
359: {
360: if (funcsym->s_type->t_subt->t_tspec == VOID)
361: return;
362: if (funcsym->s_return_type_implicit_int)
363: return;
364:
365: /* C99 5.1.2.2.3 "Program termination" p1 */
1.133 rillig 366: if (allow_c99 && strcmp(funcsym->s_name, "main") == 0)
1.72 rillig 367: return;
368:
1.142 ! rillig 369: /* function '%s' falls off bottom without returning value */
1.72 rillig 370: warning(217, funcsym->s_name);
371: }
372:
1.1 cgd 373: /*
374: * Called at the end of a function definition.
375: */
376: void
1.14 lukem 377: funcend(void)
1.1 cgd 378: {
379: sym_t *arg;
380: int n;
381:
382: if (reached) {
1.63 rillig 383: cstmt->c_had_return_noval = true;
1.72 rillig 384: check_missing_return_value();
1.1 cgd 385: }
386:
387: /*
1.22 perry 388: * This warning is printed only if the return value was implicitly
1.1 cgd 389: * declared to be int. Otherwise the wrong return statement
390: * has already printed a warning.
391: */
1.63 rillig 392: if (cstmt->c_had_return_noval && cstmt->c_had_return_value &&
1.69 rillig 393: funcsym->s_return_type_implicit_int)
1.142 ! rillig 394: /* function '%s' has 'return expr' and 'return' */
1.1 cgd 395: warning(216, funcsym->s_name);
396:
397: /* Print warnings for unused arguments */
1.81 rillig 398: arg = dcs->d_func_args;
1.1 cgd 399: n = 0;
400: while (arg != NULL && (nargusg == -1 || n < nargusg)) {
1.29 rillig 401: check_usage_sym(dcs->d_asm, arg);
1.32 rillig 402: arg = arg->s_next;
1.1 cgd 403: n++;
404: }
405: nargusg = -1;
406:
407: /*
1.4 jpo 408: * write the information about the function definition to the
1.1 cgd 409: * output file
1.15 wiz 410: * inline functions explicitly declared extern are written as
1.4 jpo 411: * declarations only.
1.1 cgd 412: */
1.4 jpo 413: if (dcs->d_scl == EXTERN && funcsym->s_inline) {
414: outsym(funcsym, funcsym->s_scl, DECL);
415: } else {
1.81 rillig 416: outfdef(funcsym, &dcs->d_func_def_pos,
417: cstmt->c_had_return_value, funcsym->s_osdef,
418: dcs->d_func_args);
1.1 cgd 419: }
420:
1.111 rillig 421: /* clean up after syntax errors, see test stmt_for.c. */
1.129 rillig 422: while (dcs->d_enclosing != NULL)
423: dcs = dcs->d_enclosing;
1.111 rillig 424:
1.1 cgd 425: /*
426: * remove all symbols declared during argument declaration from
427: * the symbol table
428: */
1.129 rillig 429: lint_assert(dcs->d_enclosing == NULL);
1.132 rillig 430: lint_assert(dcs->d_kind == DK_EXTERN);
1.81 rillig 431: rmsyms(dcs->d_func_proto_syms);
1.1 cgd 432:
433: /* must be set on level 0 */
1.93 rillig 434: set_reached(true);
1.1 cgd 435: }
436:
437: void
1.42 rillig 438: named_label(sym_t *sym)
439: {
440:
441: if (sym->s_set) {
1.142 ! rillig 442: /* label '%s' redefined */
1.42 rillig 443: error(194, sym->s_name);
444: } else {
445: mark_as_set(sym);
446: }
447:
1.93 rillig 448: set_reached(true);
1.42 rillig 449: }
450:
1.43 rillig 451: static void
1.108 rillig 452: check_case_label_bitand(const tnode_t *case_expr, const tnode_t *switch_expr)
453: {
454: uint64_t case_value, mask;
455:
456: if (switch_expr->tn_op != BITAND ||
457: switch_expr->tn_right->tn_op != CON)
458: return;
459:
460: lint_assert(case_expr->tn_op == CON);
461: case_value = case_expr->tn_val->v_quad;
462: mask = switch_expr->tn_right->tn_val->v_quad;
463:
464: if ((case_value & ~mask) != 0) {
465: /* statement not reached */
466: warning(193);
467: }
468: }
469:
470: static void
1.115 rillig 471: check_case_label_enum(const tnode_t *tn, const control_statement *cs)
1.75 rillig 472: {
473: /* similar to typeok_enum in tree.c */
474:
1.115 rillig 475: if (!(tn->tn_type->t_is_enum || cs->c_switch_type->t_is_enum))
1.75 rillig 476: return;
1.115 rillig 477: if (tn->tn_type->t_is_enum && cs->c_switch_type->t_is_enum &&
478: tn->tn_type->t_enum == cs->c_switch_type->t_enum)
1.75 rillig 479: return;
480:
1.76 rillig 481: #if 0 /* not yet ready, see msg_130.c */
1.75 rillig 482: /* enum type mismatch: '%s' '%s' '%s' */
1.115 rillig 483: warning(130, type_name(cs->c_switch_type), op_name(EQ),
1.75 rillig 484: type_name(tn->tn_type));
1.76 rillig 485: #endif
1.75 rillig 486: }
487:
488: static void
1.115 rillig 489: check_case_label(tnode_t *tn, control_statement *cs)
1.1 cgd 490: {
1.79 rillig 491: case_label_t *cl;
1.11 itohy 492: val_t *v;
493: val_t nv;
1.1 cgd 494: tspec_t t;
495:
1.115 rillig 496: if (cs == NULL) {
1.42 rillig 497: /* case not in switch */
498: error(195);
1.43 rillig 499: return;
500: }
501:
502: if (tn != NULL && tn->tn_op != CON) {
1.42 rillig 503: /* non-constant case expression */
504: error(197);
1.43 rillig 505: return;
506: }
507:
1.55 rillig 508: if (tn != NULL && !is_integer(tn->tn_type->t_tspec)) {
1.42 rillig 509: /* non-integral case expression */
510: error(198);
1.43 rillig 511: return;
1.42 rillig 512: }
1.1 cgd 513:
1.115 rillig 514: check_case_label_bitand(tn, cs->c_switch_expr);
515: check_case_label_enum(tn, cs);
1.75 rillig 516:
1.115 rillig 517: lint_assert(cs->c_switch_type != NULL);
1.1 cgd 518:
1.78 rillig 519: if (reached && !seen_fallthrough) {
1.43 rillig 520: if (hflag)
521: /* fallthrough on case statement */
522: warning(220);
523: }
1.1 cgd 524:
1.43 rillig 525: t = tn->tn_type->t_tspec;
526: if (t == LONG || t == ULONG ||
527: t == QUAD || t == UQUAD) {
1.134 rillig 528: if (!allow_c90)
1.120 rillig 529: /* case label must be of type 'int' in traditional C */
1.43 rillig 530: warning(203);
531: }
1.1 cgd 532:
1.43 rillig 533: /*
534: * get the value of the expression and convert it
535: * to the type of the switch expression
536: */
1.60 rillig 537: v = constant(tn, true);
1.101 rillig 538: (void)memset(&nv, 0, sizeof(nv));
1.115 rillig 539: convert_constant(CASE, 0, cs->c_switch_type, &nv, v);
1.43 rillig 540: free(v);
541:
542: /* look if we had this value already */
1.115 rillig 543: for (cl = cs->c_case_labels; cl != NULL; cl = cl->cl_next) {
1.43 rillig 544: if (cl->cl_val.v_quad == nv.v_quad)
545: break;
546: }
1.55 rillig 547: if (cl != NULL && is_uinteger(nv.v_tspec)) {
1.43 rillig 548: /* duplicate case in switch: %lu */
1.121 rillig 549: error(200, (unsigned long)nv.v_quad);
1.43 rillig 550: } else if (cl != NULL) {
551: /* duplicate case in switch: %ld */
552: error(199, (long)nv.v_quad);
553: } else {
1.68 rillig 554: check_getopt_case_label(nv.v_quad);
555:
1.103 rillig 556: /* append the value to the list of case values */
1.101 rillig 557: cl = xcalloc(1, sizeof(*cl));
1.43 rillig 558: cl->cl_val = nv;
1.115 rillig 559: cl->cl_next = cs->c_case_labels;
560: cs->c_case_labels = cl;
1.42 rillig 561: }
1.43 rillig 562: }
563:
564: void
565: case_label(tnode_t *tn)
566: {
1.115 rillig 567: control_statement *cs;
1.43 rillig 568:
1.51 rillig 569: /* find the innermost switch statement */
1.115 rillig 570: for (cs = cstmt; cs != NULL && !cs->c_switch; cs = cs->c_surrounding)
1.43 rillig 571: continue;
572:
1.115 rillig 573: check_case_label(tn, cs);
1.43 rillig 574:
1.99 rillig 575: expr_free_all();
1.42 rillig 576:
1.93 rillig 577: set_reached(true);
1.42 rillig 578: }
579:
580: void
581: default_label(void)
582: {
1.115 rillig 583: control_statement *cs;
1.1 cgd 584:
1.51 rillig 585: /* find the innermost switch statement */
1.115 rillig 586: for (cs = cstmt; cs != NULL && !cs->c_switch; cs = cs->c_surrounding)
1.42 rillig 587: continue;
1.1 cgd 588:
1.115 rillig 589: if (cs == NULL) {
1.42 rillig 590: /* default outside switch */
591: error(201);
1.115 rillig 592: } else if (cs->c_default) {
1.42 rillig 593: /* duplicate default in switch */
594: error(202);
595: } else {
1.78 rillig 596: if (reached && !seen_fallthrough) {
1.42 rillig 597: if (hflag)
598: /* fallthrough on default statement */
599: warning(284);
1.1 cgd 600: }
1.115 rillig 601: cs->c_default = true;
1.42 rillig 602: }
603:
1.93 rillig 604: set_reached(true);
1.1 cgd 605: }
606:
1.39 rillig 607: static tnode_t *
608: check_controlling_expression(tnode_t *tn)
609: {
610:
1.124 rillig 611: tn = cconv(tn);
1.39 rillig 612: if (tn != NULL)
1.60 rillig 613: tn = promote(NOOP, false, tn);
1.39 rillig 614:
1.55 rillig 615: if (tn != NULL && !is_scalar(tn->tn_type->t_tspec)) {
1.39 rillig 616: /* C99 6.5.15p4 for the ?: operator; see typeok:QUEST */
617: /* C99 6.8.4.1p1 for if statements */
618: /* C99 6.8.5p2 for while, do and for loops */
619: /* controlling expressions must have scalar type */
620: error(204);
621: return NULL;
622: }
623:
1.140 rillig 624: if (tn != NULL && Tflag && !is_typeok_bool_compares_with_zero(tn)) {
1.57 rillig 625: /* controlling expression must be bool, not '%s' */
626: error(333, tspec_name(tn->tn_type->t_tspec));
627: }
628:
1.39 rillig 629: return tn;
630: }
631:
1.1 cgd 632: /*
1.44 rillig 633: * T_IF T_LPAREN expr T_RPAREN
1.1 cgd 634: */
635: void
1.14 lukem 636: if1(tnode_t *tn)
1.1 cgd 637: {
1.14 lukem 638:
1.1 cgd 639: if (tn != NULL)
1.39 rillig 640: tn = check_controlling_expression(tn);
1.1 cgd 641: if (tn != NULL)
1.67 rillig 642: expr(tn, false, true, false, false);
1.96 rillig 643: begin_control_statement(CS_IF);
1.88 rillig 644:
645: if (tn != NULL && tn->tn_op == CON && !tn->tn_system_dependent) {
1.93 rillig 646: /* XXX: what if inside 'if (0)'? */
647: set_reached(constant_is_nonzero(tn));
648: /* XXX: what about always_else? */
1.88 rillig 649: cstmt->c_always_then = reached;
650: }
1.1 cgd 651: }
652:
653: /*
654: * if_without_else
655: * if_without_else T_ELSE
656: */
657: void
1.14 lukem 658: if2(void)
1.1 cgd 659: {
1.14 lukem 660:
1.87 rillig 661: cstmt->c_reached_end_of_then = reached;
1.93 rillig 662: /* XXX: what if inside 'if (0)'? */
663: set_reached(!cstmt->c_always_then);
1.1 cgd 664: }
665:
666: /*
667: * if_without_else
1.54 rillig 668: * if_without_else T_ELSE statement
1.1 cgd 669: */
670: void
1.59 rillig 671: if3(bool els)
1.1 cgd 672: {
1.90 rillig 673: if (cstmt->c_reached_end_of_then)
1.93 rillig 674: set_reached(true);
1.90 rillig 675: else if (cstmt->c_always_then)
1.93 rillig 676: set_reached(false);
1.90 rillig 677: else if (!els)
1.93 rillig 678: set_reached(true);
1.14 lukem 679:
1.96 rillig 680: end_control_statement(CS_IF);
1.1 cgd 681: }
682:
683: /*
1.44 rillig 684: * T_SWITCH T_LPAREN expr T_RPAREN
1.1 cgd 685: */
686: void
1.14 lukem 687: switch1(tnode_t *tn)
1.1 cgd 688: {
689: tspec_t t;
690: type_t *tp;
691:
692: if (tn != NULL)
693: tn = cconv(tn);
694: if (tn != NULL)
1.60 rillig 695: tn = promote(NOOP, false, tn);
1.55 rillig 696: if (tn != NULL && !is_integer(tn->tn_type->t_tspec)) {
1.1 cgd 697: /* switch expression must have integral type */
698: error(205);
699: tn = NULL;
700: }
1.134 rillig 701: if (tn != NULL && !allow_c90) {
1.1 cgd 702: t = tn->tn_type->t_tspec;
703: if (t == LONG || t == ULONG || t == QUAD || t == UQUAD) {
1.123 rillig 704: /* switch expression must be of type 'int' in ... */
1.1 cgd 705: warning(271);
706: }
707: }
708:
709: /*
1.37 rillig 710: * Remember the type of the expression. Because it's possible
711: * that (*tp) is allocated on tree memory, the type must be
1.1 cgd 712: * duplicated. This is not too complicated because it is
713: * only an integer type.
714: */
1.101 rillig 715: tp = xcalloc(1, sizeof(*tp));
1.1 cgd 716: if (tn != NULL) {
717: tp->t_tspec = tn->tn_type->t_tspec;
1.71 rillig 718: if ((tp->t_is_enum = tn->tn_type->t_is_enum) != false)
1.1 cgd 719: tp->t_enum = tn->tn_type->t_enum;
720: } else {
721: tp->t_tspec = INT;
722: }
723:
1.108 rillig 724: /* leak the memory, for check_case_label_bitand */
1.122 rillig 725: (void)expr_save_memory();
1.108 rillig 726:
1.68 rillig 727: check_getopt_begin_switch();
1.108 rillig 728: expr(tn, true, false, false, false);
1.1 cgd 729:
1.96 rillig 730: begin_control_statement(CS_SWITCH);
1.59 rillig 731: cstmt->c_switch = true;
1.97 rillig 732: cstmt->c_switch_type = tp;
1.108 rillig 733: cstmt->c_switch_expr = tn;
1.1 cgd 734:
1.93 rillig 735: set_reached(false);
1.78 rillig 736: seen_fallthrough = true;
1.1 cgd 737: }
738:
739: /*
1.54 rillig 740: * switch_expr statement
1.1 cgd 741: */
742: void
1.14 lukem 743: switch2(void)
1.1 cgd 744: {
1.8 christos 745: int nenum = 0, nclab = 0;
1.1 cgd 746: sym_t *esym;
1.79 rillig 747: case_label_t *cl;
1.1 cgd 748:
1.97 rillig 749: lint_assert(cstmt->c_switch_type != NULL);
1.1 cgd 750:
1.97 rillig 751: if (cstmt->c_switch_type->t_is_enum) {
1.112 rillig 752: /*
753: * Warn if the number of case labels is different from the
754: * number of enumerators.
755: */
1.1 cgd 756: nenum = nclab = 0;
1.97 rillig 757: lint_assert(cstmt->c_switch_type->t_enum != NULL);
758: for (esym = cstmt->c_switch_type->t_enum->en_first_enumerator;
1.32 rillig 759: esym != NULL; esym = esym->s_next) {
1.1 cgd 760: nenum++;
761: }
1.79 rillig 762: for (cl = cstmt->c_case_labels; cl != NULL; cl = cl->cl_next)
1.1 cgd 763: nclab++;
1.137 rillig 764: if (hflag && eflag && nclab < nenum && !cstmt->c_default) {
1.1 cgd 765: /* enumeration value(s) not handled in switch */
766: warning(206);
767: }
768: }
769:
1.68 rillig 770: check_getopt_end_switch();
771:
1.48 rillig 772: if (cstmt->c_break) {
1.1 cgd 773: /*
1.112 rillig 774: * The end of the switch statement is always reached since
775: * c_break is only set if a break statement can actually
776: * be reached.
1.1 cgd 777: */
1.93 rillig 778: set_reached(true);
1.112 rillig 779: } else if (cstmt->c_default ||
780: (hflag && cstmt->c_switch_type->t_is_enum &&
781: nenum == nclab)) {
1.1 cgd 782: /*
1.112 rillig 783: * The end of the switch statement is reached if the end
784: * of the last statement inside it is reached.
785: */
786: } else {
787: /*
788: * There are possible values that are not handled in the
789: * switch statement.
1.1 cgd 790: */
1.93 rillig 791: set_reached(true);
1.112 rillig 792: }
1.1 cgd 793:
1.96 rillig 794: end_control_statement(CS_SWITCH);
1.1 cgd 795: }
796:
797: /*
1.44 rillig 798: * T_WHILE T_LPAREN expr T_RPAREN
1.1 cgd 799: */
800: void
1.14 lukem 801: while1(tnode_t *tn)
1.1 cgd 802: {
1.92 rillig 803: bool body_reached;
1.14 lukem 804:
1.1 cgd 805: if (!reached) {
806: /* loop not entered at top */
807: warning(207);
1.93 rillig 808: /* FIXME: that's plain wrong. */
809: set_reached(true);
1.1 cgd 810: }
811:
812: if (tn != NULL)
1.39 rillig 813: tn = check_controlling_expression(tn);
1.1 cgd 814:
1.96 rillig 815: begin_control_statement(CS_WHILE);
1.59 rillig 816: cstmt->c_loop = true;
1.92 rillig 817: cstmt->c_maybe_endless = is_nonzero(tn);
818: body_reached = !is_zero(tn);
1.1 cgd 819:
1.68 rillig 820: check_getopt_begin_while(tn);
1.67 rillig 821: expr(tn, false, true, true, false);
1.92 rillig 822:
1.93 rillig 823: set_reached(body_reached);
1.1 cgd 824: }
825:
826: /*
1.54 rillig 827: * while_expr statement
1.1 cgd 828: * while_expr error
829: */
830: void
1.14 lukem 831: while2(void)
1.1 cgd 832: {
1.14 lukem 833:
1.1 cgd 834: /*
835: * The end of the loop can be reached if it is no endless loop
836: * or there was a break statement which was reached.
837: */
1.93 rillig 838: set_reached(!cstmt->c_maybe_endless || cstmt->c_break);
1.1 cgd 839:
1.68 rillig 840: check_getopt_end_while();
1.96 rillig 841: end_control_statement(CS_WHILE);
1.1 cgd 842: }
843:
844: /*
845: * T_DO
846: */
847: void
1.14 lukem 848: do1(void)
1.1 cgd 849: {
1.14 lukem 850:
1.1 cgd 851: if (!reached) {
852: /* loop not entered at top */
853: warning(207);
1.93 rillig 854: set_reached(true);
1.1 cgd 855: }
856:
1.96 rillig 857: begin_control_statement(CS_DO_WHILE);
1.59 rillig 858: cstmt->c_loop = true;
1.1 cgd 859: }
860:
861: /*
1.54 rillig 862: * do statement do_while_expr
1.1 cgd 863: * do error
864: */
865: void
1.14 lukem 866: do2(tnode_t *tn)
1.1 cgd 867: {
1.14 lukem 868:
1.1 cgd 869: /*
1.28 rillig 870: * If there was a continue statement, the expression controlling the
1.1 cgd 871: * loop is reached.
872: */
1.85 rillig 873: if (cstmt->c_continue)
1.93 rillig 874: set_reached(true);
1.1 cgd 875:
876: if (tn != NULL)
1.39 rillig 877: tn = check_controlling_expression(tn);
1.1 cgd 878:
879: if (tn != NULL && tn->tn_op == CON) {
1.84 rillig 880: cstmt->c_maybe_endless = constant_is_nonzero(tn);
1.85 rillig 881: if (!cstmt->c_maybe_endless && cstmt->c_continue)
1.46 rillig 882: /* continue in 'do ... while (0)' loop */
883: error(323);
1.1 cgd 884: }
885:
1.67 rillig 886: expr(tn, false, true, true, true);
1.1 cgd 887:
1.84 rillig 888: if (cstmt->c_maybe_endless)
1.93 rillig 889: set_reached(false);
1.83 rillig 890: if (cstmt->c_break)
1.93 rillig 891: set_reached(true);
1.1 cgd 892:
1.96 rillig 893: end_control_statement(CS_DO_WHILE);
1.1 cgd 894: }
895:
896: /*
1.44 rillig 897: * T_FOR T_LPAREN opt_expr T_SEMI opt_expr T_SEMI opt_expr T_RPAREN
1.1 cgd 898: */
899: void
1.14 lukem 900: for1(tnode_t *tn1, tnode_t *tn2, tnode_t *tn3)
1.1 cgd 901: {
1.14 lukem 902:
1.1 cgd 903: /*
1.73 rillig 904: * If there is no initialization expression it is possible that
1.1 cgd 905: * it is intended not to enter the loop at top.
906: */
907: if (tn1 != NULL && !reached) {
908: /* loop not entered at top */
909: warning(207);
1.93 rillig 910: set_reached(true);
1.1 cgd 911: }
912:
1.96 rillig 913: begin_control_statement(CS_FOR);
1.59 rillig 914: cstmt->c_loop = true;
1.1 cgd 915:
916: /*
1.73 rillig 917: * Store the tree memory for the reinitialization expression.
1.1 cgd 918: * Also remember this expression itself. We must check it at
919: * the end of the loop to get "used but not set" warnings correct.
920: */
1.99 rillig 921: cstmt->c_for_expr3_mem = expr_save_memory();
1.97 rillig 922: cstmt->c_for_expr3 = tn3;
923: cstmt->c_for_expr3_pos = curr_pos;
924: cstmt->c_for_expr3_csrc_pos = csrc_pos;
1.1 cgd 925:
926: if (tn1 != NULL)
1.67 rillig 927: expr(tn1, false, false, true, false);
1.1 cgd 928:
929: if (tn2 != NULL)
1.39 rillig 930: tn2 = check_controlling_expression(tn2);
1.1 cgd 931: if (tn2 != NULL)
1.67 rillig 932: expr(tn2, false, true, true, false);
1.1 cgd 933:
1.91 rillig 934: cstmt->c_maybe_endless = tn2 == NULL || is_nonzero(tn2);
1.1 cgd 935:
1.73 rillig 936: /* Checking the reinitialization expression is done in for2() */
1.1 cgd 937:
1.93 rillig 938: set_reached(!is_zero(tn2));
1.1 cgd 939: }
940:
941: /*
1.54 rillig 942: * for_exprs statement
1.1 cgd 943: * for_exprs error
944: */
945: void
1.14 lukem 946: for2(void)
1.1 cgd 947: {
948: pos_t cpos, cspos;
949: tnode_t *tn3;
950:
1.85 rillig 951: if (cstmt->c_continue)
1.93 rillig 952: set_reached(true);
1.1 cgd 953:
1.36 rillig 954: cpos = curr_pos;
955: cspos = csrc_pos;
1.1 cgd 956:
1.73 rillig 957: /* Restore the tree memory for the reinitialization expression */
1.99 rillig 958: expr_restore_memory(cstmt->c_for_expr3_mem);
1.97 rillig 959: tn3 = cstmt->c_for_expr3;
960: curr_pos = cstmt->c_for_expr3_pos;
961: csrc_pos = cstmt->c_for_expr3_csrc_pos;
1.1 cgd 962:
963: /* simply "statement not reached" would be confusing */
1.94 rillig 964: if (!reached && warn_about_unreachable) {
1.1 cgd 965: /* end-of-loop code not reached */
966: warning(223);
1.93 rillig 967: set_reached(true);
1.1 cgd 968: }
969:
970: if (tn3 != NULL) {
1.67 rillig 971: expr(tn3, false, false, true, false);
1.1 cgd 972: } else {
1.99 rillig 973: expr_free_all();
1.1 cgd 974: }
975:
1.36 rillig 976: curr_pos = cpos;
977: csrc_pos = cspos;
1.1 cgd 978:
979: /* An endless loop without break will never terminate */
1.84 rillig 980: /* TODO: What if the loop contains a 'return'? */
1.93 rillig 981: set_reached(cstmt->c_break || !cstmt->c_maybe_endless);
1.1 cgd 982:
1.96 rillig 983: end_control_statement(CS_FOR);
1.1 cgd 984: }
985:
986: /*
987: * T_GOTO identifier T_SEMI
988: */
989: void
1.89 rillig 990: do_goto(sym_t *lab)
1.1 cgd 991: {
1.14 lukem 992:
1.60 rillig 993: mark_as_used(lab, false, false);
1.1 cgd 994:
1.31 rillig 995: check_statement_reachable();
1.1 cgd 996:
1.93 rillig 997: set_reached(false);
1.1 cgd 998: }
999:
1000: /*
1001: * T_BREAK T_SEMI
1002: */
1003: void
1.89 rillig 1004: do_break(void)
1.1 cgd 1005: {
1.115 rillig 1006: control_statement *cs;
1.1 cgd 1007:
1.115 rillig 1008: cs = cstmt;
1009: while (cs != NULL && !cs->c_loop && !cs->c_switch)
1010: cs = cs->c_surrounding;
1.1 cgd 1011:
1.115 rillig 1012: if (cs == NULL) {
1.1 cgd 1013: /* break outside loop or switch */
1014: error(208);
1015: } else {
1016: if (reached)
1.115 rillig 1017: cs->c_break = true;
1.1 cgd 1018: }
1019:
1020: if (bflag)
1.31 rillig 1021: check_statement_reachable();
1.1 cgd 1022:
1.93 rillig 1023: set_reached(false);
1.1 cgd 1024: }
1025:
1026: /*
1027: * T_CONTINUE T_SEMI
1028: */
1029: void
1.89 rillig 1030: do_continue(void)
1.1 cgd 1031: {
1.115 rillig 1032: control_statement *cs;
1.1 cgd 1033:
1.115 rillig 1034: for (cs = cstmt; cs != NULL && !cs->c_loop; cs = cs->c_surrounding)
1.14 lukem 1035: continue;
1.1 cgd 1036:
1.115 rillig 1037: if (cs == NULL) {
1.1 cgd 1038: /* continue outside loop */
1039: error(209);
1040: } else {
1.85 rillig 1041: /* TODO: only if reachable, for symmetry with c_break */
1.115 rillig 1042: cs->c_continue = true;
1.1 cgd 1043: }
1044:
1.31 rillig 1045: check_statement_reachable();
1.1 cgd 1046:
1.93 rillig 1047: set_reached(false);
1.1 cgd 1048: }
1049:
1050: /*
1051: * T_RETURN T_SEMI
1052: * T_RETURN expr T_SEMI
1053: */
1054: void
1.126 rillig 1055: do_return(bool sys, tnode_t *tn)
1.1 cgd 1056: {
1057: tnode_t *ln, *rn;
1.115 rillig 1058: control_statement *cs;
1.1 cgd 1059: op_t op;
1060:
1.115 rillig 1061: cs = cstmt;
1062: if (cs == NULL) {
1.109 rillig 1063: /* syntax error '%s' */
1064: error(249, "return outside function");
1065: return;
1066: }
1067:
1.115 rillig 1068: for (; cs->c_surrounding != NULL; cs = cs->c_surrounding)
1.14 lukem 1069: continue;
1.1 cgd 1070:
1.82 rillig 1071: if (tn != NULL)
1.115 rillig 1072: cs->c_had_return_value = true;
1.82 rillig 1073: else
1.115 rillig 1074: cs->c_had_return_noval = true;
1.1 cgd 1075:
1076: if (tn != NULL && funcsym->s_type->t_subt->t_tspec == VOID) {
1.142 ! rillig 1077: /* void function '%s' cannot return value */
1.1 cgd 1078: error(213, funcsym->s_name);
1.99 rillig 1079: expr_free_all();
1.1 cgd 1080: tn = NULL;
1081: } else if (tn == NULL && funcsym->s_type->t_subt->t_tspec != VOID) {
1082: /*
1083: * Assume that the function has a return value only if it
1084: * is explicitly declared.
1085: */
1.69 rillig 1086: if (!funcsym->s_return_type_implicit_int)
1.119 rillig 1087: /* function '%s' expects to return value */
1.1 cgd 1088: warning(214, funcsym->s_name);
1089: }
1090:
1091: if (tn != NULL) {
1092:
1093: /* Create a temporary node for the left side */
1.127 rillig 1094: ln = expr_zero_alloc(sizeof(*ln));
1.1 cgd 1095: ln->tn_op = NAME;
1.116 rillig 1096: ln->tn_type = expr_unqualified_type(funcsym->s_type->t_subt);
1.59 rillig 1097: ln->tn_lvalue = true;
1.1 cgd 1098: ln->tn_sym = funcsym; /* better than nothing */
1099:
1.126 rillig 1100: tn = build_binary(ln, RETURN, sys, tn);
1.1 cgd 1101:
1102: if (tn != NULL) {
1103: rn = tn->tn_right;
1104: while ((op = rn->tn_op) == CVT || op == PLUS)
1105: rn = rn->tn_left;
1.62 rillig 1106: if (rn->tn_op == ADDR && rn->tn_left->tn_op == NAME &&
1.1 cgd 1107: rn->tn_left->tn_sym->s_scl == AUTO) {
1.142 ! rillig 1108: /* '%s' returns pointer to automatic object */
1.1 cgd 1109: warning(302, funcsym->s_name);
1110: }
1111: }
1112:
1.67 rillig 1113: expr(tn, true, false, true, false);
1.1 cgd 1114:
1115: } else {
1116:
1.31 rillig 1117: check_statement_reachable();
1.1 cgd 1118:
1119: }
1120:
1.93 rillig 1121: set_reached(false);
1.1 cgd 1122: }
1123:
1124: /*
1.7 jpo 1125: * Do some cleanup after a global declaration or definition.
1.28 rillig 1126: * Especially remove information about unused lint comments.
1.1 cgd 1127: */
1128: void
1.59 rillig 1129: global_clean_up_decl(bool silent)
1.1 cgd 1130: {
1131:
1132: if (nargusg != -1) {
1.6 jpo 1133: if (!silent) {
1.142 ! rillig 1134: /* comment ** %s ** must precede function definition */
1.105 rillig 1135: warning_at(282, &argsused_pos, "ARGSUSED");
1.1 cgd 1136: }
1137: nargusg = -1;
1138: }
1139: if (nvararg != -1) {
1.6 jpo 1140: if (!silent) {
1.142 ! rillig 1141: /* comment ** %s ** must precede function definition */
1.105 rillig 1142: warning_at(282, &vapos, "VARARGS");
1.1 cgd 1143: }
1144: nvararg = -1;
1145: }
1.49 rillig 1146: if (printflike_argnum != -1) {
1.6 jpo 1147: if (!silent) {
1.142 ! rillig 1148: /* comment ** %s ** must precede function definition */
1.105 rillig 1149: warning_at(282, &printflike_pos, "PRINTFLIKE");
1.1 cgd 1150: }
1.49 rillig 1151: printflike_argnum = -1;
1.1 cgd 1152: }
1.49 rillig 1153: if (scanflike_argnum != -1) {
1.6 jpo 1154: if (!silent) {
1.40 rillig 1155: /* must precede function definition: ** %s ** */
1.105 rillig 1156: warning_at(282, &scanflike_pos, "SCANFLIKE");
1.1 cgd 1157: }
1.49 rillig 1158: scanflike_argnum = -1;
1.1 cgd 1159: }
1160:
1.59 rillig 1161: dcs->d_asm = false;
1.107 rillig 1162:
1163: /*
1164: * Needed for BSD yacc in case of parse errors; GNU Bison 3.0.4 is
1.125 rillig 1165: * fine. See test gcc_attribute.c, function_with_unknown_attribute.
1.107 rillig 1166: */
1.125 rillig 1167: in_gcc_attribute = false;
1.130 rillig 1168: while (dcs->d_enclosing != NULL)
1169: end_declaration_level();
1.1 cgd 1170: }
1171:
1172: /*
1173: * ARGSUSED comment
1174: *
1175: * Only the first n arguments of the following function are checked
1176: * for usage. A missing argument is taken to be 0.
1177: */
1178: void
1.14 lukem 1179: argsused(int n)
1.1 cgd 1180: {
1.14 lukem 1181:
1.1 cgd 1182: if (n == -1)
1183: n = 0;
1184:
1.132 rillig 1185: if (dcs->d_kind != DK_EXTERN) {
1.142 ! rillig 1186: /* comment ** %s ** must be outside function */
1.1 cgd 1187: warning(280, "ARGSUSED");
1188: return;
1189: }
1190: if (nargusg != -1) {
1.142 ! rillig 1191: /* duplicate comment ** %s ** */
1.1 cgd 1192: warning(281, "ARGSUSED");
1193: }
1194: nargusg = n;
1.36 rillig 1195: argsused_pos = curr_pos;
1.1 cgd 1196: }
1197:
1198: /*
1199: * VARARGS comment
1200: *
1.28 rillig 1201: * Causes lint2 to check only the first n arguments for compatibility
1202: * with the function definition. A missing argument is taken to be 0.
1.1 cgd 1203: */
1204: void
1.14 lukem 1205: varargs(int n)
1.1 cgd 1206: {
1.14 lukem 1207:
1.1 cgd 1208: if (n == -1)
1209: n = 0;
1210:
1.132 rillig 1211: if (dcs->d_kind != DK_EXTERN) {
1.142 ! rillig 1212: /* comment ** %s ** must be outside function */
1.1 cgd 1213: warning(280, "VARARGS");
1214: return;
1215: }
1216: if (nvararg != -1) {
1.142 ! rillig 1217: /* duplicate comment ** %s ** */
1.1 cgd 1218: warning(281, "VARARGS");
1219: }
1220: nvararg = n;
1.36 rillig 1221: vapos = curr_pos;
1.1 cgd 1222: }
1223:
1224: /*
1225: * PRINTFLIKE comment
1226: *
1227: * Check all arguments until the (n-1)-th as usual. The n-th argument is
1228: * used the check the types of remaining arguments.
1229: */
1230: void
1.14 lukem 1231: printflike(int n)
1.1 cgd 1232: {
1.14 lukem 1233:
1.1 cgd 1234: if (n == -1)
1235: n = 0;
1236:
1.132 rillig 1237: if (dcs->d_kind != DK_EXTERN) {
1.142 ! rillig 1238: /* comment ** %s ** must be outside function */
1.1 cgd 1239: warning(280, "PRINTFLIKE");
1240: return;
1241: }
1.49 rillig 1242: if (printflike_argnum != -1) {
1.142 ! rillig 1243: /* duplicate comment ** %s ** */
1.1 cgd 1244: warning(281, "PRINTFLIKE");
1245: }
1.49 rillig 1246: printflike_argnum = n;
1.36 rillig 1247: printflike_pos = curr_pos;
1.1 cgd 1248: }
1249:
1250: /*
1251: * SCANFLIKE comment
1252: *
1253: * Check all arguments until the (n-1)-th as usual. The n-th argument is
1254: * used the check the types of remaining arguments.
1255: */
1256: void
1.14 lukem 1257: scanflike(int n)
1.1 cgd 1258: {
1.14 lukem 1259:
1.1 cgd 1260: if (n == -1)
1261: n = 0;
1262:
1.132 rillig 1263: if (dcs->d_kind != DK_EXTERN) {
1.142 ! rillig 1264: /* comment ** %s ** must be outside function */
1.1 cgd 1265: warning(280, "SCANFLIKE");
1266: return;
1267: }
1.49 rillig 1268: if (scanflike_argnum != -1) {
1.142 ! rillig 1269: /* duplicate comment ** %s ** */
1.1 cgd 1270: warning(281, "SCANFLIKE");
1271: }
1.49 rillig 1272: scanflike_argnum = n;
1.36 rillig 1273: scanflike_pos = curr_pos;
1.1 cgd 1274: }
1275:
1276: /*
1.50 rillig 1277: * Set the line number for a CONSTCOND comment. At this and the following
1.1 cgd 1278: * line no warnings about constants in conditional contexts are printed.
1279: */
1280: /* ARGSUSED */
1281: void
1.14 lukem 1282: constcond(int n)
1.1 cgd 1283: {
1.14 lukem 1284:
1.59 rillig 1285: constcond_flag = true;
1.1 cgd 1286: }
1287:
1288: /*
1289: * Suppress printing of "fallthrough on ..." warnings until next
1290: * statement.
1291: */
1292: /* ARGSUSED */
1293: void
1.14 lukem 1294: fallthru(int n)
1.1 cgd 1295: {
1.14 lukem 1296:
1.78 rillig 1297: seen_fallthrough = true;
1.1 cgd 1298: }
1299:
1300: /*
1301: * Stop warnings about statements which cannot be reached. Also tells lint
1302: * that the following statements cannot be reached (e.g. after exit()).
1303: */
1304: /* ARGSUSED */
1305: void
1.89 rillig 1306: not_reached(int n)
1.1 cgd 1307: {
1.14 lukem 1308:
1.93 rillig 1309: set_reached(false);
1.94 rillig 1310: warn_about_unreachable = false;
1.1 cgd 1311: }
1312:
1313: /* ARGSUSED */
1314: void
1.14 lukem 1315: lintlib(int n)
1.1 cgd 1316: {
1.14 lukem 1317:
1.132 rillig 1318: if (dcs->d_kind != DK_EXTERN) {
1.142 ! rillig 1319: /* comment ** %s ** must be outside function */
1.1 cgd 1320: warning(280, "LINTLIBRARY");
1321: return;
1322: }
1.59 rillig 1323: llibflg = true;
1324: vflag = false;
1.1 cgd 1325: }
1326:
1327: /*
1328: * Suppress most warnings at the current and the following line.
1329: */
1330: /* ARGSUSED */
1331: void
1.14 lukem 1332: linted(int n)
1.1 cgd 1333: {
1.14 lukem 1334:
1.118 rillig 1335: debug_step("set lwarn %d", n);
1.25 christos 1336: lwarn = n;
1.16 thorpej 1337: }
1338:
1339: /*
1340: * Suppress bitfield type errors on the current line.
1341: */
1342: /* ARGSUSED */
1343: void
1344: bitfieldtype(int n)
1345: {
1346:
1.117 rillig 1347: debug_step("%s, %d: bitfieldtype_ok = true",
1348: curr_pos.p_file, curr_pos.p_line);
1.47 rillig 1349: bitfieldtype_ok = true;
1.1 cgd 1350: }
1351:
1352: /*
1.28 rillig 1353: * PROTOLIB in conjunction with LINTLIBRARY can be used to handle
1.1 cgd 1354: * prototypes like function definitions. This is done if the argument
1.28 rillig 1355: * to PROTOLIB is nonzero. Otherwise prototypes are handled normally.
1.1 cgd 1356: */
1357: void
1.14 lukem 1358: protolib(int n)
1.1 cgd 1359: {
1.14 lukem 1360:
1.132 rillig 1361: if (dcs->d_kind != DK_EXTERN) {
1.142 ! rillig 1362: /* comment ** %s ** must be outside function */
1.1 cgd 1363: warning(280, "PROTOLIB");
1364: return;
1365: }
1.59 rillig 1366: plibflg = n != 0;
1.6 jpo 1367: }
1368:
1.59 rillig 1369: /* The next statement/declaration may use "long long" without a diagnostic. */
1.6 jpo 1370: /* ARGSUSED */
1371: void
1.14 lukem 1372: longlong(int n)
1.6 jpo 1373: {
1.14 lukem 1374:
1.59 rillig 1375: quadflg = true;
1.1 cgd 1376: }
CVSweb <webmaster@jp.NetBSD.org>