GNU bug report logs - #22486
CC Mode 5.33 (C++/l); Bad indentation in a hideous C++ struct

Previous Next

Package: cc-mode;

Reported by: Michael Welsh Duggan <mwd <at> md5i.com>

Date: Thu, 28 Jan 2016 20:38:01 UTC

Severity: normal

Done: Alan Mackenzie <acm <at> muc.de>

Bug is archived. No further changes may be made.

To add a comment to this bug, you must first unarchive it, by sending
a message to control AT debbugs.gnu.org, with unarchive 22486 in the body.
You can then email your comments to 22486 AT debbugs.gnu.org in the normal way.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-cc-mode <at> gnu.org:
bug#22486; Package cc-mode. (Thu, 28 Jan 2016 20:38:01 GMT) Full text and rfc822 format available.

Acknowledgement sent to Michael Welsh Duggan <mwd <at> md5i.com>:
New bug report received and forwarded. Copy sent to bug-cc-mode <at> gnu.org. (Thu, 28 Jan 2016 20:38:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Michael Welsh Duggan <mwd <at> md5i.com>
To: submit <at> debbugs.gnu.org
Subject: CC Mode 5.33 (C++/l); Bad indentation in a hideous C++ struct
Date: Thu, 28 Jan 2016 15:37:07 -0500
In the following C++ snippet:

template <typename Arg, typename... Args>
struct ArgListMatcher<Arg, Args...> :
    ArgListMatcher<MakeIndices<CountRef<Arg>::value>,
                   MakeIndices<sizeof...(Args) - CountRef<Arg>::value, CountRef<Arg>::value>,
                       Arg, Args...>
{
  using Parent = ArgListMatcher<
    MakeIndices<CountRef<Arg>::value>,
    MakeIndices<sizeof...(Args) + 1 - CountRef<Arg>::value,
                CountRef<Arg>::value>, Arg, Args...>;
  using Parent::ArgListMatcher;
};

Starting with "template" as the first line, the lines' contexts are
listed as:

syntax: ((topmost-intro 1)), indent: 0
syntax: ((topmost-intro-cont 1)), indent: 0
syntax: ((inher-intro 1)), indent: 4
syntax: ((template-args-cont 1 99)), indent: 19
syntax: ((member-init-intro 154)), indent: 23
syntax: ((defun-open 1)), indent: 0

All of these seem reasonable save for member-init-intro, which I
expected to be template-args-cont.


Emacs  : GNU Emacs 25.0.50.3 (x86_64-pc-linux-gnu, X toolkit)
 of 2016-01-19
Package: CC Mode 5.33 (C++/l)
Buffer Style: SiLK
c-emacs-features: (pps-extended-state col-0-paren posix-char-classes gen-string-delim gen-comment-delim syntax-properties 1-bit)

current state:
==============
(setq
 c-basic-offset 4
 c-comment-only-line-offset 0
 c-indent-comment-alist '((anchored-comment column . 0) (end-block space . 1)
                          (cpp-end-block space . 2))
 c-indent-comments-syntactically-p nil
 c-block-comment-prefix "* "
 c-comment-prefix-regexp '((pike-mode . "//+!?\\|\\**") (awk-mode . "#+")
                           (other . "//+\\|\\**"))
 c-doc-comment-style '((java-mode . javadoc) (pike-mode . autodoc)
                       (c-mode . gtkdoc))
 c-cleanup-list '(scope-operator)
 c-hanging-braces-alist '((brace-list-open) (brace-entry-open)
                          (statement-cont) (substatement-open after)
                          (block-close . c-snug-do-while)
                          (extern-lang-open after) (namespace-open after)
                          (module-open after) (composition-open after)
                          (inexpr-class-open after)
                          (inexpr-class-close before) (arglist-cont-nonempty))
 c-hanging-colons-alist nil
 c-hanging-semi&comma-criteria '(c-semi&comma-inside-parenlist)
 c-backslash-column 48
 c-backslash-max-column 72
 c-special-indent-hook nil
 c-label-minimum-indentation 1
 c-offsets-alist '((inexpr-class . +)
                   (inexpr-statement . +)
                   (lambda-intro-cont . +)
                   (inlambda . c-lineup-inexpr-block)
                   (template-args-cont c-lineup-template-args +)
                   (incomposition . +)
                   (inmodule . +)
                   (innamespace . 0)
                   (inextern-lang . 0)
                   (composition-close . 0)
                   (module-close . 0)
                   (namespace-close . 0)
                   (extern-lang-close . 0)
                   (composition-open . 0)
                   (module-open . 0)
                   (namespace-open . 0)
                   (extern-lang-open . 0)
                   (objc-method-call-cont
                    c-lineup-ObjC-method-call-colons
                    c-lineup-ObjC-method-call
                    +
                    )
                   (objc-method-args-cont . c-lineup-ObjC-method-args)
                   (objc-method-intro . [0])
                   (friend . 0)
                   (cpp-define-intro c-lineup-cpp-define +)
                   (cpp-macro-cont . +)
                   (cpp-macro . [0])
                   (inclass . +)
                   (stream-op . c-lineup-streamop)
                   (arglist-cont-nonempty
                    c-lineup-gcc-asm-reg
                    c-lineup-arglist
                    )
                   (arglist-cont c-lineup-gcc-asm-reg 0)
                   (comment-intro
                    c-lineup-knr-region-comment
                    c-lineup-comment
                    )
                   (catch-clause . 0)
                   (else-clause . 0)
                   (do-while-closure . 0)
                   (access-label . /)
                   (case-label . *)
                   (substatement . +)
                   (statement-case-intro . *)
                   (statement . 0)
                   (brace-entry-open . 0)
                   (brace-list-entry . 0)
                   (brace-list-intro . +)
                   (brace-list-close . 0)
                   (block-close . 0)
                   (block-open . 0)
                   (inher-cont . c-lineup-multi-inher)
                   (inher-intro . +)
                   (member-init-cont . c-lineup-multi-inher)
                   (member-init-intro . +)
                   (annotation-var-cont . +)
                   (annotation-top-cont . 0)
                   (topmost-intro . 0)
                   (knr-argdecl . 0)
                   (func-decl-cont . +)
                   (inline-close . 0)
                   (class-close . 0)
                   (class-open . 0)
                   (defun-block-intro . +)
                   (defun-close . 0)
                   (defun-open . 0)
                   (c . c-lineup-C-comments)
                   (string . c-lineup-dont-change)
                   (topmost-intro-cont . c-lineup-topmost-intro-cont)
                   (brace-list-open . 0)
                   (inline-open . 0)
                   (arglist-close . +)
                   (arglist-intro . +)
                   (statement-cont . c-lineup-math)
                   (statement-case-open . *)
                   (label . *)
                   (substatement-label . 2)
                   (substatement-open . 0)
                   (knr-argdecl-intro . +)
                   (statement-block-intro . +)
                   )
 c-buffer-is-cc-mode 'c++-mode
 c-tab-always-indent t
 c-syntactic-indentation t
 c-syntactic-indentation-in-macros t
 c-ignore-auto-fill '(string cpp code)
 c-auto-align-backslashes t
 c-backspace-function 'backward-delete-char-untabify
 c-delete-function 'delete-char
 c-electric-pound-behavior nil
 c-default-style '((java-mode . "java") (awk-mode . "awk") (other . "gnu"))
 c-enable-xemacs-performance-kludge-p nil
 c-old-style-variable-behavior nil
 defun-prompt-regexp nil
 tab-width 8
 comment-column 32
 parse-sexp-ignore-comments t
 parse-sexp-lookup-properties t
 auto-fill-function nil
 comment-multi-line t
 comment-start-skip "\\(//+\\|/\\*+\\)\\s *"
 fill-prefix nil
 fill-column 70
 paragraph-start "[ 	]*\\(//+\\|\\**\\)[ 	]*$\\|^\f"
 adaptive-fill-mode t
 adaptive-fill-regexp "[ 	]*\\(//+\\|\\**\\)[ 	]*\\([ 	]*\\([-–!|#%;>*·•‣⁃◦]+[ 	]*\\)*\\)"
 )
