From aec08e609e6c672c6e85d91b84f45e38019ccc9e Mon Sep 17 00:00:00 2001
From: =?utf8?q?Jo=C3=A3o=20T=C3=A1vora?= <joaotavora@gmail.com>
Date: Mon, 30 Aug 2021 16:24:25 +0100
Subject: [PATCH] Keep and report "foreign" diangnostics in flymake-cc Flymake
 backend

This includes diagnostics for .h files that sprang up when checking a
c file.  Those diagnostics are reported to the Flymake infrastructure
which does not (yet) do anything with them.

This includes a change to the test fixtures, too.

* lisp/progmodes/flymake-cc.el (flymake-cc--make-diagnostics): Rework

* test/lisp/progmodes/flymake-resources/another-problematic-file.c:
  New file.

* test/lisp/progmodes/flymake-resources/some-problems.h:
  Add a function declaration..
---
 lisp/progmodes/flymake-cc.el                  | 39 ++++++++++++-------
 .../another-problematic-file.c                |  5 +++
 .../flymake-resources/some-problems.h         |  2 +
 3 files changed, 32 insertions(+), 14 deletions(-)
 create mode 100644 test/lisp/progmodes/flymake-resources/another-problematic-file.c

diff --git a/lisp/progmodes/flymake-cc.el b/lisp/progmodes/flymake-cc.el
index bd403faf7c4..907300eb274 100644
--- a/lisp/progmodes/flymake-cc.el
+++ b/lisp/progmodes/flymake-cc.el
@@ -61,23 +61,34 @@ SOURCE."
   (cl-loop
    while
    (search-forward-regexp
-    "^\\(In file included from \\)?<stdin>:\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)?:\n?\\(.*\\): \\(.*\\)$"
+    "^\\(In file included from \\)?\\([^ :]+\\):\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)?:\n?\\(.*\\): \\(.*\\)$"
     nil t)
-   for msg = (match-string 5)
-   for (beg . end) = (flymake-diag-region
-                      source
-                      (string-to-number (match-string 2))
-                      (and (match-string 3) (string-to-number (match-string 3))))
+   for msg = (match-string 6)
+   for locus = (match-string 2)
+   for line = (string-to-number (match-string 3))
+   for col = (ignore-errors (string-to-number (match-string 4)))
+   for source-buffer = (and (string= locus "<stdin>") source)
    for type = (if (match-string 1)
                   :error
-                (assoc-default
-                 (match-string 4)
-                 '(("error" . :error)
-                   ("note" . :note)
-                   ("warning" . :warning))
-                 #'string-match
-                 :error))
-   collect (flymake-make-diagnostic source beg end type msg)))
+                (save-match-data
+                  (assoc-default
+                   (match-string 5)
+                   '(("error" . :error)
+                     ("note" . :note)
+                     ("warning" . :warning))
+                   #'string-match
+                   :error)))
+   for diag =
+   (cond (source-buffer
+          (pcase-let ((`(,beg . ,end)
+                       (flymake-diag-region source-buffer line col)))
+            (flymake-make-diagnostic source-buffer beg end type msg)))
+         (t (flymake-make-diagnostic locus (cons line col) nil type msg)))
+   collect diag
+   ;; If "In file included from..." matched, then move to end of that
+   ;; line.  This helps us collect the diagnostic at its .h locus,
+   ;; too.
+   when (match-end 1) do (goto-char (match-end 2))))
 
 (defun flymake-cc-use-special-make-target ()
   "Command for checking a file via a CHK_SOURCES Make target."
diff --git a/test/lisp/progmodes/flymake-resources/another-problematic-file.c b/test/lisp/progmodes/flymake-resources/another-problematic-file.c
new file mode 100644
index 00000000000..03eacdd8011
--- /dev/null
+++ b/test/lisp/progmodes/flymake-resources/another-problematic-file.c
@@ -0,0 +1,5 @@
+#include "some-problems.h"
+
+int frob(char* freb) {
+  return 42;
+}
diff --git a/test/lisp/progmodes/flymake-resources/some-problems.h b/test/lisp/progmodes/flymake-resources/some-problems.h
index 165d8dd525e..86ea2de3b0d 100644
--- a/test/lisp/progmodes/flymake-resources/some-problems.h
+++ b/test/lisp/progmodes/flymake-resources/some-problems.h
@@ -2,4 +2,6 @@
 
 strange;
 
+int frob(char);
+
 sint main();
-- 
2.39.5