qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v2] add macro file for coccinelle
@ 2015-09-07 10:21 Paolo Bonzini
  2015-09-08 11:10 ` Markus Armbruster
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Paolo Bonzini @ 2015-09-07 10:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-trivial, peter.maydell, armbru

Coccinelle chokes on some idioms from compiler.h and queue.h.
Extract those in a macro file, to be used with "--macro-file
scripts/cocci-macro-file.h".

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 scripts/cocci-macro-file.h | 119 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 119 insertions(+)
 create mode 100644 scripts/cocci-macro-file.h

diff --git a/scripts/cocci-macro-file.h b/scripts/cocci-macro-file.h
new file mode 100644
index 0000000..eceb4be
--- /dev/null
+++ b/scripts/cocci-macro-file.h
@@ -0,0 +1,119 @@
+/* Macro file for Coccinelle
+ *
+ * Copyright (C) 2015 Red Hat, Inc.
+ *
+ * Authors:
+ *  Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or, at your
+ * option, any later version.  See the COPYING file in the top-level directory.
+ */
+
+/* Coccinelle only does limited parsing of headers, and chokes on some idioms
+ * defined in compiler.h and queue.h.  Macros that Coccinelle must know about
+ * in order to parse .c files must be in a separate macro file---which is
+ * exactly what you're staring at now.
+ *
+ * To use this file, add the "--macro-file scripts/cocci-macro-file.h" to the
+ * Coccinelle command line.
+ */
+
+/* From qemu/compiler.h */
+#define QEMU_GNUC_PREREQ(maj, min) 1
+#define QEMU_NORETURN __attribute__ ((__noreturn__))
+#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
+#define QEMU_SENTINEL __attribute__((sentinel))
+#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
+#define QEMU_PACKED __attribute__((gcc_struct, packed))
+
+#define cat(x,y) x ## y
+#define cat2(x,y) cat(x,y)
+#define QEMU_BUILD_BUG_ON(x) \
+    typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1] __attribute__((unused));
+
+#define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
+
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+#define stringify(s)	tostring(s)
+#define tostring(s)	#s
+
+#define typeof_field(type, field) typeof(((type *)0)->field)
+#define type_check(t1,t2) ((t1*)0 - (t2*)0)
+
+/* From qemu/queue.h */
+
+#define QLIST_HEAD(name, type)                                          \
+struct name {                                                           \
+        struct type *lh_first;  /* first element */                     \
+}
+
+#define QLIST_HEAD_INITIALIZER(head)                                    \
+        { NULL }
+
+#define QLIST_ENTRY(type)                                               \
+struct {                                                                \
+        struct type *le_next;   /* next element */                      \
+        struct type **le_prev;  /* address of previous next element */  \
+}
+
+/*
+ * Singly-linked List definitions.
+ */
+#define QSLIST_HEAD(name, type)                                          \
+struct name {                                                           \
+        struct type *slh_first; /* first element */                     \
+}
+
+#define QSLIST_HEAD_INITIALIZER(head)                                    \
+        { NULL }
+
+#define QSLIST_ENTRY(type)                                               \
+struct {                                                                \
+        struct type *sle_next;  /* next element */                      \
+}
+
+/*
+ * Simple queue definitions.
+ */
+#define QSIMPLEQ_HEAD(name, type)                                       \
+struct name {                                                           \
+    struct type *sqh_first;    /* first element */                      \
+    struct type **sqh_last;    /* addr of last next element */          \
+}
+
+#define QSIMPLEQ_HEAD_INITIALIZER(head)                                 \
+    { NULL, &(head).sqh_first }
+
+#define QSIMPLEQ_ENTRY(type)                                            \
+struct {                                                                \
+    struct type *sqe_next;    /* next element */                        \
+}
+
+/*
+ * Tail queue definitions.
+ */
+#define Q_TAILQ_HEAD(name, type, qual)                                  \
+struct name {                                                           \
+        qual type *tqh_first;           /* first element */             \
+        qual type *qual *tqh_last;      /* addr of last next element */ \
+}
+#define QTAILQ_HEAD(name, type)                                         \
+struct name {                                                           \
+        type *tqh_first;      /* first element */                       \
+        type **tqh_last;      /* addr of last next element */           \
+}
+
+#define QTAILQ_HEAD_INITIALIZER(head)                                   \
+        { NULL, &(head).tqh_first }
+
+#define Q_TAILQ_ENTRY(type, qual)                                       \
+struct {                                                                \
+        qual type *tqe_next;            /* next element */              \
+        qual type *qual *tqe_prev;      /* address of previous next element */\
+}
+#define QTAILQ_ENTRY(type)                                              \
+struct {                                                                \
+        type *tqe_next;       /* next element */                        \
+        type **tqe_prev;      /* address of previous next element */    \
+}
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v2] add macro file for coccinelle
  2015-09-07 10:21 [Qemu-devel] [PATCH v2] add macro file for coccinelle Paolo Bonzini
@ 2015-09-08 11:10 ` Markus Armbruster
  2015-09-08 12:44   ` Paolo Bonzini
  2015-09-08 13:31   ` [Qemu-devel] [Qemu-trivial] " Marcel Apfelbaum
  2015-09-08 17:30 ` [Qemu-devel] " John Snow
  2015-09-15 17:55 ` Michael Tokarev
  2 siblings, 2 replies; 10+ messages in thread
