GNU bug report logs - #15415
24.3.50; c++-mode fontification for constructors is inconsistent

Previous Next

Packages: emacs, cc-mode;

Reported by: Ivan Andrus <darthandrus <at> gmail.com>

Date: Thu, 19 Sep 2013 02:46:01 UTC

Severity: normal

Found in version 24.3.50

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 15415 in the body.
You can then email your comments to 15415 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-gnu-emacs <at> gnu.org:
bug#15415; Package emacs. (Thu, 19 Sep 2013 02:46:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Ivan Andrus <darthandrus <at> gmail.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Thu, 19 Sep 2013 02:46:02 GMT) Full text and rfc822 format available.

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

From: Ivan Andrus <darthandrus <at> gmail.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 24.3.50; c++-mode fontification for constructors is inconsistent
Date: Wed, 18 Sep 2013 20:44:39 -0600
[Message part 1 (text/plain, inline)]
Font locking of C++ constructors is somewhat inconsistent.  This is no
doubt complicated by the fact that unlike other function declarations
they "don't have a return type".

When a single argument is not used but named, the constructor is not
fontified (normally it's fontified with `font-lock-function-name-face').
If the keyword explicit is used, then the argument type is fontified as
a variable, and the constructor name is fontified as a type.  Perhaps
interestingly, naming the parameter or adding another parameter causes
fontification to work correctly (with or without explicit).

I have included a sample file below with comments on what I see in `emacs -q`


class Bob
{
    // string is `font-lock-type-face', Bob is `font-lock-function-name-face'
    Bob( string bob );
    // string and Bob are not fontified (though I sometimes see string fontified as a type)
    Bob( string );
    // string is `font-lock-variable-name-face', Bob is `font-lock-type-face'
    explicit Bob( string );
    // string is `font-lock-type-face', Bob is `font-lock-function-name-face'
    explicit Bob( string, string );
};
[constructors.pdf (application/pdf, inline)]
[Message part 3 (text/plain, inline)]

Thanks,
Ivan

In GNU Emacs 24.3.50.1 (i386-apple-darwin12.5.0, NS apple-appkit-1187.39)
of 2013-09-16 on ivanandres-MacBookPro
Bzr revision: 114309 rgm <at> gnu.org-20130916192145-tr5qrfdmhcq3a563
Windowing system distributor `Apple', version 10.3.1187
Configured using:
`configure --with-ns --with-xml2'

Important settings:
  locale-coding-system: nil
  default enable-multibyte-characters: t

Major mode: C++/lah

Minor modes in effect:
  diff-auto-refine-mode: t
  eldoc-mode: t
  highlight-parentheses-mode: t
  hl-sexp-mode: t
  highlight-symbol-mode: t
  which-function-mode: t
  show-paren-mode: t
  msb-mode: t
  minibuffer-depth-indicate-mode: t
  global-hl-line-mode: t
  delete-selection-mode: t
  auto-image-file-mode: t
  auto-insert-mode: t
  yas-global-mode: t
  yas-minor-mode: t
  shell-dirtrack-mode: t
  ido-everywhere: t
  global-visible-mark-mode: t
  visible-mark-mode: t
  gvol-mode: t
  recentf-mode: t
  desktop-save-mode: t
  drag-stuff-global-mode: t
  drag-stuff-mode: t
  tooltip-mode: t
  mouse-wheel-mode: t
  tool-bar-mode: t
  menu-bar-mode: t
  file-name-shadow-mode: t
  global-font-lock-mode: t
  font-lock-mode: t
  blink-cursor-mode: t
  auto-composition-mode: t
  auto-encryption-mode: t
  auto-compression-mode: t
  column-number-mode: t
  line-number-mode: t
  transient-mark-mode: t
  abbrev-mode: t

Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#15415; Package emacs,cc-mode. (Mon, 30 Sep 2013 03:32:02 GMT) Full text and rfc822 format available.

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

From: Ivan Andrus <darthandrus <at> gmail.com>
To: 15415 <at> debbugs.gnu.org
Subject: Re: bug#15415: 24.3.50;
 c++-mode fontification for constructors is inconsistent
Date: Sun, 29 Sep 2013 21:31:13 -0600
Ivan Andrus <darthandrus <at> gmail.com> writes:

