From: josh@joshtriplett.org (Josh Triplett)
To: cocci@systeme.lip6.fr
Subject: [Cocci] Matching an absence of statements before the closing brace of a function?
Date: Sat, 2 Nov 2013 08:52:24 -0700 [thread overview]
Message-ID: <20131102155224.GX15704@leaf> (raw)
In-Reply-To: <alpine.DEB.2.02.1311021555360.2261@hadrien>
On Sat, Nov 02, 2013 at 04:02:28PM +0100, Julia Lawall wrote:
> On Sat, 2 Nov 2013, Josh Triplett wrote:
> > On Sat, Nov 02, 2013 at 03:27:35PM +0100, Julia Lawall wrote:
> > > On Sat, 2 Nov 2013, Josh Triplett wrote:
> > > > I wanted to write a semantic patch that matched (and removed) "return;"
> > > > at the end of a void function. I've attached the full .cocci file
> > > > written for coccicheck, but the key bit looks like this:
> > > >
> > > > @@
> > > > identifier fn;
> > > > @@
> > > > void fn ( ... )
> > > > {
> > > > ...
> > > > - return;
> > > > }
> > > >
> > > > However, that patch also produces results like this:
> > > >
> > > > --- a/drivers/scsi/aacraid/dpcsup.c
> > > > +++ b/drivers/scsi/aacraid/dpcsup.c
> > > > @@ -255,7 +255,6 @@ static void aac_aif_callback(void *conte
> > > > cpu_to_le32(NoMoreAifDataAvailable)) {
> > > > aac_fib_complete(fibptr);
> > > > aac_fib_free(fibptr);
> > > > - return;
> > > > }
> > > >
> > > > aac_intr_normal(dev, 0, 1, 0, fibptr->hw_fib_va);
> > > >
> > > > I'm guessing that either coccinelle didn't pair the braces (so that the
> > > > '}' matches close braces other than the one matching fn's opening brace)
> > > > or coccinelle allowed extra statements before the logical end of the
> > > > function despite the lack of '...'.
> > >
> > > The problem is that Coccinlle works on control-flow paths, and a return is
> > > always at the end of a control-flow path...
> >
> > Not sure I fully understand what you mean. I do understand why
> > coccinelle works on control-flow paths rather than literal code, and
> > that makes it much more powerful, but I'm still not sure how coccinelle
> > manages to match the patch above to the code above. Do the braces in
> > the semantic patch above not pair with each other? If not, why not? If
> > so, how does "return; }" match something between the "return;" and the
> > "}"?
>
> The return is followed by all of the nested }s to get it out of the
> function. I think that there is something special for these }s to skip
> over them, so that the return always seems to be next to the final }.
Huh. Odd.
> > > Try the following:
> > >
> > > @start@
> > > identifier f;
> > > position p;
> > > @@
> > > f(...) {@p ... }
> > >
> > > @bad@
> > > position p, s != start.p;
> > > @@
> > >
> > > {@s <... return;@p ...> }
> > >
> > > @ef@
> > > position p;
> > > statement S;
> > > @@
> > >
> > > (
> > > while (...) return;@p
> > > |
> > > if (...) return;@p else S
> > > )
> > >
> > > @@
> > > position p != {bad.p,ef.p};
> > > @@
> > >
> > > - return;@p
> >
> > Interesting; I didn't know about the ability to exclude specific
> > positions that way. However, that doesn't quite work, since it still
> > matches code like this:
>
> OK, good point. I will try to find something else.
>
> return;
> S
>
> doesn't work, because no statement follows a return. A return is just
> followed by a sequence of closing braces.
In the control-flow sense, sure. However, in addition to making this
particular case difficult, that also makes it difficult to use
coccinelle to detect dead code after a return.
> You can try this:
>
> @@
> @@
>
> - return;
> + RETURN;
>
> @r exists@
> identifier f;
> position p;
> @@
>
> f(...) {
> ...
> RETURN at p;
> }
>
> @@
> position r.p;
> @@
>
> - RETURN at p;
>
> @@
> @@
>
> - RETURN;
> + return;
Cute. I'm not sure why you need the two separate rules with matching
positions; consolidating the two middle rules into one seems to work as
well. I did have to add a rule for when the return immediately followed
a label, to make sure there was a statement to target.
However, this seems to have two issues. First, to some extent I
*wanted* the control-flow matching, to handle cases like this without
having to do so explicitly:
void f(void)
{
if (...) {
foo();
- return;
}
}
Second, this seems to lead to many formatting issues:
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -895,7 +895,7 @@ static void print_other_cpu_stall(struct
rcu_print_detail_task_stall(rsp);
- force_quiescent_state(rsp); /* Kick them all. */
+ force_quiescent_state(rsp);
}
static void print_cpu_stall(struct rcu_state *rsp)
No idea why coccinelle touched this comment. Do functions have an
implicit "return;" at the end that got patched here?
--- a/lib/xz/xz_crc32.c
+++ b/lib/xz/xz_crc32.c
@@ -43,7 +43,7 @@ XZ_EXTERN void xz_crc32_init(void)
xz_crc32_table[i] = r;
}
- return;
+ RETURN;
}
XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
No idea what happened here to prevent the RETURN; from getting
substituted back.
Also, I noticed some cases where the return; in question immediately
followed a label, so removing it would give that label no statement to
jump to. I tried handling that explicitly:
@r1 depends on patch exists@
identifier f, l;
statement S;
position p;
@@
void f(...)
{
...
(
l:
- RETURN;@p
S
|
l:
- RETURN at p
;
|
- RETURN;@p
)
}
However, while this did produce the desired result when the return
immeidately followed the label, it produced odd results in other cases:
--- a/crypto/seqiv.c
+++ b/crypto/seqiv.c
@@ -45,6 +45,7 @@ static void seqiv_complete2(struct skcip
out:
kfree(subreq->info);
+ return;
}
static void seqiv_complete(struct crypto_async_request *base, int err)
Many instances like this where coccinelle added "return;" where none
existed before.
- Josh Triplett
next prev parent reply other threads:[~2013-11-02 15:52 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-11-02 13:36 [Cocci] Matching an absence of statements before the closing brace of a function? Josh Triplett
2013-11-02 14:27 ` Julia Lawall
2013-11-02 14:54 ` Josh Triplett
2013-11-02 15:02 ` Julia Lawall
2013-11-02 15:52 ` Josh Triplett [this message]
2013-11-02 16:02 ` Julia Lawall
2013-11-02 16:28 ` Josh Triplett
2013-11-02 16:34 ` Julia Lawall
2013-11-02 16:27 ` Julia Lawall
2013-11-02 21:01 ` Julia Lawall
2013-11-02 14:46 ` [Cocci] if (...) {} semantic patch Julia Lawall
2013-11-02 15:01 ` Josh Triplett
2013-11-02 15:08 ` Julia Lawall
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
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20131102155224.GX15704@leaf \
--to=josh@joshtriplett.org \
--cc=cocci@systeme.lip6.fr \
/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.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.