]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/cc-engine.el
(gnus-newsrc-file-version): Add defvar.
[gnu-emacs] / lisp / progmodes / cc-engine.el
index 0abb5121d5bea600651dab1c5920829328f828e3..71dc39a56e90aac7a0538fd12173e28970d6c3d4 100644 (file)
@@ -1,6 +1,6 @@
 ;;; cc-engine.el --- core syntax guessing engine for CC mode
 
-;; Copyright (C) 1985,1987,1992-2003 Free Software Foundation, Inc.
+;; Copyright (C) 1985,1987,1992-2003, 2004, 2005 Free Software Foundation, Inc.
 
 ;; Authors:    1998- Martin Stjernholm
 ;;             1992-1999 Barry A. Warsaw
@@ -24,9 +24,9 @@
 ;; GNU General Public License for more details.
 
 ;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs; see the file COPYING.  If not, write to
-;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; along with this program; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 (defvar c-type-decl-end-used nil)
 (make-variable-buffer-local 'c-type-decl-end-used)
 
+\f
+;; Basic handling of preprocessor directives.
+
+;; This is a dynamically bound cache used together with
+;; `c-query-macro-start' and `c-query-and-set-macro-start'.  It only
+;; works as long as point doesn't cross a macro boundary.
+(defvar c-macro-start 'unknown)
+
+(defsubst c-query-and-set-macro-start ()
+  ;; This function does not do any hidden buffer changes.
+  (if (symbolp c-macro-start)
+      (setq c-macro-start (save-excursion
+                           (and (c-beginning-of-macro)
+                                (point))))
+    c-macro-start))
+
+(defsubst c-query-macro-start ()
+  ;; This function does not do any hidden buffer changes.
+  (if (symbolp c-macro-start)
+      (save-excursion
+       (and (c-beginning-of-macro)
+            (point)))
+    c-macro-start))
+
+(defun c-beginning-of-macro (&optional lim)
+  "Go to the beginning of a preprocessor directive.
+Leave point at the beginning of the directive and return t if in one,
+otherwise return nil and leave point unchanged.
+
+This function does not do any hidden buffer changes."
+  (when c-opt-cpp-prefix
+    (let ((here (point)))
+      (save-restriction
+       (if lim (narrow-to-region lim (point-max)))
+       (beginning-of-line)
+       (while (eq (char-before (1- (point))) ?\\)
+         (forward-line -1))
+       (back-to-indentation)
+       (if (and (<= (point) here)
+                (looking-at c-opt-cpp-start))
+           t
+         (goto-char here)
+         nil)))))
+
+(defun c-end-of-macro ()
+  "Go to the end of a preprocessor directive.
+More accurately, move point to the end of the closest following line
+that doesn't end with a line continuation backslash.
+
+This function does not do any hidden buffer changes."
+  (while (progn
+          (end-of-line)
+          (when (and (eq (char-before) ?\\)
+                     (not (eobp)))
+            (forward-char)
+            t))))
+
+(defun c-forward-to-cpp-define-body ()
+  ;; Assuming point is at the "#" that introduces a preprocessor
+  ;; directive, it's moved forward to the start of the definition body
+  ;; if it's a "#define".  Non-nil is returned in this case, in all
+  ;; other cases nil is returned and point isn't moved.
+  (when (and (looking-at
+             (concat "#[ \t]*"
+                     "define[ \t]+\\(\\sw\\|_\\)+\\(\([^\)]*\)\\)?"
+                     "\\([ \t]\\|\\\\\n\\)*"))
+            (not (= (match-end 0) (c-point 'eol))))
+    (goto-char (match-end 0))))
+
 \f
 ;;; Basic utility functions.
 
 ;; locking is in use.  This variable is extended with the face in
 ;; `c-doc-face-name' when fontification is activated in cc-fonts.el.
 (defvar c-literal-faces
-  '(font-lock-comment-face font-lock-string-face))
+  '(font-lock-comment-face font-lock-string-face
+                          font-lock-comment-delimiter-face))
+
+(defun c-shift-line-indentation (shift-amt)
+  ;; This function does not do any hidden buffer changes.
+  (let ((pos (- (point-max) (point)))
+       (c-macro-start c-macro-start)
+       tmp-char-inserted)
+    (if (zerop shift-amt)
+       nil
+      (when (and (c-query-and-set-macro-start)
+                (looking-at "[ \t]*\\\\$")
+                (save-excursion
+                  (skip-chars-backward " \t")
+                  (bolp)))
+       (insert ?x)
+       (backward-char)
+       (setq tmp-char-inserted t))
+      (unwind-protect
+         (let ((col (current-indentation)))
+           (delete-region (c-point 'bol) (c-point 'boi))
+           (beginning-of-line)
+           (indent-to (+ col shift-amt)))
+       (when tmp-char-inserted
+         (delete-char 1))))
+    ;; If initial point was within line's indentation and we're not on
+    ;; a line with a line continuation in a macro, position after the
+    ;; indentation.  Else stay at same point in text.
+    (if (and (< (point) (c-point 'boi))
+            (not tmp-char-inserted))
+       (back-to-indentation)
+      (if (> (- (point-max) pos) (point))
+         (goto-char (- (point-max) pos))))))
 
 \f
 ;; Some debug tools to visualize various special positions.  This
@@ -592,7 +693,7 @@ COMMA-DELIM is non-nil then ',' is treated likewise."
 
                ;; The PDA state handling.
                 ;;
-                ;; Refer to the description of the PDA in the openining
+                ;; Refer to the description of the PDA in the opening
                 ;; comments.  In the following OR form, the first leaf
                 ;; attempts to handles one of the specific actions detailed
                 ;; (e.g., finding token "if" whilst in state `else-boundary').
@@ -769,7 +870,9 @@ COMMA-DELIM is non-nil then ',' is treated likewise."
                        sym 'boundary)
                  (throw 'loop t))) ; like a C "continue".  Analyze the next sexp.
 
-             (when (and (numberp c-maybe-labelp) (not ignore-labels))
+             (when (and (numberp c-maybe-labelp)
+                        (not ignore-labels)
+                        (not (looking-at "\\s\(")))
                ;; c-crosses-statement-barrier-p has found a colon, so
                ;; we might be in a label now.
                (if (not after-labels-pos)
@@ -1011,75 +1114,6 @@ This function does not do any hidden buffer changes."
                (backward-char)
                t))))))
 
-\f
-;; Basic handling of preprocessor directives.
-
-;; This is a dynamically bound cache used together with
-;; `c-query-macro-start' and `c-query-and-set-macro-start'.  It only
-;; works as long as point doesn't cross a macro boundary.
-(defvar c-macro-start 'unknown)
-
-(defsubst c-query-and-set-macro-start ()
-  ;; This function does not do any hidden buffer changes.
-  (if (symbolp c-macro-start)
-      (setq c-macro-start (save-excursion
-                           (and (c-beginning-of-macro)
-                                (point))))
-    c-macro-start))
-
-(defsubst c-query-macro-start ()
-  ;; This function does not do any hidden buffer changes.
-  (if (symbolp c-macro-start)
-      (save-excursion
-       (and (c-beginning-of-macro)
-            (point)))
-    c-macro-start))
-
-(defun c-beginning-of-macro (&optional lim)
-  "Go to the beginning of a preprocessor directive.
-Leave point at the beginning of the directive and return t if in one,
-otherwise return nil and leave point unchanged.
-
-This function does not do any hidden buffer changes."
-  (when c-opt-cpp-prefix
-    (let ((here (point)))
-      (save-restriction
-       (if lim (narrow-to-region lim (point-max)))
-       (beginning-of-line)
-       (while (eq (char-before (1- (point))) ?\\)
-         (forward-line -1))
-       (back-to-indentation)
-       (if (and (<= (point) here)
-                (looking-at c-opt-cpp-start))
-           t
-         (goto-char here)
-         nil)))))
-
-(defun c-end-of-macro ()
-  "Go to the end of a preprocessor directive.
-More accurately, move point to the end of the closest following line
-that doesn't end with a line continuation backslash.
-
-This function does not do any hidden buffer changes."
-  (while (progn
-          (end-of-line)
-          (when (and (eq (char-before) ?\\)
-                     (not (eobp)))
-            (forward-char)
-            t))))
-
-(defun c-forward-to-cpp-define-body ()
-  ;; Assuming point is at the "#" that introduces a preprocessor
-  ;; directive, it's moved forward to the start of the definition body
-  ;; if it's a "#define".  Non-nil is returned in this case, in all
-  ;; other cases nil is returned and point isn't moved.
-  (when (and (looking-at
-             (concat "#[ \t]*"
-                     "define[ \t]+\\(\\sw\\|_\\)+\\(\([^\)]*\)\\)?"
-                     "\\([ \t]\\|\\\\\n\\)*"))
-            (not (= (match-end 0) (c-point 'eol))))
-    (goto-char (match-end 0))))
-
 \f
 ;; Tools for skipping over syntactic whitespace.
 
@@ -1237,7 +1271,7 @@ This function does not do any hidden buffer changes."
 
   (when (and (= beg end)
             (get-text-property beg 'c-in-sws)
-            (not (bobp))
+            (> beg (point-min))
             (get-text-property (1- beg) 'c-in-sws))
     ;; Ensure that an `c-in-sws' range gets broken.  Note that it isn't
     ;; safe to keep a range that was continuous before the change.  E.g:
@@ -1740,10 +1774,10 @@ This function does not do any hidden buffer changes."
            ;; If point-min has moved forward then we just need to cut
            ;; off a bit of the tail.
            (let ((ptr (cons nil c-state-cache)) elem)
-             (while (and (setq elem (cdr ptr))
+             (while (and (setq elem (car-safe (cdr ptr)))
                          (>= (if (consp elem) (car elem) elem)
                              (point-min)))
-               (setq ptr elem))
+               (setq ptr (cdr ptr)))
              (when (consp ptr)
                (if (eq (cdr ptr) c-state-cache)
                    (setq c-state-cache nil)
@@ -1873,7 +1907,7 @@ This function does not do any hidden buffer changes."
        (if last-pos
            ;; Prepare to loop, but record the open paren only if it's
            ;; outside a macro or within the same macro as point, and
-           ;; if it is a "real" open paren and not some character
+           ;; if it is a legitimate open paren and not some character
            ;; that got an open paren syntax-table property.
            (progn
              (setq pos last-pos)
@@ -1881,7 +1915,11 @@ This function does not do any hidden buffer changes."
                           (save-excursion
                             (goto-char last-pos)
                             (not (c-beginning-of-macro))))
-                      (= (char-syntax (char-before last-pos)) ?\())
+                      ;; Check for known types of parens that we want
+                      ;; to record.  The syntax table is not to be
+                      ;; trusted here since the caller might be using
+                      ;; e.g. `c++-template-syntax-table'.
+                      (memq (char-before last-pos) '(?{ ?\( ?\[)))
                  (setq c-state-cache (cons (1- last-pos) c-state-cache))))
 
          (if (setq last-pos (c-up-list-forward pos))
@@ -2091,7 +2129,7 @@ This function does not do any hidden buffer changes."
        (when (c-major-mode-is 'pike-mode)
          ;; Handle the `<operator> syntax in Pike.
          (let ((pos (point)))
-           (skip-chars-backward "!%&*+\\-/<=>^|~[]()")
+           (skip-chars-backward "-!%&*+/<=>^|~[]()")
            (and (if (< (skip-chars-backward "`") 0)
                     t
                   (goto-char pos)
@@ -2111,7 +2149,7 @@ This function does not do any hidden buffer changes."
       (and (c-major-mode-is 'pike-mode)
           ;; Handle the `<operator> syntax in Pike.
           (let ((pos (point)))
-            (if (and (< (skip-chars-backward "!%&*+\\-/<=>^|~[]()") 0)
+            (if (and (< (skip-chars-backward "-!%&*+/<=>^|~[]()") 0)
                      (< (skip-chars-backward "`") 0)
                      (looking-at c-symbol-key)
                      (>= (match-end 0) pos))
@@ -2351,8 +2389,11 @@ outside any comment, macro or string literal, or else the content of
 that region is taken as syntactically significant text.
 
 If PAREN-LEVEL is non-nil, an additional restriction is added to
-ignore matches in nested paren sexps, and the search will also not go
-outside the current paren sexp.
+ignore matches in nested paren sexps.  The search will also not go
+outside the current list sexp, which has the effect that if the point
+should be moved to BOUND when no match is found \(i.e. NOERROR is
+neither nil nor t), then it will be at the closing paren if the end of
+the current list sexp is encountered first.
 
 If NOT-INSIDE-TOKEN is non-nil, matches in the middle of tokens are
 ignored.  Things like multicharacter operators and special symbols
@@ -2368,11 +2409,15 @@ subexpression is never tested before the starting position, so it
 might be a good idea to include \\=\\= as a match alternative in it.
 
 Optimization note: Matches might be missed if the \"look behind\"
-subexpression should match the end of nonwhite syntactic whitespace,
+subexpression can match the end of nonwhite syntactic whitespace,
 i.e. the end of comments or cpp directives.  This since the function
-skips over such things before resuming the search.  It's also not safe
-to assume that the \"look behind\" subexpression never can match
-syntactic whitespace."
+skips over such things before resuming the search.  It's on the other
+hand not safe to assume that the \"look behind\" subexpression never
+matches syntactic whitespace.
+
+Bug: Unbalanced parens inside cpp directives are currently not handled
+correctly \(i.e. they don't get ignored as they should) when
+PAREN-LEVEL is set."
 
   (or bound (setq bound (point-max)))
   (if paren-level (setq paren-level -1))
@@ -2380,53 +2425,55 @@ syntactic whitespace."
   ;;(message "c-syntactic-re-search-forward %s %s %S" (point) bound regexp)
 
   (let ((start (point))
-       (pos (point))
+       tmp
+       ;; Start position for the last search.
+       search-pos
+       ;; The `parse-partial-sexp' state between the start position
+       ;; and the point.
+       state
+       ;; The current position after the last state update.  The next
+       ;; `parse-partial-sexp' continues from here.
+       (state-pos (point))
+       ;; The position at which to check the state and the state
+       ;; there.  This is separate from `state-pos' since we might
+       ;; need to back up before doing the next search round.
+       check-pos check-state
+       ;; Last position known to end a token.
        (last-token-end-pos (point-min))
-       match-pos found state check-pos check-state tmp)
+       ;; Set when a valid match is found.
+       found)
 
     (condition-case err
        (while
            (and
-            (re-search-forward regexp bound noerror)
+            (progn
+              (setq search-pos (point))
+              (re-search-forward regexp bound noerror))
 
             (progn
-              (setq match-pos (point)
-                    state (parse-partial-sexp
-                           pos (match-beginning 0) paren-level nil state)
-                    pos (point))
+              (setq state (parse-partial-sexp
+                           state-pos (match-beginning 0) paren-level nil state)
+                    state-pos (point))
               (if (setq check-pos (and lookbehind-submatch
+                                       (or (not paren-level)
+                                           (>= (car state) 0))
                                        (match-end lookbehind-submatch)))
                   (setq check-state (parse-partial-sexp
-                                     pos check-pos paren-level nil state))
-                (setq check-pos pos
+                                     state-pos check-pos paren-level nil state))
+                (setq check-pos state-pos
                       check-state state))
 
-              ;; If we got a look behind subexpression and get an
-              ;; insignificant match in something that isn't
+              ;; NOTE: If we got a look behind subexpression and get
+              ;; an insignificant match in something that isn't
               ;; syntactic whitespace (i.e. strings or in nested
               ;; parentheses), then we can never skip more than a
-              ;; single character from the match position before
-              ;; continuing the search.  That since the look behind
-              ;; subexpression might match the end of the
-              ;; insignificant region.
+              ;; single character from the match start position
+              ;; (i.e. `state-pos' here) before continuing the
+              ;; search.  That since the look behind subexpression
+              ;; might match the end of the insignificant region in
+              ;; the next search.
 
               (cond
-               ((setq tmp (elt check-state 3))
-                ;; Match inside a string.
-                (if (or lookbehind-submatch
-                        (not (integerp tmp)))
-                    (goto-char (min (1+ pos) bound))
-                  ;; Skip to the end of the string before continuing.
-                  (let ((ender (make-string 1 tmp)) (continue t))
-                    (while (if (search-forward ender bound noerror)
-                               (progn
-                                 (setq state (parse-partial-sexp
-                                              pos (point) nil nil state)
-                                       pos (point))
-                                 (elt state 3))
-                             (setq continue nil)))
-                    continue)))
-
                ((elt check-state 7)
                 ;; Match inside a line comment.  Skip to eol.  Use
                 ;; `re-search-forward' instead of `skip-chars-forward' to get
@@ -2439,6 +2486,7 @@ syntactic whitespace."
 
                ((and (not (elt check-state 5))
                      (eq (char-before check-pos) ?/)
+                     (not (c-get-char-property (1- check-pos) 'syntax-table))
                      (memq (char-after check-pos) '(?/ ?*)))
                 ;; Match in the middle of the opener of a block or line
                 ;; comment.
@@ -2446,19 +2494,57 @@ syntactic whitespace."
                     (re-search-forward "[\n\r]" bound noerror)
                   (search-forward "*/" bound noerror)))
 
-               ((and not-inside-token
-                     (or (< check-pos last-token-end-pos)
-                         (< check-pos
-                            (save-excursion
-                              (goto-char check-pos)
-                              (c-end-of-current-token last-token-end-pos)
-                              (setq last-token-end-pos (point))))))
-                ;; Match inside a token.
-                (cond ((<= (point) bound)
-                       (goto-char (min (1+ pos) bound))
-                       t)
-                      (noerror nil)
-                      (t (signal 'search-failed "end of token"))))
+               ;; The last `parse-partial-sexp' above might have
+               ;; stopped short of the real check position if the end
+               ;; of the current sexp was encountered in paren-level
+               ;; mode.  The checks above are always false in that
+               ;; case, and since they can do better skipping in
+               ;; lookbehind-submatch mode, we do them before
+               ;; checking the paren level.
+
+               ((and paren-level
+                     (/= (setq tmp (car check-state)) 0))
+                ;; Check the paren level first since we're short of the
+                ;; syntactic checking position if the end of the
+                ;; current sexp was encountered by `parse-partial-sexp'.
+                (if (> tmp 0)
+
+                    ;; Inside a nested paren sexp.
+                    (if lookbehind-submatch
+                        ;; See the NOTE above.
+                        (progn (goto-char state-pos) t)
+                      ;; Skip out of the paren quickly.
+                      (setq state (parse-partial-sexp state-pos bound 0 nil state)
+                            state-pos (point)))
+
+                  ;; Have exited the current paren sexp.
+                  (if noerror
+                      (progn
+                        ;; The last `parse-partial-sexp' call above
+                        ;; has left us just after the closing paren
+                        ;; in this case, so we can modify the bound
+                        ;; to leave the point at the right position
+                        ;; upon return.
+                        (setq bound (1- (point)))
+                        nil)
+                    (signal 'search-failed (list regexp)))))
+
+               ((setq tmp (elt check-state 3))
+                ;; Match inside a string.
+                (if (or lookbehind-submatch
+                        (not (integerp tmp)))
+                    ;; See the NOTE above.
+                    (progn (goto-char state-pos) t)
+                  ;; Skip to the end of the string before continuing.
+                  (let ((ender (make-string 1 tmp)) (continue t))
+                    (while (if (search-forward ender bound noerror)
+                               (progn
+                                 (setq state (parse-partial-sexp
+                                              state-pos (point) nil nil state)
+                                       state-pos (point))
+                                 (elt state 3))
+                             (setq continue nil)))
+                    continue)))
 
                ((save-excursion
                   (save-match-data
@@ -2467,48 +2553,52 @@ syntactic whitespace."
                 (c-end-of-macro)
                 (cond ((<= (point) bound) t)
                       (noerror nil)
-                      (t (signal 'search-failed "end of macro"))))
+                      (t (signal 'search-failed (list regexp)))))
 
-               ((and paren-level
-                     (/= (setq tmp (car check-state)) 0))
-                (if (> tmp 0)
-                    ;; Match inside a nested paren sexp.
-                    (if lookbehind-submatch
-                        (goto-char (min (1+ pos) bound))
-                      ;; Skip out of the paren quickly.
-                      (setq state (parse-partial-sexp pos bound 0 nil state)
-                            pos (point)))
-                  ;; Have exited the current paren sexp.  The
-                  ;; `parse-partial-sexp' above has left us just after the
-                  ;; closing paren in this case.  Just make
-                  ;; `re-search-forward' above fail in the appropriate way;
-                  ;; we'll adjust the leave off point below if necessary.
-                  (setq bound (point))))
+               ((and not-inside-token
+                     (or (< check-pos last-token-end-pos)
+                         (< check-pos
+                            (save-excursion
+                              (goto-char check-pos)
+                              (save-match-data
+                                (c-end-of-current-token last-token-end-pos))
+                              (setq last-token-end-pos (point))))))
+                ;; Inside a token.
+                (if lookbehind-submatch
+                    ;; See the NOTE above.
+                    (goto-char state-pos)
+                  (goto-char (min last-token-end-pos bound))))
 
                (t
                 ;; A real match.
                 (setq found t)
-                nil)))))
+                nil)))
+
+            ;; Should loop to search again, but take care to avoid
+            ;; looping on the same spot.
+            (or (/= search-pos (point))
+                (if (= (point) bound)
+                    (if noerror
+                        nil
+                      (signal 'search-failed (list regexp)))
+                  (forward-char)
+                  t))))
 
       (error
        (goto-char start)
        (signal (car err) (cdr err))))
 
-    ;;(message "c-syntactic-re-search-forward done %s" (or match-pos (point)))
+    ;;(message "c-syntactic-re-search-forward done %s" (or (match-end 0) (point)))
 
     (if found
        (progn
-         (goto-char match-pos)
-         match-pos)
+         (goto-char (match-end 0))
+         (match-end 0))
 
       ;; Search failed.  Set point as appropriate.
-      (cond ((eq noerror t)
-            (goto-char start))
-           (paren-level
-            (if (eq (car (parse-partial-sexp pos bound -1 nil state)) -1)
-                (backward-char)))
-           (t
-            (goto-char bound)))
+      (if (eq noerror t)
+         (goto-char start)
+       (goto-char bound))
       nil)))
 
 (defun c-syntactic-skip-backward (skip-chars &optional limit)
@@ -2516,9 +2606,7 @@ syntactic whitespace."
 i.e. don't stop at positions inside syntactic whitespace or string
 literals.  Preprocessor directives are also ignored, with the exception
 of the one that the point starts within, if any.  If LIMIT is given,
-it's assumed to be at a syntactically relevant position.
-
-This function does not do any hidden buffer changes."
+it's assumed to be at a syntactically relevant position."
 
   (let ((start (point))
        ;; A list of syntactically relevant positions in descending
@@ -3110,6 +3198,7 @@ This function does not do any hidden buffer changes."
       ;; when font-lock refontifies the current line only.
       (when (save-excursion
              (and (= (forward-line 1) 0)
+                  (bolp)               ; forward-line has funny behavior at eob.
                   (or (< (c-point 'eol) cfd-limit)
                       (progn (backward-char)
                              (not (eq (char-before) ?\\))))))
@@ -3351,9 +3440,20 @@ This function does not do any hidden buffer changes."
 (defvar c-promote-possible-types nil)
 
 ;; Dynamically bound variable that instructs `c-forward-<>-arglist' to
-;; not accept arglists that contain more than one argument.  It's used
-;; to handle ambiguous cases like "foo (a < b, c > d)" better.
-(defvar c-disallow-comma-in-<>-arglists nil)
+;; not accept arglists that contain binary operators.
+;;
+;; This is primarily used to handle C++ template arglists.  C++
+;; disambiguates them by checking whether the preceding name is a
+;; template or not.  We can't do that, so we assume it is a template
+;; if it can be parsed as one.  That usually works well since
+;; comparison expressions on the forms "a < b > c" or "a < b, c > d"
+;; in almost all cases would be pointless.
+;;
+;; However, in function arglists, e.g. in "foo (a < b, c > d)", we
+;; should let the comma separate the function arguments instead.  And
+;; in a context where the value of the expression is taken, e.g. in
+;; "if (a < b || c > d)", it's probably not a template.
+(defvar c-restricted-<>-arglists nil)
 
 ;; Dynamically bound variables that instructs `c-forward-name',
 ;; `c-forward-type' and `c-forward-<>-arglist' to record the ranges of
@@ -3494,13 +3594,13 @@ This function does not do any hidden buffer changes."
             (eq (char-after) ?<)
             (c-forward-<>-arglist (c-keyword-member kwd-sym 'c-<>-type-kwds)
                                   (or c-record-type-identifiers
-                                      c-disallow-comma-in-<>-arglists)))
+                                      c-restricted-<>-arglists)))
        (c-forward-syntactic-ws)
        (setq safe-pos (point)))
 
        ((and (c-keyword-member kwd-sym 'c-nonsymbol-sexp-kwds)
-            (not (looking-at c-symbol-start)))
-       (c-forward-sexp)
+            (not (looking-at c-symbol-start))
+            (c-safe (c-forward-sexp) t))
        (c-forward-syntactic-ws)
        (setq safe-pos (point))))
 
@@ -3543,16 +3643,7 @@ This function does not do any hidden buffer changes."
   ;; necessary if the various side effects, e.g. recording of type
   ;; ranges, are important.  Setting REPARSE to t only applies
   ;; recursively to nested angle bracket arglists if
-  ;; `c-disallow-comma-in-<>-arglists' is set.
-  ;;
-  ;; This is primarily used in C++ to mark up template arglists.  C++
-  ;; disambiguates them by checking whether the preceding name is a
-  ;; template or not.  We can't do that, so we assume it is a template
-  ;; if it can be parsed as one.  This usually works well since
-  ;; comparison expressions on the forms "a < b > c" or "a < b, c > d"
-  ;; in almost all cases would be pointless.  Cases like function
-  ;; calls on the form "foo (a < b, c > d)" needs to be handled
-  ;; specially through the `c-disallow-comma-in-<>-arglists' variable.
+  ;; `c-restricted-<>-arglists' is set.
 
   (let ((start (point))
        ;; If `c-record-type-identifiers' is set then activate
@@ -3683,11 +3774,18 @@ This function does not do any hidden buffer changes."
                        (forward-char)
                        t)
 
-                     ;; Note: This regexp exploits the match order in
-                     ;; \| so that "<>" is matched by "<" rather than
-                     ;; "[^>:-]>".
+                     ;; Note: These regexps exploit the match order in \| so
+                     ;; that "<>" is matched by "<" rather than "[^>:-]>".
                      (c-syntactic-re-search-forward
-                      "[<;{},]\\|\\([^>:-]>\\)" nil 'move t t 1)
+                      (if c-restricted-<>-arglists
+                          ;; Stop on ',', '|', '&', '+' and '-' to catch
+                          ;; common binary operators that could be between
+                          ;; two comparison expressions "a<b" and "c>d".
+                          "[<;{},|&+-]\\|\\([^>:-]>\\)"
+                        ;; Otherwise we still stop on ',' to find the
+                        ;; argument start positions.
+                        "[<;{},]\\|\\([^>:-]>\\)")
+                      nil 'move t t 1)
 
                      ;; If the arglist starter has lost its open paren
                      ;; syntax but not the closer, we won't find the
@@ -3776,7 +3874,7 @@ This function does not do any hidden buffer changes."
                                           (c-keyword-sym (match-string 1))
                                           'c-<>-type-kwds))
                                     (and reparse
-                                         c-disallow-comma-in-<>-arglists))))
+                                         c-restricted-<>-arglists))))
                            )))
 
                        ;; It was not an angle bracket arglist.
@@ -3812,7 +3910,7 @@ This function does not do any hidden buffer changes."
                  t)
 
                 ((and (eq (char-before) ?,)
-                      (not c-disallow-comma-in-<>-arglists))
+                      (not c-restricted-<>-arglists))
                  ;; Just another argument.  Record the position.  The
                  ;; type check stuff that made us stop at it is at
                  ;; the top of the loop.
@@ -3959,7 +4057,7 @@ This function does not do any hidden buffer changes."
               (when (let ((c-record-type-identifiers nil)
                           (c-record-found-types nil))
                       (c-forward-<>-arglist
-                       nil c-disallow-comma-in-<>-arglists))
+                       nil c-restricted-<>-arglists))
                 (c-forward-syntactic-ws)
                 (setq pos (point))
                 (if (and c-opt-identifier-concat-key
@@ -3989,12 +4087,13 @@ This function does not do any hidden buffer changes."
 (defun c-forward-type ()
   ;; Move forward over a type spec if at the beginning of one,
   ;; stopping at the next following token.  Return t if it's a known
-  ;; type that can't be a name, 'known if it's an otherwise known type
-  ;; (according to `*-font-lock-extra-types'), 'prefix if it's a known
-  ;; prefix of a type, 'found if it's a type that matches one in
-  ;; `c-found-types', 'maybe if it's an identfier that might be a
-  ;; type, or nil if it can't be a type (the point isn't moved then).
-  ;; The point is assumed to be at the beginning of a token.
+  ;; type that can't be a name or other expression, 'known if it's an
+  ;; otherwise known type (according to `*-font-lock-extra-types'),
+  ;; 'prefix if it's a known prefix of a type, 'found if it's a type
+  ;; that matches one in `c-found-types', 'maybe if it's an identfier
+  ;; that might be a type, or nil if it can't be a type (the point
+  ;; isn't moved then).  The point is assumed to be at the beginning
+  ;; of a token.
   ;;
   ;; Note that this function doesn't skip past the brace definition
   ;; that might be considered part of the type, e.g.
@@ -4158,11 +4257,14 @@ This function does not do any hidden buffer changes."
                ;; don't let the existence of the operator itself promote two
                ;; uncertain types to a certain one.
                (cond ((eq res t))
-                     ((or (eq res 'known) (memq res2 '(t known)))
+                     ((eq res2 t)
                       (c-add-type id-start id-end)
                       (when c-record-type-identifiers
                         (c-record-type-id id-range))
                       (setq res t))
+                     ((eq res 'known))
+                     ((eq res2 'known)
+                      (setq res 'known))
                      ((eq res 'found))
                      ((eq res2 'found)
                       (setq res 'found))
@@ -4202,7 +4304,7 @@ This function does not do any hidden buffer changes."
     (c-with-syntax-table c++-template-syntax-table
       (c-backward-token-2 0 t lim)
       (while (and (or (looking-at c-symbol-start)
-                     (looking-at "[<,]"))
+                     (looking-at "[<,]\\|::"))
                  (zerop (c-backward-token-2 1 t lim))))
       (skip-chars-forward "^:"))))
 
@@ -4251,7 +4353,7 @@ brace."
        (c-search-uplist-for-classkey paren-state))))
 
 (defun c-just-after-func-arglist-p (&optional lim)
-  ;; Return t if we are between a function's argument list closing
+  ;; Return non-nil if we are between a function's argument list closing
   ;; paren and its opening brace.  Note that the list close brace
   ;; could be followed by a "const" specifier or a member init hanging
   ;; colon.  LIM is used as bound for some backward buffer searches;
@@ -4299,20 +4401,25 @@ brace."
           (or (not (c-beginning-of-macro))
               (and (c-forward-to-cpp-define-body)
                    (< (point) checkpoint)))
-          ;; check if we are looking at an ObjC method def
-          (or (not c-opt-method-key)
-              (progn
-                (goto-char checkpoint)
-                (c-forward-sexp -1)
-                (forward-char -1)
-                (c-backward-syntactic-ws lim)
-                (not (or (memq (char-before) '(?- ?+))
-                         ;; or a class category
-                         (progn
-                           (c-forward-sexp -2)
-                           (looking-at c-class-key))
-                         )))))
-      )))
+          ;; Check if we are looking at an ObjC method def or a class
+          ;; category.
+          (not (and c-opt-method-key
+                    (progn
+                      (goto-char checkpoint)
+                      (c-safe (c-backward-sexp) t))
+                    (progn
+                      (c-backward-syntactic-ws lim)
+                      (or (memq (char-before) '(?- ?+))
+                          (and (c-safe (c-forward-sexp -2) t)
+                               (looking-at c-class-key))))))
+          ;; Pike has compound types that include parens,
+          ;; e.g. "array(string)".  Check that we aren't after one.
+          (not (and (c-major-mode-is 'pike-mode)
+                    (progn
+                      (goto-char checkpoint)
+                      (c-safe (c-backward-sexp 2) t))
+                    (looking-at c-primitive-type-key)))
+          ))))
 
 (defun c-in-knr-argdecl (&optional lim)
   ;; Return the position of the first argument declaration if point is
@@ -4321,8 +4428,7 @@ brace."
   ;; position that bounds the backward search for the argument list.
   ;;
   ;; Note: A declaration level context is assumed; the test can return
-  ;; false positives for statements.  This test is even more easily
-  ;; fooled than `c-just-after-func-arglist-p'.
+  ;; false positives for statements.
 
   (save-excursion
     (save-restriction
@@ -4332,13 +4438,12 @@ brace."
       ;; check that it's followed by some symbol before the next ';'
       ;; or '{'.  If it does, it's the header of the K&R argdecl we're
       ;; in.
-      (if lim (narrow-to-region lim (point)))
+      (if lim (narrow-to-region lim (c-point 'eol)))
       (let ((outside-macro (not (c-query-macro-start)))
            paren-end)
 
        (catch 'done
-         (while (if (and (c-safe (setq paren-end
-                                       (c-down-list-backward (point))))
+         (while (if (and (setq paren-end (c-down-list-backward (point)))
                          (eq (char-after paren-end) ?\)))
                     (progn
                       (goto-char (1+ paren-end))
@@ -4349,7 +4454,26 @@ brace."
        (and (progn
               (c-forward-syntactic-ws)
               (looking-at "\\w\\|\\s_"))
-            (c-safe (c-up-list-backward paren-end))
+
+            (save-excursion
+              ;; The function header in a K&R declaration should only
+              ;; contain identifiers separated by comma.  It should
+              ;; also contain at least one identifier since there
+              ;; wouldn't be anything to declare in the K&R region
+              ;; otherwise.
+              (when (c-go-up-list-backward paren-end)
+                (forward-char)
+                (catch 'knr-ok
+                  (while t
+                    (c-forward-syntactic-ws)
+                    (if (or (looking-at c-known-type-key)
+                            (looking-at c-keywords-regexp))
+                        (throw 'knr-ok nil))
+                    (c-forward-token-2)
+                    (if (eq (char-after) ?,)
+                        (forward-char)
+                      (throw 'knr-ok (and (eq (char-after) ?\))
+                                          (= (point) paren-end))))))))
 
             (save-excursion
               ;; If it's a K&R declaration then we're now at the
@@ -4400,24 +4524,12 @@ brace."
       (if start
          (goto-char start)))))
 
-(defun c-backward-to-decl-anchor (&optional lim)
+(defsubst c-backward-to-decl-anchor (&optional lim)
   ;; Assuming point is at a brace that opens the block of a top level
   ;; declaration of some kind, move to the proper anchor point for
   ;; that block.
   (unless (= (point) (c-point 'boi))
-    ;; What we have below is actually an extremely stripped variant of
-    ;; c-beginning-of-statement-1.
-    (let ((pos (point)) c-maybe-labelp)
-      ;; Switch syntax table to avoid stopping at line continuations.
-      (save-restriction
-       (if lim (narrow-to-region lim (point-max)))
-       (while (and (progn
-                     (c-backward-syntactic-ws)
-                     (c-safe (goto-char (scan-sexps (point) -1)) t))
-                   (not (c-crosses-statement-barrier-p (point) pos))
-                   (not c-maybe-labelp))
-         (setq pos (point)))
-       (goto-char pos)))))
+    (c-beginning-of-statement-1 lim)))
 
 (defun c-search-decl-header-end ()
   ;; Search forward for the end of the "header" of the current
@@ -4440,7 +4552,7 @@ brace."
                 ;; operator token preceded by "operator".
                 (save-excursion
                   (and (c-safe (c-backward-sexp) t)
-                       (looking-at "operator\\([^_]\\|$\\)")))
+                       (looking-at "operator\\>\\([^_]\\|$\\)")))
                 (and (eq (char-before) ?<)
                      (c-with-syntax-table c++-template-syntax-table
                        (if (c-safe (goto-char (c-up-list-forward (point))))
@@ -4475,7 +4587,8 @@ brace."
 
       ;; `c-beginning-of-statement-1' stops at a block start, but we
       ;; want to continue if the block doesn't begin a top level
-      ;; construct, i.e. if it isn't preceded by ';', '}', ':', or bob.
+      ;; construct, i.e. if it isn't preceded by ';', '}', ':', bob,
+      ;; or an open paren.
       (let ((beg (point)) tentative-move)
        (while (and
                ;; Must check with c-opt-method-key in ObjC mode.
@@ -4485,6 +4598,9 @@ brace."
                (progn
                  (c-backward-syntactic-ws lim)
                  (not (memq (char-before) '(?\; ?} ?: nil))))
+               (save-excursion
+                 (backward-char)
+                 (not (looking-at "\\s(")))
                ;; Check that we don't move from the first thing in a
                ;; macro to its header.
                (not (eq (setq tentative-move
@@ -4614,7 +4730,7 @@ brace."
       nil)))
 
 (defun c-beginning-of-member-init-list (&optional limit)
-  ;; Goes to the beginning of a member init list (i.e. just after the
+  ;; Go to the beginning of a member init list (i.e. just after the
   ;; ':') if inside one.  Returns t in that case, nil otherwise.
   (or limit
       (setq limit (point-min)))
@@ -4921,33 +5037,44 @@ brace."
       (condition-case ()
          (save-excursion
            (let ((beg (point))
-                 end type)
+                 inner-beg end type)
              (c-forward-syntactic-ws)
              (if (eq (char-after) ?\()
                  (progn
                    (forward-char 1)
                    (c-forward-syntactic-ws)
+                   (setq inner-beg (point))
                    (setq type (assq (char-after) c-special-brace-lists)))
                (if (setq type (assq (char-after) c-special-brace-lists))
                    (progn
+                     (setq inner-beg (point))
                      (c-backward-syntactic-ws)
                      (forward-char -1)
                      (setq beg (if (eq (char-after) ?\()
                                    (point)
                                  nil)))))
              (if (and beg type)
-                 (if (and (c-safe (goto-char beg)
-                                  (c-forward-sexp 1)
-                                  (setq end (point))
-                                  (= (char-before) ?\)))
-                          (c-safe (goto-char beg)
-                                  (forward-char 1)
+                 (if (and (c-safe
+                            (goto-char beg)
+                            (c-forward-sexp 1)
+                            (setq end (point))
+                            (= (char-before) ?\)))
+                          (c-safe
+                            (goto-char inner-beg)
+                            (if (looking-at "\\s(")
+                                ;; Check balancing of the inner paren
+                                ;; below.
+                                (progn
                                   (c-forward-sexp 1)
-                                  ;; Kludges needed to handle inner
-                                  ;; chars both with and without
-                                  ;; paren syntax.
-                                  (or (/= (char-syntax (char-before)) ?\))
-                                      (= (char-before) (cdr type)))))
+                                  t)
+                              ;; If the inner char isn't a paren then
+                              ;; we can't check balancing, so just
+                              ;; check the char before the outer
+                              ;; closing paren.
+                              (goto-char end)
+                              (backward-char)
+                              (c-backward-syntactic-ws)
+                              (= (char-before) (cdr type)))))
                      (if (or (/= (char-syntax (char-before)) ?\))
                              (= (progn
                                   (c-forward-syntactic-ws)
@@ -5191,7 +5318,7 @@ brace."
                         (eq step-type 'label)
                         (/= savepos boi))
 
-                    (progn
+                    (let ((save-step-type step-type))
                       ;; Current position might not be good enough;
                       ;; skip backward another statement.
                       (setq step-type (c-beginning-of-statement-1
@@ -5223,14 +5350,20 @@ brace."
                           (c-add-syntax 'substatement nil))
 
                         (setq boi (c-point 'boi))
-                        (/= (point) savepos)))))
+                        (if (= (point) savepos)
+                            (progn
+                              (setq step-type save-step-type)
+                              nil)
+                          t)))))
 
                (setq savepos (point)
                      at-comment nil))
              (setq at-comment nil)
 
-             (when (and (eq step-type 'same)
-                        containing-sexp)
+             (when (and containing-sexp
+                        (if (memq step-type '(nil same))
+                            (/= (point) boi)
+                          (eq step-type 'label)))
                (goto-char containing-sexp)
 
                ;; Don't stop in the middle of a special brace list opener
@@ -5390,21 +5523,32 @@ brace."
 
        ;; CASE B.3: The body of a function declared inside a normal
        ;; block.  Can occur e.g. in Pike and when using gcc
-       ;; extensions.  Might also trigger it with some macros followed
-       ;; by blocks, and this gives sane indentation then too.
+       ;; extensions, but watch out for macros followed by blocks.
        ;; C.f. cases E, 16F and 17G.
        ((and (not (c-looking-at-bos))
             (eq (c-beginning-of-statement-1 containing-sexp nil nil t)
-                'same))
+                'same)
+            (save-excursion
+              ;; Look for a type followed by a symbol, i.e. the start of a
+              ;; function declaration.  Doesn't work for declarations like
+              ;; "int *foo() ..."; we'd need to refactor the more competent
+              ;; analysis in `c-font-lock-declarations' for that.
+              (and (c-forward-type)
+                   (progn
+                     (c-forward-syntactic-ws)
+                     (looking-at c-symbol-start)))))
        (c-add-stmt-syntax 'defun-open nil t nil
                           containing-sexp paren-state))
 
-       ;; CASE B.4: Continued statement with block open.
+       ;; CASE B.4: Continued statement with block open.  The most
+       ;; accurate analysis is perhaps `statement-cont' together with
+       ;; `block-open' but we play DWIM and use `substatement-open'
+       ;; instead.  The rationaly is that this typically is a macro
+       ;; followed by a block which makes it very similar to a
+       ;; statement with a substatement block.
        (t
-       (goto-char beg-of-same-or-containing-stmt)
-       (c-add-stmt-syntax 'statement-cont nil nil nil
-                          containing-sexp paren-state)
-       (c-add-syntax 'block-open))
+       (c-add-stmt-syntax 'substatement-open nil nil nil
+                          containing-sexp paren-state))
        ))
 
      ;; CASE C: iostream insertion or extraction operator
@@ -5423,8 +5567,8 @@ brace."
      ((and (save-excursion
             ;; Check that the next token is a '{'.  This works as
             ;; long as no language that allows nested function
-            ;; definitions doesn't allow stuff like member init
-            ;; lists, K&R declarations or throws clauses there.
+            ;; definitions allows stuff like member init lists, K&R
+            ;; declarations or throws clauses there.
             ;;
             ;; Note that we do a forward search for something ahead
             ;; of the indentation line here.  That's not good since
@@ -5435,7 +5579,16 @@ brace."
             (eq (char-after) ?{))
           (not (c-looking-at-bos))
           (eq (c-beginning-of-statement-1 containing-sexp nil nil t)
-              'same))
+              'same)
+          (save-excursion
+            ;; Look for a type followed by a symbol, i.e. the start of a
+            ;; function declaration.  Doesn't work for declarations like "int
+            ;; *foo() ..."; we'd need to refactor the more competent analysis
+            ;; in `c-font-lock-declarations' for that.
+            (and (c-forward-type)
+                 (progn
+                   (c-forward-syntactic-ws)
+                   (looking-at c-symbol-start)))))
       (c-add-stmt-syntax 'func-decl-cont nil t nil
                         containing-sexp paren-state))
 
@@ -5446,6 +5599,7 @@ brace."
                         containing-sexp paren-state))
      )))
 
+;;;###autoload
 (defun c-guess-basic-syntax ()
   "Return the syntactic context of the current line.
 This function does not do any hidden buffer changes."
@@ -5847,7 +6001,8 @@ This function does not do any hidden buffer changes."
              ;; should be relative to the ctor's indentation
              )
             ;; CASE 5B.2: K&R arg decl intro
-            (c-recognize-knr-p
+            ((and c-recognize-knr-p
+                  (c-in-knr-argdecl lim))
              (c-beginning-of-statement-1 lim)
              (c-add-syntax 'knr-argdecl-intro (c-point 'boi))
              (if inclass-p
@@ -5951,7 +6106,12 @@ This function does not do any hidden buffer changes."
                ;; Note: We use the fact that lim is always after any
                ;; preceding brace sexp.
                (while (and (zerop (c-backward-token-2 1 t lim))
-                           (not (looking-at "[;<,=]"))))
+                           (or (not (looking-at "[;<,=]"))
+                               (and c-overloadable-operators-regexp
+                                    (looking-at c-overloadable-operators-regexp)
+                                    (save-excursion
+                                      (c-backward-token-2 1 nil lim)
+                                      (looking-at "operator\\>[^_]"))))))
                (or (memq (char-after) '(?, ?=))
                    (and (c-major-mode-is 'c++-mode)
                         (zerop (c-backward-token-2 1 nil lim))
@@ -6084,7 +6244,15 @@ This function does not do any hidden buffer changes."
           ;; CASE 5I: ObjC method definition.
           ((and c-opt-method-key
                 (looking-at c-opt-method-key))
-           (c-beginning-of-statement-1 lim)
+           (c-beginning-of-statement-1 nil t)
+           (if (= (point) indent-point)
+               ;; Handle the case when it's the first (non-comment)
+               ;; thing in the buffer.  Can't look for a 'same return
+               ;; value from cbos1 since ObjC directives currently
+               ;; aren't recognized fully, so that we get 'same
+               ;; instead of 'previous if it moved over a preceding
+               ;; directive.
+               (goto-char (point-min)))
            (c-add-syntax 'objc-method-intro (c-point 'boi)))
            ;; CASE 5P: AWK pattern or function or continuation
            ;; thereof.
@@ -6163,11 +6331,13 @@ This function does not do any hidden buffer changes."
           ;; CASE 5K: we are at an ObjC method definition
           ;; continuation line.
           ((and c-opt-method-key
-                (progn
+                (save-excursion
+                  (goto-char indent-point)
                   (c-beginning-of-statement-1 lim)
                   (beginning-of-line)
-                  (looking-at c-opt-method-key)))
-           (c-add-syntax 'objc-method-args-cont (point)))
+                  (when (looking-at c-opt-method-key)
+                    (setq placeholder (point)))))
+           (c-add-syntax 'objc-method-args-cont placeholder))
           ;; CASE 5L: we are at the first argument of a template
           ;; arglist that begins on the previous line.
           ((eq (char-before) ?<)
@@ -6194,7 +6364,7 @@ This function does not do any hidden buffer changes."
            (goto-char containing-sexp)
            (setq placeholder (c-point 'boi))
            (if (and (c-safe (backward-up-list 1) t)
-                    (> (point) placeholder))
+                    (>= (point) placeholder))
                (progn
                  (forward-char)
                  (skip-chars-forward " \t"))
@@ -6235,7 +6405,7 @@ This function does not do any hidden buffer changes."
            (goto-char containing-sexp)
            (setq placeholder (c-point 'boi))
            (when (and (c-safe (backward-up-list 1) t)
-                      (> (point) placeholder))
+                      (>= (point) placeholder))
              (forward-char)
              (skip-chars-forward " \t")
              (setq placeholder (point)))
@@ -6276,7 +6446,7 @@ This function does not do any hidden buffer changes."
            (goto-char containing-sexp)
            (setq placeholder (c-point 'boi))
            (if (and (c-safe (backward-up-list 1) t)
-                    (> (point) placeholder))
+                    (>= (point) placeholder))
                (progn
                  (forward-char)
                  (skip-chars-forward " \t"))
@@ -6488,16 +6658,24 @@ This function does not do any hidden buffer changes."
                (c-add-syntax 'inline-close (point))))
             ;; CASE 16F: Can be a defun-close of a function declared
             ;; in a statement block, e.g. in Pike or when using gcc
-            ;; extensions.  Might also trigger it with some macros
-            ;; followed by blocks, and this gives sane indentation
-            ;; then too.  Let it through to be handled below.
+            ;; extensions, but watch out for macros followed by
+            ;; blocks.  Let it through to be handled below.
             ;; C.f. cases B.3 and 17G.
             ((and (not inenclosing-p)
                   lim
                   (save-excursion
                     (and (not (c-looking-at-bos))
                          (eq (c-beginning-of-statement-1 lim nil nil t) 'same)
-                         (setq placeholder (point)))))
+                         (setq placeholder (point))
+                         ;; Look for a type or identifier followed by a
+                         ;; symbol, i.e. the start of a function declaration.
+                         ;; Doesn't work for declarations like "int *foo()
+                         ;; ..."; we'd need to refactor the more competent
+                         ;; analysis in `c-font-lock-declarations' for that.
+                         (c-forward-type)
+                         (progn
+                           (c-forward-syntactic-ws)
+                           (looking-at c-symbol-start)))))
              (back-to-indentation)
              (if (/= (point) containing-sexp)
                  (goto-char placeholder))
@@ -6622,13 +6800,21 @@ This function does not do any hidden buffer changes."
            (c-add-syntax 'defun-block-intro (point)))
           ;; CASE 17G: First statement in a function declared inside
           ;; a normal block.  This can occur in Pike and with
-          ;; e.g. the gcc extensions.  Might also trigger it with
-          ;; some macros followed by blocks, and this gives sane
-          ;; indentation then too.  C.f. cases B.3 and 16F.
+          ;; e.g. the gcc extensions, but watch out for macros
+          ;; followed by blocks.  C.f. cases B.3 and 16F.
           ((save-excursion
              (and (not (c-looking-at-bos))
                   (eq (c-beginning-of-statement-1 lim nil nil t) 'same)
-                  (setq placeholder (point))))
+                  (setq placeholder (point))
+                  ;; Look for a type or identifier followed by a
+                  ;; symbol, i.e. the start of a function declaration.
+                  ;; Doesn't work for declarations like "int *foo()
+                  ;; ..."; we'd need to refactor the more competent
+                  ;; analysis in `c-font-lock-declarations' for that.
+                  (c-forward-type)
+                  (progn
+                    (c-forward-syntactic-ws)
+                    (looking-at c-symbol-start))))
            (back-to-indentation)
            (if (/= (point) containing-sexp)
                (goto-char placeholder))
@@ -6736,6 +6922,10 @@ This function does not do any hidden buffer changes."
    ((vectorp offset)       offset)
    ((null offset)          nil)
    ((listp offset)
+    (if (eq (car offset) 'quote)
+       (error
+"Setting in c-offsets-alist element \"(%s . '%s)\" was mistakenly quoted"
+         symbol (cadr offset)))
     (let (done)
       (while (and (not done) offset)
        (setq done (c-evaluate-offset (car offset) langelem symbol)