-- 
Michael Welsh Duggan
(md5i <at> md5i.com)




Information forwarded to bug-cc-mode <at> gnu.org:
bug#22486; Package cc-mode. (Fri, 05 Feb 2016 17:15:01 GMT) Full text and rfc822 format available.

Message #8 received at 22486 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Michael Welsh Duggan <mwd <at> md5i.com>
Cc: 22486 <at> debbugs.gnu.org
Subject: Re: bug#22486: CC Mode 5.33 (C++/l); Bad indentation in a hideous
 C++ struct
Date: Fri, 5 Feb 2016 17:16:37 +0000
Hello, Michael.

On Thu, Jan 28, 2016 at 03:37:07PM -0500, Michael Welsh Duggan wrote:
> In the following C++ snippet:

> template <typename Arg, typename... Args>
> struct ArgListMatcher<Arg, Args...> :
>     ArgListMatcher<MakeIndices<CountRef<Arg>::value>,
>                    MakeIndices<sizeof...(Args) - CountRef<Arg>::value, CountRef<Arg>::value>,
>                        Arg, Args...>    <============================
> {
>   using Parent = ArgListMatcher<
>     MakeIndices<CountRef<Arg>::value>,
>     MakeIndices<sizeof...(Args) + 1 - CountRef<Arg>::value,
>                 CountRef<Arg>::value>, Arg, Args...>;
>   using Parent::ArgListMatcher;
> };

