1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_LIB_STATICANALYZER_CORE_RANGEDCONSTRAINTMANAGER_H |
14 | #define LLVM_CLANG_LIB_STATICANALYZER_CORE_RANGEDCONSTRAINTMANAGER_H |
15 | |
16 | #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" |
17 | #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" |
18 | #include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h" |
19 | |
20 | namespace clang { |
21 | |
22 | namespace ento { |
23 | |
24 | |
25 | |
26 | |
27 | class Range : public std::pair<const llvm::APSInt *, const llvm::APSInt *> { |
28 | public: |
29 | Range(const llvm::APSInt &from, const llvm::APSInt &to) |
30 | : std::pair<const llvm::APSInt *, const llvm::APSInt *>(&from, &to) { |
31 | assert(from <= to); |
32 | } |
33 | bool Includes(const llvm::APSInt &v) const { |
34 | return *first <= v && v <= *second; |
35 | } |
36 | const llvm::APSInt &From() const { return *first; } |
37 | const llvm::APSInt &To() const { return *second; } |
38 | const llvm::APSInt *getConcreteValue() const { |
39 | return &From() == &To() ? &From() : nullptr; |
40 | } |
41 | |
42 | void Profile(llvm::FoldingSetNodeID &ID) const { |
43 | ID.AddPointer(&From()); |
44 | ID.AddPointer(&To()); |
45 | } |
46 | }; |
47 | |
48 | class RangeTrait : public llvm::ImutContainerInfo<Range> { |
49 | public: |
50 | |
51 | |
52 | |
53 | |
54 | static inline bool isLess(key_type_ref lhs, key_type_ref rhs) { |
55 | return *lhs.first < *rhs.first || |
56 | (!(*rhs.first < *lhs.first) && *lhs.second < *rhs.second); |
57 | } |
58 | }; |
59 | |
60 | |
61 | |
62 | |
63 | class RangeSet { |
64 | typedef llvm::ImmutableSet<Range, RangeTrait> PrimRangeSet; |
65 | PrimRangeSet ranges; |
66 | |
67 | |
68 | public: |
69 | typedef PrimRangeSet::Factory Factory; |
70 | typedef PrimRangeSet::iterator iterator; |
71 | |
72 | RangeSet(PrimRangeSet RS) : ranges(RS) {} |
73 | |
74 | |
75 | |
76 | RangeSet addRange(Factory &F, const RangeSet &RS) { |
77 | PrimRangeSet Ranges(RS.ranges); |
78 | for (const auto &range : ranges) |
79 | Ranges = F.add(Ranges, range); |
80 | return RangeSet(Ranges); |
81 | } |
82 | |
83 | iterator begin() const { return ranges.begin(); } |
84 | iterator end() const { return ranges.end(); } |
85 | |
86 | bool isEmpty() const { return ranges.isEmpty(); } |
87 | |
88 | |
89 | RangeSet(Factory &F, const llvm::APSInt &from, const llvm::APSInt &to) |
90 | : ranges(F.add(F.getEmptySet(), Range(from, to))) {} |
91 | |
92 | |
93 | |
94 | void Profile(llvm::FoldingSetNodeID &ID) const { ranges.Profile(ID); } |
95 | |
96 | |
97 | |
98 | |
99 | const llvm::APSInt *getConcreteValue() const { |
100 | return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : nullptr; |
101 | } |
102 | |
103 | private: |
104 | void IntersectInRange(BasicValueFactory &BV, Factory &F, |
105 | const llvm::APSInt &Lower, const llvm::APSInt &Upper, |
106 | PrimRangeSet &newRanges, PrimRangeSet::iterator &i, |
107 | PrimRangeSet::iterator &e) const; |
108 | |
109 | const llvm::APSInt &getMinValue() const; |
110 | |
111 | bool pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const; |
112 | |
113 | public: |
114 | RangeSet Intersect(BasicValueFactory &BV, Factory &F, llvm::APSInt Lower, |
115 | llvm::APSInt Upper) const; |
116 | RangeSet Intersect(BasicValueFactory &BV, Factory &F, |
117 | const RangeSet &Other) const; |
118 | RangeSet Negate(BasicValueFactory &BV, Factory &F) const; |
119 | |
120 | void print(raw_ostream &os) const; |
121 | |
122 | bool operator==(const RangeSet &other) const { |
123 | return ranges == other.ranges; |
124 | } |
125 | }; |
126 | |
127 | |
128 | class ConstraintRange {}; |
129 | using ConstraintRangeTy = llvm::ImmutableMap<SymbolRef, RangeSet>; |
130 | |
131 | template <> |
132 | struct ProgramStateTrait<ConstraintRange> |
133 | : public ProgramStatePartialTrait<ConstraintRangeTy> { |
134 | static void *GDMIndex(); |
135 | }; |
136 | |
137 | |
138 | class RangedConstraintManager : public SimpleConstraintManager { |
139 | public: |
140 | RangedConstraintManager(SubEngine *SE, SValBuilder &SB) |
141 | : SimpleConstraintManager(SE, SB) {} |
142 | |
143 | ~RangedConstraintManager() override; |
144 | |
145 | |
146 | |
147 | |
148 | |
149 | ProgramStateRef assumeSym(ProgramStateRef State, SymbolRef Sym, |
150 | bool Assumption) override; |
151 | |
152 | ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, SymbolRef Sym, |
153 | const llvm::APSInt &From, |
154 | const llvm::APSInt &To, |
155 | bool InRange) override; |
156 | |
157 | ProgramStateRef assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym, |
158 | bool Assumption) override; |
159 | |
160 | protected: |
161 | |
162 | virtual ProgramStateRef assumeSymRel(ProgramStateRef State, SymbolRef Sym, |
163 | BinaryOperator::Opcode op, |
164 | const llvm::APSInt &Int); |
165 | |
166 | |
167 | |
168 | |
169 | |
170 | |
171 | |
172 | |
173 | virtual ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym, |
174 | const llvm::APSInt &V, |
175 | const llvm::APSInt &Adjustment) = 0; |
176 | |
177 | virtual ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym, |
178 | const llvm::APSInt &V, |
179 | const llvm::APSInt &Adjustment) = 0; |
180 | |
181 | virtual ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym, |
182 | const llvm::APSInt &V, |
183 | const llvm::APSInt &Adjustment) = 0; |
184 | |
185 | virtual ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym, |
186 | const llvm::APSInt &V, |
187 | const llvm::APSInt &Adjustment) = 0; |
188 | |
189 | virtual ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym, |
190 | const llvm::APSInt &V, |
191 | const llvm::APSInt &Adjustment) = 0; |
192 | |
193 | virtual ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym, |
194 | const llvm::APSInt &V, |
195 | const llvm::APSInt &Adjustment) = 0; |
196 | |
197 | virtual ProgramStateRef assumeSymWithinInclusiveRange( |
198 | ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, |
199 | const llvm::APSInt &To, const llvm::APSInt &Adjustment) = 0; |
200 | |
201 | virtual ProgramStateRef assumeSymOutsideInclusiveRange( |
202 | ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, |
203 | const llvm::APSInt &To, const llvm::APSInt &Adjustment) = 0; |
204 | |
205 | |
206 | |
207 | |
208 | private: |
209 | static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment); |
210 | }; |
211 | |
212 | } |
213 | |
214 | } |
215 | |
216 | #endif |
217 | |