clang API Documentation

AnalysisDeclContext.cpp
Go to the documentation of this file.
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/Analysis/AnalysisContext.h"
00016 #include "BodyFarm.h"
00017 #include "clang/AST/ASTContext.h"
00018 #include "clang/AST/Decl.h"
00019 #include "clang/AST/DeclObjC.h"
00020 #include "clang/AST/DeclTemplate.h"
00021 #include "clang/AST/ParentMap.h"
00022 #include "clang/AST/StmtVisitor.h"
00023 #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
00024 #include "clang/Analysis/Analyses/LiveVariables.h"
00025 #include "clang/Analysis/Analyses/PseudoConstantAnalysis.h"
00026 #include "clang/Analysis/CFG.h"
00027 #include "clang/Analysis/CFGStmtMap.h"
00028 #include "clang/Analysis/Support/BumpVector.h"
00029 #include "llvm/ADT/SmallPtrSet.h"
00030 #include "llvm/Support/ErrorHandling.h"
00031 #include "llvm/Support/SaveAndRestore.h"
00032 #include "llvm/Support/raw_ostream.h"
00033 
00034 using namespace clang;
00035 
00036 typedef llvm::DenseMap<const void *, ManagedAnalysis *> ManagedAnalysisMap;
00037 
00038 AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
00039                                          const Decl *d,
00040                                          const CFG::BuildOptions &buildOptions)
00041   : Manager(Mgr),
00042     D(d),
00043     cfgBuildOptions(buildOptions),
00044     forcedBlkExprs(nullptr),
00045     builtCFG(false),
00046     builtCompleteCFG(false),
00047     ReferencedBlockVars(nullptr),
00048     ManagedAnalyses(nullptr)
00049 {  
00050   cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
00051 }
00052 
00053 AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
00054                                          const Decl *d)
00055 : Manager(Mgr),
00056   D(d),
00057   forcedBlkExprs(nullptr),
00058   builtCFG(false),
00059   builtCompleteCFG(false),
00060   ReferencedBlockVars(nullptr),
00061   ManagedAnalyses(nullptr)
00062 {  
00063   cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
00064 }
00065 
00066 AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG,
00067                                                        bool addImplicitDtors,
00068                                                        bool addInitializers,
00069                                                        bool addTemporaryDtors,
00070                                                        bool synthesizeBodies,
00071                                                        bool addStaticInitBranch,
00072                                                        bool addCXXNewAllocator,
00073                                                        CodeInjector *injector)
00074   : Injector(injector), SynthesizeBodies(synthesizeBodies)
00075 {
00076   cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
00077   cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
00078   cfgBuildOptions.AddInitializers = addInitializers;
00079   cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
00080   cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
00081   cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
00082 }
00083 
00084 void AnalysisDeclContextManager::clear() {
00085   llvm::DeleteContainerSeconds(Contexts);
00086 }
00087 
00088 static BodyFarm &getBodyFarm(ASTContext &C, CodeInjector *injector = nullptr) {
00089   static BodyFarm *BF = new BodyFarm(C, injector);
00090   return *BF;
00091 }
00092 
00093 Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
00094   IsAutosynthesized = false;
00095   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
00096     Stmt *Body = FD->getBody();
00097     if (!Body && Manager && Manager->synthesizeBodies()) {
00098       Body = getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(FD);
00099       if (Body)
00100         IsAutosynthesized = true;
00101     }
00102     return Body;
00103   }
00104   else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
00105     Stmt *Body = MD->getBody();
00106     if (!Body && Manager && Manager->synthesizeBodies()) {
00107       Body = getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(MD);
00108       if (Body)
00109         IsAutosynthesized = true;
00110     }
00111     return Body;
00112   } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
00113     return BD->getBody();
00114   else if (const FunctionTemplateDecl *FunTmpl
00115            = dyn_cast_or_null<FunctionTemplateDecl>(D))
00116     return FunTmpl->getTemplatedDecl()->getBody();
00117 
00118   llvm_unreachable("unknown code decl");
00119 }
00120 
00121 Stmt *AnalysisDeclContext::getBody() const {
00122   bool Tmp;
00123   return getBody(Tmp);
00124 }
00125 
00126 bool AnalysisDeclContext::isBodyAutosynthesized() const {
00127   bool Tmp;
00128   getBody(Tmp);
00129   return Tmp;
00130 }
00131 
00132 bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const {
00133   bool Tmp;
00134   Stmt *Body = getBody(Tmp);
00135   return Tmp && Body->getLocStart().isValid();
00136 }
00137 
00138 
00139 const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
00140   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
00141     return MD->getSelfDecl();
00142   if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
00143     // See if 'self' was captured by the block.
00144     for (const auto &I : BD->captures()) {
00145       const VarDecl *VD = I.getVariable();
00146       if (VD->getName() == "self")
00147         return dyn_cast<ImplicitParamDecl>(VD);
00148     }    
00149   }
00150 
00151   return nullptr;
00152 }
00153 
00154 void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
00155   if (!forcedBlkExprs)
00156     forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs();
00157   // Default construct an entry for 'stmt'.
00158   if (const Expr *e = dyn_cast<Expr>(stmt))
00159     stmt = e->IgnoreParens();
00160   (void) (*forcedBlkExprs)[stmt];
00161 }
00162 
00163 const CFGBlock *
00164 AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {
00165   assert(forcedBlkExprs);
00166   if (const Expr *e = dyn_cast<Expr>(stmt))
00167     stmt = e->IgnoreParens();
00168   CFG::BuildOptions::ForcedBlkExprs::const_iterator itr = 
00169     forcedBlkExprs->find(stmt);
00170   assert(itr != forcedBlkExprs->end());
00171   return itr->second;
00172 }
00173 
00174 /// Add each synthetic statement in the CFG to the parent map, using the
00175 /// source statement's parent.
00176 static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) {
00177   if (!TheCFG)
00178     return;
00179 
00180   for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(),
00181                                     E = TheCFG->synthetic_stmt_end();
00182        I != E; ++I) {
00183     PM.setParent(I->first, PM.getParent(I->second));
00184   }
00185 }
00186 
00187 CFG *AnalysisDeclContext::getCFG() {
00188   if (!cfgBuildOptions.PruneTriviallyFalseEdges)
00189     return getUnoptimizedCFG();
00190 
00191   if (!builtCFG) {
00192     cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
00193     // Even when the cfg is not successfully built, we don't
00194     // want to try building it again.
00195     builtCFG = true;
00196 
00197     if (PM)
00198       addParentsForSyntheticStmts(cfg.get(), *PM);
00199 
00200     // The Observer should only observe one build of the CFG.
00201     getCFGBuildOptions().Observer = nullptr;
00202   }
00203   return cfg.get();
00204 }
00205 
00206 CFG *AnalysisDeclContext::getUnoptimizedCFG() {
00207   if (!builtCompleteCFG) {
00208     SaveAndRestore<bool> NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges,
00209                                   false);
00210     completeCFG =
00211         CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
00212     // Even when the cfg is not successfully built, we don't
00213     // want to try building it again.
00214     builtCompleteCFG = true;
00215 
00216     if (PM)
00217       addParentsForSyntheticStmts(completeCFG.get(), *PM);
00218 
00219     // The Observer should only observe one build of the CFG.
00220     getCFGBuildOptions().Observer = nullptr;
00221   }
00222   return completeCFG.get();
00223 }
00224 
00225 CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
00226   if (cfgStmtMap)
00227     return cfgStmtMap.get();
00228   
00229   if (CFG *c = getCFG()) {
00230     cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
00231     return cfgStmtMap.get();
00232   }
00233 
00234   return nullptr;
00235 }
00236 
00237 CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
00238   if (CFA)
00239     return CFA.get();
00240   
00241   if (CFG *c = getCFG()) {
00242     CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c));
00243     return CFA.get();
00244   }
00245 
00246   return nullptr;
00247 }
00248 
00249 void AnalysisDeclContext::dumpCFG(bool ShowColors) {
00250     getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
00251 }
00252 
00253 ParentMap &AnalysisDeclContext::getParentMap() {
00254   if (!PM) {
00255     PM.reset(new ParentMap(getBody()));
00256     if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
00257       for (const auto *I : C->inits()) {
00258         PM->addStmt(I->getInit());
00259       }
00260     }
00261     if (builtCFG)
00262       addParentsForSyntheticStmts(getCFG(), *PM);
00263     if (builtCompleteCFG)
00264       addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM);
00265   }
00266   return *PM;
00267 }
00268 
00269 PseudoConstantAnalysis *AnalysisDeclContext::getPseudoConstantAnalysis() {
00270   if (!PCA)
00271     PCA.reset(new PseudoConstantAnalysis(getBody()));
00272   return PCA.get();
00273 }
00274 
00275 AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
00276   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
00277     // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
00278     // that has the body.
00279     FD->hasBody(FD);
00280     D = FD;
00281   }
00282 
00283   AnalysisDeclContext *&AC = Contexts[D];
00284   if (!AC)
00285     AC = new AnalysisDeclContext(this, D, cfgBuildOptions);
00286   return AC;
00287 }
00288 
00289 const StackFrameContext *
00290 AnalysisDeclContext::getStackFrame(LocationContext const *Parent, const Stmt *S,
00291                                const CFGBlock *Blk, unsigned Idx) {
00292   return getLocationContextManager().getStackFrame(this, Parent, S, Blk, Idx);
00293 }
00294 
00295 const BlockInvocationContext *
00296 AnalysisDeclContext::getBlockInvocationContext(const LocationContext *parent,
00297                                                const clang::BlockDecl *BD,
00298                                                const void *ContextData) {
00299   return getLocationContextManager().getBlockInvocationContext(this, parent,
00300                                                                BD, ContextData);
00301 }
00302 
00303 LocationContextManager & AnalysisDeclContext::getLocationContextManager() {
00304   assert(Manager &&
00305          "Cannot create LocationContexts without an AnalysisDeclContextManager!");
00306   return Manager->getLocationContextManager();  
00307 }
00308 
00309 //===----------------------------------------------------------------------===//
00310 // FoldingSet profiling.
00311 //===----------------------------------------------------------------------===//
00312 
00313 void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
00314                                     ContextKind ck,
00315                                     AnalysisDeclContext *ctx,
00316                                     const LocationContext *parent,
00317                                     const void *data) {
00318   ID.AddInteger(ck);
00319   ID.AddPointer(ctx);
00320   ID.AddPointer(parent);
00321   ID.AddPointer(data);
00322 }
00323 
00324 void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
00325   Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block, Index);
00326 }
00327 
00328 void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
00329   Profile(ID, getAnalysisDeclContext(), getParent(), Enter);
00330 }
00331 
00332 void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
00333   Profile(ID, getAnalysisDeclContext(), getParent(), BD, ContextData);
00334 }
00335 
00336 //===----------------------------------------------------------------------===//
00337 // LocationContext creation.
00338 //===----------------------------------------------------------------------===//
00339 
00340 template <typename LOC, typename DATA>
00341 const LOC*
00342 LocationContextManager::getLocationContext(AnalysisDeclContext *ctx,
00343                                            const LocationContext *parent,
00344                                            const DATA *d) {
00345   llvm::FoldingSetNodeID ID;
00346   LOC::Profile(ID, ctx, parent, d);
00347   void *InsertPos;
00348 
00349   LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
00350 
00351   if (!L) {
00352     L = new LOC(ctx, parent, d);
00353     Contexts.InsertNode(L, InsertPos);
00354   }
00355   return L;
00356 }
00357 
00358 const StackFrameContext*
00359 LocationContextManager::getStackFrame(AnalysisDeclContext *ctx,
00360                                       const LocationContext *parent,
00361                                       const Stmt *s,
00362                                       const CFGBlock *blk, unsigned idx) {
00363   llvm::FoldingSetNodeID ID;
00364   StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
00365   void *InsertPos;
00366   StackFrameContext *L =
00367    cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
00368   if (!L) {
00369     L = new StackFrameContext(ctx, parent, s, blk, idx);
00370     Contexts.InsertNode(L, InsertPos);
00371   }
00372   return L;
00373 }
00374 
00375 const ScopeContext *
00376 LocationContextManager::getScope(AnalysisDeclContext *ctx,
00377                                  const LocationContext *parent,
00378                                  const Stmt *s) {
00379   return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
00380 }
00381 
00382 const BlockInvocationContext *
00383 LocationContextManager::getBlockInvocationContext(AnalysisDeclContext *ctx,
00384                                                   const LocationContext *parent,
00385                                                   const BlockDecl *BD,
00386                                                   const void *ContextData) {
00387   llvm::FoldingSetNodeID ID;
00388   BlockInvocationContext::Profile(ID, ctx, parent, BD, ContextData);
00389   void *InsertPos;
00390   BlockInvocationContext *L =
00391     cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
00392                                                                     InsertPos));
00393   if (!L) {
00394     L = new BlockInvocationContext(ctx, parent, BD, ContextData);
00395     Contexts.InsertNode(L, InsertPos);
00396   }
00397   return L;
00398 }
00399 
00400 //===----------------------------------------------------------------------===//
00401 // LocationContext methods.
00402 //===----------------------------------------------------------------------===//
00403 
00404 const StackFrameContext *LocationContext::getCurrentStackFrame() const {
00405   const LocationContext *LC = this;
00406   while (LC) {
00407     if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC))
00408       return SFC;
00409     LC = LC->getParent();
00410   }
00411   return nullptr;
00412 }
00413 
00414 bool LocationContext::inTopFrame() const {
00415   return getCurrentStackFrame()->inTopFrame();
00416 }
00417 
00418 bool LocationContext::isParentOf(const LocationContext *LC) const {
00419   do {
00420     const LocationContext *Parent = LC->getParent();
00421     if (Parent == this)
00422       return true;
00423     else
00424       LC = Parent;
00425   } while (LC);
00426 
00427   return false;
00428 }
00429 
00430 void LocationContext::dumpStack(raw_ostream &OS, StringRef Indent) const {
00431   ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
00432   PrintingPolicy PP(Ctx.getLangOpts());
00433   PP.TerseOutput = 1;
00434 
00435   unsigned Frame = 0;
00436   for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
00437     switch (LCtx->getKind()) {
00438     case StackFrame:
00439       OS << Indent << '#' << Frame++ << ' ';
00440       cast<StackFrameContext>(LCtx)->getDecl()->print(OS, PP);
00441       OS << '\n';
00442       break;
00443     case Scope:
00444       OS << Indent << "    (scope)\n";
00445       break;
00446     case Block:
00447       OS << Indent << "    (block context: "
00448                    << cast<BlockInvocationContext>(LCtx)->getContextData()
00449                    << ")\n";
00450       break;
00451     }
00452   }
00453 }
00454 
00455 LLVM_DUMP_METHOD void LocationContext::dumpStack() const {
00456   dumpStack(llvm::errs());
00457 }
00458 
00459 //===----------------------------------------------------------------------===//
00460 // Lazily generated map to query the external variables referenced by a Block.
00461 //===----------------------------------------------------------------------===//
00462 
00463 namespace {
00464 class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
00465   BumpVector<const VarDecl*> &BEVals;
00466   BumpVectorContext &BC;
00467   llvm::SmallPtrSet<const VarDecl*, 4> Visited;
00468   llvm::SmallPtrSet<const DeclContext*, 4> IgnoredContexts;
00469 public:
00470   FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
00471                             BumpVectorContext &bc)
00472   : BEVals(bevals), BC(bc) {}
00473 
00474   void VisitStmt(Stmt *S) {
00475     for (Stmt::child_range I = S->children(); I; ++I)
00476       if (Stmt *child = *I)
00477         Visit(child);
00478   }
00479 
00480   void VisitDeclRefExpr(DeclRefExpr *DR) {
00481     // Non-local variables are also directly modified.
00482     if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
00483       if (!VD->hasLocalStorage()) {
00484         if (Visited.insert(VD))
00485           BEVals.push_back(VD, BC);
00486       }
00487     }
00488   }
00489 
00490   void VisitBlockExpr(BlockExpr *BR) {
00491     // Blocks containing blocks can transitively capture more variables.
00492     IgnoredContexts.insert(BR->getBlockDecl());
00493     Visit(BR->getBlockDecl()->getBody());
00494   }
00495   
00496   void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
00497     for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(), 
00498          et = PE->semantics_end(); it != et; ++it) {
00499       Expr *Semantic = *it;
00500       if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
00501         Semantic = OVE->getSourceExpr();
00502       Visit(Semantic);
00503     }
00504   }
00505 };
00506 } // end anonymous namespace
00507 
00508 typedef BumpVector<const VarDecl*> DeclVec;
00509 
00510 static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
00511                                               void *&Vec,
00512                                               llvm::BumpPtrAllocator &A) {
00513   if (Vec)
00514     return (DeclVec*) Vec;
00515 
00516   BumpVectorContext BC(A);
00517   DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
00518   new (BV) DeclVec(BC, 10);
00519 
00520   // Go through the capture list.
00521   for (const auto &CI : BD->captures()) {
00522     BV->push_back(CI.getVariable(), BC);
00523   }
00524 
00525   // Find the referenced global/static variables.
00526   FindBlockDeclRefExprsVals F(*BV, BC);
00527   F.Visit(BD->getBody());
00528 
00529   Vec = BV;
00530   return BV;
00531 }
00532 
00533 std::pair<AnalysisDeclContext::referenced_decls_iterator,
00534           AnalysisDeclContext::referenced_decls_iterator>
00535 AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
00536   if (!ReferencedBlockVars)
00537     ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
00538 
00539   DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
00540   return std::make_pair(V->begin(), V->end());
00541 }
00542 
00543 ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(const void *tag) {
00544   if (!ManagedAnalyses)
00545     ManagedAnalyses = new ManagedAnalysisMap();
00546   ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
00547   return (*M)[tag];
00548 }
00549 
00550 //===----------------------------------------------------------------------===//
00551 // Cleanup.
00552 //===----------------------------------------------------------------------===//
00553 
00554 ManagedAnalysis::~ManagedAnalysis() {}
00555 
00556 AnalysisDeclContext::~AnalysisDeclContext() {
00557   delete forcedBlkExprs;
00558   delete ReferencedBlockVars;
00559   // Release the managed analyses.
00560   if (ManagedAnalyses) {
00561     ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
00562     llvm::DeleteContainerSeconds(*M);
00563     delete M;
00564   }
00565 }
00566 
00567 AnalysisDeclContextManager::~AnalysisDeclContextManager() {
00568   llvm::DeleteContainerSeconds(Contexts);
00569 }
00570 
00571 LocationContext::~LocationContext() {}
00572 
00573 LocationContextManager::~LocationContextManager() {
00574   clear();
00575 }
00576 
00577 void LocationContextManager::clear() {
00578   for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
00579        E = Contexts.end(); I != E; ) {
00580     LocationContext *LC = &*I;
00581     ++I;
00582     delete LC;
00583   }
00584 
00585   Contexts.clear();
00586 }
00587