Subject: bug#19134: 24.4.51; Error using mark-defun in c++-mode

From: Alan Mackenzie <[email-masked]>
Date: 22 Nov 2014 22:04:13 -0000

Hello again, Ivan.

In article <[email-masked]> you wrote:
> Starting from emacs -Q, create a buffer in `c++-mode' with contents below.

> class Bob
> {
> protected:

>    void fun()
>    {
>    }

> };

> Placing point on the line after "protected:" and running mark-defun gives
> the error:

> c-where-wrt-brace-construct: c-where-wrt-brace-construct: c-beginning-of-decl-1 returned label

Yes.  I've just pushed the following patch to the git repository:

diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el
index 5fa3b25..50cdd78 100644
--- a/lisp/progmodes/cc-cmds.el
+++ b/lisp/progmodes/cc-cmds.el
@@ -1417,12 +1417,15 @@ No indentation or other \"electric\" behavior is performed."
              (car (c-beginning-of-decl-1
                    ;; NOTE: If we're in a K&R region, this might be the start
                    ;; of a parameter declaration, not the actual function.
+                   ;; It might also leave us at a label or "label" like
+                   ;; "private:".
                    (and least-enclosing ; LIMIT for c-b-of-decl-1
                         (c-safe-position least-enclosing paren-state)))))

        ;; Has the declaration we've gone back to got braces?
-       (setq brace-decl-p
-             (save-excursion
+       (or (eq decl-result 'label)
+           (setq brace-decl-p
+                 (save-excursion
                    (and (c-syntactic-re-search-forward "[;{]" nil t t)
                         (or (eq (char-before) ?\{)
                             (and c-recognize-knr-p
@@ -1430,10 +1433,11 @@ No indentation or other \"electric\" behavior is performed."
                                  ;; ';' in a K&R argdecl.  In
                                  ;; that case the declaration
                                  ;; should contain a block.
-                                 (c-in-knr-argdecl))))))
+                                 (c-in-knr-argdecl)))))))

        (cond
-        ((= (point) kluge-start)       ; might be BOB or unbalanced parens.
+        ((or (eq decl-result 'label)   ; e.g. "private:" or invalid syntax.
+             (= (point) kluge-start))  ; might be BOB or unbalanced parens.
          'outwith-function)
         ((eq decl-result 'same)
          (if brace-decl-p

I think this should fix the problem.  Would you please test it with
`mark-defun' and confirm it works properly.  Thanks!

Incidentally, `c-mark-function' (the default binding for C-M-h in CC Mode)
doesn't do the right thing here.  I'll be looking into this.

> Ideally it would give no error, and IMO, it should mark fun(), though
> marking the class would be fine as well.

It marks the class, since it gives priority to defuns point is in, rather
than those which follow point.  There might be scope for some improvement
here.

Thanks for taking the trouble to distil the problem down to a nice, very
short piece of code, and for describing the problem so helpfully.

> -Ivan

-- 
Alan Mackenzie (Nuremberg, Germany).