// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 \
// RUN: -analyzer-checker=deadcode.DeadStores -Wno-unreachable-code \
// RUN: -analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false\
// RUN: -verify=non-nested %s
//
// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 \
// RUN: -analyzer-checker=deadcode.DeadStores \
// RUN: -analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false\
// RUN: -Wno-unreachable-code -verify=non-nested %s
//
// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11 \
// RUN: -analyzer-checker=deadcode.DeadStores -Wno-unreachable-code \
// RUN: -verify=non-nested,nested %s
//
// RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++17 \
// RUN: -analyzer-checker=deadcode.DeadStores -Wno-unreachable-code \
// RUN: -verify=non-nested,nested %s
//===----------------------------------------------------------------------===//
// Basic dead store checking (but in C++ mode).
//===----------------------------------------------------------------------===//
int j;
int make_int();
void test1() {
int x = 4;
x = x + 1; // non-nested-warning {{never read}}
switch (j) {
case 1:
throw 1;
(void)x;
break;
}
int y;
(void)y;
if ((y = make_int())) // nested-warning {{Although the value stored}}
return;
auto z = "text"; // non-nested-warning {{never read}}
}
//===----------------------------------------------------------------------===//
// Dead store checking involving constructors.
//===----------------------------------------------------------------------===//
class Test2 {
int &x;
public:
Test2(int &y) : x(y) {}
~Test2() { ++x; }
};
int test2(int x) {
{ Test2 a(x); } // no-warning
return x;
}
class TestConstructor {
public:
TestConstructor(int &y);
};
void copy(int x) {
// All these calls might have side effects in the opaque constructor
TestConstructor tc1 = x; // no-warning potential side effects
TestConstructor tc2 = TestConstructor(x); // no-warning potential side effects
TestConstructor tc3 = (TestConstructor(x)); // no-warning potential side effects
TestConstructor tc4 = (TestConstructor)(x); // no-warning potential side effects
}
//===----------------------------------------------------------------------===//
// 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
}
//===----------------------------------------------------------------------===//
// Test references.
//===----------------------------------------------------------------------===//
void test3_a(int x) {
x = x + 1; // non-nested-warning {{never read}}
}
void test3_b(int &x) {
x = x + 1; // no-warning
}
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;
}
//===----------------------------------------------------------------------===//
// Dead stores involving 'new'
//===----------------------------------------------------------------------===//
static void test_new(unsigned n) {
char **p = new char *[n]; // non-nested-warning {{never read}}
}
//===----------------------------------------------------------------------===//
// Dead stores in namespaces.
//===----------------------------------------------------------------------===//
namespace foo {
int test_4(int x) {
x = 2; // non-nested-warning {{Value stored to 'x' is never read}}
x = 2;
return x;
}
}
//===----------------------------------------------------------------------===//
// 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;
}
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;
// non-nested-warning@-1 {{Value stored to 'currDestLen' is never read}}
break;
}
} catch (void *) {
}
}
void testCXX11Using() {
using Int = int;
Int value;
value = 1; // non-nested-warning {{never read}}
}
//===----------------------------------------------------------------------===//
// 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);
}
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];
// non-nested-warning@-1 {{Value stored to 'i' during its initialization is never read}}
}();
}
//===----------------------------------------------------------------------===//
// 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;
}