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)