From: Markus Armbruster @ 2015-09-08 11:10 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-trivial, peter.maydell, qemu-devel

Paolo Bonzini <pbonzini@redhat.com> writes:

> Coccinelle chokes on some idioms from compiler.h and queue.h.
> Extract those in a macro file, to be used with "--macro-file
> scripts/cocci-macro-file.h".
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>

I tested this as follows.  Coccinelle can report on its parsing
difficulties:

$ spatch --parse-c `git-ls-files | grep '\.c$'

Requires a generous ulimit -s, and produces tons of output.  The
interesting part here is the summary at the end:

    NB total files = 1923; perfect = 1377; pbs = 545; timeout = 0; =========> 71%
    nb good = 964472,  nb passed = 14824 =========> 1.48% passed
    nb good = 964472,  nb bad = 23759 =========> 97.63% good or passed


Repeat with --macro-file scripts/cocci-macro-file.h.

    NB total files = 1923; perfect = 1463; pbs = 459; timeout = 0; =========> 76%
    nb good = 910559,  nb passed = 15352 =========> 1.53% passed
    nb good = 910559,  nb bad = 77610 =========> 92.27% good or passed

The first line shows clear improvement: 86 more files are now deemed
"perfect".  I'm not sure how to read the remaining two lines.

Also interesting are the "maybe 10 most problematic tokens".  Before:

    -----------------------------------------------------------------------
    maybe 10 most problematic tokens
    -----------------------------------------------------------------------
    glue: present in 620 parsing errors
    example: 

           #define OP_32_64(x)                             \
                   glue(glue(case INDEX_op_, x), _i32):    \
                   glue(glue(case INDEX_op_, x), _i64)
    NULL: present in 507 parsing errors
    example: 
               vs->dev = (QVirtioDevice *)dev;
               g_assert(dev != NULL);
               g_assert_cmphex(vs->dev->device_type, ==, QVIRTIO_SCSI_DEVICE_ID);

    VMStateField: present in 502 parsing errors
    example: 
               .version_id = 1,
               .minimum_version_id = 1,
               .fields = (VMStateField[]) {
                   VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
    fields: present in 502 parsing errors
    example: 
               .version_id = 1,
               .minimum_version_id = 1,
               .fields = (VMStateField[]) {
                   VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
    minimum_version_id: present in 433 parsing errors
    example: 
               .version_id = 1,
               .minimum_version_id = 1,
               .fields = (VMStateField[]) {
                   VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
    uint32_t: present in 414 parsing errors
    example: 
                                       uint32_t *bg, uint32_t *fg,                 \
                                       VncPalette **palette) {                     \
                   uint##bpp##_t *data;                                            \
                   uint##bpp##_t c0, c1, ci;                                       \
    env: present in 400 parsing errors
    example: 
               int v = float32_compare_quiet(a, b, &env->fp_status);
               set_br(env, v != float_relation_greater, br);
           }
    version_id: present in 308 parsing errors
    example: 
               .version_id = 1,
               .minimum_version_id = 1,
               .fields = (VMStateField[]) {
                   VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
    x: present in 221 parsing errors
    example: 
               Int128 a = expand(x);
               Int128 r = int128_rshift(a, n);
               g_assert_cmpuint(r.lo, ==, l);
               g_assert_cmpuint(r.hi, ==, h);
    a: present in 197 parsing errors
    example: 
               vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
               g_assert(!qemu_file_get_error(loading));
               g_assert_cmpint(obj.a, ==, 10);
               g_assert_cmpint(obj.b, ==, 20);

After:

    -----------------------------------------------------------------------
    maybe 10 most problematic tokens
    -----------------------------------------------------------------------
    NULL: present in 506 parsing errors
    example: 
               vs->dev = (QVirtioDevice *)dev;
               g_assert(dev != NULL);
               g_assert_cmphex(vs->dev->device_type, ==, QVIRTIO_SCSI_DEVICE_ID);

    VMStateField: present in 502 parsing errors
    example: 
               .version_id = 1,
               .minimum_version_id = 1,
               .fields = (VMStateField[]) {
                   VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
    fields: present in 502 parsing errors
    example: 
               .version_id = 1,
               .minimum_version_id = 1,
               .fields = (VMStateField[]) {
                   VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
    minimum_version_id: present in 433 parsing errors
    example: 
               .version_id = 1,
               .minimum_version_id = 1,
               .fields = (VMStateField[]) {
                   VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
    env: present in 376 parsing errors
    example: 
               int v = float32_compare_quiet(a, b, &env->fp_status);
               set_br(env, v != float_relation_greater, br);
           }
    version_id: present in 308 parsing errors
    example: 
               .version_id = 1,
               .minimum_version_id = 1,
               .fields = (VMStateField[]) {
                   VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
    x: present in 221 parsing errors
    example: 
               Int128 a = expand(x);
               Int128 r = int128_rshift(a, n);
               g_assert_cmpuint(r.lo, ==, l);
               g_assert_cmpuint(r.hi, ==, h);
    a: present in 197 parsing errors
    example: 
               vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
               g_assert(!qemu_file_get_error(loading));
               g_assert_cmpint(obj.a, ==, 10);
               g_assert_cmpint(obj.b, ==, 20);
    b: present in 164 parsing errors
    example: 
                   uint64_t rl, rh;
                   muls64(&rl, &rh, test_s_data[i].a, test_s_data[i].b);
                   g_assert_cmpuint(rl, ==, test_s_data[i].rl);
                   g_assert_cmpint(rh, ==, test_s_data[i].rh);
    name: present in 150 parsing errors
    example: 
               g_assert(list != NULL);
               g_assert(QTAILQ_EMPTY(&list->head));
               g_assert_cmpstr(list->name, ==, "opts_list_01");

    -----------------------------------------------------------------------

Clearly visible is the effect of your cocci-macro-file.h's glue() .

> ---
>  scripts/cocci-macro-file.h | 119 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 119 insertions(+)
>  create mode 100644 scripts/cocci-macro-file.h
>
> diff --git a/scripts/cocci-macro-file.h b/scripts/cocci-macro-file.h
> new file mode 100644
> index 0000000..eceb4be
> --- /dev/null
> +++ b/scripts/cocci-macro-file.h
> @@ -0,0 +1,119 @@
> +/* Macro file for Coccinelle
> + *
> + * Copyright (C) 2015 Red Hat, Inc.
> + *
> + * Authors:
> + *  Paolo Bonzini <pbonzini@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or, at your
> + * option, any later version.  See the COPYING file in the top-level directory.
> + */
> +
> +/* Coccinelle only does limited parsing of headers, and chokes on some idioms
> + * defined in compiler.h and queue.h.  Macros that Coccinelle must know about
> + * in order to parse .c files must be in a separate macro file---which is
> + * exactly what you're staring at now.
> + *
> + * To use this file, add the "--macro-file scripts/cocci-macro-file.h" to the
> + * Coccinelle command line.
> + */
> +
> +/* From qemu/compiler.h */
> +#define QEMU_GNUC_PREREQ(maj, min) 1
> +#define QEMU_NORETURN __attribute__ ((__noreturn__))
> +#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
> +#define QEMU_SENTINEL __attribute__((sentinel))
> +#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
> +#define QEMU_PACKED __attribute__((gcc_struct, packed))
> +
> +#define cat(x,y) x ## y
> +#define cat2(x,y) cat(x,y)

Why not reuse glue()?

> +#define QEMU_BUILD_BUG_ON(x) \
> + typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1]
> __attribute__((unused));
> +
> +#define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
> +
> +#define xglue(x, y) x ## y
> +#define glue(x, y) xglue(x, y)
> +#define stringify(s)	tostring(s)
> +#define tostring(s)	#s
> +
> +#define typeof_field(type, field) typeof(((type *)0)->field)
> +#define type_check(t1,t2) ((t1*)0 - (t2*)0)
> +
[...]

Preferably with cat2() replaced by glue():
Reviewed-by: Markus Armbruster <armbru@redhat.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v2] add macro file for coccinelle
  2015-09-08 11:10 ` Markus Armbruster
