Writing rules: More simplifications

This commit is contained in:
Daniel Marjamäki 2010-12-06 19:36:51 +01:00
parent 0b696b7079
commit 964852f14e
1 changed files with 37 additions and 92 deletions

View File

@ -8,7 +8,7 @@
<author> <author>
<firstname>Daniel</firstname> <firstname>Daniel</firstname>
<surname>Marjamäki</surname> <surname>Marjamaki</surname>
<affiliation> <affiliation>
<orgname>Cppcheck</orgname> <orgname>Cppcheck</orgname>
@ -21,34 +21,11 @@
<section> <section>
<title>Introduction</title> <title>Introduction</title>
<para>This is a short guide for developers who want to write Cppcheck <para>This is a short and simple guide that describes how rules are
rules.</para> written for Cppcheck.</para>
<para>There are two ways to write rules.</para> <para>The patterns are defined with regular expressions. It is required
that you know how regular expressions work.</para>
<variablelist>
<varlistentry>
<term>Regular expressions</term>
<listitem>
<para>Simple rules can be created by using regular expressions. No
compilation is required.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>C++</term>
<listitem>
<para>Advanced rules must be created with C++. These rules must be
compiled and linked statically with Cppcheck.</para>
</listitem>
</varlistentry>
</variablelist>
<para>It is a good first step to use regular expressions. It is easier.
You'll get results quicker. Therefore this guide will focus on regular
expressions.</para>
</section> </section>
<section> <section>
@ -59,105 +36,73 @@
before the rules are used.</para> before the rules are used.</para>
<para>Cppcheck is designed to find bugs and dangerous code. Stylistic <para>Cppcheck is designed to find bugs and dangerous code. Stylistic
information such as indentation, comments, etc are filtered out at an information (such as indentation, comments, etc) are filtered out at an
early state. You don't need to worry about such stylistic information when early state. You don't need to worry about such stylistic information when
you write rules.</para> you write rules.</para>
<para>Between each token in the code there is always a space. For instance <para>Between each token in the code there is always a space. For instance
the raw code "1+f()" is processed into "1 + f ( )".</para> the raw code "1+f()" is processed into "1 + f ( )".</para>
<para>The code is simplified in many ways. For example:</para> <para>The code is simplified in many ways.</para>
<itemizedlist>
<listitem>
<para>The templates are instantiated</para>
</listitem>
<listitem>
<para>The typedefs are handled</para>
</listitem>
<listitem>
<para>There is no "else if". These are converted into "else {
if.."</para>
</listitem>
<listitem>
<para>The bodies of "if", "else", "while", "do" and "for" are always
enclosed in "{" and "}"</para>
</listitem>
<listitem>
<para>A declaration of multiple variables is split up into multiple
variable declarations. "int a,b;" =&gt; "int a; int b;"</para>
</listitem>
<listitem>
<para>There is no sizeof</para>
</listitem>
<listitem>
<para>NULL is replaced with 0</para>
</listitem>
<listitem>
<para>Static value flow analysis is made. Known values are inserted
into the code.</para>
</listitem>
<listitem>
<para>.. and many more</para>
</listitem>
</itemizedlist>
<para>The simplifications are made in the <literal>Cppcheck</literal>
<literal>Tokenizer</literal>. For more information see:
<uri>http://cppcheck.sourceforge.net/doxyoutput/classTokenizer.html</uri></para>
</section> </section>
<section> <section>
<title>Regular expressions</title> <title>Creating a simple rule</title>
<para>Simple rules can be defined through regular expressions.</para> <para>When creating a rule there are two steps:</para>
<para>Cppcheck uses the <literal>PCRE</literal> library to handle regular <orderedlist>
expressions. <literal>PCRE</literal> stands for "Perl Compatible Regular <listitem>
Expressions". The homepage for <literal>PCRE</literal> is <para>Create the regular expression</para>
<literal>http://www.pcre.org</literal>.</para> </listitem>
<listitem>
<para>Create a XML based rule file</para>
</listitem>
</orderedlist>
<section> <section>
<title>Creating the regular expression</title> <title>Step 1 - Creating the regular expression</title>
<para>Let's create a regular expression that checks for:</para> <para>Cppcheck uses the <literal>PCRE</literal> library to handle
regular expressions. <literal>PCRE</literal> stands for "Perl Compatible
Regular Expressions". The homepage for <literal>PCRE</literal> is
<literal>http://www.pcre.org</literal>.</para>
<para>Let's create a regular expression that checks for code such
as:</para>
<programlisting>if (p) <programlisting>if (p)
free(p);</programlisting> free(p);</programlisting>
<para>For such code the condition is often redundant, on most <para>For such code the condition is often redundant (on most
implementations it is valid to free a NULL pointer.</para> implementations it is valid to free a NULL pointer).</para>
<para>The regular expression must be written for the simplified code. To <para>The regular expression must be written for the simplified code. To
see what the simplified code looks like you can create a source file see what the simplified code looks like you can create a source file
with some code:</para> with the code:</para>
<programlisting>void f() { <programlisting>void f() {
if (p) if (p)
free(p); free(p);
}</programlisting> }</programlisting>
<para>Save that code as <literal>dealloc.cpp</literal> and use <para>Save that code as <literal>dealloc.cpp</literal> and then use
<literal>cppcheck --rule=".+" dealloc.cpp</literal>:</para> <literal>cppcheck --rule=".+" dealloc.cpp</literal>:</para>
<programlisting>$ ./cppcheck --rule=".+" dealloc.cpp <programlisting>$ ./cppcheck --rule=".+" dealloc.cpp
Checking dealloc.cpp... Checking dealloc.cpp...
[dealloc.cpp:1]: (style) found ' void f ( ) { if ( p ) { free ( p ) ; } }'</programlisting> [dealloc.cpp:1]: (style) found ' void f ( ) { if ( p ) { free ( p ) ; } }'</programlisting>
<para>The regular expression <literal>.+</literal> matches everything
and the matching text is shown on the screen.</para>
<para>From that output we can see that the simplified code is:</para> <para>From that output we can see that the simplified code is:</para>
<programlisting> void f ( ) { if ( p ) { free ( p ) ; } }</programlisting> <programlisting> void f ( ) { if ( p ) { free ( p ) ; } }</programlisting>
<para>Now that we know how the simplified code looks for a simple test <para>Now that we know how the simplified code looks. We can create a
case, we can create a regular expression:</para> regular expression that matches it properly:</para>
<programlisting>$ cppcheck --rule="if \( p \) { free \( p \) ; }" dealloc.cpp <programlisting>$ cppcheck --rule="if \( p \) { free \( p \) ; }" dealloc.cpp
Checking dealloc.cpp... Checking dealloc.cpp...
@ -165,9 +110,9 @@ Checking dealloc.cpp...
</section> </section>
<section> <section>
<title>Create rule file</title> <title>Step 2 - Create rule file</title>
<para>A rule consist of:</para> <para>A rule file is a simple XML file that contains:</para>
<itemizedlist> <itemizedlist>
<listitem> <listitem>