From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.devel Subject: Re: cc-mode uniform initialization support Date: Fri, 22 Jul 2016 21:09:57 +0000 Message-ID: <20160722210957.GA3814@acm.fritz.box> References: <55D4CC9B.7020302@dancol.org> <20160704183240.GA2375@acm.fritz.box> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: ger.gmane.org 1469221914 10571 80.91.229.3 (22 Jul 2016 21:11:54 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Fri, 22 Jul 2016 21:11:54 +0000 (UTC) Cc: Emacs developers To: Daniel Colascione Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Jul 22 23:11:45 2016 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1bQhjS-0006Kt-D9 for ged-emacs-devel@m.gmane.org; Fri, 22 Jul 2016 23:11:42 +0200 Original-Received: from localhost ([::1]:49342 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bQhjO-0002aC-C4 for ged-emacs-devel@m.gmane.org; Fri, 22 Jul 2016 17:11:38 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:52855) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bQhib-0002Zw-5Q for emacs-devel@gnu.org; Fri, 22 Jul 2016 17:10:50 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bQhiW-0001Wk-4K for emacs-devel@gnu.org; Fri, 22 Jul 2016 17:10:49 -0400 Original-Received: from mail.muc.de ([193.149.48.3]:14653) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bQhiV-0001WX-Pt for emacs-devel@gnu.org; Fri, 22 Jul 2016 17:10:44 -0400 Original-Received: (qmail 2342 invoked by uid 3782); 22 Jul 2016 21:10:41 -0000 Original-Received: from acm.muc.de (p548C69A7.dip0.t-ipconnect.de [84.140.105.167]) by colin.muc.de (tmda-ofmipd) with ESMTP; Fri, 22 Jul 2016 23:10:40 +0200 Original-Received: (qmail 5092 invoked by uid 1000); 22 Jul 2016 21:09:58 -0000 Content-Disposition: inline In-Reply-To: <20160704183240.GA2375@acm.fritz.box> User-Agent: Mutt/1.5.24 (2015-08-30) X-Delivery-Agent: TMDA/1.1.12 (Macallan) X-Primary-Address: acm@muc.de X-detected-operating-system: by eggs.gnu.org: FreeBSD 9.x X-Received-From: 193.149.48.3 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.org gmane.emacs.devel:206051 Archived-At: 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).