Subject: bug#36492: c-mode fails with errors during fontification

From: Juri Linkov <[email-masked]>
Date: Wed, 03 Jul 2019 23:56:19 +0300

Opening this message in Gnus fails with the following backtrace
after setting (setq diff-font-lock-syntax 'hunk-also)
because c-mode fails to fontify the attachment.

Debugger entered--Lisp error: (wrong-type-argument integer-or-marker-p nil)
  c-forward-decl-or-cast-1(0 top nil)
  (setq decl-or-cast (c-forward-decl-or-cast-1 match-pos context last-cast-end))
  (if (eq context 'not-decl) ...)
  (if (or (and (eq (get-text-property (point) 'face) 'font-lock-keyword-face) ...) ...) t ...)
  (if (if (or (and (eq (get-text-property (point) 'face) 'font-lock-keyword-face) ...) ...) t ...) ...)
  (lambda (match-pos inside-macro &optional toplev) ...)(0 nil t)
  c-find-decl-spots(11 "[[:alpha:]_]" (nil font-lock-type-face font-lock-constant-face font-lock-keyword-face) ...)
  (let (start-pos context ...) ... nil)
  (save-restriction (let (start-pos context ...) ... nil))
  (progn (save-restriction (let (start-pos context ...) ... nil)))
  (if (< (point) limit) (progn (save-restriction (let (start-pos context ...) ... nil))))
  c-font-lock-declarations(11)
  font-lock-fontify-keywords-region(1 11 nil)
  font-lock-default-fontify-region(1 11 nil)
  funcall(font-lock-default-fontify-region 1 11 nil)
  (let (new-beg new-end new-region case-fold-search) ...)
  c-font-lock-fontify-region(1 11 nil)
  font-lock-fontify-region(1 11)
  #f(compiled-function (beg end) #<bytecode 0x1fd6e1a05171>)(1 11)
  font-lock-ensure(1 11)
  diff-syntax-fontify-props(#("a/test.c" 0 8 (face (diff-file-header diff-header))) "int i)\n{\n1" (1 3) t)
  diff-syntax-fontify-hunk(78 111 t)
  diff-syntax-fontify(78 111)
  #f(compiled-function (beg end) #<bytecode 0x158f39208a39>)(78 111)
  diff--iterate-hunks(113 #f(compiled-function (beg end) #<bytecode 0x158f39208a39>))
  diff--font-lock-syntax(113)
  font-lock-fontify-keywords-region(1 113 nil)
  font-lock-default-fontify-region(1 113 nil)
  font-lock-fontify-region(1 113)
  #f(compiled-function (beg end) #<bytecode 0x1fd6e1a05171>)(1 113)
  font-lock-ensure()
  (if (eq major-mode 'fundamental-mode) nil (font-lock-ensure))
  (progn (if mode (let ((#:wconfig (current-window-configuration))) ...) ...) ...)
  (condition-case #:err (progn ...) ((debug error) (message "Error: %S" #:err) nil))
  (let ((font-lock-verbose nil) (enable-local-variables nil)) ...)
  (progn (buffer-disable-undo) (mm-enable-multibyte) ...)
  (unwind-protect (progn (buffer-disable-undo) (mm-enable-multibyte) ...) ...)
  (save-current-buffer (set-buffer #:temp-buffer) (unwind-protect ...))
  (let ((#:temp-buffer (generate-new-buffer " *temp*"))) (save-current-buffer ...))
  (let ((charset (mail-content-type-get (nth 1 handle) 'charset)) text coding-system ovs) ...)
  mm-display-inline-fontify(... diff-mode)
  mm-display-patch-inline(...)
  mm-display-inline(...)
  gnus-mime-display-single(...)
  gnus-mime-display-part(...)
  mapcar(gnus-mime-display-part (...))
  gnus-mime-display-mixed((...))
  gnus-mime-display-part((#("multipart/mixed" 0 15 ...) ...))
  gnus-display-mime()
  gnus-article-prepare-display()
  gnus-article-prepare(5460 nil)
  funcall(gnus-article-prepare 5460 nil)
  (prog1 (funcall (or gnus-summary-display-article-function ...) article all-header) ...)
  (if (null article) nil (prog1 (funcall (or gnus-summary-display-article-function ...) article all-header)))
  gnus-summary-display-article(5460 nil)
  (progn (gnus-summary-display-article article all-headers) ...)
  (if (or (and gnus-single-article-buffer ...)) ... 'old)
  (save-current-buffer (set-buffer gnus-summary-buffer) ...)
  (let ((article (or article (gnus-summary-article-number))) ...) ...)
  gnus-summary-select-article(nil nil pseudo)
  (eq (gnus-summary-select-article nil nil 'pseudo) 'old)
  (if (eq (gnus-summary-select-article nil nil 'pseudo) 'old) ...)
  gnus-summary-scroll-up(1)
  funcall-interactively(gnus-summary-scroll-up 1)
  call-interactively(gnus-summary-scroll-up nil nil)
  command-execute(gnus-summary-scroll-up)

I don't know if it's possible to fix c-mode to not raise the error
during fontification.  But at least the patch below will avoid this error
while displaying such attachments in Gnus.  Normally calling font-lock-ensure
ignores the fontification errors when called from font-lock.
But in mm-display-inline-fontify font-lock-ensure is called directly
from top-level, so this patch ignores its errors.

diff --git a/lisp/gnus/mm-view.el b/lisp/gnus/mm-view.el
index 6ffa1fc168..ebaf8435c0 100644
--- a/lisp/gnus/mm-view.el
+++ b/lisp/gnus/mm-view.el
@@ -500,7 +500,7 @@ mm-display-inline-fontify
 	      (setq mode major-mode)))
 	  ;; Do not fontify if the guess mode is fundamental.
 	  (unless (eq major-mode 'fundamental-mode)
-	    (font-lock-ensure))))
+	    (ignore-errors (font-lock-ensure)))))
       (setq text (buffer-string))
       (when (eq mode 'diff-mode)
 	(setq ovs (mapcar (lambda (ov) (list ov (overlay-start ov)

Then visiting such attachments will just leave this line in *Messages*
without wreaking much havoc:

  Error during redisplay: (jit-lock-function 1) signaled (wrong-type-argument integer-or-marker-p nil)

diff --git a/test.c b/test.c
index aaa..bbb 100644
--- a/test.c
+++ b/test.c
@@ -1,3 +2,3 @@
 int i)
 {
-1
+2