]> code.delx.au - gnu-emacs/commitdiff
Handle "noise" macros and compiler directives.
authorAlan Mackenzie <acm@muc.de>
Mon, 29 Feb 2016 21:51:32 +0000 (21:51 +0000)
committerAlan Mackenzie <acm@muc.de>
Mon, 29 Feb 2016 21:51:32 +0000 (21:51 +0000)
* lisp/progmodes/cc-langs.el (c-symbol-char-key): New language variable.

* lisp/progmodes/cc-vars.el (c-noise-macro-names)
(c-noise-macro-with-parens-names): New customizable variables.
(c-noise-macro-name-re, c-noise-macro-with-parens-name-re): New variables.
(c-make-noise-macro-regexps): New function.

* lisp/progmodes/cc-engine.el (c-forward-sws, c-backward-sws): Adapt to treat
members of c-noise-macro-names as whitespace.
(c-forward-noise-clause): New function.
(c-forward-keyword-prefixed-id, c-forward-type, c-forward-declarator)
(c-forward-decl-or-cast-1, c-backward-over-enum-header)
(c-guess-basic-syntax CASE 5A.3, CASE 5A.5, CASE 9A):
Handle "noise clauses" in parallel with, e.g., "hangon key clauses".

* lisp/progmodes/cc-fonts.el (c-complex-decl-matchers): Handle "noise clauses"
in parallel with "prefix-spec keywords".

* lisp/progmodes/cc-mode.el (c-mode, c++-mode, objc-mode): call
c-make-noise-macro-regexps to initialize the internal variables.

* doc/misc/cc-mode.texi ("Noise Macros"): New section documenting the new
facilities.

doc/misc/cc-mode.texi
lisp/progmodes/cc-engine.el
lisp/progmodes/cc-fonts.el
lisp/progmodes/cc-langs.el
lisp/progmodes/cc-mode.el
lisp/progmodes/cc-vars.el

index bc8d24fd992c090cd24adbd023c9aa472307d3bb..cdc659ab358ae7a7433ab5944987234b333cd029 100644 (file)
@@ -338,14 +338,15 @@ Line-Up Functions
 * Comment Line-Up::
 * Misc Line-Up::
 
+
 Customizing Macros
 
 * Macro Backslashes::
 * Macros with ;::
+* Noise Macros::
 
 @end detailmenu
 @end menu
-
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 @node    Introduction, Overview, Top, Top
 @comment node-name, next, previous, up
@@ -6639,15 +6640,18 @@ Because a macro can expand into anything at all, near where one is
 invoked @ccmode{} can only indent and fontify code heuristically.
 Sometimes it gets it wrong.  Usually you should try to design your
 macros so that they ''look like ordinary code'' when you invoke them.
-However, one situation is so common that @ccmode{} handles it
+However, two situations are so common that @ccmode{} handles them
 specially: that is when certain macros needn't (or mustn't) be
-followed by a @samp{;}.  You need to configure @ccmode{} to handle
-these macros properly, see @ref{Macros with ;}.
+followed by a @samp{;}, and when certain macros (or compiler
+directives) expand to nothing.  You need to configure @ccmode{} to
+handle these macros properly, see @ref{Macros with ;} and @ref{Noise
+Macros}.
 
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 @menu
 * Macro Backslashes::
 * Macros with ;::
+* Noise Macros::
 @end menu
 
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -6699,7 +6703,7 @@ get aligned only when you explicitly invoke the command
 @end defopt
 
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-@node Macros with ;,  , Macro Backslashes, Custom Macros
+@node Macros with ;, Noise Macros, Macro Backslashes, Custom Macros
 @comment  node-name,  next,  previous,  up
 @section Macros with semicolons
 @cindex macros with semicolons
