Subject: Re: bug#36397: CC Mode 5.34 (C++//l); Bad highlighting on inserting a string

From: Alan Mackenzie <[email-masked]>
Date: Thu, 27 Jun 2019 11:11:54 +0000

Hello, Richard.

On Wed, Jun 26, 2019 at 22:36:09 +0100, Richard Copley wrote:

> Hi Alan,
> Thanks for all your recent work on CC mode.
> It isn't much fun to use, currently, on master. For example, from "emacs
> -Q":

> Add this text to a buffer in C or C++ mode (<<END):
> int main ()
> {
> }
> END

> Add a double quote, inside main() or before it. (The double quote is
> highlighted as an error. IIUC this is as expected now.)
> Add another double quote. (Actual: both quotes and what comes after are
> highlighted as a string. Expected: just the quotes are highlighted as a
> string.)
> Add a semicolon. (Actual: the semicolon is not highlighted but everything
> after it is still highlighted as a string. Expected: just the quotes.)

Yes, there is a bug here.  Sorry about that!  Thanks for taking the
trouble to report it.

The bug is to do with incorrect coding for handling a newline becoming
an escaped newline.

There are more than just that one coding error in this area, and I'd
like to fix them all at the same time.  In the meantime, please try out
this patch, and let me know how well it works.  Thanks!

diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 5c18879712..ff358aae72 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1262,11 +1262,12 @@ c-before-change-check-unbalanced-strings
 	  (setq c-new-BEG (min (car beg-limits) c-new-BEG))))
 
      ((< end (point-max))
-      (goto-char (1+ end))	; might be a newline.
-      ;; In the following regexp, the initial \n caters for a newline getting
-      ;; joined to a preceding \ by the removal of what comes between.
-      (re-search-forward "[\n\r]?\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*"
-			 nil t)
+      ;; Move to end of logical line (as it will be after the change)
+      (goto-char (if (and (memq (char-after end) '(?\n ?\r))
+			  (eq (char-before beg) ?\\))
+		     (1+ end)
+		   end))
+      (re-search-forward "\\(\\\\\\(.\\|\n\\)\\|[^\\\n\r]\\)*" nil t)
       ;; We're at an EOLL or point-max.
       (if (equal (c-get-char-property (point) 'syntax-table) '(15))
 	  (if (memq (char-after) '(?\n ?\r))

> Emacs  : GNU Emacs 27.0.50 (build 2, x86_64-w64-mingw32)
>  of 2019-06-26
> Package: CC Mode 5.34 (C++//l)
> Buffer Style: gnu
> c-emacs-features: (pps-extended-state col-0-paren posix-char-classes
> gen-string-delim gen-comment-delim syntax-properties 1-bit)

[ CC Mode configuration appreciated, but snipped. ]

-- 
Alan Mackenzie (Nuremberg, Germany).