> Starting with "template" as the first line, the lines' contexts are
> listed as:

> syntax: ((topmost-intro 1)), indent: 0
> syntax: ((topmost-intro-cont 1)), indent: 0
> syntax: ((inher-intro 1)), indent: 4
> syntax: ((template-args-cont 1 99)), indent: 19
> syntax: ((member-init-intro 154)), indent: 23  <=====================
> syntax: ((defun-open 1)), indent: 0

> All of these seem reasonable save for member-init-intro, which I
> expected to be template-args-cont.

Yes.

Also noticeable here is that some of the <...> pairs are not marked with
paren syntax by CC Mode.  Further analysis shows that these are the pairs
with arithmetic operators (- and +) inside them.

If the - operator in line 4 is replaced by a comma, then line 5 gets
correctly recognised as template-args-cont.  (No, I'm not suggesting this
as a workaround.  :-)

CC Mode currently uses the presence of things like + and - and other
things which "can't [couldn't] be inside templates" as a heuristic to
distingish template delimiters from less-than and greater-than.  [On a
personal note, it seems like the designers of C++ are lacking taste; they
just don't know where to stop.  C++'s syntax is ambiguous and highly
context dependent.  It seems like those designers are determined that
only editors attached to a compiler's syntax tree are to be practical for
C++.]

Would it, perhaps, be feasible to detect the ... operator as an
indication that +, -, (?etc.) are permissible inside template delimiters?
Is it true that ... only exists inside either a variadic parameter list
or template delimiters?

[ .... ]

> -- 
> Michael Welsh Duggan
> (md5i <at> md5i.com)

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#22486; Package cc-mode. (Fri, 05 Feb 2016 19:03:01 GMT) Full text and rfc822 format available.

Message #11 received at 22486 <at> debbugs.gnu.org (full text, mbox):

From: Michael Welsh Duggan <mwd <at> cert.org>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 22486 <at> debbugs.gnu.org
Subject: Re: bug#22486: CC Mode 5.33 (C++/l);
 Bad indentation in a hideous C++ struct
Date: Fri, 05 Feb 2016 14:01:52 -0500
Alan Mackenzie <acm <at> muc.de> writes:

> Hello, Michael.
>
> On Thu, Jan 28, 2016 at 03:37:07PM -0500, Michael Welsh Duggan wrote:
>> In the following C++ snippet:
>
>> template <typename Arg, typename... Args>
>> struct ArgListMatcher<Arg, Args...> :
>>     ArgListMatcher<MakeIndices<CountRef<Arg>::value>,
>>                    MakeIndices<sizeof...(Args) - CountRef<Arg>::value, CountRef<Arg>::value>,
>>                        Arg, Args...>    <============================
>> {
>>   using Parent = ArgListMatcher<
>>     MakeIndices<CountRef<Arg>::value>,
>>     MakeIndices<sizeof...(Args) + 1 - CountRef<Arg>::value,
>>                 CountRef<Arg>::value>, Arg, Args...>;
>>   using Parent::ArgListMatcher;
>> };
>
>> Starting with "template" as the first line, the lines' contexts are
>> listed as:
>
>> syntax: ((topmost-intro 1)), indent: 0
>> syntax: ((topmost-intro-cont 1)), indent: 0
>> syntax: ((inher-intro 1)), indent: 4
>> syntax: ((template-args-cont 1 99)), indent: 19
>> syntax: ((member-init-intro 154)), indent: 23  <=====================
>> syntax: ((defun-open 1)), indent: 0
>
>> All of these seem reasonable save for member-init-intro, which I
>> expected to be template-args-cont.
>
> Also noticeable here is that some of the <...> pairs are not marked with
> paren syntax by CC Mode.  Further analysis shows that these are the pairs
> with arithmetic operators (- and +) inside them.
>
> If the - operator in line 4 is replaced by a comma, then line 5 gets
> correctly recognised as template-args-cont.  (No, I'm not suggesting this
> as a workaround.  :-)

