GNU bug report logs - #58883
CC Mode 5.35.1 (C/*l); Incorrect fontification of X function

Previous Next

Package: cc-mode;

Reported by: Po Lu <luangruo <at> yahoo.com>

Date: Sun, 30 Oct 2022 01:24:01 UTC

Severity: normal

Done: Alan Mackenzie <acm <at> muc.de>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 58883 in the body.
You can then email your comments to 58883 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Sun, 30 Oct 2022 01:24:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Po Lu <luangruo <at> yahoo.com>:
New bug report received and forwarded. Copy sent to bug-cc-mode <at> gnu.org. (Sun, 30 Oct 2022 01:24:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Po Lu <luangruo <at> yahoo.com>
To: bug-gnu-emacs <at> gnu.org
Subject: CC Mode 5.35.1 (C/*l); Incorrect fontification of X function
Date: Sun, 30 Oct 2022 09:22:45 +0800
Package: cc-mode

In the following Xlib function:

Bool XCheckIfEvent (
	register Display *dpy,
	register XEvent *event,		/* XEvent to be filled in. */
	Bool (*predicate)(
			  Display*			/* display */,
			  XEvent*			/* event */,
			  char*				/* arg */
			  ),		/* function to call */
	char *arg)
{
	register _XQEvent *prev, *qelt;
	unsigned long qe_serial = 0;
	int n;			/* time through count */

        LockDisplay(dpy);
	prev = NULL;
	for (n = 3; --n >= 0;) {
	    for (qelt = prev ? prev->next : dpy->head;
		 qelt;
		 prev = qelt, qelt = qelt->next) {
		if(qelt->qserial_num > qe_serial
		   && (*predicate)(dpy, &qelt->event, arg)) {
		    *event = qelt->event;
		    _XDeq(dpy, prev, qelt);
		    _XStoreEventCookie(dpy, event);
		    UnlockDisplay(dpy);
		    return True;
		}
	    }
	    if (prev)
		qe_serial = prev->qserial_num;
	    switch (n) {
	      case 2:
		_XEventsQueued(dpy, QueuedAfterReading);
		break;
	      case 1:
		_XFlush(dpy);
		break;
	    }
	    if (prev && prev->qserial_num != qe_serial)
		/* another thread has snatched this event */
		prev = NULL;
	}
	UnlockDisplay(dpy);
	return False;
}

Bool XCheckIfEvent (
	register Display *dpy,
	register XEvent *event,		/* XEvent to be filled in. */
	Bool (*predicate)(
			  Display*			/* display */,
			  XEvent*			/* event */,
			  char*				/* arg */
			  ),		/* function to call */
	char *arg)
{
	register _XQEvent *prev, *qelt;
	unsigned long qe_serial = 0;
	int n;			/* time through count */

        LockDisplay(dpy);
	prev = NULL;
	for (n = 3; --n >= 0;) {
	    for (qelt = prev ? prev->next : dpy->head;
		 qelt;
		 prev = qelt, qelt = qelt->next) {
		if(qelt->qserial_num > qe_serial
		   && (*predicate)(dpy, &qelt->event, arg)) {
		    *event = qelt->event;
		    _XDeq(dpy, prev, qelt);
		    _XStoreEventCookie(dpy, event);
		    UnlockDisplay(dpy);
		    return True;
		}
	    }
	    if (prev)
		qe_serial = prev->qserial_num;
	    switch (n) {
	      case 2:
		_XEventsQueued(dpy, QueuedAfterReading);
		break;
	      case 1:
		_XFlush(dpy);
		break;
	    }
	    if (prev && prev->qserial_num != qe_serial)
		/* another thread has snatched this event */
		prev = NULL;
	}
	UnlockDisplay(dpy);
	return False;
}
"Display" and "XEvent" are not fontified as types, inside both the
function prototype and that of the predcate argument.

"_XQEvent" also fails to be fontified as a type.

Emacs  : GNU Emacs 29.0.50 (build 1, x86_64-pc-linux-gnu)
 of 2022-10-29
Package: CC Mode 5.35.1 (C/*l)
Buffer Style: gnu
c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-string-delim gen-comment-delim syntax-properties category-properties 1-bit)

current state:
==============
(setq
 c-basic-offset 2
 c-comment-only-line-offset '(0 . 0)
 c-indent-comment-alist '((anchored-comment column . 0) (end-block space . 1) (cpp-end-block space . 2))
 c-indent-comments-syntactically-p nil
 c-block-comment-prefix ""
 c-comment-prefix-regexp '((pike-mode . "//+!?\\|\\**") (awk-mode . "#+") (other . "//+\\|\\**"))
 c-doc-comment-style '((java-mode . javadoc) (pike-mode . autodoc) (c-mode . gtkdoc) (c++-mode . gtkdoc))
 c-cleanup-list '(scope-operator)
 c-hanging-braces-alist '((substatement-open before after) (arglist-cont-nonempty))
 c-hanging-colons-alist nil
 c-hanging-semi&comma-criteria '(c-semi&comma-inside-parenlist)
 c-backslash-column 48
 c-backslash-max-column 72
 c-special-indent-hook '(t c-gnu-impose-minimum)
 c-label-minimum-indentation 1
 c-offsets-alist '((inexpr-class . +)
		   (inexpr-statement . +)
		   (lambda-intro-cont . +)
		   (inlambda . 0)
		   (template-args-cont c-lineup-template-args +)
		   (incomposition . +)
		   (inmodule . +)
		   (innamespace . +)
		   (inextern-lang . +)
		   (composition-close . 0)
		   (module-close . 0)
		   (namespace-close . 0)
		   (extern-lang-close . 0)
		   (composition-open . 0)
		   (module-open . 0)
		   (namespace-open . 0)
		   (extern-lang-open . 0)
		   (objc-method-call-cont c-lineup-ObjC-method-call-colons c-lineup-ObjC-method-call +)
		   (objc-method-args-cont . c-lineup-ObjC-method-args)
		   (objc-method-intro . [0])
		   (friend . 0)
		   (cpp-define-intro c-lineup-cpp-define +)
		   (cpp-macro-cont . +)
		   (cpp-macro . [0])
		   (inclass . +)
		   (stream-op . c-lineup-streamop)
		   (arglist-cont-nonempty c-lineup-gcc-asm-reg c-lineup-arglist)
		   (arglist-cont c-lineup-gcc-asm-reg 0)
		   (comment-intro c-lineup-knr-region-comment c-lineup-comment)
		   (catch-clause . 0)
		   (else-clause . 0)
		   (do-while-closure . 0)
		   (access-label . -)
		   (case-label . 0)
		   (substatement . +)
		   (statement-case-intro . +)
		   (statement . 0)
		   (brace-entry-open . 0)
		   (brace-list-entry . 0)
		   (brace-list-close . 0)
		   (block-close . 0)
		   (block-open . 0)
		   (inher-cont . c-lineup-multi-inher)
		   (inher-intro . +)
		   (member-init-cont . c-lineup-multi-inher)
		   (member-init-intro . +)
		   (annotation-var-cont . +)
		   (annotation-top-cont . 0)
		   (topmost-intro . 0)
		   (knr-argdecl . 0)
		   (func-decl-cont . +)
		   (inline-close . 0)
		   (class-close . 0)
		   (class-open . 0)
		   (defun-block-intro . +)
		   (defun-close . 0)
		   (defun-open . 0)
		   (c . c-lineup-C-comments)
		   (string . c-lineup-dont-change)
		   (topmost-intro-cont first c-lineup-topmost-intro-cont c-lineup-gnu-DEFUN-intro-cont)
		   (brace-list-intro first c-lineup-2nd-brace-entry-in-arglist c-lineup-class-decl-init-+ +)
		   (brace-list-open . +)
		   (inline-open . 0)
		   (arglist-close . c-lineup-arglist)
		   (arglist-intro . c-lineup-arglist-intro-after-paren)
		   (statement-cont . +)
		   (statement-case-open . +)
		   (label . 0)
		   (substatement-label . 0)
		   (substatement-open . +)
		   (knr-argdecl-intro . 5)
		   (statement-block-intro . +)
		   )
 c-buffer-is-cc-mode 'c-mode
 c-tab-always-indent t
 c-syntactic-indentation t
 c-syntactic-indentation-in-macros t
 c-ignore-auto-fill '(string cpp code)
 c-auto-align-backslashes t
 c-backspace-function 'backward-delete-char-untabify
 c-delete-function 'delete-char
 c-electric-pound-behavior nil
 c-default-style '((java-mode . "java") (awk-mode . "awk") (other . "gnu"))
 c-enable-xemacs-performance-kludge-p nil
 c-old-style-variable-behavior nil
 defun-prompt-regexp nil
 tab-width 8
 comment-column 32
 parse-sexp-ignore-comments t
 parse-sexp-lookup-properties t
 auto-fill-function nil
 comment-multi-line t
 comment-start-skip "\\(?://+\\|/\\*+\\)\\s *"
 fill-prefix nil
 fill-column 70
 paragraph-start "[ 	]*\\(//+\\|\\**\\)[ 	]*$\\|^\f"
 adaptive-fill-mode t
 adaptive-fill-regexp "[ 	]*\\(//+\\|\\**\\)[ 	]*\\([ 	]*\\([-–!|#%;>*·•‣⁃◦]+[ 	]*\\)*\\)"
 )




Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Sun, 30 Oct 2022 14:06:02 GMT) Full text and rfc822 format available.

Message #8 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Po Lu <luangruo <at> yahoo.com>
Cc: 58883 <at> debbugs.gnu.org, acm <at> muc.de
Subject: Re: bug#58883: CC Mode 5.35.1 (C/*l); Incorrect fontification of X
 function
Date: Sun, 30 Oct 2022 14:05:15 +0000
[Message part 1 (text/plain, inline)]
Hello, Po.

Thanks for yet another bug report!

On Sun, Oct 30, 2022 at 09:22:45 +0800, Po Lu via CC-Mode-help wrote:
> Package: cc-mode

> In the following Xlib function:

> Bool XCheckIfEvent (
> 	register Display *dpy,
> 	register XEvent *event,		/* XEvent to be filled in. */
> 	Bool (*predicate)(
> 			  Display*			/* display */,
> 			  XEvent*			/* event */,
> 			  char*				/* arg */
> 			  ),		/* function to call */
> 	char *arg)
> {
> 	register _XQEvent *prev, *qelt;
> 	unsigned long qe_serial = 0;
> 	int n;			/* time through count */

>         LockDisplay(dpy);
> 	prev = NULL;
> 	for (n = 3; --n >= 0;) {
> 	    for (qelt = prev ? prev->next : dpy->head;
> 		 qelt;
> 		 prev = qelt, qelt = qelt->next) {
> 		if(qelt->qserial_num > qe_serial
> 		   && (*predicate)(dpy, &qelt->event, arg)) {
> 		    *event = qelt->event;
> 		    _XDeq(dpy, prev, qelt);
> 		    _XStoreEventCookie(dpy, event);
> 		    UnlockDisplay(dpy);
> 		    return True;
> 		}
> 	    }
> 	    if (prev)
> 		qe_serial = prev->qserial_num;
> 	    switch (n) {
> 	      case 2:
> 		_XEventsQueued(dpy, QueuedAfterReading);
> 		break;
> 	      case 1:
> 		_XFlush(dpy);
> 		break;
> 	    }
> 	    if (prev && prev->qserial_num != qe_serial)
> 		/* another thread has snatched this event */
> 		prev = NULL;
> 	}
> 	UnlockDisplay(dpy);
> 	return False;
> }

