1 //== AnalysisContext.cpp - Analysis context for Path Sens analysis -*- C++ -*-// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines AnalysisContext, a class that manages the analysis context 11 // data for path sensitive analysis. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "clang/AST/Decl.h" 16 #include "clang/AST/DeclObjC.h" 17 #include "clang/AST/DeclTemplate.h" 18 #include "clang/AST/ParentMap.h" 19 #include "clang/AST/StmtVisitor.h" 20 #include "clang/Analysis/Analyses/LiveVariables.h" 21 #include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" 22 #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h" 23 #include "clang/Analysis/AnalysisContext.h" 24 #include "clang/Analysis/CFG.h" 25 #include "clang/Analysis/CFGStmtMap.h" 26 #include "clang/Analysis/Support/BumpVector.h" 27 #include "clang/Analysis/Support/SaveAndRestore.h" 28 #include "llvm/ADT/SmallSet.h" 29 #include "llvm/Support/ErrorHandling.h" 30 31 using namespace clang; 32 33 typedef llvm::DenseMap<const void *, ManagedAnalysis *> ManagedAnalysisMap; 34 35 AnalysisContext::AnalysisContext(const Decl *d, 36 idx::TranslationUnit *tu, 37 const CFG::BuildOptions &buildOptions) 38 : D(d), TU(tu), 39 cfgBuildOptions(buildOptions), 40 forcedBlkExprs(0), 41 builtCFG(false), 42 builtCompleteCFG(false), 43 ReferencedBlockVars(0), 44 ManagedAnalyses(0) 45 { 46 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; 47 } 48 49 AnalysisContext::AnalysisContext(const Decl *d, 50 idx::TranslationUnit *tu) 51 : D(d), TU(tu), 52 forcedBlkExprs(0), 53 builtCFG(false), 54 builtCompleteCFG(false), 55 ReferencedBlockVars(0), 56 ManagedAnalyses(0) 57 { 58 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; 59 } 60 61 AnalysisContextManager::AnalysisContextManager(bool useUnoptimizedCFG, 62 bool addImplicitDtors, 63 bool addInitializers) { 64 cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG; 65 cfgBuildOptions.AddImplicitDtors = addImplicitDtors; 66 cfgBuildOptions.AddInitializers = addInitializers; 67 } 68 69 void AnalysisContextManager::clear() { 70 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I) 71 delete I->second; 72 Contexts.clear(); 73 } 74 75 Stmt *AnalysisContext::getBody() const { 76 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) 77 return FD->getBody(); 78 else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 79 return MD->getBody(); 80 else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) 81 return BD->getBody(); 82 else if (const FunctionTemplateDecl *FunTmpl 83 = dyn_cast_or_null<FunctionTemplateDecl>(D)) 84 return FunTmpl->getTemplatedDecl()->getBody(); 85 86 llvm_unreachable("unknown code decl"); 87 } 88 89 const ImplicitParamDecl *AnalysisContext::getSelfDecl() const { 90 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) 91 return MD->getSelfDecl(); 92 93 return NULL; 94 } 95 96 void AnalysisContext::registerForcedBlockExpression(const Stmt *stmt) { 97 if (!forcedBlkExprs) 98 forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs(); 99 // Default construct an entry for 'stmt'. 100 if (const Expr *e = dyn_cast<Expr>(stmt)) 101 stmt = e->IgnoreParens(); 102 (void) (*forcedBlkExprs)[stmt]; 103 } 104 105 const CFGBlock * 106 AnalysisContext::getBlockForRegisteredExpression(const Stmt *stmt) { 107 assert(forcedBlkExprs); 108 if (const Expr *e = dyn_cast<Expr>(stmt)) 109 stmt = e->IgnoreParens(); 110 CFG::BuildOptions::ForcedBlkExprs::const_iterator itr = 111 forcedBlkExprs->find(stmt); 112 assert(itr != forcedBlkExprs->end()); 113 return itr->second; 114 } 115 116 CFG *AnalysisContext::getCFG() { 117 if (!cfgBuildOptions.PruneTriviallyFalseEdges) 118 return getUnoptimizedCFG(); 119 120 if (!builtCFG) { 121 cfg.reset(CFG::buildCFG(D, getBody(), 122 &D->getASTContext(), cfgBuildOptions)); 123 // Even when the cfg is not successfully built, we don't 124 // want to try building it again. 125 builtCFG = true; 126 } 127 return cfg.get(); 128 } 129 130 CFG *AnalysisContext::getUnoptimizedCFG() { 131 if (!builtCompleteCFG) { 132 SaveAndRestore<bool> NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges, 133 false); 134 completeCFG.reset(CFG::buildCFG(D, getBody(), &D->getASTContext(), 135 cfgBuildOptions)); 136 // Even when the cfg is not successfully built, we don't 137 // want to try building it again. 138 builtCompleteCFG = true; 139 } 140 return completeCFG.get(); 141 } 142 143 CFGStmtMap *AnalysisContext::getCFGStmtMap() { 144 if (cfgStmtMap) 145 return cfgStmtMap.get(); 146 147 if (CFG *c = getCFG()) { 148 cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap())); 149 return cfgStmtMap.get(); 150 } 151 152 return 0; 153 } 154 155 CFGReverseBlockReachabilityAnalysis *AnalysisContext::getCFGReachablityAnalysis() { 156 if (CFA) 157 return CFA.get(); 158 159 if (CFG *c = getCFG()) { 160 CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c)); 161 return CFA.get(); 162 } 163 164 return 0; 165 } 166 167 void AnalysisContext::dumpCFG() { 168 getCFG()->dump(getASTContext().getLangOptions()); 169 } 170 171 ParentMap &AnalysisContext::getParentMap() { 172 if (!PM) 173 PM.reset(new ParentMap(getBody())); 174 return *PM; 175 } 176 177 PseudoConstantAnalysis *AnalysisContext::getPseudoConstantAnalysis() { 178 if (!PCA) 179 PCA.reset(new PseudoConstantAnalysis(getBody())); 180 return PCA.get(); 181 } 182 183 AnalysisContext *AnalysisContextManager::getContext(const Decl *D, 184 idx::TranslationUnit *TU) { 185 AnalysisContext *&AC = Contexts[D]; 186 if (!AC) 187 AC = new AnalysisContext(D, TU, cfgBuildOptions); 188 return AC; 189 } 190 191 //===----------------------------------------------------------------------===// 192 // FoldingSet profiling. 193 //===----------------------------------------------------------------------===// 194 195 void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID, 196 ContextKind ck, 197 AnalysisContext *ctx, 198 const LocationContext *parent, 199 const void *data) { 200 ID.AddInteger(ck); 201 ID.AddPointer(ctx); 202 ID.AddPointer(parent); 203 ID.AddPointer(data); 204 } 205 206 void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) { 207 Profile(ID, getAnalysisContext(), getParent(), CallSite, Block, Index); 208 } 209 210 void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) { 211 Profile(ID, getAnalysisContext(), getParent(), Enter); 212 } 213 214 void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) { 215 Profile(ID, getAnalysisContext(), getParent(), BD); 216 } 217 218 //===----------------------------------------------------------------------===// 219 // LocationContext creation. 220 //===----------------------------------------------------------------------===// 221 222 template <typename LOC, typename DATA> 223 const LOC* 224 LocationContextManager::getLocationContext(AnalysisContext *ctx, 225 const LocationContext *parent, 226 const DATA *d) { 227 llvm::FoldingSetNodeID ID; 228 LOC::Profile(ID, ctx, parent, d); 229 void *InsertPos; 230 231 LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos)); 232 233 if (!L) { 234 L = new LOC(ctx, parent, d); 235 Contexts.InsertNode(L, InsertPos); 236 } 237 return L; 238 } 239 240 const StackFrameContext* 241 LocationContextManager::getStackFrame(AnalysisContext *ctx, 242 const LocationContext *parent, 243 const Stmt *s, 244 const CFGBlock *blk, unsigned idx) { 245 llvm::FoldingSetNodeID ID; 246 StackFrameContext::Profile(ID, ctx, parent, s, blk, idx); 247 void *InsertPos; 248 StackFrameContext *L = 249 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos)); 250 if (!L) { 251 L = new StackFrameContext(ctx, parent, s, blk, idx); 252 Contexts.InsertNode(L, InsertPos); 253 } 254 return L; 255 } 256 257 const ScopeContext * 258 LocationContextManager::getScope(AnalysisContext *ctx, 259 const LocationContext *parent, 260 const Stmt *s) { 261 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s); 262 } 263 264 //===----------------------------------------------------------------------===// 265 // LocationContext methods. 266 //===----------------------------------------------------------------------===// 267 268 const StackFrameContext *LocationContext::getCurrentStackFrame() const { 269 const LocationContext *LC = this; 270 while (LC) { 271 if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) 272 return SFC; 273 LC = LC->getParent(); 274 } 275 return NULL; 276 } 277 278 const StackFrameContext * 279 LocationContext::getStackFrameForDeclContext(const DeclContext *DC) const { 280 const LocationContext *LC = this; 281 while (LC) { 282 if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) { 283 if (cast<DeclContext>(SFC->getDecl()) == DC) 284 return SFC; 285 } 286 LC = LC->getParent(); 287 } 288 return NULL; 289 } 290 291 bool LocationContext::isParentOf(const LocationContext *LC) const { 292 do { 293 const LocationContext *Parent = LC->getParent(); 294 if (Parent == this) 295 return true; 296 else 297 LC = Parent; 298 } while (LC); 299 300 return false; 301 } 302 303 //===----------------------------------------------------------------------===// 304 // Lazily generated map to query the external variables referenced by a Block. 305 //===----------------------------------------------------------------------===// 306 307 namespace { 308 class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{ 309 BumpVector<const VarDecl*> &BEVals; 310 BumpVectorContext &BC; 311 llvm::DenseMap<const VarDecl*, unsigned> Visited; 312 llvm::SmallSet<const DeclContext*, 4> IgnoredContexts; 313 public: 314 FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals, 315 BumpVectorContext &bc) 316 : BEVals(bevals), BC(bc) {} 317 318 bool IsTrackedDecl(const VarDecl *VD) { 319 const DeclContext *DC = VD->getDeclContext(); 320 return IgnoredContexts.count(DC) == 0; 321 } 322 323 void VisitStmt(Stmt *S) { 324 for (Stmt::child_range I = S->children(); I; ++I) 325 if (Stmt *child = *I) 326 Visit(child); 327 } 328 329 void VisitDeclRefExpr(const DeclRefExpr *DR) { 330 // Non-local variables are also directly modified. 331 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) 332 if (!VD->hasLocalStorage()) { 333 unsigned &flag = Visited[VD]; 334 if (!flag) { 335 flag = 1; 336 BEVals.push_back(VD, BC); 337 } 338 } 339 } 340 341 void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) { 342 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { 343 unsigned &flag = Visited[VD]; 344 if (!flag) { 345 flag = 1; 346 if (IsTrackedDecl(VD)) 347 BEVals.push_back(VD, BC); 348 } 349 } 350 } 351 352 void VisitBlockExpr(BlockExpr *BR) { 353 // Blocks containing blocks can transitively capture more variables. 354 IgnoredContexts.insert(BR->getBlockDecl()); 355 Visit(BR->getBlockDecl()->getBody()); 356 } 357 }; 358 } // end anonymous namespace 359 360 typedef BumpVector<const VarDecl*> DeclVec; 361 362 static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD, 363 void *&Vec, 364 llvm::BumpPtrAllocator &A) { 365 if (Vec) 366 return (DeclVec*) Vec; 367 368 BumpVectorContext BC(A); 369 DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>(); 370 new (BV) DeclVec(BC, 10); 371 372 // Find the referenced variables. 373 FindBlockDeclRefExprsVals F(*BV, BC); 374 F.Visit(BD->getBody()); 375 376 Vec = BV; 377 return BV; 378 } 379 380 std::pair<AnalysisContext::referenced_decls_iterator, 381 AnalysisContext::referenced_decls_iterator> 382 AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) { 383 if (!ReferencedBlockVars) 384 ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>(); 385 386 DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A); 387 return std::make_pair(V->begin(), V->end()); 388 } 389 390 ManagedAnalysis *&AnalysisContext::getAnalysisImpl(const void *tag) { 391 if (!ManagedAnalyses) 392 ManagedAnalyses = new ManagedAnalysisMap(); 393 ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses; 394 return (*M)[tag]; 395 } 396 397 //===----------------------------------------------------------------------===// 398 // Cleanup. 399 //===----------------------------------------------------------------------===// 400 401 ManagedAnalysis::~ManagedAnalysis() {} 402 403 AnalysisContext::~AnalysisContext() { 404 delete forcedBlkExprs; 405 delete ReferencedBlockVars; 406 // Release the managed analyses. 407 if (ManagedAnalyses) { 408 ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses; 409 for (ManagedAnalysisMap::iterator I = M->begin(), E = M->end(); I!=E; ++I) 410 delete I->second; 411 delete M; 412 } 413 } 414 415 AnalysisContextManager::~AnalysisContextManager() { 416 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I) 417 delete I->second; 418 } 419 420 LocationContext::~LocationContext() {} 421 422 LocationContextManager::~LocationContextManager() { 423 clear(); 424 } 425 426 void LocationContextManager::clear() { 427 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(), 428 E = Contexts.end(); I != E; ) { 429 LocationContext *LC = &*I; 430 ++I; 431 delete LC; 432 } 433 434 Contexts.clear(); 435 } 436 437