@@ -6754,6 +6758,60 @@ return value has no meaning.  This function is called by @ccmode{}'s
 initialization code.
 @end defun
 
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+@node    Noise Macros,  , Macros with ;, Custom Macros
+@comment node-name, next, previous, up
+@section Noise Macros
+@cindex noise macros
+@comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+In @ccmode{}, @dfn{noise macros} are macros which expand to nothing,
+or compiler directives (such as GCC's @code{__attribute__}) which play
+no part in the syntax of the C (etc.) language.  Some noise macros are
+followed by arguments in parentheses (possibly optionally), others
+are not.
+
+Noise macros can easily confuse @ccmode{}'s analysis of function
+headers, causing them to be mis-fontified, or even mis-indented.  You
+can prevent this confusion by specifying the identifiers which
+constitute noise macros.
+
+@defopt c-noise-macro-names
+@vindex noise-macro-names (c-)
+This variable is a list of names of noise macros which never have
+parenthesized arguments.  Each element is a string, and must be a
+valid identifier.  An element in @code{c-noise-macro-names} must not
+also be in @code{c-noise-macro-with-parens-names}.  Such an element is
+treated as whitespace by @ccmode{}.
+@end defopt
+
+@defopt c-noise-macro-with-parens-names
+@vindex noise-macro-with-parens-names (c-)
+This variable is a list of names of noise macros which optionally have
+arguments in parentheses.  Each element of the list is a string, and
+must be a valid identifier.  An element in
+@code{c-noise-macro-with-parens-names} must not also be in
+@code{c-noise-macro-names}.  For performance reasons, such an element,
+together with the optional parenthesized arguments, is specially
+handled, but it is only handled when used in declaration
+contexts@footnote{If this restriction causes your project
+difficulties, please get in touch with @email{bug-cc-mode@@gnu.org}.}.
+
+The two compiler directives @code{__attribute__} and @code{__declspec}
+have traditionally been handled specially in @ccmode{}; for example
+they are fontified with font-lock-keyword-face.  You don't need to
+include these directives in @code{c-noise-macro-with-parens-names},
+but doing so is OK.
+@end defopt
+
+@defun c-make-noise-macro-regexps
+@findex make-noise-macro-regexps (c-)
+Call this (non-interactive) function, which sets internal variables,
+after changing the value of @code{c-noise-macro-names} or
+@code{c-noise-macro-with-parens-names} (e.g. in a hook (@pxref{CC
+Hooks})).  This function is called by @ccmode{}'s initialization code.
+@end defun
+
 @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 @node    Odds and Ends, Sample Init File, Custom Macros, Top
 @comment node-name, next, previous, up
index f5aa4df7c2bab90d2b2aae09ad44529229e1d52f..66b5369bbba8cea755c53a0445744291f9ff4c2f 100644 (file)
@@ -1543,7 +1543,7 @@ comment at the start of cc-engine.el for more info."
 ;;    two newlines with horizontal whitespace between them.
 ;;
 ;;    The reason to include the first following char is to cope with
-;;    "rung positions" that doesn't have any ordinary whitespace.  If
+;;    "rung positions" that don't have any ordinary whitespace.  If
 ;;    `c-is-sws' is put on a token character it does not have
 ;;    `c-in-sws' set simultaneously.  That's the only case when that
 ;;    can occur, and the reason for not extending the `c-in-sws'
@@ -1714,7 +1714,9 @@ comment at the start of cc-engine.el for more info."
     ;; if it's anything that can't start syntactic ws, so we can bail out
     ;; early in the majority of cases when there just are a few ws chars.
     (skip-chars-forward " \t\n\r\f\v")
-    (when (looking-at c-syntactic-ws-start)
+    (when (or (looking-at c-syntactic-ws-start)
+             (and c-opt-cpp-prefix
+                  (looking-at c-noise-macro-name-re)))
 
       (setq rung-end-pos (min (1+ (point)) (point-max)))
       (if (setq rung-is-marked (text-property-any rung-pos rung-end-pos
@@ -1733,6 +1735,10 @@ comment at the start of cc-engine.el for more info."
       (with-silent-modifications
       (while
          (progn
+           ;; In the following while form, we move over a "ladder" and
+           ;; following simple WS each time round the loop, appending the WS
+           ;; onto the ladder, joining adjacent ladders, and terminating when
+           ;; there is no more WS or we reach EOB.
            (while
                (when (and rung-is-marked
                           (get-text-property (point) 'c-in-sws))
@@ -1776,6 +1782,7 @@ comment at the start of cc-engine.el for more info."
                            (setq rung-pos (point)
                                  last-put-in-sws-pos rung-pos)))
 
+           ;; Now move over any comments (x)or a CPP construct.
            (setq simple-ws-end (point))
            (c-forward-comments)
 
@@ -1801,6 +1808,13 @@ comment at the start of cc-engine.el for more info."
              (forward-line 1)
              (setq safe-start t)
              ;; Don't cache at eob in case the buffer is narrowed.
+             (not (eobp)))
+
+            ((and c-opt-cpp-prefix
+                  (looking-at c-noise-macro-name-re))
+             ;; Skip over a noise macro.
+             (goto-char (match-end 1))
+             (setq safe-start t)
              (not (eobp)))))
 
        ;; We've searched over a piece of non-white syntactic ws.  See if this
@@ -1907,8 +1921,11 @@ comment at the start of cc-engine.el for more info."
     (when (and (not (bobp))
               (save-excursion
                 (backward-char)
-                (looking-at c-syntactic-ws-end)))
-
+                (or (looking-at c-syntactic-ws-end)
+                    (and c-opt-cpp-prefix
+                         (looking-at c-symbol-char-key)
+                         (progn (c-beginning-of-current-token)
+                                (looking-at c-noise-macro-name-re))))))
       ;; Try to find a rung position in the simple ws preceding point, so that
       ;; we can get a cache hit even if the last bit of the simple ws has
       ;; changed recently.
@@ -1927,6 +1944,9 @@ comment at the start of cc-engine.el for more info."
       (with-silent-modifications
       (while
          (progn
+           ;; Each time round the next while form, we move back over a ladder
+           ;; and append any simple WS preceding it, if possible joining with
+           ;; the previous ladder.
            (while
                (when (and rung-is-marked
                           (not (bobp))
@@ -2035,6 +2055,15 @@ comment at the start of cc-engine.el for more info."
              ;; narrowed out, and we can't risk marking the simple ws
              ;; at the end of it.
              (goto-char next-rung-pos)
+             t)
+
+            ((and c-opt-cpp-prefix
+                  (save-excursion
+                    (and (< (skip-syntax-backward "w_") 0)
+                         (progn (setq next-rung-pos (point))
+                                (looking-at c-noise-macro-name-re)))))
+             ;; Skipped over a noise macro
+             (goto-char next-rung-pos)
              t)))
 
        ;; We've searched over a piece of non-white syntactic ws.  See if this
@@ -5807,8 +5836,10 @@ comment at the start of cc-engine.el for more info."
                               `(c-forward-type)
                             `(c-forward-name)))
                nil
-             (and (looking-at c-keywords-regexp)
-                  (c-forward-keyword-clause 1))))
+             (cond ((looking-at c-keywords-regexp)
+                    (c-forward-keyword-clause 1))
+                   ((looking-at c-noise-macro-with-parens-name-re)
+                    (c-forward-noise-clause)))))
      (when (memq res '(t known found prefix))
        ,(when (eq type 'ref)
          `(when c-record-type-identifiers
@@ -5830,6 +5861,17 @@ comment at the start of cc-engine.el for more info."
                 (c-forward-syntactic-ws)
                 (c-forward-keyword-prefixed-id ,type)))))
 
