108 changes: 52 additions & 56 deletions clang/www/analyzer/potential_checkers.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
<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/expandcollapse.js"></script>
<script type="text/javascript" src="scripts/menu.js"></script>
</head>
<body>
<body onload="initExpandCollapse()">

<div id="page">

Expand Down Expand Up @@ -470,118 +471,113 @@ <h3>undefined behavior</h3>
<td class="aligned"></td></tr>


<!--<tr><td><div class="namedescr expandable"><span class="name">
<tr><td><div class="namedescr expandable"><span class="name">
undefbehavior.DeadReferenced</span><span class="lang">
(C++)</span><div class="descr">
Undefined behavior: the following usage of the pointer to the object whose
lifetime has ended can result in undefined behavior.
Undefined behavior: the following usage of the pointer to the object whose
lifetime has ended can result in undefined behavior:<br>
The object will be or was of a class type with a non-trivial destructor and
<ul><li>the pointer is used as the operand of a delete-expression</li></ul>
The object will be or was of a non-POD class type (C++11: any class type) and
<ul><li>the pointer is used to access a non-static data member or call a
non-static member function of the object</li>
<li>the pointer is implicitly converted to a pointer to a base class
type</li>
<li>the pointer is used as the operand of a <code>static_cast</code> (except
when the conversion is to <code>void*</code>, or to <code>void*</code> and
subsequently to <code>char*</code>, or <code>unsigned char*</code>)</li>
<li>the pointer is used as the operand of a <code>dynamic_cast</code></li></ul>
<p>Source: C++03 3.8p5, p7; C++11 3.8p5, p7.</p></div></div></td>
<td><div class="exampleContainer expandable">
<div class="example"><pre>
#include &lt;new&gt;

class A {
public:
int i;
~A();
};

class B : public A {};

