1 /* $NetBSD: err.c,v 1.216 2023/08/03 18:48:42 rillig Exp $ */ 2 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 34 #if HAVE_NBTOOL_CONFIG_H 35 #include "nbtool_config.h" 36 #endif 37 38 #include <sys/cdefs.h> 39 #if defined(__RCSID) 40 __RCSID("$NetBSD: err.c,v 1.216 2023/08/03 18:48:42 rillig Exp $"); 41 #endif 42 43 #include <limits.h> 44 #include <stdarg.h> 45 #include <stdlib.h> 46 #include <string.h> 47 48 #include "lint1.h" 49 50 bool seen_error; 51 bool seen_warning; 52 53 /* number of syntax errors */ 54 int sytxerr; 55 56 57 static const char *const msgs[] = { 58 "empty declaration", /* 0 */ 59 "old-style declaration; add 'int'", /* 1 */ 60 "empty declaration", /* 2 */ 61 "'%s' declared in parameter declaration list", /* 3 */ 62 "illegal type combination", /* 4 */ 63 "modifying typedef with '%s'; only qualifiers allowed", /* 5 */ 64 "use 'double' instead of 'long float'", /* 6 */ 65 "only one storage class allowed", /* 7 */ 66 "illegal storage class", /* 8 */ 67 "only 'register' is valid as storage class in parameter", /* 9 */ 68 "duplicate '%s'", /* 10 */ 69 "bit-field initializer out of range", /* 11 */ 70 "compiler takes size of function", /* 12 */ 71 "incomplete enum type '%s'", /* 13 */ 72 "", /* 14 */ 73 "function returns illegal type '%s'", /* 15 */ 74 "array of function is illegal", /* 16 */ 75 "null dimension", /* 17 */ 76 "illegal use of 'void'", /* 18 */ 77 "void type for '%s'", /* 19 */ 78 "negative array dimension (%d)", /* 20 */ 79 "redeclaration of formal parameter '%s'", /* 21 */ 80 "incomplete or misplaced function definition", /* 22 */ 81 "undefined label '%s'", /* 23 */ 82 "cannot initialize function '%s'", /* 24 */ 83 "cannot initialize typedef '%s'", /* 25 */ 84 "cannot initialize extern declaration '%s'", /* 26 */ 85 "redeclaration of '%s'", /* 27 */ 86 "redefinition of '%s'", /* 28 */ 87 "'%s' was previously declared extern, becomes static", /* 29 */ 88 "redeclaration of '%s'; ANSI C requires static", /* 30 */ 89 "'%s' has incomplete type '%s'", /* 31 */ 90 "type of parameter '%s' defaults to 'int'", /* 32 */ 91 "duplicate member name '%s'", /* 33 */ 92 "nonportable bit-field type '%s'", /* 34 */ 93 "illegal bit-field type '%s'", /* 35 */ 94 "illegal bit-field size: %d", /* 36 */ 95 "zero size bit-field", /* 37 */ 96 "function illegal in structure or union", /* 38 */ 97 "zero-sized array '%s' in struct is a C99 extension", /* 39 */ 98 "", /* never used */ /* 40 */ 99 "bit-field in union is very unusual", /* 41 */ 100 "forward reference to enum type", /* 42 */ 101 "redefinition of '%s' hides earlier one", /* 43 */ 102 "declaration of '%s %s' introduces new type in ANSI C", /* 44 */ 103 "base type is really '%s %s'", /* 45 */ 104 "%s tag '%s' redeclared as %s", /* 46 */ 105 "zero sized %s is a C99 feature", /* 47 */ 106 "enumeration value '%s' overflows", /* 48 */ 107 "anonymous struct/union members is a C11 feature", /* 49 */ 108 "parameter '%s' has function type, should be pointer", /* 50 */ 109 "parameter mismatch: %d declared, %d defined", /* 51 */ 110 "cannot initialize parameter '%s'", /* 52 */ 111 "declared parameter '%s' is missing", /* 53 */ 112 "trailing ',' in enum declaration requires C99 or later", /* 54 */ 113 "integral constant expression expected", /* 55 */ 114 "integral constant too large", /* 56 */ 115 "enumeration constant '%s' hides parameter", /* 57 */ 116 "type of '%s' does not match prototype", /* 58 */ 117 "formal parameter #%d lacks name", /* 59 */ 118 "void must be sole parameter", /* 60 */ 119 "void parameter '%s' cannot have name", /* 61 */ 120 "function prototype parameters must have types", /* 62 */ 121 "prototype does not match old-style definition", /* 63 */ 122 "()-less function definition", /* 64 */ 123 "'%s' has no named members", /* 65 */ 124 "", /* 66 */ 125 "cannot return incomplete type", /* 67 */ 126 "typedef already qualified with '%s'", /* 68 */ 127 "inappropriate qualifiers with 'void'", /* 69 */ 128 "", /* unused */ /* 70 */ 129 "too many characters in character constant", /* 71 */ 130 "typedef declares no type name", /* 72 */ 131 "empty character constant", /* 73 */ 132 "no hex digits follow \\x", /* 74 */ 133 "overflow in hex escape", /* 75 */ 134 "character escape does not fit in character", /* 76 */ 135 "bad octal digit '%c'", /* 77 */ 136 "", /* unused */ /* 78 */ 137 "dubious escape \\%c", /* 79 */ 138 "dubious escape \\%o", /* 80 */ 139 "\\a undefined in traditional C", /* 81 */ 140 "\\x undefined in traditional C", /* 82 */ 141 "storage class after type is obsolescent", /* 83 */ 142 "ANSI C requires formal parameter before '...'", /* 84 */ 143 "dubious tag declaration '%s %s'", /* 85 */ 144 "automatic '%s' hides external declaration", /* 86 */ 145 "static '%s' hides external declaration", /* 87 */ 146 "typedef '%s' hides external declaration", /* 88 */ 147 "typedef '%s' redeclared", /* 89 */ 148 "inconsistent redeclaration of extern '%s'", /* 90 */ 149 "declaration of '%s' hides parameter", /* 91 */ 150 "inconsistent redeclaration of static '%s'", /* 92 */ 151 "dubious static function '%s' at block level", /* 93 */ 152 "function '%s' has illegal storage class", /* 94 */ 153 "declaration of '%s' hides earlier one", /* 95 */ 154 "cannot dereference non-pointer type '%s'", /* 96 */ 155 "suffix 'U' is illegal in traditional C", /* 97 */ 156 "suffixes 'F' and 'L' are illegal in traditional C", /* 98 */ 157 "'%s' undefined", /* 99 */ 158 "unary '+' is illegal in traditional C", /* 100 */ 159 "type '%s' does not have member '%s'", /* 101 */ 160 "illegal use of member '%s'", /* 102 */ 161 "left operand of '.' must be struct or union, not '%s'", /* 103 */ 162 "left operand of '->' must be pointer to struct or union, not '%s'", /* 104 */ 163 "non-unique member requires struct/union %s", /* 105 */ 164 "left operand of '->' must be pointer", /* 106 */ 165 "operands of '%s' have incompatible types '%s' and '%s'", /* 107 */ 166 "operand of '%s' has invalid type '%s'", /* 108 */ 167 "void type illegal in expression", /* 109 */ 168 "pointer to function is not allowed here", /* 110 */ 169 "unacceptable operand of '%s'", /* 111 */ 170 "cannot take address of bit-field", /* 112 */ 171 "cannot take address of register '%s'", /* 113 */ 172 "%soperand of '%s' must be lvalue", /* 114 */ 173 "%soperand of '%s' must be modifiable lvalue", /* 115 */ 174 "illegal pointer subtraction", /* 116 */ 175 "bitwise '%s' on signed value possibly nonportable", /* 117 */ 176 "semantics of '%s' change in ANSI C; use explicit cast", /* 118 */ 177 "conversion of '%s' to '%s' is out of range", /* 119 */ 178 "bitwise '%s' on signed value nonportable", /* 120 */ 179 "negative shift", /* 121 */ 180 "shift amount %llu is greater than bit-size %llu of '%s'", /* 122 */ 181 "illegal combination of %s '%s' and %s '%s', op '%s'", /* 123 */ 182 "illegal combination of '%s' and '%s', op '%s'", /* 124 */ 183 "ANSI C forbids ordered comparisons of pointers to functions",/* 125 */ 184 "incompatible types '%s' and '%s' in conditional", /* 126 */ 185 "'&' before array or function: ignored", /* 127 */ 186 "operands of '%s' have incompatible pointer types to '%s' and '%s'", /* 128 */ 187 "expression has null effect", /* 129 */ 188 "enum type mismatch: '%s' '%s' '%s'", /* 130 */ 189 "conversion to '%s' may sign-extend incorrectly", /* 131 */ 190 "conversion from '%s' to '%s' may lose accuracy", /* 132 */ 191 "conversion of pointer to '%s' loses bits", /* 133 */ 192 "conversion of pointer to '%s' may lose bits", /* 134 */ 193 "converting '%s' to '%s' increases alignment from %u to %u", /* 135 */ 194 "cannot do pointer arithmetic on operand of unknown size", /* 136 */ 195 "", /* unused */ /* 137 */ 196 "unknown operand size, op '%s'", /* 138 */ 197 "division by 0", /* 139 */ 198 "modulus by 0", /* 140 */ 199 "operator '%s' produces integer overflow", /* 141 */ 200 "operator '%s' produces floating point overflow", /* 142 */ 201 "cannot take size/alignment of incomplete type", /* 143 */ 202 "cannot take size/alignment of function type '%s'", /* 144 */ 203 "cannot take size/alignment of bit-field", /* 145 */ 204 "cannot take size/alignment of void", /* 146 */ 205 "invalid cast from '%s' to '%s'", /* 147 */ 206 "improper cast of void expression", /* 148 */ 207 "cannot call '%s', must be a function", /* 149 */ 208 "argument mismatch: %d %s passed, %d expected", /* 150 */ 209 "void expressions may not be arguments, arg #%d", /* 151 */ 210 "argument cannot have unknown size, arg #%d", /* 152 */ 211 "converting '%s' to incompatible '%s' for argument %d", /* 153 */ 212 "illegal combination of %s '%s' and %s '%s', arg #%d", /* 154 */ 213 "passing '%s' to incompatible '%s', arg #%d", /* 155 */ 214 "function expects '%s', passing '%s' for arg #%d", /* 156 */ 215 "ANSI C treats constant as unsigned", /* 157 */ 216 "'%s' may be used before set", /* 158 */ 217 "assignment in conditional context", /* 159 */ 218 "operator '==' found where '=' was expected", /* 160 */ 219 "constant in conditional context", /* 161 */ 220 "operator '%s' compares '%s' with '%s'", /* 162 */ 221 "a cast does not yield an lvalue", /* 163 */ 222 "assignment of negative constant to unsigned type", /* 164 */ 223 "constant truncated by assignment", /* 165 */ 224 "precision lost in bit-field assignment", /* 166 */ 225 "array subscript cannot be negative: %ld", /* 167 */ 226 "array subscript cannot be > %d: %ld", /* 168 */ 227 "precedence confusion possible: parenthesize!", /* 169 */ 228 "first operand of '?' must have scalar type", /* 170 */ 229 "cannot assign to '%s' from '%s'", /* 171 */ 230 "too many struct/union initializers", /* 172 */ 231 "too many array initializers, expected %d", /* 173 */ 232 "too many initializers", /* 174 */ 233 "initialization of incomplete type '%s'", /* 175 */ 234 "", /* no longer used */ /* 176 */ 235 "non-constant initializer", /* 177 */ 236 "initializer does not fit", /* 178 */ 237 "cannot initialize struct/union with no named member", /* 179 */ 238 "bit-field initializer does not fit", /* 180 */ 239 "{}-enclosed or constant initializer of type '%s' required", /* 181 */ 240 "incompatible pointer types to '%s' and '%s'", /* 182 */ 241 "illegal combination of %s '%s' and %s '%s'", /* 183 */ 242 "illegal combination of '%s' and '%s'", /* 184 */ 243 "cannot initialize '%s' from '%s'", /* 185 */ 244 "bit-field initialization is illegal in traditional C", /* 186 */ 245 "string literal too long (%lu) for target array (%lu)", /* 187 */ 246 "no automatic aggregate initialization in traditional C", /* 188 */ 247 "", /* no longer used */ /* 189 */ 248 "empty array declaration for '%s'", /* 190 */ 249 "'%s' set but not used in function '%s'", /* 191 */ 250 "'%s' unused in function '%s'", /* 192 */ 251 "statement not reached", /* 193 */ 252 "label '%s' redefined", /* 194 */ 253 "case not in switch", /* 195 */ 254 "case label affected by conversion", /* 196 */ 255 "non-constant case expression", /* 197 */ 256 "non-integral case expression", /* 198 */ 257 "duplicate case '%ld' in switch", /* 199 */ 258 "duplicate case '%lu' in switch", /* 200 */ 259 "default outside switch", /* 201 */ 260 "duplicate default in switch", /* 202 */ 261 "case label must be of type 'int' in traditional C", /* 203 */ 262 "controlling expressions must have scalar type", /* 204 */ 263 "switch expression must have integral type", /* 205 */ 264 "enumeration value(s) not handled in switch", /* 206 */ 265 "loop not entered at top", /* 207 */ 266 "break outside loop or switch", /* 208 */ 267 "continue outside loop", /* 209 */ 268 "enum type mismatch between '%s' and '%s' in initialization", /* 210 */ 269 "function has return type '%s' but returns '%s'", /* 211 */ 270 "cannot return incomplete type", /* 212 */ 271 "void function '%s' cannot return value", /* 213 */ 272 "function '%s' expects to return value", /* 214 */ 273 "function '%s' implicitly declared to return int", /* 215 */ 274 "function '%s' has 'return expr' and 'return'", /* 216 */ 275 "function '%s' falls off bottom without returning value", /* 217 */ 276 "ANSI C treats constant as unsigned, op '%s'", /* 218 */ 277 "concatenated strings are illegal in traditional C", /* 219 */ 278 "fallthrough on case statement", /* 220 */ 279 "initialization of unsigned with negative constant", /* 221 */ 280 "conversion of negative constant to unsigned type", /* 222 */ 281 "end-of-loop code not reached", /* 223 */ 282 "cannot recover from previous errors", /* 224 */ 283 "static function '%s' called but not defined", /* 225 */ 284 "static variable '%s' unused", /* 226 */ 285 "const object '%s' should have initializer", /* 227 */ 286 "function cannot return const or volatile object", /* 228 */ 287 "converting '%s' to '%s' is questionable", /* 229 */ 288 "nonportable character comparison '%s'", /* 230 */ 289 "parameter '%s' unused in function '%s'", /* 231 */ 290 "label '%s' unused in function '%s'", /* 232 */ 291 "struct '%s' never defined", /* 233 */ 292 "union '%s' never defined", /* 234 */ 293 "enum '%s' never defined", /* 235 */ 294 "static function '%s' unused", /* 236 */ 295 "redeclaration of formal parameter '%s'", /* 237 */ 296 "initialization of union is illegal in traditional C", /* 238 */ 297 "constant operand to '!'", /* 239 */ 298 "", /* unused */ /* 240 */ 299 "dubious operation '%s' on enum", /* 241 */ 300 "combination of '%s' and '%s', op '%s'", /* 242 */ 301 "operator '%s' assumes that '%s' is ordered", /* 243 */ 302 "illegal structure pointer combination", /* 244 */ 303 "incompatible structure pointers: '%s' '%s' '%s'", /* 245 */ 304 "dubious conversion of enum to '%s'", /* 246 */ 305 "pointer cast from '%s' to '%s' may be troublesome", /* 247 */ 306 "floating-point constant out of range", /* 248 */ 307 "syntax error '%s'", /* 249 */ 308 "unknown character \\%o", /* 250 */ 309 "malformed integer constant", /* 251 */ 310 "integer constant out of range", /* 252 */ 311 "unterminated character constant", /* 253 */ 312 "newline in string or char constant", /* 254 */ 313 "undefined or invalid '#' directive", /* 255 */ 314 "unterminated comment", /* 256 */ 315 "extra characters in lint comment", /* 257 */ 316 "unterminated string constant", /* 258 */ 317 "argument %d is converted from '%s' to '%s' due to prototype", /* 259 */ 318 "previous declaration of '%s'", /* 260 */ 319 "previous definition of '%s'", /* 261 */ 320 "\\\" inside character constants undefined in traditional C", /* 262 */ 321 "\\? undefined in traditional C", /* 263 */ 322 "\\v undefined in traditional C", /* 264 */ 323 "%s does not support 'long long'", /* 265 */ 324 "'long double' is illegal in traditional C", /* 266 */ 325 "shift amount %u equals bit-size of '%s'", /* 267 */ 326 "variable '%s' declared inline", /* 268 */ 327 "parameter '%s' declared inline", /* 269 */ 328 "function prototypes are illegal in traditional C", /* 270 */ 329 "switch expression must be of type 'int' in traditional C", /* 271 */ 330 "empty translation unit", /* 272 */ 331 "bit-field type '%s' invalid in ANSI C", /* 273 */ 332 "ANSI C forbids comparison of %s with %s", /* 274 */ 333 "cast discards 'const' from type '%s'", /* 275 */ 334 "'__%s__' is illegal for type '%s'", /* 276 */ 335 "initialization of '%s' with '%s'", /* 277 */ 336 "combination of '%s' and '%s', arg #%d", /* 278 */ 337 "combination of '%s' and '%s' in return", /* 279 */ 338 "comment /* %s */ must be outside function", /* 280 */ 339 "duplicate comment /* %s */", /* 281 */ 340 "comment /* %s */ must precede function definition", /* 282 */ 341 "parameter number mismatch in comment /* %s */", /* 283 */ 342 "fallthrough on default statement", /* 284 */ 343 "prototype declaration", /* 285 */ 344 "function definition is not a prototype", /* 286 */ 345 "function declaration is not a prototype", /* 287 */ 346 "dubious use of /* VARARGS */ with /* %s */", /* 288 */ 347 "/* PRINTFLIKE */ and /* SCANFLIKE */ cannot be combined", /* 289 */ 348 "static function '%s' declared but not defined", /* 290 */ 349 "invalid multibyte character", /* 291 */ 350 "cannot concatenate wide and regular string literals", /* 292 */ 351 "parameter %d must be 'char *' for PRINTFLIKE/SCANFLIKE", /* 293 */ 352 "multi-character character constant", /* 294 */ 353 "conversion of '%s' to '%s' is out of range, arg #%d", /* 295 */ 354 "conversion of negative constant to unsigned type, arg #%d", /* 296 */ 355 "conversion to '%s' may sign-extend incorrectly, arg #%d", /* 297 */ 356 "conversion from '%s' to '%s' may lose accuracy, arg #%d", /* 298 */ 357 "prototype does not match old-style definition, arg #%d", /* 299 */ 358 "old-style definition", /* 300 */ 359 "array of incomplete type", /* 301 */ 360 "'%s' returns pointer to automatic object", /* 302 */ 361 "ANSI C forbids conversion of %s to %s", /* 303 */ 362 "ANSI C forbids conversion of %s to %s, arg #%d", /* 304 */ 363 "ANSI C forbids conversion of %s to %s, op %s", /* 305 */ 364 "constant truncated by conversion, op '%s'", /* 306 */ 365 "static variable '%s' set but not used", /* 307 */ 366 "invalid type for _Complex", /* 308 */ 367 "extra bits set to 0 in conversion of '%s' to '%s', op '%s'", /* 309 */ 368 "symbol renaming can't be used on function parameters", /* 310 */ 369 "symbol renaming can't be used on automatic variables", /* 311 */ 370 "%s does not support '//' comments", /* 312 */ 371 "struct or union member name in initializer is a C99 feature",/* 313 */ 372 "", /* never used */ /* 314 */ 373 "GCC style struct or union member name in initializer", /* 315 */ 374 "__FUNCTION__/__PRETTY_FUNCTION__ is a GCC extension", /* 316 */ 375 "__func__ is a C99 feature", /* 317 */ 376 "variable array dimension is a C99/GCC extension", /* 318 */ 377 "compound literals are a C99/GCC extension", /* 319 */ 378 "'({ ... })' is a GCC extension", /* 320 */ 379 "array initializer with designators is a C99 feature", /* 321 */ 380 "zero sized array is a C99 extension", /* 322 */ 381 "continue in 'do ... while (0)' loop", /* 323 */ 382 "suggest cast from '%s' to '%s' on op '%s' to avoid overflow", /* 324 */ 383 "variable declaration in for loop", /* 325 */ 384 "attribute '%s' ignored for '%s'", /* 326 */ 385 "declarations after statements is a C99 feature", /* 327 */ 386 "union cast is a GCC extension", /* 328 */ 387 "type '%s' is not a member of '%s'", /* 329 */ 388 "operand of '%s' must be bool, not '%s'", /* 330 */ 389 "left operand of '%s' must be bool, not '%s'", /* 331 */ 390 "right operand of '%s' must be bool, not '%s'", /* 332 */ 391 "controlling expression must be bool, not '%s'", /* 333 */ 392 "parameter %d expects '%s', gets passed '%s'", /* 334 */ 393 "operand of '%s' must not be bool", /* 335 */ 394 "left operand of '%s' must not be bool", /* 336 */ 395 "right operand of '%s' must not be bool", /* 337 */ 396 "option '%c' should be handled in the switch", /* 338 */ 397 "option '%c' should be listed in the options string", /* 339 */ 398 "initialization with '[a...b]' is a GCC extension", /* 340 */ 399 "argument to '%s' must be 'unsigned char' or EOF, not '%s'", /* 341 */ 400 "argument to '%s' must be cast to 'unsigned char', not to '%s'", /* 342 */ 401 "static array size is a C11 extension", /* 343 */ 402 "bit-field of type plain 'int' has implementation-defined signedness", /* 344 */ 403 "generic selection requires C11 or later", /* 345 */ 404 "call to '%s' effectively discards 'const' from argument", /* 346 */ 405 "redeclaration of '%s' with type '%s', expected '%s'", /* 347 */ 406 "maximum value %d of '%s' does not match maximum array index %d", /* 348 */ 407 "non type argument to alignof is a GCC extension", /* 349 */ 408 "'_Atomic' requires C11 or later", /* 350 */ 409 "missing%s header declaration for '%s'", /* 351 */ 410 "nested 'extern' declaration of '%s'", /* 352 */ 411 "empty initializer braces require C23 or later", /* 353 */ 412 "'_Static_assert' requires C11 or later", /* 354 */ 413 "'_Static_assert' without message requires C23 or later", /* 355 */ 414 }; 415 416 static bool is_suppressed[sizeof(msgs) / sizeof(msgs[0])]; 417 418 static struct include_level { 419 const char *filename; 420 int lineno; 421 struct include_level *by; 422 } *includes; 423 424 void 425 suppress_messages(const char *p) 426 { 427 char *end; 428 429 for (; ch_isdigit(*p); p = end + 1) { 430 unsigned long id = strtoul(p, &end, 10); 431 if ((*end != '\0' && *end != ',') || 432 id >= sizeof(msgs) / sizeof(msgs[0]) || 433 msgs[id][0] == '\0') 434 break; 435 436 is_suppressed[id] = true; 437 438 if (*end == '\0') 439 return; 440 } 441 errx(1, "invalid message ID '%.*s'", (int)strcspn(p, ","), p); 442 } 443 444 void 445 update_location(const char *filename, int lineno, bool is_begin, bool is_end) 446 { 447 struct include_level *top; 448 449 top = includes; 450 if (is_begin && top != NULL) 451 top->lineno = curr_pos.p_line; 452 453 if (top == NULL || is_begin) { 454 top = xmalloc(sizeof(*top)); 455 top->filename = filename; 456 top->lineno = lineno; 457 top->by = includes; 458 includes = top; 459 } else { 460 if (is_end) { 461 includes = top->by; 462 free(top); 463 top = includes; 464 } 465 if (top != NULL) { 466 top->filename = filename; 467 top->lineno = lineno; 468 } 469 } 470 } 471 472 static void 473 print_stack_trace(void) 474 { 475 const struct include_level *top; 476 477 if ((top = includes) == NULL) 478 return; 479 /* 480 * Skip the innermost include level since it is already listed in the 481 * diagnostic itself. Furthermore, its lineno is the line number of 482 * the last '#' line, not the current line. 483 */ 484 for (top = top->by; top != NULL; top = top->by) 485 printf("\tincluded from %s(%d)\n", top->filename, top->lineno); 486 } 487 488 /* 489 * If Fflag is not set, lbasename() returns a pointer to the last 490 * component of the path, otherwise it returns the argument. 491 */ 492 static const char * 493 lbasename(const char *path) 494 { 495 496 if (Fflag) 497 return path; 498 499 const char *base = path; 500 for (const char *p = path; *p != '\0'; p++) 501 if (*p == '/') 502 base = p + 1; 503 return base; 504 } 505 506 static FILE * 507 output_channel(void) 508 { 509 return yflag ? stderr : stdout; 510 } 511 512 static void 513 verror_at(int msgid, const pos_t *pos, va_list ap) 514 { 515 516 if (is_suppressed[msgid]) 517 return; 518 519 FILE *out = output_channel(); 520 (void)fprintf(out, "%s(%d): error: ", 521 lbasename(pos->p_file), pos->p_line); 522 (void)vfprintf(out, msgs[msgid], ap); 523 (void)fprintf(out, " [%d]\n", msgid); 524 seen_error = true; 525 print_stack_trace(); 526 } 527 528 static void 529 vwarning_at(int msgid, const pos_t *pos, va_list ap) 530 { 531 532 if (is_suppressed[msgid]) 533 return; 534 535 debug_step("%s: lwarn=%d msgid=%d", __func__, lwarn, msgid); 536 if (lwarn == LWARN_NONE || lwarn == msgid) 537 /* this warning is suppressed by a LINTED comment */ 538 return; 539 540 FILE *out = output_channel(); 541 (void)fprintf(out, "%s(%d): warning: ", 542 lbasename(pos->p_file), pos->p_line); 543 (void)vfprintf(out, msgs[msgid], ap); 544 (void)fprintf(out, " [%d]\n", msgid); 545 seen_warning = true; 546 print_stack_trace(); 547 } 548 549 static void 550 vmessage_at(int msgid, const pos_t *pos, va_list ap) 551 { 552 553 if (is_suppressed[msgid]) 554 return; 555 556 FILE *out = output_channel(); 557 (void)fprintf(out, "%s(%d): ", 558 lbasename(pos->p_file), pos->p_line); 559 (void)vfprintf(out, msgs[msgid], ap); 560 (void)fprintf(out, " [%d]\n", msgid); 561 print_stack_trace(); 562 } 563 564 void 565 (error_at)(int msgid, const pos_t *pos, ...) 566 { 567 va_list ap; 568 569 va_start(ap, pos); 570 verror_at(msgid, pos, ap); 571 va_end(ap); 572 } 573 574 void 575 (error)(int msgid, ...) 576 { 577 va_list ap; 578 579 va_start(ap, msgid); 580 verror_at(msgid, &curr_pos, ap); 581 va_end(ap); 582 } 583 584 void 585 assert_failed(const char *file, int line, const char *func, const char *cond) 586 { 587 588 /* 589 * After encountering a parse error in the grammar, lint often does 590 * not properly clean up its data structures, especially in 'dcs', 591 * the stack of declaration levels. This often leads to assertion 592 * failures. These cases are not interesting though, as the purpose 593 * of lint is to check syntactically valid code. In such a case, 594 * exit gracefully. This allows a fuzzer like afl to focus on more 595 * interesting cases instead of reporting nonsense translation units 596 * like 'f=({e:;}' or 'v(const(char););e(v){'. 597 */ 598 if (sytxerr > 0) 599 norecover(); 600 601 (void)fflush(stdout); 602 (void)fprintf(stderr, 603 "lint: assertion \"%s\" failed in %s at %s:%d near %s:%d\n", 604 cond, func, file, line, 605 lbasename(curr_pos.p_file), curr_pos.p_line); 606 print_stack_trace(); 607 (void)fflush(stdout); 608 abort(); 609 } 610 611 void 612 (warning_at)(int msgid, const pos_t *pos, ...) 613 { 614 va_list ap; 615 616 va_start(ap, pos); 617 vwarning_at(msgid, pos, ap); 618 va_end(ap); 619 } 620 621 void 622 (warning)(int msgid, ...) 623 { 624 va_list ap; 625 626 va_start(ap, msgid); 627 vwarning_at(msgid, &curr_pos, ap); 628 va_end(ap); 629 } 630 631 void 632 (message_at)(int msgid, const pos_t *pos, ...) 633 { 634 va_list ap; 635 636 va_start(ap, pos); 637 vmessage_at(msgid, pos, ap); 638 va_end(ap); 639 } 640 641 void 642 (c99ism)(int msgid, ...) 643 { 644 va_list ap; 645 646 if (allow_c99) 647 return; 648 649 va_start(ap, msgid); 650 int severity = (!allow_gcc ? 1 : 0) + (!allow_trad ? 1 : 0); 651 if (severity == 2) 652 verror_at(msgid, &curr_pos, ap); 653 if (severity == 1) 654 vwarning_at(msgid, &curr_pos, ap); 655 va_end(ap); 656 } 657 658 void 659 (c11ism)(int msgid, ...) 660 { 661 va_list ap; 662 663 /* FIXME: C11 mode has nothing to do with GCC mode. */ 664 if (allow_c11 || allow_gcc) 665 return; 666 va_start(ap, msgid); 667 verror_at(msgid, &curr_pos, ap); 668 va_end(ap); 669 } 670 671 void 672 (c23ism)(int msgid, ...) 673 { 674 va_list ap; 675 676 if (allow_c23) 677 return; 678 va_start(ap, msgid); 679 verror_at(msgid, &curr_pos, ap); 680 va_end(ap); 681 } 682 683 bool 684 (gnuism)(int msgid, ...) 685 { 686 va_list ap; 687 int severity = (!allow_gcc ? 1 : 0) + 688 (!allow_trad && !allow_c99 ? 1 : 0); 689 690 va_start(ap, msgid); 691 if (severity == 2) 692 verror_at(msgid, &curr_pos, ap); 693 if (severity == 1) 694 vwarning_at(msgid, &curr_pos, ap); 695 va_end(ap); 696 return severity > 0; 697 } 698 699 700 static const char *queries[] = { 701 "", /* unused, to make queries 1-based */ 702 "implicit conversion from floating point '%s' to integer '%s'", /* Q1 */ 703 "cast from floating point '%s' to integer '%s'", /* Q2 */ 704 "implicit conversion changes sign from '%s' to '%s'", /* Q3 */ 705 "usual arithmetic conversion for '%s' from '%s' to '%s'", /* Q4 */ 706 "pointer addition has integer on the left-hand side", /* Q5 */ 707 "no-op cast from '%s' to '%s'", /* Q6 */ 708 "redundant cast from '%s' to '%s' before assignment", /* Q7 */ 709 "octal number '%.*s'", /* Q8 */ 710 "parenthesized return value", /* Q9 */ 711 "chained assignment with '%s' and '%s'", /* Q10 */ 712 "static variable '%s' in function", /* Q11 */ 713 "comma operator with types '%s' and '%s'", /* Q12 */ 714 "redundant 'extern' in function declaration of '%s'", /* Q13 */ 715 "comparison '%s' of 'char' with plain integer %d", /* Q14 */ 716 "implicit conversion from integer 0 to pointer '%s'", /* Q15 */ 717 }; 718 719 bool any_query_enabled; /* for optimizing non-query scenarios */ 720 static bool is_query_enabled[sizeof(queries) / sizeof(queries[0])]; 721 722 void 723 (query_message)(int query_id, ...) 724 { 725 726 if (!is_query_enabled[query_id]) 727 return; 728 729 va_list ap; 730 FILE *out = output_channel(); 731 (void)fprintf(out, "%s(%d): ", 732 lbasename(curr_pos.p_file), curr_pos.p_line); 733 va_start(ap, query_id); 734 (void)vfprintf(out, queries[query_id], ap); 735 va_end(ap); 736 (void)fprintf(out, " [Q%d]\n", query_id); 737 print_stack_trace(); 738 } 739 740 void 741 enable_queries(const char *p) 742 { 743 char *end; 744 745 for (; ch_isdigit(*p); p = end + 1) { 746 unsigned long id = strtoul(p, &end, 10); 747 if ((*end != '\0' && *end != ',') || 748 id >= sizeof(queries) / sizeof(queries[0]) || 749 queries[id][0] == '\0') 750 break; 751 752 any_query_enabled = true; 753 is_query_enabled[id] = true; 754 755 if (*end == '\0') 756 return; 757 } 758 errx(1, "invalid query ID '%.*s'", (int)strcspn(p, ","), p); 759 } 760