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: Sun, 10 Nov 2019 10:48:11 +0000 Message-ID: <20191110104811.GA6614@ACM> References: <20191027153956.GB27906@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="23007"; 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 Sun Nov 10 11:49:15 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 1iTkmQ-0005qO-W9 for geb-bug-gnu-emacs@m.gmane.org; Sun, 10 Nov 2019 11:49:15 +0100 Original-Received: from localhost ([::1]:42350 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iTkmP-0006Y0-6l for geb-bug-gnu-emacs@m.gmane.org; Sun, 10 Nov 2019 05:49:13 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:55691) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1iTkmI-0006Xp-4x for bug-gnu-emacs@gnu.org; Sun, 10 Nov 2019 05:49:07 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1iTkmG-0008Il-IA for bug-gnu-emacs@gnu.org; Sun, 10 Nov 2019 05:49:06 -0500 Original-Received: from debbugs.gnu.org ([209.51.188.43]:41823) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1iTkmE-0008Gn-6C; Sun, 10 Nov 2019 05:49:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1iTkmE-0001cX-2s; Sun, 10 Nov 2019 05:49: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: Sun, 10 Nov 2019 10:49: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.15733829026184 (code B ref 37910); Sun, 10 Nov 2019 10:49:02 +0000 Original-Received: (at 37910) by debbugs.gnu.org; 10 Nov 2019 10:48:22 +0000 Original-Received: from localhost ([127.0.0.1]:50644 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1iTklZ-0001bg-L8 for submit@debbugs.gnu.org; Sun, 10 Nov 2019 05:48:22 -0500 Original-Received: from colin.muc.de ([193.149.48.1]:48832 helo=mail.muc.de) by debbugs.gnu.org with smtp (Exim 4.84_2) (envelope-from ) id 1iTklV-0001bV-JL for 37910@debbugs.gnu.org; Sun, 10 Nov 2019 05:48:20 -0500 Original-Received: (qmail 4371 invoked by uid 3782); 10 Nov 2019 10:48:15 -0000 Original-Received: from acm.muc.de (p2E5D5FC7.dip0.t-ipconnect.de [46.93.95.199]) by colin.muc.de (tmda-ofmipd) with ESMTP; Sun, 10 Nov 2019 11:48:14 +0100 Original-Received: (qmail 6800 invoked by uid 1000); 10 Nov 2019 10:48:11 -0000 Content-Disposition: inline In-Reply-To: <20191027153956.GB27906@ACM> 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:171378 Archived-At: Hello, Eric. Now for a top-post. ;-) I think I may have found the cause of the bug. It may have been caused by overwriting lisp list structure, rather than creating new (parallel) list structures - a sort of corruption. See below for a fuller explanation. This hypothesis is entirely consistent with the observed result (spurious topmost-intro's). Would you please apply the patch below and byte-compile the result. It suffices just to compile cc-engine.el. (If you want any help with applying the patch or byte compiling, feel free to send me private email.) Then please try out the patched CC Mode for however long it has taken, in the past, to see the sort of bug you reported, and then somewhat longer. If the bug fails to show itself, we may well have fixed it. Please let me know how things are going. ############## Optional section. An explanation ####################### One of the caches CC Mode uses, "c-state-cache", keeps track of the nested brace structure. It is (re)calculated on calling the lisp function c-parse-state. In essence, it records the position of each enclosing brace in a list, the most nested first. So if we had the following C++ structure: { // 1 ...... { // 2 ...... { // 3 ...... , and was at the marked position, our c-state-cache would be the list of the three brace positions (P3 P2 P1). One of its uses is determining if some point is at the top level or not. If the c-state-cache list for that point is empty, it is at the top level. As point moves through the buffer, and c-parse-state is called from somewhere else, c-state-cache is "altered" in a highly optimised fashion. This avoids having to scan large portions of the buffer too often, to determine the brace structure. The nature of this "altering" is what is causing the problem. When the buffer is narrowed, say beginning with the brace 2, calling c-parse-state now has to return (P3 P2), because the brace 1 is now outside the visible portion. The suspected bug cause is the way (P3 P2 P1) is changed to (P3 P2) on this narrowing. Up to now the list structure itself has been changed, rather than making a copy of the structure. So, what may have been happening is that CC Mode is looping through the c-state-cache to determine whether point is at top level. (Being directly inside a class or namespace, etc., counts as "top level"). If point is inside brace 1, the loop will try to determine that P1 is not a class, etc., and return "not at top level". However, if c-parse-state had been called with the above narrowing, c-state-cache is now (P3 P2), point appears to be outside every brace, and the loop spuriously returns "at top level". This is what I think has been happening. When the code wrongly reports "at top level", we get the unwanted topmost-intro analyses. The solution to this is when the buffer is narrowed and we call c-parse-state, we make a COPY of the c-state-cache list, leaving the original unmolested for its original owner. This is what the patch does. ############## End of optional section. ################################ Here is the patch. It should work in Emacs-26.3, even though the line numbers are now a bit different: diff -r 2783baa48d44 cc-engine.el --- a/cc-engine.el Fri Oct 25 20:00:14 2019 +0000 +++ b/cc-engine.el Sun Nov 10 10:30:17 2019 +0000 @@ -3690,7 +3690,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 +3799,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 +4005,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 +4142,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 {. On Sun, Oct 27, 2019 at 15:39:56 +0000, Alan Mackenzie wrote: > Hello, Eric. > On Thu, Oct 24, 2019 at 12:06:18 -0700, Eric Scrivner wrote: > > This seems related to (if not the same as) bug #5490. > > - This happens randomly and then randomly stops happening (cache expiry > > maybe?) > > - M-x revert-buffer does not fix. > Thanks for taking the trouble to report this bug, and thanks even more > for including so much information. > > Here's a snippet from the buffer at the time this happen, as you can see > > there seems to be a region until the end where everything becomes > > topmost-intro: > > } // ((block-close 18328)) > > // ((statement 9560)) > > SDL_DestroyWindow(Window); // ((statement 9560)) > > } // ((block-close 9490)) > > else // ((else-clause 9466)) > > { // > > ((substatement-open 18464)) > > PlatformLog("Failed to create window: %s", SDL_GetError()); // > > ((statement-block-intro 18473)) > > } // ((block-close 18473)) > > // ((topmost-intro 18576)) > > // ((topmost-intro 18576)) > > SDL_Quit(); // ((topmost-intro 18541)) > > } // ((topmost-intro 18548)) > > else // ((else-clause 9188)) > > { // ((substatement-open 18845)) > > PlatformLog("Failed to initialize SDL: %s", SDL_GetError()); // > > ((statement-block-intro 18901))((statement-block-intro 18724)) > > } // > > ((block-close 18901)) > > // ((topmost-intro 19093)) > > return EXIT_SUCCESS; // ((topmost-intro 19093)) > > } // ((topmost-intro 19242)) > At the moment, all I can do is acknowledge receipt of your report. It's > obviously not an easy bug to diagnose. > I can see two ways of making progress: (i) Inspecting > c-guess-basic-syntax, the function which analyses code and produces > (amongs other things) all these topmost-intro's. It is essentially a > large cond form (Lisp's equivalent of a switch), and the single place > which produces topmost-intro comes fairly early on in this cond form; > (ii) Determine what aspects of a buffer do not get reinitialised after > evaluating M-x revert-buffer. That could provide some clue. > [ CC Mode config dump acknowledged with thanks, but snipped ] > Just one thing. If you haven't already done so, could you make a backup > copy of a buffer which triggers the bug, just in case after some future > edit it no longer does so. Thanks! -- Alan Mackenzie (Nuremberg, Germany).