@ 2015-09-08 12:44   ` Paolo Bonzini
  2015-09-08 13:08     ` Markus Armbruster
  2015-09-08 13:31   ` [Qemu-devel] [Qemu-trivial] " Marcel Apfelbaum
  1 sibling, 1 reply; 10+ messages in thread
From: Paolo Bonzini @ 2015-09-08 12:44 UTC (permalink / raw)
  To: Markus Armbruster; +Cc: qemu-trivial, peter maydell, qemu-devel

> > +/* From qemu/compiler.h */
> > +#define QEMU_GNUC_PREREQ(maj, min) 1
> > +#define QEMU_NORETURN __attribute__ ((__noreturn__))
> > +#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
> > +#define QEMU_SENTINEL __attribute__((sentinel))
> > +#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
> > +#define QEMU_PACKED __attribute__((gcc_struct, packed))
> > +
> > +#define cat(x,y) x ## y
> > +#define cat2(x,y) cat(x,y)
> 
> Why not reuse glue()?

Because the duplication is already in compiler.h, which should
use glue() instead of cat2().  Separate patch IMHO, but thanks
for noticing. :-)

Paolo

> > +#define QEMU_BUILD_BUG_ON(x) \
> > + typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1]
> > __attribute__((unused));
> > +
> > +#define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
> > +
> > +#define xglue(x, y) x ## y
> > +#define glue(x, y) xglue(x, y)
> > +#define stringify(s)	tostring(s)
> > +#define tostring(s)	#s
> > +
> > +#define typeof_field(type, field) typeof(((type *)0)->field)
> > +#define type_check(t1,t2) ((t1*)0 - (t2*)0)
> > +
> [...]
> 
> Preferably with cat2() replaced by glue():
> Reviewed-by: Markus Armbruster <armbru@redhat.com>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v2] add macro file for coccinelle
  2015-09-08 12:44   ` Paolo Bonzini
