File indexing completed on 2026-05-10 08:36:25
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__MAPLATTICE_H
0016 #define LLVM_CLANG_ANALYSIS_FLOWSENSITIVE__MAPLATTICE_H
0017
0018 #include <ostream>
0019 #include <string>
0020 #include <utility>
0021
0022 #include "DataflowAnalysis.h"
0023 #include "clang/AST/Decl.h"
0024 #include "clang/Analysis/FlowSensitive/DataflowLattice.h"
0025 #include "llvm/ADT/DenseMap.h"
0026 #include "llvm/ADT/StringRef.h"
0027
0028 namespace clang {
0029 namespace dataflow {
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039 template <typename Key, typename ElementLattice> class MapLattice {
0040 using Container = llvm::DenseMap<Key, ElementLattice>;
0041 Container C;
0042
0043 public:
0044 using key_type = Key;
0045 using mapped_type = ElementLattice;
0046 using value_type = typename Container::value_type;
0047 using iterator = typename Container::iterator;
0048 using const_iterator = typename Container::const_iterator;
0049
0050 MapLattice() = default;
0051
0052 explicit MapLattice(Container C) : C{std::move(C)} {};
0053
0054
0055 static MapLattice bottom() { return MapLattice(); }
0056
0057 std::pair<iterator, bool>
0058 insert(const std::pair<const key_type, mapped_type> &P) {
0059 return C.insert(P);
0060 }
0061
0062 std::pair<iterator, bool> insert(std::pair<const key_type, mapped_type> &&P) {
0063 return C.insert(std::move(P));
0064 }
0065
0066 unsigned size() const { return C.size(); }
0067 bool empty() const { return C.empty(); }
0068
0069 iterator begin() { return C.begin(); }
0070 iterator end() { return C.end(); }
0071 const_iterator begin() const { return C.begin(); }
0072 const_iterator end() const { return C.end(); }
0073
0074
0075
0076
0077 friend bool operator==(const MapLattice &LHS, const MapLattice &RHS) {
0078 return LHS.C == RHS.C;
0079 }
0080
0081 friend bool operator!=(const MapLattice &LHS, const MapLattice &RHS) {
0082 return !(LHS == RHS);
0083 }
0084
0085 bool contains(const key_type &K) const { return C.find(K) != C.end(); }
0086
0087 iterator find(const key_type &K) { return C.find(K); }
0088 const_iterator find(const key_type &K) const { return C.find(K); }
0089
0090 mapped_type &operator[](const key_type &K) { return C[K]; }
0091
0092
0093
0094
0095 LatticeJoinEffect join(const MapLattice &Other) {
0096 LatticeJoinEffect Effect = LatticeJoinEffect::Unchanged;
0097 for (const auto &O : Other.C) {
0098 auto It = C.find(O.first);
0099 if (It == C.end()) {
0100 C.insert(O);
0101 Effect = LatticeJoinEffect::Changed;
0102 } else if (It->second.join(O.second) == LatticeJoinEffect::Changed)
0103 Effect = LatticeJoinEffect::Changed;
0104 }
0105 return Effect;
0106 }
0107 };
0108
0109
0110
0111 template <typename ElementLattice>
0112 using VarMapLattice = MapLattice<const clang::VarDecl *, ElementLattice>;
0113
0114 template <typename Key, typename ElementLattice>
0115 std::ostream &
0116 operator<<(std::ostream &Os,
0117 const clang::dataflow::MapLattice<Key, ElementLattice> &M) {
0118 std::string Separator;
0119 Os << "{";
0120 for (const auto &E : M) {
0121 Os << std::exchange(Separator, ", ") << E.first << " => " << E.second;
0122 }
0123 Os << "}";
0124 return Os;
0125 }
0126
0127 template <typename ElementLattice>
0128 std::ostream &
0129 operator<<(std::ostream &Os,
0130 const clang::dataflow::VarMapLattice<ElementLattice> &M) {
0131 std::string Separator;
0132 Os << "{";
0133 for (const auto &E : M) {
0134 Os << std::exchange(Separator, ", ") << E.first->getName().str() << " => "
0135 << E.second;
0136 }
0137 Os << "}";
0138 return Os;
0139 }
0140 }
0141 }
0142
0143 #endif