mirror of https://github.com/microsoft/clang.git
[analyzer] Alpha and implicit checker lists, expand/collapse feature.
The list of alpha and the list of implicit checkers added. An ability to expand/collapse long texts added. Markup fixed. http://reviews.llvm.org/D3457 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@209131 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
323f398054
commit
76790c5cf0
|
@ -0,0 +1,848 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Alpha Checks</title>
|
||||
<link type="text/css" rel="stylesheet" href="menu.css">
|
||||
<link type="text/css" rel="stylesheet" href="content.css">
|
||||
<script type="text/javascript" src="scripts/menu.js"></script>
|
||||
<script type="text/javascript" src="scripts/expandcollapse.js"></script>
|
||||
<style type="text/css">
|
||||
tr:first-child { width:20%; }
|
||||
</style>
|
||||
</head>
|
||||
<body onload="initExpandCollapse()">
|
||||
|
||||
<div id="page">
|
||||
<!--#include virtual="menu.html.incl"-->
|
||||
|
||||
<div id="content">
|
||||
<h1>Alpha Checkers</h1>
|
||||
Experimental checkers in addition to the <a href = "available_checks.html">
|
||||
Default Checkers</a>. These are checkers with known issues or limitations that
|
||||
keep them from being on by default. They are likely to have false positives.
|
||||
Bug reports are welcome but will likely not be investigated for some time.
|
||||
Patches welcome!
|
||||
<ul>
|
||||
<li><a href="#core_alpha_checkers">Core Alpha Checkers</a></li>
|
||||
<li><a href="#cplusplus_alpha_checkers">C++ Alpha Checkers</a></li>
|
||||
<li><a href="#deadcode_alpha_checkers">Dead Code Alpha Checkers</a></li>
|
||||
<li><a href="#osx_alpha_checkers">OS X Alpha Checkers</a></li>
|
||||
<li><a href="#security_alpha_checkers">Security Alpha Checkers</a></li>
|
||||
<li><a href="#unix_alpha_checkers">Unix Alpha Checkers</a></li>
|
||||
</ul>
|
||||
|
||||
<!------------------------------ core alpha ----------------------------------->
|
||||
<h3 id="core_alpha_checkers">Core Alpha Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.core.BoolAssignment</span><span class="lang">
|
||||
(ObjC)</span><div class="descr">
|
||||
Warn about assigning non-{0,1} values to boolean variables.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
BOOL b = -1; // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.core.CastSize</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check when casting a malloc'ed type T, whether the size is a multiple of the
|
||||
size of T (Works only with <span class="name">unix.Malloc</span>
|
||||
or <span class="name">alpha.unix.MallocWithAnnotations</span>
|
||||
checks enabled).</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
int *x = (int *)malloc(11); // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.core.CastToStruct</span><span class="lang">
|
||||
(C, C++)</span><div class="descr">
|
||||
Check for cast from non-struct pointer to struct pointer.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
// C
|
||||
struct s {};
|
||||
|
||||
void test(int *p) {
|
||||
struct s *ps = (struct s *) p; // warn
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
// C++
|
||||
class c {};
|
||||
|
||||
void test(int *p) {
|
||||
c *pc = (c *) p; // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.core.FixedAddr</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check for assignment of a fixed address to a pointer.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
int *p;
|
||||
p = (int *) 0x10000; // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.core.IdenticalExpr</span><span class="lang">
|
||||
(C, C++)</span><div class="descr">
|
||||
Warn about suspicious uses of identical expressions.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
// C
|
||||
void test() {
|
||||
int a = 5;
|
||||
int b = a | 4 | a; // warn: identical expr on both sides
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
// C++
|
||||
bool f(void);
|
||||
|
||||
void test(bool b) {
|
||||
int i = 10;
|
||||
if (f()) { // warn: true and false branches are identical
|
||||
do {
|
||||
i--;
|
||||
} while (f());
|
||||
} else {
|
||||
do {
|
||||
i--;
|
||||
} while (f());
|
||||
}
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.core.PointerArithm</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check for pointer arithmetic on locations other than array
|
||||
elements.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
int x;
|
||||
int *p;
|
||||
p = &x + 1; // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.core.PointerSub</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check for pointer subtractions on two pointers pointing to different memory
|
||||
chunks.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
int x, y;
|
||||
int d = &y - &x; // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.core.SizeofPtr</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Warn about unintended use of <code>sizeof()</code> on pointer
|
||||
expressions.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
struct s {};
|
||||
|
||||
int test(struct s *p) {
|
||||
return sizeof(p);
|
||||
// warn: sizeof(ptr) can produce an unexpected result
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
</tbody></table>
|
||||
|
||||
<!--------------------------- cplusplus alpha --------------------------------->
|
||||
<h3 id="cplusplus_alpha_checkers">C++ Alpha Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.cplusplus.NewDeleteLeaks</span><span class="lang">
|
||||
(C++)</span><div class="descr">
|
||||
Check for memory leaks. Traces memory managed by <code>new</code>/<code>
|
||||
delete</code>.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
int *p = new int;
|
||||
} // warn
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.cplusplus.VirtualCall</span><span class="lang">
|
||||
(C++)</span><div class="descr">
|
||||
Check virtual member function calls during construction or
|
||||
destruction.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
class A {
|
||||
public:
|
||||
A() {
|
||||
f(); // warn
|
||||
}
|
||||
virtual void f();
|
||||
};
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
class A {
|
||||
public:
|
||||
~A() {
|
||||
this->f(); // warn
|
||||
}
|
||||
virtual void f();
|
||||
};
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
</tbody></table>
|
||||
|
||||
<!--------------------------- dead code alpha --------------------------------->
|
||||
<h3 id="deadcode_alpha_checkers">Dead Code Alpha Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.deadcode.UnreachableCode</span><span class="lang">
|
||||
(C, C++, ObjC)</span><div class="descr">
|
||||
Check unreachable code.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
// C
|
||||
int test() {
|
||||
int x = 1;
|
||||
while(x);
|
||||
return x; // warn
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
// C++
|
||||
void test() {
|
||||
int a = 2;
|
||||
|
||||
while (a > 1)
|
||||
a--;
|
||||
|
||||
if (a > 1)
|
||||
a++; // warn
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
// Objective-C
|
||||
void test(id x) {
|
||||
return;
|
||||
[x retain]; // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
</tbody></table>
|
||||
|
||||
<!---------------------------- OS X alpha -------------------------------------->
|
||||
<h3 id="osx_alpha_checkers">OS X Alpha Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.osx.cocoa.Dealloc</span><span class="lang">
|
||||
(ObjC)</span><div class="descr">
|
||||
Warn about Objective-C classes that lack a correct implementation
|
||||
of <code>-dealloc</code>.
|
||||
</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
@interface MyObject : NSObject {
|
||||
id _myproperty;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MyObject // warn: lacks 'dealloc'
|
||||
@end
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
@interface MyObject : NSObject {}
|
||||
@property(assign) id myproperty;
|
||||
@end
|
||||
|
||||
@implementation MyObject // warn: does not send 'dealloc' to super
|
||||
- (void)dealloc {
|
||||
self.myproperty = 0;
|
||||
}
|
||||
@end
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
@interface MyObject : NSObject {
|
||||
id _myproperty;
|
||||
}
|
||||
@property(retain) id myproperty;
|
||||
@end
|
||||
|
||||
@implementation MyObject
|
||||
@synthesize myproperty = _myproperty;
|
||||
// warn: var was retained but wasn't released
|
||||
- (void)dealloc {
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
@interface MyObject : NSObject {
|
||||
id _myproperty;
|
||||
}
|
||||
@property(assign) id myproperty;
|
||||
@end
|
||||
|
||||
@implementation MyObject
|
||||
@synthesize myproperty = _myproperty;
|
||||
// warn: var wasn't retained but was released
|
||||
- (void)dealloc {
|
||||
[_myproperty release];
|
||||
[super dealloc];
|
||||
}
|
||||
@end
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.osx.cocoa.DirectIvarAssignment</span><span class="lang">
|
||||
(ObjC)</span><div class="descr">
|
||||
Check that Objective C properties follow the following rule: the property
|
||||
should be set with the setter, not though a direct assignment.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
@interface MyClass : NSObject {}
|
||||
@property (readonly) id A;
|
||||
- (void) foo;
|
||||
@end
|
||||
|
||||
@implementation MyClass
|
||||
- (void) foo {
|
||||
_A = 0; // warn
|
||||
}
|
||||
@end
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.osx.cocoa.DirectIvarAssignmentForAnnotatedFunctions</span><span class="lang">
|
||||
(ObjC)</span><div class="descr">
|
||||
Check for direct assignments to instance variables in the methods annotated
|
||||
with <code>objc_no_direct_instance_variable_assignment</code>.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
@interface MyClass : NSObject {}
|
||||
@property (readonly) id A;
|
||||
- (void) fAnnotated __attribute__((
|
||||
annotate("objc_no_direct_instance_variable_assignment")));
|
||||
- (void) fNotAnnotated;
|
||||
@end
|
||||
|
||||
@implementation MyClass
|
||||
- (void) fAnnotated {
|
||||
_A = 0; // warn
|
||||
}
|
||||
- (void) fNotAnnotated {
|
||||
_A = 0; // no warn
|
||||
}
|
||||
@end
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.osx.cocoa.InstanceVariableInvalidation</span><span class="lang">
|
||||
(ObjC)</span><div class="descr">
|
||||
Check that the invalidatable instance variables are invalidated in the methods
|
||||
annotated with <code>objc_instance_variable_invalidator</code>.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
@protocol Invalidation <NSObject>
|
||||
- (void) invalidate
|
||||
__attribute__((annotate("objc_instance_variable_invalidator")));
|
||||
@end
|
||||
|
||||
@interface InvalidationImpObj : NSObject <Invalidation>
|
||||
@end
|
||||
|
||||
@interface SubclassInvalidationImpObj : InvalidationImpObj {
|
||||
InvalidationImpObj *var;
|
||||
}
|
||||
- (void)invalidate;
|
||||
@end
|
||||
|
||||
@implementation SubclassInvalidationImpObj
|
||||
- (void) invalidate {}
|
||||
@end
|
||||
// warn: var needs to be invalidated or set to nil
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.osx.cocoa.MissingInvalidationMethod</span><span class="lang">
|
||||
(ObjC)</span><div class="descr">
|
||||
Check that the invalidation methods are present in classes that contain
|
||||
invalidatable instance variables.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
@protocol Invalidation <NSObject>
|
||||
- (void)invalidate
|
||||
__attribute__((annotate("objc_instance_variable_invalidator")));
|
||||
@end
|
||||
|
||||
@interface NeedInvalidation : NSObject <Invalidation>
|
||||
@end
|
||||
|
||||
@interface MissingInvalidationMethodDecl : NSObject {
|
||||
NeedInvalidation *Var; // warn
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MissingInvalidationMethodDecl
|
||||
@end
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
</tbody></table>
|
||||
|
||||
<!------------------------- security alpha ------------------------------------>
|
||||
<h3 id="security_alpha_checkers">Security Alpha Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.security.ArrayBound</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Warn about buffer overflows (older checker).</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
char *s = "";
|
||||
char c = s[1]; // warn
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
struct seven_words {
|
||||
int c[7];
|
||||
};
|
||||
|
||||
void test() {
|
||||
struct seven_words a, *p;
|
||||
p = &a;
|
||||
p[0] = a;
|
||||
p[1] = a;
|
||||
p[2] = a; // warn
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
// note: requires unix.Malloc or
|
||||
// alpha.unix.MallocWithAnnotations checks enabled.
|
||||
void test() {
|
||||
int *p = malloc(12);
|
||||
p[3] = 4; // warn
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
char a[2];
|
||||
int *b = (int*)a;
|
||||
b[1] = 3; // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.security.ArrayBoundV2</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Warn about buffer overflows (newer checker).</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
char *s = "";
|
||||
char c = s[1]; // warn
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
int buf[100];
|
||||
int *p = buf;
|
||||
p = p + 99;
|
||||
p[1] = 1; // warn
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
// note: compiler has internal check for this.
|
||||
// Use -Wno-array-bounds to suppress compiler warning.
|
||||
void test() {
|
||||
int buf[100][100];
|
||||
buf[0][-1] = 1; // warn
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
// note: requires alpha.security.taint check turned on.
|
||||
void test() {
|
||||
char s[] = "abc";
|
||||
int x = getchar();
|
||||
char c = s[x]; // warn: index is tainted
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.security.MallocOverflow</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check for overflows in the arguments to <code>malloc()</code>.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test(int n) {
|
||||
void *p = malloc(n * sizeof(int)); // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.security.ReturnPtrRange</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check for an out-of-bound pointer being returned to callers.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
static int A[10];
|
||||
|
||||
int *test() {
|
||||
int *p = A + 10;
|
||||
return p; // warn
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
int test(void) {
|
||||
int x;
|
||||
return x; // warn: undefined or garbage returned
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.security.taint.TaintPropagation</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Generate taint information used by other checkers.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
char x = getchar(); // 'x' marked as tainted
|
||||
system(&x); // warn: untrusted data is passed to a system call
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
// note: compiler internally checks if the second param to
|
||||
// sprintf is a string literal or not.
|
||||
// Use -Wno-format-security to suppress compiler warning.
|
||||
void test() {
|
||||
char s[10], buf[10];
|
||||
fscanf(stdin, "%s", s); // 's' marked as tainted
|
||||
|
||||
sprintf(buf, s); // warn: untrusted data as a format string
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
size_t ts;
|
||||
scanf("%zd", &ts); // 'ts' marked as tainted
|
||||
int *p = (int *)malloc(ts * sizeof(int));
|
||||
// warn: untrusted data as bufer size
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
</tbody></table>
|
||||
|
||||
<!--------------------------- unix alpha -------------------------------------->
|
||||
<h3 id="unix_alpha_checkers">Unix Alpha Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.unix.Chroot</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check improper use of <code>chroot</code>.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void f();
|
||||
|
||||
void test() {
|
||||
chroot("/usr/local");
|
||||
f(); // warn: no call of chdir("/") immediately after chroot
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.unix.MallocWithAnnotations</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check for memory leaks, double free, and use-after-free problems. Assumes that
|
||||
all user-defined functions which might free a pointer are
|
||||
annotated.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
|
||||
|
||||
void test() {
|
||||
int *p = my_malloc(1);
|
||||
} // warn: potential leak
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
|
||||
void __attribute((ownership_takes(malloc, 1))) my_free(void *);
|
||||
|
||||
void test() {
|
||||
int *p = my_malloc(1);
|
||||
my_free(p);
|
||||
my_free(p); // warn: attempt to free released
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void __attribute((ownership_returns(malloc))) *my_malloc(size_t);
|
||||
void __attribute((ownership_holds(malloc, 1))) my_hold(void *);
|
||||
|
||||
void test() {
|
||||
int *p = my_malloc(1);
|
||||
my_hold(p);
|
||||
free(p); // warn: attempt to free non-owned memory
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void __attribute((ownership_takes(malloc, 1))) my_free(void *);
|
||||
|
||||
void test() {
|
||||
int *p = malloc(1);
|
||||
my_free(p);
|
||||
*p = 1; // warn: use after free
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.unix.PthreadLock</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Simple lock -> unlock checker; applies to:<div class=functions>
|
||||
pthread_mutex_lock<br>
|
||||
pthread_rwlock_rdlock<br>
|
||||
pthread_rwlock_wrlock<br>
|
||||
lck_mtx_lock<br>
|
||||
lck_rw_lock_exclusive<br>
|
||||
lck_rw_lock_shared<br>
|
||||
pthread_mutex_trylock<br>
|
||||
pthread_rwlock_tryrdlock<br>
|
||||
pthread_rwlock_tryrwlock<br>
|
||||
lck_mtx_try_lock<br>
|
||||
lck_rw_try_lock_exclusive<br>
|
||||
lck_rw_try_lock_shared<br>
|
||||
pthread_mutex_unlock<br>
|
||||
pthread_rwlock_unlock<br>
|
||||
lck_mtx_unlock<br>
|
||||
lck_rw_done</div></div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
pthread_mutex_t mtx;
|
||||
|
||||
void test() {
|
||||
pthread_mutex_lock(&mtx);
|
||||
pthread_mutex_lock(&mtx);
|
||||
// warn: this lock has already been acquired
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
lck_mtx_t lck1, lck2;
|
||||
|
||||
void test() {
|
||||
lck_mtx_lock(&lck1);
|
||||
lck_mtx_lock(&lck2);
|
||||
lck_mtx_unlock(&lck1);
|
||||
// warn: this was not the most recently acquired lock
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
lck_mtx_t lck1, lck2;
|
||||
|
||||
void test() {
|
||||
if (lck_mtx_try_lock(&lck1) == 0)
|
||||
return;
|
||||
|
||||
lck_mtx_lock(&lck2);
|
||||
lck_mtx_unlock(&lck1);
|
||||
// warn: this was not the most recently acquired lock
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.unix.SimpleStream</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check for misuses of stream APIs:<div class=functions>
|
||||
fopen<br>
|
||||
fclose</div>(demo checker, the subject of the demo
|
||||
(<a href="http://llvm.org/devmtg/2012-11/Zaks-Rose-Checker24Hours.pdf">Slides</a>
|
||||
,<a href="http://llvm.org/devmtg/2012-11/videos/Zaks-Rose-Checker24Hours.mp4">Video</a>)
|
||||
by Anna Zaks and Jordan Rose presented at the <a href="http://llvm.org/devmtg/2012-11/">
|
||||
2012 LLVM Developers' Meeting).</a></div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
FILE *F = fopen("myfile.txt", "w");
|
||||
} // warn: opened file is never closed
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
FILE *F = fopen("myfile.txt", "w");
|
||||
|
||||
if (F)
|
||||
fclose(F);
|
||||
|
||||
fclose(F); // warn: closing a previously closed file stream
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.unix.Stream</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check stream handling functions:<div class=functions>fopen<br>
|
||||
tmpfile<br>
|
||||
fclose<br>
|
||||
fread<br>
|
||||
fwrite<br>
|
||||
fseek<br>
|
||||
ftell<br>
|
||||
rewind<br>
|
||||
fgetpos<br>
|
||||
fsetpos<br>
|
||||
clearerr<br>
|
||||
feof<br>
|
||||
ferror<br>
|
||||
fileno</div></div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
FILE *p = fopen("foo", "r");
|
||||
} // warn: opened file is never closed
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
FILE *p = fopen("foo", "r");
|
||||
fseek(p, 1, SEEK_SET); // warn: stream pointer might be NULL
|
||||
fclose(p);
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
FILE *p = fopen("foo", "r");
|
||||
|
||||
if (p)
|
||||
fseek(p, 1, 3);
|
||||
// warn: third arg should be SEEK_SET, SEEK_END, or SEEK_CUR
|
||||
|
||||
fclose(p);
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
FILE *p = fopen("foo", "r");
|
||||
fclose(p);
|
||||
fclose(p); // warn: already closed
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
FILE *p = tmpfile();
|
||||
ftell(p); // warn: stream pointer might be NULL
|
||||
fclose(p);
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.unix.cstring.BufferOverlap</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Checks for overlap in two buffer arguments; applies to:<div class=functions>
|
||||
memcpy<br>
|
||||
mempcpy</div></div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
int a[4] = {0};
|
||||
memcpy(a + 2, a + 1, 8); // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.unix.cstring.NotNullTerminated</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check for arguments which are not null-terminated strings; applies
|
||||
to:<div class=functions>
|
||||
strlen<br>
|
||||
strnlen<br>
|
||||
strcpy<br>
|
||||
strncpy<br>
|
||||
strcat<br>
|
||||
strncat</div></div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
int y = strlen((char *)&test); // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
alpha.unix.cstring.OutOfBounds</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Check for out-of-bounds access in string functions; applies
|
||||
to:<div class=functions>
|
||||
strncopy<br>
|
||||
strncat</div></div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test(char *y) {
|
||||
char x[4];
|
||||
if (strlen(y) == 4)
|
||||
strncpy(x, y, 5); // warn
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
</tbody></table>
|
||||
|
||||
</div> <!-- page -->
|
||||
</div> <!-- content -->
|
||||
</body>
|
||||
</html>
|
|
@ -47,15 +47,9 @@ Experimental (Alpha) Checkers</a>.
|
|||
<h3 id="core_checkers">Core Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
|
||||
<thead>
|
||||
<tr><td><div class="namedescr">Name, Description</div></td>
|
||||
<td><div class="example">Example</div></td></tr>
|
||||
</thead>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
core.CallAndMessage</span><span class="lang">
|
||||
(C, C++, ObjC)</span><div class="descr">
|
||||
|
@ -370,11 +364,7 @@ int test() {
|
|||
<h3 id="cplusplus_checkers">C++ Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
|
||||
<thead>
|
||||
<tr><td><div class="namedescr">Name, Description</div></td>
|
||||
<td><div class="example">Example</div></td></tr>
|
||||
</thead>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
|
@ -437,11 +427,7 @@ void test() {
|
|||
<h3 id="deadcode_checkers">Dead Code Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
|
||||
<thead>
|
||||
<tr><td><div class="namedescr">Name, Description</div></td>
|
||||
<td><div class="example">Example</div></td></tr>
|
||||
</thead>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
|
@ -462,11 +448,7 @@ void test() {
|
|||
<h3 id="osx_checkers">OS X Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
|
||||
<thead>
|
||||
<tr><td><div class="namedescr">Name, Description</div></td>
|
||||
<td><div class="example">Example</div></td></tr>
|
||||
</thead>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
|
@ -877,11 +859,7 @@ void test() {
|
|||
<h3 id="security_checkers">Security Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
|
||||
<thead>
|
||||
<tr><td><div class="namedescr">Name, Description</div></td>
|
||||
<td><div class="example">Example</div></td></tr>
|
||||
</thead>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
|
@ -1021,11 +999,7 @@ void test() {
|
|||
<h3 id="unix_checkers">Unix Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
|
||||
<thead>
|
||||
<tr><td><div class="namedescr">Name, Description</div></td>
|
||||
<td><div class="example">Example</div></td></tr>
|
||||
</thead>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
|
|
|
@ -47,6 +47,7 @@ for developer guidelines and send your questions and proposals to
|
|||
<li><a href="#testing">Testing</a></li>
|
||||
<li><a href="#commands">Useful Commands/Debugging Hints</a></li>
|
||||
<li><a href="#additioninformation">Additional Sources of Information</a></li>
|
||||
<li><a href="#links">Useful Links</a></li>
|
||||
</ul>
|
||||
|
||||
<h2 id=start>Getting Started</h2>
|
||||
|
@ -605,6 +606,11 @@ href="http://llvm.org/devmtg/2012-11/videos/Zaks-Rose-Checker24Hours.mp4">video<
|
|||
are available.
|
||||
</ul>
|
||||
|
||||
<h2 id=links>Useful Links</h2>
|
||||
<ul>
|
||||
<li>The list of <a href="implicit_checks.html">Implicit Checkers</a></li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -84,16 +84,17 @@ table.checkers td.aligned { text-align: center; vertical-align: middle; }
|
|||
table.checkers col.namedescr { width: 45% }
|
||||
table.checkers col.example { width: 55% }
|
||||
table.checkers col.progress { width: 84px }
|
||||
table.checkers thead div.example,
|
||||
table.checkers thead td,
|
||||
table.checkers div.namedescr,
|
||||
table.checkers div.exampleContainer { overflow: hidden; padding: 5px 8px 10px 8px }
|
||||
/* table.checkers tbody div.example { font-family: monospace; white-space: pre } */
|
||||
table.checkers div.example { border-top:1px #cccccc dashed; width:100%; padding-top: 5px; margin-top: 5px }
|
||||
table.checkers tbody div.example:first-child { border-top:none; padding-top: 0px; margin-top: 0px }
|
||||
table.checkers div.example:first-child { border-top:none; padding-top: 0px; margin-top: 0px }
|
||||
table.checkers span.name { font-weight: bold }
|
||||
table.checkers span.lang { font-weight: bold; padding-left: 7px; /* display:block; */ }
|
||||
table.checkers div.descr { margin-top:7px }
|
||||
table.checkers div.functions { margin-top: 2px; font-style: italic; font-size: 90%; color:#00B }
|
||||
table.checkers pre { margin: 1px; font-size: 100%; word-wrap: break-word }
|
||||
table.checkers p { margin: 10px 0px 0px 0px; }
|
||||
table.checkers ul, li { margin: 0 }
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
|
@ -0,0 +1,165 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
|
||||
"http://www.w3.org/TR/html4/strict.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Implicit Checks</title>
|
||||
<link type="text/css" rel="stylesheet" href="menu.css">
|
||||
<link type="text/css" rel="stylesheet" href="content.css">
|
||||
<script type="text/javascript" src="scripts/menu.js"></script>
|
||||
<script type="text/javascript" src="scripts/expandcollapse.js"></script>
|
||||
<style type="text/css">
|
||||
tr:first-child { width:20%; }
|
||||
</style>
|
||||
</head>
|
||||
<body onload="initExpandCollapse()">
|
||||
|
||||
<div id="page">
|
||||
<!--#include virtual="menu.html.incl"-->
|
||||
|
||||
<div id="content">
|
||||
<h1>Implicit Checkers</h1>
|
||||
Even though the implicit checkers do not produce any warnings, they are used to
|
||||
support the analyzer core and model known APIs. See also
|
||||
<a href = "available_checks.html">Default Checkers</a>
|
||||
and <a href = "alpha_checks.html">Experimental (Alpha) Checkers</a>.
|
||||
<ul>
|
||||
<li><a href="#core_implicit_checkers">Core Implicit Checkers</a></li>
|
||||
<li><a href="#osx_implicit_checkers">OS X Implicit Checkers</a></li>
|
||||
</ul>
|
||||
|
||||
<!------------------------------- core implicit ------------------------------->
|
||||
<h3 id="core_implicit_checkers">Core Implicit Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
core.DynamicTypePropagation</span><span class="lang">
|
||||
(C++, ObjC)</span><div class="descr">
|
||||
Generate dynamic type information.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
// C++
|
||||
class A {
|
||||
public:
|
||||
A(int x) {}
|
||||
virtual int foo();
|
||||
};
|
||||
|
||||
class B: public A {
|
||||
public:
|
||||
B()
|
||||
:A(foo())
|
||||
// DynamicTypeInfo for 'this' rigion will wrap type 'A'
|
||||
// unless the base constructor call expression is processed
|
||||
{}
|
||||
virtual int foo();
|
||||
};
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
// Objective-C
|
||||
@interface MyClass : NSObject {}
|
||||
@end
|
||||
|
||||
@implementation MyClass
|
||||
+ (void)foo {
|
||||
MyClass *x = [[self alloc] init];
|
||||
// DynamicTypeInfo from a cast: from 'id' to 'MyClass *'
|
||||
}
|
||||
@end
|
||||
|
||||
void test() {
|
||||
MyClass *x = [MyClass alloc];
|
||||
// DynamicTypeInfo from a call to alloc:
|
||||
// from 'id' to 'MyClass *'
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
core.builtin.BuiltinFunctions</span><span class="lang">
|
||||
(C)</span><div class="descr">
|
||||
Evaluate compiler builtin functions (e.g., <code>alloca()</code>)</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test(int x) {
|
||||
int *p = (int *)__builtin_alloca(8);
|
||||
// evaluates to AllocaRegion
|
||||
|
||||
if(__builtin_expect(x > 10, 0)) // evaluates to 'x > 10'
|
||||
x = 0;
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
core.builtin.NoReturnFunctions</span><span class="lang">
|
||||
(C, ObjC)</span><div class="descr">
|
||||
Evaluate "panic" functions that are known to not return to the caller.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
// C
|
||||
void test() {
|
||||
panic(); // generate sink
|
||||
}
|
||||
</pre></div><div class="separator"></div>
|
||||
<div class="example"><pre>
|
||||
// Objective-C
|
||||
@interface MyObj : NSObject {}
|
||||
- (void)foo;
|
||||
@end
|
||||
|
||||
@implementation MyObj
|
||||
- (void)foo {
|
||||
[[NSAssertionHandler currentHandler] handleFailureInMethod:_cmd
|
||||
object:self
|
||||
file:(@"somefile.m")
|
||||
lineNumber:1
|
||||
description:(@"some text")];
|
||||
// generate sink
|
||||
}
|
||||
@end
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
</tbody></table>
|
||||
|
||||
<!---------------------------- OS X implicit ---------------------------------->
|
||||
<h3 id="osx_implicit_checkers">OS X Implicit Checkers</h3>
|
||||
<table class="checkers">
|
||||
<colgroup><col class="namedescr"><col class="example"></colgroup>
|
||||
<thead><tr><td>Name, Description</td><td>Example</td></tr></thead>
|
||||
|
||||
<tbody>
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
osx.cocoa.Loops</span><span class="lang">
|
||||
(ObjC)</span><div class="descr">
|
||||
Improved modeling of loops using Cocoa collection types.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test() {
|
||||
id x;
|
||||
for (x in [NSArray testObject]) {
|
||||
// assume the value of 'x' is non-nil
|
||||
}
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
|
||||
<tr><td><div class="namedescr expandable"><span class="name">
|
||||
osx.cocoa.NonNilReturnValue</span><span class="lang">
|
||||
(ObjC)</span><div class="descr">
|
||||
Model the APIs that are guaranteed to return a non-nil value.</div></div></td>
|
||||
<td><div class="exampleContainer expandable">
|
||||
<div class="example"><pre>
|
||||
void test(NSArray *A) {
|
||||
id subscriptObj = A[1]; // assume the value is non-nil
|
||||
}
|
||||
</pre></div></div></td></tr>
|
||||
|
||||
</tbody></table>
|
||||
|
||||
</div> <!-- page -->
|
||||
</div> <!-- content -->
|
||||
</body>
|
||||
</html>
|
|
@ -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">
|
||||
|
||||
|
@ -470,11 +471,22 @@ int i = *p; // warn
|
|||
<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>
|
||||
|
@ -482,106 +494,90 @@ lifetime has ended can result in undefined behavior.
|
|||
|
||||
class A {
|
||||
public:
|
||||
int i;
|
||||
};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
int test() {
|
||||
B *b = new B;
|
||||
new(b) A;
|
||||
return b->i; // warn
|
||||
}
|
||||
</pre></div>
|
||||
<div class="example"><pre>
|
||||
#include <new>
|
||||
|
||||
class A {
|
||||
public:
|
||||
void f() {};
|
||||
~A();
|
||||
};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
void test() {
|
||||
B *b = new B;
|
||||
new(b) A;
|
||||
b->f(); // warn
|
||||
}
|
||||
</pre></div>
|
||||
<div class="example"><pre>
|
||||
#include <new>
|
||||
|
||||
class A {};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
A* test() {
|
||||
B *b = new B;
|
||||
new(b) A;
|
||||
static_cast<A*>(b); // warn
|
||||
}
|
||||
</pre></div>
|
||||
<div class="example"><pre>
|
||||
#include <new>
|
||||
|
||||
class A {};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
A* test() {
|
||||
B *b = new B;
|
||||
new(b) A;
|
||||
dynamic_cast<A*>(b); // warn
|
||||
}
|
||||
</pre></div>
|
||||
<div class="example"><pre>
|
||||
#include <new>
|
||||
|
||||
class A {};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
A* test() {
|
||||
B *b = new B;
|
||||
new(b) A;
|
||||
dynamic_cast<A*>(b); // warn
|
||||
}
|
||||
</pre></div>
|
||||
<div class="example"><pre>
|
||||
#include <new>
|
||||
|
||||
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 <new>
|
||||
|
||||
class A {
|
||||
public:
|
||||
int i;
|
||||
};
|
||||
|
||||
class B : public A {
|
||||
public:
|
||||
~B() {};
|
||||
};
|
||||
|
||||
int test() {
|
||||
A *a = new A;
|
||||
new(a) B;
|
||||
return a->i; // warn
|
||||
delete a; // warn
|
||||
}
|
||||
</pre></div>
|
||||
<div class="example"><pre>
|
||||
#include <new>
|
||||
|
||||
class A {
|
||||
public:
|
||||
~A();
|
||||
};
|
||||
|
||||
class B {};
|
||||
|
||||
void test() {
|
||||
A *a = new A;
|
||||
new(a) B;
|
||||
a->~A();
|
||||
}
|
||||
</pre></div>
|
||||
<div class="example"><pre>
|
||||
#include <new>
|
||||
|
||||
class A {
|
||||
public:
|
||||
~A();
|
||||
};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
class C {};
|
||||
|
||||
void f(A*);
|
||||
|
||||
void test() {
|
||||
B *b = new B;
|
||||
new(b) C;
|
||||
f(b); // warn
|
||||
}
|
||||
</pre></div>
|
||||
<div class="example"><pre>
|
||||
#include <new>
|
||||
|
||||
class A {
|
||||
public:
|
||||
~A();
|
||||
};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
class C {};
|
||||
|
||||
A* test() {
|
||||
B *b = new B;
|
||||
new(b) C;
|
||||
return static_cast<A*>(b); // warn
|
||||
}
|
||||
</pre></div>
|
||||
<div class="example"><pre>
|
||||
#include <new>
|
||||
|
||||
class A {
|
||||
public:
|
||||
~A();
|
||||
};
|
||||
|
||||
class B : public A {};
|
||||
|
||||
class C {};
|
||||
|
||||
A* test() {
|
||||
B *b = new B;
|
||||
new(b) C;
|
||||
return dynamic_cast<A*>(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">
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue