From 177a2f3c1db5ae27f020c3a3b415e7cb9b435a6f Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 11 Apr 2026 13:29:18 +0200 Subject: [PATCH 1/3] Make most namespace-scope operators hidden friends --- .../DataFlow/IfdsIde/EdgeFunctionUtils.h | 84 +++++---- .../DataFlow/IfdsIde/Solver/IDESolver.h | 14 +- include/phasar/Domain/LatticeDomain.h | 160 ++++++++---------- .../Problems/IDEInstInteractionAnalysis.h | 24 +-- .../Passes/GeneralStatisticsAnalysis.h | 6 +- include/phasar/TypeHierarchy/TypeHierarchy.h | 13 +- include/phasar/TypeHierarchy/VFTable.h | 13 +- include/phasar/Utils/DOTGraph.h | 28 +-- include/phasar/Utils/DebugOutput.h | 13 +- tools/ptaben/PTAResult.h | 4 +- tools/ptaben/PTAUtils.h | 8 +- tools/ptaben/QueryLocation.h | 3 + 12 files changed, 171 insertions(+), 199 deletions(-) diff --git a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h index 6d3df38b30..7c1718fa89 100644 --- a/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h +++ b/include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h @@ -69,49 +69,48 @@ template struct ConstantEdgeFunction { [[nodiscard]] constexpr bool isConstant() const noexcept { return true; } - // -- constant data member + [[nodiscard]] friend constexpr bool + operator==(ConstantEdgeFunction LHS, ConstantEdgeFunction RHS) noexcept + requires CanEfficientlyPassByValue + { + return LHS.Value == RHS.Value; + } - value_type Value{}; -}; + [[nodiscard]] friend constexpr bool + operator==(const ConstantEdgeFunction &LHS, + const ConstantEdgeFunction &RHS) noexcept + requires(!CanEfficientlyPassByValue) + { + return LHS.Value == RHS.Value; + } -template - requires CanEfficientlyPassByValue> -[[nodiscard]] constexpr bool operator==(ConstantEdgeFunction LHS, - ConstantEdgeFunction RHS) noexcept { - return LHS.Value == RHS.Value; -} + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const ConstantEdgeFunction &Id) { + OS << "ConstantEF"; + if constexpr (is_llvm_printable_v< + typename ConstantEdgeFunction::value_type>) { + OS << '[' << Id.Value << ']'; + } + return OS; + } -template - requires(!CanEfficientlyPassByValue>) -[[nodiscard]] constexpr bool -operator==(const ConstantEdgeFunction &LHS, - const ConstantEdgeFunction &RHS) noexcept { - return LHS.Value == RHS.Value; -} + [[nodiscard]] friend auto hash_value(const ConstantEdgeFunction &CEF) noexcept + requires(is_std_hashable_v::type> || + is_llvm_hashable_v::type>) + { + using value_type = typename ConstantEdgeFunction::value_type; + if constexpr (is_std_hashable_v) { + return std::hash{}(CEF.Value); + } else { + using llvm::hash_value; + return hash_value(CEF.Value); + } + } -template -[[nodiscard]] llvm::raw_ostream & -operator<<(llvm::raw_ostream &OS, ByConstRef> Id) { - OS << "ConstantEF"; - if constexpr (is_llvm_printable_v< - typename ConstantEdgeFunction::value_type>) { - OS << '[' << Id.Value << ']'; - } - return OS; -} + // -- constant data member -template - requires(is_std_hashable_v::type> || - is_llvm_hashable_v::type>) -[[nodiscard]] auto hash_value(const ConstantEdgeFunction &CEF) noexcept { - using value_type = typename ConstantEdgeFunction::value_type; - if constexpr (is_std_hashable_v) { - return std::hash{}(CEF.Value); - } else { - using llvm::hash_value; - return hash_value(CEF.Value); - } -} + value_type Value{}; +}; template struct AllBottom final { using l_t = L; @@ -295,6 +294,10 @@ template struct EdgeFunctionComposer { return First.depth() + Second.depth(); } + friend auto hash_value(const EdgeFunctionComposer &EFC) noexcept { + return llvm::hash_combine(EFC.First, EFC.Second); + } + // -- data members EdgeFunction First{}; @@ -303,11 +306,6 @@ template struct EdgeFunctionComposer { static_assert(HasDepth>); -template -auto hash_value(const EdgeFunctionComposer &EFC) noexcept { - return llvm::hash_combine(EFC.First, EFC.Second); -} - template struct JoinEdgeFunction { using l_t = L; using JLattice = JoinLatticeTraits; diff --git a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h index 3f1218d9dc..c7dc59e871 100644 --- a/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h +++ b/include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h @@ -215,6 +215,12 @@ class IDESolver getSolverResults().dumpResults(*ICF, OS); } + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const IDESolver &Solver) { + Solver.dumpResults(OS); + return OS; + } + void dumpAllInterPathEdges() { llvm::outs() << "COMPUTED INTER PATH EDGES" << '\n'; auto Interpe = this->computedInterPathEdges.cellSet(); @@ -1917,14 +1923,6 @@ class IDESolver std::map, size_t> FSummaryReuse; }; -template -llvm::raw_ostream & -operator<<(llvm::raw_ostream &OS, - const IDESolver &Solver) { - Solver.dumpResults(OS); - return OS; -} - template IDESolver(Problem &, ICF *) -> IDESolver struct LatticeDomain : public std::variant { using std::variant::variant; - [[nodiscard]] inline bool isBottom() const noexcept { + [[nodiscard]] constexpr bool isBottom() const noexcept { return std::holds_alternative(*this); } - [[nodiscard]] inline bool isTop() const noexcept { + [[nodiscard]] constexpr bool isTop() const noexcept { return std::holds_alternative(*this); } - [[nodiscard]] inline L *getValueOrNull() noexcept { + [[nodiscard]] constexpr L *getValueOrNull() noexcept { return std::get_if(this); } - [[nodiscard]] inline const L *getValueOrNull() const noexcept { + [[nodiscard]] constexpr const L *getValueOrNull() const noexcept { return std::get_if(this); } @@ -93,119 +93,95 @@ struct LatticeDomain : public std::variant { return hash_value(std::get(LD)); } - [[nodiscard]] inline L &assertGetValue() noexcept { + [[nodiscard]] constexpr L &assertGetValue() noexcept { assert(std::holds_alternative(*this)); return std::get(*this); } - [[nodiscard]] inline const L &assertGetValue() const noexcept { + [[nodiscard]] constexpr const L &assertGetValue() const noexcept { assert(std::holds_alternative(*this)); return std::get(*this); } template - void onValue(TransformFn Transform, ArgsT &&...Args) { + constexpr void onValue(TransformFn Transform, ArgsT &&...Args) { if (auto *Val = getValueOrNull()) { std::invoke(std::move(Transform), *Val, PSR_FWD(Args)...); } } -}; -template -inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const LatticeDomain &LD) { - if (LD.isBottom()) { - return OS << "Bottom"; - } - if (LD.isTop()) { - return OS << "Top"; + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const LatticeDomain &LD) { + if (LD.isBottom()) { + return OS << "Bottom"; + } + if (LD.isTop()) { + return OS << "Top"; + } + + const auto *Val = LD.getValueOrNull(); + assert(Val && "Only alternative remaining is L"); + if constexpr (is_llvm_printable_v) { + return OS << *Val; + } else { + return OS << PrettyPrinter{*Val}; + } } - const auto *Val = LD.getValueOrNull(); - assert(Val && "Only alternative remaining is L"); - if constexpr (is_llvm_printable_v) { - return OS << *Val; - } else { - return OS << PrettyPrinter{*Val}; + friend std::ostream &operator<<(std::ostream &OS, const LatticeDomain &LD) { + llvm::raw_os_ostream ROS(OS); + ROS << LD; + return OS; } -} -template -inline std::ostream &operator<<(std::ostream &OS, const LatticeDomain &LD) { - llvm::raw_os_ostream ROS(OS); - ROS << LD; - return OS; -} + constexpr bool operator==(const LatticeDomain &Rhs) const { + if (this->index() != Rhs.index()) { + return false; + } + if (auto LhsPtr = this->getValueOrNull()) { + /// No need to check whether Rhs is an L; the indices are already the same + return *LhsPtr == *Rhs.getValueOrNull(); + } + return true; + } -template -inline bool operator==(const LatticeDomain &Lhs, - const LatticeDomain &Rhs) { - if (Lhs.index() != Rhs.index()) { + template + requires AreEqualityComparable + constexpr bool operator==(const LL &Rhs) const { + if (auto LVal = this->getValueOrNull()) { + return *LVal == Rhs; + } return false; } - if (auto LhsPtr = Lhs.getValueOrNull()) { - /// No need to check whether Lhs is an L; the indices are already the same - return *LhsPtr == *Rhs.getValueOrNull(); - } - return true; -} -template - requires AreEqualityComparable -inline bool operator==(const LL &Lhs, const LatticeDomain &Rhs) { - if (auto RVal = Rhs.getValueOrNull()) { - return Lhs == *RVal; + constexpr bool operator==(Bottom /*Rhs*/) const noexcept { + return this->isBottom(); } - return false; -} - -template - requires AreEqualityComparable -inline bool operator==(const LatticeDomain &Lhs, const LL &Rhs) { - return Rhs == Lhs; -} -template -inline bool operator==(const LatticeDomain &Lhs, Bottom /*Rhs*/) noexcept { - return Lhs.isBottom(); -} - -template -inline bool operator==(const LatticeDomain &Lhs, Top /*Rhs*/) noexcept { - return Lhs.isTop(); -} - -template -inline bool operator==(Bottom /*Lhs*/, const LatticeDomain &Rhs) noexcept { - return Rhs.isBottom(); -} - -template -inline bool operator==(Top /*Lhs*/, const LatticeDomain &Rhs) noexcept { - return Rhs.isTop(); -} - -template -inline bool operator<(const LatticeDomain &Lhs, - const LatticeDomain &Rhs) { - /// Top < (Lhs::L < Rhs::L) < Bottom - if (Rhs.isTop()) { - return false; + constexpr bool operator==(Top /*Rhs*/) const noexcept { + return this->isTop(); } - if (Lhs.isTop()) { - return true; - } - if (auto LhsPtr = Lhs.getValueOrNull()) { - if (auto RhsPtr = Rhs.getValueOrNull()) { - return *LhsPtr < *RhsPtr; + + constexpr bool operator<(const LatticeDomain &Rhs) const { + /// Top < (Lhs::L < Rhs::L) < Bottom + if (Rhs.isTop()) { + return false; } - } else if (Lhs.isBottom()) { - return false; - } - if (Rhs.isBottom()) { - return true; + if (this->isTop()) { + return true; + } + if (auto LhsPtr = this->getValueOrNull()) { + if (auto RhsPtr = Rhs.getValueOrNull()) { + return *LhsPtr < *RhsPtr; + } + } else if (this->isBottom()) { + return false; + } + if (Rhs.isBottom()) { + return true; + } + llvm_unreachable("All comparison cases should be handled above."); } - llvm_unreachable("All comparison cases should be handled above."); -} +}; template struct JoinLatticeTraits> { using l_t = L; @@ -242,7 +218,7 @@ template struct NonTopBotValue> { using type = L; - static L unwrap(LatticeDomain Value) noexcept( + constexpr static L unwrap(LatticeDomain Value) noexcept( std::is_nothrow_move_constructible_v) { return std::get(std::move(Value)); } diff --git a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h index 0e14c90f54..cd21f088e1 100644 --- a/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h +++ b/include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h @@ -154,20 +154,20 @@ class IDEIIAFlowFact { print(OS); return Ret; } -}; -inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const IDEIIAFlowFact &FlowFact) { - FlowFact.print(OS); - return OS; -} + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const IDEIIAFlowFact &FlowFact) { + FlowFact.print(OS); + return OS; + } -inline std::ostream &operator<<(std::ostream &OS, - const IDEIIAFlowFact &FlowFact) { - llvm::raw_os_ostream Rso(OS); - FlowFact.print(Rso); - return OS; -} + friend std::ostream &operator<<(std::ostream &OS, + const IDEIIAFlowFact &FlowFact) { + llvm::raw_os_ostream Rso(OS); + FlowFact.print(Rso); + return OS; + } +}; } // namespace psr diff --git a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h index aede3166e2..07e4ab2131 100644 --- a/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h +++ b/include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h @@ -75,10 +75,10 @@ struct GeneralStatistics { std::string ModuleName{}; void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const; -}; -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const GeneralStatistics &Statistics); + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const GeneralStatistics &Statistics); +}; /** * This class uses the Module Pass Mechanism of LLVM to compute diff --git a/include/phasar/TypeHierarchy/TypeHierarchy.h b/include/phasar/TypeHierarchy/TypeHierarchy.h index 6c54407cd8..d4f0d570ef 100644 --- a/include/phasar/TypeHierarchy/TypeHierarchy.h +++ b/include/phasar/TypeHierarchy/TypeHierarchy.h @@ -39,14 +39,13 @@ template class TypeHierarchy { virtual void print(llvm::raw_ostream &OS = llvm::outs()) const = 0; virtual void printAsJson(llvm::raw_ostream &OS) const = 0; -}; -template -inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const TypeHierarchy &TH) { - TH.print(OS); - return OS; -} + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const TypeHierarchy &TH) { + TH.print(OS); + return OS; + } +}; } // namespace psr diff --git a/include/phasar/TypeHierarchy/VFTable.h b/include/phasar/TypeHierarchy/VFTable.h index 62eb4432af..76e3896e1c 100644 --- a/include/phasar/TypeHierarchy/VFTable.h +++ b/include/phasar/TypeHierarchy/VFTable.h @@ -38,14 +38,13 @@ template class VFTable { virtual void print(llvm::raw_ostream &OS) const = 0; virtual void printAsJson(llvm::raw_ostream &OS) const = 0; -}; -template -inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const VFTable &Table) { - Table.print(OS); - return OS; -} + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const VFTable &Table) { + Table.print(OS); + return OS; + } +}; } // namespace psr diff --git a/include/phasar/Utils/DOTGraph.h b/include/phasar/Utils/DOTGraph.h index b16777c9fa..07cb6388c6 100644 --- a/include/phasar/Utils/DOTGraph.h +++ b/include/phasar/Utils/DOTGraph.h @@ -103,11 +103,12 @@ struct DOTNode { DOTNode(std::string FName, std::string L, std::string SId, unsigned FId = 0, bool IsStmt = true, bool Isv = true); [[nodiscard]] std::string str(const std::string &Indent = "") const; -}; -bool operator<(const DOTNode &Lhs, const DOTNode &Rhs); -bool operator==(const DOTNode &Lhs, const DOTNode &Rhs); -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const DOTNode &Node); + friend bool operator<(const DOTNode &Lhs, const DOTNode &Rhs); + friend bool operator==(const DOTNode &Lhs, const DOTNode &Rhs); + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const DOTNode &Node); +}; struct DOTEdge { DOTNode Source; @@ -119,10 +120,11 @@ struct DOTEdge { DOTEdge(DOTNode Src, DOTNode Tar, bool Isv = true, std::string Efl = "", std::string Vl = ""); [[nodiscard]] std::string str(const std::string &Indent = "") const; -}; -bool operator<(const DOTEdge &Lhs, const DOTEdge &Rhs); -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const DOTEdge &Edge); + friend bool operator<(const DOTEdge &Lhs, const DOTEdge &Rhs); + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const DOTEdge &Edge); +}; struct DOTFactSubGraph { // fact subgraph id = _ @@ -134,10 +136,10 @@ struct DOTFactSubGraph { std::set Edges; [[nodiscard]] std::string str(const std::string &Indent = "") const; -}; -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const DOTFactSubGraph &FactSG); + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const DOTFactSubGraph &FactSG); +}; struct DOTFunctionSubGraph { // function subgraph id = @@ -157,10 +159,10 @@ struct DOTFunctionSubGraph { void createLayoutCFNodes(); void createLayoutFactNodes(); void createLayoutFactEdges(); -}; -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const DOTFunctionSubGraph &FunctionSG); + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const DOTFunctionSubGraph &FunctionSG); +}; template struct DOTGraph { std::string Label; diff --git a/include/phasar/Utils/DebugOutput.h b/include/phasar/Utils/DebugOutput.h index 1e3cf6e475..5de35a679d 100644 --- a/include/phasar/Utils/DebugOutput.h +++ b/include/phasar/Utils/DebugOutput.h @@ -99,16 +99,15 @@ template struct PrettyPrinter { return OS; } + friend std::ostream &operator<<(std::ostream &OS, const PrettyPrinter &P) { + llvm::raw_os_ostream ROS(OS); + ROS << P; + return OS; + } + const T &Data; }; -template -std::ostream &operator<<(std::ostream &OS, const PrettyPrinter &P) { - llvm::raw_os_ostream ROS(OS); - ROS << P; - return OS; -} - template PrettyPrinter(const T &) -> PrettyPrinter; } // namespace psr diff --git a/tools/ptaben/PTAResult.h b/tools/ptaben/PTAResult.h index 429b990ff2..15c8011a72 100755 --- a/tools/ptaben/PTAResult.h +++ b/tools/ptaben/PTAResult.h @@ -20,8 +20,8 @@ namespace psr::ptaben { struct PTAResult { QueryId Query{}; AliasResult Result{}; -}; -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, PTAResult Res); + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, PTAResult Res); +}; } // namespace psr::ptaben diff --git a/tools/ptaben/PTAUtils.h b/tools/ptaben/PTAUtils.h index e9e920ac40..93041c62ca 100755 --- a/tools/ptaben/PTAUtils.h +++ b/tools/ptaben/PTAUtils.h @@ -31,6 +31,9 @@ class raw_ostream; namespace psr::ptaben { struct QueryResult : QueryLocation { AliasResult Result{}; + + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const QueryResult &Result); }; struct QuerySrcCodeLocation { @@ -40,11 +43,6 @@ struct QuerySrcCodeLocation { [[nodiscard]] bool isSoundResult(const QueryResult &QR) noexcept; -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const QueryResult &Result); - -llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const QueryLocation &Result); - void findAllQueryLocations( const llvm::Module &Mod, llvm::SmallVectorImpl &Locs, llvm::SmallVectorImpl *SrcLocs = nullptr); diff --git a/tools/ptaben/QueryLocation.h b/tools/ptaben/QueryLocation.h index 368247a0ea..3ce70b861d 100755 --- a/tools/ptaben/QueryLocation.h +++ b/tools/ptaben/QueryLocation.h @@ -22,5 +22,8 @@ struct QueryLocation { QueryId Id{}; const llvm::Instruction *Inst{}; AliasQueryType QueryType{}; + + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, + const QueryLocation &Result); }; } // namespace psr::ptaben From 48c56b851265474788c3680e9ed1b225c3f42924 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sat, 11 Apr 2026 13:37:50 +0200 Subject: [PATCH 2/3] Remove now invalid operator-exports from module definitions --- lib/DataFlow/IfdsIde/IfdsIde.cppm | 1 - lib/Domain/Domain.cppm | 2 -- lib/PhasarLLVM/DataFlow/IfdsIde/IfdsIde.cppm | 1 - lib/PhasarLLVM/Passes/Passes.cppm | 1 - lib/TypeHierarchy/TypeHierarchy.cppm | 1 - lib/Utils/Utils.cppm | 10 ++++------ 6 files changed, 4 insertions(+), 12 deletions(-) diff --git a/lib/DataFlow/IfdsIde/IfdsIde.cppm b/lib/DataFlow/IfdsIde/IfdsIde.cppm index c5901d725c..4a443803af 100644 --- a/lib/DataFlow/IfdsIde/IfdsIde.cppm +++ b/lib/DataFlow/IfdsIde/IfdsIde.cppm @@ -40,7 +40,6 @@ using psr::EdgeIdentity; using psr::IdeAnalysisDomain; using psr::IfdsAnalysisDomain; using psr::IsEdgeFunction; -using psr::operator==; using psr::operator<<; using psr::addSeedsForStartingPoints; using psr::AllTopFnProvider; diff --git a/lib/Domain/Domain.cppm b/lib/Domain/Domain.cppm index a04780f74c..6961c4c22c 100644 --- a/lib/Domain/Domain.cppm +++ b/lib/Domain/Domain.cppm @@ -9,8 +9,6 @@ using psr::AnalysisDomain; using psr::BinaryDomain; using psr::to_string; using psr::operator<<; -using psr::operator==; -using psr::operator<; using psr::Bottom; using psr::IRDomain; using psr::JoinLatticeTraits; diff --git a/lib/PhasarLLVM/DataFlow/IfdsIde/IfdsIde.cppm b/lib/PhasarLLVM/DataFlow/IfdsIde/IfdsIde.cppm index 22bbc7d9e2..84e764cd5a 100644 --- a/lib/PhasarLLVM/DataFlow/IfdsIde/IfdsIde.cppm +++ b/lib/PhasarLLVM/DataFlow/IfdsIde/IfdsIde.cppm @@ -96,7 +96,6 @@ using psr::SecureHeapFact; using psr::SecureHeapValue; using psr::strongUpdateStore; using psr::operator<<; -using psr::operator==; using psr::CSTDFILEIOState; using psr::EdgeFunctionBase; using psr::IDEGeneralizedLCA; diff --git a/lib/PhasarLLVM/Passes/Passes.cppm b/lib/PhasarLLVM/Passes/Passes.cppm index 5dba1c68bf..8027b36075 100644 --- a/lib/PhasarLLVM/Passes/Passes.cppm +++ b/lib/PhasarLLVM/Passes/Passes.cppm @@ -11,5 +11,4 @@ using psr::ExampleModulePass; using psr::GeneralStatistics; using psr::GeneralStatisticsAnalysis; using psr::ValueAnnotationPass; -using psr::operator<<; } // namespace psr diff --git a/lib/TypeHierarchy/TypeHierarchy.cppm b/lib/TypeHierarchy/TypeHierarchy.cppm index a7bcbd7ccd..6fbd35541b 100644 --- a/lib/TypeHierarchy/TypeHierarchy.cppm +++ b/lib/TypeHierarchy/TypeHierarchy.cppm @@ -7,6 +7,5 @@ export module phasar.typehierarchy; export namespace psr { using psr::TypeHierarchy; -using psr::operator<<; using psr::VFTable; } // namespace psr diff --git a/lib/Utils/Utils.cppm b/lib/Utils/Utils.cppm index 42f1f1af2e..39687368c6 100644 --- a/lib/Utils/Utils.cppm +++ b/lib/Utils/Utils.cppm @@ -74,18 +74,16 @@ using psr::createEquivalentGraphFrom; using psr::DefaultAnalysisPrinter; using psr::DOTConfig; using psr::DOTEdge; -using psr::DOTNode; -using psr::getDefaultValue; -using psr::minimizeGraph; -using psr::Warning; -using psr::operator<; -using psr::operator==; using psr::DOTFactSubGraph; using psr::DOTFunctionSubGraph; using psr::DOTGraph; +using psr::DOTNode; using psr::DummyPair; using psr::EmptyType; using psr::EnumFlagAutoBool; +using psr::getDefaultValue; +using psr::minimizeGraph; +using psr::Warning; using psr::operator&=; using psr::operator|; using psr::operator|=; From 120aeefe1bf08aa29ce1e3b29cc617e2a3ed12d7 Mon Sep 17 00:00:00 2001 From: Fabian Schiebel Date: Sun, 12 Apr 2026 14:07:30 +0200 Subject: [PATCH 3/3] Remove some operator fwd decls and replace with direct inline impl --- include/phasar/Utils/DOTGraph.h | 42 +++++++++++++++++++++++++++------ lib/Utils/DOTGraph.cpp | 40 ------------------------------- tools/ptaben/PTAResult.cpp | 6 ----- tools/ptaben/PTAResult.h | 4 +++- 4 files changed, 38 insertions(+), 54 deletions(-) delete mode 100644 tools/ptaben/PTAResult.cpp diff --git a/include/phasar/Utils/DOTGraph.h b/include/phasar/Utils/DOTGraph.h index 07cb6388c6..262438b373 100644 --- a/include/phasar/Utils/DOTGraph.h +++ b/include/phasar/Utils/DOTGraph.h @@ -104,10 +104,26 @@ struct DOTNode { bool IsStmt = true, bool Isv = true); [[nodiscard]] std::string str(const std::string &Indent = "") const; - friend bool operator<(const DOTNode &Lhs, const DOTNode &Rhs); - friend bool operator==(const DOTNode &Lhs, const DOTNode &Rhs); + friend bool operator<(const DOTNode &Lhs, const DOTNode &Rhs) { + StringIDLess StrLess; + // comparing control flow nodes + if (Lhs.FactId == 0 && Rhs.FactId == 0) { + return StrLess(Lhs.StmtId, Rhs.StmtId); + } // comparing fact nodes + if (Lhs.FactId == Rhs.FactId) { + return StrLess(Lhs.StmtId, Rhs.StmtId); + } + return Lhs.FactId < Rhs.FactId; + } + + friend bool operator==(const DOTNode &Lhs, const DOTNode &Rhs) { + return !(Lhs < Rhs) && !(Rhs < Lhs); + } + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const DOTNode &Node); + const DOTNode &Node) { + return OS << Node.str(); + } }; struct DOTEdge { @@ -121,9 +137,17 @@ struct DOTEdge { std::string Vl = ""); [[nodiscard]] std::string str(const std::string &Indent = "") const; - friend bool operator<(const DOTEdge &Lhs, const DOTEdge &Rhs); + friend bool operator<(const DOTEdge &Lhs, const DOTEdge &Rhs) { + if (Lhs.Source == Rhs.Source) { + return Lhs.Target < Rhs.Target; + } + return Lhs.Source < Rhs.Source; + } + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const DOTEdge &Edge); + const DOTEdge &Edge) { + return OS << Edge.str(); + } }; struct DOTFactSubGraph { @@ -138,7 +162,9 @@ struct DOTFactSubGraph { [[nodiscard]] std::string str(const std::string &Indent = "") const; friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const DOTFactSubGraph &FactSG); + const DOTFactSubGraph &FactSG) { + return OS << FactSG.str(); + } }; struct DOTFunctionSubGraph { @@ -161,7 +187,9 @@ struct DOTFunctionSubGraph { void createLayoutFactEdges(); friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, - const DOTFunctionSubGraph &FunctionSG); + const DOTFunctionSubGraph &FunctionSG) { + return OS << FunctionSG.str(); + } }; template struct DOTGraph { diff --git a/lib/Utils/DOTGraph.cpp b/lib/Utils/DOTGraph.cpp index 1bd7dc7d30..fac11333fd 100644 --- a/lib/Utils/DOTGraph.cpp +++ b/lib/Utils/DOTGraph.cpp @@ -199,46 +199,6 @@ void DOTFunctionSubGraph::createLayoutFactEdges() { } } -bool operator<(const DOTNode &Lhs, const DOTNode &Rhs) { - StringIDLess StrLess; - // comparing control flow nodes - if (Lhs.FactId == 0 && Rhs.FactId == 0) { - return StrLess(Lhs.StmtId, Rhs.StmtId); - } // comparing fact nodes - if (Lhs.FactId == Rhs.FactId) { - return StrLess(Lhs.StmtId, Rhs.StmtId); - } - return Lhs.FactId < Rhs.FactId; -} - -bool operator==(const DOTNode &Lhs, const DOTNode &Rhs) { - return !(Lhs < Rhs) && !(Rhs < Lhs); -} - -std::ostream &operator<<(std::ostream &OS, const DOTNode &Node) { - return OS << Node.str(); -} - -bool operator<(const DOTEdge &Lhs, const DOTEdge &Rhs) { - if (Lhs.Source == Rhs.Source) { - return Lhs.Target < Rhs.Target; - } - return Lhs.Source < Rhs.Source; -} - -std::ostream &operator<<(std::ostream &OS, const DOTEdge &Edge) { - return OS << Edge.str(); -} - -std::ostream &operator<<(std::ostream &OS, const DOTFactSubGraph &FactSG) { - return OS << FactSG.str(); -} - -std::ostream &operator<<(std::ostream &OS, - const DOTFunctionSubGraph &FunctionSG) { - return OS << FunctionSG.str(); -} - DOTConfig &DOTConfig::getDOTConfig() { static DOTConfig DC; return DC; diff --git a/tools/ptaben/PTAResult.cpp b/tools/ptaben/PTAResult.cpp deleted file mode 100644 index 445410c776..0000000000 --- a/tools/ptaben/PTAResult.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "PTAResult.h" - -llvm::raw_ostream &psr::ptaben::operator<<(llvm::raw_ostream &OS, - PTAResult Res) { - return OS << uint64_t(Res.Query) << ", " << to_string(Res.Result); -} diff --git a/tools/ptaben/PTAResult.h b/tools/ptaben/PTAResult.h index 15c8011a72..20617d039d 100755 --- a/tools/ptaben/PTAResult.h +++ b/tools/ptaben/PTAResult.h @@ -21,7 +21,9 @@ struct PTAResult { QueryId Query{}; AliasResult Result{}; - friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, PTAResult Res); + friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, PTAResult Res) { + return OS << uint64_t(Res.Query) << ", " << to_string(Res.Result); + } }; } // namespace psr::ptaben