GNU bug report logs - #53605
CC Mode 5.35.1 (C++//l); C++11 string literal operator mishighlighted

Previous Next

Package: cc-mode;

Reported by: Richard Copley <rcopley <at> gmail.com>

Date: Fri, 28 Jan 2022 14:55:02 UTC

Severity: normal

Done: Alan Mackenzie <acm <at> muc.de>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 53605 in the body.
You can then email your comments to 53605 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-cc-mode <at> gnu.org:
bug#53605; Package cc-mode. (Fri, 28 Jan 2022 14:55:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Richard Copley <rcopley <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-cc-mode <at> gnu.org. (Fri, 28 Jan 2022 14:55:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Richard Copley <rcopley <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: CC Mode 5.35.1 (C++//l); C++11 string literal operator mishighlighted
Date: Fri, 28 Jan 2022 14:53:20 +0000
Package: cc-mode
Hi Alan,

The code below (which is valid since C++11) is mishighlighted,
with the open-paren after "_opcode" in font-lock-warning face
and the subsequent characters in font-lock-string-face. This is
unstable: inserting and deleting a character before the open-
paren fixes the highlighting, and [M-x normal-mode RET] breaks
it again.

<<END
#include <cstddef>
int operator""_opcode(const char *p, std::size_t size) {
  return 0;
}
END

Emacs  : GNU Emacs 29.0.50 (build 3, x86_64-w64-mingw32)
 of 2022-01-28 (on master)
Package: CC Mode 5.35.1 (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)

current state:
==============
(setq
 c-basic-offset 2
 c-comment-only-line-offset '(0 . 0)
 c-indent-comment-alist '((anchored-comment column . 0) (end-block
space . 1) (cpp-end-block space . 2))
 c-indent-comments-syntactically-p nil
 c-block-comment-prefix ""
 c-comment-prefix-regexp '((pike-mode . "//+!?\\|\\**") (awk-mode .
"#+") (other . "//+\\|\\**"))
 c-doc-comment-style '((java-mode . javadoc) (pike-mode . autodoc)
(c-mode . gtkdoc) (c++-mode . gtkdoc))
 c-cleanup-list '(scope-operator)
 c-hanging-braces-alist '((substatement-open before after)
