clang API Documentation
00001 //== AnalysisDeclContext.cpp - Analysis context for Path Sens analysis -*- C++ -*-// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines AnalysisDeclContext, a class that manages the analysis context 00011 // data for path sensitive analysis. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "clang/AST/Decl.h" 00016 #include "clang/AST/DeclObjC.h" 00017 #include "clang/AST/DeclTemplate.h" 00018 #include "clang/AST/ParentMap.h" 00019 #include "clang/AST/StmtVisitor.h" 00020 #include "clang/Analysis/Analyses/LiveVariables.h" 00021 #include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" 00022 #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 00023 #include "clang/Analysis/AnalysisContext.h" 00024 #include "clang/Analysis/CFG.h" 00025 #include "clang/Analysis/CFGStmtMap.h" 00026 #include "clang/Analysis/Support/BumpVector.h" 00027 #include "llvm/Support/SaveAndRestore.h" 00028 #include "llvm/ADT/SmallPtrSet.h" 00029 #include "llvm/Support/ErrorHandling.h" 00030 00031 using namespace clang; 00032 00033 typedef llvm::DenseMap<const void *, ManagedAnalysis *> ManagedAnalysisMap; 00034 00035 AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr, 00036 const Decl *d, 00037 const CFG::BuildOptions &buildOptions) 00038 : Manager(Mgr), 00039 D(d), 00040 cfgBuildOptions(buildOptions), 00041 forcedBlkExprs(0), 00042 builtCFG(false), 00043 builtCompleteCFG(false), 00044 ReferencedBlockVars(0), 00045 ManagedAnalyses(0) 00046 { 00047 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; 00048 } 00049 00050 AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr, 00051 const Decl *d) 00052 : Manager(Mgr), 00053 D(d), 00054 forcedBlkExprs(0), 00055 builtCFG(false), 00056 builtCompleteCFG(false), 00057 ReferencedBlockVars(0), 00058 ManagedAnalyses(0) 00059 { 00060 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; 00061 } 00062 00063 AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG, 00064 bool addImplicitDtors, 00065 bool addInitializers) { 00066 cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG; 00067 cfgBuildOptions.AddImplicitDtors = addImplicitDtors; 00068 cfgBuildOptions.AddInitializers = addInitializers; 00069 } 00070 00071 void AnalysisDeclContextManager::clear() { 00072 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I) 00073 delete I->second; 00074 Contexts.clear(); 00075 } 00076 00077 Stmt *AnalysisDeclContext::getBody() const { 00078 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 00079 return FD->getBody(); 00080 else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 00081 return MD->getBody(); 00082 else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) 00083 return BD->getBody(); 00084 else if (const FunctionTemplateDecl *FunTmpl 00085 = dyn_cast_or_null<FunctionTemplateDecl>(D)) 00086 return FunTmpl->getTemplatedDecl()->getBody(); 00087 00088 llvm_unreachable("unknown code decl"); 00089 } 00090 00091 const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const { 00092 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 00093 return MD->getSelfDecl(); 00094 if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { 00095 // See if 'self' was captured by the block. 00096 for (BlockDecl::capture_const_iterator it = BD->capture_begin(), 00097 et = BD->capture_end(); it != et; ++it) { 00098 const VarDecl *VD = it->getVariable(); 00099 if (VD->getName() == "self") 00100 return dyn_cast<ImplicitParamDecl>(VD); 00101 } 00102 } 00103 00104 return NULL; 00105 } 00106 00107 void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) { 00108 if (!forcedBlkExprs) 00109 forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs(); 00110 // Default construct an entry for 'stmt'. 00111 if (const Expr *e = dyn_cast<Expr>(stmt)) 00112 stmt = e->IgnoreParens(); 00113 (void) (*forcedBlkExprs)[stmt]; 00114 } 00115 00116 const CFGBlock * 00117 AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) { 00118 assert(forcedBlkExprs); 00119 if (const Expr *e = dyn_cast<Expr>(stmt)) 00120 stmt = e->IgnoreParens(); 00121 CFG::BuildOptions::ForcedBlkExprs::const_iterator itr = 00122 forcedBlkExprs->find(stmt); 00123 assert(itr != forcedBlkExprs->end()); 00124 return itr->second; 00125 } 00126 00127 CFG *AnalysisDeclContext::getCFG() { 00128 if (!cfgBuildOptions.PruneTriviallyFalseEdges) 00129 return getUnoptimizedCFG(); 00130 00131 if (!builtCFG) { 00132 cfg.reset(CFG::buildCFG(D, getBody(), 00133 &D->getASTContext(), cfgBuildOptions)); 00134 // Even when the cfg is not successfully built, we don't 00135 // want to try building it again. 00136 builtCFG = true; 00137 } 00138 return cfg.get(); 00139 } 00140 00141 CFG *AnalysisDeclContext::getUnoptimizedCFG() { 00142 if (!builtCompleteCFG) { 00143 SaveAndRestore<bool> NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges, 00144 false); 00145 completeCFG.reset(CFG::buildCFG(D, getBody(), &D->getASTContext(), 00146 cfgBuildOptions)); 00147 // Even when the cfg is not successfully built, we don't 00148 // want to try building it again. 00149 builtCompleteCFG = true; 00150 } 00151 return completeCFG.get(); 00152 } 00153 00154 CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() { 00155 if (cfgStmtMap) 00156 return cfgStmtMap.get(); 00157 00158 if (CFG *c = getCFG()) { 00159 cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap())); 00160 return cfgStmtMap.get(); 00161 } 00162 00163 return 0; 00164 } 00165 00166 CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() { 00167 if (CFA) 00168 return CFA.get(); 00169 00170 if (CFG *c = getCFG()) { 00171 CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c)); 00172 return CFA.get(); 00173 } 00174 00175 return 0; 00176 } 00177 00178 void AnalysisDeclContext::dumpCFG(bool ShowColors) { 00179 getCFG()->dump(getASTContext().getLangOpts(), ShowColors); 00180 } 00181 00182 ParentMap &AnalysisDeclContext::getParentMap() { 00183 if (!PM) 00184 PM.reset(new ParentMap(getBody())); 00185 return *PM; 00186 } 00187 00188 PseudoConstantAnalysis *AnalysisDeclContext::getPseudoConstantAnalysis() { 00189 if (!PCA) 00190 PCA.reset(new PseudoConstantAnalysis(getBody())); 00191 return PCA.get(); 00192 } 00193 00194 AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) { 00195 AnalysisDeclContext *&AC = Contexts[D]; 00196 if (!AC) 00197 AC = new AnalysisDeclContext(this, D, cfgBuildOptions); 00198 return AC; 00199 } 00200 00201 const StackFrameContext * 00202 AnalysisDeclContext::getStackFrame(LocationContext const *Parent, const Stmt *S, 00203 const CFGBlock *Blk, unsigned Idx) { 00204 return getLocationContextManager().getStackFrame(this, Parent, S, Blk, Idx); 00205 } 00206 00207 LocationContextManager & AnalysisDeclContext::getLocationContextManager() { 00208 assert(Manager && 00209 "Cannot create LocationContexts without an AnalysisDeclContextManager!"); 00210 return Manager->getLocationContextManager(); 00211 } 00212 00213 //===----------------------------------------------------------------------===// 00214 // FoldingSet profiling. 00215 //===----------------------------------------------------------------------===// 00216 00217 void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID, 00218 ContextKind ck, 00219 AnalysisDeclContext *ctx, 00220 const LocationContext *parent, 00221 const void *data) { 00222 ID.AddInteger(ck); 00223 ID.AddPointer(ctx); 00224 ID.AddPointer(parent); 00225 ID.AddPointer(data); 00226 } 00227 00228 void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) { 00229 Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block, Index); 00230 } 00231 00232 void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) { 00233 Profile(ID, getAnalysisDeclContext(), getParent(), Enter); 00234 } 00235 00236 void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) { 00237 Profile(ID, getAnalysisDeclContext(), getParent(), BD); 00238 } 00239 00240 //===----------------------------------------------------------------------===// 00241 // LocationContext creation. 00242 //===----------------------------------------------------------------------===// 00243 00244 template <typename LOC, typename DATA> 00245 const LOC* 00246 LocationContextManager::getLocationContext(AnalysisDeclContext *ctx, 00247 const LocationContext *parent, 00248 const DATA *d) { 00249 llvm::FoldingSetNodeID ID; 00250 LOC::Profile(ID, ctx, parent, d); 00251 void *InsertPos; 00252 00253 LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos)); 00254 00255 if (!L) { 00256 L = new LOC(ctx, parent, d); 00257 Contexts.InsertNode(L, InsertPos); 00258 } 00259 return L; 00260 } 00261 00262 const StackFrameContext* 00263 LocationContextManager::getStackFrame(AnalysisDeclContext *ctx, 00264 const LocationContext *parent, 00265 const Stmt *s, 00266 const CFGBlock *blk, unsigned idx) { 00267 llvm::FoldingSetNodeID ID; 00268 StackFrameContext::Profile(ID, ctx, parent, s, blk, idx); 00269 void *InsertPos; 00270 StackFrameContext *L = 00271 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos)); 00272 if (!L) { 00273 L = new StackFrameContext(ctx, parent, s, blk, idx); 00274 Contexts.InsertNode(L, InsertPos); 00275 } 00276 return L; 00277 } 00278 00279 const ScopeContext * 00280 LocationContextManager::getScope(AnalysisDeclContext *ctx, 00281 const LocationContext *parent, 00282 const Stmt *s) { 00283 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s); 00284 } 00285 00286 //===----------------------------------------------------------------------===// 00287 // LocationContext methods. 00288 //===----------------------------------------------------------------------===// 00289 00290 const StackFrameContext *LocationContext::getCurrentStackFrame() const { 00291 const LocationContext *LC = this; 00292 while (LC) { 00293 if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) 00294 return SFC; 00295 LC = LC->getParent(); 00296 } 00297 return NULL; 00298 } 00299 00300 const StackFrameContext * 00301 LocationContext::getStackFrameForDeclContext(const DeclContext *DC) const { 00302 const LocationContext *LC = this; 00303 while (LC) { 00304 if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) { 00305 if (cast<DeclContext>(SFC->getDecl()) == DC) 00306 return SFC; 00307 } 00308 LC = LC->getParent(); 00309 } 00310 return NULL; 00311 } 00312 00313 bool LocationContext::isParentOf(const LocationContext *LC) const { 00314 do { 00315 const LocationContext *Parent = LC->getParent(); 00316 if (Parent == this) 00317 return true; 00318 else 00319 LC = Parent; 00320 } while (LC); 00321 00322 return false; 00323 } 00324 00325 //===----------------------------------------------------------------------===// 00326 // Lazily generated map to query the external variables referenced by a Block. 00327 //===----------------------------------------------------------------------===// 00328 00329 namespace { 00330 class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{ 00331 BumpVector<const VarDecl*> &BEVals; 00332 BumpVectorContext &BC; 00333 llvm::SmallPtrSet<const VarDecl*, 4> Visited; 00334 llvm::SmallPtrSet<const DeclContext*, 4> IgnoredContexts; 00335 public: 00336 FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals, 00337 BumpVectorContext &bc) 00338 : BEVals(bevals), BC(bc) {} 00339 00340 bool IsTrackedDecl(const VarDecl *VD) { 00341 const DeclContext *DC = VD->getDeclContext(); 00342 return IgnoredContexts.count(DC) == 0; 00343 } 00344 00345 void VisitStmt(Stmt *S) { 00346 for (Stmt::child_range I = S->children(); I; ++I) 00347 if (Stmt *child = *I) 00348 Visit(child); 00349 } 00350 00351 void VisitDeclRefExpr(DeclRefExpr *DR) { 00352 // Non-local variables are also directly modified. 00353 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 00354 if (!VD->hasLocalStorage()) { 00355 if (Visited.insert(VD)) 00356 BEVals.push_back(VD, BC); 00357 } else if (DR->refersToEnclosingLocal()) { 00358 if (Visited.insert(VD) && IsTrackedDecl(VD)) 00359 BEVals.push_back(VD, BC); 00360 } 00361 } 00362 } 00363 00364 void VisitBlockExpr(BlockExpr *BR) { 00365 // Blocks containing blocks can transitively capture more variables. 00366 IgnoredContexts.insert(BR->getBlockDecl()); 00367 Visit(BR->getBlockDecl()->getBody()); 00368 } 00369 00370 void VisitPseudoObjectExpr(PseudoObjectExpr *PE) { 00371 for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(), 00372 et = PE->semantics_end(); it != et; ++it) { 00373 Expr *Semantic = *it; 00374 if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic)) 00375 Semantic = OVE->getSourceExpr(); 00376 Visit(Semantic); 00377 } 00378 } 00379 }; 00380 } // end anonymous namespace 00381 00382 typedef BumpVector<const VarDecl*> DeclVec; 00383 00384 static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD, 00385 void *&Vec, 00386 llvm::BumpPtrAllocator &A) { 00387 if (Vec) 00388 return (DeclVec*) Vec; 00389 00390 BumpVectorContext BC(A); 00391 DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>(); 00392 new (BV) DeclVec(BC, 10); 00393 00394 // Find the referenced variables. 00395 FindBlockDeclRefExprsVals F(*BV, BC); 00396 F.Visit(BD->getBody()); 00397 00398 Vec = BV; 00399 return BV; 00400 } 00401 00402 std::pair<AnalysisDeclContext::referenced_decls_iterator, 00403 AnalysisDeclContext::referenced_decls_iterator> 00404 AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) { 00405 if (!ReferencedBlockVars) 00406 ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>(); 00407 00408 DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A); 00409 return std::make_pair(V->begin(), V->end()); 00410 } 00411 00412 ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(const void *tag) { 00413 if (!ManagedAnalyses) 00414 ManagedAnalyses = new ManagedAnalysisMap(); 00415 ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses; 00416 return (*M)[tag]; 00417 } 00418 00419 //===----------------------------------------------------------------------===// 00420 // Cleanup. 00421 //===----------------------------------------------------------------------===// 00422 00423 ManagedAnalysis::~ManagedAnalysis() {} 00424 00425 AnalysisDeclContext::~AnalysisDeclContext() { 00426 delete forcedBlkExprs; 00427 delete ReferencedBlockVars; 00428 // Release the managed analyses. 00429 if (ManagedAnalyses) { 00430 ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses; 00431 for (ManagedAnalysisMap::iterator I = M->begin(), E = M->end(); I!=E; ++I) 00432 delete I->second; 00433 delete M; 00434 } 00435 } 00436 00437 AnalysisDeclContextManager::~AnalysisDeclContextManager() { 00438 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I) 00439 delete I->second; 00440 } 00441 00442 LocationContext::~LocationContext() {} 00443 00444 LocationContextManager::~LocationContextManager() { 00445 clear(); 00446 } 00447 00448 void LocationContextManager::clear() { 00449 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(), 00450 E = Contexts.end(); I != E; ) { 00451 LocationContext *LC = &*I; 00452 ++I; 00453 delete LC; 00454 } 00455 00456 Contexts.clear(); 00457 } 00458