From: Alan Mackenzie <acm@muc.de>
To: Ivan Andrus <darthandrus@gmail.com>
Cc: 15415@debbugs.gnu.org
Subject: bug#15415: 24.3.50; c++-mode fontification for constructors is inconsistent
Date: Sat, 12 Oct 2013 20:45:43 +0000 [thread overview]
Message-ID: <20131012204542.GA3690@acm.acm> (raw)
In-Reply-To: <160417FD-FE6F-4C7F-AEC5-CEFD09ABE113@gmail.com>
Hello, Ivan.
On Sun, Sep 29, 2013 at 09:31:13PM -0600, Ivan Andrus wrote:
> Ivan Andrus <darthandrus@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).
next prev parent reply other threads:[~2013-10-12 20:45 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-19 2:44 bug#15415: 24.3.50; c++-mode fontification for constructors is inconsistent Ivan Andrus
2013-09-30 3:31 ` Ivan Andrus
2013-10-12 20:45 ` Alan Mackenzie [this message]
2013-10-18 22:00 ` Ivan Andrus
2013-10-19 15:18 ` Alan Mackenzie
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20131012204542.GA3690@acm.acm \
--to=acm@muc.de \
--cc=15415@debbugs.gnu.org \
--cc=darthandrus@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this external index
https://git.savannah.gnu.org/cgit/emacs.git
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.