aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Driver/ASTConsumers.cpp71
-rw-r--r--Driver/ASTConsumers.h1
-rw-r--r--Driver/clang.cpp3
-rw-r--r--include/clang/Analysis/LocalCheckers.h2
-rw-r--r--lib/Analysis/CFRefCount.cpp10
5 files changed, 58 insertions, 29 deletions
diff --git a/Driver/ASTConsumers.cpp b/Driver/ASTConsumers.cpp
index 2f04ab78d4..c01e4edb0d 100644
--- a/Driver/ASTConsumers.cpp
+++ b/Driver/ASTConsumers.cpp
@@ -690,7 +690,7 @@ public:
virtual bool printFuncDeclStart() { return false; }
virtual const char* getCheckerName() = 0;
- virtual GRTransferFuncs* getTransferFunctions() = 0;
+ virtual void getTransferFunctions(std::vector<GRTransferFuncs*>& TFs) = 0;
};
} // end anonymous namespace
@@ -732,22 +732,30 @@ void CheckerConsumer::VisitCFG(CFG& C, Decl& CD) {
else
llvm::cerr << '\n';
- // Construct the analysis engine.
- GRExprEngine Eng(C, CD, *Ctx);
+ std::vector<GRTransferFuncs*> TFs;
+ getTransferFunctions(TFs);
- // Set base transfer functions.
- llvm::OwningPtr<GRTransferFuncs> TF(getTransferFunctions());
- Eng.setTransferFunctions(TF.get());
-
- // Execute the worklist algorithm.
- Eng.ExecuteWorkList();
-
- // Display warnings.
- Eng.EmitWarnings(Diags, PD.get());
-
-#ifndef NDEBUG
- if (Visualize) Eng.ViewGraph(TrimGraph);
-#endif
+ while (!TFs.empty()) {
+
+ // Construct the analysis engine.
+ GRExprEngine Eng(C, CD, *Ctx);
+
+ // Set base transfer functions.
+ llvm::OwningPtr<GRTransferFuncs> TF(TFs.back());
+ TFs.pop_back();
+
+ Eng.setTransferFunctions(TF.get());
+
+ // Execute the worklist algorithm.
+ Eng.ExecuteWorkList();
+
+ // Display warnings.
+ Eng.EmitWarnings(Diags, PD.get());
+
+ #ifndef NDEBUG
+ if (Visualize) Eng.ViewGraph(TrimGraph);
+ #endif
+ }
}
//===----------------------------------------------------------------------===//
@@ -765,8 +773,8 @@ public:
virtual const char* getCheckerName() { return "GRSimpleVals"; }
- virtual GRTransferFuncs* getTransferFunctions() {
- return MakeGRSimpleValsTF();
+ virtual void getTransferFunctions(std::vector<GRTransferFuncs*>& TFs) {
+ return TFs.push_back(MakeGRSimpleValsTF());
}
};
} // end anonymous namespace
@@ -789,19 +797,34 @@ ASTConsumer* clang::CreateGRSimpleVals(Diagnostic &Diags,
namespace {
class CFRefCountCheckerVisitor : public CheckerConsumer {
+ const LangOptions& LangOpts;
public:
CFRefCountCheckerVisitor(Diagnostic &diags, Preprocessor* pp,
PreprocessorFactory* ppf,
+ const LangOptions& lopts,
const std::string& fname,
const std::string& htmldir,
bool visualize, bool trim, bool analyzeAll)
: CheckerConsumer(diags, pp, ppf, fname, htmldir, visualize,
- trim, analyzeAll) {}
+ trim, analyzeAll), LangOpts(lopts) {}
virtual const char* getCheckerName() { return "CFRefCountChecker"; }
- virtual GRTransferFuncs* getTransferFunctions() {
- return MakeCFRefCountTF(*Ctx);
+ virtual void getTransferFunctions(std::vector<GRTransferFuncs*>& TFs) {
+ switch (LangOpts.getGCMode()) {
+ case LangOptions::NonGC:
+ TFs.push_back(MakeCFRefCountTF(*Ctx, false));
+ break;
+
+ case LangOptions::GCOnly:
+ TFs.push_back(MakeCFRefCountTF(*Ctx, true));
+ break;
+
+ case LangOptions::HybridGC:
+ TFs.push_back(MakeCFRefCountTF(*Ctx, false));
+ TFs.push_back(MakeCFRefCountTF(*Ctx, true));
+ break;
+ }
}
};
} // end anonymous namespace
@@ -809,13 +832,15 @@ public:
ASTConsumer* clang::CreateCFRefChecker(Diagnostic &Diags,
Preprocessor* PP,
PreprocessorFactory* PPF,
+ const LangOptions& LangOpts,
const std::string& FunctionName,
const std::string& HTMLDir,
bool Visualize, bool TrimGraph,
bool AnalyzeAll) {
- return new CFRefCountCheckerVisitor(Diags, PP, PPF, FunctionName, HTMLDir,
- Visualize, TrimGraph, AnalyzeAll);
+ return new CFRefCountCheckerVisitor(Diags, PP, PPF, LangOpts, FunctionName,
+ HTMLDir, Visualize, TrimGraph,
+ AnalyzeAll);
}
//===----------------------------------------------------------------------===//
diff --git a/Driver/ASTConsumers.h b/Driver/ASTConsumers.h
index 7ef42a0707..7037ade1dd 100644
--- a/Driver/ASTConsumers.h
+++ b/Driver/ASTConsumers.h
@@ -53,6 +53,7 @@ ASTConsumer *CreateGRSimpleVals(Diagnostic &Diags,
ASTConsumer *CreateCFRefChecker(Diagnostic &Diags,
Preprocessor* PP, PreprocessorFactory* PPF,
+ const LangOptions& LangOpts,
const std::string& Function,
const std::string& HTMLDir, bool Visualize,
bool TrimGraph, bool AnalyzeAll);
diff --git a/Driver/clang.cpp b/Driver/clang.cpp
index 0b9841687b..62f570f627 100644
--- a/Driver/clang.cpp
+++ b/Driver/clang.cpp
@@ -1132,7 +1132,8 @@ static ASTConsumer* CreateASTConsumer(const std::string& InFile,
OutputFile, VisualizeEG, TrimGraph, AnalyzeAll);
case CheckerCFRef:
- return CreateCFRefChecker(Diag, PP, PPF, AnalyzeSpecificFunction,
+ return CreateCFRefChecker(Diag, PP, PPF, LangOpts,
+ AnalyzeSpecificFunction,
OutputFile, VisualizeEG, TrimGraph, AnalyzeAll);
case TestSerialization:
diff --git a/include/clang/Analysis/LocalCheckers.h b/include/clang/Analysis/LocalCheckers.h
index 6dcad7f376..bf4f30a337 100644
--- a/include/clang/Analysis/LocalCheckers.h
+++ b/include/clang/Analysis/LocalCheckers.h
@@ -31,7 +31,7 @@ void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
bool FullUninitTaint=false);
GRTransferFuncs* MakeGRSimpleValsTF();
-GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx);
+GRTransferFuncs* MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled);
BugType* MakeDeadStoresChecker();
} // end namespace clang
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index ad72d27a82..730c5311f5 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -590,7 +590,8 @@ public:
private:
// Instance variables.
- CFRefSummaryManager Summaries;
+ CFRefSummaryManager Summaries;
+ const bool GCEnabled;
RefBFactoryTy RefBFactory;
UseAfterReleasesTy UseAfterReleases;
@@ -636,8 +637,9 @@ private:
public:
- CFRefCount(ASTContext& Ctx)
+ CFRefCount(ASTContext& Ctx, bool gcenabled)
: Summaries(Ctx),
+ GCEnabled(gcenabled),
RetainSelector(GetUnarySelector("retain", Ctx)),
ReleaseSelector(GetUnarySelector("release", Ctx)) {}
@@ -1575,6 +1577,6 @@ void Leak::GetErrorNodes(std::vector<ExplodedNode<ValueState>*>& Nodes) {
// Transfer function creation for external clients.
//===----------------------------------------------------------------------===//
-GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx) {
- return new CFRefCount(Ctx);
+GRTransferFuncs* clang::MakeCFRefCountTF(ASTContext& Ctx, bool GCEnabled) {
+ return new CFRefCount(Ctx, GCEnabled);
}