Yeah.  You're going to see arithmetic operators in template parameter
lists a lot more due to the way variadic templates are handled.  (They
basically are type-matched recursively via partial template
specialization.)

> CC Mode currently uses the presence of things like + and - and other
> things which "can't [couldn't] be inside templates" as a heuristic to
> distingish template delimiters from less-than and greater-than.  [On a
> personal note, it seems like the designers of C++ are lacking taste; they
> just don't know where to stop.  C++'s syntax is ambiguous and highly
> context dependent.  It seems like those designers are determined that
> only editors attached to a compiler's syntax tree are to be practical for
> C++.]

No arguments with your parenthetical.  Though I expect some of the C++
designers are the types to use vi and manually indent everything to
their taste.

> Would it, perhaps, be feasible to detect the ... operator as an
> indication that +, -, (?etc.) are permissible inside template delimiters?
> Is it true that ... only exists inside either a variadic parameter list
> or template delimiters?

Nope, sorry.  Functions can use the ... as well.  Here's an example,
compilable with g++ -std=c++11:

  #include <iostream>
  
  int sum()
  {
      return 0;
  }
  
  template<typename... T>
  int sum(int first, T... rest)
  {
      return first + sum(rest...);
  }
  
  int sum2()
  {
      return 0;
  }
  
  template<typename... T>
  int sum2(int first, T... rest)
  {
      return first + sum2(1 + rest...);
  }
  
  int main()
  {
      std::cout << sum(1, 2, 3, 4) << std::endl;  /* outputs 10 */
      std::cout << sum2(1, 2, 3, 4) << std::endl; /* outputs 16 */
  }

sum(1, 2, 3, 4) turns into (1 + 2 + 3 + 4 + 0), whereas sum2(1, 2, 3, 4)
turns into (1 + 3 + 5 + 7 + 0).  This is because of the sum(rest...) and
sum2(1 + rest...) expansions.

sum(rest...) turns into sum(rest0, rest1, ..., restn)
sum(1 + rest...) turns into sum (1 + rest0, 1 + rest1, ..., 1 + restn)

-- 
Michael Welsh Duggan
(mwd <at> cert.org)




Information forwarded to bug-cc-mode <at> gnu.org:
bug#22486; Package cc-mode. (Sun, 14 Feb 2016 16:54:02 GMT) Full text and rfc822 format available.

Message #14 received at 22486 <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: Michael Welsh Duggan <mwd <at> cert.org>
Cc: 22486 <at> debbugs.gnu.org
Subject: Re: bug#22486: CC Mode 5.33 (C++/l); Bad indentation in a hideous
 C++ struct
Date: Sun, 14 Feb 2016 16:55:52 +0000
Hello, Michael.

On Fri, Feb 05, 2016 at 02:01:52PM -0500, Michael Welsh Duggan wrote:
> Alan Mackenzie <acm <at> muc.de> writes:

> > On Thu, Jan 28, 2016 at 03:37:07PM -0500, Michael Welsh Duggan wrote:
> >> In the following C++ snippet:

