Module Name: src Committed By: rillig Date: Thu Apr 8 22:18:27 UTC 2021
Modified Files: src/distrib/sets/lists/tests: mi src/tests/usr.bin/xlint: check-expect.lua src/tests/usr.bin/xlint/lint1: Makefile t_integration.sh src/usr.bin/xlint/lint1: err.c externs1.h lex.c Added Files: src/tests/usr.bin/xlint/lint1: feat_stacktrace.c feat_stacktrace.exp Log Message: lint: in code from included files, print stack trace Previously, the standard NetBSD build generated several lint warnings in lhash.h from OpenSSL, without providing any hint as to which file actually included that header. In cases like these, lint now interprets the line number information in the preprocessor output from GCC to reconstruct the exact include path to the file in question. The program check-expect.lua had to be rewritten almost completely since it assumed that all diagnostics would come from the main file. In all existing tests, this was true, but these tests did not cover all cases that occurred in practice. Now it records the complete location of the diagnostic instead of just the line number. To generate a diff of this commit: cvs rdiff -u -r1.1037 -r1.1038 src/distrib/sets/lists/tests/mi cvs rdiff -u -r1.7 -r1.8 src/tests/usr.bin/xlint/check-expect.lua cvs rdiff -u -r1.39 -r1.40 src/tests/usr.bin/xlint/lint1/Makefile \ src/tests/usr.bin/xlint/lint1/t_integration.sh cvs rdiff -u -r0 -r1.1 src/tests/usr.bin/xlint/lint1/feat_stacktrace.c \ src/tests/usr.bin/xlint/lint1/feat_stacktrace.exp cvs rdiff -u -r1.103 -r1.104 src/usr.bin/xlint/lint1/err.c cvs rdiff -u -r1.101 -r1.102 src/usr.bin/xlint/lint1/externs1.h cvs rdiff -u -r1.24 -r1.25 src/usr.bin/xlint/lint1/lex.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/tests/mi diff -u src/distrib/sets/lists/tests/mi:1.1037 src/distrib/sets/lists/tests/mi:1.1038 --- src/distrib/sets/lists/tests/mi:1.1037 Mon Apr 5 02:05:47 2021 +++ src/distrib/sets/lists/tests/mi Thu Apr 8 22:18:26 2021 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1037 2021/04/05 02:05:47 rillig Exp $ +# $NetBSD: mi,v 1.1038 2021/04/08 22:18:26 rillig Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -6181,6 +6181,8 @@ ./usr/tests/usr.bin/xlint/lint1/d_typefun.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/d_typename_as_var.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/d_zero_sized_arrays.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/feat_stacktrace.c tests-usr.bin-tests compattestfile,atf +./usr/tests/usr.bin/xlint/lint1/feat_stacktrace.exp tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/msg_000.c tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/msg_000.exp tests-usr.bin-tests compattestfile,atf ./usr/tests/usr.bin/xlint/lint1/msg_001.c tests-usr.bin-tests compattestfile,atf Index: src/tests/usr.bin/xlint/check-expect.lua diff -u src/tests/usr.bin/xlint/check-expect.lua:1.7 src/tests/usr.bin/xlint/check-expect.lua:1.8 --- src/tests/usr.bin/xlint/check-expect.lua:1.7 Mon Apr 5 01:35:34 2021 +++ src/tests/usr.bin/xlint/check-expect.lua Thu Apr 8 22:18:27 2021 @@ -1,5 +1,5 @@ #! /usr/bin/lua --- $NetBSD: check-expect.lua,v 1.7 2021/04/05 01:35:34 rillig Exp $ +-- $NetBSD: check-expect.lua,v 1.8 2021/04/08 22:18:27 rillig Exp $ --[[ @@ -25,57 +25,67 @@ local function load_lines(fname) return lines end + local function load_expect_comments_from_c(fname, errors) local lines = load_lines(fname) if lines == nil then return nil, nil end - local comment_linenos = {} - local comments_by_lineno = {} - local function add_expectation(lineno, msg) - if comments_by_lineno[lineno] == nil then - table.insert(comment_linenos, lineno) - comments_by_lineno[lineno] = {} + local pp_fname = fname + local pp_lineno = 0 + local comment_locations = {} + local comments_by_location = {} + + local function add_expectation(offset, message) + local location = ("%s(%d)"):format(pp_fname, pp_lineno + offset) + if comments_by_location[location] == nil then + table.insert(comment_locations, location) + comments_by_location[location] = {} end - local trimmed_msg = msg:match("^%s*(.-)%s*$") - table.insert(comments_by_lineno[lineno], trimmed_msg) + local trimmed_msg = message:match("^%s*(.-)%s*$") + table.insert(comments_by_location[location], trimmed_msg) end - for lineno, line in ipairs(lines) do + for phys_lineno, line in ipairs(lines) do for offset, comment in line:gmatch("/%* expect([+%-]%d+): (.-) %*/") do - add_expectation(lineno + tonumber(offset), comment) + add_expectation(tonumber(offset), comment) end for comment in line:gmatch("/%* expect: (.-) %*/") do - add_expectation(lineno, comment) + add_expectation(0, comment) end - local pp_lineno, pp_fname = line:match("^#%s*(%d+)%s+\"([^\"]+)\"") - if pp_lineno ~= nil then - if pp_fname == fname and tonumber(pp_lineno) ~= lineno + 1 then + pp_lineno = pp_lineno + 1 + + local ppl_lineno, ppl_fname = line:match("^#%s*(%d+)%s+\"([^\"]+)\"") + if ppl_lineno ~= nil then + if ppl_fname == fname and tonumber(ppl_lineno) ~= phys_lineno + 1 then errors:add("error: %s:%d: preprocessor line number must be %d", - fname, lineno, lineno + 1) + fname, phys_lineno, phys_lineno + 1) end + pp_fname = ppl_fname + pp_lineno = ppl_lineno end end - return comment_linenos, comments_by_lineno + return comment_locations, comments_by_location end -local function load_actual_messages_from_exp(fname) +local function load_actual_messages_from_exp(exp_fname, primary_fname) - local lines = load_lines(fname) + local lines = load_lines(exp_fname) if lines == nil then return nil end local messages = {} - for lineno, line in ipairs(lines) do - for c_lineno, message in line:gmatch("%S+%((%d+)%): (.+)$") do + for exp_lineno, line in ipairs(lines) do + for location, c_filename, c_lineno, message + in line:gmatch("((%S+)%((%d+)%)): (.+)$") do table.insert(messages, { - exp_lineno = lineno, - c_lineno = tonumber(c_lineno), - msg = message + exp_lineno = exp_lineno, + location = location, + message = message }) end end @@ -87,19 +97,19 @@ end local function check_test(c_fname, errors) local exp_fname = c_fname:gsub("%.c$", ".exp") - local comment_linenos, comments_by_lineno = + local comment_locations, comments_by_location = load_expect_comments_from_c(c_fname, errors) - if comment_linenos == nil then return end + if comment_locations == nil then return end - local messages = load_actual_messages_from_exp(exp_fname) + local messages = load_actual_messages_from_exp(exp_fname, c_fname) if messages == nil then return end for _, act in ipairs(messages) do - local exp = comments_by_lineno[act.c_lineno] or {} + local exp = comments_by_location[act.location] or {} local found = false - for i, msg in ipairs(exp) do - if msg ~= "" and act.msg:find(msg, 1, true) then + for i, message in ipairs(exp) do + if message ~= "" and act.message:find(message, 1, true) then exp[i] = "" found = true break @@ -107,17 +117,16 @@ local function check_test(c_fname, error end if not found then - errors:add("error: %s:%d: must expect \"%s\"", - c_fname, act.c_lineno, act.msg) + errors:add("error: %s: must expect \"%s\"", act.location, act.message) end end - for _, lineno in ipairs(comment_linenos) do - for _, msg in ipairs(comments_by_lineno[lineno]) do - if msg ~= "" then + for _, location in ipairs(comment_locations) do + for _, message in ipairs(comments_by_location[location]) do + if message ~= "" then errors:add( - "error: %s:%d: declared message \"%s\" is not in the actual output", - c_fname, lineno, msg) + "error: %s: declared message \"%s\" is not in the actual output", + location, message) end end end Index: src/tests/usr.bin/xlint/lint1/Makefile diff -u src/tests/usr.bin/xlint/lint1/Makefile:1.39 src/tests/usr.bin/xlint/lint1/Makefile:1.40 --- src/tests/usr.bin/xlint/lint1/Makefile:1.39 Mon Apr 5 02:05:47 2021 +++ src/tests/usr.bin/xlint/lint1/Makefile Thu Apr 8 22:18:27 2021 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.39 2021/04/05 02:05:47 rillig Exp $ +# $NetBSD: Makefile,v 1.40 2021/04/08 22:18:27 rillig Exp $ NOMAN= # defined MAX_MESSAGE= 342 # see lint1/err.c @@ -99,6 +99,8 @@ FILES+= d_type_question_colon.c FILES+= d_typefun.c FILES+= d_typename_as_var.c FILES+= d_zero_sized_arrays.c +FILES+= feat_stacktrace.c +FILES+= feat_stacktrace.exp FILES+= ${:U0 ${:U:${:Urange=${MAX_MESSAGE}}}:C,^.$,0&,:C,^..$,0&,:@i@msg_${i}.c msg_${i}.exp@:Nmsg_176.exp} FILES+= op_colon.c FILES+= op_colon.exp Index: src/tests/usr.bin/xlint/lint1/t_integration.sh diff -u src/tests/usr.bin/xlint/lint1/t_integration.sh:1.39 src/tests/usr.bin/xlint/lint1/t_integration.sh:1.40 --- src/tests/usr.bin/xlint/lint1/t_integration.sh:1.39 Mon Apr 5 02:05:47 2021 +++ src/tests/usr.bin/xlint/lint1/t_integration.sh Thu Apr 8 22:18:27 2021 @@ -1,4 +1,4 @@ -# $NetBSD: t_integration.sh,v 1.39 2021/04/05 02:05:47 rillig Exp $ +# $NetBSD: t_integration.sh,v 1.40 2021/04/08 22:18:27 rillig Exp $ # # Copyright (c) 2008, 2010 The NetBSD Foundation, Inc. # All rights reserved. @@ -168,6 +168,8 @@ test_case d_long_double_int test_case op_colon +test_case feat_stacktrace + test_case all_messages all_messages_body() { Index: src/usr.bin/xlint/lint1/err.c diff -u src/usr.bin/xlint/lint1/err.c:1.103 src/usr.bin/xlint/lint1/err.c:1.104 --- src/usr.bin/xlint/lint1/err.c:1.103 Tue Apr 6 21:32:57 2021 +++ src/usr.bin/xlint/lint1/err.c Thu Apr 8 22:18:27 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: err.c,v 1.103 2021/04/06 21:32:57 rillig Exp $ */ +/* $NetBSD: err.c,v 1.104 2021/04/08 22:18:27 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) && !defined(lint) -__RCSID("$NetBSD: err.c,v 1.103 2021/04/06 21:32:57 rillig Exp $"); +__RCSID("$NetBSD: err.c,v 1.104 2021/04/08 22:18:27 rillig Exp $"); #endif #include <sys/types.h> @@ -399,6 +399,53 @@ const char *msgs[] = { "argument to '%s' must be cast to 'unsigned char', not to '%s'", /* 342 */ }; +static struct include_level { + const char *filename; + int lineno; + struct include_level *by; +} *includes; + + +void +update_position(const char *filename, int lineno, + bool is_begin, bool is_end, bool is_system) +{ + struct include_level *top; + + top = includes; + if (is_begin && top != NULL) + top->lineno = curr_pos.p_line; + + if (top == NULL || is_begin) { + top = xmalloc(sizeof(*top)); + top->filename = filename; + top->lineno = lineno; + top->by = includes; + includes = top; + } else { + if (is_end && top != NULL) { + includes = top->by; + free(top); + top = includes; + } + top->filename = filename; + top->lineno = lineno; + } + + in_system_header = is_system; +} + +static void +print_stack_trace(void) +{ + struct include_level *top; + + if ((top = includes) == NULL) + return; + for (top = top->by; top != NULL; top = top->by) + printf("\tincluded from %s(%d)\n", top->filename, top->lineno); +} + /* * print a list of the messages with their ids */ @@ -446,6 +493,7 @@ verror(int n, va_list ap) (void)vprintf(msgs[n], ap); (void)printf(" [%d]\n", n); nerr++; + print_stack_trace(); } static void @@ -469,6 +517,7 @@ vwarning(int n, va_list ap) (void)printf(" [%d]\n", n); if (wflag) nerr++; + print_stack_trace(); } void @@ -494,6 +543,7 @@ internal_error(const char *file, int lin (void)vfprintf(stderr, msg, ap); va_end(ap); (void)fprintf(stderr, "\n"); + print_stack_trace(); abort(); } @@ -506,6 +556,7 @@ assert_failed(const char *file, int line (void)fprintf(stderr, "lint: assertion \"%s\" failed in %s at %s:%d near %s:%d\n", cond, func, file, line, fn, curr_pos.p_line); + print_stack_trace(); abort(); } @@ -534,6 +585,7 @@ void (void)vprintf(msgs[n], ap); (void)printf(" [%d]\n", n); va_end(ap); + print_stack_trace(); } /* Index: src/usr.bin/xlint/lint1/externs1.h diff -u src/usr.bin/xlint/lint1/externs1.h:1.101 src/usr.bin/xlint/lint1/externs1.h:1.102 --- src/usr.bin/xlint/lint1/externs1.h:1.101 Tue Apr 6 13:17:04 2021 +++ src/usr.bin/xlint/lint1/externs1.h Thu Apr 8 22:18:27 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: externs1.h,v 1.101 2021/04/06 13:17:04 rillig Exp $ */ +/* $NetBSD: externs1.h,v 1.102 2021/04/08 22:18:27 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -128,6 +128,7 @@ extern void internal_error(const char *, __attribute__((__noreturn__,__format__(__printf__, 3, 4))); extern void assert_failed(const char *, int, const char *, const char *) __attribute__((__noreturn__)); +extern void update_position(const char *, int, bool, bool, bool); /* * decl.c Index: src/usr.bin/xlint/lint1/lex.c diff -u src/usr.bin/xlint/lint1/lex.c:1.24 src/usr.bin/xlint/lint1/lex.c:1.25 --- src/usr.bin/xlint/lint1/lex.c:1.24 Tue Apr 6 22:21:53 2021 +++ src/usr.bin/xlint/lint1/lex.c Thu Apr 8 22:18:27 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: lex.c,v 1.24 2021/04/06 22:21:53 rillig Exp $ */ +/* $NetBSD: lex.c,v 1.25 2021/04/08 22:18:27 rillig Exp $ */ /* * Copyright (c) 1996 Christopher G. Demetriou. All Rights Reserved. @@ -38,7 +38,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) && !defined(lint) -__RCSID("$NetBSD: lex.c,v 1.24 2021/04/06 22:21:53 rillig Exp $"); +__RCSID("$NetBSD: lex.c,v 1.25 2021/04/08 22:18:27 rillig Exp $"); #endif #include <ctype.h> @@ -1052,10 +1052,13 @@ get_escaped_char(int delim) /* See https://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html */ static void -parse_line_directive_flags(const char *p) +parse_line_directive_flags(const char *p, + bool *is_begin, bool *is_end, bool *is_system) { - in_system_header = false; + *is_begin = false; + *is_end = false; + *is_system = false; while (*p != '\0') { while (ch_isspace(*p)) @@ -1066,13 +1069,20 @@ parse_line_directive_flags(const char *p p++; const char *word_end = p; + if (word_end - word_start == 1 && word_start[0] == '1') + *is_begin = true; + if (word_end - word_start == 1 && word_start[0] == '2') + *is_end = true; if (word_end - word_start == 1 && word_start[0] == '3') - in_system_header = true; + *is_system = true; + /* Flag '4' would only be interesting if lint handled C++. */ } #if 0 - if (c != '\0') - warning("extra character(s) after directive"); + if (*p != '\0') { + /* syntax error '%s' */ + warning(249, "extra character(s) after directive"); + } #endif } @@ -1089,6 +1099,8 @@ lex_directive(const char *yytext) char c, *eptr; size_t fnl; long ln; + bool is_begin, is_end, is_system; + static bool first = true; /* Go to first non-whitespace after # */ @@ -1120,8 +1132,6 @@ lex_directive(const char *yytext) goto error; if ((fnl = cp++ - fn) > PATH_MAX) goto error; - parse_line_directive_flags(cp); - /* empty string means stdin */ if (fnl == 0) { fn = "{standard input}"; @@ -1139,6 +1149,10 @@ lex_directive(const char *yytext) strlen(curr_pos.p_file))); first = false; } + + parse_line_directive_flags(cp, &is_begin, &is_end, &is_system); + update_position(curr_pos.p_file, (int)ln, + is_begin, is_end, is_system); } curr_pos.p_line = (int)ln - 1; curr_pos.p_uniq = 0; Added files: Index: src/tests/usr.bin/xlint/lint1/feat_stacktrace.c diff -u /dev/null src/tests/usr.bin/xlint/lint1/feat_stacktrace.c:1.1 --- /dev/null Thu Apr 8 22:18:27 2021 +++ src/tests/usr.bin/xlint/lint1/feat_stacktrace.c Thu Apr 8 22:18:27 2021 @@ -0,0 +1,31 @@ +/* $NetBSD: feat_stacktrace.c,v 1.1 2021/04/08 22:18:27 rillig Exp $ */ +# 3 "feat_stacktrace.c" + +/* + * In macros or nested includes, lint prints a stack trace to show exactly + * where the code comes from. + */ + +# 1 "/usr/include/stdlib.h" 1 3 4 +# 38 "/usr/include/stdlib.h" 3 4 +# 39 "/usr/include/stdlib.h" 3 4 +# 1 "/usr/include/sys/types.h" 1 3 4 +# 43 "/usr/include/sys/types.h" 3 4 +# 1 "/usr/include/amd64/types.h" 1 3 4 +# 40 "/usr/include/amd64/types.h" 3 4 +# 1 "/usr/include/sys/featuretest.h" 1 3 4 +# 41 "/usr/include/amd64/types.h" 2 3 4 +# 1 "/usr/include/amd64/int_types.h" 1 3 4 + +/* + * The next filename is a relative filename since the tests are run without + * the lint option -F, which would generate the fully qualified filename for + * the main file as well. + */ +# 1 "common_int_types.h" 1 3 4 +typedef int; /* expect: typedef declares no type name */ +# 39 "common_int_types.h" 3 4 +# 39 "/usr/include/amd64/int_types.h" 2 3 4 +# 42 "/usr/include/amd64/types.h" 2 3 4 +# 68 "/usr/include/amd64/types.h" 3 4 +# 46 "/usr/include/sys/types.h" 2 3 4 Index: src/tests/usr.bin/xlint/lint1/feat_stacktrace.exp diff -u /dev/null src/tests/usr.bin/xlint/lint1/feat_stacktrace.exp:1.1 --- /dev/null Thu Apr 8 22:18:27 2021 +++ src/tests/usr.bin/xlint/lint1/feat_stacktrace.exp Thu Apr 8 22:18:27 2021 @@ -0,0 +1,6 @@ +common_int_types.h(1): warning: typedef declares no type name [72] + included from /usr/include/amd64/int_types.h(7) + included from /usr/include/amd64/types.h(41) + included from /usr/include/sys/types.h(43) + included from /usr/include/stdlib.h(39) + included from feat_stacktrace.c(9)