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