aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Analysis/Analyses/UninitializedValues.h10
-rw-r--r--include/clang/Analysis/AnalysisContext.h5
-rw-r--r--include/clang/Sema/AnalysisBasedWarnings.h37
-rw-r--r--include/clang/Sema/Sema.h9
-rw-r--r--lib/Analysis/UninitializedValues.cpp20
-rw-r--r--lib/Parse/ParseAST.cpp7
-rw-r--r--lib/Sema/AnalysisBasedWarnings.cpp68
-rw-r--r--lib/Sema/Sema.cpp13
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.