@ 2015-09-08 13:08     ` Markus Armbruster
  0 siblings, 0 replies; 10+ messages in thread
From: Markus Armbruster @ 2015-09-08 13:08 UTC (permalink / raw)
  To: Paolo Bonzini; +Cc: qemu-trivial, peter maydell, qemu-devel

Paolo Bonzini <pbonzini@redhat.com> writes:

>> > +/* From qemu/compiler.h */
>> > +#define QEMU_GNUC_PREREQ(maj, min) 1
>> > +#define QEMU_NORETURN __attribute__ ((__noreturn__))
>> > +#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
>> > +#define QEMU_SENTINEL __attribute__((sentinel))
>> > +#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
>> > +#define QEMU_PACKED __attribute__((gcc_struct, packed))
>> > +
>> > +#define cat(x,y) x ## y
>> > +#define cat2(x,y) cat(x,y)
>> 
>> Why not reuse glue()?
>
> Because the duplication is already in compiler.h, which should
> use glue() instead of cat2().  Separate patch IMHO, but thanks
> for noticing. :-)

The separate patch is commit 24134c4 :)

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [Qemu-trivial] [PATCH v2] add macro file for coccinelle
  2015-09-08 11:10 ` Markus Armbruster
  2015-09-08 12:44   ` Paolo Bonzini
@ 2015-09-08 13:31   ` Marcel Apfelbaum
  1 sibling, 0 replies; 10+ messages in thread
From: Marcel Apfelbaum @ 2015-09-08 13:31 UTC (permalink / raw)
  To: Markus Armbruster, Paolo Bonzini; +Cc: qemu-trivial, peter.maydell, qemu-devel

