1234287Sdim//== AnalysisDeclContext.cpp - Analysis context for Path Sens analysis -*- C++ -*-//
2234287Sdim//
3234287Sdim//                     The LLVM Compiler Infrastructure
4234287Sdim//
5234287Sdim// This file is distributed under the University of Illinois Open Source
6234287Sdim// License. See LICENSE.TXT for details.
7234287Sdim//
8234287Sdim//===----------------------------------------------------------------------===//
9234287Sdim//
10234287Sdim// This file defines AnalysisDeclContext, a class that manages the analysis context
11234287Sdim// data for path sensitive analysis.
12234287Sdim//
13234287Sdim//===----------------------------------------------------------------------===//
14234287Sdim
15249423Sdim#include "clang/Analysis/AnalysisContext.h"
16249423Sdim#include "BodyFarm.h"
17239462Sdim#include "clang/AST/ASTContext.h"
18234287Sdim#include "clang/AST/Decl.h"
19234287Sdim#include "clang/AST/DeclObjC.h"
20234287Sdim#include "clang/AST/DeclTemplate.h"
21234287Sdim#include "clang/AST/ParentMap.h"
22234287Sdim#include "clang/AST/StmtVisitor.h"
23249423Sdim#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
24234287Sdim#include "clang/Analysis/Analyses/LiveVariables.h"
25234287Sdim#include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
26234287Sdim#include "clang/Analysis/CFG.h"
27234287Sdim#include "clang/Analysis/CFGStmtMap.h"
28234287Sdim#include "clang/Analysis/Support/BumpVector.h"
29234287Sdim#include "llvm/ADT/SmallPtrSet.h"
30234287Sdim#include "llvm/Support/ErrorHandling.h"
31249423Sdim#include "llvm/Support/raw_ostream.h"
32249423Sdim#include "llvm/Support/SaveAndRestore.h"
33234287Sdim
34234287Sdimusing namespace clang;
35234287Sdim
36234287Sdimtypedef llvm::DenseMap<const void *, ManagedAnalysis *> ManagedAnalysisMap;
37234287Sdim
38234287SdimAnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
39243830Sdim                                         const Decl *d,
40243830Sdim                                         const CFG::BuildOptions &buildOptions)
41234287Sdim  : Manager(Mgr),
42234287Sdim    D(d),
43234287Sdim    cfgBuildOptions(buildOptions),
44234287Sdim    forcedBlkExprs(0),
45234287Sdim    builtCFG(false),
46234287Sdim    builtCompleteCFG(false),
47234287Sdim    ReferencedBlockVars(0),
48234287Sdim    ManagedAnalyses(0)
49234287Sdim{
50234287Sdim  cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
51234287Sdim}
52234287Sdim
53234287SdimAnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
54243830Sdim                                         const Decl *d)
55234287Sdim: Manager(Mgr),
56234287Sdim  D(d),
57234287Sdim  forcedBlkExprs(0),
58234287Sdim  builtCFG(false),
59234287Sdim  builtCompleteCFG(false),
60234287Sdim  ReferencedBlockVars(0),
61234287Sdim  ManagedAnalyses(0)
62234287Sdim{
63234287Sdim  cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
64234287Sdim}
65234287Sdim
66234287SdimAnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG,
67243830Sdim                                                       bool addImplicitDtors,
68243830Sdim                                                       bool addInitializers,
69243830Sdim                                                       bool addTemporaryDtors,
70249423Sdim                                                       bool synthesizeBodies,
71249423Sdim                                                       bool addStaticInitBranch)
72243830Sdim  : SynthesizeBodies(synthesizeBodies)
73243830Sdim{
74234287Sdim  cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
75234287Sdim  cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
76234287Sdim  cfgBuildOptions.AddInitializers = addInitializers;
77243830Sdim  cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
78249423Sdim  cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
79234287Sdim}
80234287Sdim
81234287Sdimvoid AnalysisDeclContextManager::clear() {
82234287Sdim  for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
83234287Sdim    delete I->second;
84234287Sdim  Contexts.clear();
85234287Sdim}
86234287Sdim
87243830Sdimstatic BodyFarm &getBodyFarm(ASTContext &C) {
88243830Sdim  static BodyFarm *BF = new BodyFarm(C);
89243830Sdim  return *BF;
90243830Sdim}
91243830Sdim
92249423SdimStmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
93249423Sdim  IsAutosynthesized = false;
94243830Sdim  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
95243830Sdim    Stmt *Body = FD->getBody();
96249423Sdim    if (!Body && Manager && Manager->synthesizeBodies()) {
97249423Sdim      IsAutosynthesized = true;
98243830Sdim      return getBodyFarm(getASTContext()).getBody(FD);
99249423Sdim    }
100243830Sdim    return Body;
101243830Sdim  }
102234287Sdim  else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
103234287Sdim    return MD->getBody();
104234287Sdim  else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
105234287Sdim    return BD->getBody();
106234287Sdim  else if (const FunctionTemplateDecl *FunTmpl
107234287Sdim           = dyn_cast_or_null<FunctionTemplateDecl>(D))
108234287Sdim    return FunTmpl->getTemplatedDecl()->getBody();
109234287Sdim
110234287Sdim  llvm_unreachable("unknown code decl");
111234287Sdim}
112234287Sdim
113249423SdimStmt *AnalysisDeclContext::getBody() const {
114249423Sdim  bool Tmp;
115249423Sdim  return getBody(Tmp);
116249423Sdim}
117249423Sdim
118249423Sdimbool AnalysisDeclContext::isBodyAutosynthesized() const {
119249423Sdim  bool Tmp;
120249423Sdim  getBody(Tmp);
121249423Sdim  return Tmp;
122249423Sdim}
123249423Sdim
124234287Sdimconst ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
125234287Sdim  if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
126234287Sdim    return MD->getSelfDecl();
127234287Sdim  if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
128234287Sdim    // See if 'self' was captured by the block.
129234287Sdim    for (BlockDecl::capture_const_iterator it = BD->capture_begin(),
130234287Sdim         et = BD->capture_end(); it != et; ++it) {
131234287Sdim      const VarDecl *VD = it->getVariable();
132234287Sdim      if (VD->getName() == "self")
133234287Sdim        return dyn_cast<ImplicitParamDecl>(VD);
134234287Sdim    }
135234287Sdim  }
136234287Sdim
137234287Sdim  return NULL;
138234287Sdim}
139234287Sdim
140234287Sdimvoid AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
141234287Sdim  if (!forcedBlkExprs)
142234287Sdim    forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs();
143234287Sdim  // Default construct an entry for 'stmt'.
144234287Sdim  if (const Expr *e = dyn_cast<Expr>(stmt))
145234287Sdim    stmt = e->IgnoreParens();
146234287Sdim  (void) (*forcedBlkExprs)[stmt];
147234287Sdim}
148234287Sdim
149234287Sdimconst CFGBlock *
150234287SdimAnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {
151234287Sdim  assert(forcedBlkExprs);
152234287Sdim  if (const Expr *e = dyn_cast<Expr>(stmt))
153234287Sdim    stmt = e->IgnoreParens();
154234287Sdim  CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
155234287Sdim    forcedBlkExprs->find(stmt);
156234287Sdim  assert(itr != forcedBlkExprs->end());
157234287Sdim  return itr->second;
158234287Sdim}
159234287Sdim
160234287SdimCFG *AnalysisDeclContext::getCFG() {
161234287Sdim  if (!cfgBuildOptions.PruneTriviallyFalseEdges)
162234287Sdim    return getUnoptimizedCFG();
163234287Sdim
164234287Sdim  if (!builtCFG) {
165234287Sdim    cfg.reset(CFG::buildCFG(D, getBody(),
166234287Sdim                            &D->getASTContext(), cfgBuildOptions));
167234287Sdim    // Even when the cfg is not successfully built, we don't
168234287Sdim    // want to try building it again.
169234287Sdim    builtCFG = true;
170234287Sdim  }
171234287Sdim  return cfg.get();
172234287Sdim}
173234287Sdim
174234287SdimCFG *AnalysisDeclContext::getUnoptimizedCFG() {
175234287Sdim  if (!builtCompleteCFG) {
176234287Sdim    SaveAndRestore<bool> NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges,
177234287Sdim                                  false);
178234287Sdim    completeCFG.reset(CFG::buildCFG(D, getBody(), &D->getASTContext(),
179234287Sdim                                    cfgBuildOptions));
180234287Sdim    // Even when the cfg is not successfully built, we don't
181234287Sdim    // want to try building it again.
182234287Sdim    builtCompleteCFG = true;
183234287Sdim  }
184234287Sdim  return completeCFG.get();
185234287Sdim}
186234287Sdim
187234287SdimCFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
188234287Sdim  if (cfgStmtMap)
189234287Sdim    return cfgStmtMap.get();
190234287Sdim
191234287Sdim  if (CFG *c = getCFG()) {
192234287Sdim    cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
193234287Sdim    return cfgStmtMap.get();
194234287Sdim  }
195234287Sdim
196234287Sdim  return 0;
197234287Sdim}
198234287Sdim
199234287SdimCFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
200234287Sdim  if (CFA)
201234287Sdim    return CFA.get();
202234287Sdim
203234287Sdim  if (CFG *c = getCFG()) {
204234287Sdim    CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c));
205234287Sdim    return CFA.get();
206234287Sdim  }
207234287Sdim
208234287Sdim  return 0;
209234287Sdim}
210234287Sdim
211234287Sdimvoid AnalysisDeclContext::dumpCFG(bool ShowColors) {
212234287Sdim    getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
213234287Sdim}
214234287Sdim
215234287SdimParentMap &AnalysisDeclContext::getParentMap() {
216239462Sdim  if (!PM) {
217234287Sdim    PM.reset(new ParentMap(getBody()));
218239462Sdim    if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
219239462Sdim      for (CXXConstructorDecl::init_const_iterator I = C->init_begin(),
220239462Sdim                                                   E = C->init_end();
221239462Sdim           I != E; ++I) {
222239462Sdim        PM->addStmt((*I)->getInit());
223239462Sdim      }
224239462Sdim    }
225239462Sdim  }
226234287Sdim  return *PM;
227234287Sdim}
228234287Sdim
229234287SdimPseudoConstantAnalysis *AnalysisDeclContext::getPseudoConstantAnalysis() {
230234287Sdim  if (!PCA)
231234287Sdim    PCA.reset(new PseudoConstantAnalysis(getBody()));
232234287Sdim  return PCA.get();
233234287Sdim}
234234287Sdim
235239462SdimAnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
236243830Sdim  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
237243830Sdim    // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
238243830Sdim    // that has the body.
239243830Sdim    FD->hasBody(FD);
240243830Sdim    D = FD;
241243830Sdim  }
242243830Sdim
243234287Sdim  AnalysisDeclContext *&AC = Contexts[D];
244234287Sdim  if (!AC)
245239462Sdim    AC = new AnalysisDeclContext(this, D, cfgBuildOptions);
246234287Sdim  return AC;
247234287Sdim}
248234287Sdim
249234287Sdimconst StackFrameContext *
250234287SdimAnalysisDeclContext::getStackFrame(LocationContext const *Parent, const Stmt *S,
251234287Sdim                               const CFGBlock *Blk, unsigned Idx) {
252234287Sdim  return getLocationContextManager().getStackFrame(this, Parent, S, Blk, Idx);
253234287Sdim}
254234287Sdim
255239462Sdimconst BlockInvocationContext *
256239462SdimAnalysisDeclContext::getBlockInvocationContext(const LocationContext *parent,
257239462Sdim                                               const clang::BlockDecl *BD,
258239462Sdim                                               const void *ContextData) {
259239462Sdim  return getLocationContextManager().getBlockInvocationContext(this, parent,
260239462Sdim                                                               BD, ContextData);
261239462Sdim}
262239462Sdim
263234287SdimLocationContextManager & AnalysisDeclContext::getLocationContextManager() {
264234287Sdim  assert(Manager &&
265234287Sdim         "Cannot create LocationContexts without an AnalysisDeclContextManager!");
266234287Sdim  return Manager->getLocationContextManager();
267234287Sdim}
268234287Sdim
269234287Sdim//===----------------------------------------------------------------------===//
270234287Sdim// FoldingSet profiling.
271234287Sdim//===----------------------------------------------------------------------===//
272234287Sdim
273234287Sdimvoid LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
274234287Sdim                                    ContextKind ck,
275234287Sdim                                    AnalysisDeclContext *ctx,
276234287Sdim                                    const LocationContext *parent,
277234287Sdim                                    const void *data) {
278234287Sdim  ID.AddInteger(ck);
279234287Sdim  ID.AddPointer(ctx);
280234287Sdim  ID.AddPointer(parent);
281234287Sdim  ID.AddPointer(data);
282234287Sdim}
283234287Sdim
284234287Sdimvoid StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
285234287Sdim  Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block, Index);
286234287Sdim}
287234287Sdim
288234287Sdimvoid ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
289234287Sdim  Profile(ID, getAnalysisDeclContext(), getParent(), Enter);
290234287Sdim}
291234287Sdim
292234287Sdimvoid BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
293239462Sdim  Profile(ID, getAnalysisDeclContext(), getParent(), BD, ContextData);
294234287Sdim}
295234287Sdim
296234287Sdim//===----------------------------------------------------------------------===//
297234287Sdim// LocationContext creation.
298234287Sdim//===----------------------------------------------------------------------===//
299234287Sdim
300234287Sdimtemplate <typename LOC, typename DATA>
301234287Sdimconst LOC*
302234287SdimLocationContextManager::getLocationContext(AnalysisDeclContext *ctx,
303234287Sdim                                           const LocationContext *parent,
304234287Sdim                                           const DATA *d) {
305234287Sdim  llvm::FoldingSetNodeID ID;
306234287Sdim  LOC::Profile(ID, ctx, parent, d);
307234287Sdim  void *InsertPos;
308234287Sdim
309234287Sdim  LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
310234287Sdim
311234287Sdim  if (!L) {
312234287Sdim    L = new LOC(ctx, parent, d);
313234287Sdim    Contexts.InsertNode(L, InsertPos);
314234287Sdim  }
315234287Sdim  return L;
316234287Sdim}
317234287Sdim
318234287Sdimconst StackFrameContext*
319234287SdimLocationContextManager::getStackFrame(AnalysisDeclContext *ctx,
320234287Sdim                                      const LocationContext *parent,
321234287Sdim                                      const Stmt *s,
322234287Sdim                                      const CFGBlock *blk, unsigned idx) {
323234287Sdim  llvm::FoldingSetNodeID ID;
324234287Sdim  StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
325234287Sdim  void *InsertPos;
326234287Sdim  StackFrameContext *L =
327234287Sdim   cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
328234287Sdim  if (!L) {
329234287Sdim    L = new StackFrameContext(ctx, parent, s, blk, idx);
330234287Sdim    Contexts.InsertNode(L, InsertPos);
331234287Sdim  }
332234287Sdim  return L;
333234287Sdim}
334234287Sdim
335234287Sdimconst ScopeContext *
336234287SdimLocationContextManager::getScope(AnalysisDeclContext *ctx,
337234287Sdim                                 const LocationContext *parent,
338234287Sdim                                 const Stmt *s) {
339234287Sdim  return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
340234287Sdim}
341234287Sdim
342239462Sdimconst BlockInvocationContext *
343239462SdimLocationContextManager::getBlockInvocationContext(AnalysisDeclContext *ctx,
344239462Sdim                                                  const LocationContext *parent,
345239462Sdim                                                  const BlockDecl *BD,
346239462Sdim                                                  const void *ContextData) {
347239462Sdim  llvm::FoldingSetNodeID ID;
348239462Sdim  BlockInvocationContext::Profile(ID, ctx, parent, BD, ContextData);
349239462Sdim  void *InsertPos;
350239462Sdim  BlockInvocationContext *L =
351239462Sdim    cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
352239462Sdim                                                                    InsertPos));
353239462Sdim  if (!L) {
354239462Sdim    L = new BlockInvocationContext(ctx, parent, BD, ContextData);
355239462Sdim    Contexts.InsertNode(L, InsertPos);
356239462Sdim  }
357239462Sdim  return L;
358239462Sdim}
359239462Sdim
360234287Sdim//===----------------------------------------------------------------------===//
361234287Sdim// LocationContext methods.
362234287Sdim//===----------------------------------------------------------------------===//
363234287Sdim
364234287Sdimconst StackFrameContext *LocationContext::getCurrentStackFrame() const {
365234287Sdim  const LocationContext *LC = this;
366234287Sdim  while (LC) {
367234287Sdim    if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC))
368234287Sdim      return SFC;
369234287Sdim    LC = LC->getParent();
370234287Sdim  }
371234287Sdim  return NULL;
372234287Sdim}
373234287Sdim
374243830Sdimbool LocationContext::inTopFrame() const {
375243830Sdim  return getCurrentStackFrame()->inTopFrame();
376243830Sdim}
377243830Sdim
378234287Sdimbool LocationContext::isParentOf(const LocationContext *LC) const {
379234287Sdim  do {
380234287Sdim    const LocationContext *Parent = LC->getParent();
381234287Sdim    if (Parent == this)
382234287Sdim      return true;
383234287Sdim    else
384234287Sdim      LC = Parent;
385234287Sdim  } while (LC);
386234287Sdim
387234287Sdim  return false;
388234287Sdim}
389234287Sdim
390249423Sdimvoid LocationContext::dumpStack() const {
391249423Sdim  ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
392249423Sdim  PrintingPolicy PP(Ctx.getLangOpts());
393249423Sdim  PP.TerseOutput = 1;
394249423Sdim
395249423Sdim  unsigned Frame = 0;
396249423Sdim  for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
397249423Sdim    switch (LCtx->getKind()) {
398249423Sdim    case StackFrame:
399249423Sdim      llvm::errs() << '#' << Frame++ << ' ';
400249423Sdim      cast<StackFrameContext>(LCtx)->getDecl()->print(llvm::errs(), PP);
401249423Sdim      llvm::errs() << '\n';
402249423Sdim      break;
403249423Sdim    case Scope:
404249423Sdim      llvm::errs() << "    (scope)\n";
405249423Sdim      break;
406249423Sdim    case Block:
407249423Sdim      llvm::errs() << "    (block context: "
408249423Sdim                   << cast<BlockInvocationContext>(LCtx)->getContextData()
409249423Sdim                   << ")\n";
410249423Sdim      break;
411249423Sdim    }
412249423Sdim  }
413249423Sdim}
414249423Sdim
415234287Sdim//===----------------------------------------------------------------------===//
416234287Sdim// Lazily generated map to query the external variables referenced by a Block.
417234287Sdim//===----------------------------------------------------------------------===//
418234287Sdim
419234287Sdimnamespace {
420234287Sdimclass FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
421234287Sdim  BumpVector<const VarDecl*> &BEVals;
422234287Sdim  BumpVectorContext &BC;
423234287Sdim  llvm::SmallPtrSet<const VarDecl*, 4> Visited;
424234287Sdim  llvm::SmallPtrSet<const DeclContext*, 4> IgnoredContexts;
425234287Sdimpublic:
426234287Sdim  FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
427234287Sdim                            BumpVectorContext &bc)
428234287Sdim  : BEVals(bevals), BC(bc) {}
429234287Sdim
430234287Sdim  bool IsTrackedDecl(const VarDecl *VD) {
431234287Sdim    const DeclContext *DC = VD->getDeclContext();
432234287Sdim    return IgnoredContexts.count(DC) == 0;
433234287Sdim  }
434234287Sdim
435234287Sdim  void VisitStmt(Stmt *S) {
436234287Sdim    for (Stmt::child_range I = S->children(); I; ++I)
437234287Sdim      if (Stmt *child = *I)
438234287Sdim        Visit(child);
439234287Sdim  }
440234287Sdim
441234287Sdim  void VisitDeclRefExpr(DeclRefExpr *DR) {
442234287Sdim    // Non-local variables are also directly modified.
443234287Sdim    if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
444234287Sdim      if (!VD->hasLocalStorage()) {
445234287Sdim        if (Visited.insert(VD))
446234287Sdim          BEVals.push_back(VD, BC);
447234287Sdim      }
448234287Sdim    }
449234287Sdim  }
450234287Sdim
451234287Sdim  void VisitBlockExpr(BlockExpr *BR) {
452234287Sdim    // Blocks containing blocks can transitively capture more variables.
453234287Sdim    IgnoredContexts.insert(BR->getBlockDecl());
454234287Sdim    Visit(BR->getBlockDecl()->getBody());
455234287Sdim  }
456234287Sdim
457234287Sdim  void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
458234287Sdim    for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
459234287Sdim         et = PE->semantics_end(); it != et; ++it) {
460234287Sdim      Expr *Semantic = *it;
461234287Sdim      if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
462234287Sdim        Semantic = OVE->getSourceExpr();
463234287Sdim      Visit(Semantic);
464234287Sdim    }
465234287Sdim  }
466234287Sdim};
467234287Sdim} // end anonymous namespace
468234287Sdim
469234287Sdimtypedef BumpVector<const VarDecl*> DeclVec;
470234287Sdim
471234287Sdimstatic DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
472234287Sdim                                              void *&Vec,
473234287Sdim                                              llvm::BumpPtrAllocator &A) {
474234287Sdim  if (Vec)
475234287Sdim    return (DeclVec*) Vec;
476234287Sdim
477234287Sdim  BumpVectorContext BC(A);
478234287Sdim  DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
479234287Sdim  new (BV) DeclVec(BC, 10);
480234287Sdim
481249423Sdim  // Go through the capture list.
482249423Sdim  for (BlockDecl::capture_const_iterator CI = BD->capture_begin(),
483249423Sdim       CE = BD->capture_end(); CI != CE; ++CI) {
484249423Sdim    BV->push_back(CI->getVariable(), BC);
485249423Sdim  }
486249423Sdim
487249423Sdim  // Find the referenced global/static variables.
488234287Sdim  FindBlockDeclRefExprsVals F(*BV, BC);
489234287Sdim  F.Visit(BD->getBody());
490234287Sdim
491234287Sdim  Vec = BV;
492234287Sdim  return BV;
493234287Sdim}
494234287Sdim
495234287Sdimstd::pair<AnalysisDeclContext::referenced_decls_iterator,
496234287Sdim          AnalysisDeclContext::referenced_decls_iterator>
497234287SdimAnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
498234287Sdim  if (!ReferencedBlockVars)
499234287Sdim    ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
500234287Sdim
501234287Sdim  DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
502234287Sdim  return std::make_pair(V->begin(), V->end());
503234287Sdim}
504234287Sdim
505234287SdimManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(const void *tag) {
506234287Sdim  if (!ManagedAnalyses)
507234287Sdim    ManagedAnalyses = new ManagedAnalysisMap();
508234287Sdim  ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
509234287Sdim  return (*M)[tag];
510234287Sdim}
511234287Sdim
512234287Sdim//===----------------------------------------------------------------------===//
513234287Sdim// Cleanup.
514234287Sdim//===----------------------------------------------------------------------===//
515234287Sdim
516234287SdimManagedAnalysis::~ManagedAnalysis() {}
517234287Sdim
518234287SdimAnalysisDeclContext::~AnalysisDeclContext() {
519234287Sdim  delete forcedBlkExprs;
520234287Sdim  delete ReferencedBlockVars;
521234287Sdim  // Release the managed analyses.
522234287Sdim  if (ManagedAnalyses) {
523234287Sdim    ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
524234287Sdim    for (ManagedAnalysisMap::iterator I = M->begin(), E = M->end(); I!=E; ++I)
525234287Sdim      delete I->second;
526234287Sdim    delete M;
527234287Sdim  }
528234287Sdim}
529234287Sdim
530234287SdimAnalysisDeclContextManager::~AnalysisDeclContextManager() {
531234287Sdim  for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
532234287Sdim    delete I->second;
533234287Sdim}
534234287Sdim
535234287SdimLocationContext::~LocationContext() {}
536234287Sdim
537234287SdimLocationContextManager::~LocationContextManager() {
538234287Sdim  clear();
539234287Sdim}
540234287Sdim
541234287Sdimvoid LocationContextManager::clear() {
542234287Sdim  for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
543234287Sdim       E = Contexts.end(); I != E; ) {
544234287Sdim    LocationContext *LC = &*I;
545234287Sdim    ++I;
546234287Sdim    delete LC;
547234287Sdim  }
548234287Sdim
549234287Sdim  Contexts.clear();
550234287Sdim}
551234287Sdim
552