> >> template <typename Arg, typename... Args>
> >> struct ArgListMatcher<Arg, Args...> :
> >>     ArgListMatcher<MakeIndices<CountRef<Arg>::value>,
> >>                    MakeIndices<sizeof...(Args) - CountRef<Arg>::value, CountRef<Arg>::value>,
> >>                        Arg, Args...>    <============================
> >> {
> >>   using Parent = ArgListMatcher<
> >>     MakeIndices<CountRef<Arg>::value>,
> >>     MakeIndices<sizeof...(Args) + 1 - CountRef<Arg>::value,
> >>                 CountRef<Arg>::value>, Arg, Args...>;
> >>   using Parent::ArgListMatcher;
> >> };

> >> Starting with "template" as the first line, the lines' contexts are
> >> listed as:

> >> syntax: ((topmost-intro 1)), indent: 0
> >> syntax: ((topmost-intro-cont 1)), indent: 0
> >> syntax: ((inher-intro 1)), indent: 4
> >> syntax: ((template-args-cont 1 99)), indent: 19
> >> syntax: ((member-init-intro 154)), indent: 23  <=====================
> >> syntax: ((defun-open 1)), indent: 0

> >> All of these seem reasonable save for member-init-intro, which I
> >> expected to be template-args-cont.

Please see the patch below.  Basically, I've had to slacken the criteria
for detecting template delimiters, so the danger of mistaking a
less-than followed by a greater-than for a template are higher than they
were.  Come to think of it, the danger probably isn't that high anyway.

Would you please do the usual with the patch and let me know how well
the problem is solved in real code.  Thanks!

[ .... ]

> Yeah.  You're going to see arithmetic operators in template parameter
> lists a lot more due to the way variadic templates are handled.  (They
> basically are type-matched recursively via partial template
> specialization.)

Maybe C++ compilers are going to mandate the handling of tail recursion.
:-)

[ .... ]

> > Would it, perhaps, be feasible to detect the ... operator as an
> > indication that +, -, (?etc.) are permissible inside template delimiters?
> > Is it true that ... only exists inside either a variadic parameter list
> > or template delimiters?

> Nope, sorry.  Functions can use the ... as well.  Here's an example,
> compilable with g++ -std=c++11:

>   #include <iostream>
  
>   int sum()
>   {
>       return 0;
>   }
  
>   template<typename... T>
>   int sum(int first, T... rest)
>   {
>       return first + sum(rest...);
>   }
  
>   int sum2()
>   {
>       return 0;
>   }
  
>   template<typename... T>
>   int sum2(int first, T... rest)
>   {
>       return first + sum2(1 + rest...);
>   }
  
>   int main()
>   {
>       std::cout << sum(1, 2, 3, 4) << std::endl;  /* outputs 10 */
>       std::cout << sum2(1, 2, 3, 4) << std::endl; /* outputs 16 */
>   }

> sum(1, 2, 3, 4) turns into (1 + 2 + 3 + 4 + 0), whereas sum2(1, 2, 3, 4)
> turns into (1 + 3 + 5 + 7 + 0).  This is because of the sum(rest...) and
> sum2(1 + rest...) expansions.

> sum(rest...) turns into sum(rest0, rest1, ..., restn)
> sum(1 + rest...) turns into sum (1 + rest0, 1 + rest1, ..., 1 + restn)

Well it's interesting that C++ can now have functions with a genuinely
variable number of arguments, rather than the clumsy mechanism (which C
still needs to use) in <varargs.h> (or whatever that include file is
called).  The cost is high, though.

Anyhow, here's the patch:



diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index a4a1604..d4dcb1c 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -6056,7 +6056,10 @@ c-forward-<>-arglist-recur
 		   ;; Stop on ',', '|', '&', '+' and '-' to catch
 		   ;; common binary operators that could be between
 		   ;; two comparison expressions "a<b" and "c>d".
-		   "[<;{},|+&-]\\|[>)]"
+		   ;; 2016-02-11: C++11 templates can now contain arithmetic
+		   ;; expressions, so template detection in C++ is now less
+		   ;; robust than it was.
+		   c-<>-notable-chars-re
 		   nil t t))
 
 		(cond
@@ -6064,7 +6067,9 @@ c-forward-<>-arglist-recur
 		  ;; Either an operator starting with '>' or the end of
 		  ;; the angle bracket arglist.
 
-		  (if (looking-at c->-op-without->-cont-regexp)
+		  (if (save-excursion
+			(c-backward-token-2)
+			(looking-at c-multichar->-op-not->>-regexp))
 		      (progn
 			(goto-char (match-end 0))
 			t)		; Continue the loop.
@@ -6134,6 +6139,11 @@ c-forward-<>-arglist-recur
 		      )))
 		  t)			; carry on looping.
 