> "Display" and "XEvent" are not fontified as types, inside both the
> function prototype and that of the predcate argument.

> "_XQEvent" also fails to be fontified as a type.

Yes.  This was an unwanted consequence of the fix to bug #58537 two
weeks ago.  There, things were being fontified as types and, at the same
time, being wrongly added to c-found-types.  That fix prevented Display,
etc., from being fontified.

The attached patch allows the fontification of these types, but doesn't
add them to c-found-types.  Would you please do the usual with the
patch, and let me know if there are any problems with it.  Thanks!

> Emacs  : GNU Emacs 29.0.50 (build 1, x86_64-pc-linux-gnu)
>  of 2022-10-29
> Package: CC Mode 5.35.1 (C/*l)
> Buffer Style: gnu
> c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-string-delim gen-comment-delim syntax-properties category-properties 1-bit)

[ .... ]

-- 
Alan Mackenzie (Nuremberg, Germany).

[diff.20221030.diff (text/plain, attachment)]

Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Tue, 08 Nov 2022 09:39:01 GMT) Full text and rfc822 format available.

Message #11 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Po Lu <luangruo <at> yahoo.com>
Cc: 58883 <at> debbugs.gnu.org, acm <at> muc.de
Subject: bug#58883 [Was: bug#59032: CC Mode 5.35.1 (C/*l); Incorrect
 fontification of `subsurface' during typing]
Date: Tue, 8 Nov 2022 09:37:53 +0000
[Message part 1 (text/plain, inline)]
Hello, Po.

On Tue, Nov 08, 2022 at 08:25:31 +0800, Po Lu wrote:
> Alan Mackenzie <acm <at> muc.de> writes:

[ .... ]

> > I have a fix for this, I think, but it overlaps with an earlier fix to
> > bug #58883.  I sent you a patch on Sunday 2022-10-30 for this earlier
> > bug.  Did you get this patch?  If so, have you any reaction to it?

> I think it got lost in the bulk mail folder (but I can't find it there
> either, so maybe a mailer screwup?)

> So would you please send it again?  TIA.

OK, here it is!

Thanks!

[ I've set the Subject: to bug#58883, and the Cc: to
58883 <at> debbugs.gnu.org. ]

-- 
Alan Mackenzie (Nuremberg, Germany).

[diff.20221030.diff (text/plain, attachment)]

Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Tue, 08 Nov 2022 10:03:01 GMT) Full text and rfc822 format available.

Message #14 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Po Lu <luangruo <at> yahoo.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 58883 <at> debbugs.gnu.org
Subject: Re: bug#58883 [
Date: Tue, 08 Nov 2022 18:02:12 +0800
Alan Mackenzie <acm <at> muc.de> writes:

> Hello, Po.
>
> On Tue, Nov 08, 2022 at 08:25:31 +0800, Po Lu wrote:
>> Alan Mackenzie <acm <at> muc.de> writes:
>
> [ .... ]
>
>> > I have a fix for this, I think, but it overlaps with an earlier fix to
>> > bug #58883.  I sent you a patch on Sunday 2022-10-30 for this earlier
>> > bug.  Did you get this patch?  If so, have you any reaction to it?
>
>> I think it got lost in the bulk mail folder (but I can't find it there
>> either, so maybe a mailer screwup?)
>
>> So would you please send it again?  TIA.
>
> OK, here it is!
>
> Thanks!
>
> [ I've set the Subject: to bug#58883, and the Cc: to
> 58883 <at> debbugs.gnu.org. ]

That seems to solve this problem (bug#58883) for me.

However, I'm beginning to see a general pattern here.  When the mistaken
type classification is corrected, bad fortification above the last edit
is not removed.  Shouldn't that be fixed also?

Thanks.




Reply sent to Alan Mackenzie <acm <at> muc.de>:
You have taken responsibility. (Tue, 08 Nov 2022 12:22:02 GMT) Full text and rfc822 format available.

Notification sent to Po Lu <luangruo <at> yahoo.com>:
bug acknowledged by developer. (Tue, 08 Nov 2022 12:22:02 GMT) Full text and rfc822 format available.

Message #19 received at 58883-done <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Po Lu <luangruo <at> yahoo.com>
Cc: acm <at> muc.de, 58883-done <at> debbugs.gnu.org
Subject: Re: bug#58883
Date: Tue, 8 Nov 2022 12:21:02 +0000
Hello, Po.

On Tue, Nov 08, 2022 at 18:02:12 +0800, Po Lu wrote:
> Alan Mackenzie <acm <at> muc.de> writes:

> > Hello, Po.

> > On Tue, Nov 08, 2022 at 08:25:31 +0800, Po Lu wrote:
> >> Alan Mackenzie <acm <at> muc.de> writes:

> > [ .... ]

> >> > I have a fix for this, I think, but it overlaps with an earlier fix to
> >> > bug #58883.  I sent you a patch on Sunday 2022-10-30 for this earlier
> >> > bug.  Did you get this patch?  If so, have you any reaction to it?

> >> I think it got lost in the bulk mail folder (but I can't find it there
> >> either, so maybe a mailer screwup?)

> >> So would you please send it again?  TIA.

> > OK, here it is!

> > Thanks!

> > [ I've set the Subject: to bug#58883, and the Cc: to
> > 58883 <at> debbugs.gnu.org. ]

> That seems to solve this problem (bug#58883) for me.

Excellent!  I've committed the patch, and I'm closing the bug with this
post.

> However, I'm beginning to see a general pattern here.  When the mistaken
> type classification is corrected, bad fortification above the last edit
> is not removed.  Shouldn't that be fixed also?

I'm gradually fixing it.

The mechanism is that when C Mode sees what it takes to be a type, from
the context, c-forward-type returns the symbol 'maybe.

Later on in the processing, the analysis of the C code "confirms" that
this 'maybe actually is a type, and it gets promoted to 'found, and
entered into the c-found-types list.  At the same time, other occurrences
of the type throughout the buffer are fontified as types.

This mechanism is not foolproof, and goes wrong when a statement is
partially typed.  Rather than correcting the mistakenly fontified
"types", which would be more difficult, I'm concentrating on not
promoting a 'maybe type to a 'found type too enthusiasically.

The problem here is that CC Mode isn't a compiler, and doesn't do very
deep analysis on the source.  The new mode with tree sitter will likely
do much better on such troublesome sources in the future.  Sorry!

> Thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Tue, 08 Nov 2022 12:30:03 GMT) Full text and rfc822 format available.

Message #22 received at 58883-done <at> debbugs.gnu.org (full text, mbox):

From: Po Lu <luangruo <at> yahoo.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 58883-done <at> debbugs.gnu.org
Subject: Re: bug#58883
Date: Tue, 08 Nov 2022 20:29:30 +0800
Alan Mackenzie <acm <at> muc.de> writes:

> I'm gradually fixing it.

Thanks.  I hope Emacs 29 will not be released without the fix.

> The mechanism is that when C Mode sees what it takes to be a type, from
> the context, c-forward-type returns the symbol 'maybe.
>
> Later on in the processing, the analysis of the C code "confirms" that
> this 'maybe actually is a type, and it gets promoted to 'found, and
> entered into the c-found-types list.  At the same time, other occurrences
> of the type throughout the buffer are fontified as types.
>
> This mechanism is not foolproof, and goes wrong when a statement is
> partially typed.  Rather than correcting the mistakenly fontified
> "types", which would be more difficult, I'm concentrating on not
> promoting a 'maybe type to a 'found type too enthusiasically.

Right, but there are some things that simply cannot work with that
approach.  Imagine the following code being typed by the user:

foo (ptr)
     struct foobar *ptr;
{
  register struct frobar *ptr_fast;

  ptr_fast = ptr;

only for him to realize that "oops, struct frobar is not a type!" and
correct it to:

  register struct foobar *ptr_fast;

by which time it is too late, and "struct frobar" is now in
c-found-types, with all the ensuing consequences.

> The problem here is that CC Mode isn't a compiler, and doesn't do very
> deep analysis on the source.  The new mode with tree sitter will likely
> do much better on such troublesome sources in the future.  Sorry!

But it worked fine in Emacs 28...




Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Tue, 08 Nov 2022 14:33:02 GMT) Full text and rfc822 format available.

Message #25 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Po Lu <luangruo <at> yahoo.com>
Cc: 58883 <at> debbugs.gnu.org
Subject: Re: bug#58883
Date: Tue, 8 Nov 2022 14:32:01 +0000
Hello, Po.

On Tue, Nov 08, 2022 at 20:29:30 +0800, Po Lu wrote:
> Alan Mackenzie <acm <at> muc.de> writes:

> > I'm gradually fixing it.

> Thanks.  I hope Emacs 29 will not be released without the fix.

> > The mechanism is that when C Mode sees what it takes to be a type, from
> > the context, c-forward-type returns the symbol 'maybe.

> > Later on in the processing, the analysis of the C code "confirms" that
> > this 'maybe actually is a type, and it gets promoted to 'found, and
> > entered into the c-found-types list.  At the same time, other occurrences
> > of the type throughout the buffer are fontified as types.

> > This mechanism is not foolproof, and goes wrong when a statement is
> > partially typed.  Rather than correcting the mistakenly fontified
> > "types", which would be more difficult, I'm concentrating on not
> > promoting a 'maybe type to a 'found type too enthusiasically.

> Right, but there are some things that simply cannot work with that
> approach.  Imagine the following code being typed by the user:

> foo (ptr)
>      struct foobar *ptr;
> {
>   register struct frobar *ptr_fast;

>   ptr_fast = ptr;

> only for him to realize that "oops, struct frobar is not a type!" and
> correct it to:

>   register struct foobar *ptr_fast;

> by which time it is too late, and "struct frobar" is now in
> c-found-types, with all the ensuing consequences.

I don't think this happens for struct/union/enum/class/... tags anymore.
But I think it still does for other types of types.  Mostly having a
mis-typed identifier in c-found-types shouldn't annoy too much, unless
it's some other sort of identifier in the code.

> > The problem here is that CC Mode isn't a compiler, and doesn't do very
> > deep analysis on the source.  The new mode with tree sitter will likely
> > do much better on such troublesome sources in the future.  Sorry!

> But it worked fine in Emacs 28...

There were loud complaints around 18 months ago about CC Mode's
fontification being "random", together with pressure to fix it.  The
thread on emacs-devel was started by Daniel Colascione on 2021-06-03 with
subject line "cc-mode fontification feels random".  The current
compromise arose out of that thread.

As I say, I think CC Mode has pretty much reached the end of the road as
far as indentation and (particularly) fontification go.  Any fix of one
particular problem leads to other problems springing up.  I think we must
look forward to the upcoming tree-sitter new modes.  I will be trying to
break these with CC Mode's test suite and 20 years' worth of bug reports
with unusual cases in them.  ;-)

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Wed, 09 Nov 2022 00:42:02 GMT) Full text and rfc822 format available.

Message #28 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Po Lu <luangruo <at> yahoo.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 58883 <at> debbugs.gnu.org
Subject: Re: bug#58883
Date: Wed, 09 Nov 2022 08:40:48 +0800
Alan Mackenzie <acm <at> muc.de> writes:

> Hello, Po.
>
> On Tue, Nov 08, 2022 at 20:29:30 +0800, Po Lu wrote:
>> Alan Mackenzie <acm <at> muc.de> writes:
>
>> > I'm gradually fixing it.
>
>> Thanks.  I hope Emacs 29 will not be released without the fix.
>
>> > The mechanism is that when C Mode sees what it takes to be a type, from
>> > the context, c-forward-type returns the symbol 'maybe.
>
>> > Later on in the processing, the analysis of the C code "confirms" that
>> > this 'maybe actually is a type, and it gets promoted to 'found, and
>> > entered into the c-found-types list.  At the same time, other occurrences
>> > of the type throughout the buffer are fontified as types.
>
>> > This mechanism is not foolproof, and goes wrong when a statement is
>> > partially typed.  Rather than correcting the mistakenly fontified
>> > "types", which would be more difficult, I'm concentrating on not
>> > promoting a 'maybe type to a 'found type too enthusiasically.
>
>> Right, but there are some things that simply cannot work with that
>> approach.  Imagine the following code being typed by the user:
>
>> foo (ptr)
>>      struct foobar *ptr;
>> {
>>   register struct frobar *ptr_fast;
>
>>   ptr_fast = ptr;
>
>> only for him to realize that "oops, struct frobar is not a type!" and
>> correct it to:
>
>>   register struct foobar *ptr_fast;
>
>> by which time it is too late, and "struct frobar" is now in
>> c-found-types, with all the ensuing consequences.
>
> I don't think this happens for struct/union/enum/class/... tags anymore.
> But I think it still does for other types of types.  Mostly having a
> mis-typed identifier in c-found-types shouldn't annoy too much, unless
> it's some other sort of identifier in the code.

So if the typo turns from:

  register struct frobar *...

to

  register frobar *...

there will be a problem?  That's not very reassuring.

> There were loud complaints around 18 months ago about CC Mode's
> fontification being "random", together with pressure to fix it.  The
> thread on emacs-devel was started by Daniel Colascione on 2021-06-03 with
> subject line "cc-mode fontification feels random".  The current
> compromise arose out of that thread.

I suggest turning the compromise off by default.  People who care about
``random'' fontification can then turn it on, or use the new tree-sitter
modes if they can.

Misfontificiation is a much more serious problem than fontification
being ommitted for unconventional-looking types!

> As I say, I think CC Mode has pretty much reached the end of the road as
> far as indentation and (particularly) fontification go.  Any fix of one
> particular problem leads to other problems springing up.  I think we must
> look forward to the upcoming tree-sitter new modes.  I will be trying to
> break these with CC Mode's test suite and 20 years' worth of bug reports
> with unusual cases in them.  ;-)

Tree-sitter has many problems.  For one, it does not intend to support
C89 or (more importantly for me) pre-standard C.

Thanks.




Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Thu, 10 Nov 2022 14:14:01 GMT) Full text and rfc822 format available.

Message #31 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Po Lu <luangruo <at> yahoo.com>
Cc: 58883 <at> debbugs.gnu.org, acm <at> muc.de
Subject: Re: bug#58883:
Date: Thu, 10 Nov 2022 14:13:14 +0000
Hello, Po.

On Wed, Nov 09, 2022 at 08:40:48 +0800, Po Lu via CC-Mode-help wrote:
> Alan Mackenzie <acm <at> muc.de> writes:

> > On Tue, Nov 08, 2022 at 20:29:30 +0800, Po Lu wrote:
> >> Alan Mackenzie <acm <at> muc.de> writes:

> >> > I'm gradually fixing it.

> >> Thanks.  I hope Emacs 29 will not be released without the fix.

> >> > The mechanism is that when C Mode sees what it takes to be a type, from
> >> > the context, c-forward-type returns the symbol 'maybe.

> >> > Later on in the processing, the analysis of the C code "confirms" that
> >> > this 'maybe actually is a type, and it gets promoted to 'found, and
> >> > entered into the c-found-types list.  At the same time, other occurrences
> >> > of the type throughout the buffer are fontified as types.

> >> > This mechanism is not foolproof, and goes wrong when a statement is
> >> > partially typed.  Rather than correcting the mistakenly fontified
> >> > "types", which would be more difficult, I'm concentrating on not
> >> > promoting a 'maybe type to a 'found type too enthusiasically.

> >> Right, but there are some things that simply cannot work with that
> >> approach.  Imagine the following code being typed by the user:

> >> foo (ptr)
> >>      struct foobar *ptr;
> >> {
> >>   register struct frobar *ptr_fast;

> >>   ptr_fast = ptr;

> >> only for him to realize that "oops, struct frobar is not a type!" and
> >> correct it to:

> >>   register struct foobar *ptr_fast;

> >> by which time it is too late, and "struct frobar" is now in
> >> c-found-types, with all the ensuing consequences.

> > I don't think this happens for struct/union/enum/class/... tags anymore.
> > But I think it still does for other types of types.  Mostly having a
> > mis-typed identifier in c-found-types shouldn't annoy too much, unless
> > it's some other sort of identifier in the code.

> So if the typo turns from:

>   register struct frobar *...

> to

>   register frobar *...

> there will be a problem?  That's not very reassuring.

There won't usually be a problem.  There will be a superfluous entry
"frobar" in c-found-types, but that won't affect anything unless there's
an actual identifier frobar in the buffer.

> > There were loud complaints around 18 months ago about CC Mode's
> > fontification being "random", together with pressure to fix it.  The
> > thread on emacs-devel was started by Daniel Colascione on 2021-06-03 with
> > subject line "cc-mode fontification feels random".  The current
> > compromise arose out of that thread.

> I suggest turning the compromise off by default.

There is no on and off, here.  Types need to get handled somehow.  A
great portion of all types are "found types", recognised from their
context in the program and entered into c-found-types.

> People who care about ``random'' fontification can then turn it on, or
> use the new tree-sitter modes if they can.

Failing to fontify a type is just as random as wrongly fontifying
something as a type.

> Misfontificiation is a much more serious problem than fontification
> being ommitted for unconventional-looking types!

Failing to fontify a type is also misfontification.  The consensus from
that emacs-devel thread ~18 months ago was that it is not in order to
fontify randomly.

What do you think of a facility that would allow a user to remove a
specific type from c-found-types?  It would work by putting point over
the offending identifier, and entering something like C-c C-f?

Also, are you still seeing these misfontifications in practice?  The lack
of bug reports over the last few days suggests either the bugs aren't
happening (much?) any more, or you've just got tired of submitting bug
reports.  ;-)

> > As I say, I think CC Mode has pretty much reached the end of the road as
> > far as indentation and (particularly) fontification go.  Any fix of one
> > particular problem leads to other problems springing up.  I think we must
> > look forward to the upcoming tree-sitter new modes.  I will be trying to
> > break these with CC Mode's test suite and 20 years' worth of bug reports
> > with unusual cases in them.  ;-)

> Tree-sitter has many problems.  For one, it does not intend to support
> C89 or (more importantly for me) pre-standard C.

Ah.  I actually suspect tree-sitter will be a lot more painful than most
people expect, and that CC Mode will continue to be generally used for
quite some time.

> Thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).





Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Thu, 10 Nov 2022 14:41:02 GMT) Full text and rfc822 format available.

Message #34 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Po Lu <luangruo <at> yahoo.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 58883 <at> debbugs.gnu.org
Subject: Re: bug#58883:
Date: Thu, 10 Nov 2022 22:40:37 +0800
Alan Mackenzie <acm <at> muc.de> writes:

> There won't usually be a problem.  There will be a superfluous entry
> "frobar" in c-found-types, but that won't affect anything unless there's
> an actual identifier frobar in the buffer.

But what if there is?

I think I am seeing that as well.  Please see the bottom of this reply
for one actual example.

> There is no on and off, here.  Types need to get handled somehow.  A
> great portion of all types are "found types", recognised from their
> context in the program and entered into c-found-types.

But CC Mode used to work fine in Emacs 28!

Identifiers did not turn green during the course of editing.

>> People who care about ``random'' fontification can then turn it on, or
>> use the new tree-sitter modes if they can.
>
> Failing to fontify a type is just as random as wrongly fontifying
> something as a type.

But that didn't leave ugly, green, splotches all over my code.

> Failing to fontify a type is also misfontification.  The consensus from
> that emacs-devel thread ~18 months ago was that it is not in order to
> fontify randomly.

Right, but it doesn't result in types randomly turned green.

> What do you think of a facility that would allow a user to remove a
> specific type from c-found-types?  It would work by putting point over
> the offending identifier, and entering something like C-c C-f?

How about an option to turn off c-found-types, at least?

> Also, are you still seeing these misfontifications in practice?  The lack
> of bug reports over the last few days suggests either the bugs aren't
> happening (much?) any more, or you've just got tired of submitting bug
> reports.  ;-)

It's the latter.  In one file at work where this problem is particularly
evident, a quarter of the identifiers turn green after approximately 25
minutes of routine editing, at which point I have to re-enable CC Mode.
That is, with Emacs off the master branch as of 4 PM this afternoon.

I've tried to report the obvious CC Mode bugs.  I think the rest of what
is happening is now akin to this (reconstructed through view-lossage of
an example that happened just now):

  register obd *obds;

  obds = ...;

  /* many uses of obds follow.  */

typedef obds IIu32;
           ^ this is the typo!!!

after the define of `obds' is corrected to `obd', it is too late, as CC
Mode already thinks `obds' is a type.




Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Thu, 10 Nov 2022 16:34:02 GMT) Full text and rfc822 format available.

Message #37 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Po Lu <luangruo <at> yahoo.com>
Cc: 58883 <at> debbugs.gnu.org
Subject: Re: bug#58883:
Date: Thu, 10 Nov 2022 16:33:37 +0000
[Message part 1 (text/plain, inline)]
Hello, Po.

On Thu, Nov 10, 2022 at 22:40:37 +0800, Po Lu wrote:
> Alan Mackenzie <acm <at> muc.de> writes:

> > There won't usually be a problem.  There will be a superfluous entry
> > "frobar" in c-found-types, but that won't affect anything unless there's
> > an actual identifier frobar in the buffer.

> But what if there is?

OK, I see now this is a problem.  It didn't seem like it before.

> I think I am seeing that as well.  Please see the bottom of this reply
> for one actual example.

> > There is no on and off, here.  Types need to get handled somehow.  A
> > great portion of all types are "found types", recognised from their
> > context in the program and entered into c-found-types.

> But CC Mode used to work fine in Emacs 28!

> Identifiers did not turn green during the course of editing.

> >> People who care about ``random'' fontification can then turn it on, or
> >> use the new tree-sitter modes if they can.

> > Failing to fontify a type is just as random as wrongly fontifying
> > something as a type.

> But that didn't leave ugly, green, splotches all over my code.

> > Failing to fontify a type is also misfontification.  The consensus from
> > that emacs-devel thread ~18 months ago was that it is not in order to
> > fontify randomly.

> Right, but it doesn't result in types randomly turned green.

> > What do you think of a facility that would allow a user to remove a
> > specific type from c-found-types?  It would work by putting point over
> > the offending identifier, and entering something like C-c C-f?

> How about an option to turn off c-found-types, at least?

> > Also, are you still seeing these misfontifications in practice?  The lack
> > of bug reports over the last few days suggests either the bugs aren't
> > happening (much?) any more, or you've just got tired of submitting bug
> > reports.  ;-)

> It's the latter.  In one file at work where this problem is particularly
> evident, a quarter of the identifiers turn green after approximately 25
> minutes of routine editing, at which point I have to re-enable CC Mode.
> That is, with Emacs off the master branch as of 4 PM this afternoon.

> I've tried to report the obvious CC Mode bugs.  I think the rest of what
> is happening is now akin to this (reconstructed through view-lossage of
> an example that happened just now):

>   register obd *obds;

>   obds = ...;

>   /* many uses of obds follow.  */

> typedef obds IIu32;
>            ^ this is the typo!!!

> after the define of `obds' is corrected to `obd', it is too late, as CC
> Mode already thinks `obds' is a type.

OK, I think I understand the problem now.  I'll try to come up with a way
of "cancelling" these "typo" found-types.

In the meantime, can I ask you to apply the attached patch?  This
reverses an "optimisation" from 2022-10-04, which fontified identifiers
as types without full analysis.  It won't solve the problem, but it might
make things more bearable for the next few days.

Also, as I've mentioned before, there's a CC Mode hack where making a
buffer change at point-min clears c-found-types.  Again not ideal, but it
might be better than nothing, for now.

-- 
Alan Mackenzie (Nuremberg, Germany).

[diff.20221110b.diff (text/plain, attachment)]

Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Fri, 11 Nov 2022 00:49:02 GMT) Full text and rfc822 format available.

Message #40 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Po Lu <luangruo <at> yahoo.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 58883 <at> debbugs.gnu.org
Subject: Re: bug#58883:
Date: Fri, 11 Nov 2022 08:48:12 +0800
Alan Mackenzie <acm <at> muc.de> writes:

> OK, I think I understand the problem now.  I'll try to come up with a way
> of "cancelling" these "typo" found-types.

Thanks a lot!

> In the meantime, can I ask you to apply the attached patch?  This
> reverses an "optimisation" from 2022-10-04, which fontified identifiers
> as types without full analysis.  It won't solve the problem, but it might
> make things more bearable for the next few days.

Yes, I will, thanks!

> Also, as I've mentioned before, there's a CC Mode hack where making a
> buffer change at point-min clears c-found-types.  Again not ideal, but it
> might be better than nothing, for now.

Thanks.  Unfortunately, since I updated to Emacs 29, the following has
already entrenched itself into my muscle memory:

  M-x c-mode RET




Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Thu, 17 Nov 2022 16:50:01 GMT) Full text and rfc822 format available.

Message #43 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Po Lu <luangruo <at> yahoo.com>
Cc: 58883 <at> debbugs.gnu.org, acm <at> muc.de
Subject: Re: bug#58883:
Date: Thu, 17 Nov 2022 16:49:05 +0000
[Message part 1 (text/plain, inline)]
Hello, Po.

On Fri, Nov 11, 2022 at 08:48:12 +0800, Po Lu wrote:
> Alan Mackenzie <acm <at> muc.de> writes:

> > OK, I think I understand the problem now.  I'll try to come up with a way
> > of "cancelling" these "typo" found-types.

> Thanks a lot!

OK, I have something better than I had a week ago.  Now these "typo"
found-types should only exist until the typo has been corrected.  Please
try the attached patch, and let me know how well it works.

The good news is it should fix bug #59300 "CC Mode 5.35.2 (C/*l); Yet
another kind of incorrect type recognition" at the same time.

[ .... ]

-- 
Alan Mackenzie (Nuremberg, Germany).

[diff.20221117.diff (text/plain, attachment)]

Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Fri, 18 Nov 2022 01:35:02 GMT) Full text and rfc822 format available.

Message #46 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Po Lu <luangruo <at> yahoo.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 58883 <at> debbugs.gnu.org
Subject: Re: bug#58883:
Date: Fri, 18 Nov 2022 09:33:58 +0800
Alan Mackenzie <acm <at> muc.de> writes:

> Hello, Po.
>
> On Fri, Nov 11, 2022 at 08:48:12 +0800, Po Lu wrote:
>> Alan Mackenzie <acm <at> muc.de> writes:
>
>> > OK, I think I understand the problem now.  I'll try to come up with a way
>> > of "cancelling" these "typo" found-types.
>
>> Thanks a lot!
>
> OK, I have something better than I had a week ago.  Now these "typo"
> found-types should only exist until the typo has been corrected.  Please
> try the attached patch, and let me know how well it works.
>
> The good news is it should fix bug #59300 "CC Mode 5.35.2 (C/*l); Yet
> another kind of incorrect type recognition" at the same time.
>
> [ .... ]

Thanks!  This seems to be working very well.

Unfortunately, there is one small problem: editing inside an identifier
name becomes a little sluggish: if you go down to `x_initialize' (in
xterm.c), type "int", TAB, and hold down "ddddddddddddddddddddddd" on
any line, you will see Emacs slow down to a crawl.

