emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: cc-mode uniform initialization support


From: Alan Mackenzie
Subject: Re: cc-mode uniform initialization support
Date: Fri, 22 Jul 2016 21:09:57 +0000
User-agent: Mutt/1.5.24 (2015-08-30)

Hello, Daniel.

On Mon, Jul 04, 2016 at 06:32:40PM +0000, Alan Mackenzie wrote:
> On Wed, Aug 19, 2015 at 11:36:11AM -0700, Daniel Colascione wrote:
> > Recent versions of C++ support using {} to indicate an initialization
> > value. For example,

> >   1 int foo{5};
> >   2 int bar = {5};
> >   3 mumble_t mumble{
> >   4  foo,
> >   5    bar
> >   6 };
> >   7 return {mumble, foo}; // Type inferred from function declaration

> > Working with code written in this style is a nightmare right now because
> > cc-mode recognizes line 4 as defun-block-intro, leading to line 5 being
> > indented spuriously, since cc-mode thinks it's a statement continuation.
> > In reality, the construct starting at line 3 is a brace list, but
> > there's no syntactic clue to tell us that. (We can, of course, look for
> > an "=", but an "=" is no longer required for a brace list.)

[ .... ]

> I've constructed an entirely new fix for this, the first version of
> which is below.  

And now please find a much more mature version of the fix, below.  It
fails to trigger the regression test suite, yet seems to behave
reasonably with the following test file (expanded from the one you
supplied earler):

#########################################################################
int foo{5};
int bar = {5};
vec_int foo({
        abc,
        def
    });

mumble_t mumble
{
    foo,
    bar
};
return {mumble, foo}; // Type inferred from function declaration

vec_int foo({
        abc,
        def
    });
#########################################################################

[ .... ]

The patch should handle a lot of varieties of C++ uniform initialisation,
possibly all varieties (though this is unlikely).  Would you try it out
on real code, please, and let me know how it works.  Of particular
interest are any failing cases, and any circumstances where there is a
substantial slowdown caused by the patch.

I'm sure I don't need to say this, but please recompile all of the
cc-*.el files after applying the patch, so that the new macros in
cc-langs.el take full effect.