On 09/08/2015 02:10 PM, Markus Armbruster wrote:
> Paolo Bonzini <pbonzini@redhat.com> writes:
>
>> Coccinelle chokes on some idioms from compiler.h and queue.h.
>> Extract those in a macro file, to be used with "--macro-file
>> scripts/cocci-macro-file.h".
>>
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>
> I tested this as follows.  Coccinelle can report on its parsing
> difficulties:
>
> $ spatch --parse-c `git-ls-files | grep '\.c$'
>
> Requires a generous ulimit -s, and produces tons of output.  The
> interesting part here is the summary at the end:
>
>      NB total files = 1923; perfect = 1377; pbs = 545; timeout = 0; =========> 71%
>      nb good = 964472,  nb passed = 14824 =========> 1.48% passed
>      nb good = 964472,  nb bad = 23759 =========> 97.63% good or passed
>
>
> Repeat with --macro-file scripts/cocci-macro-file.h.
>
>      NB total files = 1923; perfect = 1463; pbs = 459; timeout = 0; =========> 76%
>      nb good = 910559,  nb passed = 15352 =========> 1.53% passed
>      nb good = 910559,  nb bad = 77610 =========> 92.27% good or passed
>
> The first line shows clear improvement: 86 more files are now deemed
> "perfect".  I'm not sure how to read the remaining two lines.
>
> Also interesting are the "maybe 10 most problematic tokens".  Before:
>
>      -----------------------------------------------------------------------
>      maybe 10 most problematic tokens
>      -----------------------------------------------------------------------
>      glue: present in 620 parsing errors
>      example:
>
>             #define OP_32_64(x)                             \
>                     glue(glue(case INDEX_op_, x), _i32):    \
>                     glue(glue(case INDEX_op_, x), _i64)
>      NULL: present in 507 parsing errors
>      example:
>                 vs->dev = (QVirtioDevice *)dev;
>                 g_assert(dev != NULL);
>                 g_assert_cmphex(vs->dev->device_type, ==, QVIRTIO_SCSI_DEVICE_ID);
>
>      VMStateField: present in 502 parsing errors
>      example:
>                 .version_id = 1,
>                 .minimum_version_id = 1,
>                 .fields = (VMStateField[]) {
>                     VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),

Hi Markus,

I talked to coccinelle maintainer some time ago about
the above C construct (fields = (VMStateField[]) {)
and sadly is not yet supported by the C parser.

If we want this we need to do it by ourselves :(

Thanks,
Marcel


>      fields: present in 502 parsing errors
>      example:
>                 .version_id = 1,
>                 .minimum_version_id = 1,
>                 .fields = (VMStateField[]) {
>                     VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
>      minimum_version_id: present in 433 parsing errors
>      example:
>                 .version_id = 1,
>                 .minimum_version_id = 1,
>                 .fields = (VMStateField[]) {
>                     VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
>      uint32_t: present in 414 parsing errors
>      example:
>                                         uint32_t *bg, uint32_t *fg,                 \
>                                         VncPalette **palette) {                     \
>                     uint##bpp##_t *data;                                            \
>                     uint##bpp##_t c0, c1, ci;                                       \
>      env: present in 400 parsing errors
>      example:
>                 int v = float32_compare_quiet(a, b, &env->fp_status);
>                 set_br(env, v != float_relation_greater, br);
>             }
>      version_id: present in 308 parsing errors
>      example:
>                 .version_id = 1,
>                 .minimum_version_id = 1,
>                 .fields = (VMStateField[]) {
>                     VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
>      x: present in 221 parsing errors
>      example:
>                 Int128 a = expand(x);
>                 Int128 r = int128_rshift(a, n);
>                 g_assert_cmpuint(r.lo, ==, l);
>                 g_assert_cmpuint(r.hi, ==, h);
>      a: present in 197 parsing errors
>      example:
>                 vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
>                 g_assert(!qemu_file_get_error(loading));
>                 g_assert_cmpint(obj.a, ==, 10);
>                 g_assert_cmpint(obj.b, ==, 20);
>
> After:
>
>      -----------------------------------------------------------------------
>      maybe 10 most problematic tokens
>      -----------------------------------------------------------------------
>      NULL: present in 506 parsing errors
>      example:
>                 vs->dev = (QVirtioDevice *)dev;
>                 g_assert(dev != NULL);
>                 g_assert_cmphex(vs->dev->device_type, ==, QVIRTIO_SCSI_DEVICE_ID);
>
>      VMStateField: present in 502 parsing errors
>      example:
>                 .version_id = 1,
>                 .minimum_version_id = 1,
>                 .fields = (VMStateField[]) {
>                     VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
>      fields: present in 502 parsing errors
>      example:
>                 .version_id = 1,
>                 .minimum_version_id = 1,
>                 .fields = (VMStateField[]) {
>                     VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
>      minimum_version_id: present in 433 parsing errors
>      example:
>                 .version_id = 1,
>                 .minimum_version_id = 1,
>                 .fields = (VMStateField[]) {
>                     VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
>      env: present in 376 parsing errors
>      example:
>                 int v = float32_compare_quiet(a, b, &env->fp_status);
>                 set_br(env, v != float_relation_greater, br);
>             }
>      version_id: present in 308 parsing errors
>      example:
>                 .version_id = 1,
>                 .minimum_version_id = 1,
>                 .fields = (VMStateField[]) {
>                     VMSTATE_VBUFFER_UINT32(data, Fifo8, 1, NULL, 0, capacity),
>      x: present in 221 parsing errors
>      example:
>                 Int128 a = expand(x);
>                 Int128 r = int128_rshift(a, n);
>                 g_assert_cmpuint(r.lo, ==, l);
>                 g_assert_cmpuint(r.hi, ==, h);
>      a: present in 197 parsing errors
>      example:
>                 vmstate_load_state(loading, &vmstate_skipping, &obj, 2);
>                 g_assert(!qemu_file_get_error(loading));
>                 g_assert_cmpint(obj.a, ==, 10);
>                 g_assert_cmpint(obj.b, ==, 20);
>      b: present in 164 parsing errors
>      example:
>                     uint64_t rl, rh;
>                     muls64(&rl, &rh, test_s_data[i].a, test_s_data[i].b);
>                     g_assert_cmpuint(rl, ==, test_s_data[i].rl);
>                     g_assert_cmpint(rh, ==, test_s_data[i].rh);
>      name: present in 150 parsing errors
>      example:
>                 g_assert(list != NULL);
>                 g_assert(QTAILQ_EMPTY(&list->head));
>                 g_assert_cmpstr(list->name, ==, "opts_list_01");
>
>      -----------------------------------------------------------------------
>
> Clearly visible is the effect of your cocci-macro-file.h's glue() .
>
>> ---
>>   scripts/cocci-macro-file.h | 119 +++++++++++++++++++++++++++++++++++++++++++++
>>   1 file changed, 119 insertions(+)
>>   create mode 100644 scripts/cocci-macro-file.h
>>
>> diff --git a/scripts/cocci-macro-file.h b/scripts/cocci-macro-file.h
>> new file mode 100644
>> index 0000000..eceb4be
>> --- /dev/null
>> +++ b/scripts/cocci-macro-file.h
>> @@ -0,0 +1,119 @@
>> +/* Macro file for Coccinelle
>> + *
>> + * Copyright (C) 2015 Red Hat, Inc.
>> + *
>> + * Authors:
>> + *  Paolo Bonzini <pbonzini@redhat.com>
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2 or, at your
>> + * option, any later version.  See the COPYING file in the top-level directory.
>> + */
>> +
>> +/* Coccinelle only does limited parsing of headers, and chokes on some idioms
>> + * defined in compiler.h and queue.h.  Macros that Coccinelle must know about
>> + * in order to parse .c files must be in a separate macro file---which is
>> + * exactly what you're staring at now.
>> + *
>> + * To use this file, add the "--macro-file scripts/cocci-macro-file.h" to the
>> + * Coccinelle command line.
>> + */
>> +
>> +/* From qemu/compiler.h */
>> +#define QEMU_GNUC_PREREQ(maj, min) 1
>> +#define QEMU_NORETURN __attribute__ ((__noreturn__))
>> +#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
>> +#define QEMU_SENTINEL __attribute__((sentinel))
>> +#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
>> +#define QEMU_PACKED __attribute__((gcc_struct, packed))
>> +
>> +#define cat(x,y) x ## y
>> +#define cat2(x,y) cat(x,y)
>
> Why not reuse glue()?
>
>> +#define QEMU_BUILD_BUG_ON(x) \
>> + typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1]
>> __attribute__((unused));
>> +
>> +#define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
>> +
>> +#define xglue(x, y) x ## y
>> +#define glue(x, y) xglue(x, y)
>> +#define stringify(s)	tostring(s)
>> +#define tostring(s)	#s
>> +
>> +#define typeof_field(type, field) typeof(((type *)0)->field)
>> +#define type_check(t1,t2) ((t1*)0 - (t2*)0)
>> +
> [...]
>
> Preferably with cat2() replaced by glue():
> Reviewed-by: Markus Armbruster <armbru@redhat.com>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v2] add macro file for coccinelle
  2015-09-07 10:21 [Qemu-devel] [PATCH v2] add macro file for coccinelle Paolo Bonzini
  2015-09-08 11:10 ` Markus Armbruster