That seems to only be a problem in big files, however.




Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Fri, 18 Nov 2022 01:55:01 GMT) Full text and rfc822 format available.

Message #49 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Po Lu <luangruo <at> yahoo.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 58883 <at> debbugs.gnu.org
Subject: Re: bug#58883:
Date: Fri, 18 Nov 2022 09:53:43 +0800
Po Lu <luangruo <at> yahoo.com> writes:

> Thanks!  This seems to be working very well.
>
> Unfortunately, there is one small problem: editing inside an identifier
> name becomes a little sluggish: if you go down to `x_initialize' (in
> xterm.c), type "int", TAB, and hold down "ddddddddddddddddddddddd" on
> any line, you will see Emacs slow down to a crawl.
>
> That seems to only be a problem in big files, however.

Big problem: trying to edit in a string literal in a big file results is
very slow.  Quitting reveals the following call stack:

Debugger entered--entering a function:
* re-search-forward("[[:alpha:]_]" 25554 bound)
  c-unfind-tokens-in-region(1 25554)
  c-before-change(1 25554)
  c-after-change(25546 25547 0)
  self-insert-command(1 100)
  funcall-interactively(self-insert-command 1 100)
  command-execute(self-insert-command)

here is some text to reproduce the problem.  Insert the following text
in a c-mode buffer:

void
verify_image_data (struct test_display *display, Window window,
		   const char *filename)
{
  XImage *image;
  XWindowAttributes attrs;
  unsigned char *data;
  struct image_data_header header;
  unsigned short data_bpp, i;
  int byte_order;
  struct image_difference_statistics statistics;

  statistics.min_diff = 0;
  statistics.max_diff = 0;

  if (write_image_data_instead)
    write_image_data (display, window, filename);

  data = load_image_data (filename, &header);

  if (!data)
    report_test_failure ("failed to load input file: %s", filename);

  XGetWindowAttributes (display->x_display, window, &attrs);
  image = XGetImage (display->x_display, window, 0, 0, attrs.width,
		     attrs.height, ~0, ZPixmap);

  test_log ("verifying image data from: %s", filename);

  if (!image)
    report_test_failure ("failed to load from drawable 0x%lx", window);

  /* Check if the image data is compatible.  */
  data_bpp = bytes_per_pixel_for_format (header.format);
  byte_order = byte_order_for_format (header.format);

  if (byte_order != image->byte_order)
    report_test_failure ("image data has wrong byte order");

  if (data_bpp * 8 != image->bits_per_pixel)
    report_test_failure ("image data has %d bits per pixel, but reference"
			 " data has %hd * 8", image->bits_per_pixel, data_bpp);

  if (image->width != header.width
      || image->height != header.height)
    report_test_failure ("image data is %d by %d, but reference data is"
			 " %hd by %hd", image->width, image->height,
			 header.width, header.height);

  /* Now compare the actual image data.  Make sure this is done with
     the same visual as the reference data was saved in!  */

  for (i = 0; i < header.height; ++i)
    compare_single_row (data, i, &header, image, &statistics);

  /* Note that statistics is not always used by
     compare_single_row.  */

  test_log ("comparison finished.  channel differences were: %d, %d",
	    statistics.min_diff, statistics.max_diff);

  if (statistics.min_diff < -3 || statistics.max_diff > 4)
    {
      /* Write the reject to a file.  */
      test_log ("writing reject to reject.dump");
      write_image_data_1 (image, "reject.dump");

      report_test_failure ("differences exceeded thresholds (-3, 4)");
    }

  /* Destroy the images.  */
  free (data);
  XDestroyImage (image);

  test_log ("verified image data");
}
void
verify_image_data (struct test_display *display, Window window,
		   const char *filename)
{
  XImage *image;
  XWindowAttributes attrs;
  unsigned char *data;
  struct image_data_header header;
  unsigned short data_bpp, i;
  int byte_order;
  struct image_difference_statistics statistics;

  statistics.min_diff = 0;
  statistics.max_diff = 0;

  if (write_image_data_instead)
    write_image_data (display, window, filename);

  data = load_image_data (filename, &header);

  if (!data)
    report_test_failure ("failed to load input file: %s", filename);

  XGetWindowAttributes (display->x_display, window, &attrs);
  image = XGetImage (display->x_display, window, 0, 0, attrs.width,
		     attrs.height, ~0, ZPixmap);

  test_log ("verifying image data from: %s", filename);

  if (!image)
    report_test_failure ("failed to load from drawable 0x%lx", window);

  /* Check if the image data is compatible.  */
  data_bpp = bytes_per_pixel_for_format (header.format);
  byte_order = byte_order_for_format (header.format);

  if (byte_order != image->byte_order)
    report_test_failure ("image data has wrong byte order");

  if (data_bpp * 8 != image->bits_per_pixel)
    report_test_failure ("image data has %d bits per pixel, but reference"
			 " data has %hd * 8", image->bits_per_pixel, data_bpp);

  if (image->width != header.width
      || image->height != header.height)
    report_test_failure ("image data is %d by %d, but reference data is"
			 " %hd by %hd", image->width, image->height,
			 header.width, header.height);

  /* Now compare the actual image data.  Make sure this is done with
     the same visual as the reference data was saved in!  */

  for (i = 0; i < header.height; ++i)
    compare_single_row (data, i, &header, image, &statistics);

  /* Note that statistics is not always used by
     compare_single_row.  */

  test_log ("comparison finished.  channel differences were: %d, %d",
	    statistics.min_diff, statistics.max_diff);

  if (statistics.min_diff < -3 || statistics.max_diff > 4)
    {
      /* Write the reject to a file.  */
      test_log ("writing reject to reject.dump");
      write_image_data_1 (image, "reject.dump");

      report_test_failure ("differences exceeded thresholds (-3, 4)");
    }

  /* Destroy the images.  */
  free (data);
  XDestroyImage (image);

  test_log ("verified image data");
}

/* Verify the image data against a file.  */

void
verify_image_data (struct test_display *display, Window window,
		   const char *filename)
{
  XImage *image;
  XWindowAttributes attrs;
  unsigned char *data;
  struct image_data_header header;
  unsigned short data_bpp, i;
  int byte_order;
  struct image_difference_statistics statistics;

  statistics.min_diff = 0;
  statistics.max_diff = 0;

  if (write_image_data_instead)
    write_image_data (display, window, filename);

  data = load_image_data (filename, &header);

  if (!data)
    report_test_failure ("failed to load input file: %s", filename);

  XGetWindowAttributes (display->x_display, window, &attrs);
  image = XGetImage (display->x_display, window, 0, 0, attrs.width,
		     attrs.height, ~0, ZPixmap);

  test_log ("verifying image data from: %s", filename);

  if (!image)
    report_test_failure ("failed to load from drawable 0x%lx", window);

  /* Check if the image data is compatible.  */
  data_bpp = bytes_per_pixel_for_format (header.format);
  byte_order = byte_order_for_format (header.format);

  if (byte_order != image->byte_order)
    report_test_failure ("image data has wrong byte order");

  if (data_bpp * 8 != image->bits_per_pixel)
    report_test_failure ("image data has %d bits per pixel, but reference"
			 " data has %hd * 8", image->bits_per_pixel, data_bpp);

  if (image->width != header.width
      || image->height != header.height)
    report_test_failure ("image data is %d by %d, but reference data is"
			 " %hd by %hd", image->width, image->height,
			 header.width, header.height);

  /* Now compare the actual image data.  Make sure this is done with
     the same visual as the reference data was saved in!  */

  for (i = 0; i < header.height; ++i)
    compare_single_row (data, i, &header, image, &statistics);

  /* Note that statistics is not always used by
     compare_single_row.  */

  test_log ("comparison finished.  channel differences were: %d, %d",
	    statistics.min_diff, statistics.max_diff);

  if (statistics.min_diff < -3 || statistics.max_diff > 4)
    {
      /* Write the reject to a file.  */
      test_log ("writing reject to reject.dump");
      write_image_data_1 (image, "reject.dump");

      report_test_failure ("differences exceeded thresholds (-3, 4)");
    }

  /* Destroy the images.  */
  free (data);
  XDestroyImage (image);

  test_log ("verified image data");
}

void
test_set_scale (struct test_display *display, int scale)
{
  test_scale_lock_set_scale (display->scale_lock, scale);
}

void
test_init (void)
{
  write_image_data_instead
    = getenv ("TEST_WRITE_REFERENCE") != NULL;
}



static void
handle_seat_controller_device_id (void *data,
				  struct test_seat_controller *controller,
				  uint32_t device_id)
{
  struct test_display *display;

  display = data;
  display->seat->device_id = device_id;
}

static const struct test_seat_controller_listener seat_controller_listener =
  {
    handle_seat_controller_device_id,
  };



void
test_init_seat (struct test_display *display)
{
  if (display->seat)
    report_test_internal_error ("tried to initialize seat twice");

  display->seat = malloc (sizeof *display->seat);

  if (!display->seat)
    report_test_failure ("failed to allocate seat");

  display->seat->controller
    = test_manager_get_test_seat (display->test_manager);

  if (!display->seat->controller)
    report_test_failure ("failed to obtain seat controller");

  display->seat->device_controller
    = test_seat_controller_get_device_controller (display->seat->controller);

  if (!display->seat->device_controller)
    report_test_failure ("failed to obtain device controller");

  /* Fetch the device ID of the seat.  */
  display->seat->device_id = 0;
  test_seat_controller_add_listener (display->seat->controller,
				     &seat_controller_listener,
				     display);
  wl_display_roundtrip (display->display);

  if (!display->seat->device_id)
    report_test_failure ("failed to obtain device ID");

  /* The protocol translator currently supports version 8 of wl_seat,
     so bind to that.  */

  display->seat->seat
    = test_seat_controller_bind_seat (display->seat->controller,
				      8);

  if (!display->seat->seat)
    report_test_failure ("failed to bind to test seat");

  display->seat->pointer
    = wl_seat_get_pointer (display->seat->seat);

  if (!display->seat->pointer)
    report_test_failure ("failed to bind to test pointer");

  display->seat->keyboard
    = wl_seat_get_keyboard (display->seat->seat);

  if (!display->seat->keyboard)
    report_test_failure ("failed to bind to test keyboard");
}

void __attribute__ ((noreturn))
test_complete (void)
{
  test_log ("test ran successfully");
  exit_with_code (0);
}

uint32_t
test_get_serial (struct test_display *display)
{
  test_manager_get_serial (display->test_manager);
  wl_display_roundtrip (display->display);

  return display->serial;
}

void
verify_window_size (struct test_display *display,
		    Window window, int width, int height)
{
  XWindowAttributes attrs;

  XGetWindowAttributes (display->x_display, window, &attrs);

  if (width != attrs.width || height != attrs.height)
    report_test_failure ("window is incorrect size.  expected: %d %d"
			 ", actual: %d %d", width, height,
			 attrs.width, attrs.height);
}



static void
handle_wl_buffer_release (void *data, struct wl_buffer *buffer)
{
  struct test_buffer *test_buffer;

  test_buffer = data;
  test_buffer->busy = false;
}

static const struct wl_buffer_listener test_buffer_listener =
  {
    handle_wl_buffer_release,
  };



struct test_buffer *
get_test_buffer (struct test_display *display, struct wl_buffer *buffer)
{
  struct test_buffer *test_buffer;

  test_buffer = malloc (sizeof *test_buffer);

  if (!test_buffer)
    return NULL;

  test_buffer->buffer = buffer;
  test_buffer->busy = false;

  wl_buffer_add_listener (buffer, &test_buffer_listener, test_buffer);
}

void
test_buffer_committed (struct test_buffer *test_buffer)
{
  test_buffer->busy = true;
}

void
verify_buffer_released (struct test_buffer *buffer)
{
  if (!test_buffer->busy)
    report_test_failure ("buffer %p");
}

and type " is busy, but should have been released" after "%p".  Editing
will slow down to a crawl.

Thanks.




Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Fri, 18 Nov 2022 07:36:02 GMT) Full text and rfc822 format available.

Message #52 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Po Lu <luangruo <at> yahoo.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 58883 <at> debbugs.gnu.org
Subject: Re: bug#58883:
Date: Fri, 18 Nov 2022 15:35:30 +0800
Po Lu <luangruo <at> yahoo.com> writes:

> Big problem: trying to edit in a string literal in a big file results is
> very slow.  Quitting reveals the following call stack:
>
> Debugger entered--entering a function:
> * re-search-forward("[[:alpha:]_]" 25554 bound)
>   c-unfind-tokens-in-region(1 25554)
>   c-before-change(1 25554)
>   c-after-change(25546 25547 0)
>   self-insert-command(1 100)
>   funcall-interactively(self-insert-command 1 100)
>   command-execute(self-insert-command)
>
> here is some text to reproduce the problem.  Insert the following text
> in a c-mode buffer:
>
> void
> verify_image_data (struct test_display *display, Window window,
> 		   const char *filename)
> {
>   XImage *image;
>   XWindowAttributes attrs;
>   unsigned char *data;
>   struct image_data_header header;
>   unsigned short data_bpp, i;
>   int byte_order;
>   struct image_difference_statistics statistics;
>
>   statistics.min_diff = 0;
>   statistics.max_diff = 0;
>
>   if (write_image_data_instead)
>     write_image_data (display, window, filename);
>
>   data = load_image_data (filename, &header);
>
>   if (!data)
>     report_test_failure ("failed to load input file: %s", filename);
>
>   XGetWindowAttributes (display->x_display, window, &attrs);
>   image = XGetImage (display->x_display, window, 0, 0, attrs.width,
> 		     attrs.height, ~0, ZPixmap);
>
>   test_log ("verifying image data from: %s", filename);
>
>   if (!image)
>     report_test_failure ("failed to load from drawable 0x%lx", window);
>
>   /* Check if the image data is compatible.  */
>   data_bpp = bytes_per_pixel_for_format (header.format);
>   byte_order = byte_order_for_format (header.format);
>
>   if (byte_order != image->byte_order)
>     report_test_failure ("image data has wrong byte order");
>
>   if (data_bpp * 8 != image->bits_per_pixel)
>     report_test_failure ("image data has %d bits per pixel, but reference"
> 			 " data has %hd * 8", image->bits_per_pixel, data_bpp);
>
>   if (image->width != header.width
>       || image->height != header.height)
>     report_test_failure ("image data is %d by %d, but reference data is"
> 			 " %hd by %hd", image->width, image->height,
> 			 header.width, header.height);
>
>   /* Now compare the actual image data.  Make sure this is done with
>      the same visual as the reference data was saved in!  */
>
>   for (i = 0; i < header.height; ++i)
>     compare_single_row (data, i, &header, image, &statistics);
>
>   /* Note that statistics is not always used by
>      compare_single_row.  */
>
>   test_log ("comparison finished.  channel differences were: %d, %d",
> 	    statistics.min_diff, statistics.max_diff);
>
>   if (statistics.min_diff < -3 || statistics.max_diff > 4)
>     {
>       /* Write the reject to a file.  */
>       test_log ("writing reject to reject.dump");
>       write_image_data_1 (image, "reject.dump");
>
>       report_test_failure ("differences exceeded thresholds (-3, 4)");
>     }
>
>   /* Destroy the images.  */
>   free (data);
>   XDestroyImage (image);
>
>   test_log ("verified image data");
> }
> void
> verify_image_data (struct test_display *display, Window window,
> 		   const char *filename)
> {
>   XImage *image;
>   XWindowAttributes attrs;
>   unsigned char *data;
>   struct image_data_header header;
>   unsigned short data_bpp, i;
>   int byte_order;
>   struct image_difference_statistics statistics;
>
>   statistics.min_diff = 0;
>   statistics.max_diff = 0;
>
>   if (write_image_data_instead)
>     write_image_data (display, window, filename);
>
>   data = load_image_data (filename, &header);
>
>   if (!data)
>     report_test_failure ("failed to load input file: %s", filename);
>
>   XGetWindowAttributes (display->x_display, window, &attrs);
>   image = XGetImage (display->x_display, window, 0, 0, attrs.width,
> 		     attrs.height, ~0, ZPixmap);
>
>   test_log ("verifying image data from: %s", filename);
>
>   if (!image)
>     report_test_failure ("failed to load from drawable 0x%lx", window);
>
>   /* Check if the image data is compatible.  */
>   data_bpp = bytes_per_pixel_for_format (header.format);
>   byte_order = byte_order_for_format (header.format);
>
>   if (byte_order != image->byte_order)
>     report_test_failure ("image data has wrong byte order");
>
>   if (data_bpp * 8 != image->bits_per_pixel)
>     report_test_failure ("image data has %d bits per pixel, but reference"
> 			 " data has %hd * 8", image->bits_per_pixel, data_bpp);
>
>   if (image->width != header.width
>       || image->height != header.height)
>     report_test_failure ("image data is %d by %d, but reference data is"
> 			 " %hd by %hd", image->width, image->height,
> 			 header.width, header.height);
>
>   /* Now compare the actual image data.  Make sure this is done with
>      the same visual as the reference data was saved in!  */
>
>   for (i = 0; i < header.height; ++i)
>     compare_single_row (data, i, &header, image, &statistics);
>
>   /* Note that statistics is not always used by
>      compare_single_row.  */
>
>   test_log ("comparison finished.  channel differences were: %d, %d",
> 	    statistics.min_diff, statistics.max_diff);
>
>   if (statistics.min_diff < -3 || statistics.max_diff > 4)
>     {
>       /* Write the reject to a file.  */
>       test_log ("writing reject to reject.dump");
>       write_image_data_1 (image, "reject.dump");
>
>       report_test_failure ("differences exceeded thresholds (-3, 4)");
>     }
>
>   /* Destroy the images.  */
>   free (data);
>   XDestroyImage (image);
>
>   test_log ("verified image data");
> }
>
> /* Verify the image data against a file.  */
>
> void
> verify_image_data (struct test_display *display, Window window,
> 		   const char *filename)
> {
>   XImage *image;
>   XWindowAttributes attrs;
>   unsigned char *data;
>   struct image_data_header header;
>   unsigned short data_bpp, i;
>   int byte_order;
>   struct image_difference_statistics statistics;
>
>   statistics.min_diff = 0;
>   statistics.max_diff = 0;
>
>   if (write_image_data_instead)
>     write_image_data (display, window, filename);
>
>   data = load_image_data (filename, &header);
>
>   if (!data)
>     report_test_failure ("failed to load input file: %s", filename);
>
>   XGetWindowAttributes (display->x_display, window, &attrs);
>   image = XGetImage (display->x_display, window, 0, 0, attrs.width,
> 		     attrs.height, ~0, ZPixmap);
>
>   test_log ("verifying image data from: %s", filename);
>
>   if (!image)
>     report_test_failure ("failed to load from drawable 0x%lx", window);
>
>   /* Check if the image data is compatible.  */
>   data_bpp = bytes_per_pixel_for_format (header.format);
>   byte_order = byte_order_for_format (header.format);
>
>   if (byte_order != image->byte_order)
>     report_test_failure ("image data has wrong byte order");
>
>   if (data_bpp * 8 != image->bits_per_pixel)
>     report_test_failure ("image data has %d bits per pixel, but reference"
> 			 " data has %hd * 8", image->bits_per_pixel, data_bpp);
>
>   if (image->width != header.width
>       || image->height != header.height)
>     report_test_failure ("image data is %d by %d, but reference data is"
> 			 " %hd by %hd", image->width, image->height,
> 			 header.width, header.height);
>
>   /* Now compare the actual image data.  Make sure this is done with
>      the same visual as the reference data was saved in!  */
>
>   for (i = 0; i < header.height; ++i)
>     compare_single_row (data, i, &header, image, &statistics);
>
>   /* Note that statistics is not always used by
>      compare_single_row.  */
>
>   test_log ("comparison finished.  channel differences were: %d, %d",
> 	    statistics.min_diff, statistics.max_diff);
>
>   if (statistics.min_diff < -3 || statistics.max_diff > 4)
>     {
>       /* Write the reject to a file.  */
>       test_log ("writing reject to reject.dump");
>       write_image_data_1 (image, "reject.dump");
>
>       report_test_failure ("differences exceeded thresholds (-3, 4)");
>     }
>
>   /* Destroy the images.  */
>   free (data);
>   XDestroyImage (image);
>
>   test_log ("verified image data");
> }
>
> void
> test_set_scale (struct test_display *display, int scale)
> {
>   test_scale_lock_set_scale (display->scale_lock, scale);
> }
>
> void
> test_init (void)
> {
>   write_image_data_instead
>     = getenv ("TEST_WRITE_REFERENCE") != NULL;
> }
>
> 
>
> static void
> handle_seat_controller_device_id (void *data,
> 				  struct test_seat_controller *controller,
> 				  uint32_t device_id)
> {
>   struct test_display *display;
>
>   display = data;
>   display->seat->device_id = device_id;
> }
>
> static const struct test_seat_controller_listener seat_controller_listener =
>   {
>     handle_seat_controller_device_id,
>   };
>
> 
>
> void
> test_init_seat (struct test_display *display)
> {
>   if (display->seat)
>     report_test_internal_error ("tried to initialize seat twice");
>
>   display->seat = malloc (sizeof *display->seat);
>
>   if (!display->seat)
>     report_test_failure ("failed to allocate seat");
>
>   display->seat->controller
>     = test_manager_get_test_seat (display->test_manager);
>
>   if (!display->seat->controller)
>     report_test_failure ("failed to obtain seat controller");
>
>   display->seat->device_controller
>     = test_seat_controller_get_device_controller (display->seat->controller);
>
>   if (!display->seat->device_controller)
>     report_test_failure ("failed to obtain device controller");
>
>   /* Fetch the device ID of the seat.  */
>   display->seat->device_id = 0;
>   test_seat_controller_add_listener (display->seat->controller,
> 				     &seat_controller_listener,
> 				     display);
>   wl_display_roundtrip (display->display);
>
>   if (!display->seat->device_id)
>     report_test_failure ("failed to obtain device ID");
>
>   /* The protocol translator currently supports version 8 of wl_seat,
>      so bind to that.  */
>
>   display->seat->seat
>     = test_seat_controller_bind_seat (display->seat->controller,
> 				      8);
>
>   if (!display->seat->seat)
>     report_test_failure ("failed to bind to test seat");
>
>   display->seat->pointer
>     = wl_seat_get_pointer (display->seat->seat);
>
>   if (!display->seat->pointer)
>     report_test_failure ("failed to bind to test pointer");
>
>   display->seat->keyboard
>     = wl_seat_get_keyboard (display->seat->seat);
>
>   if (!display->seat->keyboard)
>     report_test_failure ("failed to bind to test keyboard");
> }
>
> void __attribute__ ((noreturn))
> test_complete (void)
> {
>   test_log ("test ran successfully");
>   exit_with_code (0);
> }
>
> uint32_t
> test_get_serial (struct test_display *display)
> {
>   test_manager_get_serial (display->test_manager);
>   wl_display_roundtrip (display->display);
>
>   return display->serial;
> }
>
> void
> verify_window_size (struct test_display *display,
> 		    Window window, int width, int height)
> {
>   XWindowAttributes attrs;
>
>   XGetWindowAttributes (display->x_display, window, &attrs);
>
>   if (width != attrs.width || height != attrs.height)
>     report_test_failure ("window is incorrect size.  expected: %d %d"
> 			 ", actual: %d %d", width, height,
> 			 attrs.width, attrs.height);
> }
>
> 
>
> static void
> handle_wl_buffer_release (void *data, struct wl_buffer *buffer)
> {
>   struct test_buffer *test_buffer;
>
>   test_buffer = data;
>   test_buffer->busy = false;
> }
>
> static const struct wl_buffer_listener test_buffer_listener =
>   {
>     handle_wl_buffer_release,
>   };
>
> 
>
> struct test_buffer *
> get_test_buffer (struct test_display *display, struct wl_buffer *buffer)
> {
>   struct test_buffer *test_buffer;
>
>   test_buffer = malloc (sizeof *test_buffer);
>
>   if (!test_buffer)
>     return NULL;
>
>   test_buffer->buffer = buffer;
>   test_buffer->busy = false;
>
>   wl_buffer_add_listener (buffer, &test_buffer_listener, test_buffer);
> }
>
> void
> test_buffer_committed (struct test_buffer *test_buffer)
> {
>   test_buffer->busy = true;
> }
>
> void
> verify_buffer_released (struct test_buffer *buffer)
> {
>   if (!test_buffer->busy)
>     report_test_failure ("buffer %p");
> }
>
> and type " is busy, but should have been released" after "%p".  Editing
> will slow down to a crawl.
>
> Thanks.

Also, it seems that `CHECK_LISP_OBJECT_TYPE' is fontified as a type in
lisp.h, tho I've no idea whether or not that is related to this patch.




