https://github.com/steakhal updated https://github.com/llvm/llvm-project/pull/127409
>From 5eb1d222478c6966780f22aa664321807da87114 Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Sun, 16 Feb 2025 20:37:34 +0100 Subject: [PATCH 1/2] [analyzer] Delay the checker constructions after parsing If we were to delay checker constructions after we have a filled ASTContext, then we could get rid of a bunch of "lazy initializers" in checkers. Turns out in the register functions of the checkers we could transfer the ASTContext and all other things to checkers, so those could benefit from in-class initializers and const fields. For example, if a checker would take the ASTContext as the first field, then the rest of the fields could use it in their in-class initializers, so the ctor of the checker would only need to set a single field! This would open uup countless opportunities for cleaning up the asthetics of our checkers. I attached a single use-case for the AST and the PP as demonstrating purposes. You can imagine the rest. --- .../Core/PathSensitive/CheckerHelpers.h | 17 ++++++ .../Checkers/UnixAPIChecker.cpp | 61 ++++++++++--------- .../Frontend/AnalysisConsumer.cpp | 18 +++--- 3 files changed, 57 insertions(+), 39 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h index b4afaaeec9a4b..f7635aa0342d1 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h @@ -73,6 +73,23 @@ Nullability getNullabilityAnnotation(QualType Type); /// returned. std::optional<int> tryExpandAsInteger(StringRef Macro, const Preprocessor &PP); +class CachedMacroValue { +public: + CachedMacroValue(StringRef MacroSpelling, const Preprocessor &PP) + : MacroValueOrFailure(tryExpandAsInteger(MacroSpelling, PP)) {} + explicit CachedMacroValue(int ConcreteValue) + : MacroValueOrFailure(ConcreteValue) {} + + int valueOr(int Default) const { + return MacroValueOrFailure.value_or(Default); + } + bool hasValue() const { return MacroValueOrFailure.has_value(); } + int value() const { return MacroValueOrFailure.value(); } + +private: + std::optional<int> MacroValueOrFailure; +}; + class OperatorKind { union { BinaryOperatorKind Bin; diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index da2d16ca9b5dd..0452e541e8d5c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -40,17 +40,28 @@ enum class OpenVariant { OpenAt }; +static CachedMacroValue getCreateFlagValue(const ASTContext &Ctx, + const Preprocessor &PP) { + CachedMacroValue MacroVal("O_CREAT", PP); + if (MacroVal.hasValue()) + return MacroVal; + + // If we failed, fall-back to known values. + if (Ctx.getTargetInfo().getTriple().getVendor() == llvm::Triple::Apple) + return CachedMacroValue{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 CachedMacroValue 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.hasValue()) { 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/Frontend/AnalysisConsumer.cpp b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp index 189d7d6bede8e..db177b584b4f5 100644 --- a/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp @@ -224,16 +224,6 @@ class AnalysisConsumer : public AnalysisASTConsumer, } } - void Initialize(ASTContext &Context) override { - Ctx = &Context; - checkerMgr = std::make_unique<CheckerManager>(*Ctx, Opts, PP, Plugins, - CheckerRegistrationFns); - - Mgr = std::make_unique<AnalysisManager>(*Ctx, PP, PathConsumers, - CreateStoreMgr, CreateConstraintMgr, - checkerMgr.get(), Opts, Injector); - } - /// Store the top level decls in the set to be processed later on. /// (Doing this pre-processing avoids deserialization of data from PCH.) bool HandleTopLevelDecl(DeclGroupRef D) override; @@ -615,6 +605,14 @@ void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) { if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred()) return; + Ctx = &C; + checkerMgr = std::make_unique<CheckerManager>(*Ctx, Opts, PP, Plugins, + CheckerRegistrationFns); + + Mgr = std::make_unique<AnalysisManager>(*Ctx, PP, PathConsumers, + CreateStoreMgr, CreateConstraintMgr, + checkerMgr.get(), Opts, Injector); + // Explicitly destroy the PathDiagnosticConsumer. This will flush its output. // FIXME: This should be replaced with something that doesn't rely on // side-effects in PathDiagnosticConsumer's destructor. This is required when >From 10b4bd0403aa82a97f22a7fd55ee512625139091 Mon Sep 17 00:00:00 2001 From: Balazs Benics <benicsbal...@gmail.com> Date: Mon, 17 Feb 2025 15:14:04 +0100 Subject: [PATCH 2/2] Drop the CachedMacroValue class --- .../Core/PathSensitive/CheckerHelpers.h | 17 ----------------- .../StaticAnalyzer/Checkers/UnixAPIChecker.cpp | 14 +++++++------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h index f7635aa0342d1..b4afaaeec9a4b 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h @@ -73,23 +73,6 @@ Nullability getNullabilityAnnotation(QualType Type); /// returned. std::optional<int> tryExpandAsInteger(StringRef Macro, const Preprocessor &PP); -class CachedMacroValue { -public: - CachedMacroValue(StringRef MacroSpelling, const Preprocessor &PP) - : MacroValueOrFailure(tryExpandAsInteger(MacroSpelling, PP)) {} - explicit CachedMacroValue(int ConcreteValue) - : MacroValueOrFailure(ConcreteValue) {} - - int valueOr(int Default) const { - return MacroValueOrFailure.value_or(Default); - } - bool hasValue() const { return MacroValueOrFailure.has_value(); } - int value() const { return MacroValueOrFailure.value(); } - -private: - std::optional<int> MacroValueOrFailure; -}; - class OperatorKind { union { BinaryOperatorKind Bin; diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index 0452e541e8d5c..10dfa73cc522d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -40,15 +40,15 @@ enum class OpenVariant { OpenAt }; -static CachedMacroValue getCreateFlagValue(const ASTContext &Ctx, - const Preprocessor &PP) { - CachedMacroValue MacroVal("O_CREAT", PP); - if (MacroVal.hasValue()) +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 CachedMacroValue{0x0200}; + return {0x0200}; return MacroVal; } @@ -61,7 +61,7 @@ class UnixAPIMisuseChecker : public Checker<check::PreCall> { const BugType BT_pthreadOnce{this, "Improper use of 'pthread_once'", categories::UnixAPI}; const BugType BT_ArgumentNull{this, "NULL pointer", categories::UnixAPI}; - const CachedMacroValue Val_O_CREAT; + const std::optional<int> Val_O_CREAT; ProgramStateRef EnsurePtrNotNull(SVal PtrVal, const Expr *PtrExpr, CheckerContext &C, @@ -262,7 +262,7 @@ void UnixAPIMisuseChecker::CheckOpenVariant(CheckerContext &C, return; } - if (!Val_O_CREAT.hasValue()) { + if (!Val_O_CREAT.has_value()) { return; } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits