diff --git a/clang-tools-extra/clang-tidy/ClangTidy.cpp b/clang-tools-extra/clang-tidy/ClangTidy.cpp --- a/clang-tools-extra/clang-tidy/ClangTidy.cpp +++ b/clang-tools-extra/clang-tidy/ClangTidy.cpp @@ -444,8 +444,8 @@ AnalyzerOptions->eagerlyAssumeBinOpBifurcation = true; std::unique_ptr AnalysisConsumer = ento::CreateAnalysisConsumer(Compiler); - AnalysisConsumer->AddDiagnosticConsumer( - new AnalyzerDiagnosticConsumer(Context)); + AnalysisConsumer->addDiagnosticConsumer( + std::make_unique(Context)); Consumers.push_back(std::move(AnalysisConsumer)); } #endif // CLANG_TIDY_ENABLE_STATIC_ANALYZER diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h --- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -570,7 +570,8 @@ public: virtual ~BugReporterData() = default; - virtual ArrayRef getPathDiagnosticConsumers() = 0; + virtual ArrayRef> + getPathDiagnosticConsumers() = 0; virtual ASTContext &getASTContext() = 0; virtual SourceManager &getSourceManager() = 0; virtual AnalyzerOptions &getAnalyzerOptions() = 0; @@ -602,7 +603,8 @@ /// Generate and flush diagnostics for all bug reports. void FlushReports(); - ArrayRef getPathDiagnosticConsumers() { + ArrayRef> + getPathDiagnosticConsumers() { return D.getPathDiagnosticConsumers(); } @@ -656,9 +658,10 @@ protected: /// Generate the diagnostics for the given bug report. virtual std::unique_ptr - generateDiagnosticForConsumerMap(BugReport *exampleReport, - ArrayRef consumers, - ArrayRef bugReports); + generateDiagnosticForConsumerMap( + BugReport *exampleReport, + ArrayRef> consumers, + ArrayRef bugReports); }; /// GRBugReporter is used for generating path-sensitive reports. @@ -670,10 +673,11 @@ SmallVectorImpl &bugReports) override; /// Generate the diagnostics for the given bug report. - std::unique_ptr - generateDiagnosticForConsumerMap(BugReport *exampleReport, - ArrayRef consumers, - ArrayRef bugReports) override; + std::unique_ptr generateDiagnosticForConsumerMap( + BugReport *exampleReport, + ArrayRef> consumers, + ArrayRef bugReports) override; + public: PathSensitiveBugReporter(BugReporterData& d, ExprEngine& eng) : BugReporter(d), Eng(eng) {} @@ -692,7 +696,7 @@ /// Iterates through the bug reports within a single equivalence class, /// stops at a first non-invalidated report. std::unique_ptr generatePathDiagnostics( - ArrayRef consumers, + ArrayRef> consumers, ArrayRef &bugReports); void emitReport(std::unique_ptr R) override; diff --git a/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h --- a/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h @@ -29,8 +29,8 @@ namespace ento { -class PathDiagnosticConsumer; -typedef std::vector PathDiagnosticConsumers; +using PathDiagnosticConsumers = + std::vector>; #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \ void CREATEFN(PathDiagnosticConsumerOptions Diagopts, \ diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -47,7 +47,7 @@ AnalyzerOptions &options; AnalysisManager(ASTContext &ctx, Preprocessor &PP, - const PathDiagnosticConsumers &Consumers, + PathDiagnosticConsumers &&Consumers, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr, AnalyzerOptions &Options, @@ -91,10 +91,15 @@ return LangOpts; } - ArrayRef getPathDiagnosticConsumers() override { + ArrayRef> + getPathDiagnosticConsumers() override { return PathConsumers; } + void addDiagnosticConsumer(std::unique_ptr Consumer) { + PathConsumers.push_back(std::move(Consumer)); + } + void FlushDiagnostics(); bool shouldVisualize() const { diff --git a/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h --- a/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h +++ b/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h @@ -29,7 +29,8 @@ class AnalysisASTConsumer : public ASTConsumer { public: - virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) = 0; + virtual void + addDiagnosticConsumer(std::unique_ptr Consumer) = 0; /// This method allows registering statically linked custom checkers that are /// not a part of the Clang tree. It employs the same mechanism that is used diff --git a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp --- a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp @@ -14,7 +14,7 @@ void AnalysisManager::anchor() { } AnalysisManager::AnalysisManager(ASTContext &ASTCtx, Preprocessor &PP, - const PathDiagnosticConsumers &PDC, + PathDiagnosticConsumers &&PDC, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr, @@ -23,23 +23,19 @@ : AnaCtxMgr( ASTCtx, Options.UnoptimizedCFG, Options.ShouldIncludeImplicitDtorsInCFG, - /*addInitializers=*/true, - Options.ShouldIncludeTemporaryDtorsInCFG, + /*addInitializers=*/true, Options.ShouldIncludeTemporaryDtorsInCFG, Options.ShouldIncludeLifetimeInCFG, // Adding LoopExit elements to the CFG is a requirement for loop // unrolling. - Options.ShouldIncludeLoopExitInCFG || - Options.ShouldUnrollLoops, - Options.ShouldIncludeScopesInCFG, - Options.ShouldSynthesizeBodies, + Options.ShouldIncludeLoopExitInCFG || Options.ShouldUnrollLoops, + Options.ShouldIncludeScopesInCFG, Options.ShouldSynthesizeBodies, Options.ShouldConditionalizeStaticInitializers, /*addCXXNewAllocator=*/true, Options.ShouldIncludeRichConstructorsInCFG, Options.ShouldElideConstructors, - /*addVirtualBaseBranches=*/true, - injector), + /*addVirtualBaseBranches=*/true, injector), Ctx(ASTCtx), PP(PP), LangOpts(ASTCtx.getLangOpts()), - PathConsumers(PDC), CreateStoreMgr(storemgr), + PathConsumers(std::move(PDC)), CreateStoreMgr(storemgr), CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr), options(Options) { AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd(); @@ -48,16 +44,10 @@ Options.ShouldIncludeDefaultInitForAggregates; } -AnalysisManager::~AnalysisManager() { - FlushDiagnostics(); - for (PathDiagnosticConsumer *Consumer : PathConsumers) { - delete Consumer; - } -} +AnalysisManager::~AnalysisManager() { FlushDiagnostics(); } void AnalysisManager::FlushDiagnostics() { PathDiagnosticConsumer::FilesMade filesMade; - for (PathDiagnosticConsumer *Consumer : PathConsumers) { + for (const auto &Consumer : PathConsumers) Consumer->FlushDiagnostics(&filesMade); - } } diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2871,7 +2871,7 @@ std::unique_ptr PathSensitiveBugReporter::generatePathDiagnostics( - ArrayRef consumers, + ArrayRef> consumers, ArrayRef &bugReports) { assert(!bugReports.empty()); @@ -2881,9 +2881,9 @@ PathDiagnosticBuilder::findValidReport(bugReports, *this); if (PDB) { - for (PathDiagnosticConsumer *PC : consumers) { - if (std::unique_ptr PD = PDB->generate(PC)) { - (*Out)[PC] = std::move(PD); + for (const auto &PC : consumers) { + if (std::unique_ptr PD = PDB->generate(PC.get())) { + (*Out)[PC.get()] = std::move(PD); } } } @@ -3071,7 +3071,8 @@ return; } - ArrayRef Consumers = getPathDiagnosticConsumers(); + ArrayRef> Consumers = + getPathDiagnosticConsumers(); std::unique_ptr Diagnostics = generateDiagnosticForConsumerMap(report, Consumers, bugReports); @@ -3195,12 +3196,13 @@ std::unique_ptr BugReporter::generateDiagnosticForConsumerMap( - BugReport *exampleReport, ArrayRef consumers, + BugReport *exampleReport, + ArrayRef> consumers, ArrayRef bugReports) { auto *basicReport = cast(exampleReport); auto Out = std::make_unique(); - for (auto *Consumer : consumers) - (*Out)[Consumer] = generateDiagnosticForBasicReport(basicReport); + for (const auto &Consumer : consumers) + (*Out)[Consumer.get()] = generateDiagnosticForBasicReport(basicReport); return Out; } @@ -3267,11 +3269,10 @@ } } - - std::unique_ptr PathSensitiveBugReporter::generateDiagnosticForConsumerMap( - BugReport *exampleReport, ArrayRef consumers, + BugReport *exampleReport, + ArrayRef> consumers, ArrayRef bugReports) { std::vector BasicBugReports; std::vector PathSensitiveBugReports; diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp --- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -188,7 +188,8 @@ if (OutputDir.empty()) return; - C.push_back(new HTMLDiagnostics(std::move(DiagOpts), OutputDir, PP, true)); + C.push_back(std::make_unique(std::move(DiagOpts), OutputDir, + PP, true)); } void ento::createHTMLSingleFileDiagnosticConsumer( @@ -203,7 +204,8 @@ if (OutputDir.empty()) return; - C.push_back(new HTMLDiagnostics(std::move(DiagOpts), OutputDir, PP, false)); + C.push_back(std::make_unique(std::move(DiagOpts), OutputDir, + PP, false)); } void ento::createPlistHTMLDiagnosticConsumer( diff --git a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp --- a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -541,9 +541,9 @@ if (OutputFile.empty()) return; - C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU, - MacroExpansions, - /*supportsMultipleFiles=*/false)); + C.push_back(std::make_unique( + DiagOpts, OutputFile, PP, CTU, MacroExpansions, + /*supportsMultipleFiles=*/false)); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile, PP, CTU, MacroExpansions); } @@ -558,9 +558,9 @@ if (OutputFile.empty()) return; - C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU, - MacroExpansions, - /*supportsMultipleFiles=*/true)); + C.push_back(std::make_unique( + DiagOpts, OutputFile, PP, CTU, MacroExpansions, + /*supportsMultipleFiles=*/true)); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile, PP, CTU, MacroExpansions); } diff --git a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp --- a/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp @@ -23,6 +23,7 @@ #include "llvm/Support/ConvertUTF.h" #include "llvm/Support/JSON.h" #include "llvm/Support/Path.h" +#include using namespace llvm; using namespace clang; @@ -60,8 +61,8 @@ if (Output.empty()) return; - C.push_back( - new SarifDiagnostics(Output, PP.getLangOpts(), PP.getSourceManager())); + C.push_back(std::make_unique(Output, PP.getLangOpts(), + PP.getSourceManager())); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Output, PP, CTU, MacroExpansions); } diff --git a/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp --- a/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/TextDiagnostics.cpp @@ -139,9 +139,9 @@ const std::string &Prefix, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU, const MacroExpansionContext &MacroExpansions) { - C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(), - PP.getLangOpts(), - /*ShouldDisplayPathNotes=*/true)); + C.emplace_back(std::make_unique( + std::move(DiagOpts), PP.getDiagnostics(), PP.getLangOpts(), + /*ShouldDisplayPathNotes=*/true)); } void ento::createTextMinimalPathDiagnosticConsumer( @@ -149,7 +149,7 @@ const std::string &Prefix, const Preprocessor &PP, const cross_tu::CrossTranslationUnitContext &CTU, const MacroExpansionContext &MacroExpansions) { - C.emplace_back(new TextDiagnostics(std::move(DiagOpts), PP.getDiagnostics(), - PP.getLangOpts(), - /*ShouldDisplayPathNotes=*/false)); + C.emplace_back(std::make_unique( + std::move(DiagOpts), PP.getDiagnostics(), PP.getLangOpts(), + /*ShouldDisplayPathNotes=*/false)); } diff --git a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -101,8 +101,9 @@ MacroExpansionContext MacroExpansions; - // Set of PathDiagnosticConsumers. Owned by AnalysisManager. - PathDiagnosticConsumers PathConsumers; + // PathDiagnosticConsumers that is consumed by AnalysisManager once + // initialized. + PathDiagnosticConsumers TempPathConsumers; StoreManagerCreator CreateStoreMgr; ConstraintManagerCreator CreateConstraintMgr; @@ -161,7 +162,7 @@ break; #define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN) \ case PD_##NAME: \ - CREATEFN(Opts->getDiagOpts(), PathConsumers, OutDir, PP, CTU, \ + CREATEFN(Opts->getDiagOpts(), TempPathConsumers, OutDir, PP, CTU, \ MacroExpansions); \ break; #include "clang/StaticAnalyzer/Core/Analyses.def" @@ -225,9 +226,9 @@ checkerMgr = std::make_unique(*Ctx, *Opts, PP, Plugins, CheckerRegistrationFns); - Mgr = std::make_unique(*Ctx, PP, PathConsumers, - CreateStoreMgr, CreateConstraintMgr, - checkerMgr.get(), *Opts, Injector); + Mgr = std::make_unique( + *Ctx, PP, std::move(TempPathConsumers), CreateStoreMgr, + CreateConstraintMgr, checkerMgr.get(), *Opts, Injector); } /// Store the top level decls in the set to be processed later on. @@ -341,8 +342,10 @@ return true; } - void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) override { - PathConsumers.push_back(Consumer); + void addDiagnosticConsumer( + std::unique_ptr Consumer) override { + assert(Mgr); + Mgr->addDiagnosticConsumer(std::move(Consumer)); } void AddCheckerRegistrationFn(std::function Fn) override { diff --git a/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp b/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp --- a/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp +++ b/clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp @@ -19,6 +19,7 @@ #include "clang/StaticAnalyzer/Frontend/CheckerRegistry.h" #include "clang/Tooling/Tooling.h" #include "gtest/gtest.h" +#include using namespace clang; using namespace ento; @@ -112,8 +113,9 @@ StringRef File) override { std::unique_ptr AnalysisConsumer = CreateAnalysisConsumer(Compiler); - AnalysisConsumer->AddDiagnosticConsumer(new VerifyPathDiagnosticConsumer( - std::move(ExpectedDiags), Compiler.getSourceManager())); + AnalysisConsumer->addDiagnosticConsumer( + std::make_unique( + std::move(ExpectedDiags), Compiler.getSourceManager())); AnalysisConsumer->AddCheckerRegistrationFn([](CheckerRegistry &Registry) { Registry.addChecker("test.Interestingness", "Description", ""); diff --git a/clang/unittests/StaticAnalyzer/CheckerRegistration.h b/clang/unittests/StaticAnalyzer/CheckerRegistration.h --- a/clang/unittests/StaticAnalyzer/CheckerRegistration.h +++ b/clang/unittests/StaticAnalyzer/CheckerRegistration.h @@ -94,11 +94,11 @@ std::unique_ptr AnalysisConsumer = CreateAnalysisConsumer(Compiler); if (OnlyEmitWarnings) - AnalysisConsumer->AddDiagnosticConsumer( - new OnlyWarningsDiagConsumer(DiagsOutput)); + AnalysisConsumer->addDiagnosticConsumer( + std::make_unique(DiagsOutput)); else - AnalysisConsumer->AddDiagnosticConsumer( - new PathDiagConsumer(DiagsOutput)); + AnalysisConsumer->addDiagnosticConsumer( + std::make_unique(DiagsOutput)); addChecker(*AnalysisConsumer, *Compiler.getAnalyzerOpts()); return std::move(AnalysisConsumer); } diff --git a/clang/unittests/StaticAnalyzer/Reusables.h b/clang/unittests/StaticAnalyzer/Reusables.h --- a/clang/unittests/StaticAnalyzer/Reusables.h +++ b/clang/unittests/StaticAnalyzer/Reusables.h @@ -47,7 +47,6 @@ // We need to construct all of these in order to construct ExprEngine. CheckerManager ChkMgr; cross_tu::CrossTranslationUnitContext CTU; - PathDiagnosticConsumers Consumers; AnalysisManager AMgr; SetOfConstDecls VisitedCallees; FunctionSummariesTy FS; @@ -59,8 +58,8 @@ ExprEngineConsumer(CompilerInstance &C) : C(C), ChkMgr(C.getASTContext(), *C.getAnalyzerOpts(), C.getPreprocessor()), - CTU(C), Consumers(), - AMgr(C.getASTContext(), C.getPreprocessor(), Consumers, + CTU(C), + AMgr(C.getASTContext(), C.getPreprocessor(), PathDiagnosticConsumers{}, CreateRegionStoreManager, CreateRangeConstraintManager, &ChkMgr, *C.getAnalyzerOpts()), VisitedCallees(), FS(),