> Font locking of C++ constructors is somewhat inconsistent.  This is no
> doubt complicated by the fact that unlike other function declarations
> they "don't have a return type".
>
> When a single argument is not used but named, the constructor is not
> fontified (normally it's fontified with `font-lock-function-name-face').
> If the keyword explicit is used, then the argument type is fontified as
> a variable, and the constructor name is fontified as a type.  Perhaps
> interestingly, naming the parameter or adding another parameter causes
> fontification to work correctly (with or without explicit).
>
> I have included a sample file below with comments on what I see in `emacs -q`
>
>
> class Bob
> {
>     // string is `font-lock-type-face', Bob is `font-lock-function-name-face'
>     Bob( string bob );
>     // string and Bob are not fontified (though I sometimes see string fontified as a type)
>     Bob( string );
>     // string is `font-lock-variable-name-face', Bob is `font-lock-type-face'
>     explicit Bob( string );
>     // string is `font-lock-type-face', Bob is `font-lock-function-name-face'
>     explicit Bob( string, string );
> };

In fact, it's not just constructors that have this problem.  For example
the following function declaration:

string lookup( size_t ) const;

Removing const, or adding a name to the size_t parameter causes
fontification to work correctly.

-Ivan




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#15415; Package emacs,cc-mode. (Sat, 12 Oct 2013 20:48:02 GMT) Full text and rfc822 format available.

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

From: Alan Mackenzie <acm <at> muc.de>
To: Ivan Andrus <darthandrus <at> gmail.com>
Cc: 15415 <at> debbugs.gnu.org
Subject: Re: bug#15415: 24.3.50; c++-mode fontification for constructors is
 inconsistent
Date: Sat, 12 Oct 2013 20:45:43 +0000
Hello, Ivan.

On Sun, Sep 29, 2013 at 09:31:13PM -0600, Ivan Andrus wrote:
> Ivan Andrus <darthandrus <at> gmail.com> writes:

> > Font locking of C++ constructors is somewhat inconsistent.  This is
> > no doubt complicated by the fact that unlike other function
> > declarations they "don't have a return type".

This is, indeed, problematic.

