From 97c19eb0dcc494ff5940c35c56161943baac671a Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 11 Jan 2026 11:41:55 +0100 Subject: [PATCH 1/6] Add concepts for ProjectIRDB and IRDomain --- include/phasar/DB/ProjectIRDB.h | 88 +++++++++++++++++++ include/phasar/DB/ProjectIRDBBase.h | 7 +- .../phasar/DataFlow/IfdsIde/EntryPointUtils.h | 17 ++-- .../DataFlow/IfdsIde/IDETabulationProblem.h | 9 +- .../DataFlow/IfdsIde/IFDSTabulationProblem.h | 2 +- .../DataFlow/IfdsIde/Solver/Compressor.h | 5 +- .../phasar/DataFlow/Mono/InterMonoProblem.h | 5 +- .../phasar/DataFlow/Mono/IntraMonoProblem.h | 11 +-- include/phasar/Domain/IRDomain.h | 22 +++++ .../phasar/PhasarLLVM/DB/LLVMProjectIRDB.h | 3 + .../IfdsIde/DefaultAliasAwareIDEProblem.h | 4 +- ...efaultReachableAllocationSitesIDEProblem.h | 4 +- lib/PhasarLLVM/DB/LLVMProjectIRDB.cpp | 3 + .../Problems/IDETSAnalysisFileIOTest.cpp | 6 +- unittests/TestUtils/SrcCodeLocationEntry.h | 7 +- 15 files changed, 150 insertions(+), 43 deletions(-) create mode 100644 include/phasar/DB/ProjectIRDB.h create mode 100644 include/phasar/Domain/IRDomain.h diff --git a/include/phasar/DB/ProjectIRDB.h b/include/phasar/DB/ProjectIRDB.h new file mode 100644 index 0000000000..1af22c1c81 --- /dev/null +++ b/include/phasar/DB/ProjectIRDB.h @@ -0,0 +1,88 @@ +#pragma once + +#include "phasar/Utils/Nullable.h" +#include "phasar/Utils/TypeTraits.h" + +#include "llvm/ADT/StringRef.h" + +#include + +namespace psr { + +template +concept ProjectSymbolTable = requires(const T &ST, llvm::StringRef Name, + size_t InstId, typename T::n_t Inst) { + /// Reference to a Instruction/Statement + typename T::n_t; + /// Reference to a function + typename T::f_t; + /// Reference to a program module (potentially containing the whole + /// program) + typename T::m_t; + /// Reference to a Global Variable + typename T::g_t; + + /// Returns the function (declaration or definition) if available, + /// nullptr/nullopt otherwise. + { ST.getFunction(Name) } -> std::convertible_to>; + + /// Returns the function's definition if available, null otherwise. + { + ST.getFunctionDefinition(Name) + } -> std::convertible_to>; + + /// Returns whether the IRDB contains a function (declaration or + /// definition) with the given name. + { ST.hasFunction(Name) } -> std::convertible_to; + + /// Returns the global variable (declaration or definition) if available, + /// nullptr/nullopt otherwise. + { + ST.getGlobalVariable(Name) + } -> std::convertible_to>; + + /// Returns the global variable's definition if available, nullptr/nullopt + /// otherwise. + { + ST.getGlobalVariableDefinition(Name) + } -> std::convertible_to>; + + /// Returns the instruction to the corresponding Id. Returns + /// nullptr/nullopt, if there is no instruction for this Id + { + ST.getInstruction(InstId) + } -> std::convertible_to>; + + /// Returns an instruction's Id. The instruction must belong to the managed + /// module for this function to work. + /// + /// You can expect the instruction-ids to be sequential in the interval [0, + /// N), where N is the total number of managed instructions. + { ST.getInstructionId(Inst) } -> std::convertible_to; +}; + +/// This concept describes the minimum requirements for a project-IR-database. +/// Each phasar-analysis works on a program that is managed by a ProjectIRDB. +template +concept ProjectIRDB = requires(const T &DB) { + /// Returns the managed module + { DB.getModule() } noexcept -> std::convertible_to; + + /// Check if debug information are available. + { DB.debugInfoAvailable() } -> std::convertible_to; + + /// Returns a range of all function definitions and declarations available + { DB.getAllFunctions() } -> psr::is_iterable_over_v; + + /// Returns the number of functions in the managed module. + { DB.getNumFunctions() } -> std::convertible_to; + + /// Returns a range of all instructions available. + { DB.getAllInstructions() } -> psr::is_iterable_over_v; + + /// Returns the number of instruction in the managed module. + { DB.getNumInstructions() } -> std::convertible_to; + + requires ProjectSymbolTable; +}; +} // namespace psr diff --git a/include/phasar/DB/ProjectIRDBBase.h b/include/phasar/DB/ProjectIRDBBase.h index 60e08cd2ab..c30fffd342 100644 --- a/include/phasar/DB/ProjectIRDBBase.h +++ b/include/phasar/DB/ProjectIRDBBase.h @@ -37,7 +37,10 @@ template struct ProjectIRDBTraits { /// /// \remark XXX Once we have upgraded to C++20, we might want to use a concept /// instead... -template class ProjectIRDBBase { +template +class LLVM_DEPRECATED( + "This CRTP mixin is deprecated in favor of the ProjectIRDB-concept", + "Use ProjectIRDB instead") ProjectIRDBBase { public: using n_t = typename ProjectIRDBTraits::n_t; using f_t = typename ProjectIRDBTraits::f_t; @@ -81,7 +84,7 @@ template class ProjectIRDBBase { return self().hasFunctionImpl(FunctionName); } - /// Returns the global variable's definition if available, nullptr/nullopt + /// Returns the global variable if available, nullptr/nullopt /// otherwise. [[nodiscard]] Nullable getGlobalVariable(llvm::StringRef GlobalVariableName) const { diff --git a/include/phasar/DataFlow/IfdsIde/EntryPointUtils.h b/include/phasar/DataFlow/IfdsIde/EntryPointUtils.h index d5626a2e0d..90aa30ddc4 100644 --- a/include/phasar/DataFlow/IfdsIde/EntryPointUtils.h +++ b/include/phasar/DataFlow/IfdsIde/EntryPointUtils.h @@ -11,7 +11,7 @@ #define PHASAR_DATAFLOW_IFDSIDE_ENTRYPOINTUTILS_H #include "phasar/ControlFlow/CFGBase.h" -#include "phasar/DB/ProjectIRDBBase.h" +#include "phasar/DB/ProjectIRDB.h" #include "phasar/Domain/BinaryDomain.h" #include "llvm/ADT/STLExtras.h" @@ -57,9 +57,8 @@ void forallStartingPoints(const EntryRange &EntryPoints, const ICFGorIRDB *ICDB, } // namespace detail -template -void forallStartingPoints(const EntryRange &EntryPoints, - const ProjectIRDBBase *IRDB, +template +void forallStartingPoints(const EntryRange &EntryPoints, const DB *IRDB, const CFGBase &CFG, HandlerFn Handler) { return detail::forallStartingPoints(EntryPoints, IRDB, CFG, std::move(Handler)); @@ -71,12 +70,11 @@ void forallStartingPoints(const EntryRange &EntryPoints, const I *ICF, detail::forallStartingPoints(EntryPoints, ICF, *ICF, std::move(Handler)); } -template requires(std::is_convertible_v && std::is_convertible_v) -void addSeedsForStartingPoints(const EntryRange &EntryPoints, - const ProjectIRDBBase *IRDB, +void addSeedsForStartingPoints(const EntryRange &EntryPoints, const DB *IRDB, const CFGBase &CFG, SeedsT &Seeds, const D &ZeroValue, const L &BottomValue) { forallStartingPoints(EntryPoints, IRDB, CFG, @@ -99,12 +97,11 @@ void addSeedsForStartingPoints(const EntryRange &EntryPoints, const I *ICF, } /// Simplification for IFDS, passing BinaryDomain::BOTTOM as L -template requires(std::is_same_v && std::is_convertible_v) -void addSeedsForStartingPoints(const EntryRange &EntryPoints, - const ProjectIRDBBase *IRDB, +void addSeedsForStartingPoints(const EntryRange &EntryPoints, const DB *IRDB, const CFGBase &CFG, SeedsT &Seeds, const D &ZeroValue) { addSeedsForStartingPoints(EntryPoints, IRDB, CFG, Seeds, ZeroValue, diff --git a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h index b722ca7ae3..020441332e 100644 --- a/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IDETabulationProblem.h @@ -10,7 +10,6 @@ #ifndef PHASAR_DATAFLOW_IFDSIDE_IDETABULATIONPROBLEM_H_ #define PHASAR_DATAFLOW_IFDSIDE_IDETABULATIONPROBLEM_H_ -#include "phasar/DB/ProjectIRDBBase.h" #include "phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h" #include "phasar/DataFlow/IfdsIde/EdgeFunctions.h" #include "phasar/DataFlow/IfdsIde/EntryPointUtils.h" @@ -95,7 +94,7 @@ class IDETabulationProblem : public FlowFunctions, /// Λ). If not provided here, you must set it via \link initializeZeroValue() /// \endlink. explicit IDETabulationProblem( - const ProjectIRDBBase *IRDB, std::vector EntryPoints, + const db_t *IRDB, std::vector EntryPoints, std::optional ZeroValue) noexcept(std::is_nothrow_move_constructible_v) : IRDB(IRDB), EntryPoints(std::move(EntryPoints)), @@ -175,9 +174,7 @@ class IDETabulationProblem : public FlowFunctions, /// the level of soundness is ignored. Otherwise, true. virtual bool setSoundness(Soundness /*S*/) { return false; } - [[nodiscard]] const ProjectIRDBBase *getProjectIRDB() const noexcept { - return IRDB; - } + [[nodiscard]] const db_t *getProjectIRDB() const noexcept { return IRDB; } protected: typename FlowFunctions::FlowFunctionPtrType @@ -215,7 +212,7 @@ class IDETabulationProblem : public FlowFunctions, return Seeds; } - const ProjectIRDBBase *IRDB{}; + const db_t *IRDB{}; std::vector EntryPoints; std::optional ZeroValue; diff --git a/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h b/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h index 723f0acce3..33a9604f8d 100644 --- a/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h +++ b/include/phasar/DataFlow/IfdsIde/IFDSTabulationProblem.h @@ -55,7 +55,7 @@ class IFDSTabulationProblem /// @param[in] ZeroValue Provides the special tautological zero value (aka. /// Λ). /// \endlink. - explicit IFDSTabulationProblem(const ProjectIRDBBase *IRDB, + explicit IFDSTabulationProblem(const db_t *IRDB, std::vector EntryPoints, d_t ZeroValue) : Base(IRDB, std::move(EntryPoints), std::move(ZeroValue)) {} diff --git a/include/phasar/DataFlow/IfdsIde/Solver/Compressor.h b/include/phasar/DataFlow/IfdsIde/Solver/Compressor.h index fdeef7e304..7479bbd0c9 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/Compressor.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/Compressor.h @@ -1,7 +1,6 @@ #ifndef PHASAR_DATAFLOW_IFDSIDE_SOLVER_COMPRESSOR_H #define PHASAR_DATAFLOW_IFDSIDE_SOLVER_COMPRESSOR_H -#include "phasar/DB/ProjectIRDBBase.h" #include "phasar/Utils/ByRef.h" #include "phasar/Utils/Compressor.h" @@ -39,8 +38,8 @@ class LLVMProjectIRDB; template struct NodeCompressorTraits { using type = Compressor; - static type create(const ProjectIRDBBase - * /*IRDB*/) noexcept(noexcept(type())) { + static type + create(const LLVMProjectIRDB * /*IRDB*/) noexcept(noexcept(type())) { return type(); } }; diff --git a/include/phasar/DataFlow/Mono/InterMonoProblem.h b/include/phasar/DataFlow/Mono/InterMonoProblem.h index 326cf9df91..8c5981c2ed 100644 --- a/include/phasar/DataFlow/Mono/InterMonoProblem.h +++ b/include/phasar/DataFlow/Mono/InterMonoProblem.h @@ -58,9 +58,8 @@ class InterMonoProblem : public IntraMonoProblem { /// @param[in] CF A control flow graph based on the given IRDB. /// @param[in] PT Points-to information based on the given IRDB. /// @param[in] EntryPoints A vector of entry points. Provide at least one. - InterMonoProblem(const ProjectIRDBBase *IRDB, - const TypeHierarchy *TH, const i_t *ICF, - AliasInfoRef PT, + InterMonoProblem(const db_t *IRDB, const TypeHierarchy *TH, + const i_t *ICF, AliasInfoRef PT, std::vector EntryPoints = {}) : IntraMonoProblem(IRDB, TH, ICF, PT, EntryPoints), ICF(ICF) { diff --git a/include/phasar/DataFlow/Mono/IntraMonoProblem.h b/include/phasar/DataFlow/Mono/IntraMonoProblem.h index 954d2913a8..aa63dc22c8 100644 --- a/include/phasar/DataFlow/Mono/IntraMonoProblem.h +++ b/include/phasar/DataFlow/Mono/IntraMonoProblem.h @@ -53,7 +53,7 @@ template class IntraMonoProblem { using ProblemAnalysisDomain = AnalysisDomainTy; protected: - const ProjectIRDBBase *IRDB; + const db_t *IRDB; const TypeHierarchy *TH; const CFGBase *CF; AliasInfoRef PT; @@ -71,9 +71,8 @@ template class IntraMonoProblem { /// @param[in] CF A control flow graph based on the given IRDB. /// @param[in] PT Points-to information based on the given IRDB. /// @param[in] EntryPoints A vector of entry points. Provide at least one. - IntraMonoProblem(const ProjectIRDBBase *IRDB, - const TypeHierarchy *TH, const CFGBase *CF, - AliasInfoRef PT, + IntraMonoProblem(const db_t *IRDB, const TypeHierarchy *TH, + const CFGBase *CF, AliasInfoRef PT, std::vector EntryPoints = {}) : IRDB(IRDB), TH(TH), CF(CF), PT(PT), EntryPoints(std::move(EntryPoints)) {} @@ -96,9 +95,7 @@ template class IntraMonoProblem { return EntryPoints; } - [[nodiscard]] const ProjectIRDBBase *getProjectIRDB() const { - return IRDB; - } + [[nodiscard]] const db_t *getProjectIRDB() const { return IRDB; } [[nodiscard]] const TypeHierarchy *getTypeHierarchy() const { return TH; diff --git a/include/phasar/Domain/IRDomain.h b/include/phasar/Domain/IRDomain.h new file mode 100644 index 0000000000..1d524f0c5d --- /dev/null +++ b/include/phasar/Domain/IRDomain.h @@ -0,0 +1,22 @@ +#pragma once + +#include "phasar/DB/ProjectIRDB.h" + +namespace psr { +/// Describes useful properties of the program intermediate representation (IR). +template +concept IRDomain = requires() { + /// (Control-flow) Node --- Specifies the type of a node in the + /// (inter-procedural) control-flow graph and can be though of as an + /// individual statement or instruction of the target program. + typename T::n_t; + /// Function --- Specifies the type of functions/procedures in the target + /// program. + typename T::f_t; + /// (Pointer) value --- Specifies the type of pointers. + typename T::v_t; + /// The ProjectIRDB type --- Provides access to the IR. + typename T::db_t; + requires ProjectIRDB; +}; +} // namespace psr diff --git a/include/phasar/PhasarLLVM/DB/LLVMProjectIRDB.h b/include/phasar/PhasarLLVM/DB/LLVMProjectIRDB.h index d079bbd9db..aaeb884cf7 100644 --- a/include/phasar/PhasarLLVM/DB/LLVMProjectIRDB.h +++ b/include/phasar/PhasarLLVM/DB/LLVMProjectIRDB.h @@ -38,7 +38,10 @@ template <> struct ProjectIRDBTraits { }; /// \brief Project IR Database that manages a LLVM IR module. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" class LLVMProjectIRDB : public ProjectIRDBBase { +#pragma GCC diagnostic pop friend ProjectIRDBBase; public: diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h index fbe5e3d14e..1394608607 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultAliasAwareIDEProblem.h @@ -77,7 +77,7 @@ class DefaultAliasAwareIDEProblem /// \note It is useful to use an instance of FilteredAliasSet for the alias /// information to lower suprious aliases explicit DefaultAliasAwareIDEProblem( - const ProjectIRDBBase *IRDB, LLVMAliasIteratorRef AS, + const db_t *IRDB, LLVMAliasIteratorRef AS, std::vector EntryPoints, std::optional ZeroValue) noexcept(std::is_nothrow_move_constructible_v) @@ -124,7 +124,7 @@ class DefaultAliasAwareIFDSProblem /// \note It is useful to use an instance of FilteredAliasSet for the alias /// information to lower suprious aliases explicit DefaultAliasAwareIFDSProblem( - const ProjectIRDBBase *IRDB, LLVMAliasIteratorRef AS, + const db_t *IRDB, LLVMAliasIteratorRef AS, std::vector EntryPoints, d_t ZeroValue) noexcept(std::is_nothrow_move_constructible_v) : IFDSTabulationProblem(IRDB, std::move(EntryPoints), ZeroValue), diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h index 783df3c193..ffec300b26 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/DefaultReachableAllocationSitesIDEProblem.h @@ -77,7 +77,7 @@ class DefaultReachableAllocationSitesIDEProblem /// \note It is useful to use an instance of FilteredAliasSet for the alias /// information to lower suprious aliases explicit DefaultReachableAllocationSitesIDEProblem( - const ProjectIRDBBase *IRDB, LLVMPointsToIteratorRef AS, + const db_t *IRDB, LLVMPointsToIteratorRef AS, std::vector EntryPoints, std::optional ZeroValue) noexcept(std::is_nothrow_move_constructible_v) @@ -125,7 +125,7 @@ class DefaultReachableAllocationSitesIFDSProblem /// \note It is useful to use an instance of FilteredAliasSet for the alias /// information to lower suprious aliases explicit DefaultReachableAllocationSitesIFDSProblem( - const ProjectIRDBBase *IRDB, LLVMPointsToIteratorRef AS, + const db_t *IRDB, LLVMPointsToIteratorRef AS, std::vector EntryPoints, d_t ZeroValue) noexcept(std::is_nothrow_move_constructible_v) : IFDSTabulationProblem(IRDB, std::move(EntryPoints), ZeroValue), diff --git a/lib/PhasarLLVM/DB/LLVMProjectIRDB.cpp b/lib/PhasarLLVM/DB/LLVMProjectIRDB.cpp index 2cf6eccc54..f6fe8de817 100644 --- a/lib/PhasarLLVM/DB/LLVMProjectIRDB.cpp +++ b/lib/PhasarLLVM/DB/LLVMProjectIRDB.cpp @@ -1,6 +1,7 @@ #include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/Config/Configuration.h" +#include "phasar/DB/ProjectIRDB.h" #include "phasar/PhasarLLVM/Utils/LLVMShorthands.h" #include "phasar/Utils/Logger.h" #include "phasar/Utils/Macros.h" @@ -24,6 +25,8 @@ namespace psr { +static_assert(ProjectIRDB); + [[deprecated]] static void setOpaquePointersForCtx(llvm::LLVMContext &Ctx, bool Enable) { #if LLVM_VERSION_MAJOR >= 15 && LLVM_VERSION_MAJOR < 17 diff --git a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp index db858dd575..0b4ff582ca 100644 --- a/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp +++ b/unittests/PhasarLLVM/DataFlow/IfdsIde/Problems/IDETSAnalysisFileIOTest.cpp @@ -64,9 +64,9 @@ class IDETSAnalysisFileIOTest : public ::testing::Test { using GroundTruthMapTy = std::map>; - [[nodiscard]] static inline auto convertTestingLocationMapMapInIR( - const GroundTruthMapTy &Locs, - const ProjectIRDBBase &IRDB) { + [[nodiscard]] static inline auto + convertTestingLocationMapMapInIR(const GroundTruthMapTy &Locs, + const LLVMProjectIRDB &IRDB) { std::map> Ret; llvm::transform( Locs, std::inserter(Ret, Ret.end()), [&](const auto &LocAndSet) { diff --git a/unittests/TestUtils/SrcCodeLocationEntry.h b/unittests/TestUtils/SrcCodeLocationEntry.h index 9cfafd1cb8..26a993fc6f 100644 --- a/unittests/TestUtils/SrcCodeLocationEntry.h +++ b/unittests/TestUtils/SrcCodeLocationEntry.h @@ -297,8 +297,7 @@ getInstAtOrNull(const llvm::Function *F, uint32_t ReqLine, } [[nodiscard]] inline const llvm::Value * -testingLocInIR(TestingSrcLocation Loc, - const ProjectIRDBBase &IRDB, +testingLocInIR(TestingSrcLocation Loc, const LLVMProjectIRDB &IRDB, const llvm::Function *InterestingFunction = nullptr) { const auto GetFunction = [&IRDB](llvm::StringRef Name) { const auto *InFun = IRDB.getFunctionDefinition(Name); @@ -411,7 +410,7 @@ testingLocInIR(TestingSrcLocation Loc, template [[nodiscard]] inline std::set convertTestingLocationSetInIR( - const SetTy &Locs, const ProjectIRDBBase &IRDB, + const SetTy &Locs, const LLVMProjectIRDB &IRDB, const llvm::Function *InterestingFunction = nullptr) { std::set Ret; llvm::transform(Locs, std::inserter(Ret, Ret.end()), @@ -423,7 +422,7 @@ convertTestingLocationSetInIR( template [[nodiscard]] inline auto convertTestingLocationSetMapInIR( - const MapTy &Locs, const ProjectIRDBBase &IRDB, + const MapTy &Locs, const LLVMProjectIRDB &IRDB, const llvm::Function *InterestingFunction = nullptr) { std::map> Ret; llvm::transform( From 2443b591d57d6a271f4ba73e1ac5dd348b9b0c39 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 11 Jan 2026 15:55:28 +0100 Subject: [PATCH 2/6] Add comcepts for CFG --- BreakingChanges.md | 1 + include/phasar/ControlFlow/CFG.h | 91 +++++++++++++++++++ include/phasar/ControlFlow/CFGBase.h | 7 +- include/phasar/DB/ProjectIRDB.h | 8 ++ .../phasar/DataFlow/IfdsIde/EntryPointUtils.h | 25 +++-- .../phasar/DataFlow/Mono/InterMonoProblem.h | 12 +-- .../phasar/DataFlow/Mono/IntraMonoProblem.h | 27 +++--- .../DataFlow/Mono/Solver/IntraMonoSolver.h | 2 +- include/phasar/Domain/AnalysisDomain.h | 21 +++++ include/phasar/Domain/IRDomain.h | 15 +++ .../InterMonoFullConstantPropagation.h | 1 - .../Mono/Problems/InterMonoSolverTest.h | 5 +- .../Mono/Problems/InterMonoTaintAnalysis.h | 7 +- .../IntraMonoFullConstantPropagation.h | 3 +- .../Mono/Problems/IntraMonoSolverTest.h | 5 +- .../Mono/Problems/IntraMonoUninitVariables.h | 7 +- .../PhasarLLVM/Domain/LLVMAnalysisDomain.h | 20 +++- .../PhasarLLVM/SimpleAnalysisConstructor.h | 5 + include/phasar/Utils/TypeTraits.h | 2 +- .../InterMonoFullConstantPropagation.cpp | 8 +- .../Mono/Problems/InterMonoSolverTest.cpp | 3 +- .../Mono/Problems/InterMonoTaintAnalysis.cpp | 5 +- .../IntraMonoFullConstantPropagation.cpp | 5 +- .../Mono/Problems/IntraMonoSolverTest.cpp | 3 +- .../Problems/IntraMonoUninitVariables.cpp | 5 +- lib/PhasarPass/PhasarPass.cpp | 4 +- 26 files changed, 219 insertions(+), 78 deletions(-) create mode 100644 include/phasar/ControlFlow/CFG.h diff --git a/BreakingChanges.md b/BreakingChanges.md index acb51fa4a9..c343795c6a 100644 --- a/BreakingChanges.md +++ b/BreakingChanges.md @@ -2,6 +2,7 @@ ## development HEAD +- `IntraMonoProblem` and `InterMonoProblem`, and all reference-implementations of these problems do not receive a TypeHierarchy-pointer anymore in the ctor. - Requiring C++20 instead of C++17 - Type-traits and other templates that are specialized now use `requires` instead of `enable_if`, wherever possible. This may reduce the number of (defaulted) template parameters in some cases. - The `AdjacencyList` struct now now has one more template argument to denote the intege-like `vertex_t` type. It is the second template argument (which previously was the EdgeType). The edge-type is now denoted by the *third* template argument. diff --git a/include/phasar/ControlFlow/CFG.h b/include/phasar/ControlFlow/CFG.h new file mode 100644 index 0000000000..961fc9847e --- /dev/null +++ b/include/phasar/ControlFlow/CFG.h @@ -0,0 +1,91 @@ +/****************************************************************************** + * Copyright (c) 2026 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel and others + *****************************************************************************/ +#pragma once + +#include "phasar/Utils/TypeTraits.h" + +#include "llvm/Support/raw_ostream.h" + +#include +#include + +namespace psr { + +template +concept InstructionClassifier = + requires(const T &IC, typename T::n_t Inst, typename T::n_t Succ) { + { IC.isCallSite(Inst) } -> std::convertible_to; + { IC.isFieldLoad(Inst) } -> std::convertible_to; + { IC.isFieldStore(Inst) } -> std::convertible_to; + { IC.isFallThroughSuccessor(Inst, Succ) } -> std::convertible_to; + { IC.isBranchTarget(Inst, Succ) } -> std::convertible_to; + }; + +template +concept CFG = requires(const T &CF, typename T::n_t Inst, typename T::f_t Fun) { + typename T::n_t; + typename T::f_t; + + /// Returns an iterable range of all predecessor instructions of Inst in the + /// CFG + // TODO: Actually belongs into ProjectIRDB! + { CF.getFunctionOf(Inst) } -> std::convertible_to; + /// Returns an iterable range of all instructions of the given function that + /// are part of the control-flow graph. + // TODO: We should have sth like this in the ProjectIRDB as well! + { CF.getAllInstructionsOf(Fun) } -> psr::is_iterable_over_v; + + /// Returns an iterable range of all successor instructions of Inst in the + /// CFG. + /// NOTE: This function is typically being called in a hot part of the + /// analysis and should therefore be highly optimized for performance. + { CF.getSuccsOf(Inst) } -> psr::is_iterable_over_v; + + /// Returns an iterable range of all starting instructions of the given + /// function. For a forward-CFG, this is typically a singleton range. + { CF.getStartPointsOf(Fun) } -> psr::is_iterable_over_v; + + /// Returns whether the given Inst is a root node of the CFG + { CF.isStartPoint(Inst) } -> std::convertible_to; + + /// Returns whether the given Inst is a leaf node of the CFG + { CF.isExitInst(Inst) } -> std::convertible_to; + + requires InstructionClassifier; +}; + +template +concept BidiCFG = + CFG && requires(const T &CF, typename T::n_t Inst, typename T::f_t Fun) { + /// Returns an iterable range of all predecessor instructions of Inst in + /// the CFG + { CF.getPredsOf(Inst) } -> psr::is_iterable_over_v; + + /// Returns an iterable range of all exit instructions (often return + /// instructions) of the given function. For a backward-CFG, this is + /// typically a singleton range + { CF.getExitPointsOf(Fun) } -> psr::is_iterable_over_v; + }; + +template +concept CFGDump = requires(const T &CF, typename T::n_t Inst, + typename T::f_t Fun, llvm::raw_ostream &OS) { + { CF.getStatementId(Inst) } -> psr::is_string_like_v; + { CF.getFunctionName(Fun) } -> psr::is_string_like_v; + { CF.getDemangledFunctionName(Fun) } -> psr::is_string_like_v; + CF.print(Fun, OS); +}; + +template +concept CFGEdgesProvider = requires(const T &CF, typename T::f_t Fun) { + { + CF.getAllControlFlowEdges(Fun) + } -> psr::is_iterable_over_v>; +}; +} // namespace psr diff --git a/include/phasar/ControlFlow/CFGBase.h b/include/phasar/ControlFlow/CFGBase.h index 3523600428..28fdd7c995 100644 --- a/include/phasar/ControlFlow/CFGBase.h +++ b/include/phasar/ControlFlow/CFGBase.h @@ -10,6 +10,7 @@ #ifndef PHASAR_CONTROLFLOW_CFGBASE_H #define PHASAR_CONTROLFLOW_CFGBASE_H +#include "phasar/ControlFlow/CFG.h" #include "phasar/Utils/ByRef.h" #include "phasar/Utils/CRTPUtils.h" #include "phasar/Utils/TypeTraits.h" @@ -139,9 +140,9 @@ template class CFGBase : public CRTPBase { template // NOLINTNEXTLINE(readability-identifier-naming) -concept is_cfg_v = is_crtp_base_of_v && - std::is_same_v && - std::is_same_v; +concept is_cfg_v = BidiCFG && CFGDump && CFGEdgesProvider && + std::same_as && + std::same_as; } // namespace psr diff --git a/include/phasar/DB/ProjectIRDB.h b/include/phasar/DB/ProjectIRDB.h index 1af22c1c81..6a0487c2ae 100644 --- a/include/phasar/DB/ProjectIRDB.h +++ b/include/phasar/DB/ProjectIRDB.h @@ -1,3 +1,11 @@ +/****************************************************************************** + * Copyright (c) 2026 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel and others + *****************************************************************************/ #pragma once #include "phasar/Utils/Nullable.h" diff --git a/include/phasar/DataFlow/IfdsIde/EntryPointUtils.h b/include/phasar/DataFlow/IfdsIde/EntryPointUtils.h index 90aa30ddc4..b449f7794e 100644 --- a/include/phasar/DataFlow/IfdsIde/EntryPointUtils.h +++ b/include/phasar/DataFlow/IfdsIde/EntryPointUtils.h @@ -10,7 +10,7 @@ #ifndef PHASAR_DATAFLOW_IFDSIDE_ENTRYPOINTUTILS_H #define PHASAR_DATAFLOW_IFDSIDE_ENTRYPOINTUTILS_H -#include "phasar/ControlFlow/CFGBase.h" +#include "phasar/ControlFlow/CFG.h" #include "phasar/DB/ProjectIRDB.h" #include "phasar/Domain/BinaryDomain.h" @@ -22,8 +22,8 @@ namespace psr { namespace detail { -template -void forallStartingPoints(const EntryRange &EntryPoints, const CFGBase &CFG, +template +void forallStartingPoints(const EntryRange &EntryPoints, const C &CFG, HandlerFn Handler) { for (const auto &EntryPointFn : EntryPoints) { if constexpr (std::is_convertible_v, @@ -38,10 +38,9 @@ void forallStartingPoints(const EntryRange &EntryPoints, const CFGBase &CFG, } } -template +template void forallStartingPoints(const EntryRange &EntryPoints, const ICFGorIRDB *ICDB, - const CFGBase &CFG, HandlerFn Handler) { + const C &CFG, HandlerFn Handler) { if (llvm::hasSingleElement(EntryPoints) && *llvm::adl_begin(EntryPoints) == "__ALL__") { @@ -57,9 +56,9 @@ void forallStartingPoints(const EntryRange &EntryPoints, const ICFGorIRDB *ICDB, } // namespace detail -template +template void forallStartingPoints(const EntryRange &EntryPoints, const DB *IRDB, - const CFGBase &CFG, HandlerFn Handler) { + const C &CFG, HandlerFn Handler) { return detail::forallStartingPoints(EntryPoints, IRDB, CFG, std::move(Handler)); } @@ -70,13 +69,13 @@ void forallStartingPoints(const EntryRange &EntryPoints, const I *ICF, detail::forallStartingPoints(EntryPoints, ICF, *ICF, std::move(Handler)); } -template requires(std::is_convertible_v && std::is_convertible_v) void addSeedsForStartingPoints(const EntryRange &EntryPoints, const DB *IRDB, - const CFGBase &CFG, SeedsT &Seeds, - const D &ZeroValue, const L &BottomValue) { + const C &CFG, SeedsT &Seeds, const D &ZeroValue, + const L &BottomValue) { forallStartingPoints(EntryPoints, IRDB, CFG, [&Seeds, &ZeroValue, &BottomValue](const auto &SP) { Seeds.addSeed(SP, ZeroValue, BottomValue); @@ -97,12 +96,12 @@ void addSeedsForStartingPoints(const EntryRange &EntryPoints, const I *ICF, } /// Simplification for IFDS, passing BinaryDomain::BOTTOM as L -template requires(std::is_same_v && std::is_convertible_v) void addSeedsForStartingPoints(const EntryRange &EntryPoints, const DB *IRDB, - const CFGBase &CFG, SeedsT &Seeds, + const C &CFG, SeedsT &Seeds, const D &ZeroValue) { addSeedsForStartingPoints(EntryPoints, IRDB, CFG, Seeds, ZeroValue, BinaryDomain::BOTTOM); diff --git a/include/phasar/DataFlow/Mono/InterMonoProblem.h b/include/phasar/DataFlow/Mono/InterMonoProblem.h index 8c5981c2ed..bee1c85b7b 100644 --- a/include/phasar/DataFlow/Mono/InterMonoProblem.h +++ b/include/phasar/DataFlow/Mono/InterMonoProblem.h @@ -28,13 +28,14 @@ namespace psr { -template class TypeHierarchy; -template class ICFG; +template +concept InterMonoAnalysisDomain = + MonoAnalysisDomain && requires() { typename T::i_t; }; /// \brief The analysis problem interface for interprocedural monotone problems /// (solvable by the InterMonoSolver). Create a subclass from this and override /// all pure-virtual functions to create your own inter-mono analysis. -template +template class InterMonoProblem : public IntraMonoProblem { public: using n_t = typename AnalysisDomainTy::n_t; @@ -58,10 +59,9 @@ class InterMonoProblem : public IntraMonoProblem { /// @param[in] CF A control flow graph based on the given IRDB. /// @param[in] PT Points-to information based on the given IRDB. /// @param[in] EntryPoints A vector of entry points. Provide at least one. - InterMonoProblem(const db_t *IRDB, const TypeHierarchy *TH, - const i_t *ICF, AliasInfoRef PT, + InterMonoProblem(const db_t *IRDB, const i_t *ICF, AliasInfoRef PT, std::vector EntryPoints = {}) - : IntraMonoProblem(IRDB, TH, ICF, PT, EntryPoints), + : IntraMonoProblem(IRDB, ICF, PT, EntryPoints), ICF(ICF) { static_assert(is_icfg_v, "Type parameter i_t must implement the ICFG interface!"); diff --git a/include/phasar/DataFlow/Mono/IntraMonoProblem.h b/include/phasar/DataFlow/Mono/IntraMonoProblem.h index aa63dc22c8..fddc862997 100644 --- a/include/phasar/DataFlow/Mono/IntraMonoProblem.h +++ b/include/phasar/DataFlow/Mono/IntraMonoProblem.h @@ -17,8 +17,8 @@ #ifndef PHASAR_DATAFLOW_MONO_INTRAMONOPROBLEM_H #define PHASAR_DATAFLOW_MONO_INTRAMONOPROBLEM_H -#include "phasar/ControlFlow/CFGBase.h" -#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" +#include "phasar/ControlFlow/CFG.h" +#include "phasar/Domain/AnalysisDomain.h" #include "phasar/Pointer/AliasInfo.h" #include "phasar/Utils/Printer.h" #include "phasar/Utils/Soundness.h" @@ -32,13 +32,15 @@ namespace psr { struct HasNoConfigurationType; -template class TypeHierarchy; -template class CFG; +template +concept MonoAnalysisDomain = IsAnalysisDomain && BidiCFG && + CFGEdgesProvider && + requires() { typename T::mono_container_t; }; /// \brief The analysis problem interface for intraprocedural monotone problems /// (solvable by the IntraMonoSolver). Create a subclass from this and override /// all pure-virtual functions to create your own mono analysis. -template class IntraMonoProblem { +template class IntraMonoProblem { public: using n_t = typename AnalysisDomainTy::n_t; using d_t = typename AnalysisDomainTy::d_t; @@ -54,8 +56,7 @@ template class IntraMonoProblem { protected: const db_t *IRDB; - const TypeHierarchy *TH; - const CFGBase *CF; + const c_t *CF; AliasInfoRef PT; std::vector EntryPoints; [[maybe_unused]] Soundness S = Soundness::Soundy; @@ -71,11 +72,9 @@ template class IntraMonoProblem { /// @param[in] CF A control flow graph based on the given IRDB. /// @param[in] PT Points-to information based on the given IRDB. /// @param[in] EntryPoints A vector of entry points. Provide at least one. - IntraMonoProblem(const db_t *IRDB, const TypeHierarchy *TH, - const CFGBase *CF, AliasInfoRef PT, + IntraMonoProblem(const db_t *IRDB, const c_t *CF, AliasInfoRef PT, std::vector EntryPoints = {}) - : IRDB(IRDB), TH(TH), CF(CF), PT(PT), - EntryPoints(std::move(EntryPoints)) {} + : IRDB(IRDB), CF(CF), PT(PT), EntryPoints(std::move(EntryPoints)) {} virtual ~IntraMonoProblem() = default; @@ -97,11 +96,7 @@ template class IntraMonoProblem { [[nodiscard]] const db_t *getProjectIRDB() const { return IRDB; } - [[nodiscard]] const TypeHierarchy *getTypeHierarchy() const { - return TH; - } - - [[nodiscard]] const CFGBase *getCFG() const { return CF; } + [[nodiscard]] const c_t *getCFG() const { return CF; } [[nodiscard]] AliasInfoRef getPointstoInfo() const { return PT; } diff --git a/include/phasar/DataFlow/Mono/Solver/IntraMonoSolver.h b/include/phasar/DataFlow/Mono/Solver/IntraMonoSolver.h index ed5b1f449d..fbe48992bc 100644 --- a/include/phasar/DataFlow/Mono/Solver/IntraMonoSolver.h +++ b/include/phasar/DataFlow/Mono/Solver/IntraMonoSolver.h @@ -49,7 +49,7 @@ template class IntraMonoSolver { ProblemTy &IMProblem; std::deque> Worklist; std::unordered_map Analysis; - const CFGBase *CFG; + const c_t *CFG; void initialize() { const auto &EntryPoints = IMProblem.getEntryPoints(); diff --git a/include/phasar/Domain/AnalysisDomain.h b/include/phasar/Domain/AnalysisDomain.h index a4622695a8..6715ad0554 100644 --- a/include/phasar/Domain/AnalysisDomain.h +++ b/include/phasar/Domain/AnalysisDomain.h @@ -10,10 +10,29 @@ #ifndef PHASAR_DOMAIN_ANALYSISDOMAIN_H #define PHASAR_DOMAIN_ANALYSISDOMAIN_H +#include "phasar/ControlFlow/CFG.h" +#include "phasar/Domain/IRDomain.h" + #include namespace psr { +/// Minimum requirements of an analysis domain. Analyses may add extra +/// requirements. +template +concept IsAnalysisDomain = IRDomain && requires() { + typename T::ir_t; + requires IRDomain; + requires std::same_as; + requires std::same_as; + requires std::same_as; + requires std::same_as; + requires std::same_as; + + typename T::c_t; + requires CFG; +}; + /// AnalysisDomain - This class should be specialized by different static /// analyses types... which is why the default version declares all analysis /// domains as aliases of void. @@ -30,6 +49,8 @@ namespace psr { /// conduct an analysis but not correctly set, it will statically report an /// error and ask for the missing piece of information. struct AnalysisDomain { + /// Program IR + using ir_t = void; /// Data-flow fact --- Specifies the type of an individual data-flow fact that /// is propagated through the program under analysis. using d_t = void; diff --git a/include/phasar/Domain/IRDomain.h b/include/phasar/Domain/IRDomain.h index 1d524f0c5d..66a214ac87 100644 --- a/include/phasar/Domain/IRDomain.h +++ b/include/phasar/Domain/IRDomain.h @@ -1,3 +1,11 @@ +/****************************************************************************** + * Copyright (c) 2026 Fabian Schiebel. + * All rights reserved. This program and the accompanying materials are made + * available under the terms of LICENSE.txt. + * + * Contributors: + * Fabian Schiebel and others + *****************************************************************************/ #pragma once #include "phasar/DB/ProjectIRDB.h" @@ -10,11 +18,18 @@ concept IRDomain = requires() { /// (inter-procedural) control-flow graph and can be though of as an /// individual statement or instruction of the target program. typename T::n_t; + /// Function --- Specifies the type of functions/procedures in the target /// program. typename T::f_t; + /// (Pointer) value --- Specifies the type of pointers. typename T::v_t; + + /// (User-defined) type --- Specifies the type of a user-defined (i.e. struct + /// or class) data type. + typename T::t_t; + /// The ProjectIRDB type --- Provides access to the IR. typename T::db_t; requires ProjectIRDB; diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.h index d1e1ffce70..3b2c413f12 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoFullConstantPropagation.h @@ -48,7 +48,6 @@ class InterMonoFullConstantPropagation using mono_container_t = IntraMonoFullConstantPropagation::mono_container_t; InterMonoFullConstantPropagation(const LLVMProjectIRDB *IRDB, - const DIBasedTypeHierarchy *TH, const LLVMBasedICFG *ICF, LLVMAliasInfoRef PT, std::vector EntryPoints = {}); diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.h index a280365a53..88fd072cc7 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoSolverTest.h @@ -18,6 +18,8 @@ #define PHASAR_PHASARLLVM_DATAFLOW_MONO_PROBLEMS_INTERMONOSOLVERTEST_H #include "phasar/DataFlow/Mono/InterMonoProblem.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/Utils/BitVectorSet.h" @@ -52,8 +54,7 @@ class InterMonoSolverTest : public InterMonoProblem { using i_t = InterMonoSolverTestDomain::i_t; using mono_container_t = InterMonoSolverTestDomain::mono_container_t; - InterMonoSolverTest(const LLVMProjectIRDB *IRDB, - const DIBasedTypeHierarchy *TH, const LLVMBasedICFG *ICF, + InterMonoSolverTest(const LLVMProjectIRDB *IRDB, const LLVMBasedICFG *ICF, LLVMAliasInfoRef PT, std::vector EntryPoints = {}); diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.h index 7a78746ecf..e7391fc1e9 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/InterMonoTaintAnalysis.h @@ -19,6 +19,7 @@ #include "phasar/DataFlow/Mono/InterMonoProblem.h" #include "phasar/PhasarLLVM/ControlFlow/LLVMBasedICFG.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/PhasarLLVM/TaintConfig/LLVMTaintConfig.h" @@ -55,10 +56,8 @@ class InterMonoTaintAnalysis using mono_container_t = InterMonoTaintAnalysisDomain::mono_container_t; using ConfigurationTy = LLVMTaintConfig; - InterMonoTaintAnalysis(const LLVMProjectIRDB *IRDB, - const DIBasedTypeHierarchy *TH, - const LLVMBasedICFG *ICF, LLVMAliasInfoRef PT, - const LLVMTaintConfig &Config, + InterMonoTaintAnalysis(const LLVMProjectIRDB *IRDB, const LLVMBasedICFG *ICF, + LLVMAliasInfoRef PT, const LLVMTaintConfig &Config, std::vector EntryPoints = {}); ~InterMonoTaintAnalysis() override = default; diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.h index 0bebfc4e68..9600657ed5 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoFullConstantPropagation.h @@ -19,6 +19,8 @@ #include "phasar/DataFlow/Mono/IntraMonoProblem.h" #include "phasar/Domain/LatticeDomain.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/Utils/BitVectorSet.h" @@ -81,7 +83,6 @@ class IntraMonoFullConstantPropagation public: IntraMonoFullConstantPropagation(const LLVMProjectIRDB *IRDB, - const DIBasedTypeHierarchy *TH, const LLVMBasedCFG *CF, LLVMAliasInfoRef PT, std::vector EntryPoints = {}); diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.h index 75e31f25ef..cc664a6b54 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoSolverTest.h @@ -18,6 +18,8 @@ #define PHASAR_PHASARLLVM_DATAFLOW_MONO_PROBLEMS_INTRAMONOSOLVERTEST_H #include "phasar/DataFlow/Mono/IntraMonoProblem.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" #include "phasar/Utils/BitVectorSet.h" @@ -54,8 +56,7 @@ class IntraMonoSolverTest using i_t = IntraMonoSolverTestAnalysisDomain::i_t; using mono_container_t = IntraMonoSolverTestAnalysisDomain::mono_container_t; - IntraMonoSolverTest(const LLVMProjectIRDB *IRDB, - const DIBasedTypeHierarchy *TH, const LLVMBasedCFG *CF, + IntraMonoSolverTest(const LLVMProjectIRDB *IRDB, const LLVMBasedCFG *CF, LLVMAliasInfoRef PT, std::vector EntryPoints = {}); diff --git a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.h b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.h index b08b91179c..d7894565f2 100644 --- a/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.h +++ b/include/phasar/PhasarLLVM/DataFlow/Mono/Problems/IntraMonoUninitVariables.h @@ -11,6 +11,8 @@ #define PHASAR_PHASARLLVM_DATAFLOW_MONO_PROBLEMS_INTRAMONOUNINITVARIABLES_H #include "phasar/DataFlow/Mono/IntraMonoProblem.h" +#include "phasar/PhasarLLVM/ControlFlow/LLVMBasedCFG.h" +#include "phasar/PhasarLLVM/DB/LLVMProjectIRDB.h" #include "phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h" #include "phasar/PhasarLLVM/Pointer/LLVMAliasInfo.h" @@ -47,9 +49,8 @@ class IntraMonoUninitVariables using i_t = IntraMonoUninitVariablesDomain::i_t; using mono_container_t = IntraMonoUninitVariablesDomain::mono_container_t; - IntraMonoUninitVariables(const LLVMProjectIRDB *IRDB, - const DIBasedTypeHierarchy *TH, - const LLVMBasedCFG *CF, LLVMAliasInfoRef PT, + IntraMonoUninitVariables(const LLVMProjectIRDB *IRDB, const LLVMBasedCFG *CF, + LLVMAliasInfoRef PT, std::vector EntryPoints = {}); ~IntraMonoUninitVariables() override = default; diff --git a/include/phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h b/include/phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h index 80aadd85f9..45bf95f948 100644 --- a/include/phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h +++ b/include/phasar/PhasarLLVM/Domain/LLVMAnalysisDomain.h @@ -28,17 +28,27 @@ class LLVMProjectIRDB; class LLVMBasedICFG; class LLVMBasedCFG; +struct LLVMIRDomain { + using n_t = const llvm::Instruction *; + using f_t = const llvm::Function *; + using v_t = const llvm::Value *; + using t_t = const llvm::DIType *; + using db_t = LLVMProjectIRDB; +}; + /// \brief An AnalysisDomain that specializes sensible defaults for LLVM-based /// analysis struct LLVMAnalysisDomainDefault : public AnalysisDomain { + using ir_t = LLVMIRDomain; + using n_t = typename ir_t::n_t; + using f_t = typename ir_t::f_t; + using t_t = typename ir_t::t_t; + using v_t = typename ir_t::v_t; + using db_t = typename ir_t::db_t; + using d_t = const llvm::Value *; - using n_t = const llvm::Instruction *; - using f_t = const llvm::Function *; - using t_t = const llvm::DIType *; - using v_t = const llvm::Value *; using c_t = LLVMBasedCFG; using i_t = LLVMBasedICFG; - using db_t = LLVMProjectIRDB; }; /// \brief An AnalysisDomain that specializes sensible defaults for LLVM-based diff --git a/include/phasar/PhasarLLVM/SimpleAnalysisConstructor.h b/include/phasar/PhasarLLVM/SimpleAnalysisConstructor.h index e6e80094a9..ebc62aa065 100644 --- a/include/phasar/PhasarLLVM/SimpleAnalysisConstructor.h +++ b/include/phasar/PhasarLLVM/SimpleAnalysisConstructor.h @@ -57,6 +57,11 @@ ProblemTy createAnalysisProblem(HelperAnalyses &HA, ArgTys &&...Args) { return ProblemTy(&HA.getProjectIRDB(), &HA.getTypeHierarchy(), &HA.getICFG(), &HA.getAliasInfo(), std::forward(Args)...); + } else if constexpr (std::is_constructible_v< + ProblemTy, const LLVMProjectIRDB *, + const LLVMBasedCFG *, LLVMAliasSet *, ArgTys...>) { + return ProblemTy(&HA.getProjectIRDB(), &HA.getCFG(), &HA.getAliasInfo(), + std::forward(Args)...); } else { static_assert( std::is_constructible_v, diff --git a/include/phasar/Utils/TypeTraits.h b/include/phasar/Utils/TypeTraits.h index ffff49c225..579bb1c5a4 100644 --- a/include/phasar/Utils/TypeTraits.h +++ b/include/phasar/Utils/TypeTraits.h @@ -145,7 +145,7 @@ concept is_variant_v = is_variant::value; // NOLINT template // NOLINTNEXTLINE -concept is_string_like_v = std::is_convertible_v; +concept is_string_like_v = std::is_convertible_v; template