Skip to content

Commit 201012b

Browse files
authored
Make most namespace-scope operators hidden friends (#825)
* Make most namespace-scope operators hidden friends * Remove now invalid operator-exports from module definitions * Remove some operator fwd decls and replace with direct inline impl * Aim for fixing CI with DebugLibDeps+Modules Apparently, some compiler versions do not export hidden friends with C++20 modules... * ci
1 parent 6a94e07 commit 201012b

26 files changed

Lines changed: 267 additions & 291 deletions

File tree

include/phasar/DataFlow/IfdsIde/EdgeFunctionUtils.h

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -70,49 +70,48 @@ template <typename L> struct ConstantEdgeFunction {
7070

7171
[[nodiscard]] constexpr bool isConstant() const noexcept { return true; }
7272

73-
// -- constant data member
73+
[[nodiscard]] friend constexpr bool
74+
operator==(ConstantEdgeFunction<L> LHS, ConstantEdgeFunction<L> RHS) noexcept
75+
requires CanEfficientlyPassByValue<ConstantEdgeFunction>
76+
{
77+
return LHS.Value == RHS.Value;
78+
}
7479

75-
value_type Value{};
76-
};
80+
[[nodiscard]] friend constexpr bool
81+
operator==(const ConstantEdgeFunction<L> &LHS,
82+
const ConstantEdgeFunction<L> &RHS) noexcept
83+
requires(!CanEfficientlyPassByValue<ConstantEdgeFunction>)
84+
{
85+
return LHS.Value == RHS.Value;
86+
}
7787

78-
template <typename L>
79-
requires CanEfficientlyPassByValue<ConstantEdgeFunction<L>>
80-
[[nodiscard]] constexpr bool operator==(ConstantEdgeFunction<L> LHS,
81-
ConstantEdgeFunction<L> RHS) noexcept {
82-
return LHS.Value == RHS.Value;
83-
}
88+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
89+
const ConstantEdgeFunction &Id) {
90+
OS << "ConstantEF";
91+
if constexpr (is_llvm_printable_v<
92+
typename ConstantEdgeFunction<L>::value_type>) {
93+
OS << '[' << Id.Value << ']';
94+
}
95+
return OS;
96+
}
8497

85-
template <typename L>
86-
requires(!CanEfficientlyPassByValue<ConstantEdgeFunction<L>>)
87-
[[nodiscard]] constexpr bool
88-
operator==(const ConstantEdgeFunction<L> &LHS,
89-
const ConstantEdgeFunction<L> &RHS) noexcept {
90-
return LHS.Value == RHS.Value;
91-
}
98+
[[nodiscard]] friend auto hash_value(const ConstantEdgeFunction &CEF) noexcept
99+
requires(is_std_hashable_v<typename NonTopBotValue<L>::type> ||
100+
is_llvm_hashable_v<typename NonTopBotValue<L>::type>)
101+
{
102+
using value_type = typename ConstantEdgeFunction<L>::value_type;
103+
if constexpr (is_std_hashable_v<value_type>) {
104+
return std::hash<value_type>{}(CEF.Value);
105+
} else {
106+
using llvm::hash_value;
107+
return hash_value(CEF.Value);
108+
}
109+
}
92110

93-
template <typename L>
94-
[[nodiscard]] llvm::raw_ostream &
95-
operator<<(llvm::raw_ostream &OS, ByConstRef<ConstantEdgeFunction<L>> Id) {
96-
OS << "ConstantEF";
97-
if constexpr (is_llvm_printable_v<
98-
typename ConstantEdgeFunction<L>::value_type>) {
99-
OS << '[' << Id.Value << ']';
100-
}
101-
return OS;
102-
}
111+
// -- constant data member
103112

