virtual bool visit(const WorkListUnit &U) { ProgramPoint P = U.getNode()->getLocation(); const CFGBlock *B = 0; if (Optional<StmtPoint> SP = P.getAs<StmtPoint>()) { B = CBM->getBlock(SP->getStmt()); } else if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) { B = BE->getDst(); } else if (Optional<BlockEntrance> BEnt = P.getAs<BlockEntrance>()) { B = BEnt->getBlock(); } else if (Optional<BlockExit> BExit = P.getAs<BlockExit>()) { B = BExit->getBlock(); } if (!B) return true; return B == TargetBlock || CRA.isReachable(B, TargetBlock); }
virtual bool visit(const WorkListUnit &U) { ProgramPoint P = U.getNode()->getLocation(); const CFGBlock *B = 0; if (StmtPoint *SP = dyn_cast<StmtPoint>(&P)) { B = CBM->getBlock(SP->getStmt()); } else if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { B = BE->getDst(); } else if (BlockEntrance *BEnt = dyn_cast<BlockEntrance>(&P)) { B = BEnt->getBlock(); } else if (BlockExit *BExit = dyn_cast<BlockExit>(&P)) { B = BExit->getBlock(); } if (!B) return true; return B == TargetBlock || CRA.isReachable(B, TargetBlock); }
// Returns false if a path to this block was not completely analyzed, or true // otherwise. bool IdempotentOperationChecker::pathWasCompletelyAnalyzed(AnalysisDeclContext *AC, const CFGBlock *CB, const CoreEngine &CE) { CFGReverseBlockReachabilityAnalysis *CRA = AC->getCFGReachablityAnalysis(); // Test for reachability from any aborted blocks to this block typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator; for (ExhaustedIterator I = CE.blocks_exhausted_begin(), E = CE.blocks_exhausted_end(); I != E; ++I) { const BlockEdge &BE = I->first; // The destination block on the BlockEdge is the first block that was not // analyzed. If we can reach this block from the aborted block, then this // block was not completely analyzed. // // Also explicitly check if the current block is the destination block. // While technically reachable, it means we aborted the analysis on // a path that included that block. const CFGBlock *destBlock = BE.getDst(); if (destBlock == CB || CRA->isReachable(destBlock, CB)) return false; } // Test for reachability from blocks we just gave up on. typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator; for (AbortedIterator I = CE.blocks_aborted_begin(), E = CE.blocks_aborted_end(); I != E; ++I) { const CFGBlock *destBlock = I->first; if (destBlock == CB || CRA->isReachable(destBlock, CB)) return false; } // For the items still on the worklist, see if they are in blocks that // can eventually reach 'CB'. class VisitWL : public WorkList::Visitor { const CFGStmtMap *CBM; const CFGBlock *TargetBlock; CFGReverseBlockReachabilityAnalysis &CRA; public: VisitWL(const CFGStmtMap *cbm, const CFGBlock *targetBlock, CFGReverseBlockReachabilityAnalysis &cra) : CBM(cbm), TargetBlock(targetBlock), CRA(cra) {} virtual bool visit(const WorkListUnit &U) { ProgramPoint P = U.getNode()->getLocation(); const CFGBlock *B = 0; if (StmtPoint *SP = dyn_cast<StmtPoint>(&P)) { B = CBM->getBlock(SP->getStmt()); } else if (BlockEdge *BE = dyn_cast<BlockEdge>(&P)) { B = BE->getDst(); } else if (BlockEntrance *BEnt = dyn_cast<BlockEntrance>(&P)) { B = BEnt->getBlock(); } else if (BlockExit *BExit = dyn_cast<BlockExit>(&P)) { B = BExit->getBlock(); } if (!B) return true; return B == TargetBlock || CRA.isReachable(B, TargetBlock); } }; VisitWL visitWL(AC->getCFGStmtMap(), CB, *CRA); // Were there any items in the worklist that could potentially reach // this block? if (CE.getWorkList()->visitItemsInWorkList(visitWL)) return false; // Verify that this block is reachable from the entry block if (!CRA->isReachable(&AC->getCFG()->getEntry(), CB)) return false; // If we get to this point, there is no connection to the entry block or an // aborted block. This path is unreachable and we can report the error. return true; }