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& 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 TFs; + getTransferFunctions(TFs); - // Set base transfer functions. - llvm::OwningPtr 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 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& 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& 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*>& 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); }