+(defun c-forward-noise-clause ()
+  ;; Point is at a c-noise-macro-with-parens-names macro identifier.  Go
+  ;; forward over this name, any parenthesis expression which follows it, and
+  ;; any syntactic WS, ending up at the next token.  If there is an unbalanced
+  ;; paren expression, leave point at it.  Always Return t.
+  (c-forward-token-2)
+  (if (and (eq (char-after) ?\()
+          (c-go-list-forward))
+      (c-forward-syntactic-ws))
+  t)
+
 (defun c-forward-keyword-clause (match)
   ;; Submatch MATCH in the current match data is assumed to surround a
   ;; token.  If it's a keyword, move over it and any immediately
@@ -6460,6 +6502,13 @@ comment at the start of cc-engine.el for more info."
                                     ; "typedef".
       (goto-char (match-end 1))
       (c-forward-syntactic-ws)
+
+      (while (cond
+             ((looking-at c-decl-hangon-key)
+              (c-forward-keyword-clause 1))
+             ((looking-at c-noise-macro-with-parens-name-re)
+              (c-forward-noise-clause))))
+
       (setq pos (point))
 
       (setq name-res (c-forward-name))
@@ -6852,31 +6901,38 @@ comment at the start of cc-engine.el for more info."
           ;; of the while.  These are, e.g. "*" in "int *foo" or "(" and
           ;; "*" in "int (*foo) (void)" (Note similar code in
           ;; `c-forward-decl-or-cast-1'.)
-          (while (and (looking-at c-type-decl-prefix-key)
-                      (if (and (c-major-mode-is 'c++-mode)
-                               (match-beginning 3))
-                          ;; 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.
-                          (progn
-                            (setq id-start (point))
-                            (c-forward-name)
-                            (if (looking-at "\\(::\\)")
-                                ;; We only check for a trailing "::" and
-                                ;; let the "*" that should follow be
-                                ;; matched in the next round.
-                                t
-                              ;; It turned out to be the real identifier,
-                              ;; so flag that and stop.
-                              (setq got-identifier t)
-                              nil))
-                        t))
-            (if (eq (char-after) ?\()
-                (progn
-                  (setq paren-depth (1+ paren-depth))
-                  (forward-char))
-              (goto-char (match-end 1)))
-            (c-forward-syntactic-ws))
+             (while
+                 (cond
+                  ((looking-at c-decl-hangon-key)
+                   (c-forward-keyword-clause 1))
+                  ((looking-at c-noise-macro-with-parens-name-re)
+                   (c-forward-noise-clause))
+                  ((and (looking-at c-type-decl-prefix-key)
+                        (if (and (c-major-mode-is 'c++-mode)
+                                 (match-beginning 3))
+                            ;; 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.
+                            (progn
+                              (setq id-start (point))
+                              (c-forward-name)
+                              (if (looking-at "\\(::\\)")
+                                  ;; We only check for a trailing "::" and
+                                  ;; let the "*" that should follow be
+                                  ;; matched in the next round.
+                                  t
+                                ;; It turned out to be the real identifier,
+                                ;; so flag that and stop.
+                                (setq got-identifier t)
+                                nil))
+                          t))
+                   (if (eq (char-after) ?\()
+                       (progn
+                         (setq paren-depth (1+ paren-depth))
+                         (forward-char))
+                     (goto-char (match-end 1)))
+                   (c-forward-syntactic-ws)
+                   t)))
 
           ;; If we haven't passed the identifier already, do it now.
           (unless got-identifier
@@ -6901,9 +6957,12 @@ comment at the start of cc-engine.el for more info."
 
         ;; Skip over any trailing bit, such as "__attribute__".
         (progn
-          (when (looking-at c-decl-hangon-key)
-            (c-forward-keyword-clause 1))
-          (<= (point) limit))
+             (while (cond
+                     ((looking-at c-decl-hangon-key)
+                      (c-forward-keyword-clause 1))
+                     ((looking-at c-noise-macro-with-parens-name-re)
+                      (c-forward-noise-clause))))
+             (<= (point) limit))
 
         ;; Search syntactically to the end of the declarator (";",
         ;; ",", a closing paren, eob etc) or to the beginning of an
@@ -7082,18 +7141,24 @@ comment at the start of cc-engine.el for more info."
     ;; macros like __INLINE__, so we recognize both types and known
     ;; specifiers after them too.
     (while
-       (let* ((start (point)) kwd-sym kwd-clause-end found-type)
+       (let* ((start (point)) kwd-sym kwd-clause-end found-type noise-start)
 
+         (cond
          ;; Look for a specifier keyword clause.
-         (when (or (looking-at c-prefix-spec-kwds-re) ;FIXME!!! includes auto
-                   (and (c-major-mode-is 'java-mode)
-                        (looking-at "@[A-Za-z0-9]+")))
-           (if (save-match-data (looking-at c-typedef-key))
-               (setq at-typedef t))
+          ((or (looking-at c-prefix-spec-kwds-re)
+               (and (c-major-mode-is 'java-mode)
+                (looking-at "@[A-Za-z0-9]+")))
+           (save-match-data
+             (if (looking-at c-typedef-key)
+                 (setq at-typedef t)))
            (setq kwd-sym (c-keyword-sym (match-string 1)))
            (save-excursion
              (c-forward-keyword-clause 1)
              (setq kwd-clause-end (point))))
+          ((looking-at c-noise-macro-with-parens-name-re)
+           (setq noise-start (point))
+           (c-forward-noise-clause)
+           (setq kwd-clause-end (point))))
 
          (when (setq found-type (c-forward-type t)) ; brace-block-too
            ;; Found a known or possible type or a prefix of a known type.
@@ -7131,16 +7196,17 @@ comment at the start of cc-engine.el for more info."
                  backup-at-type-decl nil
                  backup-maybe-typeless nil))
 
-         (if kwd-sym
+         (if (or kwd-sym noise-start)
              (progn
                ;; Handle known specifier keywords and
                ;; `c-decl-hangon-kwds' which can occur after known
                ;; types.
 
-               (if (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
-                   ;; It's a hang-on keyword that can occur anywhere.
+               (if (or (c-keyword-member kwd-sym 'c-decl-hangon-kwds)
+                       noise-start)
+                   ;; It's a hang-on keyword or noise clause that can occur
+                   ;; anywhere.
                    (progn
-                     (setq at-decl-or-cast t)
                      (if at-type
                          ;; Move the identifier start position if
                          ;; we've passed a type.
@@ -7192,8 +7258,11 @@ comment at the start of cc-engine.el for more info."
       ;; If a known type was found, we still need to skip over any
       ;; hangon keyword clauses after it.  Otherwise it has already
       ;; been done in the loop above.
-      (while (looking-at c-decl-hangon-key)
-       (c-forward-keyword-clause 1))
+      (while
+         (cond ((looking-at c-decl-hangon-key)
+                (c-forward-keyword-clause 1))
+               ((looking-at c-noise-macro-with-parens-name-re)
+                (c-forward-noise-clause))))
       (setq id-start (point)))
 
      ((eq at-type 'prefix)
@@ -8960,6 +9029,11 @@ comment at the start of cc-engine.el for more info."
           t)
          ((looking-at c-after-brace-list-key) t)
          ((looking-at c-brace-list-key) nil)
+         ((eq (char-after) ?\()
+          (and (eq (c-backward-token-2) 0)
+               (or (looking-at c-decl-hangon-key)
+                   (looking-at c-noise-macro-with-parens-name-re))))
+
          ((and c-recognize-<>-arglists
                (eq (char-after) ?<)
                (looking-at "\\s("))
@@ -10220,9 +10294,11 @@ comment at the start of cc-engine.el for more info."
           ;; CASE 5A.3: brace list open
           ((save-excursion
              (c-beginning-of-decl-1 lim)
-             (while (looking-at c-specifier-key)
-               (goto-char (match-end 1))
-               (c-forward-syntactic-ws indent-point))
+             (while (cond
+                     ((looking-at c-specifier-key)
+                      (c-forward-keyword-clause 1))
+                     ((looking-at c-noise-macro-with-parens-name-re)
+                      (c-forward-noise-clause))))
              (setq placeholder (c-point 'boi))
              (or (consp special-brace-list)
                  (and (or (save-excursion
@@ -10274,9 +10350,11 @@ comment at the start of cc-engine.el for more info."
           (t
            (save-excursion
              (c-beginning-of-decl-1 lim)
-             (while (looking-at c-specifier-key)
-               (goto-char (match-end 1))
-               (c-forward-syntactic-ws indent-point))
+             (while (cond
+                     ((looking-at c-specifier-key)
+                      (c-forward-keyword-clause 1))
+                     ((looking-at c-noise-macro-with-parens-name-re)
+                      (c-forward-noise-clause))))
              (c-add-syntax 'defun-open (c-point 'boi))
              ;; Bogus to use bol here, but it's the legacy.  (Resolved,
              ;; 2007-11-09)
@@ -10907,9 +10985,11 @@ comment at the start of cc-engine.el for more info."
            (c-beginning-of-statement-1
             (c-safe-position (1- containing-sexp) paren-state))
            (c-forward-token-2 0)
-           (while (looking-at c-specifier-key)
-             (goto-char (match-end 1))
-             (c-forward-syntactic-ws))
+           (while (cond
+                   ((looking-at c-specifier-key)
+                    (c-forward-keyword-clause 1))
+                   ((looking-at c-noise-macro-with-parens-name-re)
+                    (c-forward-noise-clause))))
            (c-add-syntax 'brace-list-open (c-point 'boi))))
 
         ;; CASE 9B: brace-list-close brace
index 3cc537bba3df128fc3847acfe6bca95ab5bf5219..a7097b98c9d29328508cdab7b8136bebacaae3e3 100644 (file)
@@ -1698,10 +1698,16 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
                        (unless (c-skip-comments-and-strings limit)
                          (c-forward-syntactic-ws)
                          ;; Handle prefix declaration specifiers.
-                         (when (or (looking-at c-prefix-spec-kwds-re)
-                                   (and (c-major-mode-is 'java-mode)
-                                        (looking-at "@[A-Za-z0-9]+")))
-                           (c-forward-keyword-clause 1))
+                         (while
+                             (or
+                              (when (or (looking-at c-prefix-spec-kwds-re)
+                                        (and (c-major-mode-is 'java-mode)
+                                             (looking-at "@[A-Za-z0-9]+")))
+                                (c-forward-keyword-clause 1)
+                                t)
+                              (when (looking-at c-noise-macro-with-parens-name-re)
+                                (c-forward-noise-clause)
+                                t)))
                          ,(if (c-major-mode-is 'c++-mode)
                               `(when (and (c-forward-type)
                                           (eq (char-after) ?=))
@@ -1827,7 +1833,7 @@ higher."
                "\\)\\>"
                ;; Disallow various common punctuation chars that can't come
                ;; before the '{' of the enum list, to avoid searching too far.
-               "[^][{}();/#=]*"
+               "[^][{};/#=]*"
                "{")
               '((c-font-lock-declarators limit t nil)
                 (save-match-data
index 86b6bec78a143163c7edc24ff7894c43540c6364..d212482790d00eabf74e0ac8d2b036d42057802e 100644 (file)
@@ -619,6 +619,11 @@ This is of the form that fits inside [ ] in a regexp."
   objc (concat c-alnum "_$@"))
 (c-lang-defvar c-symbol-chars (c-lang-const c-symbol-chars))
 
+(c-lang-defconst c-symbol-char-key
+  "Regexp matching a sequence of at least one identifier character."
+  t (concat "[" (c-lang-const c-symbol-chars) "]+"))
+(c-lang-defvar c-symbol-char-key (c-lang-const c-symbol-char-key))
+
 (c-lang-defconst c-symbol-key
   "Regexp matching identifiers and keywords (with submatch 0).  Assumed
 to match if `c-symbol-start' matches on the same position."
index 58aebf8b410b52ea4333a235a75846092d12731f..9ebe6f79eb3f49aaf7c10332341e0340852245f6 100644 (file)
@@ -1493,6 +1493,7 @@ Key bindings:
        abbrev-mode t)
   (use-local-map c-mode-map)
   (c-init-language-vars-for 'c-mode)
+  (c-make-noise-macro-regexps)
   (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ;
   (c-common-init 'c-mode)
   (easy-menu-add c-c-menu)
@@ -1548,6 +1549,7 @@ Key bindings:
        abbrev-mode t)
   (use-local-map c++-mode-map)
   (c-init-language-vars-for 'c++-mode)
+  (c-make-noise-macro-regexps)
   (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ;
   (c-common-init 'c++-mode)
   (easy-menu-add c-c++-menu)
@@ -1601,6 +1603,7 @@ Key bindings:
        abbrev-mode t)
   (use-local-map objc-mode-map)
   (c-init-language-vars-for 'objc-mode)
+  (c-make-noise-macro-regexps)
   (c-make-macro-with-semi-re) ; matches macro names whose expansion ends with ;
   (c-common-init 'objc-mode)
   (easy-menu-add c-objc-menu)
index 8cee733ec8e3461b56f92daa08e0b91c928e69d1..a6957185a2b273ae28c564ecc31249470e4ebcfc 100644 (file)
@@ -1619,6 +1619,49 @@ names)."))
   :type 'c-extra-types-widget
   :group 'c)
 
+(defvar c-noise-macro-with-parens-name-re nil)
+(defvar c-noise-macro-name-re nil)
+
+(defcustom c-noise-macro-names nil
+  "A list of names of macros which expand to nothing, or compiler extensions
+like \"????\" which are syntactic noise.  Such a macro/extension is complete in
+itself, never having parentheses.  All these names must be syntactically valid
+identifiers.
+
+If you change this variable's value, call the function
+`c-make-noise-macro-regexps' to set the necessary internal variables (or do
+this implicitly by reinitialising C/C++/Objc Mode on any buffer)."
+  :type '(repeat :tag "List of names" string)
+  :group 'c)
+
+(defcustom c-noise-macro-with-parens-names nil
+  "A list of names of macros \(or compiler extensions like \"__attribute__\")
+which optionally have arguments in parentheses, and which expand to nothing.
+These are recognized by CC Mode only in declarations."
+  :type '(regexp :tag "List of names (possibly empty)" string)
+  :group 'c)
+
+(defun c-make-noise-macro-regexps ()
+  ;; Convert `c-noise-macro-names' and `c-noise-macro-with-parens-names' into
+  ;; `c-noise-macro-name-re' and `c-noise-macro-with-parens-name-re'.
+  (setq c-noise-macro-with-parens-name-re
+       (cond ((null c-noise-macro-with-parens-names) "\\<\\>")
+             ((consp c-noise-macro-with-parens-names)
+              (concat (regexp-opt c-noise-macro-with-parens-names t)
+                      "\\([^[:alnum:]_$]\\|$\\)"))
+             ((stringp c-noise-macro-with-parens-names)
+              (copy-sequence c-noise-macro-with-parens-names))
+             (t (error "c-make-noise-macro-regexps: \
+c-noise-macro-with-parens-names is invalid: %s" c-noise-macro-with-parens-names))))
+  (setq c-noise-macro-name-re
+       (cond ((null c-noise-macro-names) "\\<\\>")
+             ((consp c-noise-macro-names)
+              (concat (regexp-opt c-noise-macro-names t)
+                      "\\([^[:alnum:]_$]\\|$\\)"))
+             ((stringp c-noise-macro-names)
+              (copy-sequence c-noise-macro-names))
+             (t (error "c-make-noise-macro-regexps: \
+c-noise-macro-names is invalid: %s" c-noise-macro-names)))))
 \f
 ;; Non-customizable variables, still part of the interface to CC Mode
 (defvar c-macro-with-semi-re nil