llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-static-analyzer-1 Author: Balazs Benics (steakhal) <details> <summary>Changes</summary> Reapply "[analyzer] Delay the checker constructions after parsing" (#<!-- -->128350) This reverts commit db836edf47f36ed04cab919a7a2c4414f4d0d7e6, as-is. Depends on #<!-- -->128368 --- Patch is 27.75 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/128369.diff 16 Files Affected: - (modified) clang/include/clang/Analysis/AnalysisDeclContext.h (+1-1) - (modified) clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h (+14-10) - (modified) clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h (+2-1) - (modified) clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h (+4-3) - (modified) clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h (+2-1) - (modified) clang/lib/Analysis/AnalysisDeclContext.cpp (+2-2) - (modified) clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp (+32-29) - (modified) clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp (+8-15) - (modified) clang/lib/StaticAnalyzer/Core/BugReporter.cpp (+11-11) - (modified) clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp (+4-2) - (modified) clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp (+6-6) - (modified) clang/lib/StaticAnalyzer/Core/SarifDiagnostics.cpp (+3-2) - (modified) clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (+16-17) - (modified) clang/unittests/StaticAnalyzer/BugReportInterestingnessTest.cpp (+4-2) - (modified) clang/unittests/StaticAnalyzer/CheckerRegistration.h (+2-2) - (modified) clang/unittests/StaticAnalyzer/Reusables.h (+3-4) ``````````diff diff --git a/clang/include/clang/Analysis/AnalysisDeclContext.h b/clang/include/clang/Analysis/AnalysisDeclContext.h index a517a4e757c9f..ced4bb8595bea 100644 --- a/clang/include/clang/Analysis/AnalysisDeclContext.h +++ b/clang/include/clang/Analysis/AnalysisDeclContext.h @@ -451,7 +451,7 @@ class AnalysisDeclContextManager { bool synthesizeBodies = false, bool addStaticInitBranches = false, bool addCXXNewAllocator = true, bool addRichCXXConstructors = true, bool markElidedCXXConstructors = true, bool addVirtualBaseBranches = true, - CodeInjector *injector = nullptr); + std::unique_ptr<CodeInjector> injector = nullptr); AnalysisDeclContext *getContext(const Decl *D); diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 7563d8bbd1d27..8e1d25b3eefa1 100644 --- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -570,7 +570,8 @@ class BugReporterData { public: virtual ~BugReporterData() = default; - virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0; + virtual ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> + getPathDiagnosticConsumers() = 0; virtual ASTContext &getASTContext() = 0; virtual SourceManager &getSourceManager() = 0; virtual AnalyzerOptions &getAnalyzerOptions() = 0; @@ -608,7 +609,8 @@ class BugReporter { /// Generate and flush diagnostics for all bug reports. void FlushReports(); - ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() { + ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> + getPathDiagnosticConsumers() { return D.getPathDiagnosticConsumers(); } @@ -670,9 +672,10 @@ class BugReporter { protected: /// Generate the diagnostics for the given bug report. virtual std::unique_ptr<DiagnosticForConsumerMapTy> - generateDiagnosticForConsumerMap(BugReport *exampleReport, - ArrayRef<PathDiagnosticConsumer *> consumers, - ArrayRef<BugReport *> bugReports); + generateDiagnosticForConsumerMap( + BugReport *exampleReport, + ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers, + ArrayRef<BugReport *> bugReports); }; /// GRBugReporter is used for generating path-sensitive reports. @@ -684,10 +687,11 @@ class PathSensitiveBugReporter final : public BugReporter { SmallVectorImpl<BugReport *> &bugReports) override; /// Generate the diagnostics for the given bug report. - std::unique_ptr<DiagnosticForConsumerMapTy> - generateDiagnosticForConsumerMap(BugReport *exampleReport, - ArrayRef<PathDiagnosticConsumer *> consumers, - ArrayRef<BugReport *> bugReports) override; + std::unique_ptr<DiagnosticForConsumerMapTy> generateDiagnosticForConsumerMap( + BugReport *exampleReport, + ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers, + ArrayRef<BugReport *> bugReports) override; + public: PathSensitiveBugReporter(BugReporterData& d, ExprEngine& eng) : BugReporter(d), Eng(eng) {} @@ -706,7 +710,7 @@ class PathSensitiveBugReporter final : public BugReporter { /// Iterates through the bug reports within a single equivalence class, /// stops at a first non-invalidated report. std::unique_ptr<DiagnosticForConsumerMapTy> generatePathDiagnostics( - ArrayRef<PathDiagnosticConsumer *> consumers, + ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers, ArrayRef<PathSensitiveBugReport *> &bugReports); void emitReport(std::unique_ptr<BugReport> R) override; diff --git a/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h index 88a9d76f24887..9fafd6acaa2ac 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h @@ -30,7 +30,8 @@ class CrossTranslationUnitContext; namespace ento { class PathDiagnosticConsumer; -typedef std::vector<PathDiagnosticConsumer*> PathDiagnosticConsumers; +using PathDiagnosticConsumers = + std::vector<std::unique_ptr<PathDiagnosticConsumer>>; #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 index c76e9c0326afe..e3cf1bac83ad0 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -47,11 +47,11 @@ class AnalysisManager : public BugReporterData { AnalyzerOptions &options; AnalysisManager(ASTContext &ctx, Preprocessor &PP, - const PathDiagnosticConsumers &Consumers, + PathDiagnosticConsumers Consumers, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr, AnalyzerOptions &Options, - CodeInjector *injector = nullptr); + std::unique_ptr<CodeInjector> injector = nullptr); ~AnalysisManager() override; @@ -91,7 +91,8 @@ class AnalysisManager : public BugReporterData { return LangOpts; } - ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() override { + ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> + getPathDiagnosticConsumers() override { return PathConsumers; } diff --git a/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h index f3b1c1f206459..2163d66466c1c 100644 --- a/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h +++ b/clang/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h @@ -29,7 +29,8 @@ class CheckerRegistry; class AnalysisASTConsumer : public ASTConsumer { public: - virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) = 0; + virtual void + AddDiagnosticConsumer(std::unique_ptr<PathDiagnosticConsumer> 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/Analysis/AnalysisDeclContext.cpp b/clang/lib/Analysis/AnalysisDeclContext.cpp index d3a1a993711fb..d0b663bd94580 100644 --- a/clang/lib/Analysis/AnalysisDeclContext.cpp +++ b/clang/lib/Analysis/AnalysisDeclContext.cpp @@ -71,8 +71,8 @@ AnalysisDeclContextManager::AnalysisDeclContextManager( bool addLoopExit, bool addScopes, bool synthesizeBodies, bool addStaticInitBranch, bool addCXXNewAllocator, bool addRichCXXConstructors, bool markElidedCXXConstructors, - bool addVirtualBaseBranches, CodeInjector *injector) - : Injector(injector), FunctionBodyFarm(ASTCtx, injector), + bool addVirtualBaseBranches, std::unique_ptr<CodeInjector> injector) + : Injector(std::move(injector)), FunctionBodyFarm(ASTCtx, Injector.get()), SynthesizeBodies(synthesizeBodies) { cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG; cfgBuildOptions.AddImplicitDtors = addImplicitDtors; diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index da2d16ca9b5dd..10dfa73cc522d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -40,17 +40,28 @@ enum class OpenVariant { OpenAt }; +static std::optional<int> getCreateFlagValue(const ASTContext &Ctx, + const Preprocessor &PP) { + std::optional<int> MacroVal = tryExpandAsInteger("O_CREAT", PP); + if (MacroVal.has_value()) + return MacroVal; + + // If we failed, fall-back to known values. + if (Ctx.getTargetInfo().getTriple().getVendor() == llvm::Triple::Apple) + return {0x0200}; + return MacroVal; +} + namespace { -class UnixAPIMisuseChecker - : public Checker<check::PreCall, check::ASTDecl<TranslationUnitDecl>> { +class UnixAPIMisuseChecker : public Checker<check::PreCall> { const BugType BT_open{this, "Improper use of 'open'", categories::UnixAPI}; const BugType BT_getline{this, "Improper use of getdelim", categories::UnixAPI}; const BugType BT_pthreadOnce{this, "Improper use of 'pthread_once'", categories::UnixAPI}; const BugType BT_ArgumentNull{this, "NULL pointer", categories::UnixAPI}; - mutable std::optional<uint64_t> Val_O_CREAT; + const std::optional<int> Val_O_CREAT; ProgramStateRef EnsurePtrNotNull(SVal PtrVal, const Expr *PtrExpr, CheckerContext &C, @@ -63,6 +74,9 @@ class UnixAPIMisuseChecker const Expr *SizePtrExpr, CheckerContext &C, ProgramStateRef State) const; public: + UnixAPIMisuseChecker(const ASTContext &Ctx, const Preprocessor &PP) + : Val_O_CREAT(getCreateFlagValue(Ctx, PP)) {} + void checkASTDecl(const TranslationUnitDecl *TU, AnalysisManager &Mgr, BugReporter &BR) const; @@ -134,20 +148,6 @@ ProgramStateRef UnixAPIMisuseChecker::EnsurePtrNotNull( return PtrNotNull; } -void UnixAPIMisuseChecker::checkASTDecl(const TranslationUnitDecl *TU, - AnalysisManager &Mgr, - BugReporter &) const { - // The definition of O_CREAT is platform specific. - // Try to get the macro value from the preprocessor. - Val_O_CREAT = tryExpandAsInteger("O_CREAT", Mgr.getPreprocessor()); - // If we failed, fall-back to known values. - if (!Val_O_CREAT) { - if (TU->getASTContext().getTargetInfo().getTriple().getVendor() == - llvm::Triple::Apple) - Val_O_CREAT = 0x0200; - } -} - //===----------------------------------------------------------------------===// // "open" (man 2 open) //===----------------------------------------------------------------------===/ @@ -262,7 +262,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, return; } - if (!Val_O_CREAT) { + if (!Val_O_CREAT.has_value()) { return; } @@ -276,7 +276,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, } NonLoc oflags = V.castAs<NonLoc>(); NonLoc ocreateFlag = C.getSValBuilder() - .makeIntVal(*Val_O_CREAT, oflagsEx->getType()) + .makeIntVal(Val_O_CREAT.value(), oflagsEx->getType()) .castAs<NonLoc>(); SVal maskedFlagsUC = C.getSValBuilder().evalBinOpNN(state, BO_And, oflags, ocreateFlag, @@ -621,14 +621,17 @@ void UnixAPIPortabilityChecker::checkPreStmt(const CallExpr *CE, // Registration. //===----------------------------------------------------------------------===// -#define REGISTER_CHECKER(CHECKERNAME) \ - void ento::register##CHECKERNAME(CheckerManager &mgr) { \ - mgr.registerChecker<CHECKERNAME>(); \ - } \ - \ - bool ento::shouldRegister##CHECKERNAME(const CheckerManager &mgr) { \ - return true; \ - } +void ento::registerUnixAPIMisuseChecker(CheckerManager &Mgr) { + Mgr.registerChecker<UnixAPIMisuseChecker>(Mgr.getASTContext(), + Mgr.getPreprocessor()); +} +bool ento::shouldRegisterUnixAPIMisuseChecker(const CheckerManager &Mgr) { + return true; +} -REGISTER_CHECKER(UnixAPIMisuseChecker) -REGISTER_CHECKER(UnixAPIPortabilityChecker) +void ento::registerUnixAPIPortabilityChecker(CheckerManager &Mgr) { + Mgr.registerChecker<UnixAPIPortabilityChecker>(); +} +bool ento::shouldRegisterUnixAPIPortabilityChecker(const CheckerManager &Mgr) { + return true; +} diff --git a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp index f9750db7b5017..8a16716f951b8 100644 --- a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp @@ -14,32 +14,28 @@ using namespace ento; void AnalysisManager::anchor() { } AnalysisManager::AnalysisManager(ASTContext &ASTCtx, Preprocessor &PP, - const PathDiagnosticConsumers &PDC, + PathDiagnosticConsumers PDC, StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr, AnalyzerOptions &Options, - CodeInjector *injector) + std::unique_ptr<CodeInjector> injector) : 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, std::move(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(); @@ -50,14 +46,11 @@ AnalysisManager::AnalysisManager(ASTContext &ASTCtx, Preprocessor &PP, AnalysisManager::~AnalysisManager() { FlushDiagnostics(); - for (PathDiagnosticConsumer *Consumer : PathConsumers) { - delete Consumer; - } } 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 index 13677ed341d0c..7101b1eb2c7f5 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2958,7 +2958,7 @@ std::optional<PathDiagnosticBuilder> PathDiagnosticBuilder::findValidReport( std::unique_ptr<DiagnosticForConsumerMapTy> PathSensitiveBugReporter::generatePathDiagnostics( - ArrayRef<PathDiagnosticConsumer *> consumers, + ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers, ArrayRef<PathSensitiveBugReport *> &bugReports) { assert(!bugReports.empty()); @@ -2968,9 +2968,9 @@ PathSensitiveBugReporter::generatePathDiagnostics( PathDiagnosticBuilder::findValidReport(bugReports, *this); if (PDB) { - for (PathDiagnosticConsumer *PC : consumers) { - if (std::unique_ptr<PathDiagnostic> PD = PDB->generate(PC)) { - (*Out)[PC] = std::move(PD); + for (const auto &PC : consumers) { + if (std::unique_ptr<PathDiagnostic> PD = PDB->generate(PC.get())) { + (*Out)[PC.get()] = std::move(PD); } } } @@ -3164,7 +3164,7 @@ void BugReporter::FlushReport(BugReportEquivClass &EQ) { return; } - ArrayRef<PathDiagnosticConsumer*> Consumers = getPathDiagnosticConsumers(); + ArrayRef Consumers = getPathDiagnosticConsumers(); std::unique_ptr<DiagnosticForConsumerMapTy> Diagnostics = generateDiagnosticForConsumerMap(report, Consumers, bugReports); @@ -3298,12 +3298,13 @@ findExecutedLines(const SourceManager &SM, const ExplodedNode *N) { std::unique_ptr<DiagnosticForConsumerMapTy> BugReporter::generateDiagnosticForConsumerMap( - BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers, + BugReport *exampleReport, + ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers, ArrayRef<BugReport *> bugReports) { auto *basicReport = cast<BasicBugReport>(exampleReport); auto Out = std::make_unique<DiagnosticForConsumerMapTy>(); - for (auto *Consumer : consumers) - (*Out)[Consumer] = + for (const auto &Consumer : consumers) + (*Out)[Consumer.get()] = generateDiagnosticForBasicReport(basicReport, AnalysisEntryPoint); return Out; } @@ -3371,11 +3372,10 @@ static void resetDiagnosticLocationToMainFile(PathDiagnostic &PD) { } } - - std::unique_ptr<DiagnosticForConsumerMapTy> PathSensitiveBugReporter::generateDiagnosticForConsumerMap( - BugReport *exampleReport, ArrayRef<PathDiagnosticConsumer *> consumers, + BugReport *exampleReport, + ArrayRef<std::unique_ptr<PathDiagnosticConsumer>> consumers, ArrayRef<BugReport *> bugReports) { std::vector<BasicBugReport *> BasicBugReports; std::vector<PathSensitiveBugReport *> PathSensitiveBugReports; diff --git a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp index 5c0df8808c272..21d99a359ca80 100644 --- a/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/HTMLDiagnostics.cpp @@ -193,7 +193,8 @@ void ento::createHTMLDiagnosticConsumer( if (OutputDir.empty()) return; - C.push_back(new HTMLDiagnostics(std::move(DiagOpts), OutputDir, PP, true)); + C.emplace_back(std::make_unique<HTMLDiagnostics>(std::move(DiagOpts), + OutputDir, PP, true)); } void ento::createHTMLSingleFileDiagnosticConsumer( @@ -208,7 +209,8 @@ void ento::createHTMLSingleFileDiagnosticConsumer( if (OutputDir.empty()) return; - C.push_back(new HTMLDiagnostics(std::move(DiagOpts), OutputDir, PP, false)); + C.emplace_back(std::make_unique<HTMLDiagnostics>(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 index d806d970acf8d..2ab248f9aa6d9 100644 --- a/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp +++ b/clang/lib/StaticAnalyzer/Core/PlistDiagnostics.cpp @@ -541,9 +541,9 @@ void ento::createPlistDiagnosticConsumer( if (OutputFile.empty()) return; - C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU, - MacroExpansions, - /*supportsMultipleFiles=*/false)); + C.push_back(std::make_unique<PlistDiagnostics>( + DiagOpts, OutputFile, PP, CTU, MacroExpansions, + /*supportsMultipleFiles=*/false)); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, OutputFile, PP, CTU, MacroExpansions); } @@ -558,9 +558,9 @@ void ento::createPlistMultiFileDiagnosticConsumer( if (OutputFile.empty()) return; - C.push_back(new PlistDiagnostics(DiagOpts, OutputFile, PP, CTU, - MacroExpansions, - /*supportsMultipleFiles=*/true)); + C.push_back(std::make_unique<PlistDiagnostics>( + DiagOpts, OutputFile, PP, CTU, MacroExpansions, + /*supportsMultipleFiles=*/true)); createTextMinimalPathDiagnosticConsumer(std::move(DiagOpts), C, Ou... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/128369 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits