On 12/29/2011 02:02 PM, Artem Bityutskiy wrote:
> Hi,
> 
> I am trying to clean-up the MTD linux kernel subsystem and I have
> some troubles with writing a semantic patch. I've created a small
> example.c file:
> 
> $ cat example.c 
> static int mtd_read(int *retlen)
> {
>         *retlen = 0;
>         return 0;
> }
> 
> static void mtdchar_read1(void)
> {
>         int retlen;
> 
>         retlen = 0;
>         mtd_read(&retlen);
> }
> 
> static void mtdchar_read2(void)
> {
>         int retlen = 0;
> 
>         mtd_read(&retlen);
> }
> 
> static void mtdchar_read3(void)
> {
>         int retlen;
>         int mode = 1;
> 
>         retlen = 0;
> 
>         switch (mode) {
>         case 1:
>                 mtd_read(&retlen);
>                 break;
>         case 2:
>                 break;
>         }
> }
> 
> I know that mtd_read initialized the retlen to 0, so I do not want the
> callers to do this. I want to find all the places. Here is the semantic
> patch I've tried:
> 
> $ cat retlen.cocci 
> @@
> identifier retlen;
> @@
> - retlen = 0
> ...
> mtd_read(&retlen)
> 
> And here is the result:
> 
> $ spatch -sp_file retlen.cocci example.c
> init_defs_builtins: /usr/share/coccinelle/standard.h
> the simple assignment expression on line 4 contains transformations
> that prevent it from matching a declaration (multiple replacements)
> 
> HANDLING: example.c
> diff = 
> --- example.c
> +++ /tmp/cocci-output-16957-5edc2c-example.c
> @@ -8,7 +8,7 @@ static void mtdchar_read1(void)
>  {
>         int retlen;
>  
> -       retlen = 0;
> +       ;
>         mtd_read(&retlen);
>  }
> 
> I have several questions:
> 
> 1. Warning about "preventing from matching a declaration" worries me. As
>    I understand - a declaration is a construct like "int a" or
>    "static long x, y=0, z", etc (C99 6.7).
> 
>    But I do want to match "int retlen = 0"... What should I do?
>    IOW, how to match 'mtdchar_read2()' ?

Since you want to remove the complete statement if its only an assignment, but
only the assignment if it is a declaration plus assignment it is probably
better to have two different matches for this.

e.g.

(
-retlen = 0;
|
-int retlen = 0;
+int retlen;
)

On a sidenote: If you know that mtd_read will overwrite retlen anyway you can
probably just remove any assignments to it before the mtd_read call, not just
the 0 case. Although to be safe it is probably a good idea to add a check
whether retlen is used between the assignment and the mtd_read call.

> 
> 3. Why "mtdchar_read3()" does not match?

It does not match because there is no mtd_read(&retlen) on all possible paths.
In your case there are two paths in the switch statement.
If you'd want it to match anyway you can use a subexpression. e.g.
'<+...mtd_read(&retlen)...+>'. But this has the downside that retlen might be
used uninitialized at a later point.

- Lars
_______________________________________________
Cocci mailing list
[email protected]
http://lists.diku.dk/mailman/listinfo/cocci
(Web access from inside DIKUs LAN only)

Reply via email to