2017-03-04 02:02:02 +08:00
|
|
|
// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 -analyzer-checker=deadcode.DeadStores -verify -Wno-unreachable-code %s
|
|
|
|
// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 -analyzer-store=region -analyzer-checker=deadcode.DeadStores -verify -Wno-unreachable-code %s
|
2009-07-23 06:56:04 +08:00
|
|
|
|
2009-12-15 12:12:12 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Basic dead store checking (but in C++ mode).
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-07-23 06:56:04 +08:00
|
|
|
int j;
|
Add (initial?) static analyzer support for handling C++ references.
This change was a lot bigger than I originally anticipated; among
other things it requires us storing more information in the CFG to
record what block-level expressions need to be evaluated as lvalues.
The big change is that CFGBlocks no longer contain Stmt*'s by
CFGElements. Currently CFGElements just wrap Stmt*, but they also
store a bit indicating whether the block-level expression should be
evalauted as an lvalue. DeclStmts involving the initialization of a
reference require us treating the initialization expression as an
lvalue, even though that information isn't recorded in the AST.
Conceptually this change isn't that complicated, but it required
bubbling up the data through the CFGBuilder, to GRCoreEngine, and
eventually to GRExprEngine.
The addition of CFGElement is also useful for when we want to handle
more control-flow constructs or other data we want to keep in the CFG
that isn't represented well with just a block of statements.
In GRExprEngine, this patch introduces logic for evaluating the
lvalues of references, which currently retrieves the internal "pointer
value" that the reference represents. EvalLoad does a two stage load
to catch null dereferences involving an invalid reference (although
this could possibly be caught earlier during the initialization of a
reference).
Symbols are currently symbolicated using the reference type, instead
of a pointer type, and special handling is required creating
ElementRegions that layer on SymbolicRegions (see the changes to
RegionStoreManager).
Along the way, the DeadStoresChecker also silences warnings involving
dead stores to references. This was the original change I introduced
(which I wrote test cases for) that I realized caused GRExprEngine to
crash.
llvm-svn: 91501
2009-12-16 11:18:58 +08:00
|
|
|
void test1() {
|
2009-07-23 06:56:04 +08:00
|
|
|
int x = 4;
|
|
|
|
|
2011-02-12 08:17:19 +08:00
|
|
|
x = x + 1; // expected-warning{{never read}}
|
2009-07-23 06:56:04 +08:00
|
|
|
|
|
|
|
switch (j) {
|
|
|
|
case 1:
|
|
|
|
throw 1;
|
|
|
|
(void)x;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-12-15 12:12:12 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Dead store checking involving constructors.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
Add (initial?) static analyzer support for handling C++ references.
This change was a lot bigger than I originally anticipated; among
other things it requires us storing more information in the CFG to
record what block-level expressions need to be evaluated as lvalues.
The big change is that CFGBlocks no longer contain Stmt*'s by
CFGElements. Currently CFGElements just wrap Stmt*, but they also
store a bit indicating whether the block-level expression should be
evalauted as an lvalue. DeclStmts involving the initialization of a
reference require us treating the initialization expression as an
lvalue, even though that information isn't recorded in the AST.
Conceptually this change isn't that complicated, but it required
bubbling up the data through the CFGBuilder, to GRCoreEngine, and
eventually to GRExprEngine.
The addition of CFGElement is also useful for when we want to handle
more control-flow constructs or other data we want to keep in the CFG
that isn't represented well with just a block of statements.
In GRExprEngine, this patch introduces logic for evaluating the
lvalues of references, which currently retrieves the internal "pointer
value" that the reference represents. EvalLoad does a two stage load
to catch null dereferences involving an invalid reference (although
this could possibly be caught earlier during the initialization of a
reference).
Symbols are currently symbolicated using the reference type, instead
of a pointer type, and special handling is required creating
ElementRegions that layer on SymbolicRegions (see the changes to
RegionStoreManager).
Along the way, the DeadStoresChecker also silences warnings involving
dead stores to references. This was the original change I introduced
(which I wrote test cases for) that I realized caused GRExprEngine to
crash.
llvm-svn: 91501
2009-12-16 11:18:58 +08:00
|
|
|
class Test2 {
|
2009-12-15 12:12:12 +08:00
|
|
|
int &x;
|
|
|
|
public:
|
Add (initial?) static analyzer support for handling C++ references.
This change was a lot bigger than I originally anticipated; among
other things it requires us storing more information in the CFG to
record what block-level expressions need to be evaluated as lvalues.
The big change is that CFGBlocks no longer contain Stmt*'s by
CFGElements. Currently CFGElements just wrap Stmt*, but they also
store a bit indicating whether the block-level expression should be
evalauted as an lvalue. DeclStmts involving the initialization of a
reference require us treating the initialization expression as an
lvalue, even though that information isn't recorded in the AST.
Conceptually this change isn't that complicated, but it required
bubbling up the data through the CFGBuilder, to GRCoreEngine, and
eventually to GRExprEngine.
The addition of CFGElement is also useful for when we want to handle
more control-flow constructs or other data we want to keep in the CFG
that isn't represented well with just a block of statements.
In GRExprEngine, this patch introduces logic for evaluating the
lvalues of references, which currently retrieves the internal "pointer
value" that the reference represents. EvalLoad does a two stage load
to catch null dereferences involving an invalid reference (although
this could possibly be caught earlier during the initialization of a
reference).
Symbols are currently symbolicated using the reference type, instead
of a pointer type, and special handling is required creating
ElementRegions that layer on SymbolicRegions (see the changes to
RegionStoreManager).
Along the way, the DeadStoresChecker also silences warnings involving
dead stores to references. This was the original change I introduced
(which I wrote test cases for) that I realized caused GRExprEngine to
crash.
llvm-svn: 91501
2009-12-16 11:18:58 +08:00
|
|
|
Test2(int &y) : x(y) {}
|
|
|
|
~Test2() { ++x; }
|
2009-12-15 12:12:12 +08:00
|
|
|
};
|
|
|
|
|
Add (initial?) static analyzer support for handling C++ references.
This change was a lot bigger than I originally anticipated; among
other things it requires us storing more information in the CFG to
record what block-level expressions need to be evaluated as lvalues.
The big change is that CFGBlocks no longer contain Stmt*'s by
CFGElements. Currently CFGElements just wrap Stmt*, but they also
store a bit indicating whether the block-level expression should be
evalauted as an lvalue. DeclStmts involving the initialization of a
reference require us treating the initialization expression as an
lvalue, even though that information isn't recorded in the AST.
Conceptually this change isn't that complicated, but it required
bubbling up the data through the CFGBuilder, to GRCoreEngine, and
eventually to GRExprEngine.
The addition of CFGElement is also useful for when we want to handle
more control-flow constructs or other data we want to keep in the CFG
that isn't represented well with just a block of statements.
In GRExprEngine, this patch introduces logic for evaluating the
lvalues of references, which currently retrieves the internal "pointer
value" that the reference represents. EvalLoad does a two stage load
to catch null dereferences involving an invalid reference (although
this could possibly be caught earlier during the initialization of a
reference).
Symbols are currently symbolicated using the reference type, instead
of a pointer type, and special handling is required creating
ElementRegions that layer on SymbolicRegions (see the changes to
RegionStoreManager).
Along the way, the DeadStoresChecker also silences warnings involving
dead stores to references. This was the original change I introduced
(which I wrote test cases for) that I realized caused GRExprEngine to
crash.
llvm-svn: 91501
2009-12-16 11:18:58 +08:00
|
|
|
int test2(int x) {
|
|
|
|
{ Test2 a(x); } // no-warning
|
2009-12-15 12:12:12 +08:00
|
|
|
return x;
|
|
|
|
}
|
Add (initial?) static analyzer support for handling C++ references.
This change was a lot bigger than I originally anticipated; among
other things it requires us storing more information in the CFG to
record what block-level expressions need to be evaluated as lvalues.
The big change is that CFGBlocks no longer contain Stmt*'s by
CFGElements. Currently CFGElements just wrap Stmt*, but they also
store a bit indicating whether the block-level expression should be
evalauted as an lvalue. DeclStmts involving the initialization of a
reference require us treating the initialization expression as an
lvalue, even though that information isn't recorded in the AST.
Conceptually this change isn't that complicated, but it required
bubbling up the data through the CFGBuilder, to GRCoreEngine, and
eventually to GRExprEngine.
The addition of CFGElement is also useful for when we want to handle
more control-flow constructs or other data we want to keep in the CFG
that isn't represented well with just a block of statements.
In GRExprEngine, this patch introduces logic for evaluating the
lvalues of references, which currently retrieves the internal "pointer
value" that the reference represents. EvalLoad does a two stage load
to catch null dereferences involving an invalid reference (although
this could possibly be caught earlier during the initialization of a
reference).
Symbols are currently symbolicated using the reference type, instead
of a pointer type, and special handling is required creating
ElementRegions that layer on SymbolicRegions (see the changes to
RegionStoreManager).
Along the way, the DeadStoresChecker also silences warnings involving
dead stores to references. This was the original change I introduced
(which I wrote test cases for) that I realized caused GRExprEngine to
crash.
llvm-svn: 91501
2009-12-16 11:18:58 +08:00
|
|
|
|
2009-12-23 12:11:44 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Dead store checking involving CXXTemporaryExprs
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace TestTemp {
|
|
|
|
template<typename _Tp>
|
|
|
|
class pencil {
|
|
|
|
public:
|
|
|
|
~pencil() throw() {}
|
|
|
|
};
|
|
|
|
template<typename _Tp, typename _Number2> struct _Row_base {
|
|
|
|
_Row_base(const pencil<_Tp>& x) {}
|
|
|
|
};
|
|
|
|
template<typename _Tp, typename _Number2 = TestTemp::pencil<_Tp> >
|
|
|
|
class row : protected _Row_base<_Tp, _Number2> {
|
|
|
|
typedef _Row_base<_Tp, _Number2> _Base;
|
|
|
|
typedef _Number2 pencil_type;
|
|
|
|
public:
|
|
|
|
explicit row(const pencil_type& __a = pencil_type()) : _Base(__a) {}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
void test2_b() {
|
|
|
|
TestTemp::row<const char*> x; // no-warning
|
|
|
|
}
|
|
|
|
|
Add (initial?) static analyzer support for handling C++ references.
This change was a lot bigger than I originally anticipated; among
other things it requires us storing more information in the CFG to
record what block-level expressions need to be evaluated as lvalues.
The big change is that CFGBlocks no longer contain Stmt*'s by
CFGElements. Currently CFGElements just wrap Stmt*, but they also
store a bit indicating whether the block-level expression should be
evalauted as an lvalue. DeclStmts involving the initialization of a
reference require us treating the initialization expression as an
lvalue, even though that information isn't recorded in the AST.
Conceptually this change isn't that complicated, but it required
bubbling up the data through the CFGBuilder, to GRCoreEngine, and
eventually to GRExprEngine.
The addition of CFGElement is also useful for when we want to handle
more control-flow constructs or other data we want to keep in the CFG
that isn't represented well with just a block of statements.
In GRExprEngine, this patch introduces logic for evaluating the
lvalues of references, which currently retrieves the internal "pointer
value" that the reference represents. EvalLoad does a two stage load
to catch null dereferences involving an invalid reference (although
this could possibly be caught earlier during the initialization of a
reference).
Symbols are currently symbolicated using the reference type, instead
of a pointer type, and special handling is required creating
ElementRegions that layer on SymbolicRegions (see the changes to
RegionStoreManager).
Along the way, the DeadStoresChecker also silences warnings involving
dead stores to references. This was the original change I introduced
(which I wrote test cases for) that I realized caused GRExprEngine to
crash.
llvm-svn: 91501
2009-12-16 11:18:58 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Test references.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void test3_a(int x) {
|
2011-02-12 08:17:19 +08:00
|
|
|
x = x + 1; // expected-warning{{never read}}
|
Add (initial?) static analyzer support for handling C++ references.
This change was a lot bigger than I originally anticipated; among
other things it requires us storing more information in the CFG to
record what block-level expressions need to be evaluated as lvalues.
The big change is that CFGBlocks no longer contain Stmt*'s by
CFGElements. Currently CFGElements just wrap Stmt*, but they also
store a bit indicating whether the block-level expression should be
evalauted as an lvalue. DeclStmts involving the initialization of a
reference require us treating the initialization expression as an
lvalue, even though that information isn't recorded in the AST.
Conceptually this change isn't that complicated, but it required
bubbling up the data through the CFGBuilder, to GRCoreEngine, and
eventually to GRExprEngine.
The addition of CFGElement is also useful for when we want to handle
more control-flow constructs or other data we want to keep in the CFG
that isn't represented well with just a block of statements.
In GRExprEngine, this patch introduces logic for evaluating the
lvalues of references, which currently retrieves the internal "pointer
value" that the reference represents. EvalLoad does a two stage load
to catch null dereferences involving an invalid reference (although
this could possibly be caught earlier during the initialization of a
reference).
Symbols are currently symbolicated using the reference type, instead
of a pointer type, and special handling is required creating
ElementRegions that layer on SymbolicRegions (see the changes to
RegionStoreManager).
Along the way, the DeadStoresChecker also silences warnings involving
dead stores to references. This was the original change I introduced
(which I wrote test cases for) that I realized caused GRExprEngine to
crash.
llvm-svn: 91501
2009-12-16 11:18:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void test3_b(int &x) {
|
2011-02-12 08:17:19 +08:00
|
|
|
x = x + 1; // no-warninge
|
Add (initial?) static analyzer support for handling C++ references.
This change was a lot bigger than I originally anticipated; among
other things it requires us storing more information in the CFG to
record what block-level expressions need to be evaluated as lvalues.
The big change is that CFGBlocks no longer contain Stmt*'s by
CFGElements. Currently CFGElements just wrap Stmt*, but they also
store a bit indicating whether the block-level expression should be
evalauted as an lvalue. DeclStmts involving the initialization of a
reference require us treating the initialization expression as an
lvalue, even though that information isn't recorded in the AST.
Conceptually this change isn't that complicated, but it required
bubbling up the data through the CFGBuilder, to GRCoreEngine, and
eventually to GRExprEngine.
The addition of CFGElement is also useful for when we want to handle
more control-flow constructs or other data we want to keep in the CFG
that isn't represented well with just a block of statements.
In GRExprEngine, this patch introduces logic for evaluating the
lvalues of references, which currently retrieves the internal "pointer
value" that the reference represents. EvalLoad does a two stage load
to catch null dereferences involving an invalid reference (although
this could possibly be caught earlier during the initialization of a
reference).
Symbols are currently symbolicated using the reference type, instead
of a pointer type, and special handling is required creating
ElementRegions that layer on SymbolicRegions (see the changes to
RegionStoreManager).
Along the way, the DeadStoresChecker also silences warnings involving
dead stores to references. This was the original change I introduced
(which I wrote test cases for) that I realized caused GRExprEngine to
crash.
llvm-svn: 91501
2009-12-16 11:18:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void test3_c(int x) {
|
|
|
|
int &y = x;
|
|
|
|
// Shows the limitation of dead stores tracking. The write is really
|
|
|
|
// dead since the value cannot escape the function.
|
|
|
|
++y; // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void test3_d(int &x) {
|
|
|
|
int &y = x;
|
|
|
|
++y; // no-warning
|
|
|
|
}
|
|
|
|
|
|
|
|
void test3_e(int &x) {
|
|
|
|
int &y = x;
|
|
|
|
}
|
|
|
|
|
2010-06-26 06:48:52 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Dead stores involving 'new'
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
static void test_new(unsigned n) {
|
|
|
|
char **p = new char* [n]; // expected-warning{{never read}}
|
|
|
|
}
|
|
|
|
|
2011-01-21 01:09:48 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Dead stores in namespaces.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
namespace foo {
|
|
|
|
int test_4(int x) {
|
|
|
|
x = 2; // expected-warning{{Value stored to 'x' is never read}}
|
|
|
|
x = 2;
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-07 06:32:48 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Dead stores in with EH code.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void test_5_Aux();
|
|
|
|
int test_5() {
|
|
|
|
int x = 0;
|
|
|
|
try {
|
|
|
|
x = 2; // no-warning
|
|
|
|
test_5_Aux();
|
|
|
|
}
|
|
|
|
catch (int z) {
|
|
|
|
return x + z;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2012-11-13 08:12:13 +08:00
|
|
|
|
|
|
|
int test_6_aux(unsigned x);
|
|
|
|
|
|
|
|
void test_6() {
|
|
|
|
unsigned currDestLen = 0; // no-warning
|
|
|
|
try {
|
|
|
|
while (test_6_aux(currDestLen)) {
|
|
|
|
currDestLen += 2; // no-warning
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (void *) {}
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_6b() {
|
|
|
|
unsigned currDestLen = 0; // no-warning
|
|
|
|
try {
|
|
|
|
while (test_6_aux(currDestLen)) {
|
|
|
|
currDestLen += 2; // expected-warning {{Value stored to 'currDestLen' is never read}}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch (void *) {}
|
|
|
|
}
|
2013-02-16 09:33:16 +08:00
|
|
|
|
|
|
|
|
|
|
|
void testCXX11Using() {
|
|
|
|
using Int = int;
|
|
|
|
Int value;
|
|
|
|
value = 1; // expected-warning {{never read}}
|
|
|
|
}
|
2013-02-18 15:18:28 +08:00
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Dead stores in template instantiations (do not warn).
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
template <bool f> int radar13213575_testit(int i) {
|
|
|
|
int x = 5+i; // warning: Value stored to 'x' during its initialization is never read
|
|
|
|
int y = 7;
|
|
|
|
if (f)
|
|
|
|
return x;
|
|
|
|
else
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
int radar_13213575() {
|
|
|
|
return radar13213575_testit<true>(5) + radar13213575_testit<false>(3);
|
|
|
|
}
|
|
|
|
|
2015-11-19 06:46:52 +08:00
|
|
|
template <class T>
|
|
|
|
void test_block_in_dependent_context(typename T::some_t someArray) {
|
|
|
|
^{
|
|
|
|
int i = someArray[0]; // no-warning
|
|
|
|
}();
|
|
|
|
}
|
|
|
|
|
|
|
|
void test_block_in_non_dependent_context(int *someArray) {
|
|
|
|
^{
|
|
|
|
int i = someArray[0]; // expected-warning {{Value stored to 'i' during its initialization is never read}}
|
|
|
|
}();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-12 00:55:01 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Dead store checking involving lambdas.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
int basicLambda(int i, int j) {
|
|
|
|
i = 5; // no warning
|
|
|
|
j = 6; // no warning
|
|
|
|
[i] { (void)i; }();
|
|
|
|
[&j] { (void)j; }();
|
|
|
|
i = 2;
|
|
|
|
j = 3;
|
|
|
|
return i + j;
|
|
|
|
}
|
|
|
|
|