Subject: CC Mode 5.35.1 (ObjC//l); Incorrect fontification of structs and enums

From: Po Lu <[email-masked]>
Date: Wed, 26 Oct 2022 20:51:48 +0800

Package: cc-mode

Go to src/nsfont.m in the master branch of Emacs's source repository.
Notice every "enum gs_font_xxx" and "struct gs_font_data" identifier is
fontified as a type.  Here are some examples:

struct gs_font_data
{
  int specified;
  enum gs_font_slant slant;
  enum gs_font_weight weight;
  enum gs_font_width width;
  bool monospace_p;
  char *family_name;
};

here, slant, weight and width are fontified as types.

static void
ns_done_font_data (struct gs_font_data *data)
{
  if (data->specified & GS_SPECIFIED_FAMILY)
    xfree (data->family_name);
}

here, data is fontified as a type.

static void
ns_get_font_data (NSFontDescriptor *desc, struct gs_font_data *dat)
{
  NSNumber *tem;
  NSFontSymbolicTraits traits = [desc symbolicTraits];
  NSDictionary *dict = [desc objectForKey: NSFontTraitsAttribute];
  NSString *family = [desc objectForKey: NSFontFamilyAttribute];

  dat->specified = 0;

  if (family != nil)
    {
      dat->specified |= GS_SPECIFIED_FAMILY;
      dat->family_name = xstrdup ([family cStringUsingEncoding: NSUTF8StringEncoding]);
    }

  tem = [desc objectForKey: NSFontFixedAdvanceAttribute];

  if ((tem != nil && [tem boolValue] != NO)
      || (traits & NSFontMonoSpaceTrait))
    {
      dat->specified |= GS_SPECIFIED_SPACING;
      dat->monospace_p = true;
    }
  else if (tem != nil && [tem boolValue] == NO)
    {
      dat->specified |= GS_SPECIFIED_SPACING;
      dat->monospace_p = false;
    }

  if (traits & NSFontBoldTrait)
    {
      dat->specified |= GS_SPECIFIED_WEIGHT;
      dat->weight = GS_FONT_WEIGHT_BOLD;
    }

  if (traits & NSFontItalicTrait)
    {
      dat->specified |= GS_SPECIFIED_SLANT;
      dat->slant = GS_FONT_SLANT_ITALIC;
    }

  if (traits & NSFontCondensedTrait)
    {
      dat->specified |= GS_SPECIFIED_WIDTH;
      dat->width = GS_FONT_WIDTH_CONDENSED;
    }
  else if (traits & NSFontExpandedTrait)
    {
      dat->specified |= GS_SPECIFIED_WIDTH;
      dat->width = GS_FONT_WIDTH_EXPANDED;
    }

  if (dict != nil)
    {
      tem = [dict objectForKey: NSFontSlantTrait];

      if (tem != nil)
	{
	  dat->specified |= GS_SPECIFIED_SLANT;

	  dat->slant = [tem floatValue] > 0
	    ? GS_FONT_SLANT_ITALIC
	    : ([tem floatValue] < 0
	       ? GS_FONT_SLANT_REVERSE_ITALIC
	       : GS_FONT_SLANT_NORMAL);
	}

      tem = [dict objectForKey: NSFontWeightTrait];

      if (tem != nil)
	{
	  dat->specified |= GS_SPECIFIED_WEIGHT;

	  dat->weight = [tem floatValue] > 0
	    ? GS_FONT_WEIGHT_BOLD
	    : ([tem floatValue] < -0.4f
	       ? GS_FONT_WEIGHT_LIGHT
	       : GS_FONT_WEIGHT_NORMAL);
	}

      tem = [dict objectForKey: NSFontWidthTrait];

      if (tem != nil)
	{
	  dat->specified |= GS_SPECIFIED_WIDTH;

	  dat->width = [tem floatValue] > 0
	    ? GS_FONT_WIDTH_EXPANDED
	    : ([tem floatValue] < 0
	       ? GS_FONT_WIDTH_NORMAL
	       : GS_FONT_WIDTH_CONDENSED);
	}
    }
}

here, "dat" is fontified as a type.

static bool
ns_font_descs_match_p (NSFontDescriptor *desc, NSFontDescriptor *target)
{
  struct gs_font_data dat;
  struct gs_font_data t;

  ns_get_font_data (desc, &dat);
  ns_get_font_data (target, &t);

  if (!(t.specified & GS_SPECIFIED_WIDTH))
    t.width = GS_FONT_WIDTH_NORMAL;
  if (!(t.specified & GS_SPECIFIED_WEIGHT))
    t.weight = GS_FONT_WEIGHT_NORMAL;
  if (!(t.specified & GS_SPECIFIED_SPACING))
    t.monospace_p = false;
  if (!(t.specified & GS_SPECIFIED_SLANT))
    t.slant = GS_FONT_SLANT_NORMAL;

  if (!(t.specified & GS_SPECIFIED_FAMILY))
    emacs_abort ();

  bool match_p = true;

  if (dat.specified & GS_SPECIFIED_WIDTH
      && dat.width != t.width)
    {
      match_p = false;
      goto gout;
    }

  if (dat.specified & GS_SPECIFIED_WEIGHT
      && dat.weight != t.weight)
    {
      match_p = false;
      goto gout;
    }

  if (dat.specified & GS_SPECIFIED_SPACING
      && dat.monospace_p != t.monospace_p)
    {
      match_p = false;
      goto gout;
    }

  if (dat.specified & GS_SPECIFIED_SLANT
      && dat.monospace_p != t.monospace_p)
    {
      if (NSFONT_TRACE)
	printf ("Matching monospace for %s: %d %d\n",
		t.family_name, dat.monospace_p,
		t.monospace_p);
      match_p = false;
      goto gout;
    }

  if (dat.specified & GS_SPECIFIED_FAMILY
      && strcmp (dat.family_name, t.family_name))
    match_p = false;

 gout:
  ns_done_font_data (&dat);
  ns_done_font_data (&t);

  return match_p;
}

here, "dat" and "t" are fontified as types.  However, if part of this
function definition is not visible and is later scrolled into the
window, "dat" and "t" will not be fontified as types in that newly
visible part.

Emacs  : GNU Emacs 29.0.50 (build 7, x86_64-pc-linux-gnu, NS gnustep-gui-0.29.0)
 of 2022-10-26
Package: CC Mode 5.35.1 (ObjC//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 'objc-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 "[ 	]*\\(//+\\|\\**\\)[ 	]*\\([ 	]*\\([-–!|#%;>*·•‣⁃◦]+[ 	]*\\)*\\)"
 )