Subject: Re: 24.2; c functions recognition breaks on certain preprocessor macros

From: Alan Mackenzie <[email-masked]>
Date: Tue, 9 Apr 2013 21:06:21 +0000

Hi, Gauthier.

> Function coloring, c-beginning-of-defun and c-end-of-defun behaves
> strangely if the functions contain ifdef'd code.

More precisely, doing C-M-a from function_two goes to the beginning of
function_one.  I couldn't see any fault with the font locking, though.

> For example:
> void function_one(void)
> {
>     // Make the number of spaces before # vary.
>     #if defined(DEBUG)
>     trap();
>     #endif // DEBUG
> }
>
>
> void function_two(void)
> {
>     // doing nothing
> }

> The number of spaces that precede the macros seem to influence the
> strange behavior.

Actually, it is the prescence of spaces before the # which are triggering
the bug.

> It is quite easy to see if the current state is working or not: the
> identifier 'function_two' is not colored correctly when the function
> recognition fails.

I didn't see this.  Would you please try the patch below and let me know
how much it fixes and how much is still not working.  After applying the
patch, you MUST byte-compile cc-langs.el, cc-engine.el and cc-mode.el,
for it to work.  (Let me know if you have any trouble doing this.)

Thanks for taking the trouble to report the bug.  Here's the patch:

=== modified file 'lisp/progmodes/cc-langs.el'
*** lisp/progmodes/cc-langs.el	2013-03-05 17:13:01 +0000
--- lisp/progmodes/cc-langs.el	2013-04-09 20:36:25 +0000
***************
*** 812,819 ****
  (c-lang-defconst c-anchored-cpp-prefix
    "Regexp matching the prefix of a cpp directive anchored to BOL,
  in the languages that have a macro preprocessor."
!   t (if (c-lang-const c-opt-cpp-prefix)
! 	(concat "^" (c-lang-const c-opt-cpp-prefix))))
  (c-lang-defvar c-anchored-cpp-prefix (c-lang-const c-anchored-cpp-prefix))
  
  (c-lang-defconst c-opt-cpp-start
--- 812,819 ----
  (c-lang-defconst c-anchored-cpp-prefix
    "Regexp matching the prefix of a cpp directive anchored to BOL,
  in the languages that have a macro preprocessor."
!   t "^\\s *\\(#\\)\\s *"
!   (java awk) nil)
  (c-lang-defvar c-anchored-cpp-prefix (c-lang-const c-anchored-cpp-prefix))
  
  (c-lang-defconst c-opt-cpp-start

=== modified file 'lisp/progmodes/cc-mode.el'
*** lisp/progmodes/cc-mode.el	2013-01-02 16:13:04 +0000
--- lisp/progmodes/cc-mode.el	2013-04-09 20:39:18 +0000
***************
*** 936,942 ****
  
      ;; Add needed properties to each CPP construct in the region.
      (goto-char c-new-BEG)
!     (let ((pps-position c-new-BEG)  pps-state mbeg)
        (while (and (< (point) c-new-END)
  		  (search-forward-regexp c-anchored-cpp-prefix c-new-END t))
  	;; If we've found a "#" inside a string/comment, ignore it.
--- 936,943 ----
  
      ;; Add needed properties to each CPP construct in the region.
      (goto-char c-new-BEG)
!     (skip-chars-backward " \t")
!     (let ((pps-position (point))  pps-state mbeg)
        (while (and (< (point) c-new-END)
  		  (search-forward-regexp c-anchored-cpp-prefix c-new-END t))
  	;; If we've found a "#" inside a string/comment, ignore it.
***************
*** 945,958 ****
  	      pps-position (point))
  	(unless (or (nth 3 pps-state)	; in a string?
  		    (nth 4 pps-state))	; in a comment?
! 	  (goto-char (match-beginning 0))
  	  (setq mbeg (point))
  	  (if (> (c-syntactic-end-of-macro) mbeg)
  	      (progn
  		(c-neutralize-CPP-line mbeg (point))
! 		(c-set-cpp-delimiters mbeg (point))
! 		;(setq pps-position (point))
! 		)
  	    (forward-line))	      ; no infinite loop with, e.g., "#//"
  	  )))))
  
--- 946,957 ----
  	      pps-position (point))
  	(unless (or (nth 3 pps-state)	; in a string?
  		    (nth 4 pps-state))	; in a comment?
! 	  (goto-char (match-beginning 1))
  	  (setq mbeg (point))
  	  (if (> (c-syntactic-end-of-macro) mbeg)
  	      (progn
  		(c-neutralize-CPP-line mbeg (point))
! 		(c-set-cpp-delimiters mbeg (point)))
  	    (forward-line))	      ; no infinite loop with, e.g., "#//"
  	  )))))

-- 
Alan Mackenzie (Nuremberg, Germany).