// Is any successor of BB in the LiveIn set? static bool successorHasLiveIn(SILBasicBlock *BB, llvm::SmallPtrSetImpl<SILBasicBlock *> &LiveIn) { for (auto &Succ : BB->getSuccessors()) if (LiveIn.count(Succ)) return true; return false; }
void ModuleManager::removeModules( ModuleIterator first, ModuleIterator last, llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully, ModuleMap *modMap) { if (first == last) return; // Collect the set of module file pointers that we'll be removing. llvm::SmallPtrSet<ModuleFile *, 4> victimSet(first, last); auto IsVictim = [&](ModuleFile *MF) { return victimSet.count(MF); }; // Remove any references to the now-destroyed modules. for (unsigned i = 0, n = Chain.size(); i != n; ++i) { Chain[i]->ImportedBy.remove_if(IsVictim); } Roots.erase(std::remove_if(Roots.begin(), Roots.end(), IsVictim), Roots.end()); // Delete the modules and erase them from the various structures. for (ModuleIterator victim = first; victim != last; ++victim) { Modules.erase((*victim)->File); if (modMap) { StringRef ModuleName = (*victim)->ModuleName; if (Module *mod = modMap->findModule(ModuleName)) { mod->setASTFile(nullptr); } } // Files that didn't make it through ReadASTCore successfully will be // rebuilt (or there was an error). Invalidate them so that we can load the // new files that will be renamed over the old ones. if (LoadedSuccessfully.count(*victim) == 0) FileMgr.invalidateCache((*victim)->File); delete *victim; } // Remove the modules from the chain. Chain.erase(first, last); }
/// \brief Issue an "unreachable code" diagnostic if the blocks contains or /// leads to another block that contains user code. /// /// Note, we rely on SILLocation information to determine if SILInstructions /// correspond to user code. static bool diagnoseUnreachableBlock(const SILBasicBlock &B, SILModule &M, const SILBasicBlockSet &Reachable, UnreachableUserCodeReportingState *State, const SILBasicBlock *TopLevelB, llvm::SmallPtrSetImpl<const SILBasicBlock*> &Visited){ if (Visited.count(&B)) return false; Visited.insert(&B); assert(State); for (auto I = B.begin(), E = B.end(); I != E; ++I) { SILLocation Loc = I->getLoc(); // If we've reached an implicit return, we have not found any user code and // can stop searching for it. if (Loc.is<ImplicitReturnLocation>() || Loc.isAutoGenerated()) return false; // Check if the instruction corresponds to user-written code, also make // sure we don't report an error twice for the same instruction. if (isUserCode(&*I) && !State->BlocksWithErrors.count(&B)) { // Emit the diagnostic. auto BrInfoIter = State->MetaMap.find(TopLevelB); assert(BrInfoIter != State->MetaMap.end()); auto BrInfo = BrInfoIter->second; switch (BrInfo.Kind) { case (UnreachableKind::FoldedBranch): // Emit the diagnostic on the unreachable block and emit the // note on the branch responsible for the unreachable code. diagnose(M.getASTContext(), Loc.getSourceLoc(), diag::unreachable_code); diagnose(M.getASTContext(), BrInfo.Loc.getSourceLoc(), diag::unreachable_code_branch, BrInfo.CondIsAlwaysTrue); break; case (UnreachableKind::FoldedSwitchEnum): { // If we are warning about a switch condition being a constant, the main // emphasis should be on the condition (to ensure we have a single // message per switch). const SwitchStmt *SS = BrInfo.Loc.getAsASTNode<SwitchStmt>(); if (!SS) break; assert(SS); const Expr *SE = SS->getSubjectExpr(); diagnose(M.getASTContext(), SE->getLoc(), diag::switch_on_a_constant); diagnose(M.getASTContext(), Loc.getSourceLoc(), diag::unreachable_code_note); break; } case (UnreachableKind::NoreturnCall): { // Specialcase when we are warning about unreachable code after a call // to a noreturn function. if (!BrInfo.Loc.isASTNode<ExplicitCastExpr>()) { assert(BrInfo.Loc.isASTNode<ApplyExpr>()); diagnose(M.getASTContext(), Loc.getSourceLoc(), diag::unreachable_code); diagnose(M.getASTContext(), BrInfo.Loc.getSourceLoc(), diag::call_to_noreturn_note); } break; } } // Record that we've reported this unreachable block to avoid duplicates // in the future. State->BlocksWithErrors.insert(&B); return true; } } // This block could be empty if it's terminator has been folded. if (B.empty()) return false; // If we have not found user code in this block, inspect it's successors. // Check if at least one of the successors contains user code. for (auto I = B.succ_begin(), E = B.succ_end(); I != E; ++I) { SILBasicBlock *SB = *I; bool HasReachablePred = false; for (auto PI = SB->pred_begin(), PE = SB->pred_end(); PI != PE; ++PI) { if (Reachable.count(*PI)) HasReachablePred = true; } // If all of the predecessors of this successor are unreachable, check if // it contains user code. if (!HasReachablePred && diagnoseUnreachableBlock(*SB, M, Reachable, State, TopLevelB, Visited)) return true; } return false; }