unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Alan Mackenzie <acm@muc.de>
To: Nikolai Weibull <now@disu.se>
Cc: Stefan Monnier <monnier@iro.umontreal.ca>,
	Emacs Developers <emacs-devel@gnu.org>
Subject: Re: C99 compound literals in c-mode
Date: Sun, 20 Aug 2017 20:40:30 +0000	[thread overview]
Message-ID: <20170820204030.GA8206@ACM> (raw)
In-Reply-To: <CADdV=MtiJ1MXLu34BTp-h1mOxe1C0Wc2XZw2MJufY3GwGzQ5aQ@mail.gmail.com>

Hello, Nikolai.

On Tue, Aug 15, 2017 at 11:57:25 +0200, Nikolai Weibull wrote:
> On Tue, Aug 15, 2017 at 11:03 AM, Stefan Monnier
> <monnier@iro.umontreal.ca> wrote:
> >> C-mode doesn’t seem to understand C99’s compound literals, resulting in
> >> rather broken indentation.  Is this correct and, if so, how difficult would
> >> it be to add support for it?

> > Could you show some example problematic code?

> Yes:

> struct a {
>         int b;
> };

This seems to be correctly analysed and indented by CC Mode.  You can
see this by doing C-c C-s on any line to get the syntactic analysis.  On
the middle line, this shows ((inclass 332) (topmost-intro 332)) (where
the "332" may vary, depending on the position in the file).  The
"inclass" bit causes an indentation of c-basic-offset (here 8) columns.

What indentation do you want here?

> int
> main(void)
> {
>         return (struct a){
>                 0
>                         }.b;
> }

Here, the "0" line is being wrongly analysed as a statement-block-intro,
when it should be a brace-list-intro.  The problem is that brace lists
are recognised only by their context in the source code, rather than
their internal structure.  When a brace list can appear virtually
anywhere, this doesn't make sense.

The following patch causes brace lists to be recognised by their
internal structure too.  Would you please apply it to CC Mode (in
directory .../lisp/progmodes), try it out, and let me know how well it
solves the problems with compound literals.



diff -r 9533dc4cbda3 cc-engine.el
--- a/cc-engine.el	Thu Jul 27 17:37:02 2017 +0000
+++ b/cc-engine.el	Sun Aug 20 20:00:49 2017 +0000
@@ -10658,26 +10658,35 @@
 
 (defun c-looking-at-statement-block ()
   ;; Point is at an opening brace.  If this is a statement block (i.e. the
-  ;; elements in it are terminated by semicolons) return t.  Otherwise, return
-  ;; nil.
+  ;; elements in the block are terminated by semicolons, or the block is
+  ;; empty, or the block contains a keyword) return t.  Otherwise, return nil.
   (let ((here (point)))
     (prog1
 	(if (c-go-list-forward)
 	    (let ((there (point)))
 	      (backward-char)
-	      (c-syntactic-skip-backward
-	       "^;," here t)
+	      (c-syntactic-skip-backward "^;," here t)
 	      (cond
 	       ((eq (char-before) ?\;) t)
 	       ((eq (char-before) ?,) nil)
-	       (t (goto-char here)
-		  (forward-char)
-		  (and (c-syntactic-re-search-forward "{" there t t)
-		       (progn (backward-char)
-			      (c-looking-at-statement-block))))))
+	       (t 			; We're at (1+ here).
+		(cond
+		 ((progn (c-forward-syntactic-ws)
+			 (eq (point) (1- there)))
+		  t)
+		 ((c-syntactic-re-search-forward c-keywords-regexp there t)
+		  t)
+		 ((c-syntactic-re-search-forward "{" there t t)
+		  (backward-char)
+		  (c-looking-at-statement-block))
+		 (t nil)))))
 	  (forward-char)
-	  (and (c-syntactic-re-search-forward "[;,]" nil t t)
-	       (eq (char-before) ?\;)))
+	  (cond
+	   ((c-syntactic-re-search-forward "[;,]" nil t t)
+	    (eq (char-before) ?\;))
+	   ((c-syntactic-re-search-forward c-keywords-regexp nil t t)
+	    t)
+	   (t nil)))
       (goto-char here))))
 
 (defun c-looking-at-inexpr-block (lim containing-sexp &optional check-at-end)
@@ -12467,7 +12476,11 @@
 			    (save-excursion
 			      (goto-char containing-sexp)
 			      (c-looking-at-special-brace-list)))
-		       (c-inside-bracelist-p containing-sexp paren-state))))
+		       (c-inside-bracelist-p containing-sexp paren-state)
+		       (save-excursion
+			 (goto-char containing-sexp)
+			 (and (eq (char-after) ?{)
+			      (not (c-looking-at-statement-block)))))))
 	(cond
 
 	 ;; CASE 9A: In the middle of a special brace list opener.


[ .... ]

>   Nikolai

-- 
Alan Mackenzie (Nuremberg, Germany).



  parent reply	other threads:[~2017-08-20 20:40 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-15  8:04 C99 compound literals in c-mode Nikolai Weibull
2017-08-15  9:03 ` Stefan Monnier
2017-08-15  9:56   ` Nikolai Weibull
2017-08-15  9:57   ` Helmut Eller
2017-08-15  9:57   ` Nikolai Weibull
2017-08-16 17:26     ` Alan Mackenzie
2017-08-16 17:52       ` Nikolai Weibull
2017-08-20 20:40     ` Alan Mackenzie [this message]
2017-08-23 10:01       ` Nikolai Weibull
2017-08-24 16:37         ` Alan Mackenzie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170820204030.GA8206@ACM \
    --to=acm@muc.de \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    --cc=now@disu.se \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).