Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/usr.bin/xlint/lint1 lint: in code from included files, print...



details:   https://anonhg.NetBSD.org/src/rev/4c3d401d1f44
branches:  trunk
changeset: 961073:4c3d401d1f44
user:      rillig <rillig%NetBSD.org@localhost>
date:      Thu Apr 08 22:18:26 2021 +0000

description:
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.

diffstat:

 distrib/sets/lists/tests/mi                   |   4 +-
 tests/usr.bin/xlint/check-expect.lua          |  83 ++++++++++++++------------
 tests/usr.bin/xlint/lint1/Makefile            |   4 +-
 tests/usr.bin/xlint/lint1/feat_stacktrace.c   |  31 ++++++++++
 tests/usr.bin/xlint/lint1/feat_stacktrace.exp |   6 +
 tests/usr.bin/xlint/lint1/t_integration.sh    |   4 +-
 usr.bin/xlint/lint1/err.c                     |  56 +++++++++++++++++-
 usr.bin/xlint/lint1/externs1.h                |   3 +-
 usr.bin/xlint/lint1/lex.c                     |  32 +++++++--
 9 files changed, 171 insertions(+), 52 deletions(-)

diffs (truncated from 466 to 300 lines):

diff -r fe9651749640 -r 4c3d401d1f44 distrib/sets/lists/tests/mi
--- a/distrib/sets/lists/tests/mi       Thu Apr 08 19:37:43 2021 +0000
+++ b/distrib/sets/lists/tests/mi       Thu Apr 08 22:18:26 2021 +0000
@@ -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
diff -r fe9651749640 -r 4c3d401d1f44 tests/usr.bin/xlint/check-expect.lua
--- a/tests/usr.bin/xlint/check-expect.lua      Thu Apr 08 19:37:43 2021 +0000
+++ b/tests/usr.bin/xlint/check-expect.lua      Thu Apr 08 22:18:26 2021 +0000
@@ -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 @@
   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 @@
 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 @@
     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
diff -r fe9651749640 -r 4c3d401d1f44 tests/usr.bin/xlint/lint1/Makefile
--- a/tests/usr.bin/xlint/lint1/Makefile        Thu Apr 08 19:37:43 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/Makefile        Thu Apr 08 22:18:26 2021 +0000
@@ -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_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
diff -r fe9651749640 -r 4c3d401d1f44 tests/usr.bin/xlint/lint1/feat_stacktrace.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/feat_stacktrace.c       Thu Apr 08 22:18:26 2021 +0000
@@ -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
diff -r fe9651749640 -r 4c3d401d1f44 tests/usr.bin/xlint/lint1/feat_stacktrace.exp
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/usr.bin/xlint/lint1/feat_stacktrace.exp     Thu Apr 08 22:18:26 2021 +0000
@@ -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)
diff -r fe9651749640 -r 4c3d401d1f44 tests/usr.bin/xlint/lint1/t_integration.sh
--- a/tests/usr.bin/xlint/lint1/t_integration.sh        Thu Apr 08 19:37:43 2021 +0000
+++ b/tests/usr.bin/xlint/lint1/t_integration.sh        Thu Apr 08 22:18:26 2021 +0000
@@ -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 op_colon
 
+test_case feat_stacktrace
+
 test_case all_messages
 all_messages_body()
 {
diff -r fe9651749640 -r 4c3d401d1f44 usr.bin/xlint/lint1/err.c
--- a/usr.bin/xlint/lint1/err.c Thu Apr 08 19:37:43 2021 +0000
+++ b/usr.bin/xlint/lint1/err.c Thu Apr 08 22:18:26 2021 +0000
@@ -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 @@
        "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;



Home | Main Index | Thread Index | Old Index