From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED.blaine.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.bugs Subject: bug#37910: CC Mode 5.33.2 (C++//l); CC-mode inconsistently indents everything as topmost-intro after a while Date: Wed, 13 Nov 2019 18:38:58 +0000 Message-ID: <20191113183858.GA4942@ACM> References: <20191027153956.GB27906@ACM> <20191110104811.GA6614@ACM> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: blaine.gmane.org; posting-host="blaine.gmane.org:195.159.176.226"; logging-data="199766"; mail-complaints-to="usenet@blaine.gmane.org" User-Agent: Mutt/1.10.1 (2018-07-13) Cc: 37910@debbugs.gnu.org To: Eric Scrivner Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed Nov 13 19:40:13 2019 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([209.51.188.17]) by blaine.gmane.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.89) (envelope-from ) id 1iUxYq-000pkb-TR for geb-bug-gnu-emacs@m.gmane.org; Wed, 13 Nov 2019 19:40:13 +0100 Original-Received: from localhost ([::1]:49866 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iUxYp-0003DW-On for geb-bug-gnu-emacs@m.gmane.org; Wed, 13 Nov 2019 13:40:11 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:38154) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iUxYi-0003D9-Eg for bug-gnu-emacs@gnu.org; Wed, 13 Nov 2019 13:40:05 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iUxYg-0004Yg-ST for bug-gnu-emacs@gnu.org; Wed, 13 Nov 2019 13:40:04 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:51332) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iUxYg-0004YW-Nf; Wed, 13 Nov 2019 13:40:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1iUxYg-0003NI-Ft; Wed, 13 Nov 2019 13:40:02 -0500 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: Wed, 13 Nov 2019 18:40:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 37910 X-GNU-PR-Package: emacs,cc-mode Original-Received: via spool by 37910-submit@debbugs.gnu.org id=B37910.157367035012895 (code B ref 37910); Wed, 13 Nov 2019 18:40:02 +0000 Original-Received: (at 37910) by debbugs.gnu.org; 13 Nov 2019 18:39:10 +0000 Original-Received: from localhost ([127.0.0.1]:60153 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1iUxXp-0003Lu-IN for submit@debbugs.gnu.org; Wed, 13 Nov 2019 13:39:09 -0500 Original-Received: from colin.muc.de ([193.149.48.1]:10886 helo=mail.muc.de) by debbugs.gnu.org with smtp (Exim 4.84_2) (envelope-from ) id 1iUxXi-0003LO-8h for 37910@debbugs.gnu.org; Wed, 13 Nov 2019 13:39:04 -0500 Original-Received: (qmail 80839 invoked by uid 3782); 13 Nov 2019 18:39:00 -0000 Original-Received: from acm.muc.de (p4FE1584D.dip0.t-ipconnect.de [79.225.88.77]) by colin.muc.de (tmda-ofmipd) with ESMTP; Wed, 13 Nov 2019 19:38:58 +0100 Original-Received: (qmail 5045 invoked by uid 1000); 13 Nov 2019 18:38:58 -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: 209.51.188.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:171500 Archived-At: Hello again, Eric. On Sun, Nov 10, 2019 at 09:47:35 -0800, Eric Scrivner wrote: > I've applied the patch and run emacs with it. Unfortunately, it doesn't > seem to solve the issue. One the bright side, I believe I had buffers which > can reliably reproduce the issue (at least locally). I've copied one such > file below. The issue can be reproduced by simply going to the end of > `main` and attempting to indent the `SQL_Quit()` statement. At first it > attempts to overindent the line as `statement-cont`, then if I go up and > attempt to indent the `PlatformLog` in the else statement then return to > the SDL_Quit and indent it, it has become `topmost-intro`. Apologies for > the long length of the file, but hopefully it can help with reproduction: I've had a look at the bug and there was a non-sensical function in CC Mode fouling things up. In the patch below, I've rewritten this function. Could I ask you please to apply the new patch (to the original Emacs 26.3 version off cc-engine.el), byte-compile it and test it. Then please let me know how it goes. However .... I would strongly advise you to set the Emacs variable open-parens-in-column-0-is-defun-start to nil. Whether for C++ Mode in general (in a hook function), for this one file in particular (in a Local Variables: section at the end of the file), or globally. With open-p......-start left at its default of t, Emacs will search backward for the beginning of a function by searching for an open paren/brace/bracket at column 0. It deems the found paren/brace/bracket the start of a function even if that p/b/b is inside a string or function. This seems likely to happen in your test file, where you've got such braces at column 0 inside two raw strings. This variable codifies a difficult dilemma for Emacs. Without the paren in column 0 heuristic, the beginning of function search would have to scan to the beginning of the buffer every time which is somewhat slow (perhaps less slow now on modern PCs, but still slow). With the heuristic, analysis problems happen when there are braces at col 0 which aren't BO functions (e.g., in C++ Mode when things inside a namespace start at column 0, a popular convention). For a time, o-p-i-c-0-i-d-s was spiked to nil by CC Mode, but this led to complaints of slowness. Anyhow, here's the improved patch. I look forward to hearing back from you. Thanks for all the time you've spent on this bug. diff -r 2783baa48d44 cc-engine.el --- a/cc-engine.el Fri Oct 25 20:00:14 2019 +0000 +++ b/cc-engine.el Wed Nov 13 18:13:11 2019 +0000 @@ -3371,19 +3371,35 @@ (or (car (c-state-literal-at pos)) pos)) -(defsubst c-state-cache-non-literal-place (pos state) - ;; Return a position outside of a string/comment/macro at or before POS. - ;; STATE is the parse-partial-sexp state at POS. - (let ((res (if (or (nth 3 state) ; in a string? - (and (nth 4 state) - (not (eq (nth 7 state) 'syntax-table)))) ; in a comment? - (nth 8 state) - pos))) +(defun c-state-cache-lower-good-pos (here pos state) + ;; Return a good pos (in the sense of `c-state-cache-good-pos') at the + ;; lowest[*] position between POS and HERE which is syntactically equivalent + ;; to HERE. This position may be HERE itself. POS is before HERE in the + ;; buffer. + ;; [*] We don't actually always determine this exact position, since this + ;; would require a disproportionate amount of work, given that this function + ;; deals only with a corner condition, and POS and HERE are typically on + ;; adjacent lines. We actually return either POS, when POS is a good + ;; position, HERE otherwise. Exceptionally, when POS is in a comment, but + ;; HERE not, we can return the position of the end of the comment. + (let (s) (save-excursion - (goto-char res) - (if (c-beginning-of-macro) - (point) - res)))) + (goto-char pos) + (when (nth 8 state) ; POS in a comment or string. Move out of it. + (setq s (parse-partial-sexp pos here nil nil state 'syntax-table)) + (when (< (point) here) + (setq pos (point) + state s))) + (if (eq (point) here) ; HERE is in the same literal as POS + pos + (setq s (parse-partial-sexp pos here (1+ (car state)) nil state nil)) + (cond + ((> (car s) (car state)) ; Moved into a paren between POS and HERE + here) + ((not (eq (nth 6 s) (car state))) ; Moved out of a paren between POS + ; and HERE + here) + (t pos)))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Stuff to do with point-min, and coping with any literal there. @@ -3690,7 +3706,13 @@ ; brace pair. (setq c-state-cache nil c-state-cache-good-pos c-state-min-scan-pos) - (setcdr ptr nil) + ;; Do not alter the original `c-state-cache' structure, since there + ;; may be a loop suspended which is looping through that structure. + ;; This may have been the cause of bug #37910. + (let ((cdr-ptr (cdr ptr))) + (setcdr ptr nil) + (setq c-state-cache (copy-sequence c-state-cache)) + (setcdr ptr cdr-ptr)) (setq c-state-cache-good-pos (1+ (c-state-cache-top-lparen)))) ))) @@ -3793,11 +3815,12 @@ (setq new-cons (cons bra (1+ ce))) (cond ((consp (car c-state-cache)) - (setcar c-state-cache new-cons)) + (setq c-state-cache (cons new-cons (cdr c-state-cache)))) ((and (numberp (car c-state-cache)) ; probably never happens (< ce (car c-state-cache))) - (setcdr c-state-cache - (cons new-cons (cdr c-state-cache)))) + (setq c-state-cache + (cons (car c-state-cache) + (cons new-cons (cdr c-state-cache))))) (t (setq c-state-cache (cons new-cons c-state-cache))))) ;; We haven't found a brace pair. Record this in the cache. @@ -3998,7 +4021,7 @@ (when (and c-state-cache (consp (car c-state-cache)) (> (cdar c-state-cache) upper-lim)) - (setcar c-state-cache (caar c-state-cache)) + (setq c-state-cache (cons (caar c-state-cache) (cdr c-state-cache))) (setq scan-back-pos (car c-state-cache) cons-separated t)) @@ -4135,7 +4158,7 @@ ;; knowledge of what's inside these braces, we have no alternative but ;; to direct the caller to scan the buffer from the opening brace. (setq pos (caar c-state-cache)) - (setcar c-state-cache pos) + (setq c-state-cache (cons pos (cdr c-state-cache))) (list (1+ pos) pos t)) ; return value. We've just converted a brace pair ; entry into a { entry, so the caller needs to ; search for a brace pair before the {. @@ -4385,7 +4408,7 @@ (setq c-state-cache-good-pos (if (and bopl-state (< good-pos (- here c-state-cache-too-far))) - (c-state-cache-non-literal-place here-bopl bopl-state) + (c-state-cache-lower-good-pos here here-bopl bopl-state) good-pos))) ((eq strategy 'backward) -- Alan Mackenzie (Nuremberg, Germany).