On Tue, 18 Oct 2016, Junjie Mao wrote:
> Hi all,
>
> I'm recently collecting collateral evolutions in Linux, inferring the
> patterns in these patches and generate semantic patches for maintainers
> of out-of-tree modules. During the work I am not sure how to express the
> following cases in SmPL.
>
> 1. add a reader for a structure field
>
> For example, in the following code
>
> 1 int foo(struct device* dev, int mask) {
> 2 int old_flags = dev->flags;
> 3 dev->flags &= mask;
> 4 return (dev->flags == old_flags);
> 5 }
>
> 'dev->flags' need to be replaced by 'dev_flags(dev)' where
> dev_flags(dev) is a function returning 'dev->flags'. The following
> semantic patch:
>
> @@
> struct device *dev;
> @@
> -dev->flags
> +dev_flags(dev)
>
> will rewrites all occurences of 'dev->flags', including the one on
> line 3, which makes the program incorrect. How can I avoid touching
> line 3 while updating line 2 and line 4 using spatch?
(
dev->flags = e
|
- dev->flags
+ dev_flags(dev)
)
A disjunction should take the first pattern that matches.
>
> Related commits:
> -
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=2f064f3485cd29633ad1b3cfb00cc519509a3d72
> -
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=4d0e965732db6f7cce78e6b8f5d3073249004c3a
>
> 2. rewriting part of a branch condition
>
> int foo(int i, int j) {
> if (i > 3 && i < 10 && j > 5 && j < 8)
> return i;
> return j;
> }
>
> If a commit replaces (i < 10 && j > 5) with (i < 8) (the order of
> comparisons and logical operators are fixed), how can I express this
> pattern in SmPL?
>
> I have tried the following, but it does not work.
>
> @@
> identifier foo, i, j;
> @@
> foo(int i, int j) {
> <...
> - i < 10 && j > 5
> + i < 8
> ...>
> }
>
> Related commit:
> -
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=dc3f4198eac14e52a98dfc79cd84b45e280f59cd
This is due to how the && is parsed. a && b && c && d is either parsed as
((a && b) && c) && d or a && (b && (c && d)) (I don't remember which), but
neither has b && c as a sub parse tree. I think that the only possibility
here is to make some special cases.
> 3. add a statement right after local variable declarations
>
> In the following function,
>
> int foo(int i) {
> int j,k,l;
>
> j = baz(i);
> ...
> }
>
> How can I add the statement 'bar(i);' before 'j = baz(i)' but after
> the local variable declarations?
f(...) {
... when != S
+ newcode
S1
...
}
Declarations don't match S (statement metavariable).
> Related commit:
> -
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=54efd50bfd873e2dbf784e0b21a8027ba4299a3e
>
> 4. change callback prototypes
>
> Assume a driver defines a global structure initialized with
> callbacks:
>
> 1 int foo(int i, int j) { ... }
> 2 int bar(int i, int j) { ... }
> 3
> 4 struct netdev_ops ops = {
> 5 .foo = foo,
> 6 };
>
> and a commit requires the prototype of the callback being changed to
> foo(int i, int j, intk), how can I achieve that without touching
> bar() using spatch?
@r@
identifier i,f;
@@
struct netdev_ops i = { .foo = f, };
@@
identifier r.f;
@@
Now do whatever you want with f
---
julia
> Related commit:
> -
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=88e72717c2de4181d8a6de1b04315953ad2bebdf
> -
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=dece16353ef47d8d33f5302bc158072a9d65e26f
>
> --
> Best Regards
> Junjie Mao
> _______________________________________________
> Cocci mailing list
> [email protected]
> https://systeme.lip6.fr/mailman/listinfo/cocci
>
_______________________________________________
Cocci mailing list
[email protected]
https://systeme.lip6.fr/mailman/listinfo/cocci