diff options
-rw-r--r-- | include/clang/Analysis/Analyses/UninitializedValues.h | 10 | ||||
-rw-r--r-- | include/clang/Analysis/AnalysisContext.h | 5 | ||||
-rw-r--r-- | include/clang/Sema/AnalysisBasedWarnings.h | 37 | ||||
-rw-r--r-- | include/clang/Sema/Sema.h | 9 | ||||
-rw-r--r-- | lib/Analysis/UninitializedValues.cpp | 20 | ||||
-rw-r--r-- | lib/Parse/ParseAST.cpp | 7 | ||||
-rw-r--r-- | lib/Sema/AnalysisBasedWarnings.cpp | 68 | ||||
-rw-r--r-- | lib/Sema/Sema.cpp | 13 |
8 files changed, 152 insertions, 17 deletions
diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index b966f3a90f..badb493a9d 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -32,10 +32,16 @@ public: const VarDecl *vd, bool isAlwaysUninit) {} }; - + +struct UninitVariablesAnalysisStats { + unsigned NumVariablesAnalyzed; + unsigned NumBlockVisits; +}; + void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, AnalysisContext &ac, - UninitVariablesHandler &handler); + UninitVariablesHandler &handler, + UninitVariablesAnalysisStats &stats); } #endif diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 66c12a5384..6a1876e659 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -107,6 +107,11 @@ public: void dumpCFG(); + /// \brief Returns true if we have built a CFG for this analysis context. + /// Note that this doesn't correspond to whether or not a valid CFG exists, it + /// corresponds to whether we *attempted* to build one. + bool isCFGBuilt() const { return builtCFG; } + ParentMap &getParentMap(); PseudoConstantAnalysis *getPseudoConstantAnalysis(); LiveVariables *getLiveVariables(); diff --git a/include/clang/Sema/AnalysisBasedWarnings.h b/include/clang/Sema/AnalysisBasedWarnings.h index b7ae25486f..8e781cd521 100644 --- a/include/clang/Sema/AnalysisBasedWarnings.h +++ b/include/clang/Sema/AnalysisBasedWarnings.h @@ -49,6 +49,41 @@ private: enum VisitFlag { NotVisited = 0, Visited = 1, Pending = 2 }; llvm::DenseMap<const FunctionDecl*, VisitFlag> VisitedFD; + /// \name Statistics + /// @{ + + /// \brief Number of function CFGs built and analyzed. + unsigned NumFunctionsAnalyzed; + + /// \brief Number of functions for which the CFG could not be successfully + /// built. + unsigned NumFunctionsWithBadCFGs; + + /// \brief Total number of blocks across all CFGs. + unsigned NumCFGBlocks; + + /// \brief Largest number of CFG blocks for a single function analyzed. + unsigned MaxCFGBlocksPerFunction; + + /// \brief Total number of CFGs with variables analyzed for uninitialized + /// uses. + unsigned NumUninitAnalysisFunctions; + + /// \brief Total number of variables analyzed for uninitialized uses. + unsigned NumUninitAnalysisVariables; + + /// \brief Max number of variables analyzed for uninitialized uses in a single + /// function. + unsigned MaxUninitAnalysisVariablesPerFunction; + + /// \brief Total number of block visits during uninitialized use analysis. + unsigned NumUninitAnalysisBlockVisits; + + /// \brief Max number of block visits during uninitialized use analysis of + /// a single function. + unsigned MaxUninitAnalysisBlockVisitsPerFunction; + + /// @} public: AnalysisBasedWarnings(Sema &s); @@ -57,6 +92,8 @@ public: const Decl *D, const BlockExpr *blkExpr); Policy getDefaultPolicy() { return DefaultPolicy; } + + void PrintStats() const; }; }} // end namespace clang::sema diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 67a2678690..4682404873 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -193,6 +193,9 @@ public: Diagnostic &Diags; SourceManager &SourceMgr; + /// \brief Flag indicating whether or not to collect detailed statistics. + bool CollectStats; + /// \brief Source of additional semantic information. ExternalSemaSource *ExternalSource; @@ -689,7 +692,9 @@ public: ASTContext &getASTContext() const { return Context; } ASTConsumer &getASTConsumer() const { return Consumer; } ASTMutationListener *getASTMutationListener() const; - + + void PrintStats() const; + /// \brief Helper class that creates diagnostics with optional /// template instantiation stacks. /// @@ -5849,8 +5854,6 @@ public: llvm::SmallVectorImpl<CodeCompletionResult> &Results); //@} - void PrintStats() const {} - //===--------------------------------------------------------------------===// // Extra semantic analysis beyond the C type system diff --git a/lib/Analysis/UninitializedValues.cpp b/lib/Analysis/UninitializedValues.cpp index e80e282813..96cae9d1f4 100644 --- a/lib/Analysis/UninitializedValues.cpp +++ b/lib/Analysis/UninitializedValues.cpp @@ -654,15 +654,19 @@ static bool runOnBlock(const CFGBlock *block, const CFG &cfg, return vals.updateValueVectorWithScratch(block); } -void clang::runUninitializedVariablesAnalysis(const DeclContext &dc, - const CFG &cfg, - AnalysisContext &ac, - UninitVariablesHandler &handler) { +void clang::runUninitializedVariablesAnalysis( + const DeclContext &dc, + const CFG &cfg, + AnalysisContext &ac, + UninitVariablesHandler &handler, + UninitVariablesAnalysisStats &stats) { CFGBlockValues vals(cfg); vals.computeSetOfDeclarations(dc); if (vals.hasNoDeclarations()) return; + stats.NumVariablesAnalyzed = vals.getNumEntries(); + // Mark all variables uninitialized at the entry. const CFGBlock &entry = cfg.getEntry(); for (CFGBlock::const_succ_iterator i = entry.succ_begin(), @@ -684,7 +688,8 @@ void clang::runUninitializedVariablesAnalysis(const DeclContext &dc, while (const CFGBlock *block = worklist.dequeue()) { // Did the block change? - bool changed = runOnBlock(block, cfg, ac, vals, wasAnalyzed); + bool changed = runOnBlock(block, cfg, ac, vals, wasAnalyzed); + ++stats.NumBlockVisits; if (changed || !previouslyVisited[block->getBlockID()]) worklist.enqueueSuccessors(block); previouslyVisited[block->getBlockID()] = true; @@ -692,11 +697,12 @@ void clang::runUninitializedVariablesAnalysis(const DeclContext &dc, // Run through the blocks one more time, and report uninitialized variabes. for (CFG::const_iterator BI = cfg.begin(), BE = cfg.end(); BI != BE; ++BI) { - if (wasAnalyzed[(*BI)->getBlockID()]) + if (wasAnalyzed[(*BI)->getBlockID()]) { runOnBlock(*BI, cfg, ac, vals, wasAnalyzed, &handler, /* flagBlockUses */ true); + ++stats.NumBlockVisits; + } } } UninitVariablesHandler::~UninitVariablesHandler() {} - diff --git a/lib/Parse/ParseAST.cpp b/lib/Parse/ParseAST.cpp index 00685362fd..56584c9618 100644 --- a/lib/Parse/ParseAST.cpp +++ b/lib/Parse/ParseAST.cpp @@ -57,6 +57,10 @@ void clang::ParseAST(Sema &S, bool PrintStats) { Stmt::CollectingStats(true); } + // Also turn on collection of stats inside of the Sema object. + bool OldCollectStats = PrintStats; + std::swap(OldCollectStats, S.CollectStats); + ASTConsumer *Consumer = &S.getASTConsumer(); llvm::OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S)); @@ -95,7 +99,8 @@ void clang::ParseAST(Sema &S, bool PrintStats) { Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); Consumer->HandleTranslationUnit(S.getASTContext()); - + + std::swap(OldCollectStats, S.CollectStats); if (PrintStats) { llvm::errs() << "\nSTATISTICS:\n"; P.getActions().PrintStats(); diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp index e560ef8a5c..8a4634df2f 100644 --- a/lib/Sema/AnalysisBasedWarnings.cpp +++ b/lib/Sema/AnalysisBasedWarnings.cpp @@ -597,7 +597,11 @@ clang::sema::AnalysisBasedWarnings::Policy::Policy() { enableCheckUnreachable = 0; } -clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) : S(s) { +clang::sema::AnalysisBasedWarnings::AnalysisBasedWarnings(Sema &s) + : S(s), + NumFunctionsAnalyzed(0), + NumCFGBlocks(0), + MaxCFGBlocksPerFunction(0) { Diagnostic &D = S.getDiagnostics(); DefaultPolicy.enableCheckUnreachable = (unsigned) (D.getDiagnosticLevel(diag::warn_unreachable, SourceLocation()) != @@ -713,8 +717,68 @@ AnalysisBasedWarnings::IssueWarnings(sema::AnalysisBasedWarnings::Policy P, != Diagnostic::Ignored) { if (CFG *cfg = AC.getCFG()) { UninitValsDiagReporter reporter(S); + UninitVariablesAnalysisStats stats = {}; runUninitializedVariablesAnalysis(*cast<DeclContext>(D), *cfg, AC, - reporter); + reporter, stats); + + if (S.CollectStats && stats.NumVariablesAnalyzed > 0) { + ++NumUninitAnalysisFunctions; + NumUninitAnalysisVariables += stats.NumVariablesAnalyzed; + NumUninitAnalysisBlockVisits += stats.NumBlockVisits; + MaxUninitAnalysisVariablesPerFunction = + std::max(MaxUninitAnalysisVariablesPerFunction, + stats.NumVariablesAnalyzed); + MaxUninitAnalysisBlockVisitsPerFunction = + std::max(MaxUninitAnalysisBlockVisitsPerFunction, + stats.NumBlockVisits); + } + } + } + + // Collect statistics about the CFG if it was built. + if (S.CollectStats && AC.isCFGBuilt()) { + ++NumFunctionsAnalyzed; + if (CFG *cfg = AC.getCFG()) { + // If we successfully built a CFG for this context, record some more + // detail information about it. + unsigned NumBlocks = std::distance(cfg->begin(), cfg->end()); + NumCFGBlocks += NumBlocks; + MaxCFGBlocksPerFunction = std::max(MaxCFGBlocksPerFunction, + NumBlocks); + } else { + ++NumFunctionsWithBadCFGs; } } } + +void clang::sema::AnalysisBasedWarnings::PrintStats() const { + llvm::errs() << "\n*** Analysis Based Warnings Stats:\n"; + + unsigned NumCFGsBuilt = NumFunctionsAnalyzed - NumFunctionsWithBadCFGs; + unsigned AvgCFGBlocksPerFunction = + !NumCFGsBuilt ? 0 : NumCFGBlocks/NumCFGsBuilt; + llvm::errs() << NumFunctionsAnalyzed << " functions analyzed (" + << NumFunctionsWithBadCFGs << " w/o CFGs).\n" + << " " << NumCFGBlocks << " CFG blocks built.\n" + << " " << AvgCFGBlocksPerFunction + << " average CFG blocks per function.\n" + << " " << MaxCFGBlocksPerFunction + << " max CFG blocks per function.\n"; + + unsigned AvgUninitVariablesPerFunction = !NumUninitAnalysisFunctions ? 0 + : NumUninitAnalysisVariables/NumUninitAnalysisFunctions; + unsigned AvgUninitBlockVisitsPerFunction = !NumUninitAnalysisFunctions ? 0 + : NumUninitAnalysisBlockVisits/NumUninitAnalysisFunctions; + llvm::errs() << NumUninitAnalysisFunctions + << " functions analyzed for uninitialiazed variables\n" + << " " << NumUninitAnalysisVariables << " variables analyzed.\n" + << " " << AvgUninitVariablesPerFunction + << " average variables per function.\n" + << " " << MaxUninitAnalysisVariablesPerFunction + << " max variables per function.\n" + << " " << NumUninitAnalysisBlockVisits << " block visits.\n" + << " " << AvgUninitBlockVisitsPerFunction + << " average block visits per function.\n" + << " " << MaxUninitAnalysisBlockVisitsPerFunction + << " max block visits per function.\n"; +} diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 9550f9aad2..fdf3bb3cb0 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -141,8 +141,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, : TheTargetAttributesSema(0), FPFeatures(pp.getLangOptions()), LangOpts(pp.getLangOptions()), PP(pp), Context(ctxt), Consumer(consumer), Diags(PP.getDiagnostics()), SourceMgr(PP.getSourceManager()), - ExternalSource(0), CodeCompleter(CodeCompleter), CurContext(0), - PackContext(0), MSStructPragmaOn(false), VisContext(0), + CollectStats(false), ExternalSource(0), CodeCompleter(CodeCompleter), + CurContext(0), PackContext(0), MSStructPragmaOn(false), VisContext(0), ExprNeedsCleanups(0), LateTemplateParser(0), OpaqueParser(0), IdResolver(pp.getLangOptions()), CXXTypeInfoDecl(0), MSVCGuidDecl(0), GlobalNewDeleteDeclared(false), @@ -234,6 +234,15 @@ ASTMutationListener *Sema::getASTMutationListener() const { return getASTConsumer().GetASTMutationListener(); } +/// \brief Print out statistics about the semantic analysis. +void Sema::PrintStats() const { + llvm::errs() << "\n*** Semantic Analysis Stats:\n"; + llvm::errs() << NumSFINAEErrors << " SFINAE diagnostics trapped.\n"; + + BumpAlloc.PrintStats(); + AnalysisWarnings.PrintStats(); +} + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. /// If there is already an implicit cast, merge into the existing one. /// The result is of the given category. |