@ 2015-09-08 17:30 ` John Snow
  2015-09-08 18:35   ` Markus Armbruster
  2015-09-15 17:55 ` Michael Tokarev
  2 siblings, 1 reply; 10+ messages in thread
From: John Snow @ 2015-09-08 17:30 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: qemu-trivial, peter.maydell, armbru



On 09/07/2015 06:21 AM, Paolo Bonzini wrote:
> Coccinelle chokes on some idioms from compiler.h and queue.h.
> Extract those in a macro file, to be used with "--macro-file
> scripts/cocci-macro-file.h".
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  scripts/cocci-macro-file.h | 119 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 119 insertions(+)
>  create mode 100644 scripts/cocci-macro-file.h
> 
> diff --git a/scripts/cocci-macro-file.h b/scripts/cocci-macro-file.h
> new file mode 100644
> index 0000000..eceb4be
> --- /dev/null
> +++ b/scripts/cocci-macro-file.h
> @@ -0,0 +1,119 @@
> +/* Macro file for Coccinelle
> + *
> + * Copyright (C) 2015 Red Hat, Inc.
> + *
> + * Authors:
> + *  Paolo Bonzini <pbonzini@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or, at your
> + * option, any later version.  See the COPYING file in the top-level directory.
> + */
> +
> +/* Coccinelle only does limited parsing of headers, and chokes on some idioms
> + * defined in compiler.h and queue.h.  Macros that Coccinelle must know about
> + * in order to parse .c files must be in a separate macro file---which is
> + * exactly what you're staring at now.
> + *
> + * To use this file, add the "--macro-file scripts/cocci-macro-file.h" to the
> + * Coccinelle command line.
> + */
> +
> +/* From qemu/compiler.h */
> +#define QEMU_GNUC_PREREQ(maj, min) 1
> +#define QEMU_NORETURN __attribute__ ((__noreturn__))
> +#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
> +#define QEMU_SENTINEL __attribute__((sentinel))
> +#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
> +#define QEMU_PACKED __attribute__((gcc_struct, packed))
> +
> +#define cat(x,y) x ## y
> +#define cat2(x,y) cat(x,y)
> +#define QEMU_BUILD_BUG_ON(x) \
> +    typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1] __attribute__((unused));
> +
> +#define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
> +
> +#define xglue(x, y) x ## y
> +#define glue(x, y) xglue(x, y)
> +#define stringify(s)	tostring(s)
> +#define tostring(s)	#s
> +
> +#define typeof_field(type, field) typeof(((type *)0)->field)
> +#define type_check(t1,t2) ((t1*)0 - (t2*)0)
> +
> +/* From qemu/queue.h */
> +
> +#define QLIST_HEAD(name, type)                                          \
> +struct name {                                                           \
> +        struct type *lh_first;  /* first element */                     \
> +}
> +
> +#define QLIST_HEAD_INITIALIZER(head)                                    \
> +        { NULL }
> +
> +#define QLIST_ENTRY(type)                                               \
> +struct {                                                                \
> +        struct type *le_next;   /* next element */                      \
> +        struct type **le_prev;  /* address of previous next element */  \
> +}
> +
> +/*
> + * Singly-linked List definitions.
> + */
> +#define QSLIST_HEAD(name, type)                                          \
> +struct name {                                                           \
> +        struct type *slh_first; /* first element */                     \
> +}
> +
> +#define QSLIST_HEAD_INITIALIZER(head)                                    \
> +        { NULL }
> +
> +#define QSLIST_ENTRY(type)                                               \
> +struct {                                                                \
> +        struct type *sle_next;  /* next element */                      \
> +}
> +
> +/*
> + * Simple queue definitions.
> + */
> +#define QSIMPLEQ_HEAD(name, type)                                       \
> +struct name {                                                           \
> +    struct type *sqh_first;    /* first element */                      \
> +    struct type **sqh_last;    /* addr of last next element */          \
> +}
> +
> +#define QSIMPLEQ_HEAD_INITIALIZER(head)                                 \
> +    { NULL, &(head).sqh_first }
> +
> +#define QSIMPLEQ_ENTRY(type)                                            \
> +struct {                                                                \
> +    struct type *sqe_next;    /* next element */                        \
> +}
> +
> +/*
> + * Tail queue definitions.
> + */
> +#define Q_TAILQ_HEAD(name, type, qual)                                  \
> +struct name {                                                           \
> +        qual type *tqh_first;           /* first element */             \
> +        qual type *qual *tqh_last;      /* addr of last next element */ \
> +}
> +#define QTAILQ_HEAD(name, type)                                         \
> +struct name {                                                           \
> +        type *tqh_first;      /* first element */                       \
> +        type **tqh_last;      /* addr of last next element */           \
> +}
> +
> +#define QTAILQ_HEAD_INITIALIZER(head)                                   \
> +        { NULL, &(head).tqh_first }
> +
> +#define Q_TAILQ_ENTRY(type, qual)                                       \
> +struct {                                                                \
> +        qual type *tqe_next;            /* next element */              \
> +        qual type *qual *tqe_prev;      /* address of previous next element */\
> +}
> +#define QTAILQ_ENTRY(type)                                              \
> +struct {                                                                \
> +        type *tqe_next;       /* next element */                        \
> +        type **tqe_prev;      /* address of previous next element */    \
> +}
> 

Having not used Coccinelle yet, what happens if any of these functions
become desynchronized ?

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v2] add macro file for coccinelle
  2015-09-08 17:30 ` [Qemu-devel] " John Snow