> > When a single argument is not used but named, the constructor is not
> > fontified (normally it's fontified with
> > `font-lock-function-name-face').  If the keyword explicit is used,
> > then the argument type is fontified as a variable, and the
> > constructor name is fontified as a type.  Perhaps interestingly,
> > naming the parameter or adding another parameter causes fontification
> > to work correctly (with or without explicit).

Yes.  The pertinent function, `c-forward-decl-or-cast-1', is somewhat
probablistic.  If it gets sufficient clues from the context, it gets
things right, otherwise it has to guess, and sometimes will get things
wrong, particularly in C++, which doesn't have a nice context-free
syntax.

> > I have included a sample file below with comments on what I see in
> > `emacs -q`


  > > class Bob
  > > {
  > >     // string is `font-lock-type-face', Bob is `font-lock-function-name-face'
1 > >     Bob( string bob );
  > >     // string and Bob are not fontified (though I sometimes see string fontified as a type)
2 > >     Bob( string );
  > >     // string is `font-lock-variable-name-face', Bob is `font-lock-type-face'
3 > >     explicit Bob( string );
  > >     // string is `font-lock-type-face', Bob is `font-lock-function-name-face'
4 > >     explicit Bob( string, string );
  > > };

> In fact, it's not just constructors that have this problem.  For
> example the following function declaration:

5 > string lookup( size_t ) const;

> Removing const, or adding a name to the size_t parameter causes
> fontification to work correctly.

Yes.

Of the lines of code you've illustrated, 1 and 4 were OK.  I've corrected
3 and 5, which were relatively simple.

2 is a problem, because it looks like a normal function call.  If the
identifier in the parentheses (here "string") can be positively
identified as a type (for example, some use elsewhere can only be a type,
or it's a standard type like "string") it gets fontified.  Otherwise,
it's assumed the construct is a function call.  It would no doubt be
possible to check that the enclosing braces are a class declaration, and
that "Bob" is the name of the class, but this would slow down the
fontification, probably by a lot.

Would you please try out the patch below, and let me know how it goes.
It is based on the current source in the bzr trunk.

Again, thanks for such a crisp and concise bug report.



=== modified file 'lisp/progmodes/cc-engine.el'
*** lisp/progmodes/cc-engine.el	2013-09-28 17:17:01 +0000
--- lisp/progmodes/cc-engine.el	2013-10-12 20:18:26 +0000
***************
*** 6917,6923 ****
  	  ;; can happen since we don't know if
  	  ;; `c-restricted-<>-arglists' will be correct inside the
  	  ;; arglist paren that gets entered.
! 	  c-parse-and-markup-<>-arglists)
  
        (goto-char id-start)
  
--- 6917,6925 ----
  	  ;; can happen since we don't know if
  	  ;; `c-restricted-<>-arglists' will be correct inside the
  	  ;; arglist paren that gets entered.
! 	  c-parse-and-markup-<>-arglists
! 	  ;; Start of the identifier for which `got-identifier' was set.
! 	  name-start)
  
        (goto-char id-start)
  
***************
*** 6935,6941 ****
  			;; If the third submatch matches in C++ then
  			;; we're looking at an identifier that's a
  			;; prefix only if it specifies a member pointer.
! 			(when (setq got-identifier (c-forward-name))
  			  (if (looking-at "\\(::\\)")
  			      ;; We only check for a trailing "::" and
  			      ;; let the "*" that should follow be
--- 6937,6945 ----
  			;; If the third submatch matches in C++ then
  			;; we're looking at an identifier that's a
  			;; prefix only if it specifies a member pointer.
! 			(when (progn (setq pos (point))
! 				     (setq got-identifier (c-forward-name)))
! 			  (setq name-start pos)
  			  (if (looking-at "\\(::\\)")
  			      ;; We only check for a trailing "::" and
  			      ;; let the "*" that should follow be
***************
*** 6961,6967 ****
        ;; Skip over an identifier.
        (or got-identifier
  	  (and (looking-at c-identifier-start)
! 	       (setq got-identifier (c-forward-name))))
  
        ;; Skip over type decl suffix operators.
        (while (if (looking-at c-type-decl-suffix-key)
--- 6965,6973 ----
        ;; Skip over an identifier.
        (or got-identifier
  	  (and (looking-at c-identifier-start)
! 	       (setq pos (point))
! 	       (setq got-identifier (c-forward-name))
! 	       (setq name-start pos)))
  
        ;; Skip over type decl suffix operators.
        (while (if (looking-at c-type-decl-suffix-key)
***************
*** 7052,7074 ****
  		;; declaration.
  		(throw 'at-decl-or-cast t))
  
- 	      (when (and got-parens
- 			 (not got-prefix)
- 			 (not got-suffix-after-parens)
- 			 (or backup-at-type
- 			     maybe-typeless
- 			     backup-maybe-typeless))
- 		;; Got a declaration of the form "foo bar (gnu);" where we've
- 		;; recognized "bar" as the type and "gnu" as the declarator.
- 		;; In this case it's however more likely that "bar" is the
- 		;; declarator and "gnu" a function argument or initializer (if
- 		;; `c-recognize-paren-inits' is set), since the parens around
- 		;; "gnu" would be superfluous if it's a declarator.  Shift the
- 		;; type one step backward.
- 		(c-fdoc-shift-type-backward)))
  
