220 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			220 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			C++
		
	
	
	
// 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-store=region -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
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// 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;
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// 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;
 | 
						|
}
 | 
						|
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
// 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;
 | 
						|
}
 | 
						|
 |