+		 ((and
+		   (eq (char-before) ?\()
+		   (c-go-up-list-forward)
+		   (eq (char-before) ?\))))
+
 		 ((and (not c-restricted-<>-arglists)
 		       (or (and (eq (char-before) ?&)
 				(not (eq (char-after) ?&)))
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el
index 8a1d43c..9f1dd1d 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -228,6 +228,12 @@ c-lang-defvar
     ;; with the group symbol for each group and should return non-nil
     ;; if that group is to be included.
     ;;
+    ;; OP-FILTER selects the operators.  It is either t to select all
+    ;; operators, a string to select all operators for which `string-match'
+    ;; matches the operator with the string, or a function which will be
+    ;; called with the operator and should return non-nil when the operator
+    ;; is to be selected.
+    ;;
     ;; If XLATE is given, it's a function which is called for each
     ;; matching operator and its return value is collected instead.
     ;; If it returns a list, the elements are spliced directly into
@@ -1245,7 +1251,6 @@ 'c-opt-op-identitier-prefix
 		    t
 		    "\\`<."
 		    (lambda (op) (substring op 1)))))
-
 (c-lang-defvar c-<-op-cont-regexp (c-lang-const c-<-op-cont-regexp))
 
 (c-lang-defconst c->-op-cont-tokens
@@ -1264,7 +1269,6 @@ 'c-opt-op-identitier-prefix
   ;; Regexp matching the second and subsequent characters of all
   ;; multicharacter tokens that begin with ">".
   t (c-make-keywords-re nil (c-lang-const c->-op-cont-tokens)))
-
 (c-lang-defvar c->-op-cont-regexp (c-lang-const c->-op-cont-regexp))
 
 (c-lang-defconst c->-op-without->-cont-regexp
@@ -1279,10 +1283,19 @@ 'c-opt-op-identitier-prefix
 		     "\\`>>"
 		     (lambda (op) (substring op 1)))
        :test 'string-equal)))
-
 (c-lang-defvar c->-op-without->-cont-regexp
   (c-lang-const c->-op-without->-cont-regexp))
 
