boolCompilerInstance::ExecuteAction(FrontendAction&Act) { ... for (const FrontendInputFile &FIF : getFrontendOpts().Inputs) { // Reset the ID tables if we are reusing the SourceManager and parsing // regular files. if (hasSourceManager() && !Act.isModelParsingAction()) getSourceManager().clearIDTables();
if (CI.hasFrontendTimer()) llvm::TimeRegion Timer(CI.getFrontendTimer()); // 核心,虚函数,子类重写 ExecuteAction();
// If we are supposed to rebuild the global module index, do so now unless // there were any module-build failures. if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() && CI.hasPreprocessor()) { StringRef Cache = CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath(); if (!Cache.empty()) GlobalModuleIndex::writeIndex(CI.getFileManager(), CI.getPCHContainerReader(), Cache); }
// Don't run the actions if an error has occurred with parsing the file. DiagnosticsEngine &Diags = PP.getDiagnostics(); if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) return;
if (TUTotalTimer) TUTotalTimer->startTimer();
if (isBisonFile(C)) { reportAnalyzerProgress("Skipping bison-generated file\n"); } elseif (Opts->DisableAllChecks) {
// Don't analyze if the user explicitly asked for no checks to be performed // on this file. reportAnalyzerProgress("All checks are disabled using a supplied option\n"); } else { // Otherwise, just run the analysis. // 核心 runAnalysisOnTranslationUnit(C); }
if (TUTotalTimer) TUTotalTimer->stopTimer();
// Count how many basic blocks we have not covered. NumBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumBasicBlocks(); NumVisitedBlocksInAnalyzedFunctions = FunctionSummaries.getTotalNumVisitedBasicBlocks(); if (NumBlocksInAnalyzedFunctions > 0) PercentReachableBlocks = (FunctionSummaries.getTotalNumVisitedBasicBlocks() * 100) / NumBlocksInAnalyzedFunctions;
void AnalysisConsumer::HandleDeclsCallGraph(const unsigned LocalTUDeclsSize) { // 构建函数调用图 // 思想:遍历函数体,定位到Call Site,然后向外传播 CallGraph CG; for (unsigned i = 0 ; i < LocalTUDeclsSize ; ++i) { CG.addToCallGraph(LocalTUDecls[i]); }
SetOfConstDecls Visited; SetOfConstDecls VisitedAsTopLevel; llvm::ReversePostOrderTraversal<clang::CallGraph*> RPOT(&CG); for (llvm::ReversePostOrderTraversal<clang::CallGraph*>::rpo_iterator I = RPOT.begin(), E = RPOT.end(); I != E; ++I) { NumFunctionTopLevel++;
CallGraphNode *N = *I; Decl *D = N->getDecl();
// Skip the abstract root node. if (!D) continue;
// Skip the functions which have been processed already or previously // inlined. if (shouldSkipFunction(D, Visited, VisitedAsTopLevel)) continue;
// Analyze the function. SetOfConstDecls VisitedCallees; HandleCode(D, AM_Path, getInliningModeForFunction(D, Visited), (Mgr->options.InliningMode == All ? nullptr : &VisitedCallees));
// Add the visited callees to the global visited set. for (const Decl *Callee : VisitedCallees) // Decls from CallGraph are already canonical. But Decls coming from // CallExprs may be not. We should canonicalize them manually. Visited.insert(isa<ObjCMethodDecl>(Callee) ? Callee : Callee->getCanonicalDecl()); VisitedAsTopLevel.insert(D); } }
// Clear the AnalysisManager of old AnalysisDeclContexts. Mgr->ClearContexts(); // Ignore autosynthesized code. if (Mgr->getAnalysisDeclContext(D)->isBodyAutosynthesized()) return;
DisplayFunction(D, Mode, IMode); CFG *DeclCFG = Mgr->getCFG(D); if (DeclCFG) MaxCFGSize.updateMax(DeclCFG->size());
BugReporter BR(*Mgr);
if (Mode & AM_Syntax) checkerMgr->runCheckersOnASTBody(D, *Mgr, BR); if ((Mode & AM_Path) && checkerMgr->hasPathSensitiveCheckers()) { RunPathSensitiveChecks(D, IMode, VisitedCallees); if (IMode != ExprEngine::Inline_Minimal) NumFunctionsAnalyzed++; } }