From: Alan Mackenzie <acm@muc.de>
To: Tadeus Prastowo <tadeus.prastowo@unitn.it>
Cc: John Wiegley <jwiegley@gmail.com>, 28623@debbugs.gnu.org
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 [thread overview]
Message-ID: <20171104195639.GA5384@ACM> (raw)
In-Reply-To: <CAN-HRFb8SrNAX=-p8_BhcQg7Nto8GRb+6ufmirs++GeBEK_DcQ@mail.gmail.com>
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 <acm@muc.de> 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).
next prev parent reply other threads:[~2017-11-04 19:56 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-09-27 17:49 bug#28623: 27.0.50; lisp/progmodes/cc-engine.el incorrect indentation of C++14 curly-brace initializer list Tadeus Prastowo
2017-09-27 19:31 ` John Wiegley
2017-10-04 18:15 ` Alan Mackenzie
2017-10-06 2:59 ` Tadeus Prastowo
2017-10-11 20:32 ` Alan Mackenzie
2017-10-12 11:38 ` Tadeus Prastowo
2017-11-04 19:56 ` Alan Mackenzie [this message]
2017-11-06 22:46 ` Tadeus Prastowo
2017-11-08 19:23 ` Alan Mackenzie
[not found] ` <20171108192358.GA4582@ACM>
2017-11-09 9:27 ` Tadeus Prastowo
2017-11-09 18:53 ` Alan Mackenzie
[not found] ` <20171109185354.GA15085@ACM>
2017-11-10 12:07 ` Tadeus Prastowo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20171104195639.GA5384@ACM \
--to=acm@muc.de \
--cc=28623@debbugs.gnu.org \
--cc=jwiegley@gmail.com \
--cc=tadeus.prastowo@unitn.it \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.