+(c-lang-defconst c-multichar->-op-not->>-regexp
+  ;; Regexp matching multichar tokens containing ">", except ">>"
+  t (c-make-keywords-re nil
+      (delete ">>"
+	      (c-filter-ops (c-lang-const c-all-op-syntax-tokens)
+			    t
+			    "\\(.>\\|>.\\)"))))
+(c-lang-defvar c-multichar->-op-not->>-regexp
+  (c-lang-const c-multichar->-op-not->>-regexp))
+
 (c-lang-defconst c-stmt-delim-chars
   ;; The characters that should be considered to bound statements.  To
   ;; optimize `c-crosses-statement-barrier-p' somewhat, it's assumed to
@@ -3087,6 +3100,19 @@ 'c-opt-op-identitier-prefix
 		    ; generics is not yet coded in CC Mode.
 (c-lang-defvar c-recognize-<>-arglists (c-lang-const c-recognize-<>-arglists))
 
+(c-lang-defconst c-<>-notable-chars-re
+  "A regexp matching any single character notable inside a <...> construct.
+This must include \"<\" and \">\", \",\", and any character which cannot be
+valid inside such a construct.  This is used in `c-forward-<>-arglist-recur' to
+try to detect sequences of tokens which cannot be a template \(etc.)
+construct.  When \"(\" is present, that defun will attempt to parse a
+parenthesized expression inside the template.  When \")\" is present it will
+treat an unbalanced closing paren as a sign of the invalidity of the
+putative template construct."
+  t "[<;{},|+&->)]"
+  c++ "[<;{},>()]")
+(c-lang-defvar c-<>-notable-chars-re (c-lang-const c-<>-notable-chars-re))
+
 (c-lang-defconst c-enums-contain-decls
   "Non-nil means that an enum structure can contain declarations."
   t nil


> -- 
> Michael Welsh Duggan
> (mwd <at> cert.org)

-- 
Alan Mackenzie (Nuremberg, Germany).




Information forwarded to bug-cc-mode <at> gnu.org:
bug#22486; Package cc-mode. (Sun, 14 Feb 2016 20:42:02 GMT) Full text and rfc822 format available.

Message #17 received at 22486 <at> debbugs.gnu.org (full text, mbox):

From: Michael Welsh Duggan <mwd <at> md5i.com>
To: Alan Mackenzie <acm <at> muc.de>
Cc: 22486 <at> debbugs.gnu.org, Michael Welsh Duggan <mwd <at> cert.org>
Subject: Re: bug#22486: CC Mode 5.33 (C++/l);
 Bad indentation in a hideous C++ struct
Date: Sun, 14 Feb 2016 15:41:29 -0500
Alan Mackenzie <acm <at> muc.de> writes:

> Hello, Michael.
>
> On Fri, Feb 05, 2016 at 02:01:52PM -0500, Michael Welsh Duggan wrote:
>> Alan Mackenzie <acm <at> muc.de> writes:
>
>> > On Thu, Jan 28, 2016 at 03:37:07PM -0500, Michael Welsh Duggan wrote:
>> >> In the following C++ snippet:
>
>> >> template <typename Arg, typename... Args>
>> >> struct ArgListMatcher<Arg, Args...> :
>> >>     ArgListMatcher<MakeIndices<CountRef<Arg>::value>,
>> >>                    MakeIndices<sizeof...(Args) - CountRef<Arg>::value, CountRef<Arg>::value>,
>> >>                        Arg, Args...>    <============================
>> >> {
>> >>   using Parent = ArgListMatcher<
>> >>     MakeIndices<CountRef<Arg>::value>,
>> >>     MakeIndices<sizeof...(Args) + 1 - CountRef<Arg>::value,
>> >>                 CountRef<Arg>::value>, Arg, Args...>;
>> >>   using Parent::ArgListMatcher;
>> >> };
>
>> >> Starting with "template" as the first line, the lines' contexts are
>> >> listed as:
>
>> >> syntax: ((topmost-intro 1)), indent: 0
>> >> syntax: ((topmost-intro-cont 1)), indent: 0
>> >> syntax: ((inher-intro 1)), indent: 4
>> >> syntax: ((template-args-cont 1 99)), indent: 19
>> >> syntax: ((member-init-intro 154)), indent: 23  <=====================
>> >> syntax: ((defun-open 1)), indent: 0
>
>> >> All of these seem reasonable save for member-init-intro, which I
>> >> expected to be template-args-cont.
>
> Please see the patch below.  Basically, I've had to slacken the criteria
> for detecting template delimiters, so the danger of mistaking a
> less-than followed by a greater-than for a template are higher than they
> were.  Come to think of it, the danger probably isn't that high anyway.
>
> Would you please do the usual with the patch and let me know how well
> the problem is solved in real code.  Thanks!

Seems to work for me.  Thanks!  (Have fun with the more recent bug I
sent you, #22644.  I verified that it still bugs with this patch.)

-- 
Michael Welsh Duggan
(md5i <at> md5i.com)




Reply sent to Alan Mackenzie <acm <at> muc.de>:
You have taken responsibility. (Mon, 15 Feb 2016 13:47:02 GMT) Full text and rfc822 format available.

Notification sent to Michael Welsh Duggan <mwd <at> md5i.com>:
bug acknowledged by developer. (Mon, 15 Feb 2016 13:47:02 GMT) Full text and rfc822 format available.

Message #22 received at 22486-done <at> debbugs.gnu.org (full text, mbox):

From: Alan Mackenzie <acm <at> muc.de>
To: 22486-done <at> debbugs.gnu.org
Subject: Re: bug#22486: CC Mode 5.33 (C++/l); Bad indentation in a hideous
 C++ struct
Date: Mon, 15 Feb 2016 13:49:01 +0000
Bug fixed in emacs-25 branch.

-- 
Alan Mackenzie (Nuremberg, Germany).




bug archived. Request was from Debbugs Internal Request <help-debbugs <at> gnu.org> to internal_control <at> debbugs.gnu.org. (Tue, 15 Mar 2016 11:24:04 GMT) Full text and rfc822 format available.

This bug report was last modified 9 years and 98 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.