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