xref: /llvm-project/clang/test/Analysis/dead-stores.cpp (revision 16cb3be62600621361644ebd15d071c711d6aa86)
1 // RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11    \
2 // RUN:  -analyzer-checker=deadcode.DeadStores -Wno-unreachable-code            \
3 // RUN:  -analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false\
4 // RUN:  -verify=non-nested %s
5 //
6 // RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11    \
7 // RUN:  -analyzer-checker=deadcode.DeadStores           \
8 // RUN:  -analyzer-config deadcode.DeadStores:WarnForDeadNestedAssignments=false\
9 // RUN:  -Wno-unreachable-code -verify=non-nested %s
10 //
11 // RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++11    \
12 // RUN:  -analyzer-checker=deadcode.DeadStores -Wno-unreachable-code            \
13 // RUN:  -verify=non-nested,nested %s
14 //
15 // RUN: %clang_analyze_cc1 -fcxx-exceptions -fexceptions -fblocks -std=c++17    \
16 // RUN:  -analyzer-checker=deadcode.DeadStores -Wno-unreachable-code            \
17 // RUN:  -verify=non-nested,nested %s
18 
19 //===----------------------------------------------------------------------===//
20 // Basic dead store checking (but in C++ mode).
21 //===----------------------------------------------------------------------===//
22 
23 int j;
24 int make_int();
test1()25 void test1() {
26   int x = 4;
27   x = x + 1; // non-nested-warning {{never read}}
28 
29   switch (j) {
30   case 1:
31     throw 1;
32     (void)x;
33     break;
34   }
35 
36   int y;
37   (void)y;
38   if ((y = make_int())) // nested-warning {{Although the value stored}}
39     return;
40 
41   auto z = "text"; // non-nested-warning {{never read}}
42 }
43 
44 //===----------------------------------------------------------------------===//
45 // Dead store checking involving constructors.
46 //===----------------------------------------------------------------------===//
47 
48 class Test2 {
49   int &x;
50 
51 public:
Test2(int & y)52   Test2(int &y) : x(y) {}
~Test2()53   ~Test2() { ++x; }
54 };
55 
test2(int x)56 int test2(int x) {
57   { Test2 a(x); } // no-warning
58   return x;
59 }
60 
61 class TestConstructor {
62 public:
63   TestConstructor(int &y);
64 };
copy(int x)65 void copy(int x) {
66   // All these calls might have side effects in the opaque constructor
67   TestConstructor tc1 = x;                    // no-warning potential side effects
68   TestConstructor tc2 = TestConstructor(x);   // no-warning potential side effects
69   TestConstructor tc3 = (TestConstructor(x)); // no-warning potential side effects
70   TestConstructor tc4 = (TestConstructor)(x); // no-warning potential side effects
71 }
72 
73 //===----------------------------------------------------------------------===//
74 // Dead store checking involving CXXTemporaryExprs
75 //===----------------------------------------------------------------------===//
76 
77 namespace TestTemp {
78   template<typename _Tp>
79   class pencil {
80   public:
~pencil()81     ~pencil() throw() {}
82   };
83   template<typename _Tp, typename _Number2> struct _Row_base {
_Row_baseTestTemp::_Row_base84     _Row_base(const pencil<_Tp>& x) {}
85   };
86   template<typename _Tp, typename _Number2 = TestTemp::pencil<_Tp> >
87   class row : protected _Row_base<_Tp, _Number2>     {
88     typedef _Row_base<_Tp, _Number2> _Base;
89     typedef _Number2 pencil_type;
90   public:
row(const pencil_type & __a=pencil_type ())91     explicit row(const pencil_type& __a = pencil_type()) : _Base(__a) {}
92   };
93 }
94 
test2_b()95 void test2_b() {
96   TestTemp::row<const char*> x; // no-warning
97 }
98 
99 //===----------------------------------------------------------------------===//
100 // Test references.
101 //===----------------------------------------------------------------------===//
102 
test3_a(int x)103 void test3_a(int x) {
104   x = x + 1; // non-nested-warning {{never read}}
105 }
106 
test3_b(int & x)107 void test3_b(int &x) {
108   x = x + 1; // no-warning
109 }
110 
test3_c(int x)111 void test3_c(int x) {
112   int &y = x;
113   // Shows the limitation of dead stores tracking. The write is really dead
114   // since the value cannot escape the function.
115   ++y; // no-warning
116 }
117 
test3_d(int & x)118 void test3_d(int &x) {
119   int &y = x;
120   ++y; // no-warning
121 }
122 
test3_e(int & x)123 void test3_e(int &x) {
124   int &y = x;
125 }
126 
127 //===----------------------------------------------------------------------===//
128 // Dead stores involving 'new'
129 //===----------------------------------------------------------------------===//
130 
test_new(unsigned n)131 static void test_new(unsigned n) {
132   char **p = new char *[n]; // non-nested-warning {{never read}}
133 }
134 
135 //===----------------------------------------------------------------------===//
136 // Dead stores in namespaces.
137 //===----------------------------------------------------------------------===//
138 
139 namespace foo {
test_4(int x)140 int test_4(int x) {
141   x = 2; // non-nested-warning {{Value stored to 'x' is never read}}
142   x = 2;
143   return x;
144 }
145 }
146 
147 //===----------------------------------------------------------------------===//
148 // Dead stores in with EH code.
149 //===----------------------------------------------------------------------===//
150 
151 void test_5_Aux();
test_5()152 int test_5() {
153   int x = 0;
154   try {
155     x = 2; // no-warning
156     test_5_Aux();
157   } catch (int z) {
158     return x + z;
159   }
160   return 1;
161 }
162 
163 int test_6_aux(unsigned x);
test_6()164 void test_6() {
165   unsigned currDestLen = 0; // no-warning
166   try {
167     while (test_6_aux(currDestLen)) {
168       currDestLen += 2; // no-warning
169     }
170   } catch (void *) {
171   }
172 }
173 
test_6b()174 void test_6b() {
175   unsigned currDestLen = 0; // no-warning
176   try {
177     while (test_6_aux(currDestLen)) {
178       currDestLen += 2;
179       // non-nested-warning@-1 {{Value stored to 'currDestLen' is never read}}
180       break;
181     }
182   } catch (void *) {
183   }
184 }
185 
testCXX11Using()186 void testCXX11Using() {
187   using Int = int;
188   Int value;
189   value = 1; // non-nested-warning {{never read}}
190 }
191 
192 //===----------------------------------------------------------------------===//
193 // Dead stores in template instantiations (do not warn).
194 //===----------------------------------------------------------------------===//
195 
radar13213575_testit(int i)196 template <bool f> int radar13213575_testit(int i) {
197   int x = 5+i; // warning: Value stored to 'x' during its initialization is never read
198   int y = 7;
199   if (f)
200     return x;
201   else
202     return y;
203 }
204 
radar_13213575()205 int radar_13213575() {
206   return radar13213575_testit<true>(5) + radar13213575_testit<false>(3);
207 }
208 
209 template <class T>
test_block_in_dependent_context(typename T::some_t someArray)210 void test_block_in_dependent_context(typename T::some_t someArray) {
211   ^{
212     int i = someArray[0]; // no-warning
213   }();
214 }
215 
test_block_in_non_dependent_context(int * someArray)216 void test_block_in_non_dependent_context(int *someArray) {
217   ^{
218     int i = someArray[0];
219     // non-nested-warning@-1 {{Value stored to 'i' during its initialization is never read}}
220   }();
221 }
222 
223 
224 //===----------------------------------------------------------------------===//
225 // Dead store checking involving lambdas.
226 //===----------------------------------------------------------------------===//
227 
basicLambda(int i,int j)228 int basicLambda(int i, int j) {
229   i = 5; // no warning
230   j = 6; // no warning
231   [i] { (void)i; }();
232   [&j] { (void)j; }();
233   i = 2;
234   j = 3;
235   return i + j;
236 }
237 
238