diff -r 2fcfc6e054b3 cc-engine.el
--- a/cc-engine.el      Sun Jul 03 17:54:20 2016 +0000
+++ b/cc-engine.el      Fri Jul 22 20:47:38 2016 +0000
@@ -7333,10 +7333,10 @@
   ;; this construct and return t.  If the parsing fails, return nil, leaving
   ;; point unchanged.
   (let ((here (point))
-       end
-       )
-    (if (not (c-simple-skip-symbol-backward))
+       end)
+    (if (not (c-on-identifier))
        nil
+      (c-simple-skip-symbol-backward)
       (while
          (progn
            (setq end (point))
@@ -8084,6 +8084,8 @@
                              backup-maybe-typeless
                              (when c-recognize-typeless-decls
                                (not context)))
+;;;; (2016-07-05): the next two conditions foul up font locking of a line
+;;;; ending in "({".  FIXME!!!
                          (setq pos (c-up-list-forward (point)))
                          (eq (char-before pos) ?\)))
                 (c-fdoc-shift-type-backward)
@@ -9784,9 +9786,11 @@
            ;; check for the class key here.
            (and (c-major-mode-is 'pike-mode)
                 c-decl-block-key))
-          bufpos braceassignp lim next-containing macro-start)
+          bufpos braceassignp lim next-containing macro-start res
+          after-type-id-pos)
        (while (and (not bufpos)
                   containing-sexp)
+        (setq after-type-id-pos nil)
         (when paren-state
           (if (consp (car paren-state))
               (setq lim (cdr (car paren-state))
@@ -9805,8 +9809,32 @@
           ;; see if the open brace is preceded by = or [...] in
           ;; this statement, but watch out for operator=
           (setq braceassignp 'dontknow)
-          (c-backward-token-2 1 t lim)
+          (setq res (c-backward-token-2 1 t lim))
           ;; Checks to do only on the first sexp before the brace.
+          ;; Have we a C++ initialisation, without an "="?
+          (if (and (c-major-mode-is 'c++-mode)
+                   (cond
+                    ((and (not (eq res 0))
+                          (c-go-up-list-backward nil lim) ; FIXME!!! Check ; 
`lim' 2016-07-12.
+                          (eq (char-after) ?\())
+                     (setq braceassignp 'c++-noassign))
+                    ((looking-at c-pre-id-bracelist-key)
+                     (point))
+                    ((and (looking-at c-symbol-start)
+                          (not (looking-at c-keywords-regexp)))
+                     (setq after-type-id-pos (point))
+                     (point))
+                    (t nil))
+                   (save-excursion
+                     (cond
+                      ((not (eq res 0))
+                       (and (c-go-up-list-backward nil lim) ; FIXME!!! Check 
`lim' 2016-07-12.
+                            (eq (char-after) ?\()))
+                      ((looking-at c-pre-id-bracelist-key))
+                      (t (setq after-type-id-pos (point))
+                         nil))))
+              (setq braceassignp 'c++-noassign))
+
           (when (and c-opt-inexpr-brace-list-key
                      (eq (char-after) ?\[))
             ;; In Java, an initialization brace list may follow
@@ -9877,6 +9905,24 @@
             (c-beginning-of-statement-1
              (c-most-enclosing-brace paren-state))
             (setq bufpos (point)))
+           ((and after-type-id-pos
+                 (save-excursion
+                   (if (eq (char-after) ?\;)
+                       (c-forward-token-2 1 t))
+                   (and
+                    (or (not (looking-at c-class-key))
+                        (save-excursion
+                          (goto-char (match-end 1))
+                          (c-forward-syntactic-ws)
+                          (not (eq (point) after-type-id-pos))))
+                    (progn
+                      (setq res
+                            (c-forward-decl-or-cast-1
+                             (save-excursion (c-backward-syntactic-ws) (point))
+                             nil nil))
+                      (and (consp res)
+                           (eq (car res) after-type-id-pos))))))
+            (setq bufpos (point)))
            ((eq (char-after) ?\;)
             ;; Brace lists can't contain a semicolon, so we're done.
             (setq containing-sexp nil))
@@ -10079,7 +10125,19 @@
                      (and (> (point) (or lim (point-min)))
                           (c-on-identifier)))
                    (and c-special-brace-lists
-                        (c-looking-at-special-brace-list)))
+                        (c-looking-at-special-brace-list))
+                   (and (c-major-mode-is 'c++-mode)
+                        (save-excursion
+                          (goto-char block-follows)
+                          (if (c-go-list-forward)
+                              (progn
+                                (backward-char)
+                                (c-syntactic-skip-backward
+                                 "^;," block-follows t)
+                                (not (eq (char-before) ?\;)))
+                            (or (not (c-syntactic-re-search-forward
+                                      "[;,]" nil t t))
+                                (not (eq (char-before) ?\;)))))))
                nil
              (cons 'inexpr-statement (point))))
 
@@ -11031,7 +11089,14 @@
                                    (looking-at c-opt-inexpr-brace-list-key)
                                    (setq tmpsymbol 'topmost-intro-cont)))
                             (looking-at "=\\([^=]\\|$\\)"))
-                          (looking-at c-brace-list-key))
+                          (looking-at c-brace-list-key)
+                          (looking-at c-return-key)
+                          (save-excursion
+                            (and (c-forward-type)
+                                 (looking-at c-identifier-start)
+                                 (not (looking-at c-keywords-regexp))
+                                 (c-forward-token-2)
+                                 (eq (point) (c-point 'boi indent-point)))))
                       (save-excursion
                         (while (and (< (point) indent-point)
                                     (zerop (c-forward-token-2 1 t))
diff -r 2fcfc6e054b3 cc-langs.el
--- a/cc-langs.el       Sun Jul 03 17:54:20 2016 +0000
+++ b/cc-langs.el       Fri Jul 22 20:47:38 2016 +0000
@@ -1726,6 +1726,16 @@
         "array" "float" "function" "int" "mapping" "mixed" "multiset"
         "object" "program" "string" "this_program" "void"))
 
+(c-lang-defconst c-return-kwds
+  "Keywords which return a value to the calling function."
+  t '("return")
+  idl nil)
+
+(c-lang-defconst c-return-key
+  ;; Adorned regexp matching `c-return-kwds'.
+  t (c-make-keywords-re t (c-lang-const c-return-kwds)))
+(c-lang-defvar c-return-key (c-lang-const c-return-key))
+
 (c-lang-defconst c-primitive-type-key
   ;; An adorned regexp that matches `c-primitive-type-kwds'.
   t (c-make-keywords-re t (c-lang-const c-primitive-type-kwds)))
@@ -3096,6 +3106,13 @@
   c t)
 (c-lang-defvar c-recognize-knr-p (c-lang-const c-recognize-knr-p))
 
+(c-lang-defconst c-pre-id-bracelist-key
+  "A regexp matching things which, preceding an identifier, signify a 
bracelist.
+"
+  t "\\<\\>"
+  c++ "new\\([^[:alnum:]_$]\\|$\\)\\|&&?\\(\\S.\\|$\\)")
+(c-lang-defvar c-pre-id-bracelist-key (c-lang-const c-pre-id-bracelist-key))
+
 (c-lang-defconst c-recognize-typeless-decls
   "Non-nil means function declarations without return type should be
 recognized.  That can introduce an ambiguity with parenthesized macro




-- 
Alan Mackenzie (Nuremberg, Germany).



reply via email to

[Prev in Thread] Current Thread [Next in Thread]