Subject: bug#36650: 27.0.50; CC Mode: Support C++ attributes

From: Alan Mackenzie <[email-masked]>
Date: Sun, 21 Jul 2019 11:33:05 +0000

Hello, Óscar.

Thanks for the rapid response!

On Sun, Jul 21, 2019 at 00:21:43 +0200, Óscar Fuentes wrote:
> Alan Mackenzie <[email-masked]> writes:

> > The patch below (which should apply cleanly to the master branch) is
> > a first attempt at handling C++ attributes.

> Thank you Alan. Wow, it required more changes than I would expect.

These attributes can appear anywhere.  That's why.

> Seems that it mostly works. The only issue I've found so far is

> struct S {
>   S[[using : const]]()
>   : data(0)
>   {}
>   int data;
> };

> Note how ": data(0)" is not indented. If the attribute is moved before the
> name:

> struct S {
>   [[using : const]] S()
>     : data(0)
>   {}
>   int data;
> };

> or after the parameter list:

> struct S {
>   S() [[using: const]]
>     : data(0)
>   {}
>   int data;
> };

> then the indentation is correct. This only happens if the attribute is
> of the form "using:" (it is irrelevant if there is space between "using"
> and the colon).

Yes.  More precisely, it was the presence of the colon inside the
attribute which confused a low level CC Mode function
(c-crosses-statement-barrier-p).   This function scans forward for a
character which might be relevant for statement boundaries, and one of
these characters is :.  I've added handling for [[...]] into this
function, and it now seems to be working.

Would you please apply the following supplementary patch to your current
master state, try it out again, and let me know how it goes.

Thanks!

--- cc-engine.el~	2019-07-20 17:45:13.944753490 +0000
+++ cc-engine.el	2019-07-21 10:43:31.470078502 +0000
@@ -697,6 +697,21 @@
       (overlay-put (make-overlay end ol-end) 'face face))))
 
 
+(defmacro c-looking-at-c++-attribute ()
+  ;; If we're in C++ Mode, and point is at the [[ introducing an attribute,
+  ;; return the position of the end of the attribute, otherwise return nil.
+  ;; The match data are NOT preserved over this macro.
+  `(and
+    (c-major-mode-is 'c++-mode)
+    (looking-at "\\[\\[")
+    (save-excursion
+      (and
+       (c-go-list-forward)
+       (eq (char-before) ?\])
+       (eq (char-before (1- (point))) ?\])
+       (point)))))
+
+
 ;; `c-beginning-of-statement-1' and accompanying stuff.
 
 ;; KLUDGE ALERT: c-maybe-labelp is used to pass information between
@@ -1420,9 +1435,15 @@
 		      c-opt-cpp-symbol			 ; usually "#"
 		      (substring c-stmt-delim-chars 1))	 ; e.g. ";{}?:"
 	    c-stmt-delim-chars))
+	 (skip-chars
+	  (if (c-major-mode-is 'c++-mode)
+	      (concat (substring skip-chars 0 1) ; "^"
+		      "["			 ; to catch C++ attributes
+		      (substring skip-chars 1))	; e.g. "#;{}?:"
+	    skip-chars))
 	 (non-skip-list
 	  (append (substring skip-chars 1) nil)) ; e.g. (?# ?\; ?{ ?} ?? ?:)
-	 lit-range lit-start vsemi-pos)
+	 lit-range lit-start vsemi-pos attr-end)
     (save-restriction
       (widen)
       (save-excursion
@@ -1446,6 +1467,11 @@
 	     ;; In a string/comment?
 	     ((setq lit-range (c-literal-limits from))
 	      (goto-char (cdr lit-range)))
+	     ;; Skip over a C++ attribute?
+	     ((eq (char-after) ?\[)
+	      (if (setq attr-end (c-looking-at-c++-attribute))
+		  (goto-char attr-end)
+		(forward-char)))
 	     ((eq (char-after) ?:)
 	      (forward-char)
 	      (if (and (eq (char-after) ?:)
@@ -1839,21 +1865,6 @@
 ;; enclosing END, if any, else nil.
 (defvar c-sws-lit-limits nil)
 
-(defmacro c-looking-at-c++-attribute ()
-  ;; If we're in C++ Mode, and point is at the [[ introducing an attribute,
-  ;; return the position of the end of the attribute, otherwise return nil.
-  ;; The match data are NOT preserved over this macro.
-  `(and
-    (c-major-mode-is 'c++-mode)
-    (looking-at "\\[\\[")
-    (save-excursion
-      (and
-       (c-go-list-forward)
-       (eq (char-before) ?\])
-       (eq (char-before (1- (point))) ?\])
-       (point)))))
-
-;; (defmacro c-enclosing-c++-attribute ()
 (defun c-enclosing-c++-attribute ()
   ;; If we're in C++ Mode, and point is within a correctly balanced [[ ... ]]
   ;; attribute structure, return a cons of its starting and ending positions.

-- 
Alan Mackenzie (Nuremberg, Germany).