1218887Sdim//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9218887Sdim//
10218887Sdim//  This file defines SymbolManager, a class that manages symbolic values
11218887Sdim//  created for use by ExprEngine and related classes.
12218887Sdim//
13218887Sdim//===----------------------------------------------------------------------===//
14218887Sdim
15218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
16218887Sdim#include "clang/Analysis/Analyses/LiveVariables.h"
17218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
18226633Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
19218887Sdim#include "llvm/Support/raw_ostream.h"
20218887Sdim
21218887Sdimusing namespace clang;
22218887Sdimusing namespace ento;
23218887Sdim
24234353Sdimvoid SymExpr::anchor() { }
25234353Sdim
26218887Sdimvoid SymExpr::dump() const {
27218887Sdim  dumpToStream(llvm::errs());
28218887Sdim}
29218887Sdim
30226633Sdimvoid SymIntExpr::dumpToStream(raw_ostream &os) const {
31218887Sdim  os << '(';
32218887Sdim  getLHS()->dumpToStream(os);
33249423Sdim  os << ") "
34249423Sdim     << BinaryOperator::getOpcodeStr(getOpcode()) << ' '
35249423Sdim     << getRHS().getZExtValue();
36249423Sdim  if (getRHS().isUnsigned())
37249423Sdim    os << 'U';
38218887Sdim}
39218887Sdim
40234353Sdimvoid IntSymExpr::dumpToStream(raw_ostream &os) const {
41249423Sdim  os << getLHS().getZExtValue();
42249423Sdim  if (getLHS().isUnsigned())
43249423Sdim    os << 'U';
44249423Sdim  os << ' '
45249423Sdim     << BinaryOperator::getOpcodeStr(getOpcode())
46249423Sdim     << " (";
47234353Sdim  getRHS()->dumpToStream(os);
48249423Sdim  os << ')';
49234353Sdim}
50234353Sdim
51226633Sdimvoid SymSymExpr::dumpToStream(raw_ostream &os) const {
52218887Sdim  os << '(';
53218887Sdim  getLHS()->dumpToStream(os);
54249423Sdim  os << ") "
55249423Sdim     << BinaryOperator::getOpcodeStr(getOpcode())
56249423Sdim     << " (";
57218887Sdim  getRHS()->dumpToStream(os);
58218887Sdim  os << ')';
59218887Sdim}
60218887Sdim
61234353Sdimvoid SymbolCast::dumpToStream(raw_ostream &os) const {
62234353Sdim  os << '(' << ToTy.getAsString() << ") (";
63234353Sdim  Operand->dumpToStream(os);
64234353Sdim  os << ')';
65234353Sdim}
66234353Sdim
67226633Sdimvoid SymbolConjured::dumpToStream(raw_ostream &os) const {
68218887Sdim  os << "conj_$" << getSymbolID() << '{' << T.getAsString() << '}';
69218887Sdim}
70218887Sdim
71226633Sdimvoid SymbolDerived::dumpToStream(raw_ostream &os) const {
72218887Sdim  os << "derived_$" << getSymbolID() << '{'
73218887Sdim     << getParentSymbol() << ',' << getRegion() << '}';
74218887Sdim}
75218887Sdim
76226633Sdimvoid SymbolExtent::dumpToStream(raw_ostream &os) const {
77218887Sdim  os << "extent_$" << getSymbolID() << '{' << getRegion() << '}';
78218887Sdim}
79218887Sdim
80226633Sdimvoid SymbolMetadata::dumpToStream(raw_ostream &os) const {
81218887Sdim  os << "meta_$" << getSymbolID() << '{'
82218887Sdim     << getRegion() << ',' << T.getAsString() << '}';
83218887Sdim}
84218887Sdim
85234353Sdimvoid SymbolData::anchor() { }
86234353Sdim
87226633Sdimvoid SymbolRegionValue::dumpToStream(raw_ostream &os) const {
88218887Sdim  os << "reg_$" << getSymbolID() << "<" << R << ">";
89218887Sdim}
90218887Sdim
91234353Sdimbool SymExpr::symbol_iterator::operator==(const symbol_iterator &X) const {
92234353Sdim  return itr == X.itr;
93234353Sdim}
94234353Sdim
95234353Sdimbool SymExpr::symbol_iterator::operator!=(const symbol_iterator &X) const {
96234353Sdim  return itr != X.itr;
97234353Sdim}
98234353Sdim
99234353SdimSymExpr::symbol_iterator::symbol_iterator(const SymExpr *SE) {
100234353Sdim  itr.push_back(SE);
101234353Sdim}
102234353Sdim
103234353SdimSymExpr::symbol_iterator &SymExpr::symbol_iterator::operator++() {
104234353Sdim  assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
105243830Sdim  expand();
106234353Sdim  return *this;
107234353Sdim}
108234353Sdim
109234353SdimSymbolRef SymExpr::symbol_iterator::operator*() {
110234353Sdim  assert(!itr.empty() && "attempting to dereference an 'end' iterator");
111243830Sdim  return itr.back();
112234353Sdim}
113234353Sdim
114234353Sdimvoid SymExpr::symbol_iterator::expand() {
115263508Sdim  const SymExpr *SE = itr.pop_back_val();
116234353Sdim
117234353Sdim  switch (SE->getKind()) {
118234353Sdim    case SymExpr::RegionValueKind:
119234353Sdim    case SymExpr::ConjuredKind:
120234353Sdim    case SymExpr::DerivedKind:
121234353Sdim    case SymExpr::ExtentKind:
122234353Sdim    case SymExpr::MetadataKind:
123234353Sdim      return;
124234353Sdim    case SymExpr::CastSymbolKind:
125234353Sdim      itr.push_back(cast<SymbolCast>(SE)->getOperand());
126234353Sdim      return;
127234353Sdim    case SymExpr::SymIntKind:
128234353Sdim      itr.push_back(cast<SymIntExpr>(SE)->getLHS());
129234353Sdim      return;
130234353Sdim    case SymExpr::IntSymKind:
131234353Sdim      itr.push_back(cast<IntSymExpr>(SE)->getRHS());
132234353Sdim      return;
133234353Sdim    case SymExpr::SymSymKind: {
134234353Sdim      const SymSymExpr *x = cast<SymSymExpr>(SE);
135234353Sdim      itr.push_back(x->getLHS());
136234353Sdim      itr.push_back(x->getRHS());
137234353Sdim      return;
138234353Sdim    }
139234353Sdim  }
140234353Sdim  llvm_unreachable("unhandled expansion case");
141234353Sdim}
142234353Sdim
143239462Sdimunsigned SymExpr::computeComplexity() const {
144239462Sdim  unsigned R = 0;
145239462Sdim  for (symbol_iterator I = symbol_begin(), E = symbol_end(); I != E; ++I)
146239462Sdim    R++;
147239462Sdim  return R;
148239462Sdim}
149239462Sdim
150218887Sdimconst SymbolRegionValue*
151226633SdimSymbolManager::getRegionValueSymbol(const TypedValueRegion* R) {
152218887Sdim  llvm::FoldingSetNodeID profile;
153218887Sdim  SymbolRegionValue::Profile(profile, R);
154226633Sdim  void *InsertPos;
155218887Sdim  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
156218887Sdim  if (!SD) {
157218887Sdim    SD = (SymExpr*) BPAlloc.Allocate<SymbolRegionValue>();
158218887Sdim    new (SD) SymbolRegionValue(SymbolCounter, R);
159218887Sdim    DataSet.InsertNode(SD, InsertPos);
160218887Sdim    ++SymbolCounter;
161218887Sdim  }
162218887Sdim
163218887Sdim  return cast<SymbolRegionValue>(SD);
164218887Sdim}
165218887Sdim
166243830Sdimconst SymbolConjured* SymbolManager::conjureSymbol(const Stmt *E,
167243830Sdim                                                   const LocationContext *LCtx,
168243830Sdim                                                   QualType T,
169243830Sdim                                                   unsigned Count,
170243830Sdim                                                   const void *SymbolTag) {
171218887Sdim  llvm::FoldingSetNodeID profile;
172234353Sdim  SymbolConjured::Profile(profile, E, T, Count, LCtx, SymbolTag);
173226633Sdim  void *InsertPos;
174218887Sdim  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
175218887Sdim  if (!SD) {
176218887Sdim    SD = (SymExpr*) BPAlloc.Allocate<SymbolConjured>();
177234353Sdim    new (SD) SymbolConjured(SymbolCounter, E, LCtx, T, Count, SymbolTag);
178218887Sdim    DataSet.InsertNode(SD, InsertPos);
179218887Sdim    ++SymbolCounter;
180218887Sdim  }
181218887Sdim
182218887Sdim  return cast<SymbolConjured>(SD);
183218887Sdim}
184218887Sdim
185218887Sdimconst SymbolDerived*
186218887SdimSymbolManager::getDerivedSymbol(SymbolRef parentSymbol,
187226633Sdim                                const TypedValueRegion *R) {
188218887Sdim
189218887Sdim  llvm::FoldingSetNodeID profile;
190218887Sdim  SymbolDerived::Profile(profile, parentSymbol, R);
191226633Sdim  void *InsertPos;
192218887Sdim  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
193218887Sdim  if (!SD) {
194218887Sdim    SD = (SymExpr*) BPAlloc.Allocate<SymbolDerived>();
195218887Sdim    new (SD) SymbolDerived(SymbolCounter, parentSymbol, R);
196218887Sdim    DataSet.InsertNode(SD, InsertPos);
197218887Sdim    ++SymbolCounter;
198218887Sdim  }
199218887Sdim
200218887Sdim  return cast<SymbolDerived>(SD);
201218887Sdim}
202218887Sdim
203218887Sdimconst SymbolExtent*
204218887SdimSymbolManager::getExtentSymbol(const SubRegion *R) {
205218887Sdim  llvm::FoldingSetNodeID profile;
206218887Sdim  SymbolExtent::Profile(profile, R);
207226633Sdim  void *InsertPos;
208218887Sdim  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
209218887Sdim  if (!SD) {
210218887Sdim    SD = (SymExpr*) BPAlloc.Allocate<SymbolExtent>();
211218887Sdim    new (SD) SymbolExtent(SymbolCounter, R);
212218887Sdim    DataSet.InsertNode(SD, InsertPos);
213218887Sdim    ++SymbolCounter;
214218887Sdim  }
215218887Sdim
216218887Sdim  return cast<SymbolExtent>(SD);
217218887Sdim}
218218887Sdim
219218887Sdimconst SymbolMetadata*
220226633SdimSymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt *S, QualType T,
221226633Sdim                                 unsigned Count, const void *SymbolTag) {
222218887Sdim
223218887Sdim  llvm::FoldingSetNodeID profile;
224218887Sdim  SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag);
225226633Sdim  void *InsertPos;
226218887Sdim  SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
227218887Sdim  if (!SD) {
228218887Sdim    SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
229218887Sdim    new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
230218887Sdim    DataSet.InsertNode(SD, InsertPos);
231218887Sdim    ++SymbolCounter;
232218887Sdim  }
233218887Sdim
234218887Sdim  return cast<SymbolMetadata>(SD);
235218887Sdim}
236218887Sdim
237234353Sdimconst SymbolCast*
238234353SdimSymbolManager::getCastSymbol(const SymExpr *Op,
239234353Sdim                             QualType From, QualType To) {
240234353Sdim  llvm::FoldingSetNodeID ID;
241234353Sdim  SymbolCast::Profile(ID, Op, From, To);
242234353Sdim  void *InsertPos;
243234353Sdim  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
244234353Sdim  if (!data) {
245234353Sdim    data = (SymbolCast*) BPAlloc.Allocate<SymbolCast>();
246234353Sdim    new (data) SymbolCast(Op, From, To);
247234353Sdim    DataSet.InsertNode(data, InsertPos);
248234353Sdim  }
249234353Sdim
250234353Sdim  return cast<SymbolCast>(data);
251234353Sdim}
252234353Sdim
253218887Sdimconst SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
254218887Sdim                                               BinaryOperator::Opcode op,
255218887Sdim                                               const llvm::APSInt& v,
256218887Sdim                                               QualType t) {
257218887Sdim  llvm::FoldingSetNodeID ID;
258218887Sdim  SymIntExpr::Profile(ID, lhs, op, v, t);
259218887Sdim  void *InsertPos;
260218887Sdim  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
261218887Sdim
262218887Sdim  if (!data) {
263218887Sdim    data = (SymIntExpr*) BPAlloc.Allocate<SymIntExpr>();
264218887Sdim    new (data) SymIntExpr(lhs, op, v, t);
265218887Sdim    DataSet.InsertNode(data, InsertPos);
266218887Sdim  }
267218887Sdim
268218887Sdim  return cast<SymIntExpr>(data);
269218887Sdim}
270218887Sdim
271234353Sdimconst IntSymExpr *SymbolManager::getIntSymExpr(const llvm::APSInt& lhs,
272234353Sdim                                               BinaryOperator::Opcode op,
273234353Sdim                                               const SymExpr *rhs,
274234353Sdim                                               QualType t) {
275234353Sdim  llvm::FoldingSetNodeID ID;
276234353Sdim  IntSymExpr::Profile(ID, lhs, op, rhs, t);
277234353Sdim  void *InsertPos;
278234353Sdim  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
279234353Sdim
280234353Sdim  if (!data) {
281234353Sdim    data = (IntSymExpr*) BPAlloc.Allocate<IntSymExpr>();
282234353Sdim    new (data) IntSymExpr(lhs, op, rhs, t);
283234353Sdim    DataSet.InsertNode(data, InsertPos);
284234353Sdim  }
285234353Sdim
286234353Sdim  return cast<IntSymExpr>(data);
287234353Sdim}
288234353Sdim
289218887Sdimconst SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs,
290218887Sdim                                               BinaryOperator::Opcode op,
291218887Sdim                                               const SymExpr *rhs,
292218887Sdim                                               QualType t) {
293218887Sdim  llvm::FoldingSetNodeID ID;
294218887Sdim  SymSymExpr::Profile(ID, lhs, op, rhs, t);
295218887Sdim  void *InsertPos;
296218887Sdim  SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos);
297218887Sdim
298218887Sdim  if (!data) {
299218887Sdim    data = (SymSymExpr*) BPAlloc.Allocate<SymSymExpr>();
300218887Sdim    new (data) SymSymExpr(lhs, op, rhs, t);
301218887Sdim    DataSet.InsertNode(data, InsertPos);
302218887Sdim  }
303218887Sdim
304218887Sdim  return cast<SymSymExpr>(data);
305218887Sdim}
306218887Sdim
307243830SdimQualType SymbolConjured::getType() const {
308218887Sdim  return T;
309218887Sdim}
310218887Sdim
311243830SdimQualType SymbolDerived::getType() const {
312218887Sdim  return R->getValueType();
313218887Sdim}
314218887Sdim
315243830SdimQualType SymbolExtent::getType() const {
316243830Sdim  ASTContext &Ctx = R->getMemRegionManager()->getContext();
317218887Sdim  return Ctx.getSizeType();
318218887Sdim}
319218887Sdim
320243830SdimQualType SymbolMetadata::getType() const {
321218887Sdim  return T;
322218887Sdim}
323218887Sdim
324243830SdimQualType SymbolRegionValue::getType() const {
325218887Sdim  return R->getValueType();
326218887Sdim}
327218887Sdim
328226633SdimSymbolManager::~SymbolManager() {
329226633Sdim  for (SymbolDependTy::const_iterator I = SymbolDependencies.begin(),
330226633Sdim       E = SymbolDependencies.end(); I != E; ++I) {
331226633Sdim    delete I->second;
332226633Sdim  }
333218887Sdim
334226633Sdim}
335226633Sdim
336218887Sdimbool SymbolManager::canSymbolicate(QualType T) {
337218887Sdim  T = T.getCanonicalType();
338218887Sdim
339218887Sdim  if (Loc::isLocType(T))
340218887Sdim    return true;
341218887Sdim
342251662Sdim  if (T->isIntegralOrEnumerationType())
343251662Sdim    return true;
344218887Sdim
345218887Sdim  if (T->isRecordType() && !T->isUnionType())
346218887Sdim    return true;
347218887Sdim
348218887Sdim  return false;
349218887Sdim}
350218887Sdim
351226633Sdimvoid SymbolManager::addSymbolDependency(const SymbolRef Primary,
352226633Sdim                                        const SymbolRef Dependent) {
353226633Sdim  SymbolDependTy::iterator I = SymbolDependencies.find(Primary);
354226633Sdim  SymbolRefSmallVectorTy *dependencies = 0;
355226633Sdim  if (I == SymbolDependencies.end()) {
356226633Sdim    dependencies = new SymbolRefSmallVectorTy();
357226633Sdim    SymbolDependencies[Primary] = dependencies;
358226633Sdim  } else {
359226633Sdim    dependencies = I->second;
360226633Sdim  }
361226633Sdim  dependencies->push_back(Dependent);
362226633Sdim}
363226633Sdim
364226633Sdimconst SymbolRefSmallVectorTy *SymbolManager::getDependentSymbols(
365226633Sdim                                                     const SymbolRef Primary) {
366226633Sdim  SymbolDependTy::const_iterator I = SymbolDependencies.find(Primary);
367226633Sdim  if (I == SymbolDependencies.end())
368226633Sdim    return 0;
369226633Sdim  return I->second;
370226633Sdim}
371226633Sdim
372226633Sdimvoid SymbolReaper::markDependentsLive(SymbolRef sym) {
373226633Sdim  // Do not mark dependents more then once.
374226633Sdim  SymbolMapTy::iterator LI = TheLiving.find(sym);
375226633Sdim  assert(LI != TheLiving.end() && "The primary symbol is not live.");
376226633Sdim  if (LI->second == HaveMarkedDependents)
377226633Sdim    return;
378226633Sdim  LI->second = HaveMarkedDependents;
379226633Sdim
380226633Sdim  if (const SymbolRefSmallVectorTy *Deps = SymMgr.getDependentSymbols(sym)) {
381226633Sdim    for (SymbolRefSmallVectorTy::const_iterator I = Deps->begin(),
382226633Sdim                                                E = Deps->end(); I != E; ++I) {
383226633Sdim      if (TheLiving.find(*I) != TheLiving.end())
384226633Sdim        continue;
385226633Sdim      markLive(*I);
386226633Sdim    }
387226633Sdim  }
388226633Sdim}
389226633Sdim
390218887Sdimvoid SymbolReaper::markLive(SymbolRef sym) {
391226633Sdim  TheLiving[sym] = NotProcessed;
392218887Sdim  TheDead.erase(sym);
393226633Sdim  markDependentsLive(sym);
394218887Sdim}
395218887Sdim
396226633Sdimvoid SymbolReaper::markLive(const MemRegion *region) {
397226633Sdim  RegionRoots.insert(region);
398226633Sdim}
399226633Sdim
400218887Sdimvoid SymbolReaper::markInUse(SymbolRef sym) {
401218887Sdim  if (isa<SymbolMetadata>(sym))
402218887Sdim    MetadataInUse.insert(sym);
403218887Sdim}
404218887Sdim
405218887Sdimbool SymbolReaper::maybeDead(SymbolRef sym) {
406218887Sdim  if (isLive(sym))
407218887Sdim    return false;
408218887Sdim
409218887Sdim  TheDead.insert(sym);
410218887Sdim  return true;
411218887Sdim}
412218887Sdim
413226633Sdimbool SymbolReaper::isLiveRegion(const MemRegion *MR) {
414226633Sdim  if (RegionRoots.count(MR))
415226633Sdim    return true;
416226633Sdim
417218887Sdim  MR = MR->getBaseRegion();
418218887Sdim
419218887Sdim  if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
420226633Sdim    return isLive(SR->getSymbol());
421218887Sdim
422218887Sdim  if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
423226633Sdim    return isLive(VR, true);
424218887Sdim
425218887Sdim  // FIXME: This is a gross over-approximation. What we really need is a way to
426218887Sdim  // tell if anything still refers to this region. Unlike SymbolicRegions,
427218887Sdim  // AllocaRegions don't have associated symbols, though, so we don't actually
428218887Sdim  // have a way to track their liveness.
429218887Sdim  if (isa<AllocaRegion>(MR))
430218887Sdim    return true;
431218887Sdim
432218887Sdim  if (isa<CXXThisRegion>(MR))
433218887Sdim    return true;
434218887Sdim
435218887Sdim  if (isa<MemSpaceRegion>(MR))
436218887Sdim    return true;
437218887Sdim
438263508Sdim  if (isa<CodeTextRegion>(MR))
439263508Sdim    return true;
440263508Sdim
441218887Sdim  return false;
442218887Sdim}
443218887Sdim
444218887Sdimbool SymbolReaper::isLive(SymbolRef sym) {
445226633Sdim  if (TheLiving.count(sym)) {
446226633Sdim    markDependentsLive(sym);
447218887Sdim    return true;
448226633Sdim  }
449243830Sdim
450243830Sdim  bool KnownLive;
451243830Sdim
452243830Sdim  switch (sym->getKind()) {
453243830Sdim  case SymExpr::RegionValueKind:
454249423Sdim    KnownLive = isLiveRegion(cast<SymbolRegionValue>(sym)->getRegion());
455243830Sdim    break;
456243830Sdim  case SymExpr::ConjuredKind:
457243830Sdim    KnownLive = false;
458243830Sdim    break;
459243830Sdim  case SymExpr::DerivedKind:
460243830Sdim    KnownLive = isLive(cast<SymbolDerived>(sym)->getParentSymbol());
461243830Sdim    break;
462243830Sdim  case SymExpr::ExtentKind:
463243830Sdim    KnownLive = isLiveRegion(cast<SymbolExtent>(sym)->getRegion());
464243830Sdim    break;
465243830Sdim  case SymExpr::MetadataKind:
466243830Sdim    KnownLive = MetadataInUse.count(sym) &&
467243830Sdim                isLiveRegion(cast<SymbolMetadata>(sym)->getRegion());
468243830Sdim    if (KnownLive)
469243830Sdim      MetadataInUse.erase(sym);
470243830Sdim    break;
471243830Sdim  case SymExpr::SymIntKind:
472243830Sdim    KnownLive = isLive(cast<SymIntExpr>(sym)->getLHS());
473243830Sdim    break;
474243830Sdim  case SymExpr::IntSymKind:
475243830Sdim    KnownLive = isLive(cast<IntSymExpr>(sym)->getRHS());
476243830Sdim    break;
477243830Sdim  case SymExpr::SymSymKind:
478243830Sdim    KnownLive = isLive(cast<SymSymExpr>(sym)->getLHS()) &&
479243830Sdim                isLive(cast<SymSymExpr>(sym)->getRHS());
480243830Sdim    break;
481243830Sdim  case SymExpr::CastSymbolKind:
482243830Sdim    KnownLive = isLive(cast<SymbolCast>(sym)->getOperand());
483243830Sdim    break;
484218887Sdim  }
485218887Sdim
486243830Sdim  if (KnownLive)
487243830Sdim    markLive(sym);
488218887Sdim
489243830Sdim  return KnownLive;
490218887Sdim}
491218887Sdim
492234353Sdimbool
493234353SdimSymbolReaper::isLive(const Stmt *ExprVal, const LocationContext *ELCtx) const {
494243830Sdim  if (LCtx == 0)
495243830Sdim    return false;
496243830Sdim
497234353Sdim  if (LCtx != ELCtx) {
498234353Sdim    // If the reaper's location context is a parent of the expression's
499234353Sdim    // location context, then the expression value is now "out of scope".
500234353Sdim    if (LCtx->isParentOf(ELCtx))
501234353Sdim      return false;
502234353Sdim    return true;
503234353Sdim  }
504243830Sdim
505239462Sdim  // If no statement is provided, everything is this and parent contexts is live.
506239462Sdim  if (!Loc)
507239462Sdim    return true;
508234353Sdim
509226633Sdim  return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal);
510218887Sdim}
511218887Sdim
512226633Sdimbool SymbolReaper::isLive(const VarRegion *VR, bool includeStoreBindings) const{
513218887Sdim  const StackFrameContext *VarContext = VR->getStackFrame();
514243830Sdim
515243830Sdim  if (!VarContext)
516243830Sdim    return true;
517243830Sdim
518243830Sdim  if (!LCtx)
519243830Sdim    return false;
520218887Sdim  const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
521218887Sdim
522226633Sdim  if (VarContext == CurrentContext) {
523243830Sdim    // If no statement is provided, everything is live.
524239462Sdim    if (!Loc)
525239462Sdim      return true;
526239462Sdim
527226633Sdim    if (LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, VR->getDecl()))
528226633Sdim      return true;
529218887Sdim
530226633Sdim    if (!includeStoreBindings)
531226633Sdim      return false;
532226633Sdim
533226633Sdim    unsigned &cachedQuery =
534226633Sdim      const_cast<SymbolReaper*>(this)->includedRegionCache[VR];
535226633Sdim
536226633Sdim    if (cachedQuery) {
537226633Sdim      return cachedQuery == 1;
538226633Sdim    }
539226633Sdim
540226633Sdim    // Query the store to see if the region occurs in any live bindings.
541226633Sdim    if (Store store = reapedStore.getStore()) {
542226633Sdim      bool hasRegion =
543226633Sdim        reapedStore.getStoreManager().includedInBindings(store, VR);
544226633Sdim      cachedQuery = hasRegion ? 1 : 2;
545226633Sdim      return hasRegion;
546226633Sdim    }
547226633Sdim
548226633Sdim    return false;
549226633Sdim  }
550226633Sdim
551218887Sdim  return VarContext->isParentOf(CurrentContext);
552218887Sdim}
553218887Sdim
554218887SdimSymbolVisitor::~SymbolVisitor() {}
555