(arglist-cont-nonempty))
 c-hanging-colons-alist nil
 c-hanging-semi&comma-criteria '(c-semi&comma-inside-parenlist)
 c-backslash-column 48
 c-backslash-max-column 72
 c-special-indent-hook '(t c-gnu-impose-minimum)
 c-label-minimum-indentation 1
 c-offsets-alist '((inexpr-class . +)
           (inexpr-statement . +)
           (lambda-intro-cont . +)
           (inlambda . 0)
           (template-args-cont c-lineup-template-args +)
           (incomposition . +)
           (inmodule . +)
           (innamespace . +)
           (inextern-lang . +)
           (composition-close . 0)
           (module-close . 0)
           (namespace-close . 0)
           (extern-lang-close . 0)
           (composition-open . 0)
           (module-open . 0)
           (namespace-open . 0)
           (extern-lang-open . 0)
           (objc-method-call-cont c-lineup-ObjC-method-call-colons
c-lineup-ObjC-method-call +)
           (objc-method-args-cont . c-lineup-ObjC-method-args)
           (objc-method-intro . [0])
           (friend . 0)
           (cpp-define-intro c-lineup-cpp-define +)
           (cpp-macro-cont . +)
           (cpp-macro . [0])
           (inclass . +)
           (stream-op . c-lineup-streamop)
           (arglist-cont-nonempty c-lineup-gcc-asm-reg c-lineup-arglist)
           (arglist-cont c-lineup-gcc-asm-reg 0)
           (comment-intro c-lineup-knr-region-comment c-lineup-comment)
           (catch-clause . 0)
           (else-clause . 0)
           (do-while-closure . 0)
           (access-label . -)
           (case-label . 0)
           (substatement . +)
           (statement-case-intro . +)
           (statement . 0)
           (brace-entry-open . 0)
           (brace-list-entry . 0)
           (brace-list-close . 0)
           (block-close . 0)
           (block-open . 0)
           (inher-cont . c-lineup-multi-inher)
           (inher-intro . +)
           (member-init-cont . c-lineup-multi-inher)
           (member-init-intro . +)
           (annotation-var-cont . +)
           (annotation-top-cont . 0)
           (topmost-intro . 0)
           (knr-argdecl . 0)
           (func-decl-cont . +)
           (inline-close . 0)
           (class-close . 0)
           (class-open . 0)
           (defun-block-intro . +)
           (defun-close . 0)
           (defun-open . 0)
           (c . c-lineup-C-comments)
           (string . c-lineup-dont-change)
           (topmost-intro-cont first c-lineup-topmost-intro-cont
c-lineup-gnu-DEFUN-intro-cont)
           (brace-list-intro first c-lineup-2nd-brace-entry-in-arglist
c-lineup-class-decl-init-+ +)
           (brace-list-open . +)
           (inline-open . 0)
           (arglist-close . c-lineup-arglist)
           (arglist-intro . c-lineup-arglist-intro-after-paren)
           (statement-cont . +)
           (statement-case-open . +)
           (label . 0)
           (substatement-label . 0)
           (substatement-open . +)
           (knr-argdecl-intro . 5)
           (statement-block-intro . +)
           )
 c-buffer-is-cc-mode 'c++-mode
 c-tab-always-indent t
 c-syntactic-indentation t
 c-syntactic-indentation-in-macros t
 c-ignore-auto-fill '(string cpp code)
 c-auto-align-backslashes t
 c-backspace-function 'backward-delete-char-untabify
 c-delete-function 'delete-char
 c-electric-pound-behavior nil
 c-default-style '((java-mode . "java") (awk-mode . "awk") (other . "gnu"))
 c-enable-xemacs-performance-kludge-p nil
 c-old-style-variable-behavior nil
 defun-prompt-regexp nil
 tab-width 8
 comment-column 32
 parse-sexp-ignore-comments t
 parse-sexp-lookup-properties t
 auto-fill-function nil
 comment-multi-line t
 comment-start-skip "\\(?://+\\|/\\*+\\)\\s *"
 fill-prefix nil
 fill-column 70
 paragraph-start "[     ]*\\(//+\\|\\**\\)[     ]*$\\|^\f"
 adaptive-fill-mode t
 adaptive-fill-regexp "[     ]*\\(//+\\|\\**\\)[     ]*\\([
]*\\([-–!|#%;>*·•‣⁃◦]+[     ]*\\)*\\)"
 )




Information forwarded to bug-cc-mode <at> gnu.org:
bug#53605; Package cc-mode. (Sat, 29 Jan 2022 11:35:01 GMT) Full text and rfc822 format available.

Message #8 received at 53605 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Richard Copley <rcopley <at> gmail.com>
Cc: 53605 <at> debbugs.gnu.org
Subject: Re: bug#53605: CC Mode 5.35.1 (C++//l); C++11 string literal
 operator mishighlighted
Date: Sat, 29 Jan 2022 11:34:44 +0000
Hello, Richard.

Thanks for the bug report.

On Fri, Jan 28, 2022 at 14:53:20 +0000, Richard Copley wrote:
> Package: cc-mode
> Hi Alan,

> The code below (which is valid since C++11) is mishighlighted,
> with the open-paren after "_opcode" in font-lock-warning face
> and the subsequent characters in font-lock-string-face. This is
> unstable: inserting and deleting a character before the open-
> paren fixes the highlighting, and [M-x normal-mode RET] breaks
> it again.

> <<END
> #include <cstddef>
> int operator""_opcode(const char *p, std::size_t size) {
>   return 0;
> }
> END

It looks like the r""_opcode( has been mistaken for the raw string
delimiter R""_opcode(, and the ( is in warning face because there's no
matching closing delimiter.  case-fold-search ought to be nil here, but
appears not to be.  And the check for the "R" ought to exclude other
alphanumeric characters.

I'll have a closer look at it in the next few days.  I'm a bit short of
time right at the moment.  (Sorry.)

> Emacs  : GNU Emacs 29.0.50 (build 3, x86_64-w64-mingw32)
>  of 2022-01-28 (on master)
> Package: CC Mode 5.35.1 (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)

[ .... thanks for the (snipped) status dump! ]

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#53605; Package cc-mode. (Sun, 30 Jan 2022 15:43:02 GMT) Full text and rfc822 format available.

Message #11 received at 53605 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Richard Copley <rcopley <at> gmail.com>
Cc: 53605 <at> debbugs.gnu.org
Subject: Re: bug#53605: CC Mode 5.35.1 (C++//l); C++11 string literal
 operator mishighlighted
Date: Sun, 30 Jan 2022 15:42:03 +0000
Hello again, Richard.

On Fri, Jan 28, 2022 at 14:53:20 +0000, Richard Copley wrote:
> Package: cc-mode
> Hi Alan,

> The code below (which is valid since C++11) is mishighlighted,
> with the open-paren after "_opcode" in font-lock-warning face
> and the subsequent characters in font-lock-string-face. This is
> unstable: inserting and deleting a character before the open-
> paren fixes the highlighting, and [M-x normal-mode RET] breaks
> it again.

> <<END
> #include <cstddef>
> int operator""_opcode(const char *p, std::size_t size) {
>   return 0;
> }
> END

Yes.  Please try out the following patch, and confirm that it has fixed
the problem (or let me know what is still not right).  It's actually a
small patch, just binding `case-fold-search' to nil in a function, but
reindenting the entire function.

As I said earlier, the r""_opcode( was getting confused for R""_opcode(,
which would be a valid raw string delimiter.

Thanks!


diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 3a3413dc36..957a0b8a7c 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -798,43 +798,44 @@ c-common-init
 `c-basic-common-init' for details.  It's only optional to be
 compatible with old code; callers should always specify it."
 
-  (unless mode
-    ;; Called from an old third party package.  The fallback is to
-    ;; initialize for C.
-    (c-init-language-vars-for 'c-mode))
-
-  (c-basic-common-init mode c-default-style)
-  (when mode
-    ;; Only initialize font locking if we aren't called from an old package.
-    (c-font-lock-init))
-
-  ;; Starting a mode is a sort of "change".  So call the change functions...
-  (save-restriction
-    (widen)
-    (setq c-new-BEG (point-min))
-    (setq c-new-END (point-max))
-    (save-excursion
-      (let (before-change-functions after-change-functions)
-	(mapc (lambda (fn)
-		(funcall fn (point-min) (point-max)))
-	      c-get-state-before-change-functions)
-	(mapc (lambda (fn)
-		(funcall fn (point-min) (point-max)
-			 (- (point-max) (point-min))))
-	      c-before-font-lock-functions))))
-
-  (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
-  (set (make-local-variable 'outline-level) 'c-outline-level)
-  (set (make-local-variable 'add-log-current-defun-function)
-       (lambda ()
-	 (or (c-cpp-define-name) (car (c-defun-name-and-limits nil)))))
-  (let ((rfn (assq mode c-require-final-newline)))
-    (when rfn
-      (if (boundp 'mode-require-final-newline)
-          (and (cdr rfn)
-               (set (make-local-variable 'require-final-newline)
-                    mode-require-final-newline))
-        (set (make-local-variable 'require-final-newline) (cdr rfn))))))
+  (let (case-fold-search)
+    (unless mode
+      ;; Called from an old third party package.  The fallback is to
+      ;; initialize for C.
+      (c-init-language-vars-for 'c-mode))
+
+    (c-basic-common-init mode c-default-style)
+    (when mode
+      ;; Only initialize font locking if we aren't called from an old package.
+      (c-font-lock-init))
+
+    ;; Starting a mode is a sort of "change".  So call the change functions...
+    (save-restriction
+      (widen)
+      (setq c-new-BEG (point-min))
+      (setq c-new-END (point-max))
+      (save-excursion
+	(let (before-change-functions after-change-functions)
+	  (mapc (lambda (fn)
+		  (funcall fn (point-min) (point-max)))
+		c-get-state-before-change-functions)
+	  (mapc (lambda (fn)
+		  (funcall fn (point-min) (point-max)
+			   (- (point-max) (point-min))))
+		c-before-font-lock-functions))))
+
+    (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
+    (set (make-local-variable 'outline-level) 'c-outline-level)
+    (set (make-local-variable 'add-log-current-defun-function)
+	 (lambda ()
+	   (or (c-cpp-define-name) (car (c-defun-name-and-limits nil)))))
+    (let ((rfn (assq mode c-require-final-newline)))
+      (when rfn
+	(if (boundp 'mode-require-final-newline)
+            (and (cdr rfn)
+		 (set (make-local-variable 'require-final-newline)
+                      mode-require-final-newline))
+          (set (make-local-variable 'require-final-newline) (cdr rfn)))))))
 
 (defun c-count-cfss (lv-alist)
   ;; LV-ALIST is an alist like `file-local-variables-alist'.  Count how many


[ .... ]

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#53605; Package cc-mode. (Mon, 31 Jan 2022 14:38:01 GMT) Full text and rfc822 format available.

Message #14 received at 53605 <at> debbugs.gnu.org (full text, mbox):

From: Richard Copley <rcopley <at> gmail.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 53605 <at> debbugs.gnu.org
Subject: Re: bug#53605: CC Mode 5.35.1 (C++//l);
 C++11 string literal operator mishighlighted
Date: Mon, 31 Jan 2022 14:37:12 +0000
Hi Alan,

On Sun, 30 Jan 2022 at 15:42, Alan Mackenzie <acm <at> muc.de> wrote:
>
> Hello again, Richard.
>
> Yes.  Please try out the following patch, and confirm that it has fixed
> the problem (or let me know what is still not right).  It's actually a
> small patch, just binding `case-fold-search' to nil in a function, but
> reindenting the entire function.

Works for me. Thank you!

> As I said earlier, the r""_opcode( was getting confused for R""_opcode(,
> which would be a valid raw string delimiter.
>
> Thanks!
>
>
> diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
> index 3a3413dc36..957a0b8a7c 100644
> --- a/lisp/progmodes/cc-mode.el
> +++ b/lisp/progmodes/cc-mode.el
> @@ -798,43 +798,44 @@ c-common-init
>  `c-basic-common-init' for details.  It's only optional to be
>  compatible with old code; callers should always specify it."
>
> -  (unless mode
> -    ;; Called from an old third party package.  The fallback is to
> -    ;; initialize for C.
> -    (c-init-language-vars-for 'c-mode))
> -
> -  (c-basic-common-init mode c-default-style)
> -  (when mode
> -    ;; Only initialize font locking if we aren't called from an old package.
> -    (c-font-lock-init))
> -
> -  ;; Starting a mode is a sort of "change".  So call the change functions...
> -  (save-restriction
> -    (widen)
> -    (setq c-new-BEG (point-min))
> -    (setq c-new-END (point-max))
> -    (save-excursion
> -      (let (before-change-functions after-change-functions)
> -       (mapc (lambda (fn)
> -               (funcall fn (point-min) (point-max)))
> -             c-get-state-before-change-functions)
> -       (mapc (lambda (fn)
> -               (funcall fn (point-min) (point-max)
> -                        (- (point-max) (point-min))))
> -             c-before-font-lock-functions))))
> -
> -  (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
> -  (set (make-local-variable 'outline-level) 'c-outline-level)
> -  (set (make-local-variable 'add-log-current-defun-function)
> -       (lambda ()
> -        (or (c-cpp-define-name) (car (c-defun-name-and-limits nil)))))
> -  (let ((rfn (assq mode c-require-final-newline)))
> -    (when rfn
> -      (if (boundp 'mode-require-final-newline)
> -          (and (cdr rfn)
> -               (set (make-local-variable 'require-final-newline)
> -                    mode-require-final-newline))
> -        (set (make-local-variable 'require-final-newline) (cdr rfn))))))
> +  (let (case-fold-search)
> +    (unless mode
> +      ;; Called from an old third party package.  The fallback is to
> +      ;; initialize for C.
> +      (c-init-language-vars-for 'c-mode))
> +
> +    (c-basic-common-init mode c-default-style)
> +    (when mode
> +      ;; Only initialize font locking if we aren't called from an old package.
> +      (c-font-lock-init))
> +
> +    ;; Starting a mode is a sort of "change".  So call the change functions...
> +    (save-restriction
> +      (widen)
> +      (setq c-new-BEG (point-min))
> +      (setq c-new-END (point-max))
> +      (save-excursion
> +       (let (before-change-functions after-change-functions)
> +         (mapc (lambda (fn)
> +                 (funcall fn (point-min) (point-max)))
> +               c-get-state-before-change-functions)
> +         (mapc (lambda (fn)
> +                 (funcall fn (point-min) (point-max)
> +                          (- (point-max) (point-min))))
> +               c-before-font-lock-functions))))
> +
> +    (set (make-local-variable 'outline-regexp) "[^#\n\^M]")
> +    (set (make-local-variable 'outline-level) 'c-outline-level)
> +    (set (make-local-variable 'add-log-current-defun-function)
> +        (lambda ()
> +          (or (c-cpp-define-name) (car (c-defun-name-and-limits nil)))))
> +    (let ((rfn (assq mode c-require-final-newline)))
> +      (when rfn
> +       (if (boundp 'mode-require-final-newline)
> +            (and (cdr rfn)
> +                (set (make-local-variable 'require-final-newline)
> +                      mode-require-final-newline))
> +          (set (make-local-variable 'require-final-newline) (cdr rfn)))))))
>
>  (defun c-count-cfss (lv-alist)
>    ;; LV-ALIST is an alist like `file-local-variables-alist'.  Count how many
>
>
> [ .... ]
>
> --
> Alan Mackenzie (Nuremberg, Germany).




Reply sent to Alan Mackenzie <acm <at> muc.de>:
You have taken responsibility. (Mon, 31 Jan 2022 17:51:01 GMT) Full text and rfc822 format available.

Notification sent to Richard Copley <rcopley <at> gmail.com>:
bug acknowledged by developer. (Mon, 31 Jan 2022 17:51:01 GMT) Full text and rfc822 format available.

Message #19 received at 53605-done <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Richard Copley <rcopley <at> gmail.com>
Cc: 53605-done <at> debbugs.gnu.org
Subject: Re: bug#53605: CC Mode 5.35.1 (C++//l); C++11 string literal
 operator mishighlighted
Date: Mon, 31 Jan 2022 17:50:44 +0000
Hello, Richard.

On Mon, Jan 31, 2022 at 14:37:12 +0000, Richard Copley wrote:
> Hi Alan,

> On Sun, 30 Jan 2022 at 15:42, Alan Mackenzie <acm <at> muc.de> wrote:

> > Yes.  Please try out the following patch, and confirm that it has
> > fixed the problem (or let me know what is still not right).  It's
> > actually a small patch, just binding `case-fold-search' to nil in a
> > function, but reindenting the entire function.

> Works for me. Thank you!

Thanks for the quick response!  I've committed the fix to CC Mode and
the Emacs master branch at savannah, and I'm closing the bug with this
post.

-- 
Alan Mackenzie (Nuremberg, Germany).




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 01 Mar 2022 12:24:03 GMT) Full text and rfc822 format available.

This bug report was last modified 3 years and 112 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.