@ 2015-09-08 18:35   ` Markus Armbruster
  2015-09-09  9:51     ` Paolo Bonzini
  0 siblings, 1 reply; 10+ messages in thread
From: Markus Armbruster @ 2015-09-08 18:35 UTC (permalink / raw)
  To: John Snow; +Cc: qemu-trivial, Paolo Bonzini, qemu-devel, peter.maydell

John Snow <jsnow@redhat.com> writes:

> On 09/07/2015 06:21 AM, Paolo Bonzini wrote:
>> Coccinelle chokes on some idioms from compiler.h and queue.h.
>> Extract those in a macro file, to be used with "--macro-file
>> scripts/cocci-macro-file.h".
>> 
>> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
>> ---
>>  scripts/cocci-macro-file.h | 119
>> +++++++++++++++++++++++++++++++++++++++++++++
>>  1 file changed, 119 insertions(+)
>>  create mode 100644 scripts/cocci-macro-file.h
>> 
>> diff --git a/scripts/cocci-macro-file.h b/scripts/cocci-macro-file.h
>> new file mode 100644
>> index 0000000..eceb4be
>> --- /dev/null
>> +++ b/scripts/cocci-macro-file.h
>> @@ -0,0 +1,119 @@
>> +/* Macro file for Coccinelle
>> + *
>> + * Copyright (C) 2015 Red Hat, Inc.
>> + *
>> + * Authors:
>> + *  Paolo Bonzini <pbonzini@redhat.com>
>> + *
>> + * This work is licensed under the terms of the GNU GPL, version 2
>> or, at your
>> + * option, any later version.  See the COPYING file in the
>> top-level directory.
>> + */
>> +
>> +/* Coccinelle only does limited parsing of headers, and chokes on some idioms
>> + * defined in compiler.h and queue.h.  Macros that Coccinelle must know about
>> + * in order to parse .c files must be in a separate macro file---which is
>> + * exactly what you're staring at now.
>> + *
>> + * To use this file, add the "--macro-file scripts/cocci-macro-file.h" to the
>> + * Coccinelle command line.
>> + */
>> +
>> +/* From qemu/compiler.h */
[Stuff cribbed from various headers...]
>
> Having not used Coccinelle yet, what happens if any of these functions
> become desynchronized ?

Coccinelle transforms C to C.  Problem: if you parse C the normal way
(first run preprocessor, then the parser proper), you have to unparse
and unpreprocess at the end to get a useful result.  Unparsing is easy,
but unpreprocessing is hard.

Instead, Coccinelle tries to parse *unpreprocessed* C.  Works most of
the time, because most uses of function-like macros can be treated as if
they were function calls, and most uses of object-like macros can be
treated as if they were values.

When it doesn't work, Coccinelle needs to resort to magic and / or skip
over some code it can't decipher.  The latter is undesirable, because if
the skipped code contains something we'd like to transform, we won't.

Part of the magic is treating "bad" macros specially.  --macro-file
helps with that part: macros defined there are "bad".  Sorry, I can't
really explain it, -EMAGIC.  /usr/share/coccinelle/standard.h is used by
default.

So what happens when the this file gets out of sync?  Worst case is
Coccinelle misses a pattern it could find if it was in sync.

