/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- SymbolManager.h - Management of Symbolic Values --------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file defines SymbolManager, a class that manages symbolic values |
10 | | // created for use by ExprEngine and related classes. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" |
15 | | #include "clang/AST/ASTContext.h" |
16 | | #include "clang/AST/Expr.h" |
17 | | #include "clang/AST/StmtObjC.h" |
18 | | #include "clang/Analysis/Analyses/LiveVariables.h" |
19 | | #include "clang/Analysis/AnalysisDeclContext.h" |
20 | | #include "clang/Basic/LLVM.h" |
21 | | #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" |
22 | | #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" |
23 | | #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" |
24 | | #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" |
25 | | #include "llvm/ADT/FoldingSet.h" |
26 | | #include "llvm/ADT/STLExtras.h" |
27 | | #include "llvm/Support/Casting.h" |
28 | | #include "llvm/Support/Compiler.h" |
29 | | #include "llvm/Support/ErrorHandling.h" |
30 | | #include "llvm/Support/raw_ostream.h" |
31 | | #include <cassert> |
32 | | |
33 | | using namespace clang; |
34 | | using namespace ento; |
35 | | |
36 | 0 | void SymExpr::anchor() {} |
37 | | |
38 | 265 | StringRef SymbolConjured::getKindStr() const { return "conj_$"; } |
39 | 3 | StringRef SymbolDerived::getKindStr() const { return "derived_$"; } |
40 | 8 | StringRef SymbolExtent::getKindStr() const { return "extent_$"; } |
41 | 0 | StringRef SymbolMetadata::getKindStr() const { return "meta_$"; } |
42 | 3.29k | StringRef SymbolRegionValue::getKindStr() const { return "reg_$"; } |
43 | | |
44 | 0 | LLVM_DUMP_METHOD void SymExpr::dump() const { dumpToStream(llvm::errs()); } |
45 | | |
46 | 128 | void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS, const SymExpr *Sym) { |
47 | 128 | OS << '('; |
48 | 128 | Sym->dumpToStream(OS); |
49 | 128 | OS << ')'; |
50 | 128 | } |
51 | | |
52 | | void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS, |
53 | 52 | const llvm::APSInt &Value) { |
54 | 52 | if (Value.isUnsigned()) |
55 | 18 | OS << Value.getZExtValue(); |
56 | 34 | else |
57 | 34 | OS << Value.getSExtValue(); |
58 | 52 | if (Value.isUnsigned()) |
59 | 18 | OS << 'U'; |
60 | 52 | } |
61 | | |
62 | | void BinarySymExpr::dumpToStreamImpl(raw_ostream &OS, |
63 | 90 | BinaryOperator::Opcode Op) { |
64 | 90 | OS << ' ' << BinaryOperator::getOpcodeStr(Op) << ' '; |
65 | 90 | } |
66 | | |
67 | 3.47k | void SymbolCast::dumpToStream(raw_ostream &os) const { |
68 | 3.47k | os << '(' << ToTy << ") ("; |
69 | 3.47k | Operand->dumpToStream(os); |
70 | 3.47k | os << ')'; |
71 | 3.47k | } |
72 | | |
73 | 5 | void UnarySymExpr::dumpToStream(raw_ostream &os) const { |
74 | 5 | os << UnaryOperator::getOpcodeStr(Op); |
75 | 5 | bool Binary = isa<BinarySymExpr>(Operand); |
76 | 5 | if (Binary) |
77 | 2 | os << '('; |
78 | 5 | Operand->dumpToStream(os); |
79 | 5 | if (Binary) |
80 | 2 | os << ')'; |
81 | 5 | } |
82 | | |
83 | 265 | void SymbolConjured::dumpToStream(raw_ostream &os) const { |
84 | 265 | os << getKindStr() << getSymbolID() << '{' << T << ", LC" << LCtx->getID(); |
85 | 265 | if (S) |
86 | 257 | os << ", S" << S->getID(LCtx->getDecl()->getASTContext()); |
87 | 8 | else |
88 | 8 | os << ", no stmt"; |
89 | 265 | os << ", #" << Count << '}'; |
90 | 265 | } |
91 | | |
92 | 3 | void SymbolDerived::dumpToStream(raw_ostream &os) const { |
93 | 3 | os << getKindStr() << getSymbolID() << '{' << getParentSymbol() << ',' |
94 | 3 | << getRegion() << '}'; |
95 | 3 | } |
96 | | |
97 | 8 | void SymbolExtent::dumpToStream(raw_ostream &os) const { |
98 | 8 | os << getKindStr() << getSymbolID() << '{' << getRegion() << '}'; |
99 | 8 | } |
100 | | |
101 | 0 | void SymbolMetadata::dumpToStream(raw_ostream &os) const { |
102 | 0 | os << getKindStr() << getSymbolID() << '{' << getRegion() << ',' << T << '}'; |
103 | 0 | } |
104 | | |
105 | 0 | void SymbolData::anchor() {} |
106 | | |
107 | 3.29k | void SymbolRegionValue::dumpToStream(raw_ostream &os) const { |
108 | 3.29k | os << getKindStr() << getSymbolID() << '<' << getType() << ' ' << R << '>'; |
109 | 3.29k | } |
110 | | |
111 | 0 | bool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const { |
112 | 0 | return itr == X.itr; |
113 | 0 | } |
114 | | |
115 | 5.76M | bool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const { |
116 | 5.76M | return itr != X.itr; |
117 | 5.76M | } |
118 | | |
119 | 1.42M | SymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) { |
120 | 1.42M | itr.push_back(SE); |
121 | 1.42M | } |
122 | | |
123 | 3.43M | SymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() { |
124 | 3.43M | assert(!itr.empty() && "attempting to iterate on an 'end' iterator"); |
125 | 3.43M | expand(); |
126 | 3.43M | return *this; |
127 | 3.43M | } |
128 | | |
129 | 3.44M | SymbolRef SymExpr::symbol_iterator::operator*() { |
130 | 3.44M | assert(!itr.empty() && "attempting to dereference an 'end' iterator"); |
131 | 3.44M | return itr.back(); |
132 | 3.44M | } |
133 | | |
134 | 3.43M | void SymExpr::symbol_iterator::expand() { |
135 | 3.43M | const SymExpr *SE = itr.pop_back_val(); |
136 | | |
137 | 3.43M | switch (SE->getKind()) { |
138 | 850k | case SymExpr::SymbolRegionValueKind: |
139 | 2.20M | case SymExpr::SymbolConjuredKind: |
140 | 2.27M | case SymExpr::SymbolDerivedKind: |
141 | 2.27M | case SymExpr::SymbolExtentKind: |
142 | 2.27M | case SymExpr::SymbolMetadataKind: |
143 | 2.27M | return; |
144 | 3.92k | case SymExpr::SymbolCastKind: |
145 | 3.92k | itr.push_back(cast<SymbolCast>(SE)->getOperand()); |
146 | 3.92k | return; |
147 | 394 | case SymExpr::UnarySymExprKind: |
148 | 394 | itr.push_back(cast<UnarySymExpr>(SE)->getOperand()); |
149 | 394 | return; |
150 | 272k | case SymExpr::SymIntExprKind: |
151 | 272k | itr.push_back(cast<SymIntExpr>(SE)->getLHS()); |
152 | 272k | return; |
153 | 25.5k | case SymExpr::IntSymExprKind: |
154 | 25.5k | itr.push_back(cast<IntSymExpr>(SE)->getRHS()); |
155 | 25.5k | return; |
156 | 858k | case SymExpr::SymSymExprKind: { |
157 | 858k | const auto *x = cast<SymSymExpr>(SE); |
158 | 858k | itr.push_back(x->getLHS()); |
159 | 858k | itr.push_back(x->getRHS()); |
160 | 858k | return; |
161 | 2.27M | } |
162 | 3.43M | } |
163 | 0 | llvm_unreachable("unhandled expansion case"); |
164 | 0 | } |
165 | | |
166 | | const SymbolRegionValue* |
167 | 164k | SymbolManager::getRegionValueSymbol(const TypedValueRegion* R) { |
168 | 164k | llvm::FoldingSetNodeID profile; |
169 | 164k | SymbolRegionValue::Profile(profile, R); |
170 | 164k | void *InsertPos; |
171 | 164k | SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); |
172 | 164k | if (!SD) { |
173 | 16.0k | SD = new (BPAlloc) SymbolRegionValue(SymbolCounter, R); |
174 | 16.0k | DataSet.InsertNode(SD, InsertPos); |
175 | 16.0k | ++SymbolCounter; |
176 | 16.0k | } |
177 | | |
178 | 164k | return cast<SymbolRegionValue>(SD); |
179 | 164k | } |
180 | | |
181 | | const SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E, |
182 | | const LocationContext *LCtx, |
183 | | QualType T, |
184 | | unsigned Count, |
185 | 136k | const void *SymbolTag) { |
186 | 136k | llvm::FoldingSetNodeID profile; |
187 | 136k | SymbolConjured::Profile(profile, E, T, Count, LCtx, SymbolTag); |
188 | 136k | void *InsertPos; |
189 | 136k | SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); |
190 | 136k | if (!SD) { |
191 | 73.4k | SD = new (BPAlloc) SymbolConjured(SymbolCounter, E, LCtx, T, Count, SymbolTag); |
192 | 73.4k | DataSet.InsertNode(SD, InsertPos); |
193 | 73.4k | ++SymbolCounter; |
194 | 73.4k | } |
195 | | |
196 | 136k | return cast<SymbolConjured>(SD); |
197 | 136k | } |
198 | | |
199 | | const SymbolDerived* |
200 | | SymbolManager::getDerivedSymbol(SymbolRef parentSymbol, |
201 | 15.8k | const TypedValueRegion *R) { |
202 | 15.8k | llvm::FoldingSetNodeID profile; |
203 | 15.8k | SymbolDerived::Profile(profile, parentSymbol, R); |
204 | 15.8k | void *InsertPos; |
205 | 15.8k | SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); |
206 | 15.8k | if (!SD) { |
207 | 3.10k | SD = new (BPAlloc) SymbolDerived(SymbolCounter, parentSymbol, R); |
208 | 3.10k | DataSet.InsertNode(SD, InsertPos); |
209 | 3.10k | ++SymbolCounter; |
210 | 3.10k | } |
211 | | |
212 | 15.8k | return cast<SymbolDerived>(SD); |
213 | 15.8k | } |
214 | | |
215 | | const SymbolExtent* |
216 | 9.57k | SymbolManager::getExtentSymbol(const SubRegion *R) { |
217 | 9.57k | llvm::FoldingSetNodeID profile; |
218 | 9.57k | SymbolExtent::Profile(profile, R); |
219 | 9.57k | void *InsertPos; |
220 | 9.57k | SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); |
221 | 9.57k | if (!SD) { |
222 | 285 | SD = new (BPAlloc) SymbolExtent(SymbolCounter, R); |
223 | 285 | DataSet.InsertNode(SD, InsertPos); |
224 | 285 | ++SymbolCounter; |
225 | 285 | } |
226 | | |
227 | 9.57k | return cast<SymbolExtent>(SD); |
228 | 9.57k | } |
229 | | |
230 | | const SymbolMetadata * |
231 | | SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T, |
232 | | const LocationContext *LCtx, |
233 | 694 | unsigned Count, const void *SymbolTag) { |
234 | 694 | llvm::FoldingSetNodeID profile; |
235 | 694 | SymbolMetadata::Profile(profile, R, S, T, LCtx, Count, SymbolTag); |
236 | 694 | void *InsertPos; |
237 | 694 | SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); |
238 | 694 | if (!SD) { |
239 | 662 | SD = new (BPAlloc) SymbolMetadata(SymbolCounter, R, S, T, LCtx, Count, SymbolTag); |
240 | 662 | DataSet.InsertNode(SD, InsertPos); |
241 | 662 | ++SymbolCounter; |
242 | 662 | } |
243 | | |
244 | 694 | return cast<SymbolMetadata>(SD); |
245 | 694 | } |
246 | | |
247 | | const SymbolCast* |
248 | | SymbolManager::getCastSymbol(const SymExpr *Op, |
249 | 5.02k | QualType From, QualType To) { |
250 | 5.02k | llvm::FoldingSetNodeID ID; |
251 | 5.02k | SymbolCast::Profile(ID, Op, From, To); |
252 | 5.02k | void *InsertPos; |
253 | 5.02k | SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); |
254 | 5.02k | if (!data) { |
255 | 1.04k | data = new (BPAlloc) SymbolCast(Op, From, To); |
256 | 1.04k | DataSet.InsertNode(data, InsertPos); |
257 | 1.04k | } |
258 | | |
259 | 5.02k | return cast<SymbolCast>(data); |
260 | 5.02k | } |
261 | | |
262 | | const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs, |
263 | | BinaryOperator::Opcode op, |
264 | | const llvm::APSInt& v, |
265 | 223k | QualType t) { |
266 | 223k | llvm::FoldingSetNodeID ID; |
267 | 223k | SymIntExpr::Profile(ID, lhs, op, v, t); |
268 | 223k | void *InsertPos; |
269 | 223k | SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); |
270 | | |
271 | 223k | if (!data) { |
272 | 31.8k | data = new (BPAlloc) SymIntExpr(lhs, op, v, t); |
273 | 31.8k | DataSet.InsertNode(data, InsertPos); |
274 | 31.8k | } |
275 | | |
276 | 223k | return cast<SymIntExpr>(data); |
277 | 223k | } |
278 | | |
279 | | const IntSymExpr *SymbolManager::getIntSymExpr(const llvm::APSInt& lhs, |
280 | | BinaryOperator::Opcode op, |
281 | | const SymExpr *rhs, |
282 | 1.41k | QualType t) { |
283 | 1.41k | llvm::FoldingSetNodeID ID; |
284 | 1.41k | IntSymExpr::Profile(ID, lhs, op, rhs, t); |
285 | 1.41k | void *InsertPos; |
286 | 1.41k | SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); |
287 | | |
288 | 1.41k | if (!data) { |
289 | 281 | data = new (BPAlloc) IntSymExpr(lhs, op, rhs, t); |
290 | 281 | DataSet.InsertNode(data, InsertPos); |
291 | 281 | } |
292 | | |
293 | 1.41k | return cast<IntSymExpr>(data); |
294 | 1.41k | } |
295 | | |
296 | | const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs, |
297 | | BinaryOperator::Opcode op, |
298 | | const SymExpr *rhs, |
299 | 305k | QualType t) { |
300 | 305k | llvm::FoldingSetNodeID ID; |
301 | 305k | SymSymExpr::Profile(ID, lhs, op, rhs, t); |
302 | 305k | void *InsertPos; |
303 | 305k | SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); |
304 | | |
305 | 305k | if (!data) { |
306 | 11.4k | data = new (BPAlloc) SymSymExpr(lhs, op, rhs, t); |
307 | 11.4k | DataSet.InsertNode(data, InsertPos); |
308 | 11.4k | } |
309 | | |
310 | 305k | return cast<SymSymExpr>(data); |
311 | 305k | } |
312 | | |
313 | | const UnarySymExpr *SymbolManager::getUnarySymExpr(const SymExpr *Operand, |
314 | | UnaryOperator::Opcode Opc, |
315 | 356k | QualType T) { |
316 | 356k | llvm::FoldingSetNodeID ID; |
317 | 356k | UnarySymExpr::Profile(ID, Operand, Opc, T); |
318 | 356k | void *InsertPos; |
319 | 356k | SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); |
320 | 356k | if (!data) { |
321 | 10.1k | data = new (BPAlloc) UnarySymExpr(Operand, Opc, T); |
322 | 10.1k | DataSet.InsertNode(data, InsertPos); |
323 | 10.1k | } |
324 | | |
325 | 356k | return cast<UnarySymExpr>(data); |
326 | 356k | } |
327 | | |
328 | 1.22M | QualType SymbolConjured::getType() const { |
329 | 1.22M | return T; |
330 | 1.22M | } |
331 | | |
332 | 289k | QualType SymbolDerived::getType() const { |
333 | 289k | return R->getValueType(); |
334 | 289k | } |
335 | | |
336 | 853k | QualType SymbolExtent::getType() const { |
337 | 853k | ASTContext &Ctx = R->getMemRegionManager().getContext(); |
338 | 853k | return Ctx.getSizeType(); |
339 | 853k | } |
340 | | |
341 | 25.1k | QualType SymbolMetadata::getType() const { |
342 | 25.1k | return T; |
343 | 25.1k | } |
344 | | |
345 | 8.26M | QualType SymbolRegionValue::getType() const { |
346 | 8.26M | return R->getValueType(); |
347 | 8.26M | } |
348 | | |
349 | 327k | bool SymbolManager::canSymbolicate(QualType T) { |
350 | 327k | T = T.getCanonicalType(); |
351 | | |
352 | 327k | if (Loc::isLocType(T)) |
353 | 84.0k | return true; |
354 | | |
355 | 243k | if (T->isIntegralOrEnumerationType()) |
356 | 231k | return true; |
357 | | |
358 | 11.6k | if (T->isRecordType() && !T->isUnionType()955 ) |
359 | 953 | return true; |
360 | | |
361 | 10.6k | return false; |
362 | 11.6k | } |
363 | | |
364 | | void SymbolManager::addSymbolDependency(const SymbolRef Primary, |
365 | 129 | const SymbolRef Dependent) { |
366 | 129 | auto &dependencies = SymbolDependencies[Primary]; |
367 | 129 | if (!dependencies) { |
368 | 119 | dependencies = std::make_unique<SymbolRefSmallVectorTy>(); |
369 | 119 | } |
370 | 129 | dependencies->push_back(Dependent); |
371 | 129 | } |
372 | | |
373 | | const SymbolRefSmallVectorTy *SymbolManager::getDependentSymbols( |
374 | 7.25M | const SymbolRef Primary) { |
375 | 7.25M | SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary); |
376 | 7.25M | if (I == SymbolDependencies.end()) |
377 | 7.24M | return nullptr; |
378 | 1.79k | return I->second.get(); |
379 | 7.25M | } |
380 | | |
381 | 10.3M | void SymbolReaper::markDependentsLive(SymbolRef sym) { |
382 | | // Do not mark dependents more then once. |
383 | 10.3M | SymbolMapTy::iterator LI = TheLiving.find(sym); |
384 | 10.3M | assert(LI != TheLiving.end() && "The primary symbol is not live."); |
385 | 10.3M | if (LI->second == HaveMarkedDependents) |
386 | 3.07M | return; |
387 | 7.25M | LI->second = HaveMarkedDependents; |
388 | | |
389 | 7.25M | if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) { |
390 | 1.96k | for (const auto I : *Deps) { |
391 | 1.96k | if (TheLiving.contains(I)) |
392 | 1.02k | continue; |
393 | 942 | markLive(I); |
394 | 942 | } |
395 | 1.79k | } |
396 | 7.25M | } |
397 | | |
398 | 7.25M | void SymbolReaper::markLive(SymbolRef sym) { |
399 | 7.25M | TheLiving[sym] = NotProcessed; |
400 | 7.25M | markDependentsLive(sym); |
401 | 7.25M | } |
402 | | |
403 | 1.42M | void SymbolReaper::markLive(const MemRegion *region) { |
404 | 1.42M | LiveRegionRoots.insert(region->getBaseRegion()); |
405 | 1.42M | markElementIndicesLive(region); |
406 | 1.42M | } |
407 | | |
408 | 4.86k | void SymbolReaper::markLazilyCopied(const clang::ento::MemRegion *region) { |
409 | 4.86k | LazilyCopiedRegionRoots.insert(region->getBaseRegion()); |
410 | 4.86k | } |
411 | | |
412 | 3.13M | void SymbolReaper::markElementIndicesLive(const MemRegion *region) { |
413 | 6.19M | for (auto SR = dyn_cast<SubRegion>(region); SR; |
414 | 3.13M | SR = dyn_cast<SubRegion>(SR->getSuperRegion())3.05M ) { |
415 | 3.05M | if (const auto ER = dyn_cast<ElementRegion>(SR)) { |
416 | 232k | SVal Idx = ER->getIndex(); |
417 | 232k | for (SymbolRef Sym : Idx.symbols()) |
418 | 937k | markLive(Sym); |
419 | 232k | } |
420 | 3.05M | } |
421 | 3.13M | } |
422 | | |
423 | 1.89k | void SymbolReaper::markInUse(SymbolRef sym) { |
424 | 1.89k | if (isa<SymbolMetadata>(sym)) |
425 | 1.84k | MetadataInUse.insert(sym); |
426 | 1.89k | } |
427 | | |
428 | 1.74M | bool SymbolReaper::isLiveRegion(const MemRegion *MR) { |
429 | | // TODO: For now, liveness of a memory region is equivalent to liveness of its |
430 | | // base region. In fact we can do a bit better: say, if a particular FieldDecl |
431 | | // is not used later in the path, we can diagnose a leak of a value within |
432 | | // that field earlier than, say, the variable that contains the field dies. |
433 | 1.74M | MR = MR->getBaseRegion(); |
434 | 1.74M | if (LiveRegionRoots.count(MR)) |
435 | 334k | return true; |
436 | | |
437 | 1.41M | if (const auto *SR = dyn_cast<SymbolicRegion>(MR)) |
438 | 915k | return isLive(SR->getSymbol()); |
439 | | |
440 | 498k | if (const auto *VR = dyn_cast<VarRegion>(MR)) |
441 | 490k | return isLive(VR, true); |
442 | | |
443 | | // FIXME: This is a gross over-approximation. What we really need is a way to |
444 | | // tell if anything still refers to this region. Unlike SymbolicRegions, |
445 | | // AllocaRegions don't have associated symbols, though, so we don't actually |
446 | | // have a way to track their liveness. |
447 | 8.10k | return isa<AllocaRegion, CXXThisRegion, MemSpaceRegion, CodeTextRegion>(MR); |
448 | 498k | } |
449 | | |
450 | 254k | bool SymbolReaper::isLazilyCopiedRegion(const MemRegion *MR) const { |
451 | | // TODO: See comment in isLiveRegion. |
452 | 254k | return LazilyCopiedRegionRoots.count(MR->getBaseRegion()); |
453 | 254k | } |
454 | | |
455 | 1.54M | bool SymbolReaper::isReadableRegion(const MemRegion *MR) { |
456 | 1.54M | return isLiveRegion(MR) || isLazilyCopiedRegion(MR)254k ; |
457 | 1.54M | } |
458 | | |
459 | 7.44M | bool SymbolReaper::isLive(SymbolRef sym) { |
460 | 7.44M | if (TheLiving.count(sym)) { |
461 | 3.07M | markDependentsLive(sym); |
462 | 3.07M | return true; |
463 | 3.07M | } |
464 | | |
465 | 4.37M | bool KnownLive; |
466 | | |
467 | 4.37M | switch (sym->getKind()) { |
468 | 1.54M | case SymExpr::SymbolRegionValueKind: |
469 | 1.54M | KnownLive = isReadableRegion(cast<SymbolRegionValue>(sym)->getRegion()); |
470 | 1.54M | break; |
471 | 68.7k | case SymExpr::SymbolConjuredKind: |
472 | 68.7k | KnownLive = false; |
473 | 68.7k | break; |
474 | 62.0k | case SymExpr::SymbolDerivedKind: |
475 | 62.0k | KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol()); |
476 | 62.0k | break; |
477 | 70.1k | case SymExpr::SymbolExtentKind: |
478 | 70.1k | KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion()); |
479 | 70.1k | break; |
480 | 1.88k | case SymExpr::SymbolMetadataKind: |
481 | 1.88k | KnownLive = MetadataInUse.count(sym) && |
482 | 1.88k | isLiveRegion(cast<SymbolMetadata>(sym)->getRegion())1.58k ; |
483 | 1.88k | if (KnownLive) |
484 | 619 | MetadataInUse.erase(sym); |
485 | 1.88k | break; |
486 | 1.76M | case SymExpr::SymIntExprKind: |
487 | 1.76M | KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS()); |
488 | 1.76M | break; |
489 | 47.0k | case SymExpr::IntSymExprKind: |
490 | 47.0k | KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS()); |
491 | 47.0k | break; |
492 | 814k | case SymExpr::SymSymExprKind: |
493 | 814k | KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) && |
494 | 814k | isLive(cast<SymSymExpr>(sym)->getRHS())783k ; |
495 | 814k | break; |
496 | 79 | case SymExpr::SymbolCastKind: |
497 | 79 | KnownLive = isLive(cast<SymbolCast>(sym)->getOperand()); |
498 | 79 | break; |
499 | 43 | case SymExpr::UnarySymExprKind: |
500 | 43 | KnownLive = isLive(cast<UnarySymExpr>(sym)->getOperand()); |
501 | 43 | break; |
502 | 4.37M | } |
503 | | |
504 | 4.37M | if (KnownLive) |
505 | 3.95M | markLive(sym); |
506 | | |
507 | 4.37M | return KnownLive; |
508 | 4.37M | } |
509 | | |
510 | | bool |
511 | 2.46M | SymbolReaper::isLive(const Expr *ExprVal, const LocationContext *ELCtx) const { |
512 | 2.46M | if (LCtx == nullptr) |
513 | 47.7k | return false; |
514 | | |
515 | 2.42M | if (LCtx != ELCtx) { |
516 | | // If the reaper's location context is a parent of the expression's |
517 | | // location context, then the expression value is now "out of scope". |
518 | 750k | if (LCtx->isParentOf(ELCtx)) |
519 | 102k | return false; |
520 | 647k | return true; |
521 | 750k | } |
522 | | |
523 | | // If no statement is provided, everything in this and parent contexts is |
524 | | // live. |
525 | 1.67M | if (!Loc) |
526 | 94.6k | return true; |
527 | | |
528 | 1.57M | return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal); |
529 | 1.67M | } |
530 | | |
531 | 1.28M | bool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{ |
532 | 1.28M | const StackFrameContext *VarContext = VR->getStackFrame(); |
533 | | |
534 | 1.28M | if (!VarContext) |
535 | 93.4k | return true; |
536 | | |
537 | 1.19M | if (!LCtx) |
538 | 117k | return false; |
539 | 1.07M | const StackFrameContext *CurrentContext = LCtx->getStackFrame(); |
540 | | |
541 | 1.07M | if (VarContext == CurrentContext) { |
542 | | // If no statement is provided, everything is live. |
543 | 717k | if (!Loc) |
544 | 35.8k | return true; |
545 | | |
546 | | // Anonymous parameters of an inheriting constructor are live for the entire |
547 | | // duration of the constructor. |
548 | 681k | if (isa<CXXInheritedCtorInitExpr>(Loc)) |
549 | 6 | return true; |
550 | | |
551 | 681k | if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl())) |
552 | 552k | return true; |
553 | | |
554 | 128k | if (!includeStoreBindings) |
555 | 90.1k | return false; |
556 | | |
557 | 38.8k | unsigned &cachedQuery = |
558 | 38.8k | const_cast<SymbolReaper *>(this)->includedRegionCache[VR]; |
559 | | |
560 | 38.8k | if (cachedQuery) { |
561 | 1.16k | return cachedQuery == 1; |
562 | 1.16k | } |
563 | | |
564 | | // Query the store to see if the region occurs in any live bindings. |
565 | 37.6k | if (Store store = reapedStore.getStore()) { |
566 | 14.8k | bool hasRegion = |
567 | 14.8k | reapedStore.getStoreManager().includedInBindings(store, VR); |
568 | 14.8k | cachedQuery = hasRegion ? 10 : 2; |
569 | 14.8k | return hasRegion; |
570 | 14.8k | } |
571 | | |
572 | 22.8k | return false; |
573 | 37.6k | } |
574 | | |
575 | 357k | return VarContext->isParentOf(CurrentContext); |
576 | 1.07M | } |