]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - www/analyzer/potential_checkers.html
Vendor import of clang tags/RELEASE_33/final r183502 (effectively, 3.3
[FreeBSD/FreeBSD.git] / www / analyzer / potential_checkers.html
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>