Provided the macro file makes sense initially, a moderately bit-rotten
version is still almost certainly better than nothing.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v2] add macro file for coccinelle
  2015-09-08 18:35   ` Markus Armbruster
@ 2015-09-09  9:51     ` Paolo Bonzini
  2015-09-10 21:23       ` John Snow
  0 siblings, 1 reply; 10+ messages in thread
From: Paolo Bonzini @ 2015-09-09  9:51 UTC (permalink / raw)
  To: Markus Armbruster, John Snow; +Cc: qemu-trivial, peter.maydell, qemu-devel



On 08/09/2015 20:35, Markus Armbruster wrote:
>> > Having not used Coccinelle yet, what happens if any of these functions
>> > become desynchronized ?
> Coccinelle transforms C to C.  Problem: if you parse C the normal way
> (first run preprocessor, then the parser proper), you have to unparse
> and unpreprocess at the end to get a useful result.  Unparsing is easy,
> but unpreprocessing is hard.
> 
> Instead, Coccinelle tries to parse *unpreprocessed* C.  Works most of
> the time, because most uses of function-like macros can be treated as if
> they were function calls, and most uses of object-like macros can be
> treated as if they were values.
> 
> When it doesn't work, Coccinelle needs to resort to magic and / or skip
> over some code it can't decipher.  The latter is undesirable, because if
> the skipped code contains something we'd like to transform, we won't.
> 
> Part of the magic is treating "bad" macros specially.  --macro-file
> helps with that part: macros defined there are "bad".  Sorry, I can't
> really explain it, -EMAGIC.  /usr/share/coccinelle/standard.h is used by
> default.
> 
> So what happens when the this file gets out of sync?  Worst case is
> Coccinelle misses a pattern it could find if it was in sync.
> 
> Provided the macro file makes sense initially, a moderately bit-rotten
> version is still almost certainly better than nothing.

Great answer.  I'll only add that exactly the same issue happens with
the Coverity model.

Paolo

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v2] add macro file for coccinelle
  2015-09-09  9:51     ` Paolo Bonzini
@ 2015-09-10 21:23       ` John Snow
  0 siblings, 0 replies; 10+ messages in thread
From: John Snow @ 2015-09-10 21:23 UTC (permalink / raw)
  To: Paolo Bonzini, Markus Armbruster; +Cc: qemu-trivial, peter.maydell, qemu-devel



On 09/09/2015 05:51 AM, Paolo Bonzini wrote:
> 
> 
> On 08/09/2015 20:35, Markus Armbruster wrote:
>>>> Having not used Coccinelle yet, what happens if any of these functions
>>>> become desynchronized ?
>> Coccinelle transforms C to C.  Problem: if you parse C the normal way
>> (first run preprocessor, then the parser proper), you have to unparse
>> and unpreprocess at the end to get a useful result.  Unparsing is easy,
>> but unpreprocessing is hard.
>>
>> Instead, Coccinelle tries to parse *unpreprocessed* C.  Works most of
>> the time, because most uses of function-like macros can be treated as if
>> they were function calls, and most uses of object-like macros can be
>> treated as if they were values.
>>
>> When it doesn't work, Coccinelle needs to resort to magic and / or skip
>> over some code it can't decipher.  The latter is undesirable, because if
>> the skipped code contains something we'd like to transform, we won't.
>>
>> Part of the magic is treating "bad" macros specially.  --macro-file
>> helps with that part: macros defined there are "bad".  Sorry, I can't
>> really explain it, -EMAGIC.  /usr/share/coccinelle/standard.h is used by
>> default.
>>
>> So what happens when the this file gets out of sync?  Worst case is
>> Coccinelle misses a pattern it could find if it was in sync.
>>
>> Provided the macro file makes sense initially, a moderately bit-rotten
>> version is still almost certainly better than nothing.
> 
> Great answer.  I'll only add that exactly the same issue happens with
> the Coverity model.
> 
> Paolo
> 

Great, thanks for the info :)

--js

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [Qemu-devel] [PATCH v2] add macro file for coccinelle
  2015-09-07 10:21 [Qemu-devel] [PATCH v2] add macro file for coccinelle Paolo Bonzini
  2015-09-08 11:10 ` Markus Armbruster
  2015-09-08 17:30 ` [Qemu-devel] " John Snow
@ 2015-09-15 17:55 ` Michael Tokarev
  2 siblings, 0 replies; 10+ messages in thread
From: Michael Tokarev @ 2015-09-15 17:55 UTC (permalink / raw)
  To: Paolo Bonzini, qemu-devel; +Cc: qemu-trivial, peter.maydell, armbru

07.09.2015 13:21, Paolo Bonzini wrote:
> Coccinelle chokes on some idioms from compiler.h and queue.h.
> Extract those in a macro file, to be used with "--macro-file
> scripts/cocci-macro-file.h".

Applied to -trivial, thank you!

/mjt

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2015-09-15 17:55 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-09-07 10:21 [Qemu-devel] [PATCH v2] add macro file for coccinelle Paolo Bonzini
2015-09-08 11:10 ` Markus Armbruster
2015-09-08 12:44   ` Paolo Bonzini
2015-09-08 13:08     ` Markus Armbruster
2015-09-08 13:31   ` [Qemu-devel] [Qemu-trivial] " Marcel Apfelbaum
2015-09-08 17:30 ` [Qemu-devel] " John Snow
2015-09-08 18:35   ` Markus Armbruster
2015-09-09  9:51     ` Paolo Bonzini
2015-09-10 21:23       ` John Snow
2015-09-15 17:55 ` Michael Tokarev

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 NNTP newsgroup(s).