! 	  ;; Found no identifier.
  
  	  (if backup-at-type
  	      (progn
  
--- 7058,7084 ----
  		;; declaration.
  		(throw 'at-decl-or-cast t))
  
  
! 	       (when (and got-parens
! 			  (not got-prefix)
! 			  ;; (not got-suffix-after-parens)
! 			  (or backup-at-type
! 			      maybe-typeless
! 			      backup-maybe-typeless
! 			      (eq at-decl-or-cast t)
! 			      (save-excursion
! 				(goto-char name-start)
! 				(not (memq (c-forward-type) '(nil maybe))))))
! 		 ;; Got a declaration of the form "foo bar (gnu);" or "bar
! 		 ;; (gnu);" where we've recognized "bar" as the type and "gnu"
! 		 ;; as the declarator.  In this case it's however more likely
! 		 ;; that "bar" is the declarator and "gnu" a function argument
! 		 ;; or initializer (if `c-recognize-paren-inits' is set),
! 		 ;; since the parens around "gnu" would be superfluous if it's
! 		 ;; a declarator.  Shift the type one step backward.
! 		 (c-fdoc-shift-type-backward)))
  
+ 	   ;; Found no identifier.
  	  (if backup-at-type
  	      (progn
  




> -Ivan

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-gnu-emacs <at> gnu.org, bug-cc-mode <at> gnu.org:
bug#15415; Package emacs,cc-mode. (Fri, 18 Oct 2013 22:01:02 GMT) Full text and rfc822 format available.

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

From: Ivan Andrus <darthandrus <at> gmail.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: "15415 <at> debbugs.gnu.org" <15415 <at> debbugs.gnu.org>
Subject: Re: bug#15415: 24.3.50;
 c++-mode fontification for constructors is inconsistent
Date: Fri, 18 Oct 2013 16:00:45 -0600
[Message part 1 (text/plain, inline)]
Oops, forgot to CC the bug.

I've been using the patch for a week now and haven't noticed any ill
effects.

Thanks,
Ivan


On Sat, Oct 12, 2013 at 2:45 PM, Alan Mackenzie <acm <at> muc.de> wrote:

> Hello, Ivan.
>
> On Sun, Sep 29, 2013 at 09:31:13PM -0600, Ivan Andrus wrote:
> > Ivan Andrus <darthandrus <at> gmail.com> writes:
>
> > > Font locking of C++ constructors is somewhat inconsistent.  This is
> > > no doubt complicated by the fact that unlike other function
> > > declarations they "don't have a return type".
>
> This is, indeed, problematic.
>
> > > When a single argument is not used but named, the constructor is not
> > > fontified (normally it's fontified with
> > > `font-lock-function-name-face').  If the keyword explicit is used,
> > > then the argument type is fontified as a variable, and the
> > > constructor name is fontified as a type.  Perhaps interestingly,
> > > naming the parameter or adding another parameter causes fontification
> > > to work correctly (with or without explicit).
>
> Yes.  The pertinent function, `c-forward-decl-or-cast-1', is somewhat
> probablistic.  If it gets sufficient clues from the context, it gets
> things right, otherwise it has to guess, and sometimes will get things
> wrong, particularly in C++, which doesn't have a nice context-free
> syntax.
>
> > > I have included a sample file below with comments on what I see in
> > > `emacs -q`
>
>
>   > > class Bob
>   > > {
>   > >     // string is `font-lock-type-face', Bob is
> `font-lock-function-name-face'
> 1 > >     Bob( string bob );
>   > >     // string and Bob are not fontified (though I sometimes see
> string fontified as a type)
> 2 > >     Bob( string );
>   > >     // string is `font-lock-variable-name-face', Bob is
> `font-lock-type-face'
> 3 > >     explicit Bob( string );
>   > >     // string is `font-lock-type-face', Bob is
> `font-lock-function-name-face'
> 4 > >     explicit Bob( string, string );
>   > > };
>
> > In fact, it's not just constructors that have this problem.  For
> > example the following function declaration:
>
> 5 > string lookup( size_t ) const;
>
> > Removing const, or adding a name to the size_t parameter causes
> > fontification to work correctly.
>
> Yes.
>
> Of the lines of code you've illustrated, 1 and 4 were OK.  I've corrected
> 3 and 5, which were relatively simple.
>
> 2 is a problem, because it looks like a normal function call.  If the
> identifier in the parentheses (here "string") can be positively
> identified as a type (for example, some use elsewhere can only be a type,
> or it's a standard type like "string") it gets fontified.  Otherwise,
> it's assumed the construct is a function call.  It would no doubt be
> possible to check that the enclosing braces are a class declaration, and
> that "Bob" is the name of the class, but this would slow down the
> fontification, probably by a lot.
>
> Would you please try out the patch below, and let me know how it goes.
> It is based on the current source in the bzr trunk.
>
> Again, thanks for such a crisp and concise bug report.
>
>
>
> === modified file 'lisp/progmodes/cc-engine.el'
> *** lisp/progmodes/cc-engine.el 2013-09-28 17:17:01 +0000
> --- lisp/progmodes/cc-engine.el 2013-10-12 20:18:26 +0000
> ***************
> *** 6917,6923 ****
>           ;; can happen since we don't know if
>           ;; `c-restricted-<>-arglists' will be correct inside the
>           ;; arglist paren that gets entered.
> !         c-parse-and-markup-<>-arglists)
>
>         (goto-char id-start)
>
> --- 6917,6925 ----
>           ;; can happen since we don't know if
>           ;; `c-restricted-<>-arglists' will be correct inside the
>           ;; arglist paren that gets entered.
> !         c-parse-and-markup-<>-arglists
> !         ;; Start of the identifier for which `got-identifier' was set.
> !         name-start)
>
>         (goto-char id-start)
>
> ***************
> *** 6935,6941 ****
>                         ;; If the third submatch matches in C++ then
>                         ;; we're looking at an identifier that's a
>                         ;; prefix only if it specifies a member pointer.
> !                       (when (setq got-identifier (c-forward-name))
>                           (if (looking-at "\\(::\\)")
>                               ;; We only check for a trailing "::" and
>                               ;; let the "*" that should follow be
> --- 6937,6945 ----
>                         ;; If the third submatch matches in C++ then
>                         ;; we're looking at an identifier that's a
>                         ;; prefix only if it specifies a member pointer.
> !                       (when (progn (setq pos (point))
> !                                    (setq got-identifier
> (c-forward-name)))
> !                         (setq name-start pos)
>                           (if (looking-at "\\(::\\)")
>                               ;; We only check for a trailing "::" and
>                               ;; let the "*" that should follow be
> ***************
> *** 6961,6967 ****
>         ;; Skip over an identifier.
>         (or got-identifier
>           (and (looking-at c-identifier-start)
> !              (setq got-identifier (c-forward-name))))
>
>         ;; Skip over type decl suffix operators.
>         (while (if (looking-at c-type-decl-suffix-key)
> --- 6965,6973 ----
>         ;; Skip over an identifier.
>         (or got-identifier
>           (and (looking-at c-identifier-start)
> !              (setq pos (point))
> !              (setq got-identifier (c-forward-name))
> !              (setq name-start pos)))
>
>         ;; Skip over type decl suffix operators.
>         (while (if (looking-at c-type-decl-suffix-key)
> ***************
> *** 7052,7074 ****
>                 ;; declaration.
>                 (throw 'at-decl-or-cast t))
>
> -             (when (and got-parens
> -                        (not got-prefix)
> -                        (not got-suffix-after-parens)
> -                        (or backup-at-type
> -                            maybe-typeless
> -                            backup-maybe-typeless))
> -               ;; Got a declaration of the form "foo bar (gnu);" where
> we've
> -               ;; recognized "bar" as the type and "gnu" as the
> declarator.
> -               ;; In this case it's however more likely that "bar" is the
> -               ;; declarator and "gnu" a function argument or initializer
> (if
> -               ;; `c-recognize-paren-inits' is set), since the parens
> around
> -               ;; "gnu" would be superfluous if it's a declarator.  Shift
> the
> -               ;; type one step backward.
> -               (c-fdoc-shift-type-backward)))
>
> !         ;; Found no identifier.
>
>           (if backup-at-type
>               (progn
>
> --- 7058,7084 ----
>                 ;; declaration.
>                 (throw 'at-decl-or-cast t))
>
>
> !              (when (and got-parens
> !                         (not got-prefix)
> !                         ;; (not got-suffix-after-parens)
> !                         (or backup-at-type
> !                             maybe-typeless
> !                             backup-maybe-typeless
> !                             (eq at-decl-or-cast t)
> !                             (save-excursion
> !                               (goto-char name-start)
> !                               (not (memq (c-forward-type) '(nil
> maybe))))))
> !                ;; Got a declaration of the form "foo bar (gnu);" or "bar
> !                ;; (gnu);" where we've recognized "bar" as the type and
> "gnu"
> !                ;; as the declarator.  In this case it's however more
> likely
> !                ;; that "bar" is the declarator and "gnu" a function
> argument
> !                ;; or initializer (if `c-recognize-paren-inits' is set),
> !                ;; since the parens around "gnu" would be superfluous if
> it's
> !                ;; a declarator.  Shift the type one step backward.
> !                (c-fdoc-shift-type-backward)))
>
> +          ;; Found no identifier.
>           (if backup-at-type
>               (progn
>
>
>
>
>
> > -Ivan
>
> --
> Alan Mackenzie (Nuremberg, Germany).
>
[Message part 2 (text/html, inline)]

Reply sent to Alan Mackenzie <acm <at> muc.de>:
You have taken responsibility. (Sat, 19 Oct 2013 15:21:02 GMT) Full text and rfc822 format available.

Notification sent to Ivan Andrus <darthandrus <at> gmail.com>:
bug acknowledged by developer. (Sat, 19 Oct 2013 15:21:06 GMT) Full text and rfc822 format available.

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

From: Alan Mackenzie <acm <at> muc.de>
To: 15415-done <at> debbugs.gnu.org
Subject: Re: bug#15415: 24.3.50; c++-mode fontification for constructors is
 inconsistent
Date: Sat, 19 Oct 2013 15:18:30 +0000
Bug fixed.

-- 
Alan Mackenzie (Nuremberg, Germany).




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

This bug report was last modified 11 years and 221 days ago.

Previous Next


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