<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body text="#000000" bgcolor="#FFFFFF">
Hi,<br>
<br>
It depends on how strict do you want the checking be and on the
details of the rule. If you're designing a new API from scratch and
stuck with gcc forever, i wouldn't mind using the gcc
__attribute__((cleanup())) for your purpose.<br>
<br>
The rule you described should be reasonably easy to implement with
the Static Analyzer. The good side of it is that you get a lot of
semantic modeling for free. For instance, if the developer copies
`dev` into a local variable and then uses that local variable
outside of api_enter..api_exit, the tool will be able to handle
transparently, as it deals with values rather than with variables.
Also it will probably be the easiest tool for your problem. The
downside would be that it's not guaranteed to find all bugs; it'll
inevitably give up on complicated code with high cyclomatic
complexity :) So if you want strict/paranoid enforcement of rules,
the Static Analyzer is not the right tool. But if you want to simply
find some bugs for free, it's the right tool.<br>
<br>
It sounds as if your problem is not inter-procedural. Let me
double-check this: would you have another api_enter..api_exit pair
in the body of your tweak() function? Or is just one
api_enter..api_exit enough? Or is it a bug to call api_enter twice
without an api_exit in between?<br>
<br>
If you have to write api_enter..api_exit in *every* function that
deals with devices, then the problem is not inter-procedural, which
makes it much easier. In particular, you should be able to come up
with a purely syntactic analysis ("every function that accesses a
device_t must start with api_enter() and must end in exactly one
spot with api_exit()"). Such analysis should be easily do-able in
clang-tidy as long as you're satisfied with this level of
aggressiveness. In particular, you'll have to be willing to
sacrifice code like this:<br>
<br>
void foo(device_t *dev) {<br>
if (flip_a_coin()) {<br>
api_enter(dev);<br>
...<br>
api_exit(dev);<br>
}<br>
}<br>
<br>
But it may be perfectly fine if you seriously want to enforce a
strict structure on all your functions that deal with devices.<br>
<br>
I think the truly-truly right tool for your problem would be to come
up with a custom analysis over Clang CFG. It would be harder to
implement, but it would allow you to express things like "every
execution path within a function that accesses `dev` must have a
api_enter before it and an api_exit after it; you are not allowed to
copy `dev` around". This would strictly enforce the rule. At the
same time it'll allow you to lift the requirement of exactly one
return point - you would still be able to ensure that all accesses
are covered. If you need to allow to copy `dev` around, it should
still be doable, but it will be significantly more difficult to
implement.<br>
<br>
<div class="moz-cite-prefix">On 7/2/19 12:13 PM, Billy O'Mahony via
cfe-dev wrote:<br>
</div>
<blockquote type="cite"
cite="mid:CAEHc-tV67OO3Zf-y4PLe1gPo3Vzdsgm4mGq6=_d4OMeWXGA8Xg@mail.gmail.com">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<div dir="ltr">
<div>Hello,</div>
<div><br>
</div>
<div>I'd like to write a rule for either clang-tidy or static
analyzer to help catch some potential errors in a project I'm
working on.</div>
<div><br>
</div>
<div>My questions are: <br>
</div>
<div> a) is only one or the other will be able to do what I
want to do?<br>
</div>
<div> b) if both are feasible which would have the simpler
implementation?</div>
<div><br>
</div>
<div>The project involves writing an API that will run in a
multi-threaded application and is responsible for serializing
all access to a device structure. Therefore the first thing in
every function in the API must be to call api_enter (which
will among other things acquire a mutex on the device) and the
last thing before returning must be to call api_exit. Also I
want to enforce single exit point from every API function - or
certainly if there are any return points that bypass the
api_exit call.<br>
</div>
<div><br>
</div>
<div>So here is an example function with errors I want to catch
highlighted.</div>
<div><br>
</div>
<div>int api_foo(device_t *dev) {</div>
<div> int ret_val = 0;<br>
</div>
<div><br>
</div>
<div> bar(); // fn calls & decls before api_enter is ok-
just don't access dev.</div>
<div> dev->bla = 1; // NO! device access before
api_enter() called</div>
<div> api_enter(dev); // error if this call is not present
exactly once</div>
<div><br>
</div>
<div> if (dev->bla)</div>
<div> return; // NO! didn't call api_exit before rtn.
Also two return points</div>
<div><br>
</div>
<div> if (dev->ma) {</div>
<div> ret_val = 1;<br>
</div>
<div> goto cleanup;</div>
<div> }</div>
<div> tweak(dev);<br>
</div>
<div><br>
</div>
<div>cleanup:</div>
<div> api_exit(dev); // error if this is not present exactly
once<br>
</div>
<div> dev->bla = 1; //NO! device access after api_exit()<br>
</div>
<div> return ret_val;<br>
</div>
<div>}</div>
<div><br>
</div>
<div>I don't think it matters but the project is C compiled with
gcc.<br>
</div>
<div><br>
</div>
<div>Also if both are feasible any other pointers, tips or good
resources would be appreciated. E.g is there a totally
different methodology I'm not considering - e.g. would using
something like pycparser be a lot easier - though I'd prefer
to keep it in clang as we plan to use tidy & static
analyzer in any case for standard QA.<br>
</div>
<div><br>
</div>
<div>Thanks for reading,</div>
<div>Billy.<br>
</div>
</div>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset>
<pre class="moz-quote-pre" wrap="">_______________________________________________
cfe-dev mailing list
<a class="moz-txt-link-abbreviated" href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>
<a class="moz-txt-link-freetext" href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a>
</pre>
</blockquote>
<br>
</body>
</html>