From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.bugs Subject: bug#28623: 27.0.50; lisp/progmodes/cc-engine.el incorrect indentation of C++14 curly-brace initializer list Date: Sat, 4 Nov 2017 19:56:39 +0000 Message-ID: <20171104195639.GA5384@ACM> References: <20171004181552.GA15562@ACM> <20171011203221.GB7384@ACM> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Transfer-Encoding: 8bit X-Trace: blaine.gmane.org 1509825856 32396 195.159.176.226 (4 Nov 2017 20:04:16 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Sat, 4 Nov 2017 20:04:16 +0000 (UTC) User-Agent: Mutt/1.7.2 (2016-11-26) Cc: John Wiegley , 28623@debbugs.gnu.org To: Tadeus Prastowo Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Nov 04 21:04:11 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eB4fr-000846-GB for geb-bug-gnu-emacs@m.gmane.org; Sat, 04 Nov 2017 21:04:11 +0100 Original-Received: from localhost ([::1]:42054 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eB4fy-0007ye-LB for geb-bug-gnu-emacs@m.gmane.org; Sat, 04 Nov 2017 16:04:18 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:39680) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eB4fo-0007yF-54 for bug-gnu-emacs@gnu.org; Sat, 04 Nov 2017 16:04:10 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eB4fm-0000Oj-8H for bug-gnu-emacs@gnu.org; Sat, 04 Nov 2017 16:04:08 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:42279) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1eB4fi-0000Fq-EC; Sat, 04 Nov 2017 16:04:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1eB4fi-0006Q1-0B; Sat, 04 Nov 2017 16:04:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Alan Mackenzie Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org, bug-cc-mode@gnu.org Resent-Date: Sat, 04 Nov 2017 20:04:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 28623 X-GNU-PR-Package: emacs,cc-mode X-GNU-PR-Keywords: Original-Received: via spool by 28623-submit@debbugs.gnu.org id=B28623.150982583124655 (code B ref 28623); Sat, 04 Nov 2017 20:04:01 +0000 Original-Received: (at 28623) by debbugs.gnu.org; 4 Nov 2017 20:03:51 +0000 Original-Received: from localhost ([127.0.0.1]:50960 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1eB4fX-0006Pb-3H for submit@debbugs.gnu.org; Sat, 04 Nov 2017 16:03:51 -0400 Original-Received: from ocolin.muc.de ([193.149.48.4]:45125 helo=mail.muc.de) by debbugs.gnu.org with smtp (Exim 4.84_2) (envelope-from ) id 1eB4fV-0006PS-Q6 for 28623@debbugs.gnu.org; Sat, 04 Nov 2017 16:03:50 -0400 Original-Received: (qmail 36597 invoked by uid 3782); 4 Nov 2017 20:03:48 -0000 Original-Received: from acm.muc.de (p548C71A6.dip0.t-ipconnect.de [84.140.113.166]) by colin.muc.de (tmda-ofmipd) with ESMTP; Sat, 04 Nov 2017 21:03:46 +0100 Original-Received: (qmail 5927 invoked by uid 1000); 4 Nov 2017 19:56:39 -0000 Content-Disposition: inline In-Reply-To: X-Delivery-Agent: TMDA/1.1.12 (Macallan) X-Primary-Address: acm@muc.de X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:139448 Archived-At: Hello, Tadeus. On Thu, Oct 12, 2017 at 13:38:56 +0200, Tadeus Prastowo wrote: > Hi Alan! > On Wed, Oct 11, 2017 at 10:32 PM, Alan Mackenzie wrote: > > Hello, Tadeus. > [...] > > I'm sorry is been a week without any communication from me. The reason > > is I've run into problems with other related cases. For example, in > > 1. auto bad4 = f <3> ( > > 2. {3, 4}, > > L2 needs to be parsed as an arglist-intro and indented as shown. It's > > actually being parsed as a brace-list-open with anchor point on "auto". > > What's confusing me is the confusion between a brace list being > > recognised by its context (which is what > > c-looking-at-or-maybe-in-bracelist mostly does) and by its content. The > > {3, 4} above is a brace list by its content but not by its context. > > However, it's being wrongly recognised as a by-context brace list, hence > > is being parsed and indented wrongly. > > I'm not going to have much time to sort this out over the next week or > > two, so please bear with me. I haven't forgotten about this. > Thanks for sharing the problem with me. I will also look into the > matter during this weekend. Hopefully I can come up with a good > solution :) I think I've solved this, though it's been perhaps the most difficult bug in CC Mode for some years. Each time I thought I'd nailed it, some awkward test case would misbehave. Anyhow, would you please try the patch below, which should apply cleanly to either the emacs-26 branch or master. It is not finished; for example I've still got to amend several comments. Nevertheless I think it's working. I look forward to hearing of any problems which are still in this patch, or of a report that it seems to be working. If you have nothing against it, I intend to put your test file (or bits of it) into a new file in the CC Mode test suite. Here's the patch: have fun! diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index 6f39cc6433..2da9e98345 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -10426,17 +10426,20 @@ c-looking-at-or-maybe-in-bracelist (and (c-major-mode-is 'pike-mode) c-decl-block-key)) (braceassignp 'dontknow) - inexpr-brace-list bufpos macro-start res pos after-type-id-pos) + inexpr-brace-list bufpos macro-start res pos after-type-id-pos + in-paren) (setq res (c-backward-token-2 1 t lim)) ;; Checks to do only on the first sexp before the brace. ;; Have we a C++ initialization, without an "="? (if (and (c-major-mode-is 'c++-mode) (cond - ((and (not (eq res 0)) + ((and (or (not (eq res 0)) + (eq (char-after) ?,)) (c-go-up-list-backward nil lim) ; FIXME!!! Check ; `lim' 2016-07-12. (eq (char-after) ?\()) - (setq braceassignp 'c++-noassign)) + (setq braceassignp 'c++-noassign + in-paren 'in-paren)) ((looking-at c-pre-id-bracelist-key)) ((looking-at c-return-key)) ((and (looking-at c-symbol-start) @@ -10445,9 +10448,11 @@ c-looking-at-or-maybe-in-bracelist (t nil)) (save-excursion (cond - ((not (eq res 0)) + ((or (not (eq res 0)) + (eq (char-after) ?,)) (and (c-go-up-list-backward nil lim) ; FIXME!!! Check `lim' 2016-07-12. - (eq (char-after) ?\())) + (eq (char-after) ?\() + (setq in-paren 'in-paren))) ((looking-at c-pre-id-bracelist-key)) ((looking-at c-return-key)) (t (setq after-type-id-pos (point)) @@ -10486,7 +10491,7 @@ c-looking-at-or-maybe-in-bracelist (c-backward-syntactic-ws) (eq (char-before) ?\())) ;; Single identifier between '(' and '{'. We have a bracelist. - (cons after-type-id-pos nil)) + (cons after-type-id-pos 'in-paren)) (t (goto-char pos) @@ -10544,7 +10549,7 @@ c-looking-at-or-maybe-in-bracelist (braceassignp ;; We've hit the beginning of the aggregate list. (c-beginning-of-statement-1 containing-sexp) - (cons (point) inexpr-brace-list)) + (cons (point) (or in-paren inexpr-brace-list))) ((and after-type-id-pos (save-excursion (when (eq (char-after) ?\;) @@ -10569,7 +10574,7 @@ c-looking-at-or-maybe-in-bracelist nil nil)) (and (consp res) (eq (car res) after-type-id-pos)))))) - (cons bufpos inexpr-brace-list)) + (cons bufpos (or in-paren inexpr-brace-list))) ((eq (char-after) ?\;) ;; Brace lists can't contain a semicolon, so we're done. ;; (setq containing-sexp nil) @@ -10593,7 +10598,7 @@ c-looking-at-or-maybe-in-bracelist (t t)))) ;; The caller can go up one level. ))) -(defun c-inside-bracelist-p (containing-sexp paren-state) +(defun c-inside-bracelist-p (containing-sexp paren-state by-content) ;; return the buffer position of the beginning of the brace list ;; statement if we're inside a brace list, otherwise return nil. ;; CONTAINING-SEXP is the buffer pos of the innermost containing @@ -10632,14 +10637,22 @@ c-inside-bracelist-p ;; containing sexp, so that c-looking-at-inexpr-block ;; doesn't check for an identifier before it. (setq bufpos nil) - (when (or (not (eq (char-after) ?{)) - (eq (setq bufpos (c-looking-at-or-maybe-in-bracelist - next-containing lim)) - t)) - (setq containing-sexp next-containing - lim nil - next-containing nil)))) - (and (consp bufpos) (car bufpos)))))) + (if (not (eq (char-after) ?{)) + (setq bufpos nil) + (when (eq (setq bufpos (c-looking-at-or-maybe-in-bracelist + next-containing lim)) + t) + (setq containing-sexp next-containing + lim nil + next-containing nil))))) + (cond + ((eq bufpos t) + (and containing-sexp + (not (c-looking-at-statement-block)))) + ((consp bufpos) + (and (or by-content (not (eq (cdr bufpos) 'in-paren))) + (car bufpos))) + (t nil)))))) (defun c-looking-at-special-brace-list (&optional _lim) ;; If we're looking at the start of a pike-style list, i.e., `({ })', @@ -11506,6 +11519,7 @@ c-guess-basic-syntax ;; The paren state outside `containing-sexp', or at ;; `indent-point' if `containing-sexp' is nil. (paren-state (c-parse-state)) + (state-cache (copy-tree paren-state)) ;; There's always at most one syntactic element which got ;; an anchor pos. It's stored in syntactic-relpos. syntactic-relpos @@ -11668,7 +11682,7 @@ c-guess-basic-syntax (not (c-at-vsemi-p before-ws-ip)) (not (memq char-after-ip '(?\) ?\] ?,))) (or (not (eq char-before-ip ?})) - (c-looking-at-inexpr-block-backward c-state-cache)) + (c-looking-at-inexpr-block-backward state-cache)) (> (point) (progn ;; Ought to cache the result from the @@ -11746,7 +11760,7 @@ c-guess-basic-syntax (if containing-sexp (progn (goto-char containing-sexp) - (setq lim (c-most-enclosing-brace c-state-cache + (setq lim (c-most-enclosing-brace state-cache containing-sexp)) (c-backward-to-block-anchor lim) (c-add-stmt-syntax 'case-label nil t lim paren-state)) @@ -11772,7 +11786,7 @@ c-guess-basic-syntax (containing-sexp (goto-char containing-sexp) - (setq lim (c-most-enclosing-brace c-state-cache + (setq lim (c-most-enclosing-brace state-cache containing-sexp)) (save-excursion (setq tmpsymbol @@ -11816,7 +11830,7 @@ c-guess-basic-syntax (goto-char (cdr placeholder)) (back-to-indentation) (c-add-stmt-syntax tmpsymbol nil t - (c-most-enclosing-brace c-state-cache (point)) + (c-most-enclosing-brace state-cache (point)) paren-state) (unless (eq (point) (cdr placeholder)) (c-add-syntax (car placeholder)))) @@ -12239,11 +12253,11 @@ c-guess-basic-syntax (and (eq (char-before) ?}) (save-excursion (let ((start (point))) - (if (and c-state-cache - (consp (car c-state-cache)) - (eq (cdar c-state-cache) (point))) + (if (and state-cache + (consp (car state-cache)) + (eq (cdar state-cache) (point))) ;; Speed up the backward search a bit. - (goto-char (caar c-state-cache))) + (goto-char (caar state-cache))) (c-beginning-of-decl-1 containing-sexp) ; Can't use `lim' here. (setq placeholder (point)) (if (= start (point)) @@ -12400,7 +12414,8 @@ c-guess-basic-syntax ((and (eq char-after-ip ?{) (progn (setq placeholder (c-inside-bracelist-p (point) - paren-state)) + paren-state + nil)) (if placeholder (setq tmpsymbol '(brace-list-open . inexpr-class)) (setq tmpsymbol '(block-open . inexpr-statement) @@ -12482,7 +12497,7 @@ c-guess-basic-syntax (skip-chars-forward " \t")) (goto-char placeholder)) (c-add-stmt-syntax 'arglist-cont-nonempty (list containing-sexp) t - (c-most-enclosing-brace c-state-cache (point)) + (c-most-enclosing-brace state-cache (point)) paren-state)) ;; CASE 7G: we are looking at just a normal arglist @@ -12523,7 +12538,7 @@ c-guess-basic-syntax (save-excursion (goto-char containing-sexp) (c-looking-at-special-brace-list))) - (c-inside-bracelist-p containing-sexp paren-state)))) + (c-inside-bracelist-p containing-sexp paren-state t)))) (cond ;; CASE 9A: In the middle of a special brace list opener. @@ -12571,7 +12586,7 @@ c-guess-basic-syntax (= (point) containing-sexp))) (if (eq (point) (c-point 'boi)) (c-add-syntax 'brace-list-close (point)) - (setq lim (c-most-enclosing-brace c-state-cache (point))) + (setq lim (c-most-enclosing-brace state-cache (point))) (c-beginning-of-statement-1 lim nil nil t) (c-add-stmt-syntax 'brace-list-close nil t lim paren-state))) @@ -12597,7 +12612,7 @@ c-guess-basic-syntax (goto-char containing-sexp)) (if (eq (point) (c-point 'boi)) (c-add-syntax 'brace-list-intro (point)) - (setq lim (c-most-enclosing-brace c-state-cache (point))) + (setq lim (c-most-enclosing-brace state-cache (point))) (c-beginning-of-statement-1 lim) (c-add-stmt-syntax 'brace-list-intro nil t lim paren-state))) @@ -12619,7 +12634,7 @@ c-guess-basic-syntax ((and (not (memq char-before-ip '(?\; ?:))) (not (c-at-vsemi-p before-ws-ip)) (or (not (eq char-before-ip ?})) - (c-looking-at-inexpr-block-backward c-state-cache)) + (c-looking-at-inexpr-block-backward state-cache)) (> (point) (save-excursion (c-beginning-of-statement-1 containing-sexp) @@ -12750,10 +12765,10 @@ c-guess-basic-syntax (if (>= (point) placeholder) (progn (forward-char) - (skip-chars-forward " \t")) + (skip-chars-forward " \t")) (goto-char placeholder)) (c-add-stmt-syntax 'template-args-cont (list containing-<) t - (c-most-enclosing-brace c-state-cache (point)) + (c-most-enclosing-brace state-cache (point)) paren-state)) ;; CASE 17: Statement or defun catchall. @@ -12827,7 +12842,7 @@ c-guess-basic-syntax (goto-char (cdr placeholder)) (back-to-indentation) (c-add-stmt-syntax tmpsymbol nil t - (c-most-enclosing-brace c-state-cache (point)) + (c-most-enclosing-brace state-cache (point)) paren-state) (if (/= (point) (cdr placeholder)) (c-add-syntax (car placeholder)))) > -- > Best regards, > Tadeus -- Alan Mackenzie (Nuremberg, Germany).