104-
template <typename L>
105-
requires(is_std_hashable_v<typename NonTopBotValue<L>::type> ||
106-
is_llvm_hashable_v<typename NonTopBotValue<L>::type>)
107-
[[nodiscard]] auto hash_value(const ConstantEdgeFunction<L> &CEF) noexcept {
108-
using value_type = typename ConstantEdgeFunction<L>::value_type;
109-
if constexpr (is_std_hashable_v<value_type>) {
110-
return std::hash<value_type>{}(CEF.Value);
111-
} else {
112-
using llvm::hash_value;
113-
return hash_value(CEF.Value);
114-
}
115-
}
113+
value_type Value{};
114+
};
116115

117116
template <typename L> struct AllBottom final {
118117
using l_t = L;
@@ -299,6 +298,10 @@ template <typename L> struct EdgeFunctionComposer {
299298
return First.depth() + Second.depth();
300299
}
301300

301+
friend auto hash_value(const EdgeFunctionComposer &EFC) noexcept {
302+
return llvm::hash_combine(EFC.First, EFC.Second);
303+
}
304+
302305
// -- data members
303306

304307
EdgeFunction<l_t> First{};
@@ -307,11 +310,6 @@ template <typename L> struct EdgeFunctionComposer {
307310

308311
static_assert(HasDepth<EdgeFunctionComposer<int>>);
309312

310-
template <typename L>
311-
auto hash_value(const EdgeFunctionComposer<L> &EFC) noexcept {
312-
return llvm::hash_combine(EFC.First, EFC.Second);
313-
}
314-
315313
template <typename L, uint8_t N> struct JoinEdgeFunction {
316314
using l_t = L;
317315
using JLattice = JoinLatticeTraits<L>;

include/phasar/DataFlow/IfdsIde/Solver/IDESolver.h

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,12 @@ class IDESolver
215215
getSolverResults().dumpResults(*ICF, OS);
216216
}
217217

218+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
219+
const IDESolver &Solver) {
220+
Solver.dumpResults(OS);
221+
return OS;
222+
}
223+
218224
void dumpAllInterPathEdges() {
219225
llvm::outs() << "COMPUTED INTER PATH EDGES" << '\n';
220226
auto Interpe = this->computedInterPathEdges.cellSet();
@@ -1917,14 +1923,6 @@ class IDESolver
19171923
std::map<std::pair<n_t, d_t>, size_t> FSummaryReuse;
19181924
};
19191925

1920-
template <typename AnalysisDomainTy, typename Container>
1921-
llvm::raw_ostream &
1922-
operator<<(llvm::raw_ostream &OS,
1923-
const IDESolver<AnalysisDomainTy, Container> &Solver) {
1924-
Solver.dumpResults(OS);
1925-
return OS;
1926-
}
1927-
19281926
template <typename Problem, typename ICF>
19291927
IDESolver(Problem &, ICF *)
19301928
-> IDESolver<typename Problem::ProblemAnalysisDomain,

include/phasar/Domain/LatticeDomain.h

Lines changed: 61 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -103,94 +103,85 @@ struct LatticeDomain : public std::variant<Top, L, Bottom> {
103103
}
104104

105105
template <typename TransformFn, typename... ArgsT>
106-
void onValue(TransformFn Transform, ArgsT &&...Args) {
106+
constexpr void onValue(TransformFn Transform, ArgsT &&...Args) {
107107
if (auto *Val = getValueOrNull()) {
108108
std::invoke(std::move(Transform), *Val, PSR_FWD(Args)...);
109109
}
110110
}
111-
};
112111

113-
template <typename L>
114-
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
115-
const LatticeDomain<L> &LD) {
116-
if (LD.isBottom()) {
117-
return OS << "Bottom";
118-
}
119-
if (LD.isTop()) {
120-
return OS << "Top";
112+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
113+
const LatticeDomain &LD) {
114+
if (LD.isBottom()) {
115+
return OS << "Bottom";
116+
}
117+
if (LD.isTop()) {
118+
return OS << "Top";
119+
}
120+
121+
const auto *Val = LD.getValueOrNull();
122+
assert(Val && "Only alternative remaining is L");
123+
if constexpr (is_llvm_printable_v<L>) {
124+
return OS << *Val;
125+
} else {
126+
return OS << PrettyPrinter{*Val};
127+
}
121128
}
122129

123-
const auto *Val = LD.getValueOrNull();
124-
assert(Val && "Only alternative remaining is L");
125-
if constexpr (is_llvm_printable_v<L>) {
126-
return OS << *Val;
127-
} else {
128-
return OS << PrettyPrinter{*Val};
130+
friend std::ostream &operator<<(std::ostream &OS, const LatticeDomain &LD) {
131+
llvm::raw_os_ostream ROS(OS);
132+
ROS << LD;
133+
return OS;
129134
}
130-
}
131135

132-
template <typename L>
133-
inline std::ostream &operator<<(std::ostream &OS, const LatticeDomain<L> &LD) {
134-
llvm::raw_os_ostream ROS(OS);
135-
ROS << LD;
136-
return OS;
137-
}
136+
constexpr bool operator==(const LatticeDomain &Rhs) const {
137+
if (this->index() != Rhs.index()) {
138+
return false;
139+
}
140+
if (auto LhsPtr = this->getValueOrNull()) {
141+
/// No need to check whether Rhs is an L; the indices are already the same
142+
return *LhsPtr == *Rhs.getValueOrNull();
143+
}
144+
return true;
145+
}
138146

139-
template <typename L>
140-
constexpr bool operator==(const LatticeDomain<L> &Lhs,
141-
const LatticeDomain<L> &Rhs) {
142-
if (Lhs.index() != Rhs.index()) {
147+
template <typename LL>
148+
requires AreEqualityComparable<L, LL>
149+
constexpr bool operator==(const LL &Rhs) const {
150+
if (auto LVal = this->getValueOrNull()) {
151+
return *LVal == Rhs;
152+
}
143153
return false;
144154
}
145-
if (auto LhsPtr = Lhs.getValueOrNull()) {
146-
/// No need to check whether Lhs is an L; the indices are already the same
147-
return *LhsPtr == *Rhs.getValueOrNull();
148-
}
149-
return true;
150-
}
151155

152-
template <typename L, typename LL>
153-
requires AreEqualityComparable<LL, L>
154-
constexpr bool operator==(const LatticeDomain<L> &Lhs, const LL &Rhs) {
155-
if (auto LVal = Lhs.getValueOrNull()) {
156-
return *LVal == Rhs;
156+
constexpr bool operator==(Bottom /*Rhs*/) const noexcept {
157+
return this->isBottom();
157158
}
158-
return false;
159-
}
160-
161-
template <typename L>
162-
constexpr bool operator==(const LatticeDomain<L> &Lhs,
163-
Bottom /*Rhs*/) noexcept {
164-
return Lhs.isBottom();
165-
}
166-
167-
template <typename L>
168-
constexpr bool operator==(const LatticeDomain<L> &Lhs, Top /*Rhs*/) noexcept {
169-
return Lhs.isTop();
170-
}
171159

172-
template <typename L>
173-
constexpr bool operator<(const LatticeDomain<L> &Lhs,
174-
const LatticeDomain<L> &Rhs) {
175-
/// Top < (Lhs::L < Rhs::L) < Bottom
176-
if (Rhs.isTop()) {
177-
return false;
178-
}
179-
if (Lhs.isTop()) {
180-
return true;
160+
constexpr bool operator==(Top /*Rhs*/) const noexcept {
161+
return this->isTop();
181162
}
182-
if (auto LhsPtr = Lhs.getValueOrNull()) {
183-
if (auto RhsPtr = Rhs.getValueOrNull()) {
184-
return *LhsPtr < *RhsPtr;
163+
164+
constexpr bool operator<(const LatticeDomain &Rhs) const {
165+
/// Top < (Lhs::L < Rhs::L) < Bottom
166+
if (Rhs.isTop()) {
167+
return false;
185168
}
186-
} else if (Lhs.isBottom()) {
187-
return false;
188-
}
189-
if (Rhs.isBottom()) {
190-
return true;
169+
if (this->isTop()) {
170+
return true;
171+
}
172+
if (auto LhsPtr = this->getValueOrNull()) {
173+
if (auto RhsPtr = Rhs.getValueOrNull()) {
174+
return *LhsPtr < *RhsPtr;
175+
}
176+
} else if (this->isBottom()) {
177+
return false;
178+
}
179+
if (Rhs.isBottom()) {
180+
return true;
181+
}
182+
llvm_unreachable("All comparison cases should be handled above.");
191183
}
192-
llvm_unreachable("All comparison cases should be handled above.");
193-
}
184+
};
194185

195186
template <typename L> struct JoinLatticeTraits<LatticeDomain<L>> {
196187
using l_t = L;

include/phasar/PhasarLLVM/DataFlow/IfdsIde/Problems/IDEInstInteractionAnalysis.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,20 +154,20 @@ class IDEIIAFlowFact {
154154
print(OS);
155155
return Ret;
156156
}
157-
};
158157

159-
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
160-
const IDEIIAFlowFact &FlowFact) {
161-
FlowFact.print(OS);
162-
return OS;
163-
}
158+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
159+
const IDEIIAFlowFact &FlowFact) {
160+
FlowFact.print(OS);
161+
return OS;
162+
}
164163

165-
inline std::ostream &operator<<(std::ostream &OS,
166-
const IDEIIAFlowFact &FlowFact) {
167-
llvm::raw_os_ostream Rso(OS);
168-
FlowFact.print(Rso);
169-
return OS;
170-
}
164+
friend std::ostream &operator<<(std::ostream &OS,
165+
const IDEIIAFlowFact &FlowFact) {
166+
llvm::raw_os_ostream Rso(OS);
167+
FlowFact.print(Rso);
168+
return OS;
169+
}
170+
};
171171

172172
} // namespace psr
173173

include/phasar/PhasarLLVM/Passes/GeneralStatisticsAnalysis.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ struct GeneralStatistics {
7575
std::string ModuleName{};
7676

7777
void printAsJson(llvm::raw_ostream &OS = llvm::outs()) const;
78-
};
7978

80-
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
81-
const GeneralStatistics &Statistics);
79+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
80+
const GeneralStatistics &Statistics);
81+
};
8282

