Subject: bug#22079: CC Mode 5.33 (C++/l); C++ cache inconsistency

From: Alan Mackenzie <[email-masked]>
Date: Thu, 3 Dec 2015 10:20:07 +0000

Hello, Michael.

Thanks for another bug report.

On Wed, Dec 02, 2015 at 11:28:00PM -0500, Michael Welsh Duggan wrote:
> Steps to reproduce:

> Using the attached traits.hpp file:

> emacs -Q traits.hpp
> M-x c-toggle-parse-state-debug
> M->

> In *Messages* I find:

> c-parse-state inconsistency at 4541: using cache: (4451 (2110 . 4210)), from scratch: (4451 (2110 . 4210) 1868 (123 . 1830))
> Old state:
> (setq c-state-cache ’((4451 . 5298))  c-state-cache-good-pos 5298  c-state-nonlit-pos-cache ’(3001)  c-state-nonlit-pos-cache-limit 3001  c-state-semi-nonlit-pos-cache ’(3001)  c-state-semi-nonlit-pos-cache-limit 3001  c-state-brace-pair-desert nil  c-state-point-min 1  c-state-point-min-lit-type nil  c-state-point-min-lit-start nil  c-state-min-scan-pos 1  c-state-old-cpp-beg (copy-marker 5325)  c-state-old-cpp-end (copy-marker 5351)  c-parse-state-point 5325)
> c-parse-state inconsistency at 4661: using cache: (4660 4451 (2110 . 4210)), from scratch: (4660 4451 (2110 . 4210) 1868 (123 . 1830))
> Old state:
> (setq c-state-cache ’(4451 (2110 . 4210))  c-state-cache-good-pos 4452  c-state-nonlit-pos-cache ’(3001)  c-state-nonlit-pos-cache-limit 3001  c-state-semi-nonlit-pos-cache ’(3001)  c-state-semi-nonlit-pos-cache-limit 3001  c-state-brace-pair-desert nil  c-state-point-min 1  c-state-point-min-lit-type nil  c-state-point-min-lit-start nil  c-state-min-scan-pos 1  c-state-old-cpp-beg nil  c-state-old-cpp-end nil  c-parse-state-point 4541)

[ .... ]

I see you are using a relatively recent snapshot of the savannah master
or emacs-25 branch (from ~26th November).

The cause of the problem is not hard to track down.  On 11th November, I
committed a fix "CC Mode: Respect users' settings of
open-paren-in-column-0-is-defun-start.", which does precisely what it
says.  Previously, I had bound open-paren-in-column-0-is-defun-start to
nil around certain primitive calls for the sake of accurate scanning.

The problem with binding o-p-i-c-0-i-d-s to nil is that it makes CC Mode
very slow, particularly in big files, where continually scanning from
the beginning of the file is sub-optimal.

In the scenario you documented, we have ....

> namespace std {                                    <=============== B
> 
> static_assert(ipfix::traits::is_same<uint8_t, unsigned char>,
>               "Assumption that uint8_t is unsigned char is false");
> 
> template<>
> struct char_traits<ipfix::traits::enable_if<
>     ipfix::traits::is_signed<char>, unsigned char>>
> {                                                  <=============== A
>     typedef unsigned char                 char_type;
>     typedef char_traits<char>::int_type   int_type;
>     typedef char_traits<char>::off_type   off_type;
>     typedef char_traits<char>::pos_type   pos_type;
>     typedef char_traits<char>::state_type state_type;

[ .... ]

The actual top level (I think) is the brace at B.  CC Mode has, however,
taken the brace at A (in column 0) to be a top level brace.

This is a difficult problem to resolve satisfactorally, in general.
What you could do is set open-paren-etc. to nil, or even set it to nil
buffer locally for some files.  When I tried this on traits.hpp, it
scanned without any parse state inconsistencies.

> Emacs  : GNU Emacs 25.1.50.1 (x86_64-pc-linux-gnu, X toolkit)
>  of 2015-11-26
> Package: CC Mode 5.33 (C++/l)
> Buffer Style: SiLK
> c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-string-delim gen-comment-delim syntax-properties 1-bit)

[ full CC Mode dump snipped, but appreciated. ]

> -- 
> Michael Welsh Duggan
> ([email-masked])

-- 
Alan Mackenzie (Nuremberg, Germany).