aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-12-07 22:06:12 +0000
committerTed Kremenek <kremenek@apple.com>2009-12-07 22:06:12 +0000
commitfc576514d06c46a7cac49500169411d82f38d04b (patch)
tree495a811390c9348fb49d4d2c8d9cd58b3d4f3976
parent67d1287035767f4f6c8ca0c2bb755990012a44ca (diff)
Add clang-cc option '-analyzer-opt-analyze-nested-blocks' to treat block literals as an entry point for analyzer checks.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@90810 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Driver/CC1Options.td4
-rw-r--r--include/clang/Frontend/AnalysisConsumer.h2
-rw-r--r--lib/Frontend/AnalysisConsumer.cpp41
-rw-r--r--lib/Frontend/CompilerInvocation.cpp6
4 files changed, 43 insertions, 10 deletions
diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td
index 582b9c28ac..aa4d3bfadc 100644
--- a/include/clang/Driver/CC1Options.td
+++ b/include/clang/Driver/CC1Options.td
@@ -55,7 +55,7 @@ def analysis_CheckerCFRef : Flag<"-checker-cfref">,
def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">,
HelpText<"Warn about unintended use of sizeof() on pointer expressions">;
def analysis_InlineCall : Flag<"-inline-call">,
- HelpText<"Experimental transfer function inling callees when its definition is available.">;
+ HelpText<"Experimental transfer function inlining callees when its definition is available.">;
def analyzer_store : Separate<"-analyzer-store">,
HelpText<"Source Code Analysis - Abstract Memory Store Models">;
@@ -73,6 +73,8 @@ def analyzer_output_EQ : Joined<"-analyzer-output=">,
def analyzer_opt_analyze_headers : Flag<"-analyzer-opt-analyze-headers">,
HelpText<"Force the static analyzer to analyze functions defined in header files">;
+def analyzer_opt_analyze_nested_blocks : Flag<"-analyzer-opt-analyze-nested-blocks">,
+ HelpText<"Analyze the definitions of blocks in addition to functions">;
def analyzer_display_progress : Flag<"-analyzer-display-progress">,
HelpText<"Emit verbose output about the analyzer's progress">;
def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">,
diff --git a/include/clang/Frontend/AnalysisConsumer.h b/include/clang/Frontend/AnalysisConsumer.h
index 24fed6e76a..f55e5dc040 100644
--- a/include/clang/Frontend/AnalysisConsumer.h
+++ b/include/clang/Frontend/AnalysisConsumer.h
@@ -62,6 +62,7 @@ public:
std::string AnalyzeSpecificFunction;
unsigned AnalyzeAll : 1;
unsigned AnalyzerDisplayProgress : 1;
+ unsigned AnalyzeNestedBlocks : 1;
unsigned EagerlyAssume : 1;
unsigned PurgeDead : 1;
unsigned TrimGraph : 1;
@@ -76,6 +77,7 @@ public:
AnalysisDiagOpt = PD_HTML;
AnalyzeAll = 0;
AnalyzerDisplayProgress = 0;
+ AnalyzeNestedBlocks = 0;
EagerlyAssume = 0;
PurgeDead = 1;
TrimGraph = 0;
diff --git a/lib/Frontend/AnalysisConsumer.cpp b/lib/Frontend/AnalysisConsumer.cpp
index 5df1eceb88..92f34b21fe 100644
--- a/lib/Frontend/AnalysisConsumer.cpp
+++ b/lib/Frontend/AnalysisConsumer.cpp
@@ -139,14 +139,21 @@ public:
return;
declDisplayed = true;
- // FIXME: Is getCodeDecl() always a named decl?
- if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
- const NamedDecl *ND = cast<NamedDecl>(D);
- SourceManager &SM = Mgr->getASTContext().getSourceManager();
- llvm::errs() << "ANALYZE: "
- << SM.getPresumedLoc(ND->getLocation()).getFilename()
- << ' ' << ND->getNameAsString() << '\n';
+ SourceManager &SM = Mgr->getASTContext().getSourceManager();
+ PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
+ llvm::errs() << "ANALYZE: " << Loc.getFilename();
+
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+ assert(isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D));
+ llvm::errs() << ' ' << ND->getNameAsString();
+ }
+ else {
+ assert(isa<BlockDecl>(D));
+ llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
+ << Loc.getColumn();
}
+
+ llvm::errs() << '\n';
}
void addCodeAction(CodeAction action) {
@@ -269,6 +276,16 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
Mgr.reset(NULL);
}
+static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) {
+ if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
+ WL.push_back(BD);
+
+ for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
+ I!=E; ++I)
+ if (DeclContext *DC = dyn_cast<DeclContext>(*I))
+ FindBlocks(DC, WL);
+}
+
void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
// Don't run the actions if an error has occured with parsing the file.
@@ -285,8 +302,16 @@ void AnalysisConsumer::HandleCode(Decl *D, Stmt* Body, Actions& actions) {
Mgr->ClearContexts();
// Dispatch on the actions.
+ llvm::SmallVector<Decl*, 10> WL;
+ WL.push_back(D);
+
+ if (Opts.AnalyzeNestedBlocks)
+ FindBlocks(cast<DeclContext>(D), WL);
+
for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
- (*I)(*this, *Mgr, D);
+ for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
+ WI != WE; ++WI)
+ (*I)(*this, *Mgr, *WI);
}
//===----------------------------------------------------------------------===//
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 2ecbcfe862..1f64e1e7fa 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -31,7 +31,7 @@ using namespace clang;
static const char *getAnalysisName(Analyses Kind) {
switch (Kind) {
default:
- llvm::llvm_unreachable("Unknown analysis store!");
+ llvm::llvm_unreachable("Unknown analysis kind!");
#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
case NAME: return "-" CMDFLAG;
#include "clang/Frontend/Analyses.def"
@@ -96,6 +96,8 @@ static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
Res.push_back("-analyzer-opt-analyze-headers");
if (Opts.AnalyzerDisplayProgress)
Res.push_back("-analyzer-display-progress");
+ if (Opts.AnalyzeNestedBlocks)
+ Res.push_back("-analyzer-opt-analyze-nested-blocks");
if (Opts.EagerlyAssume)
Res.push_back("-analyzer-eagerly-assume");
if (!Opts.PurgeDead)
@@ -709,6 +711,8 @@ static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph);
Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
+ Opts.AnalyzeNestedBlocks =
+ Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
Opts.PurgeDead = !Args.hasArg(OPT_analyzer_no_purge_dead);
Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume);
Opts.AnalyzeSpecificFunction = getLastArgValue(Args, OPT_analyze_function);