Information forwarded to bug-cc-mode <at> gnu.org:
bug#58883; Package cc-mode. (Fri, 18 Nov 2022 22:05:01 GMT) Full text and rfc822 format available.

Message #55 received at 58883 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Po Lu <luangruo <at> yahoo.com>
Cc: 58883 <at> debbugs.gnu.org
Subject: Re: bug#58883:
Date: Fri, 18 Nov 2022 22:03:47 +0000
Hello, Po.

On Fri, Nov 18, 2022 at 09:53:43 +0800, Po Lu wrote:
> Po Lu <luangruo <at> yahoo.com> writes:

> > Thanks!  This seems to be working very well.

> > Unfortunately, there is one small problem: editing inside an identifier
> > name becomes a little sluggish: if you go down to `x_initialize' (in
> > xterm.c), type "int", TAB, and hold down "ddddddddddddddddddddddd" on
> > any line, you will see Emacs slow down to a crawl.

> > That seems to only be a problem in big files, however.

> Big problem: trying to edit in a string literal in a big file results is
> very slow.  Quitting reveals the following call stack:

> Debugger entered--entering a function:
> * re-search-forward("[[:alpha:]_]" 25554 bound)
>   c-unfind-tokens-in-region(1 25554)
>   c-before-change(1 25554)
>   c-after-change(25546 25547 0)
>   self-insert-command(1 100)
>   funcall-interactively(self-insert-command 1 100)
>   command-execute(self-insert-command)

Yes, that is a big problem.  Apologies that the patch was not very good.
I'll be looking at it over the coming days, and hope to produce a
properly working version in that sort of timescale.  Please regard the
patch as a mere proof of concept, that the bug _can_ be fixed, rather
than the fix itself.

> here is some text to reproduce the problem.  Insert the following text
> in a c-mode buffer:

Thanks for that.  I can reproduce all the problems.

[ .... ]

> Thanks.

-- 
Alan Mackenzie (Nuremberg, Germany).




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Sat, 17 Dec 2022 12:24:11 GMT) Full text and rfc822 format available.

This bug report was last modified 1 year and 101 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.