int test() {
B *b = new B;
new(b) A;
return b-&gt;i; // warn
void test() {
A *a = new A;
new(a) B;
delete a; // warn
}
</pre></div>
<div class="example"><pre>
#include &lt;new&gt;

class A {
public:
void f() {};
~A();
};

class B : public A {};
class B {};

void test() {
B *b = new B;
new(b) A;
b-&gt;f(); // warn
A *a = new A;
new(a) B;
a->~A();
}
</pre></div>
<div class="example"><pre>
#include &lt;new&gt;

class A {};
class A {
public:
~A();
};

class B : public A {};

A* test() {
B *b = new B;
new(b) A;
static_cast&lt;A*&gt;(b); // warn
}
</pre></div>
<div class="example"><pre>
#include &lt;new&gt;
class A {};
class C {};

class B : public A {};
void f(A*);

A* test() {
void test() {
B *b = new B;
new(b) A;
dynamic_cast&lt;A*&gt;(b); // warn
new(b) C;
f(b); // warn
}
</pre></div>
<div class="example"><pre>
#include &lt;new&gt;

class A {};
class A {
public:
~A();
};

class B : public A {};

class C {};

A* test() {
B *b = new B;
new(b) A;
dynamic_cast&lt;A*&gt;(b); // warn
new(b) C;
return static_cast&lt;A*&gt;(b); // warn
}
</pre></div>
<div class="example"><pre>
#include &lt;new&gt;

class A {};
class B : public A {};
void test() {
B *b = new B;
new(b) A;
delete b; // warn
}
</pre></div>
<div class="example"><pre>
// C++11
#include &lt;new&gt;
class A {
public:
int i;
~A();
};

class B : public A {
public:
~B() {};
};
class B : public A {};

int test() {
A *a = new A;
new(a) B;
return a-&gt;i; // warn
class C {};

A* test() {
B *b = new B;
new(b) C;
return dynamic_cast&lt;A*&gt;(b); // warn
}
</pre></div></div></td>
<td class="aligned"></td></tr>-->
<td class="aligned"></td></tr>


<tr><td><div class="namedescr expandable"><span class="name">
Expand Down
191 changes: 191 additions & 0 deletions clang/www/analyzer/scripts/expandcollapse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
// expand/collapse button (expander) is added if height of a cell content
// exceeds CLIP_HEIGHT px.
var CLIP_HEIGHT = 135;

// Height in pixels of an expander image.
var EXPANDER_HEIGHT = 13;

// Path to images for an expander.
var imgPath = "./images/expandcollapse/";

// array[group][cell] of { 'height', 'expanded' }.
// group: a number; cells of the same group belong to the same table row.
// cell: a number; unique index of a cell in a group.
// height: a number, px; original height of a cell in a table.
// expanded: boolean; is a cell expanded or collapsed?
var CellsInfo = [];

// Extracts group and cell indices from an id of the form identifier_group_cell.
function getCellIdx(id) {
var idx = id.substr(id.indexOf("_") + 1).split("_");
return { 'group': idx[0], 'cell': idx[1] };
}

// Returns { 'height', 'expanded' } info for a cell with a given id.
function getCellInfo(id) {
var idx = getCellIdx(id);
return CellsInfo[idx.group][idx.cell];
}

// Initialization, add nodes, collect info.
function initExpandCollapse() {
if (!document.getElementById)
return;

var groupCount = 0;

// Examine all table rows in the document.
var rows = document.body.getElementsByTagName("tr");
for (var i=0; i<rows.length; i+=1) {

var cellCount=0, newGroupCreated = false;

// Examine all divs in a table row.
var divs = rows[i].getElementsByTagName("div");
for (var j=0; j<divs.length; j+=1) {

var expandableDiv = divs[j];

if (expandableDiv.className.indexOf("expandable") == -1)
continue;

if (expandableDiv.offsetHeight <= CLIP_HEIGHT)
continue;

// We found a div wrapping a cell content whose height exceeds
// CLIP_HEIGHT.
var originalHeight = expandableDiv.offsetHeight;
// Unique postfix for ids for generated nodes for a given cell.
var idxStr = "_" + groupCount + "_" + cellCount;
// Create an expander and an additional wrapper for a cell content.
//
// --- expandableDiv ----
// --- expandableDiv --- | ------ data ------ |
// | cell content | -> | | cell content | |
// --------------------- | ------------------ |
// | ---- expander ---- |
// ----------------------
var data = document.createElement("div");
data.className = "data";
data.id = "data" + idxStr;
data.innerHTML = expandableDiv.innerHTML;
with (data.style) { height = (CLIP_HEIGHT - EXPANDER_HEIGHT) + "px";
overflow = "hidden" }

var expander = document.createElement("img");
with (expander.style) { display = "block"; paddingTop = "5px"; }
expander.src = imgPath + "ellipses_light.gif";
expander.id = "expander" + idxStr;

// Add mouse calbacks to expander.
expander.onclick = function() {
expandCollapse(this.id);
// Hack for Opera - onmouseout callback is not invoked when page
// content changes dinamically and mouse pointer goes out of an element.
this.src = imgPath +
(getCellInfo(this.id).expanded ? "arrows_light.gif"
: "ellipses_light.gif");
}
expander.onmouseover = function() {
this.src = imgPath +
(getCellInfo(this.id).expanded ? "arrows_dark.gif"
: "ellipses_dark.gif");
}
expander.onmouseout = function() {
this.src = imgPath +
(getCellInfo(this.id).expanded ? "arrows_light.gif"
: "ellipses_light.gif");
}

expandableDiv.innerHTML = "";
expandableDiv.appendChild(data);
expandableDiv.appendChild(expander);
expandableDiv.style.height = CLIP_HEIGHT + "px";
expandableDiv.id = "cell"+ idxStr;

// Keep original cell height and its ecpanded/cpllapsed state.
if (!newGroupCreated) {
CellsInfo[groupCount] = [];
newGroupCreated = true;
}
CellsInfo[groupCount][cellCount] = { 'height' : originalHeight,
'expanded' : false };
cellCount += 1;
}
groupCount += newGroupCreated ? 1 : 0;
}
}

function isElemTopVisible(elem) {
var body = document.body,
html = document.documentElement,
// Calculate expandableDiv absolute Y coordinate from the top of body.
bodyRect = body.getBoundingClientRect(),
elemRect = elem.getBoundingClientRect(),
elemOffset = Math.floor(elemRect.top - bodyRect.top),
// Calculate the absoute Y coordinate of visible area.
scrollTop = html.scrollTop || body && body.scrollTop || 0;
scrollTop -= html.clientTop; // IE<8


if (elemOffset < scrollTop)
return false;

return true;
}

// Invoked when an expander is pressed; expand/collapse a cell.
function expandCollapse(id) {
var cellInfo = getCellInfo(id);
var idx = getCellIdx(id);

// New height of a row.
var newHeight;
// Smart page scrolling may be done after collapse.
var mayNeedScroll;

if (cellInfo.expanded) {
// Cell is expanded - collapse the row height to CLIP_HEIGHT.
newHeight = CLIP_HEIGHT;
mayNeedScroll = true;
}
else {
// Cell is collapsed - expand the row height to the cells original height.
newHeight = cellInfo.height;
mayNeedScroll = false;
}

// Update all cells (height and expanded/collapsed state) in a row according
// to the new height of the row.
for (var i = 0; i < CellsInfo[idx.group].length; i++) {
var idxStr = "_" + idx.group + "_" + i;
var expandableDiv = document.getElementById("cell" + idxStr);
expandableDiv.style.height = newHeight + "px";
var data = document.getElementById("data" + idxStr);
var expander = document.getElementById("expander" + idxStr);
var state = CellsInfo[idx.group][i];

if (state.height > newHeight) {
// Cell height exceeds row height - collapse a cell.
data.style.height = (newHeight - EXPANDER_HEIGHT) + "px";
expander.src = imgPath + "ellipses_light.gif";
CellsInfo[idx.group][i].expanded = false;
} else {
// Cell height is less then or equal to row height - expand a cell.
data.style.height = "";
expander.src = imgPath + "arrows_light.gif";
CellsInfo[idx.group][i].expanded = true;
}
}

if (mayNeedScroll) {
var idxStr = "_" + idx.group + "_" + idx.cell;
var clickedExpandableDiv = document.getElementById("cell" + idxStr);
// Scroll page up if a row is collapsed and the rows top is above the
// viewport. The amount of scroll is the difference between a new and old
// row height.
if (!isElemTopVisible(clickedExpandableDiv)) {
window.scrollBy(0, newHeight - cellInfo.height);
}
}
}