Home | History | Annotate | Download | only in analyzer
      1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
      2           "http://www.w3.org/TR/html4/strict.dtd">
      3 <html>
      4 <head>
      5   <title>List of potential checkers</title>
      6   <link type="text/css" rel="stylesheet" href="content.css">
      7   <link type="text/css" rel="stylesheet" href="menu.css">
      8   <script type="text/javascript" src="scripts/menu.js"></script>
      9   <script type="text/javascript" src="scripts/dbtree.js"></script>
     10 </head>
     11 <body>
     12 
     13 <div id="page">
     14 
     15 <!-- menu -->
     16 <!--#include virtual="menu.html.incl"-->
     17 <!-- page content -->
     18 <div id="content">
     19 <h1>List of potential checkers</h1>
     20 
     21 <p>This page contains a list of potential checkers to implement in the static analyzer.  If you are interested in contributing to the analyzer's development, this is a good resource to help you get started.  The specific names of the checkers are subject to review, and are provided here as suggestions.</p>
     22 
     23 <!-- ========================= allocation/deallocation ======================= -->
     24 <h3>allocation/deallocation</h3>
     25 <table class="checkers">
     26 <col class="namedescr"><col class="example"><col class="progress">
     27 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
     28 
     29 <tr><td><span class="name">memory.LeakNeverReleased<br>
     30 (C, C++)</span><br><br>
     31 Memory may be never released, potential leak of memory
     32 </td><td>
     33 <pre>
     34 #include &lt;stdlib.h&gt;
     35 
     36 int f() {};
     37 
     38 void test() { 
     39   int *p1 = (int*)malloc(sizeof(int)); // warn
     40   int *p2 = new int; // warn
     41   int x = f();
     42   if (x==1)
     43     return;
     44   delete p2;
     45 }
     46 </pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=15237">PR15237</a>
     47 </td></tr>
     48 
     49 <tr><td><span class="name">memory.MismatchedFree
     50 <br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
     51 Mismatched deallocation function is used
     52 </td><td><pre>
     53 #include &lt;stdlib.h&gt;
     54 
     55 void test() {
     56   int *p1 = new int;
     57   int *p2 = new int[1];
     58 
     59   free(p1); // warn
     60   free(p2); // warn
     61 }
     62 </pre></td><td class="aligned"><a href="http://llvm.org/bugs/show_bug.cgi?id=15238">PR15238</a>
     63 </td></tr>
     64 
     65 <tr><td><span class="name">memory.LeakPtrValChanged
     66 <br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
     67 Potential memory leak: a pointer to newly allocated data loses its original 
     68 value
     69 </td><td><pre>
     70 #include &lt;stdlib.h&gt;
     71 
     72 void f(const int *);
     73 void g(int *);
     74 
     75 void test() {
     76   int *p1 = new int;
     77   p1++; // warn
     78   int *p2 = (int *)malloc(sizeof(int));
     79   p2 = p1; // warn
     80   int *p3 = new int;
     81   f(p3);
     82   p3++; // warn
     83   int *p4 = new int;
     84   f(p4);
     85   p4++; // ok
     86 }
     87 </pre></td><td class="aligned">done at r174678 (C case)
     88 </td></tr>
     89 
     90 <tr><td><span class="name">memory.LeakEvalOrder<br>
     91 (C, C++)</span><br><br>
     92 Potential memory leak: argument evaluation order is undefined, g() may never be called
     93 </td><td><pre>
     94 #include &lt;stdlib.h&gt;
     95 
     96 void f1(int, int);
     97 void f2(int*, int*);
     98 int g(int *) { throw 1; };
     99 int h();
    100 
    101 void test() {
    102   f1(g(new int), h()); // warn
    103   f1(g((int *)malloc(sizeof(int))), h()); // warn
    104   f2(new int, new int);
    105 }
    106 </pre></td><td class="aligned"></td></tr>
    107 
    108 <tr><td><span class="name">memory.DstBufferTooSmall
    109 <br>(C, C++)</span><br><br>
    110 Destination buffer too small
    111 </td><td><pre>
    112 #include &lt;string.h&gt;
    113 
    114 void test() {
    115   const char* s1 = "abc";
    116   char *s2 = new char;
    117   strcpy(s2, s1); // warn
    118 
    119   int* p1 = new int[3];
    120   int* p2 = new int;
    121   memcpy(p2, p1, 3); // warn
    122 }
    123 </pre></td><td class="aligned"></td></tr>
    124 
    125 <tr><td><span class="name">memory.NegativeArraySize
    126 <br>enhancement to experimental.security.MallocOverflow<br>(C, C++)
    127 </span><br><br>
    128 'n' is used to specify the buffer size may be negative
    129 </td><td><pre>
    130 #include &lt;stdlib.h&gt;
    131 
    132 void test() {
    133   int *p;
    134   int n1 = -1;
    135   p = new int[n1]; // warn
    136 }
    137 </pre></td><td class="aligned"></td></tr>
    138 
    139 </table>
    140 
    141 <!-- ======================= constructors/destructors ====================== -->
    142 <h3>constructors/destructors</h3>
    143 <table class="checkers">
    144 <col class="namedescr"><col class="example"><col class="progress">
    145 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
    146 
    147 <tr><td><span class="name">ctordtor.ExptInsideDtorExplicit<br>
    148 (C++)</span><br><br>
    149 It is dangerous to let an exception leave a destructor. Using try..catch will 
    150 solve the problem.
    151 </td><td><pre>
    152 void f();
    153 
    154 class A {
    155   A() {}
    156   ~A() { throw 1; } // warn
    157 };
    158 </pre></td><td class="aligned"></td></tr>
    159 
    160 <tr><td><span class="name">ctordtor.ExptInsideDtorImplicit<br>
    161 (C++)</span><br><br>
    162 Calls to functions inside a destructor that are known to throw exceptions is 
    163 dangerous. Using try..catch will solve the problem.
    164 </td><td><pre>
    165 void f() { throw 1; };
    166 
    167 class A {
    168   A() {}
    169   ~A() { f(); } // warn
    170 };
    171 </pre></td><td class="aligned"></td></tr>
    172 
    173 <tr><td><span class="name">ctordtor.PlacementSelfCopy<br>
    174 (C++11)</span><br><br>
    175 For a placement copy or move, it is almost certainly an error if the constructed object is also the object being copied from.
    176 </td><td><pre>
    177 class A {};
    178 
    179 void test(A *dst, A *src) {
    180   ::new (dst) A(*dst); // warn (should be 'src')
    181 }
    182 </pre></td><td class="aligned"><!--rdar://problem/13688366--></td></tr>
    183 
    184 </table>
    185 
    186 <!-- ============================== exceptions ============================= -->
    187 <h3>exceptions</h3>
    188 <table class="checkers">
    189 <col class="namedescr"><col class="example"><col class="progress">
    190 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
    191 
    192 <tr><td><span class="name">exceptions.ThrowSpecButNotThrow
    193 <br>(C++)</span><br><br>
    194 Function prototype has throw(T) specifier but the function do not throw
    195 </td><td><pre>
    196 void f() throw(int) { // warn
    197 }
    198 </pre></td><td class="aligned"></td></tr>
    199 
    200 <tr><td><span class="name">exceptions.NoThrowSpecButThrows
    201 <br>(C++)</span><br><br>
    202 An exception is throw from a function having the throw() specifier
    203 </td><td><pre>
    204 void f() throw() {
    205   throw(1); // warn
    206 }
    207 </pre></td><td class="aligned"></td></tr>
    208 
    209 <tr><td><span class="name">exceptions.ThrownTypeDiffersSpec
    210 <br>(C++)</span><br><br>
    211 The type of a thrown exception differs from those specified in the throw(T) 
    212 specifier
    213 </td><td><pre>
    214 struct S{};
    215 void f() throw(int) {
    216   S s;
    217   throw (s); // warn
    218 }
    219 </pre></td><td class="aligned"></td></tr>
    220 
    221 </table>
    222 
    223 <!-- ========================= smart pointers ============================== -->
    224 <h3>smart pointers</h3>
    225 <table class="checkers">
    226 <col class="namedescr"><col class="example"><col class="progress">
    227 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
    228 
    229 <tr><td><span class="name">smartptr.SmartPtrInit<br>
    230 (C++)</span><br><br>
    231 C++03: auto_ptr should store a pointer to an object obtained via new as allocated
    232 memory will be cleaned using delete<br>
    233 C++11: one should use unique_ptr&lt;T[]&gt; to keep a pointer to memory
    234 allocated by new[]<br>
    235 C++11: to keep a pointer to memory allocated by new[] in a shared_ptr one
    236 should use a custom deleter that calls delete[]
    237 </td><td><pre>
    238 #include &lt;stdlib.h&gt;
    239 #include &lt;memory&gt;
    240 
    241 void test() {
    242   std::auto_ptr&lt;int&gt; p1(new int); // Ok
    243   std::auto_ptr&lt;int&gt; p2(new int[3]); // warn
    244   std::auto_ptr&lt;int&gt; 
    245          p3((int *)malloc(sizeof(int))); // warn
    246 }
    247 </pre></td><td class="aligned"></td></tr>
    248 
    249 </table>
    250 
    251 <!-- ========================= undefined behavior ========================== -->
    252 <h3>undefined behavior</h3>
    253 <table class="checkers">
    254 <col class="namedescr"><col class="example"><col class="progress">
    255 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
    256 
    257 <tr><td><span class="name">undefbehavior.ExitInDtor
    258 <br>(C++)</span><br><br>
    259 Undefined behavior: std::exit is called to end the program during the 
    260 destruction of an object with static storage duration
    261 </td><td><pre>
    262 #include &lt;cstdlib&gt;
    263 
    264 class A {
    265 public:
    266   ~A() {
    267     std::exit(1); // warn
    268   }
    269 };
    270 
    271 A a;
    272 </pre></td><td class="aligned"></td></tr>
    273 
    274 <tr><td><span class="name">undefbehavior.LocalStaticDestroyed
    275 <br>(C++)</span><br><br>
    276 Undefined behavior: function containing a definition of static local object is 
    277 called during the destruction of an object with static storage duration so that 
    278 flow of control passes through the definition of the previously destroyed 
    279 static local object
    280 </td><td><pre>
    281 void f();
    282 
    283 class A {
    284 public:
    285   ~A() {
    286     f(); // warn
    287   }
    288 };
    289 
    290 class B {};
    291 
    292 A a;
    293 
    294 void f() {
    295   static B b; // &lt;-
    296 }
    297 </pre></td><td class="aligned"></td></tr>
    298 
    299 <tr><td><span class="name">undefbehavior.UseAfterRelease
    300 <br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
    301 Pointer to deleted object is referenced (The effect of using an invalid pointer 
    302 value is undefined)
    303 </td><td><pre>
    304 #include &lt;stdlib.h&gt;
    305 
    306 void test() {
    307   int *p = new int;
    308   delete p;
    309   int i = *p; // warn
    310 }
    311 
    312 </pre></td><td class="aligned"></td></tr>
    313 
    314 <tr><td><span class="name">undefbehavior.ZeroAllocDereference
    315 <br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
    316 The effect of dereferencing a pointer returned as a request for zero size is 
    317 undefined
    318 </td><td><pre>
    319 #include &lt;stdlib.h&gt;
    320 
    321 int *p = new int[0];
    322 int i = p[0]; // warn
    323 </pre></td><td class="aligned"></td></tr>
    324 
    325 <tr><td><span class="name">undefbehavior.DeadReferenced
    326 <br>(C++)</span><br><br>
    327 Undefined behavior: the following usage of the pointer to the object whose 
    328 lifetime has ended can result in undefined behavior
    329 </td><td><pre>
    330 // C++03
    331 #include &lt;new&gt;
    332 
    333 class A {
    334 public:
    335   int i;
    336   void f() {};
    337 };
    338 
    339 class B : public A {
    340 };
    341 
    342 void test() {
    343   B *b = new B;
    344   new(b) A;
    345   b->i; // warn
    346   b->f(); // warn
    347   static_cast&lt;A*&gt;(b); // warn
    348   dynamic_cast&lt;A*&gt;(b); // warn
    349   delete b; // warn
    350 }
    351 
    352 // C++11
    353 #include &lt;new&gt;
    354 
    355 class A {
    356 public:
    357   int i;
    358   void f() {};
    359 };
    360 
    361 class B : public A {
    362 public:
    363   ~B() {};
    364 };
    365 
    366 void test() {
    367   A *a = new A;
    368   new(a) B;
    369   a->i; // warn
    370   a->f(); // warn
    371   B *b = new B;
    372   new(b) A;
    373   b->i; // warn
    374   b->f(); // warn
    375   static_cast&lt;A*&gt;(b); // warn
    376   dynamic_cast&lt;A*&gt;(b); // warn
    377   delete b; // warn
    378 }
    379 </pre></td><td class="aligned"></td></tr>
    380 
    381 <tr><td><span class="name">undefbehavior.ObjLocChanges
    382 <br>(C++)</span><br><br>
    383 Undefined behavior: the program must ensure that an object occupies the same 
    384 storage location when the implicit or explicit destructor call takes place
    385 </td><td><pre>
    386 #include &lt;new&gt;
    387 
    388 class T { };
    389 struct B {
    390   ~B();
    391 };
    392 
    393 void test() {
    394   B *b1 = new B;
    395   B b2;
    396   new (b1) T;
    397   new (&amp;b2) T;
    398   delete b1; // warn
    399 } // warn
    400 </pre></td><td class="aligned"></td></tr>
    401 
    402 <tr><td><span class="name">undefbehavior.ExprEvalOrderUndef
    403 <br>(C, C++03)</span><br><br>
    404 Undefined behavior: a scalar object shall have its stored value modified at 
    405 most once by the evaluation of an expression
    406 </td><td><pre>
    407 void test () {
    408   int i = 0;
    409   int v[1] = {0};
    410   i = v[i++]; // warn
    411   i = ++i + 1; // warn
    412 }
    413 </pre></td><td class="aligned"></td></tr>
    414 
    415 <tr><td><span class="name">undefbehavior.StaticInitReentered
    416 <br>(C)</span><br><br>
    417 Undefined behavior: static declaration is re-entered while the object is being 
    418 initialized
    419 </td><td><pre>
    420 int test(int i) {
    421   static int s = test(2*i); // warn
    422   return i+1;
    423 }
    424 </pre></td><td class="aligned"></td></tr>
    425 
    426 <tr><td><span class="name">undefbehavior.ConstModified
    427 <br>(C, C++)</span><br><br>
    428 Undefined behavior: const object is being modified
    429 </td><td><pre>
    430 #include &lt;stdlib.h&gt;
    431 
    432 class X {
    433 public :
    434   mutable int i;
    435   int j;
    436 };
    437 class Y {
    438 public :
    439   X x;
    440   Y();
    441 };
    442 
    443 void test() {
    444   const int *ciq = 
    445     (int *)malloc(sizeof(int));
    446   int *iq = const_cast&lt;int *&gt;(ciq);
    447   *iq = 1; // warn
    448 
    449   const Y y;
    450   Y* p = const_cast&lt;Y*&gt;(&amp;y);
    451   p-&gt;x.i = 1; // ok
    452   p-&gt;x.j = 1; // warn
    453 }
    454 </pre></td><td class="aligned"></td></tr>
    455 
    456 <tr><td><span class="name">undefbehavior.DeadDestructed
    457 <br>(C++)</span><br><br>
    458 Undefined behavior: the destructor is invoked for an object whose lifetime 
    459 has ended
    460 </td><td><pre>
    461 class A {
    462 public:
    463   void f() {};
    464   A() {};
    465   ~A() {};
    466 };
    467 
    468 void test() {
    469   A a;
    470   a.~A();
    471 } // warn
    472 </pre></td><td class="aligned"></td></tr>
    473 
    474 <tr><td><span class="name">undefbehavior.MethodCallBeforeBaseInit
    475 <br>(C++)</span><br><br>
    476 Undefined behavior: calls member function but base not yet initialized
    477 </td><td><pre>
    478 class A {
    479 public :
    480   A(int );
    481 };
    482 class B : public A {
    483 public :
    484   int f();
    485   B() : A(f()) {} // warn
    486 };
    487 </pre></td><td class="aligned"></td></tr>
    488 
    489 <tr><td><span class="name">undefbehavior.MemberOrBaseRefBeforeCtor
    490 <br>(C++)</span><br><br>
    491 C++ Undefined behavior: non-static member or base class of non-POD class type 
    492 is referred before constructor begins execution<br>
    493 C++11 Undefined behavior: non-static member or base class of a class with a 
    494 non-trivial constructor is referred before constructor begins execution
    495 </td><td><pre>
    496 // C++03
    497 struct POD { 
    498   int i; 
    499 };
    500 
    501 struct non_POD : public POD { 
    502   int j; 
    503   POD pod;
    504 };
    505 
    506 extern POD pod;
    507 extern non_POD non_pod;
    508 
    509 int *p1 = &amp;non_pod.j; // warn
    510 int *p2 = &amp;non_pod.pod.i; // warn
    511 int *p3 = &amp;pod.i; // ok
    512 POD *p4 = &amp;non_pod; // warn
    513 
    514 POD a;
    515 non_POD b;
    516 
    517 struct S {
    518   int *k;
    519   non_POD non_pod;
    520   S() : k(&amp;non_pod.j) {} // warn
    521 };
    522 
    523 // C++11
    524 struct trivial { 
    525   int i; 
    526 };
    527 
    528 struct non_trivial: public trivial { 
    529   non_trivial() {};
    530   int j; 
    531   trivial pod;
    532 };
    533 
    534 extern trivial t;
    535 extern non_trivial nt;
    536 
    537 int *p1 = &amp;nt.j; // warn
    538 int *p2 = &amp;nt.i; // warn
    539 int *p3 = &amp;t.i; // ok
    540 trivial *p4 = &amp;nt;
    541 
    542 trivial t;
    543 non_trivial nt;
    544 
    545 struct S {
    546   int *k;
    547   non_trivial nt;
    548   S() : k(&amp;nt.j) {} // warn
    549 };
    550 </pre></td><td class="aligned"></td></tr>
    551 
    552 <tr><td><span class="name">undefbehavior.MemberRefAfterDtor
    553 <br>(C++)</span><br><br>
    554 C++03: Undefined behavior: non-static member of non-POD class type is referred 
    555 after destructor ends execution<br>
    556 C++11: Undefined behavior: non-static member of a class with a non-trivial 
    557 destructor is referred after destructor ends execution
    558 </td><td><pre>
    559 // C++03
    560 struct non_POD {
    561   virtual void f() {};
    562 };
    563 
    564 void test() {
    565   non_POD *non_pod = new non_POD();
    566   non_pod->~non_POD();  
    567   non_pod->f(); // warn
    568 }
    569 
    570 // C++11
    571 struct S {
    572   ~S() {};
    573   void f() {};
    574 };
    575 
    576 void test() {
    577   S *s = new S();
    578   s->~S();  
    579   s->f(); // warn
    580 }
    581 </pre></td><td class="aligned"></td></tr>
    582 
    583 <tr><td><span class="name">undefbehavior.CtorForeignCall
    584 <br>(C++)</span><br><br>
    585 Undefined behavior: call to virtual function of an object under construction 
    586 whose type is neither the constructors own class or one of its bases
    587 </td><td><pre>
    588 class A {
    589 public:
    590   virtual void f() {};
    591 };
    592 
    593 class B {
    594 public:
    595   B(A* a) { a-&gt;f(); } // warn
    596 };
    597 
    598 class C : public A, B {
    599 public:
    600   C() : B((A*)this) {}
    601 };
    602 </pre></td><td class="aligned"></td></tr>
    603 
    604 <tr><td><span class="name">undefbehavior.CtorForeignCast 
    605 undefbehavior.CtorForeignTypeid
    606 <br>(C++)</span><br><br>
    607 Undefined behavior: the operand of typeid/dynamic_cast is an object under 
    608 construction whose type is neither the constructors own class or one of its 
    609 bases
    610 </td><td><pre>
    611 #include &lt;typeinfo&gt;
    612 
    613 class A {
    614 public:
    615   virtual void f() {};
    616 };
    617 
    618 class B {
    619 public:
    620   B(A* a) { 
    621     typeid(*a); // warn
    622     dynamic_cast&lt;B*&gt;(a); //warn
    623   }
    624 };
    625 
    626 class C : public A, B {
    627 public:
    628   C() : B((A*)this) {}
    629 };
    630 </pre></td><td class="aligned"></td></tr>
    631 
    632 <tr><td><span class="name">undefbehavior.MemberRefInCatch 
    633 undefbehavior.BaseRefInCatch
    634 <br>(C++)</span><br><br>
    635 Undefined behavior: referring to any non-static member or base class of an 
    636 object in the handler for a function-try-block of a constructor or destructor 
    637 for that object results in undefined behavior
    638 </td><td><pre>
    639 class C {
    640   int i;
    641 public :
    642   C()
    643   try
    644   : i(1) {}
    645   catch (...)
    646   {
    647     i=2; // warn
    648   }
    649 };
    650 </pre></td><td class="aligned"></td></tr>
    651 
    652 <tr><td><span class="name">undefbehavior.ReturnAtCatchEnd
    653 <br>(C++)</span><br><br>
    654 Undefined behavior: a function returns when control reaches the end of a 
    655 handler. This results in undefined behavior in a value-returning 
    656 function
    657 </td><td><pre>
    658 int test() try {
    659 }
    660 catch(int) {
    661 } // warn
    662 </pre></td><td class="aligned"></td></tr>
    663 
    664 <tr><td><span class="name">undefbehavior.AutoptrsOwnSameObj
    665 <br>(C++03)</span><br><br>
    666 Undefined behavior: if more than one auto_ptr owns the same object at the same 
    667 time the behavior of the program is undefined.
    668 </td><td><pre>
    669 #include &lt;memory&gt;
    670 
    671 void test() {
    672   int *data = new int;
    673   std::auto_ptr&lt;int&gt; p(data);
    674   std::auto_ptr&lt;int&gt; q(data); // warn
    675 }
    676 </pre></td><td class="aligned"></td></tr>
    677 
    678 <tr><td><span class="name">undefbehavior.BasicStringBoundAccess
    679 <br>(C++03)</span><br><br>
    680 Undefined behavior: out-of-bound basic_string access
    681 </td><td><pre>
    682 void test() {
    683   std::basic_string&lt;char&gt; s;
    684   char c = s[10]; // warn
    685 }
    686 </pre></td><td class="aligned"></td></tr>
    687 
    688 <tr><td><span class="name">undefbehavior.BasicStringBoundModification
    689 <br>(C++)</span><br><br>
    690 Undefined behavior: out-of-bound basic_string modification
    691 </td><td><pre>
    692 void test() {
    693   std::basic_string&lt;char&gt; s;
    694   s[10] = 0; // warn
    695 }
    696 </pre></td><td class="aligned"></td></tr>
    697 
    698 <tr><td><span class="name">undefbehavior.EosDereference
    699 <br>(C++)</span><br><br>
    700 Undefined behavior: the result of operator*() on an end of stream is 
    701 undefined
    702 </td><td><pre>
    703 #include &lt;vector&gt;
    704 
    705 void test() {
    706   std::vector&lt;int&gt; v;
    707   int i = *v.end(); // warn
    708   *v.end() = 0; // warn
    709 }
    710 </pre></td><td class="aligned"></td></tr>
    711 
    712 <tr><td><span class="name">undefbehavior.QsortNonPOD 
    713 undefbehavior.QsortNonTrivial
    714 <br>C++</span><br><br>
    715 C++03: Undefined behavior: the objects in the array passed to qsort are of 
    716 non-POD type<br>
    717 C++11: Undefined behavior: the objects in the array passed to qsort are of 
    718 non-trivial type
    719 </td><td><pre>
    720 // C++03
    721 #include &lt;cstdlib&gt;
    722 
    723 struct non_POD {
    724   int i;
    725   non_POD(int ii) : i(ii) {}
    726 };
    727 
    728 non_POD values[] = { non_POD(2), non_POD(1) };
    729 
    730 int compare(const void *a, 
    731             const void *b) {
    732   return ( (*(non_POD*)a).i -
    733            (*(non_POD*)b).i );
    734 }
    735 
    736 void test() {
    737   qsort(values, 2, sizeof(non_POD), 
    738         compare); // warn
    739 }
    740 
    741 // C++11
    742 #include &lt;cstdlib&gt;
    743 
    744 struct S {};
    745 
    746 struct trivial_non_POD : public S {
    747   int i;
    748 };
    749 
    750 struct non_trivial {
    751   int i;
    752   non_trivial() {}
    753 };
    754 
    755 trivial_non_POD tnp[2];
    756 non_trivial nt[2];
    757 
    758 int compare1(const void *a, 
    759              const void *b) {
    760   return ( (*(trivial_non_POD *)a).i -
    761            (*(trivial_non_POD *)b).i );
    762 }
    763 
    764 int compare2(const void *a, 
    765              const void *b) {
    766   return ( (*(non_trivial *)a).i -
    767            (*(non_trivial *)b).i );
    768 }
    769 
    770 void test() {
    771   qsort(tnp, 2, sizeof(trivial_non_POD), 
    772         compare1); // ok
    773   qsort(nt, 2, sizeof(non_trivial), 
    774         compare2); // warn
    775 }
    776 </pre></td><td class="aligned"></td></tr>
    777 
    778 <tr><td><span class="name">undefbehavior.ThrowWhileCopy
    779 <br>C++</span><br><br>
    780 Undefined behavior: copy constructor/assignment operator can throw an exception.
    781 The effects are undefined if an exception is thrown.
    782 </td><td><pre>
    783 struct S {
    784   int i, j;
    785   S (const S &amp;s) {
    786     i = s.i;
    787     throw 1; // warn
    788     j = s.j;
    789   };
    790   S &amp;operator=(const S &amp;s) {
    791     i = s.i;
    792     throw 1; // warn
    793     j = s.j;
    794   }
    795 };
    796 </pre></td><td class="aligned"></td></tr>
    797 
    798 <tr><td><span class="name">undefbehavior.ValarrayArgBound
    799 <br>(C++)</span><br><br>
    800 Undefined behavior: the value of the second argument is greater than the number 
    801 of values pointed to by the first argument
    802 </td><td><pre>
    803 #include &lt;valarray&gt;
    804 
    805 struct S {
    806   int i;
    807   S(int ii) : i(ii) {};
    808 };
    809 
    810 void test(void) {
    811   S s[] = { S(1), S(2) };
    812   std::valarray&lt;S&gt; v(s,3); // warn
    813 }
    814 </pre></td><td class="aligned"></td></tr>
    815 
    816 <tr><td><span class="name">undefbehavior.ValarrayLengthDiffer
    817 <br>(C++)</span><br><br>
    818 Undefined behavior: valarray operands are of different length
    819 </td><td><pre>
    820 // C++03
    821 #include &lt;valarray&gt;
    822 
    823 void test(void) {
    824   std::valarray&lt;int&gt; a(0, 1), b(0, 2);
    825   std::valarray&lt;bool&gt; c(false, 1);
    826   a = b; // warn
    827   a *= b; // warn
    828   a = a * b; // warn
    829   c = a == b; // warn
    830   b.resize(1);
    831   a = b; // OK
    832 }
    833 
    834 // C++11
    835 #include &lt;valarray&gt;
    836 
    837 void test(void) {
    838   std::valarray&lt;int&gt; a(0, 1), b(0, 2);
    839   std::valarray&lt;bool&gt; c(false, 1);
    840   a = b; // ok
    841   a *= b; // ok
    842   a = a * b; // warn
    843   c = a == b; // warn
    844   b.resize(1);
    845   a = b; // OK
    846 }
    847 </pre></td><td class="aligned"></td></tr>
    848 
    849 <tr><td><span class="name">undefbehavior.ValarrayZeroLength
    850 <br>(C++)</span><br><br>
    851 Undefined behavior: calling sum()/min()/max() method of an array having zero 
    852 length, the behavior is undefined
    853 </td><td><pre>
    854 #include &lt;valarray&gt;
    855 
    856 void test(void) {
    857   std::valarray&lt;int&gt; v(0, 0);
    858   v.sum(); // warn
    859   v.min(); // warn
    860   v.max(); // warn
    861 }
    862 </pre></td><td class="aligned"></td></tr>
    863 
    864 <tr><td><span class="name">undefbehavior.ValarrayBadIndirection
    865 <br>(C++)</span><br><br>
    866 Undefined behavior: element N is specified more than once in the 
    867 indirection
    868 </td><td><pre>
    869 #include &lt;valarray&gt;
    870 
    871 void test() {
    872   size_t addr[] = {0, 1, 1}; // N is 1
    873   std::valarray&lt;size_t&gt;indirect(addr, 3);
    874   std::valarray&lt;int&gt; a(0, 5), b(1, 3);
    875   a[indirect] = b; //warn
    876   a[indirect] *= b; //warn
    877 }
    878 </pre></td><td class="aligned"></td></tr>
    879 
    880 <tr><td><span class="name">undefbehavior.IosBaseDestroyedBeforeInit
    881 <br>(C++)</span><br>
    882 <br>Undefined behavior: ios_base object is destroyed before initialization have 
    883 taken place. basic_ios::init should be call to initialize ios_base 
    884 members
    885 </td><td><pre>
    886 #include &lt;ios&gt;
    887 
    888 using namespace std;
    889 template &lt;class T, class Traits = std::char_traits&lt;T&gt;&gt;
    890 class my_stream1 : public std::basic_ios&lt;T, Traits&gt; {
    891 };
    892 
    893 template &lt;class T, class Traits = std::char_traits&lt;T&gt;&gt;
    894 class my_stream2 : public std::basic_ios&lt;T, Traits&gt; {
    895   class my_streambuf : public std::basic_streambuf&lt;T, Traits&gt; {
    896   };
    897 public:
    898   my_stream2() {
    899     this->init(new my_streambuf);
    900   }
    901 };
    902 
    903 void test() {
    904   my_stream1&lt;char&gt; *p1 = new my_stream1&lt;char&gt;
    905   my_stream2&lt;char&gt; *p2 = new my_stream2&lt;char&gt;
    906   delete p1; // warn
    907   delete p2; // ok
    908 }
    909 </pre></td><td class="aligned"></td></tr>
    910 
    911 <tr><td><span class="name">undefbehavior.IosBaseUsedBeforeInit
    912 <br>(C++11)</span><br><br>
    913 Undefined behavior: ios_base object is used before initialization have taken 
    914 place. basic_ios::init should be call to initialize ios_base members
    915 </td><td><pre>
    916 #include &lt;ios&gt;
    917 
    918 using namespace std;
    919 template &lt;class T, class Traits = std::char_traits&lt;T&gt;&gt;
    920 class my_stream1 : public std::basic_ios&lt;T, Traits&gt; {
    921 };
    922 
    923 template &lt;class T, class Traits = std::char_traits&lt;T&gt;&gt;
    924 class my_stream2 : public std::basic_ios&lt;T, Traits&gt; {
    925   class my_streambuf : public std::basic_streambuf&lt;T, Traits&gt; {
    926   };
    927 public:
    928   my_stream2() {
    929     this->init(new my_streambuf);
    930   }
    931 };
    932 
    933 void test() {
    934   my_stream1&lt;char&gt; *p1 = new my_stream1&lt;char&gt;
    935   my_stream2&lt;char&gt; *p2 = new my_stream2&lt;char&gt;
    936   p1->narrow('a', 'b'); // warn
    937   p2->narrow('a', 'b'); // ok
    938   delete p1; // warn
    939   delete p2; // ok
    940 }
    941 </pre></td><td class="aligned"></td></tr>
    942 
    943 <tr><td><span class="name">undefbehavior.MinusOnePosType
    944 <br>(C++)</span><br><br>
    945 Undefined behavior: passing -1 to any streambuf/istream/ostream member that 
    946 accepts a value of type traits::pos_type result in undefined behavior
    947 </td><td><pre>
    948 #include &lt;fstream&gt;
    949 
    950 class my_streambuf : public std::streambuf {
    951   void f() {
    952     seekpos(-1); // warn
    953   }
    954 };
    955 
    956 void test() {
    957   std::filebuf fb;
    958   std::istream in(&amp;fb);
    959   std::ostream out(&amp;fb);
    960   std::filebuf::off_type pos(-1);
    961   in.seekg(pos); // warn
    962   out.seekp(-1); // warn
    963 }
    964 </pre></td><td class="aligned"></td></tr>
    965 </table>
    966 
    967 <!-- ============================ different ================================ -->
    968 <h3>different</h3>
    969 <table class="checkers">
    970 <col class="namedescr"><col class="example"><col class="progress">
    971 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr>
    972 </thead>
    973 
    974 <tr><td><span class="name">different.ArgEvalOrderUndef
    975 <br>(C)</span><br><br>
    976 Errors because of the order of evaluation of function arguments is undefined
    977 </td><td><pre>
    978 void f(int, int);
    979 
    980 void test() {
    981   int i = 0;
    982   int v[1] = {0};
    983   f(v[i], i++); // warn
    984 }
    985 </pre></td><td class="aligned"></td></tr>
    986 
    987 <tr><td><span class="name">different.IdenticalExprBinOp
    988 <br>(C)</span><br><br>
    989 There are identical sub-expressions to the left and to the right of the 
    990 operator
    991 </td><td><pre>
    992 #define A 1
    993 #define B 1
    994 
    995 bool isNan(double d) { 
    996   return d != d; // ok
    997 }
    998 
    999 int f();
   1000 
   1001 void test() {
   1002   int i = 0;
   1003   if (i != 0 && i != 0) {} // warn
   1004 
   1005   if(i == A || i == B) {} // ok
   1006 
   1007   if (++i != 0 && ++i != 0) {} // ok
   1008 
   1009   if (f() && f()) {} // ok
   1010 }
   1011 </pre></td><td class="aligned"></td></tr>
   1012 
   1013 <tr><td><span class="name">different.FuncPtrInsteadOfCall
   1014 <br>(C)</span><br><br>
   1015 Possibly a function call should be used instead of a pointer to function
   1016 </td><td><pre>
   1017 int f();
   1018 
   1019 void test() {
   1020   if (f == 0) {} // warn
   1021 }
   1022 </pre></td><td class="aligned"></td></tr>
   1023 
   1024 <tr><td><span class="name">different.IdenticalCondIfElseIf
   1025 <br>(C)</span><br><br>
   1026 The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a 
   1027 probability of logical error presence
   1028 </td><td><pre>
   1029 void test() { 
   1030   int i = 7;
   1031   if (i == 1) {}
   1032   else if (i == 1) {} // warn
   1033 }
   1034 </pre></td><td class="aligned"></td></tr>
   1035 
   1036 <tr><td><span class="name">SuccessiveAssign
   1037 <br>(C)</span><br><br>
   1038 Successive assign to a variable
   1039 </td><td><pre>
   1040 void test() { 
   1041   int i=0;
   1042   i=1;
   1043   i=2; // warn
   1044 }
   1045 </pre></td><td class="aligned"></td></tr>
   1046 
   1047 <tr><td><span class="name">different.NullDerefStmtOrder
   1048 <br>enhancement to core.NullDereference<br>(C)</span><br><br>
   1049 Dereferencing of the null pointer might take place. Checking the pointer for 
   1050 null should be performed first
   1051 </td><td><pre>
   1052 struct S {
   1053   int x;
   1054 };
   1055 
   1056 S* f();
   1057 
   1058 void test() {
   1059   S *p1 = f();
   1060   int x1 = p1-&gt;x; // warn
   1061   if (p1) {};
   1062 
   1063   S *p2 = f();
   1064   int x2 = p2-&gt;x; // ok
   1065 }
   1066 </pre></td><td class="aligned"></td></tr>
   1067 
   1068 <tr><td><span class="name">different.NullDerefCondOrder
   1069 <br>enhancement to core.NullDereference<br>(C)</span><br><br>
   1070 Dereferencing of the null pointer might take place. Checking the pointer for 
   1071 null should be performed first
   1072 </td><td><pre>
   1073 struct S{bool b;};
   1074 
   1075 S* f();
   1076 
   1077 void test() {
   1078   S *p = f();
   1079   if (p-&gt;b && p) {}; // warn
   1080 }
   1081 </pre></td><td class="aligned"></td></tr>
   1082 
   1083 <tr><td><span class="name">different.IdenticalStmtThenElse
   1084 <br>(C)</span><br><br>
   1085 The 'else' statement is equivalent to the 'then' statement
   1086 </td><td><pre>
   1087 void test() {
   1088   int i;
   1089   if (i==1) {
   1090     i++;
   1091   }
   1092   else { // warn
   1093     i++;
   1094   }
   1095 }
   1096 </pre></td><td class="aligned"></td></tr>
   1097 
   1098 <tr><td><span class="name">different.MultipleAccessors
   1099 <br>(C++)</span><br><br>
   1100 multiple accessors met for 'class::field'
   1101 </td><td><pre>
   1102 class A {
   1103   int i;
   1104   int j;
   1105 public:
   1106   int getI() { return i; }
   1107   int getJ() { return i; } // warn
   1108   void setI(int& ii) { i = ii; }
   1109   void setJ(int& jj) { i = jj; } // warn
   1110 };
   1111 </pre></td><td class="aligned"></td></tr>
   1112 
   1113 <tr><td><span class="name">different.AccessorsForPublic
   1114 <br>(C++)</span><br><br>
   1115 Accessors exist for 'class::field'. Should this field really be public?
   1116 </td><td><pre>
   1117 class A {
   1118 public:
   1119   int i; // warn
   1120   int getI() { return i; }
   1121   void setI(int& ii) { i = ii; }
   1122 };
   1123 </pre></td><td class="aligned"></td></tr>
   1124 
   1125 <tr><td><span class="name">different.LibFuncResultUnised
   1126 <br>(C, C++)</span><br><br>
   1127 Calling 'f' ignoring its return value is of no use (* create the list of known 
   1128 system/library/API functions falling into this category)
   1129 </td><td><pre>
   1130 #include &lt;vector&gt;
   1131 
   1132 void test() {
   1133   std::vector&lt;int&gt; v;
   1134   v.empty(); // warn
   1135 }
   1136 </pre></td><td class="aligned"></td></tr>
   1137 
   1138 <tr><td><span class="name">different.WrongVarForStmt
   1139 <br>(C, C++)</span><br><br>
   1140 Possibly wrong variable is used in the loop/cond-expression of the 'for'
   1141 statement. Did you mean 'proper_variable_name'?
   1142 </td><td><pre>
   1143 void test() {
   1144   int i;
   1145   int j;
   1146   for (j=0; j&lt;3; ++i); // warn
   1147   for (int j=0; i&lt;3; ++j); // warn
   1148 }
   1149 </pre></td><td class="aligned"></td></tr>
   1150 
   1151 <tr><td><span class="name">different.FloatingCompare
   1152 <br>(C)</span><br><br>
   1153 Comparing floating point numbers may be not precise
   1154 </td><td><pre>
   1155 #include &lt;math.h&gt;
   1156 
   1157 void test() {
   1158   double b = sin(M_PI / 6.0);
   1159   if (b == 0.5) // warn
   1160     b = 0;
   1161 }
   1162 </pre></td><td class="aligned"></td></tr>
   1163 
   1164 <tr><td><span class="name">different.BoolCompare
   1165 <br>maybe merge with experimental.core.BoolAssignment<br>(C, C++)</span><br><br>
   1166 Comparing boolean to a value other then 0 or 1
   1167 </td><td><pre>
   1168 void test() {
   1169   int i;
   1170   if (0 < i < 3) {}; // warn
   1171   bool b;
   1172   if (b == 3) {}; // warn
   1173 }
   1174 </pre></td><td class="aligned"></td></tr>
   1175 
   1176 <tr><td><span class="name">different.BitwiseOpBoolArg
   1177 <br>maybe join with experimental.core.BoolAssignment<br>(C, C++)</span><br><br>
   1178 bool value is used at the left/right part of the &amp; (|) operator. Did you mean 
   1179 &amp;&amp; (||) ?
   1180 </td><td><pre>
   1181 int f();
   1182 
   1183 void test() {
   1184   bool b = true;
   1185   if (b &amp; f()) {} // warn
   1186 }
   1187 </pre></td><td class="aligned"></td></tr>
   1188 
   1189 <tr><td><span class="name">different.LabelInsideSwitch
   1190 <br>(C)</span><br><br>
   1191 Possible misprint: label found inside the switch() statement. (* did you mean 
   1192 'default'?)
   1193 </td><td><pre>
   1194 void test() {
   1195   int c = 7;
   1196   switch(c){
   1197   case 1:
   1198     c += 1; break;
   1199   defalt: // warn
   1200     c -= 1; break;
   1201   }
   1202 }
   1203 </pre></td><td class="aligned"></td></tr>
   1204 
   1205 <tr><td><span class="name">different.IdenticalCondIfIf
   1206 <br>(C)</span><br><br>
   1207 The conditions of two subsequent 'if' statements are identical
   1208 </td><td><pre>
   1209 void test() {
   1210   int c = 7;
   1211   if (c &gt; 5) // &lt;-
   1212     c += 1;
   1213   if (c &gt; 5) // warn
   1214     c -= 1;
   1215 }
   1216 </pre></td><td class="aligned"></td></tr>
   1217 
   1218 <tr><td><span class="name">different.CondOpIdenticalReturn
   1219 <br>(C)</span><br><br>
   1220 The return expressions of the '?:' operator are identical
   1221 </td><td><pre>
   1222 void test() {
   1223   unsigned a;
   1224   a = a > 5 ? a : a; // warn
   1225 }
   1226 </pre></td><td class="aligned"></td></tr>
   1227 
   1228 <tr><td><span class="name">different.LogicalOpUselessArg
   1229 <br>(C)</span><br><br>
   1230 The second operand of the &amp;&amp; operator has no impact on expression result
   1231 </td><td><pre>
   1232 void test() {
   1233   unsigned a;
   1234   if (a&lt;7 &amp;&amp; a&lt;10) {}; // warn
   1235 }
   1236 </pre></td><td class="aligned"></td></tr>
   1237 
   1238 <tr><td><span class="name">different.SameResLogicalExpr
   1239 <br>(C)</span><br><br>
   1240 The expression always evaluates to true/false
   1241 </td><td><pre>
   1242 void test() {
   1243   int i=0;
   1244   if (i!=0) {}; // warn
   1245   if (i==0 &amp;&amp; i==1) {}; // warn
   1246   if (i<0 || i>=0) {}; // warn
   1247 }
   1248 </pre></td><td class="aligned"></td></tr>
   1249 
   1250 <tr><td><span class="name">different.SameResUnsignedCmp
   1251 <br>(C)</span><br><br>
   1252 Comparison of unsigned expression 'op expr' is always true/false
   1253 </td><td><pre>
   1254 void test() {
   1255   unsigned u;
   1256   if (u &lt; -1) {}; // warn
   1257   if (u &gt;= 0) {}; // warn
   1258 }
   1259 </pre></td><td class="aligned"></td></tr>
   1260 
   1261 <tr><td><span class="name">different.OpPrecedenceAssignCmp
   1262 <br>(C)</span><br><br>
   1263 Comparison operation has higher precedence then assignment. Bool value is 
   1264 assigned to variable of type 'type'. Parenthesis may bee required around an 
   1265 assignment
   1266 </td><td><pre>
   1267 int f();
   1268 
   1269 void test() {
   1270   bool b;
   1271   int x, y;
   1272   if((b = x != y)) {} // ok
   1273   if((x = f() != y)) {} // warn
   1274 }
   1275 </pre></td><td class="aligned"></td></tr>
   1276 
   1277 <tr><td><span class="name">different.OpPrecedenceIifShift
   1278 <br>(C)</span><br><br>
   1279 ?: has lower precedence then &lt;&lt;
   1280 </td><td><pre>
   1281 #include &lt;iostream&gt;
   1282 
   1283 void test() {
   1284   int a;
   1285   std::cout &lt;&lt; a ? "a" : "b"; // warn
   1286   a &lt;&lt; a&gt;7 ? 1 : 2; // warn
   1287 }
   1288 </pre></td><td class="aligned"></td></tr>
   1289 
   1290 <tr><td><span class="name">different.ObjectUnused
   1291 <br>(C++)</span><br><br>
   1292 The object was created but is not being used<br><br>
   1293 The exception object was created but is not being used. Did you mean 
   1294 'throw std::exception();'?
   1295 </td><td><pre>
   1296 #include &lt;exception&gt;
   1297 
   1298 struct S {
   1299   int x, y;
   1300   S(int xx, int yy) : x(xx), y(yy) {
   1301   }
   1302   S(int xx) {
   1303     S(xx, 0); // warn
   1304   }
   1305 };
   1306 
   1307 void test() {
   1308   S(0, 0); // warn
   1309   std::exception(); // warn
   1310 }
   1311 </pre></td><td class="aligned"></td></tr>
   1312 
   1313 <tr><td><span class="name">different.StaticArrayPtrCompare
   1314 <br>(C)</span><br><br>
   1315 Pointer to static array is being compared to NULL. May the subscripting is 
   1316 missing
   1317 </td><td><pre>
   1318 void test() {
   1319   int a1[1];
   1320   if (a1 == 0) {}; // warn
   1321 
   1322   int a2[1][1];
   1323   if (a2[0]) {}; // warn
   1324 }
   1325 </pre></td><td class="aligned"></td></tr>
   1326 
   1327 <tr><td><span class="name">different.ConversionToBool
   1328 <br>maybe join with experimental.core.BoolAssignment<br>(C, C++)</span><br><br>
   1329 Odd implicit conversion from 'type' to 'bool'
   1330 </td><td><pre>
   1331 bool test() {
   1332   return 1.; // warn
   1333   return ""; // warn
   1334 }
   1335 </pre></td><td class="aligned"></td></tr>
   1336 
   1337 <tr><td><span class="name">different.ArrayBound
   1338 <br>enhancement to experimental.security.ArrayBound[v2]<br>(C, C++)</span><br><br>
   1339 Out-of-bound dynamic array access
   1340 </td><td><pre>
   1341 #include &lt;stdlib.h&gt;
   1342 
   1343 void test() {
   1344   int *p2 = new int[1];
   1345   if(p2[1]) {}; // warn
   1346   int i = 1;
   1347   if(p2[i]) {}; // warn
   1348 }
   1349 </pre></td><td class="aligned"></td></tr>
   1350 
   1351 <tr><td><span class="name">different.StrcpyInputSize
   1352 <BR>enhancement to experimental.unix.cstring.OutOfBounds<br>(C)</span><br><br>
   1353 Buffer copy without checking size of input
   1354 </td><td><pre>
   1355 void test(char* string) {
   1356   char buf[24];
   1357   strcpy(buf, string); // warn
   1358 }
   1359 </pre></td><td class="aligned"></td></tr>
   1360 
   1361 <tr><td><span class="name">different.IntegerOverflow
   1362 <br>(C)</span><br><br>
   1363 Integer overflow
   1364 </td><td><pre>
   1365 #include &lt;limits.h&gt;
   1366 
   1367 int f(int x) {
   1368   return INT_MAX+1; // warn
   1369 }
   1370 
   1371 void test() {
   1372   int x = INT_MAX+1; // warn
   1373   f(INT_MAX+1); // warn
   1374 
   1375   int y = INT_MAX/2+1; // warn
   1376   x = y*2; // warn
   1377 }
   1378 </pre></td><td class="aligned"></td></tr>
   1379 
   1380 <tr><td><span class="name">different.SignExtension
   1381 <br>(C)</span><br><br>
   1382 Unexpected sign extension might take place
   1383 </td><td><pre>
   1384 void f(unsigned int i);
   1385 int g();
   1386 
   1387 unsigned int test() {
   1388   long long sll;
   1389   unsigned long long ull = sll; // warn
   1390   long sl;
   1391   unsigned long ul = sl; // warn
   1392   int si;
   1393   unsigned int ui = si; // warn
   1394   short ss;
   1395   unsigned short us = ss; // warn
   1396   signed char sc;
   1397   unsigned char uc = sc; // warn
   1398   f(si); // warn
   1399   ui = g(); // warn
   1400   return si; // warn
   1401 }
   1402 </pre></td><td class="aligned"></td></tr>
   1403 
   1404 <tr><td><span class="name">different.NumericTruncation
   1405 <br>(C)</span><br><br>
   1406 Numeric truncation might take place
   1407 </td><td><pre>
   1408 void f(int i);
   1409 int g();
   1410 
   1411 int test() {
   1412   unsigned long long ull;
   1413   long long sll;
   1414   unsigned long ul = ull; // warn
   1415   long sl = sll; // warn
   1416   unsigned int ui = ul; // warn
   1417   int si = sl; // warn
   1418   unsigned short us = ui; // warn
   1419   short ss = si; // warn
   1420   unsigned char uc = us; // warn
   1421   signed char sc = uc; // warn
   1422   f(sll); // warn
   1423   ss = g(); // warn
   1424   return sll; // warn
   1425 }
   1426 </pre></td><td class="aligned"></td></tr>
   1427 
   1428 <tr><td><span class="name">different.MissingCopyCtorAssignOp
   1429 <br>(C, C++)</span><br><br>
   1430 The class has dynamically allocated data members but do not define a copy 
   1431 constructor/assignment operator
   1432 </td><td><pre>
   1433 class C { // warn
   1434   int *p; // &lt;-
   1435 public:
   1436   C() { p = new int; }
   1437   ~C() { delete p; }
   1438 };
   1439 </pre></td><td class="aligned"></td></tr>
   1440 
   1441 </table>
   1442 
   1443 <!-- ============================ WinAPI =================================== -->
   1444 <h3>WinAPI</h3>
   1445 <table class="checkers">
   1446 <col class="namedescr"><col class="example"><col class="progress">
   1447 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
   1448 
   1449 <tr><td><span class="name">WinAPI.CreateProcess
   1450 <br>(C)</span><br><br>
   1451 After calling CreateProcess(), ensure that process and thread handles get closed
   1452 (* for the given example: examine data flow from pi, pi.hProcess and pi.hThread)
   1453 </td><td><pre>
   1454 #include &lt;windows.h&gt;
   1455 
   1456 void test() {
   1457   STARTUPINFO si;
   1458   PROCESS_INFORMATION pi;
   1459   BOOL fSuccess;
   1460   fSuccess = CreateProcess(
   1461     NULL, TEXT("MyProgram.exe"), NULL, NULL, 
   1462     TRUE, 0, NULL, NULL, &amp;si, &amp;pi);
   1463 } // warn
   1464 </pre></td><td class="aligned"></td></tr>
   1465 
   1466 <tr><td><span class="name">WinAPI.LoadLibrary
   1467 <br>(C)</span><br><br>
   1468 Calling LoadLibrary without a fully qualified path may allow to load a DLL from 
   1469 arbitrary location
   1470 </td><td><pre>
   1471 #include &lt;windows.h&gt;
   1472 
   1473 void test() {
   1474   HINSTANCE h = LoadLibrary("X.dll"); // warn
   1475 }
   1476 </pre></td><td class="aligned"></td></tr>
   1477 
   1478 <tr><td><span class="name">WinAPI.WideCharToMultiByte
   1479 <br>(C)</span><br><br>
   1480 Buffer overrun while calling WideCharToMultiByte
   1481 </td><td><pre>
   1482 #include &lt;windows.h&gt;
   1483 
   1484 void test() 
   1485 {
   1486   wchar_t ws[] = L"abc";
   1487   char s[3];
   1488   int res1 = WideCharToMultiByte(
   1489                CP_UTF8, 0, ws, -1, s, 
   1490                3, NULL, NULL); // warn
   1491   int res2 = WideCharToMultiByte(
   1492                CP_UTF8, 0, ws, -1, s, 
   1493                3, NULL, NULL); // ok
   1494   if (res2 == sizeof(s))
   1495     s[res2-1] = 0;
   1496   else
   1497    s[res2] = 0;
   1498 }
   1499 </pre></td><td class="aligned"></td></tr>
   1500 
   1501 </table>
   1502 
   1503 <!-- =========================== optimization ============================== -->
   1504 <h3>optimization</h3>
   1505 <table class="checkers">
   1506 <col class="namedescr"><col class="example"><col class="progress">
   1507 <thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
   1508 
   1509 <tr><td><span class="name">optimization.PassConstObjByValue
   1510 <br>(C, C++)</span><br><br>
   1511 Optimization: It is more effective to pass const n-th parameter by reference to 
   1512 avoid unnecessary object copying
   1513 </td><td><pre>
   1514 struct A {
   1515   int a[20];
   1516   int b;
   1517 };
   1518 
   1519 bool FirstIsZero(const struct A a) { // warn
   1520   return a.a[0] == 0;
   1521 }
   1522 </pre></td><td class="aligned"></td></tr>
   1523 
   1524 <tr><td><span class="name">optimization.PostfixIncIter
   1525 <br>(C++)</span><br><br>
   1526 Optimization: It is more effective to use prefix ++ with iterator here
   1527 </td><td><pre>
   1528 #include &lt;vector&gt;
   1529 
   1530 void test() {
   1531   std::vector&lt;int&gt; v;
   1532   std::vector&lt;int&gt;::const_iterator it;
   1533   for(it = v.begin(); 
   1534       it != v.end(); it++) {}; // warn
   1535 }
   1536 </pre></td><td class="aligned"></td></tr>
   1537 
   1538 <tr><td><span class="name">optimization.MultipleCallsStrlen
   1539 <br>(C)</span><br><br>
   1540 Optimization: multiple calls to strlen for a given string in the given 
   1541 expression. It is more effective to hold strlen result in a temporary 
   1542 variable
   1543 </td><td><pre>
   1544 #include &lt;string.h&gt;
   1545 
   1546 void test() {
   1547   const char* s = "abc";
   1548   if (strlen(s) &gt; 0 &amp;&amp;
   1549       strlen(s) &lt; 7) {}; // warn
   1550 }
   1551 </pre></td><td class="aligned"></td></tr>
   1552 
   1553 <tr><td><span class="name">optimization.EmptyCstrDetect
   1554 <br>(C)</span><br><br>
   1555 Optimization: it is more efficient to use "str[0] != '\0'" to identify an empty 
   1556 string
   1557 </td><td><pre>
   1558 #include &lt;string.h&gt;
   1559 
   1560 void test() {
   1561   const char* s = "abc";
   1562   if (strlen(s) &gt; 0) {}; // warn
   1563 }
   1564 </pre></td><td class="aligned"></td></tr>
   1565 
   1566 <tr><td><span class="name">optimization.StrLengthCalculation
   1567 <br>(C, C++)</span><br><br>
   1568 Optimization: it is more efficient to use string::length() method to calculate 
   1569 string length
   1570 </td><td><pre>
   1571 #include &lt;string&gt;
   1572 #include &lt;string.h&gt;
   1573 
   1574 void test() {
   1575   std::string s;
   1576   if (strlen(s.c_str()) != 0) {}; // warn
   1577 }
   1578 </pre></td><td class="aligned"></td></tr>
   1579 
   1580 <tr><td><span class="name">optimization.EmptyContainerDetect
   1581 <br>(C, C++)</span><br><br>
   1582 Optimization: It is more efficient to use container.empty() to identify an 
   1583 empty container
   1584 </td><td><pre>
   1585 #include &lt;list&gt;
   1586 
   1587 void test() {
   1588   std::list&lt;int&gt; l;
   1589   if (l.size() != 0) {}; // warn
   1590 }
   1591 </pre></td><td class="aligned"></td></tr>
   1592 
   1593 </table>
   1594 
   1595 <br>
   1596 </div> <!-- page -->
   1597 </div> <!-- content -->
   1598 </body>
   1599 </html>
   1600