8383
/**
8484
* This class uses the Module Pass Mechanism of LLVM to compute

include/phasar/TypeHierarchy/TypeHierarchy.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,13 @@ template <typename T, typename F> class TypeHierarchy {
3939
virtual void print(llvm::raw_ostream &OS = llvm::outs()) const = 0;
4040

4141
virtual void printAsJson(llvm::raw_ostream &OS) const = 0;
42-
};
4342

44-
template <typename T, typename F>
45-
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
46-
const TypeHierarchy<T, F> &TH) {
47-
TH.print(OS);
48-
return OS;
49-
}
43+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
44+
const TypeHierarchy &TH) {
45+
TH.print(OS);
46+
return OS;
47+
}
48+
};
5049

5150
} // namespace psr
5251

include/phasar/TypeHierarchy/VFTable.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,13 @@ template <typename F> class VFTable {
3838
virtual void print(llvm::raw_ostream &OS) const = 0;
3939

4040
virtual void printAsJson(llvm::raw_ostream &OS) const = 0;
41-
};
4241

43-
template <typename T, typename F>
44-
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
45-
const VFTable<F> &Table) {
46-
Table.print(OS);
47-
return OS;
48-
}
42+
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
43+
const VFTable &Table) {
44+
Table.print(OS);
45+
return OS;
46+
}
47+
};
4948

5049
} // namespace psr
5150

0 commit comments

Comments
 (0)