<br><br><div class="gmail_quote">On Thu, May 17, 2012 at 2:14 AM, Guillem Marpons <span dir="ltr"><<a href="mailto:gmarpons@babel.ls.fi.upm.es" target="_blank">gmarpons@babel.ls.fi.upm.es</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi,<br>
<br>
I've been working the last months on a coding rule validation add-on<br>
for clang/LLVM, called Crisp:<br>
<br>
    <a href="https://github.com/gmarpons/Crisp" target="_blank">https://github.com/gmarpons/Crisp</a><br>
<br>
Coding Rules constrain admissible constructs of a language to help<br>
produce better code (improving reliability, portability,<br>
maintainability, etc.). Some well-known coding rule sets are:<br>
<br>
- MISRA-C/C++ (no public access available)<br>
- High Integrity C++ Coding Standard (HICPP): <a href="http://www.codingstandard.com/" target="_blank">http://www.codingstandard.com/</a><br>
- CERT's Secure Coding Standards: <a href="http://www.cert.org/secure-coding/" target="_blank">http://www.cert.org/secure-coding/</a><br>
<br>
Coding rule sets can include style conventions but they go typically<br>
further. Rules range from purely syntactic properties (e.g. "Do not<br>
use the ‘inline’ keyword for member functions") to those that need<br>
deep static analyses to be automated (e.g. "Do not return non-const<br>
handles to class data from const member functions", both examples are<br>
from HICPP).<br>
<br>
There are some tools that can be used to define and enforce coding<br>
rules on C/C++ code. Some distinctive features of our tool are:<br>
<br>
- Rules (i.e., user checks) are going to be defined using a high-level<br>
declarative Domain Specific Language. This language, called CRISP, is<br>
not implemented yet. CRISP is based on first order logic, and rule<br>
definitions are expected to be very concise and easy to read (see<br>
below). The use of CRISP to formally define rules should avoid the<br>
ambiguity and imprecision problems that arise with current standard<br>
rule sets (they use plain English to define rules), and make the tool<br>
highly and easily extensible (which is important, as almost every<br>
project establish its own set of rules). E.g., part of<br>
<a href="http://llvm.org/docs/CodingStandards.html" target="_blank">http://llvm.org/docs/CodingStandards.html</a> could be probably formalized<br>
and automatically enforced.<br>
- It uses clang as front-end, taking advantage of its rich AST. The<br>
full clang API is available to write new rules. Rules can be checked<br>
during ordinary execution.<br>
- It can integrate information from static analyses to implement<br>
rules. At time being, the only interfaced analysis is alias analysis<br>
as implemented in LLVM.<br>
- It's free software.<br>
<br>
Example<br>
=======<br>
<br>
Take as example rule HICPP 3.3.13: "Do not invoke virtual methods of<br>
the declared class in a constructor or destructor".<br>
<br>
This rule was discussed in this mailing list some months ago:<br>
<a href="http://lists.cs.uiuc.edu/pipermail/cfe-dev/2011-September/thread.html#17024" target="_blank">http://lists.cs.uiuc.edu/pipermail/cfe-dev/2011-September/thread.html#17024</a>.<br>
A justification of the rule can be found here:<br>
<a href="http://www.codingstandard.com/HICPPCM/High_Integrity_CPP_Rule_3.3.13.html" target="_blank">http://www.codingstandard.com/HICPPCM/High_Integrity_CPP_Rule_3.3.13.html</a>.<br>
<br>
A tentative formalization in CRISP could be the following (many<br>
details of CRISP are not defined, yet):<br>
<br>
rule    HICPP 3.3.13<br>
warn    "ctor/dtor %0 calls (maybe indirectly) virtual method %1"<br>
vars    Caller is CXXMethodDecl, note "caller %0 declared here"<br>
        Callee is CXXMethodDecl, note "callee %0 declared here"<br>
def     Record is CXXRecordDecl<br>
        Record has ctor or destructor Caller<br>
        Record has method Callee<br>
        Callee is virtual<br>
        Caller calls+ Callee where ( CallExpr is CXXMemberCallExpr<br>
                                   CallExpr has implicitObjectArgument<br>
MemberExpr<br>
                                   MemberExpr is CXXThisExpr )<br>
<br>
Words beginning with a capital letter are either CRISP variables or clang types.<br>
<br>
<br>
Implementation<br>
==============<br>
<br>
The tool is implemented as a clang plug-in plus a LLVM module pass<br>
that has access to alias analysis information.<br>
<br>
CRISP is meant to be automatically translated into Prolog, and then<br>
rule validation machinery is executed in Prolog. In its current<br>
status, our tool can be extended with rules directly written in<br>
Prolog. For example, rule HICPP 3.3.13 has been defined as follows<br>
(which is quite difficult to read to people not acquainted to Prolog,<br>
but not that complex, and far more concise that a manual check written<br>
in C++):<br>
<br>
violation('HICPP 3.3.13',<br>
          'ctor/dtor %0 calls (maybe indirectly) virtual method %1',<br>
          [ 'NamedDecl'(Caller, 'caller %0 declared here')<br>
          , 'NamedDecl'(Callee, 'callee %0 declared here')]) :-<br>
        isA(Record, 'CXXRecordDecl'),<br>
        ( 'CXXRecordDecl::ctor'(Record, Caller)<br>
        ; 'CXXRecordDecl::destructor'(Record, Caller)<br>
        ),<br>
        'CXXRecordDecl::method'(Record, Callee),<br>
        'CXXMethodDecl::is_virtual'(Callee),                       %<br>
implies Caller \= Callee<br>
        'calls_to_this+'(Caller, Callee).<br>
<br>
The diagnostic reporting machinery of clang is used to inform the user<br>
about rule violations (they are reported as warnings, and for every<br>
code entity involved a "note" message is generated).<br>
<br>
A number of const methods and iterators from the C++ API are available<br>
from Prolog code to write rules. There are more than a thousand<br>
functions (or Prolog predicates) available so far: those of classes<br>
inheriting from Decl, Type or Stmt, so an enormous number of rules can<br>
be easily written. Examples of Prolog predicates available in the rule<br>
above are 'CXXRecordDecl::ctor' (an iterator in clang) and<br>
'CXXMethodDecl::is_virtual' (a method in clang, with slightly<br>
different name). Methods and iterators from llvm::Value heirs can also<br>
be used for rules that need alias analysis. 'calls_to_this+' is<br>
implemented in Prolog.<br>
<br>
All this Prolog binding of clang/LLVM is automatically generated<br>
during the build process of the tool. In fact, this binding is useful<br>
in itself, as it could be used to, e.g., implement:<br>
<br>
- A documentation tool<br>
- A refactoring tool<br>
- An API analysis tool for automatically generate bindings for other languages<br>
- More ideas??<br>
<br>
Well, I think it's enough information for one single mail. Detailed<br>
installation instructions are given here:<br>
<a href="https://github.com/gmarpons/Crisp" target="_blank">https://github.com/gmarpons/Crisp</a>. Any comments, criticisms, ideas<br>
will be really welcome,<br>
<br>
--<br>
Guillem Marpons<br>
Universidad Politécnica de Madrid - Babel Group<br></blockquote></div><br>Impressive!<br><br>There has been some talk on a new tool called clang-format to automatically apply style rules (indentation, brace placement, ...) and the discussion had been that a more involved coding-rules tool would be welcome but would be much more involved. It is great to see that you seem so advanced already.<br>
<br>I have been looking for this kind of automatic coding-rule checker for a while, and kudos for using HICPP (Misra et al are good... but *very* restrictive, and not really modern).<br><br>-- Matthieu<br>