[cfe-commits] r165359 - in /cfe/trunk/www/analyzer: content.css potential_checkers.html

Ted Kremenek kremenek at apple.com
Fri Oct 5 22:09:43 PDT 2012


Author: kremenek
Date: Sat Oct  6 00:09:43 2012
New Revision: 165359

URL: http://llvm.org/viewvc/llvm-project?rev=165359&view=rev
Log:
Add list of potential checkers.  Provided by Anton Yartsev!

Added:
    cfe/trunk/www/analyzer/potential_checkers.html
Modified:
    cfe/trunk/www/analyzer/content.css

Modified: cfe/trunk/www/analyzer/content.css
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/content.css?rev=165359&r1=165358&r2=165359&view=diff
==============================================================================
--- cfe/trunk/www/analyzer/content.css (original)
+++ cfe/trunk/www/analyzer/content.css Sat Oct  6 00:09:43 2012
@@ -63,6 +63,38 @@
 table.options td { padding:5px; padding-left:8px; padding-right:8px }
 table.options td { text-align:left; font-size:9pt }
 
+table.checkers { 
+  border: 1px #cccccc solid;
+  border-collapse: collapse;
+  margin:0px; margin-top:20px; margin-bottom:20px;
+  text-align:left;
+  table-layout: fixed;
+  width: 100%;
+  word-wrap :break-word;
+  font-size: 100%;
+}
+
+table.checkers thead {
+  background-color:#eee; color:#666666;
+  border-top: 2px solid #cccccc;
+  border-bottom: 2px solid #cccccc;
+  font-weight: bold; font-family: Verdana;
+}
+
+table.checkers td { 
+  padding:5px; padding-left:8px; padding-right:8px;
+  border-right: 1px #cccccc dotted;
+  border-bottom: 1px #cccccc dotted;
+}
+
+table.checkers col.namedescr { width: 45% }
+table.checkers col.example { width: 55% }
+table.checkers col.progress { width: 84px }
+table.checkers pre { margin:1px; font-size: 100%; word-wrap :break-word; }
+table.checkers .name { font-weight:bold; }
+table.checkers .checked { background-color:#81F781; }
+table.checkers .commented { color:#909090; }
+
 /* Collapsing Trees: http://dbtree.megalingo.com/web/demo/simple-collapsible-tree.cfm  */
 #collapsetree, #collapsetree a:link, #collapsetree li a:link, #collapsetree a:visited, #collapsetree li a:visited{color:#000;text-decoration:none}
 #collapsetree,#collapsetree ul{list-style-type:none; width:auto; margin:0; padding:0}

Added: cfe/trunk/www/analyzer/potential_checkers.html
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/www/analyzer/potential_checkers.html?rev=165359&view=auto
==============================================================================
--- cfe/trunk/www/analyzer/potential_checkers.html (added)
+++ cfe/trunk/www/analyzer/potential_checkers.html Sat Oct  6 00:09:43 2012
@@ -0,0 +1,1645 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
+          "http://www.w3.org/TR/html4/strict.dtd">
+<html>
+<head>
+  <title>List of potential checkers</title>
+  <link type="text/css" rel="stylesheet" href="content.css">
+  <link type="text/css" rel="stylesheet" href="menu.css">
+  <script type="text/javascript" src="scripts/menu.js"></script>
+  <script type="text/javascript" src="scripts/dbtree.js"></script>
+</head>
+<body>
+
+<div id="page">
+
+<!-- menu -->
+<!--#include virtual="menu.html.incl"-->
+<!-- page content -->
+<div id="content">
+<h1>List of potential checkers</h1>
+
+<!---------------------------- allocation/deallocation -------------------------->
+<h3>allocation/deallocation</h3>
+<table class="checkers">
+<col class="namedescr"><col class="example"><col class="progress">
+<thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
+
+<tr><td><span class="name">memory.LeakNeverReleased<br>
+(C, C++)</span><br><br>
+Memory may be never released, potential leak of memory
+</td><td>
+<pre>
+#include <stdlib.h>
+
+int f() {};
+
+void test() { 
+  int *p1 = (int*)malloc(sizeof(int)); // warn
+  int *p2 = new int; // warn
+  int x = f();
+  if (x==1)
+    return;
+  delete p2;
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.MismatchedFree
+<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
+Mismatched deallocation function is used
+</td><td><pre>
+#include <stdlib.h>
+
+void test() {
+  int *p1 = new int;
+  int *p2 = new int[1];
+
+  free(p1); // warn
+  free(p2); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.MismatchedDelete
+<br>(C, C++)</span><br><br>
+Mismatched deallocation function is used
+</td><td><pre>
+#include <stdlib.h>
+
+void test() {
+  int *p1 = new int;
+  int *p2 = new int[1];
+  int *p3 = (int*)malloc(sizeof(int));
+
+  delete[] p1; // warn
+  delete p2; // warn
+  delete p3; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.MultipleDelete
+<br>(C++)</span><br><br>
+Attempt to deallocate released memory
+</td><td><pre>
+#include <new>
+
+void test() {
+  int *p1 = new int;
+  int *p2 = new(p1) int;
+  int *p3 = p1;
+  delete p1;
+  delete p1; // warn
+  delete p2; // warn
+  delete p3; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.LeakPtrValChanged
+<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
+Potential memory leak: a pointer to newly allocated data loses its original 
+value
+</td><td><pre>
+#include <stdlib.h>
+
+void f(const int *);
+void g(int *);
+
+void test() {
+  int *p1 = new int;
+  p1++; // warn
+  int *p2 = (int *)malloc(sizeof(int));
+  p2 = p1; // warn
+  int *p3 = new int;
+  f(p3);
+  p3++; // warn
+  int *p4 = new int;
+  f(p4);
+  p4++; // ok
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.DeallocateNonPtr
+<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
+Deallocation function is applied to non-pointer
+</td><td><pre>
+#include <stdlib.h>
+
+class A {
+  int *p;
+public:
+  operator int *() { return p; }  
+};
+
+void test() {
+  A a;
+  delete a; // warn
+  free(a); // warn
+  const char *s = "text";
+  delete s; // warn
+  free(s); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.LeakEvalOrder<br>
+(C, C++)</span><br><br>
+Potential memory leak: argument evaluation order is undefined, g() may never be called
+</td><td><pre>
+#include <stdlib.h>
+
+void f1(int, int);
+void f2(int*, int*);
+int g(int *) { throw 1; };
+int h();
+
+void test() {
+  f1(g(new int), h()); // warn
+  f1(g((int *)malloc(sizeof(int))), h()); // warn
+  f2(new int, new int);
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.DstBufferTooSmall
+<br>(C, C++)</span><br><br>
+Destination buffer too small
+</td><td><pre>
+#include <string.h>
+
+void test() {
+  const char* s1 = "abc";
+  char *s2 = new char;
+  strcpy(s2, s1); // warn
+
+  int* p1 = new int[3];
+  int* p2 = new int;
+  memcpy(p2, p1, 3); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">memory.NegativeArraySize
+<br>enhancement to experimental.security.MallocOverflow<br>(C, C++)
+</span><br><br>
+‘n’ is used to specify the buffer size may be negative
+</td><td><pre>
+#include <stdlib.h>
+
+void test() {
+  int *p;
+  int n1 = -1;
+  p = new int[n1]; // warn
+}
+</pre></td><td></td></tr>
+
+</table>
+
+<!-------------------------- constructors/destructors ------------------------->
+<h3>constructors/destructors</h3>
+<table class="checkers">
+<col class="namedescr"><col class="example"><col class="progress">
+<thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
+
+<tr><td><span class="name">ctordtor.ExptInsideDtorExplicit<br>
+(C++)</span><br><br>
+It is dangerous to let an exception leave a destructor. Using try..catch will 
+solve the problem.
+</td><td><pre>
+void f();
+
+class A {
+  A() {}
+  ~A() { throw 1; } // warn
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">ctordtor.ExptInsideDtorImplicit<br>
+(C++)</span><br><br>
+Calls to functions inside a destructor that are known to throw exceptions is 
+dangerous. Using try..catch will solve the problem.
+</td><td><pre>
+void f() { throw 1; };
+
+class A {
+  A() {}
+  ~A() { f(); } // warn
+};
+</pre></td><td></td></tr>
+
+</table>
+
+<!--------------------------------- exceptions -------------------------------->
+<h3>exceptions</h3>
+<table class="checkers">
+<col class="namedescr"><col class="example"><col class="progress">
+<thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
+
+<tr><td><span class="name">exceptions.ThrowSpecButNotThrow
+<br>(C++)</span><br><br>
+Function prototype has throw(T) specifier but the function do not throw
+</td><td><pre>
+void f() throw(int) { // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">exceptions.NoThrowSpecButThrows
+<br>(C++)</span><br><br>
+An exception is throw from a function having the throw() specifier
+</td><td><pre>
+void f() throw() {
+  throw(1); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">exceptions.ThrownTypeDiffersSpec
+<br>(C++)</span><br><br>
+The type of a thrown exception differs from those specified in the throw(T) 
+specifier
+</td><td><pre>
+struct S{};
+void f() throw(int) {
+  S s;
+  throw (s); // warn
+}
+</pre></td><td></td></tr>
+
+</table>
+
+<!---------------------------- smart pointers --------------------------------->
+<h3>smart pointers</h3>
+<table class="checkers">
+<col class="namedescr"><col class="example"><col class="progress">
+<thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
+
+<tr><td><span class="name">smartptr.AutoPtrInit<br>
+(C++03)</span><br><br>
+auto_ptr should store a pointer to an object obtained via new as allocated 
+memory will be cleaned using delete
+</td><td><pre>
+#include <stdlib.h>
+#include <memory>
+
+void test() {
+  std::auto_ptr<int> p1(new int); // Ok
+  std::auto_ptr<int> p2(new int[3]); // warn
+  std::auto_ptr<int> 
+         p3((int *)malloc(sizeof(int))); // warn
+}
+</pre></td><td></td></tr>
+
+</table>
+
+<!---------------------------- undefined behavior ----------------------------->
+<h3>undefined behavior</h3>
+<table class="checkers">
+<col class="namedescr"><col class="example"><col class="progress">
+<thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
+
+<tr><td><span class="name">undefbehavior.ExitInDtor
+<br>(C++)</span><br><br>
+Undefined behavior: std::exit is called to end the program during the 
+destruction of an object with static storage duration
+</td><td><pre>
+#include <cstdlib>
+
+class A {
+public:
+  ~A() {
+    std::exit(1); // warn
+  }
+};
+
+A a;
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.LocalStaticDestroyed
+<br>(C++)</span><br><br>
+Undefined behavior: function containing a definition of static local object is 
+called during the destruction of an object with static storage duration so that 
+flow of control passes through the definition of the previously destroyed 
+static local object
+</td><td><pre>
+void f();
+
+class A {
+public:
+  ~A() {
+    f(); // warn
+  }
+};
+
+class B {};
+
+A a;
+
+void f() {
+  static B b; // <-
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.UseAfterRelease
+<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
+Pointer to deleted object is referenced (The effect of using an invalid pointer 
+value is undefined)
+</td><td><pre>
+#include <stdlib.h>
+
+void test() {
+  int *p = new int;
+  delete p;
+  int i = *p; // warn
+}
+
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ZeroAllocDereference
+<br>enhancement to unix.Malloc<br>(C, C++)</span><br><br>
+The effect of dereferencing a pointer returned as a request for zero size is 
+undefined
+</td><td><pre>
+#include <stdlib.h>
+
+int *p = new int[0];
+int i = p[0]; // warn
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.DeadReferenced
+<br>(C++)</span><br><br>
+Undefined behavior: the following usage of the pointer to the object whose 
+lifetime has ended can result in undefined behavior
+</td><td><pre>
+// C++03
+#include <new>
+
+class A {
+public:
+  int i;
+  void f() {};
+};
+
+class B : public A {
+};
+
+void test() {
+  B *b = new B;
+  new(b) A;
+  b->i; // warn
+  b->f(); // warn
+  static_cast<A*>(b); // warn
+  dynamic_cast<A*>(b); // warn
+  delete b; // warn
+}
+
+// C++11
+#include <new>
+
+class A {
+public:
+  int i;
+  void f() {};
+};
+
+class B : public A {
+public:
+  ~B() {};
+};
+
+void test() {
+  A *a = new A;
+  new(a) B;
+  a->i; // warn
+  a->f(); // warn
+  B *b = new B;
+  new(b) A;
+  b->i; // warn
+  b->f(); // warn
+  static_cast<A*>(b); // warn
+  dynamic_cast<A*>(b); // warn
+  delete b; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ObjLocChanges
+<br>(C++)</span><br><br>
+Undefined behavior: the program must ensure that an object occupies the same 
+storage location when the implicit or explicit destructor call takes place
+</td><td><pre>
+#include <new>
+
+class T { };
+struct B {
+  ~B();
+};
+
+void test() {
+  B *b1 = new B;
+  B b2;
+  new (b1) T;
+  new (&b2) T;
+  delete b1; // warn
+} // warn
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ExprEvalOrderUndef
+<br>(C, C++03)</span><br><br>
+Undefined behavior: a scalar object shall have its stored value modified at 
+most once by the evaluation of an expression
+</td><td><pre>
+void test () {
+  int i = 0;
+  int v[1] = {0};
+  i = v[i++]; // warn
+  i = ++i + 1; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.StaticInitReentered
+<br>(C)</span><br><br>
+Undefined behavior: static declaration is re-entered while the object is being 
+initialized
+</td><td><pre>
+int test(int i) {
+  static int s = test(2*i); // warn
+  return i+1;
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ConstModified
+<br>(C, C++)</span><br><br>
+Undefined behavior: const object is being modified
+</td><td><pre>
+#include <stdlib.h>
+
+class X {
+public :
+  mutable int i;
+  int j;
+};
+class Y {
+public :
+  X x;
+  Y();
+};
+
+void test() {
+  const int *ciq = 
+    (int *)malloc(sizeof(int));
+  int *iq = const_cast<int *>(ciq);
+  *iq = 1; // warn
+
+  const Y y;
+  Y* p = const_cast<Y*>(&y);
+  p->x.i = 1; // ok
+  p->x.j = 1; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.DeadDestructed
+<br>(C++)</span><br><br>
+Undefined behavior: the destructor is invoked for an object whose lifetime 
+has ended
+</td><td><pre>
+class A {
+public:
+  void f() {};
+  A() {};
+  ~A() {};
+};
+
+void test() {
+  A a;
+  a.~A();
+} // warn
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.MethodCallBeforeBaseInit
+<br>(C++)</span><br><br>
+Undefined behavior: calls member function but base not yet initialized
+</td><td><pre>
+class A {
+public :
+  A(int );
+};
+class B : public A {
+public :
+  int f();
+  B() : A(f()) {} // warn
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.MemberOrBaseRefBeforeCtor
+<br>(C++)</span><br><br>
+C++ Undefined behavior: non-static member or base class of non-POD class type 
+is referred before constructor begins execution<br>
+C++11 Undefined behavior: non-static member or base class of a class with a 
+non-trivial constructor is referred before constructor begins execution
+</td><td><pre>
+// C++03
+struct POD { 
+  int i; 
+};
+
+struct non_POD : public POD { 
+  int j; 
+  POD pod;
+};
+
+extern POD pod;
+extern non_POD non_pod;
+
+int *p1 = &non_pod.j; // warn
+int *p2 = &non_pod.pod.i; // warn
+int *p3 = &pod.i; // ok
+POD *p4 = & non_pod; // warn
+
+POD a;
+non_POD b;
+
+struct S {
+  int *k;
+  non_POD non_pod;
+  S() : k(&non_pod.j) {} // warn
+};
+
+// C++11
+struct trivial { 
+  int i; 
+};
+
+struct non_trivial: public trivial { 
+  non_trivial() {};
+  int j; 
+  trivial pod;
+};
+
+extern trivial t;
+extern non_trivial nt;
+
+int *p1 = &nt.j; // warn
+int *p2 = &nt.i; // warn
+int *p3 = &t.i; // ok
+trivial *p4 = &nt;
+
+trivial t;
+non_trivial nt;
+
+struct S {
+  int *k;
+  non_trivial nt;
+  S() : k(&nt.j) {} // warn
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.MemberRefAfterDtor
+<br>(C++)</span><br><br>
+C++03: Undefined behavior: non-static member of non-POD class type is referred 
+after destructor ends execution<br>
+C++11: Undefined behavior: non-static member of a class with a non-trivial 
+destructor is referred after destructor ends execution
+</td><td><pre>
+// C++03
+struct non_POD {
+  virtual void f() {};
+};
+
+void test() {
+  non_POD *non_pod = new non_POD();
+  non_pod->~non_POD();  
+  non_pod->f(); // warn
+}
+
+// C++11
+struct S {
+  ~S() {};
+  void f() {};
+};
+
+void test() {
+  S *s = new S();
+  s->~S();  
+  s->f(); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.CtorForeignCall
+<br>(C++)</span><br><br>
+Undefined behavior: call to virtual function of an object under construction 
+whose type is neither the constructors own class or one of its bases
+</td><td><pre>
+class A {
+public:
+  virtual void f() {};
+};
+
+class B {
+public:
+  B(A* a) { a->f(); } // warn
+};
+
+class C : public A, B {
+public:
+  C() : B((A*)this) {}
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.CtorForeignCast 
+undefbehavior.CtorForeignTypeid
+<br>(C++)</span><br><br>
+Undefined behavior: the operand of typeid/dynamic_cast is an object under 
+construction whose type is neither the constructors own class or one of its 
+bases
+</td><td><pre>
+#include <typeinfo>
+
+class A {
+public:
+  virtual void f() {};
+};
+
+class B {
+public:
+  B(A* a) { 
+    typeid(*a); // warn
+    dynamic_cast<B*>(a); //warn
+  }
+};
+
+class C : public A, B {
+public:
+  C() : B((A*)this) {}
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.MemberRefInCatch 
+undefbehavior.BaseRefInCatch
+<br>(C++)</span><br><br>
+Undefined behavior: referring to any non-static member or base class of an 
+object in the handler for a function-try-block of a constructor or destructor 
+for that object results in undefined behavior
+</td><td><pre>
+class C {
+  int i;
+public :
+  C()
+  try
+  : i(1) {}
+  catch (...)
+  {
+    i=2; // warn
+  }
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ReturnAtCatchEnd
+<br>(C++)</span><br><br>
+Undefined behavior: a function returns when control reaches the end of a 
+handler. This results in undefined behavior in a value-returning 
+function
+</td><td><pre>
+int test() try {
+}
+catch(int) {
+} // warn
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.AutoptrsOwnSameObj
+<br>(C++03)</span><br><br>
+Undefined behavior: if more than one auto_ptr owns the same object at the same 
+time the behavior of the program is undefined.
+</td><td><pre>
+#include <memory>
+
+void test() {
+  int *data = new int;
+  std::auto_ptr<int> p(data);
+  std::auto_ptr<int> q(data); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.BasicStringBoundAccess
+<br>(C++03)</span><br><br>
+Undefined behavior: out-of-bound basic_string access
+</td><td><pre>
+void test() {
+  std::basic_string<char> s;
+  char c = s[10]; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.BasicStringBoundModification
+<br>(C++)</span><br><br>
+Undefined behavior: out-of-bound basic_string modification
+</td><td><pre>
+void test() {
+  std::basic_string<char> s;
+  s[10] = 0; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.EosDereference
+<br>(C++)</span><br><br>
+Undefined behavior: the result of operator*() on an end of stream is 
+undefined
+</td><td><pre>
+#include <vector>
+
+void test() {
+  std::vector<int> v;
+  int i = *v.end(); // warn
+  *v.end() = 0; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.QsortNonPOD 
+undefbehavior.QsortNonTrivial
+<br>C++</span><br><br>
+C++03: Undefined behavior: the objects in the array passed to qsort are of 
+non-POD type<br>
+C++11: Undefined behavior: the objects in the array passed to qsort are of 
+non-trivial type
+</td><td><pre>
+// C++03
+#include <cstdlib>
+
+struct non_POD {
+  int i;
+  non_POD(int ii) : i(ii) {}
+};
+
+non_POD values[] = { non_POD(2), non_POD(1) };
+
+int compare(const void *a, 
+            const void *b) {
+  return ( (*(non_POD*)a).i -
+           (*(non_POD*)b).i );
+}
+
+void test() {
+  qsort(values, 2, sizeof(non_POD), 
+        compare); // warn
+}
+
+// C++11
+#include <cstdlib>
+
+struct S {};
+
+struct trivial_non_POD : public S {
+  int i;
+};
+
+struct non_trivial {
+  int i;
+  non_trivial() {}
+};
+
+trivial_non_POD tnp[2];
+non_trivial nt[2];
+
+int compare1(const void *a, 
+             const void *b) {
+  return ( (*(trivial_non_POD *)a).i -
+           (*(trivial_non_POD *)b).i );
+}
+
+int compare2(const void *a, 
+             const void *b) {
+  return ( (*(non_trivial *)a).i -
+           (*(non_trivial *)b).i );
+}
+
+void test() {
+  qsort(tnp, 2, sizeof(trivial_non_POD), 
+        compare1); // ok
+  qsort(nt, 2, sizeof(non_trivial), 
+        compare2); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ThrowWhileCopy
+<br>C++</span><br><br>
+Undefined behavior: copy constructor/assignment operator can throw an exception.
+The effects are undefined if an exception is thrown.
+</td><td><pre>
+struct S {
+  int i, j;
+  S (const S &s) {
+    i = s.i;
+    throw 1; // warn
+    j = s.j;
+  };
+  S& operator=(const S &s) {
+    i = s.i;
+    throw 1; // warn
+    j = s.j;
+  }
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ValarrayArgBound
+<br>(C++)</span><br><br>
+Undefined behavior: the value of the second argument is greater than the number 
+of values pointed to by the first argument
+</td><td><pre>
+#include <valarray>
+
+struct S {
+  int i;
+  S(int ii) : i(ii) {};
+};
+
+void test(void) {
+  S s[] = { S(1), S(2) };
+  std::valarray<S> v(s,3); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ValarrayLengthDiffer
+<br>(C++)</span><br><br>
+Undefined behavior: valarray operands are of different length
+</td><td><pre>
+// C++03
+#include <valarray>
+
+void test(void) {
+  std::valarray<int> a(0, 1), b(0, 2);
+  std::valarray<bool> c(false, 1);
+  a = b; // warn
+  a *= b; // warn
+  a = a * b; // warn
+  c = a == b; // warn
+  b.resize(1);
+  a = b; // OK
+}
+
+// C++11
+#include <valarray>
+
+void test(void) {
+  std::valarray<int> a(0, 1), b(0, 2);
+  std::valarray<bool> c(false, 1);
+  a = b; // ok
+  a *= b; // ok
+  a = a * b; // warn
+  c = a == b; // warn
+  b.resize(1);
+  a = b; // OK
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ValarrayZeroLength
+<br>(C++)</span><br><br>
+Undefined behavior: calling sum()/min()/max() method of an array having zero 
+length, the behavior is undefined
+</td><td><pre>
+#include <valarray>
+
+void test(void) {
+  std::valarray<int> v(0, 0);
+  v.sum(); // warn
+  v.min(); // warn
+  v.max(); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.ValarrayBadIndirection
+<br>(C++)</span><br><br>
+Undefined behavior: element N is specified more than once in the 
+indirection
+</td><td><pre>
+#include <valarray>
+
+void test() {
+  size_t addr[] = {0, 1, 1}; // N is 1
+  std::valarray<size_t>indirect(addr, 3);
+  std::valarray<int> a(0, 5), b(1, 3);
+  a[indirect] = b; //warn
+  a[indirect] *= b; //warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.IosBaseDestroyedBeforeInit
+<br>(C++)</span><br>
+<br>Undefined behavior: ios_base object is destroyed before initialization have 
+taken place. basic_ios::init should be call to initialize ios_base 
+members
+</td><td><pre>
+#include <ios>
+
+using namespace std;
+template <class T, class Traits = std::char_traits<T>>
+class my_stream1 : public std::basic_ios<T, Traits> {
+};
+
+template <class T, class Traits = std::char_traits<T>>
+class my_stream2 : public std::basic_ios<T, Traits> {
+  class my_streambuf : public std::basic_streambuf<T, Traits> {
+  };
+public:
+  my_stream2() {
+    this->init(new my_streambuf);
+  }
+};
+
+void test() {
+  my_stream1<char> *p1 = new my_stream1<char>
+  my_stream2<char> *p2 = new my_stream2<char>
+  delete p1; // warn
+  delete p2; // ok
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.IosBaseUsedBeforeInit
+<br>(C++11)</span><br><br>
+Undefined behavior: ios_base object is used before initialization have taken 
+place. basic_ios::init should be call to initialize ios_base members
+</td><td><pre>
+#include <ios>
+
+using namespace std;
+template <class T, class Traits = std::char_traits<T>>
+class my_stream1 : public std::basic_ios<T, Traits> {
+};
+
+template <class T, class Traits = std::char_traits<T>>
+class my_stream2 : public std::basic_ios<T, Traits> {
+  class my_streambuf : public std::basic_streambuf<T, Traits> {
+  };
+public:
+  my_stream2() {
+    this->init(new my_streambuf);
+  }
+};
+
+void test() {
+  my_stream1<char> *p1 = new my_stream1<char>
+  my_stream2<char> *p2 = new my_stream2<char>
+  p1->narrow('a', 'b'); // warn
+  p2->narrow('a', 'b'); // ok
+  delete p1; // warn
+  delete p2; // ok
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">undefbehavior.MinusOnePosType
+<br>(C++)</span><br><br>
+Undefined behavior: passing -1 to any streambuf/istream/ostream member that 
+accepts a value of type traits::pos_type result in undefined behavior
+</td><td><pre>
+#include <fstream>
+
+class my_streambuf : public std::streambuf {
+  void f() {
+    seekpos(-1); // warn
+  }
+};
+
+void test() {
+  std::filebuf fb;
+  std::istream in(&fb);
+  std::ostream out(&fb);
+  std::filebuf::off_type pos(-1);
+  in.seekg(pos); // warn
+  out.seekp(-1); // warn
+}
+</pre></td><td></td></tr>
+</table>
+
+<!------------------------------- different ----------------------------------->
+<h3>different</h3>
+<table class="checkers">
+<col class="namedescr"><col class="example"><col class="progress">
+<thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr>
+</thead>
+
+<tr><td><span class="name">different.ArgEvalOrderUndef
+<br>(C)</span><br><br>
+Errors because of the order of evaluation of function arguments is undefined
+</td><td><pre>
+void f(int, int);
+
+void test() {
+  int i = 0;
+  int v[1] = {0};
+  f(v[i], i++); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.IdenticalExprBinOp
+<br>(C)</span><br><br>
+There are identical sub-expressions to the left and to the right of the 
+operator
+</td><td><pre>
+#define A 1
+#define B 1
+
+bool isNan(double d) { 
+  return d != d; // ok
+}
+
+int f();
+
+void test() {
+  int i = 0;
+  if (i != 0 && i != 0) {} // warn
+
+  if(i == A || i == B) {} // ok
+
+  if (++i != 0 && ++i != 0) {} // ok
+
+  if (f() && f()) {} // ok
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.FuncPtrInsteadOfCall
+<br>(C)</span><br><br>
+Possibly a function call should be used instead of a pointer to function
+</td><td><pre>
+int f();
+
+void test() {
+  if (f == 0) {} // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.IdenticalCondIfElseIf
+<br>(C)</span><br><br>
+The use of 'if (A) {...} else if (A) {...}' pattern was detected. There is a 
+probability of logical error presence
+</td><td><pre>
+void test() { 
+  int i = 7;
+  if (i == 1) {}
+  else if (i == 1) {} // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">SuccessiveAssign
+<br>(C)</span><br><br>
+Successive assign to a variable
+</td><td><pre>
+void test() { 
+  int i=0;
+  i=1;
+  i=2; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.NullDerefStmtOrder
+<br>enhancement to core.NullDereference<br>(C)</span><br><br>
+Dereferencing of the null pointer might take place. Checking the pointer for 
+null should be performed first
+</td><td><pre>
+struct S {
+  int x;
+};
+
+S* f();
+
+void test() {
+  S *p1 = f();
+  int x1 = p1->x; // warn
+  if (p1) {};
+
+  S *p2 = f();
+  int x2 = p2->x; // ok
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.NullDerefCondOrder
+<br>enhancement to core.NullDereference<br>(C)</span><br><br>
+Dereferencing of the null pointer might take place. Checking the pointer for 
+null should be performed first
+</td><td><pre>
+struct S{bool b;};
+
+S* f();
+
+void test() {
+  S *p = f();
+  if (p->b && p) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.IdenticalStmtThenElse
+<br>(C)</span><br><br>
+The 'else' statement is equivalent to the 'then' statement
+</td><td><pre>
+void test() {
+  int i;
+  if (i==1) {
+    i++;
+  }
+  else { // warn
+    i++;
+  }
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.MultipleAccessors
+<br>(C++)</span><br><br>
+multiple accessors met for 'class::field'
+</td><td><pre>
+class A {
+  int i;
+  int j;
+public:
+  int getI() { return i; }
+  int getJ() { return i; } // warn
+  void setI(int& ii) { i = ii; }
+  void setJ(int& jj) { i = jj; } // warn
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.AccessorsForPublic
+<br>(C++)</span><br><br>
+Accessors exist for 'class::field'. Should this field really be public?
+</td><td><pre>
+class A {
+public:
+  int i; // warn
+  int getI() { return i; }
+  void setI(int& ii) { i = ii; }
+};
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.LibFuncResultUnised
+<br>(C, C++)</span><br><br>
+Calling 'f' ignoring its return value is of no use (* create the list of known 
+system/library/API functions falling into this category)
+</td><td><pre>
+#include <vector>
+
+void test() {
+  std::vector<int> v;
+  v.empty(); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.WrongVarForStmt
+<br>(C, C++)</span><br><br>
+Possibly wrong variable is used in the loop/cond-expression of the ‘for’ 
+statement. Did you mean ‘proper_variable_name’?
+</td><td><pre>
+void test() {
+  int i;
+  int j;
+  for (j=0; j<3; ++i); // warn
+  for (int j=0; i<3; ++j); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.FloatingCompare
+<br>(C)</span><br><br>
+Comparing floating point numbers may be not precise
+</td><td><pre>
+#include <math.h>
+
+void test() {
+  double b = sin(M_PI / 6.0);
+  if (b == 0.5) // warn
+    b = 0;
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.BoolCompare
+<br>maybe merge with experimental.core.BoolAssignment<br>(C, C++)</span><br><br>
+Comparing boolean to a value other then 0 or 1
+</td><td><pre>
+void test() {
+  int i;
+  if (0 < i < 3) {}; // warn
+  bool b;
+  if (b == 3) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.BitwiseOpBoolArg
+<br>maybe join with experimental.core.BoolAssignment<br>(C, C++)</span><br><br>
+bool value is used at the left/right part of the & (|) operator. Did you mean 
+&& (||) ?
+</td><td><pre>
+int f();
+
+void test() {
+  bool b = true;
+  if (b & f()) {} // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.LabelInsideSwitch
+<br>(C)</span><br><br>
+Possible misprint: label found inside the switch() statement. (* did you mean 
+‘default’?)
+</td><td><pre>
+void test() {
+  int c = 7;
+  switch(c){
+  case 1:
+    c += 1; break;
+  defalt: // warn
+    c -= 1; break;
+  }
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.IdenticalCondIfIf
+<br>(C)</span><br><br>
+The conditions of two subsequent ‘if’ statements are identical
+</td><td><pre>
+void test() {
+  int c = 7;
+  if (c > 5) // <-
+    c += 1;
+  if (c > 5) // warn
+    c -= 1;
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.CondOpIdenticalReturn
+<br>(C)</span><br><br>
+The return expressions of the ‘?:’ operator are identical
+</td><td><pre>
+void test() {
+  unsigned a;
+  a = a > 5 ? a : a; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.UnaryPlusWithUnsigned
+<br>(C)</span><br><br>
+Using ‘unary +’ with unsigned is meaningless
+</td><td><pre>
+void test() {
+  unsigned a;
+  a = +a; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.LogicalOpUselessArg
+<br>(C)</span><br><br>
+The second operand of the && operator has no impact on expression result
+</td><td><pre>
+void test() {
+  unsigned a;
+  if (a<7 && a<10) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.SameResLogicalExpr
+<br>(C)</span><br><br>
+The expression always evaluates to true/false
+</td><td><pre>
+void test() {
+  int i=0;
+  if (i!=0) {}; // warn
+  if (i==0 && i==1) {}; // warn
+  if (i<0 || i>=0) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.SameResUnsignedCmp
+<br>(C)</span><br><br>
+Comparison of unsigned expression ‘op expr’ is always true/false
+</td><td><pre>
+void test() {
+  unsigned u;
+  if (u < -1) {}; // warn
+  if (u >= 0) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.OpPrecedenceAssignCmp
+<br>(C)</span><br><br>
+Comparison operation has higher precedence then assignment. Bool value is 
+assigned to variable of type ‘type’. Parenthesis may bee required around an 
+assignment
+</td><td><pre>
+int f();
+
+void test() {
+  bool b;
+  int x, y;
+  if((b = x != y)) {} // ok
+  if((x = f() != y)) {} // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.OpPrecedenceIifShift
+<br>(C)</span><br><br>
+?: has lower precedence then <<
+</td><td><pre>
+#include <iostream>
+
+void test() {
+  int a;
+  std::cout << a ? "a" : "b"; // warn
+  a << a>7 ? 1 : 2; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.ObjectUnused
+<br>(C++)</span><br><br>
+The object was created but is not being used<br><br>
+The exception object was created but is not being used. Did you mean 
+‘throw std::exception();’ ?
+</td><td><pre>
+#include <exception>
+
+struct S {
+  int x, y;
+  S(int xx, int yy) : x(xx), y(yy) {
+  }
+  S(int xx) {
+    S(xx, 0); // warn
+  }
+};
+
+void test() {
+  S(0, 0); // warn
+  std::exception(); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.StaticArrayPtrCompare
+<br>(C)</span><br><br>
+Pointer to static array is being compared to NULL. May the subscripting is 
+missing
+</td><td><pre>
+void test() {
+  int a1[1];
+  if (a1 == 0) {}; // warn
+
+  int a2[1][1];
+  if (a2[0]) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.ConversionToBool
+<br>maybe join with experimental.core.BoolAssignment<br>(C, C++)</span><br><br>
+Odd implicit conversion from ‘type’ to ‘bool’
+</td><td><pre>
+bool test() {
+  return 1.; // warn
+  return ""; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.ArrayBound
+<br>enhancement to experimental.security.ArrayBound[v2]<br>(C, C++)</span><br><br>
+Out-of-bound dynamic array access
+</td><td><pre>
+#include <stdlib.h>
+
+void test() {
+  int *p2 = new int[1];
+  if(p2[1]) {}; // warn
+  int i = 1;
+  if(p2[i]) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.StrcpyInputSize
+<BR>enhancement to experimental.unix.cstring.OutOfBounds<br>(C)</span><br><br>
+Buffer copy without checking size of input
+</td><td><pre>
+void test(char* string) {
+  char buf[24];
+  strcpy(buf, string); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.IntegerOverflow
+<br>(C)</span><br><br>
+Integer overflow
+</td><td><pre>
+#include <limits.h>
+
+int f(int x) {
+  return INT_MAX+1; // warn
+}
+
+void test() {
+  int x = INT_MAX+1; // warn
+  f(INT_MAX+1); // warn
+
+  int y = INT_MAX/2+1; // warn
+  x = y*2; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.SignExtension
+<br>(C)</span><br><br>
+Unexpected sign extension might take place
+</td><td><pre>
+void f(unsigned int i);
+int g();
+
+unsigned int test() {
+  long long sll;
+  unsigned long long ull = sll; // warn
+  long sl;
+  unsigned long ul = sl; // warn
+  int si;
+  unsigned int ui = si; // warn
+  short ss;
+  unsigned short us = ss; // warn
+  signed char sc;
+  unsigned char uc = sc; // warn
+  f(si); // warn
+  ui = g(); // warn
+  return si; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.NumericTruncation
+<br>(C)</span><br><br>
+Numeric truncation might take place
+</td><td><pre>
+void f(int i);
+int g();
+
+int test() {
+  unsigned long long ull;
+  long long sll;
+  unsigned long ul = ull; // warn
+  long sl = sll; // warn
+  unsigned int ui = ul; // warn
+  int si = sl; // warn
+  unsigned short us = ui; // warn
+  short ss = si; // warn
+  unsigned char uc = us; // warn
+  signed char sc = uc; // warn
+  f(sll); // warn
+  ss = g(); // warn
+  return sll; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">different.MissingCopyCtorAssignOp
+<br>(C, C++)</span><br><br>
+The class has dynamically allocated data members but do not define a copy 
+constructor/assignment operator
+</td><td><pre>
+class C { // warn
+  int *p; // <-
+public:
+  C() { p = new int; }
+  ~C() { delete p; }
+};
+</pre></td><td></td></tr>
+
+</table>
+
+<!------------------------------- WinAPI -------------------------------------->
+<h3>WinAPI</h3>
+<table class="checkers">
+<col class="namedescr"><col class="example"><col class="progress">
+<thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
+
+<tr><td><span class="name">WinAPI.CreateProcess
+<br>(C)</span><br><br>
+After calling CreateProcess(), ensure that process and thread handles get closed
+(* for the given example: examine data flow from pi, pi.hProcess and pi.hThread)
+</td><td><pre>
+#include <windows.h>
+
+void test() {
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+  BOOL fSuccess;
+  fSuccess = CreateProcess(
+    NULL, TEXT("MyProgram.exe"), NULL, NULL, 
+    TRUE, 0, NULL, NULL, &si, &pi);
+} // warn
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">WinAPI.LoadLibrary
+<br>(C)</span><br><br>
+Calling LoadLibrary without a fully qualified path may allow to load a DLL from 
+arbitrary location
+</td><td><pre>
+#include <windows.h>
+
+void test() {
+  HINSTANCE h = LoadLibrary("X.dll"); // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">WinAPI.WideCharToMultiByte
+<br>(C)</span><br><br>
+Buffer overrun while calling WideCharToMultiByte
+</td><td><pre>
+#include <windows.h>
+
+void test() 
+{
+  wchar_t ws[] = L"abc";
+  char s[3];
+  int res1 = WideCharToMultiByte(
+               CP_UTF8, 0, ws, -1, s, 
+               3, NULL, NULL); // warn
+  int res2 = WideCharToMultiByte(
+               CP_UTF8, 0, ws, -1, s, 
+               3, NULL, NULL); // ok
+  if (res2 == sizeof(s))
+    s[res2-1] = 0;
+  else
+   s[res2] = 0;
+}
+</pre></td><td></td></tr>
+
+</table>
+
+<!------------------------------ optimization --------------------------------->
+<h3>optimization</h3>
+<table class="checkers">
+<col class="namedescr"><col class="example"><col class="progress">
+<thead><tr><td>Name, Description</td><td>Example</td><td>Progress</td></tr></thead>
+
+<tr><td><span class="name">optimization.PassConstObjByValue
+<br>(C, C++)</span><br><br>
+Optimization: It is more effective to pass const n-th parameter by reference to 
+avoid unnecessary object copying
+</td><td><pre>
+struct A {
+  int a[20];
+  int b;
+};
+
+bool FirstIsZero(const struct A a) { // warn
+  return a.a[0] == 0;
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">optimization.PostfixIncIter
+<br>(C++)</span><br><br>
+Optimization: It is more effective to use prefix ++ with iterator here
+</td><td><pre>
+#include <vector>
+
+void test() {
+  std::vector<int> v;
+  std::vector<int>::const_iterator it;
+  for(it = v.begin(); 
+      it != v.end(); it++) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">optimization.MultipleCallsStrlen
+<br>(C)</span><br><br>
+Optimization: multiple calls to strlen for a given string in the given 
+expression. It is more effective to hold strlen result in a temporary 
+variable
+</td><td><pre>
+#include <string.h>
+
+void test() {
+  const char* s = "abc";
+  if (strlen(s) > 0 && 
+      strlen(s) < 7) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">optimization.EmptyCstrDetect
+<br>(C)</span><br><br>
+Optimization: it is more efficient to use “str[0] != ‘\0’” to identify an empty 
+string
+</td><td><pre>
+#include <string.h>
+
+void test() {
+  const char* s = "abc";
+  if (strlen(s) > 0) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">optimization.StrLengthCalculation
+<br>(C, C++)</span><br><br>
+Optimization: it is more efficient to use string::length() method to calculate 
+string length
+</td><td><pre>
+#include <string>
+#include <string.h>
+
+void test() {
+  std::string s;
+  if (strlen(s.c_str()) != 0) {}; // warn
+}
+</pre></td><td></td></tr>
+
+<tr><td><span class="name">optimization.EmptyContainerDetect
+<br>(C, C++)</span><br><br>
+Optimization: It is more efficient to use container.empty() to identify an 
+empty container
+</td><td><pre>
+#include <list>
+
+void test() {
+  std::list<int> l;
+  if (l.size() != 0) {}; // warn
+}
+</pre></td><td></td></tr>
+
+</table>
+
+<br>
+</div> <!-- page -->
+</div> <!-- content -->
+</body>
+</html>





More information about the cfe-commits mailing list