clang 20.0.0git
RangeConstraintManager.cpp
Go to the documentation of this file.
1//== RangeConstraintManager.cpp - Manage range constraints.------*- C++ -*--==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines RangeConstraintManager, a class that tracks simple
10// equality and inequality constraints on symbolic values of ProgramState.
11//
12//===----------------------------------------------------------------------===//
13
20#include "llvm/ADT/FoldingSet.h"
21#include "llvm/ADT/ImmutableSet.h"
22#include "llvm/ADT/STLExtras.h"
23#include "llvm/ADT/SmallSet.h"
24#include "llvm/ADT/StringExtras.h"
25#include "llvm/Support/Compiler.h"
26#include "llvm/Support/raw_ostream.h"
27#include <algorithm>
28#include <iterator>
29#include <optional>
30
31using namespace clang;
32using namespace ento;
33
34// This class can be extended with other tables which will help to reason
35// about ranges more precisely.
37 static_assert(BO_LT < BO_GT && BO_GT < BO_LE && BO_LE < BO_GE &&
38 BO_GE < BO_EQ && BO_EQ < BO_NE,
39 "This class relies on operators order. Rework it otherwise.");
40
41public:
43 False = 0,
46 };
47
48private:
49 // CmpOpTable holds states which represent the corresponding range for
50 // branching an exploded graph. We can reason about the branch if there is
51 // a previously known fact of the existence of a comparison expression with
52 // operands used in the current expression.
53 // E.g. assuming (x < y) is true that means (x != y) is surely true.
54 // if (x previous_operation y) // < | != | >
55 // if (x operation y) // != | > | <
56 // tristate // True | Unknown | False
57 //
58 // CmpOpTable represents next:
59 // __|< |> |<=|>=|==|!=|UnknownX2|
60 // < |1 |0 |* |0 |0 |* |1 |
61 // > |0 |1 |0 |* |0 |* |1 |
62 // <=|1 |0 |1 |* |1 |* |0 |
63 // >=|0 |1 |* |1 |1 |* |0 |
64 // ==|0 |0 |* |* |1 |0 |1 |
65 // !=|1 |1 |* |* |0 |1 |0 |
66 //
67 // Columns stands for a previous operator.
68 // Rows stands for a current operator.
69 // Each row has exactly two `Unknown` cases.
70 // UnknownX2 means that both `Unknown` previous operators are met in code,
71 // and there is a special column for that, for example:
72 // if (x >= y)
73 // if (x != y)
74 // if (x <= y)
75 // False only
76 static constexpr size_t CmpOpCount = BO_NE - BO_LT + 1;
77 const TriStateKind CmpOpTable[CmpOpCount][CmpOpCount + 1] = {
78 // < > <= >= == != UnknownX2
81 {True, False, True, Unknown, True, Unknown, False}, // <=
82 {False, True, Unknown, True, True, Unknown, False}, // >=
83 {False, False, Unknown, Unknown, True, False, True}, // ==
84 {True, True, Unknown, Unknown, False, True, False}, // !=
85 };
86
87 static size_t getIndexFromOp(BinaryOperatorKind OP) {
88 return static_cast<size_t>(OP - BO_LT);
89 }
90
91public:
92 constexpr size_t getCmpOpCount() const { return CmpOpCount; }
93
94 static BinaryOperatorKind getOpFromIndex(size_t Index) {
95 return static_cast<BinaryOperatorKind>(Index + BO_LT);
96 }
97
99 BinaryOperatorKind QueriedOP) const {
100 return CmpOpTable[getIndexFromOp(CurrentOP)][getIndexFromOp(QueriedOP)];
101 }
102
104 return CmpOpTable[getIndexFromOp(CurrentOP)][CmpOpCount];
105 }
106};
107
108//===----------------------------------------------------------------------===//
109// RangeSet implementation
110//===----------------------------------------------------------------------===//
111
112RangeSet::ContainerType RangeSet::Factory::EmptySet{};
113
115 ContainerType Result;
116 Result.reserve(LHS.size() + RHS.size());
117 std::merge(LHS.begin(), LHS.end(), RHS.begin(), RHS.end(),
118 std::back_inserter(Result));
119 return makePersistent(std::move(Result));
120}
121
123 ContainerType Result;
124 Result.reserve(Original.size() + 1);
125
126 const_iterator Lower = llvm::lower_bound(Original, Element);
127 Result.insert(Result.end(), Original.begin(), Lower);
128 Result.push_back(Element);
129 Result.insert(Result.end(), Lower, Original.end());
130
131 return makePersistent(std::move(Result));
132}
133
134RangeSet RangeSet::Factory::add(RangeSet Original, const llvm::APSInt &Point) {
135 return add(Original, Range(Point));
136}
137
139 ContainerType Result = unite(*LHS.Impl, *RHS.Impl);
140 return makePersistent(std::move(Result));
141}
142
144 ContainerType Result;
145 Result.push_back(R);
146 Result = unite(*Original.Impl, Result);
147 return makePersistent(std::move(Result));
148}
149
150RangeSet RangeSet::Factory::unite(RangeSet Original, llvm::APSInt Point) {
151 return unite(Original, Range(ValueFactory.getValue(Point)));
152}
153
154RangeSet RangeSet::Factory::unite(RangeSet Original, llvm::APSInt From,
155 llvm::APSInt To) {
156 return unite(Original,
157 Range(ValueFactory.getValue(From), ValueFactory.getValue(To)));
158}
159
160template <typename T>
161static void swapIterators(T &First, T &FirstEnd, T &Second, T &SecondEnd) {
162 std::swap(First, Second);
163 std::swap(FirstEnd, SecondEnd);
164}
165
166RangeSet::ContainerType RangeSet::Factory::unite(const ContainerType &LHS,
167 const ContainerType &RHS) {
168 if (LHS.empty())
169 return RHS;
170 if (RHS.empty())
171 return LHS;
172
173 using llvm::APSInt;
174 using iterator = ContainerType::const_iterator;
175
176 iterator First = LHS.begin();
177 iterator FirstEnd = LHS.end();
178 iterator Second = RHS.begin();
179 iterator SecondEnd = RHS.end();
180 APSIntType Ty = APSIntType(First->From());
181 const APSInt Min = Ty.getMinValue();
182
183 // Handle a corner case first when both range sets start from MIN.
184 // This helps to avoid complicated conditions below. Specifically, this
185 // particular check for `MIN` is not needed in the loop below every time
186 // when we do `Second->From() - One` operation.
187 if (Min == First->From() && Min == Second->From()) {
188 if (First->To() > Second->To()) {
189 // [ First ]--->
190 // [ Second ]----->
191 // MIN^
192 // The Second range is entirely inside the First one.
193
194 // Check if Second is the last in its RangeSet.
195 if (++Second == SecondEnd)
196 // [ First ]--[ First + 1 ]--->
197 // [ Second ]--------------------->
198 // MIN^
199 // The Union is equal to First's RangeSet.
200 return LHS;
201 } else {
202 // case 1: [ First ]----->
203 // case 2: [ First ]--->
204 // [ Second ]--->
205 // MIN^
206 // The First range is entirely inside or equal to the Second one.
207
208 // Check if First is the last in its RangeSet.
209 if (++First == FirstEnd)
210 // [ First ]----------------------->
211 // [ Second ]--[ Second + 1 ]---->
212 // MIN^
213 // The Union is equal to Second's RangeSet.
214 return RHS;
215 }
216 }
217
218 const APSInt One = Ty.getValue(1);
219 ContainerType Result;
220
221 // This is called when there are no ranges left in one of the ranges.
222 // Append the rest of the ranges from another range set to the Result
223 // and return with that.
224 const auto AppendTheRest = [&Result](iterator I, iterator E) {
225 Result.append(I, E);
226 return Result;
227 };
228
229 while (true) {
230 // We want to keep the following invariant at all times:
231 // ---[ First ------>
232 // -----[ Second --->
233 if (First->From() > Second->From())
234 swapIterators(First, FirstEnd, Second, SecondEnd);
235
236 // The Union definitely starts with First->From().
237 // ----------[ First ------>
238 // ------------[ Second --->
239 // ----------[ Union ------>
240 // UnionStart^
241 const llvm::APSInt &UnionStart = First->From();
242
243 // Loop where the invariant holds.
244 while (true) {
245 // Skip all enclosed ranges.
246 // ---[ First ]--->
247 // -----[ Second ]--[ Second + 1 ]--[ Second + N ]----->
248 while (First->To() >= Second->To()) {
249 // Check if Second is the last in its RangeSet.
250 if (++Second == SecondEnd) {
251 // Append the Union.
252 // ---[ Union ]--->
253 // -----[ Second ]----->
254 // --------[ First ]--->
255 // UnionEnd^
256 Result.emplace_back(UnionStart, First->To());
257 // ---[ Union ]----------------->
258 // --------------[ First + 1]--->
259 // Append all remaining ranges from the First's RangeSet.
260 return AppendTheRest(++First, FirstEnd);
261 }
262 }
263
264 // Check if First and Second are disjoint. It means that we find
265 // the end of the Union. Exit the loop and append the Union.
266 // ---[ First ]=------------->
267 // ------------=[ Second ]--->
268 // ----MinusOne^
269 if (First->To() < Second->From() - One)
270 break;
271
272 // First is entirely inside the Union. Go next.
273 // ---[ Union ----------->
274 // ---- [ First ]-------->
275 // -------[ Second ]----->
276 // Check if First is the last in its RangeSet.
277 if (++First == FirstEnd) {
278 // Append the Union.
279 // ---[ Union ]--->
280 // -----[ First ]------->
281 // --------[ Second ]--->
282 // UnionEnd^
283 Result.emplace_back(UnionStart, Second->To());
284 // ---[ Union ]------------------>
285 // --------------[ Second + 1]--->
286 // Append all remaining ranges from the Second's RangeSet.
287 return AppendTheRest(++Second, SecondEnd);
288 }
289
290 // We know that we are at one of the two cases:
291 // case 1: --[ First ]--------->
292 // case 2: ----[ First ]------->
293 // --------[ Second ]---------->
294 // In both cases First starts after Second->From().
295 // Make sure that the loop invariant holds.
296 swapIterators(First, FirstEnd, Second, SecondEnd);
297 }
298
299 // Here First and Second are disjoint.
300 // Append the Union.
301 // ---[ Union ]--------------->
302 // -----------------[ Second ]--->
303 // ------[ First ]--------------->
304 // UnionEnd^
305 Result.emplace_back(UnionStart, First->To());
306
307 // Check if First is the last in its RangeSet.
308 if (++First == FirstEnd)
309 // ---[ Union ]--------------->
310 // --------------[ Second ]--->
311 // Append all remaining ranges from the Second's RangeSet.
312 return AppendTheRest(Second, SecondEnd);
313 }
314
315 llvm_unreachable("Normally, we should not reach here");
316}
317
319 ContainerType Result;
320 Result.push_back(From);
321 return makePersistent(std::move(Result));
322}
323
324RangeSet RangeSet::Factory::makePersistent(ContainerType &&From) {
325 llvm::FoldingSetNodeID ID;
326 void *InsertPos;
327
328 From.Profile(ID);
329 ContainerType *Result = Cache.FindNodeOrInsertPos(ID, InsertPos);
330
331 if (!Result) {
332 // It is cheaper to fully construct the resulting range on stack
333 // and move it to the freshly allocated buffer if we don't have
334 // a set like this already.
335 Result = construct(std::move(From));
336 Cache.InsertNode(Result, InsertPos);
337 }
338
339 return Result;
340}
341
342RangeSet::ContainerType *RangeSet::Factory::construct(ContainerType &&From) {
343 void *Buffer = Arena.Allocate();
344 return new (Buffer) ContainerType(std::move(From));
345}
346
347const llvm::APSInt &RangeSet::getMinValue() const {
348 assert(!isEmpty());
349 return begin()->From();
350}
351
352const llvm::APSInt &RangeSet::getMaxValue() const {
353 assert(!isEmpty());
354 return std::prev(end())->To();
355}
356
358 assert(!isEmpty());
359 return begin()->From().isUnsigned();
360}
361
363 assert(!isEmpty());
364 return begin()->From().getBitWidth();
365}
366
368 assert(!isEmpty());
369 return APSIntType(begin()->From());
370}
371
372bool RangeSet::containsImpl(llvm::APSInt &Point) const {
373 if (isEmpty() || !pin(Point))
374 return false;
375
376 Range Dummy(Point);
377 const_iterator It = llvm::upper_bound(*this, Dummy);
378 if (It == begin())
379 return false;
380
381 return std::prev(It)->Includes(Point);
382}
383
384bool RangeSet::pin(llvm::APSInt &Point) const {
386 if (Type.testInRange(Point, true) != APSIntType::RTR_Within)
387 return false;
388
389 Type.apply(Point);
390 return true;
391}
392
393bool RangeSet::pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const {
394 // This function has nine cases, the cartesian product of range-testing
395 // both the upper and lower bounds against the symbol's type.
396 // Each case requires a different pinning operation.
397 // The function returns false if the described range is entirely outside
398 // the range of values for the associated symbol.
400 APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower, true);
401 APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper, true);
402
403 switch (LowerTest) {
405 switch (UpperTest) {
407 // The entire range is outside the symbol's set of possible values.
408 // If this is a conventionally-ordered range, the state is infeasible.
409 if (Lower <= Upper)
410 return false;
411
412 // However, if the range wraps around, it spans all possible values.
413 Lower = Type.getMinValue();
414 Upper = Type.getMaxValue();
415 break;
417 // The range starts below what's possible but ends within it. Pin.
418 Lower = Type.getMinValue();
419 Type.apply(Upper);
420 break;
422 // The range spans all possible values for the symbol. Pin.
423 Lower = Type.getMinValue();
424 Upper = Type.getMaxValue();
425 break;
426 }
427 break;
429 switch (UpperTest) {
431 // The range wraps around, but all lower values are not possible.
432 Type.apply(Lower);
433 Upper = Type.getMaxValue();
434 break;
436 // The range may or may not wrap around, but both limits are valid.
437 Type.apply(Lower);
438 Type.apply(Upper);
439 break;
441 // The range starts within what's possible but ends above it. Pin.
442 Type.apply(Lower);
443 Upper = Type.getMaxValue();
444 break;
445 }
446 break;
448 switch (UpperTest) {
450 // The range wraps but is outside the symbol's set of possible values.
451 return false;
453 // The range starts above what's possible but ends within it (wrap).
454 Lower = Type.getMinValue();
455 Type.apply(Upper);
456 break;
458 // The entire range is outside the symbol's set of possible values.
459 // If this is a conventionally-ordered range, the state is infeasible.
460 if (Lower <= Upper)
461 return false;
462
463 // However, if the range wraps around, it spans all possible values.
464 Lower = Type.getMinValue();
465 Upper = Type.getMaxValue();
466 break;
467 }
468 break;
469 }
470
471 return true;
472}
473
475 llvm::APSInt Upper) {
476 if (What.isEmpty() || !What.pin(Lower, Upper))
477 return getEmptySet();
478
479 ContainerType DummyContainer;
480
481 if (Lower <= Upper) {
482 // [Lower, Upper] is a regular range.
483 //
484 // Shortcut: check that there is even a possibility of the intersection
485 // by checking the two following situations:
486 //
487 // <---[ What ]---[------]------>
488 // Lower Upper
489 // -or-
490 // <----[------]----[ What ]---->
491 // Lower Upper
492 if (What.getMaxValue() < Lower || Upper < What.getMinValue())
493 return getEmptySet();
494
495 DummyContainer.push_back(
496 Range(ValueFactory.getValue(Lower), ValueFactory.getValue(Upper)));
497 } else {
498 // [Lower, Upper] is an inverted range, i.e. [MIN, Upper] U [Lower, MAX]
499 //
500 // Shortcut: check that there is even a possibility of the intersection
501 // by checking the following situation:
502 //
503 // <------]---[ What ]---[------>
504 // Upper Lower
505 if (What.getMaxValue() < Lower && Upper < What.getMinValue())
506 return getEmptySet();
507
508 DummyContainer.push_back(
509 Range(ValueFactory.getMinValue(Upper), ValueFactory.getValue(Upper)));
510 DummyContainer.push_back(
511 Range(ValueFactory.getValue(Lower), ValueFactory.getMaxValue(Lower)));
512 }
513
514 return intersect(*What.Impl, DummyContainer);
515}
516
517RangeSet RangeSet::Factory::intersect(const RangeSet::ContainerType &LHS,
518 const RangeSet::ContainerType &RHS) {
519 ContainerType Result;
520 Result.reserve(std::max(LHS.size(), RHS.size()));
521
522 const_iterator First = LHS.begin(), Second = RHS.begin(),
523 FirstEnd = LHS.end(), SecondEnd = RHS.end();
524
525 // If we ran out of ranges in one set, but not in the other,
526 // it means that those elements are definitely not in the
527 // intersection.
528 while (First != FirstEnd && Second != SecondEnd) {
529 // We want to keep the following invariant at all times:
530 //
531 // ----[ First ---------------------->
532 // --------[ Second ----------------->
533 if (Second->From() < First->From())
534 swapIterators(First, FirstEnd, Second, SecondEnd);
535
536 // Loop where the invariant holds:
537 do {
538 // Check for the following situation:
539 //
540 // ----[ First ]--------------------->
541 // ---------------[ Second ]--------->
542 //
543 // which means that...
544 if (Second->From() > First->To()) {
545 // ...First is not in the intersection.
546 //
547 // We should move on to the next range after First and break out of the
548 // loop because the invariant might not be true.
549 ++First;
550 break;
551 }
552
553 // We have a guaranteed intersection at this point!
554 // And this is the current situation:
555 //
556 // ----[ First ]----------------->
557 // -------[ Second ------------------>
558 //
559 // Additionally, it definitely starts with Second->From().
560 const llvm::APSInt &IntersectionStart = Second->From();
561
562 // It is important to know which of the two ranges' ends
563 // is greater. That "longer" range might have some other
564 // intersections, while the "shorter" range might not.
565 if (Second->To() > First->To()) {
566 // Here we make a decision to keep First as the "longer"
567 // range.
568 swapIterators(First, FirstEnd, Second, SecondEnd);
569 }
570
571 // At this point, we have the following situation:
572 //
573 // ---- First ]-------------------->
574 // ---- Second ]--[ Second+1 ---------->
575 //
576 // We don't know the relationship between First->From and
577 // Second->From and we don't know whether Second+1 intersects
578 // with First.
579 //
580 // However, we know that [IntersectionStart, Second->To] is
581 // a part of the intersection...
582 Result.push_back(Range(IntersectionStart, Second->To()));
583 ++Second;
584 // ...and that the invariant will hold for a valid Second+1
585 // because First->From <= Second->To < (Second+1)->From.
586 } while (Second != SecondEnd);
587 }
588
589 if (Result.empty())
590 return getEmptySet();
591
592 return makePersistent(std::move(Result));
593}
594
596 // Shortcut: let's see if the intersection is even possible.
597 if (LHS.isEmpty() || RHS.isEmpty() || LHS.getMaxValue() < RHS.getMinValue() ||
598 RHS.getMaxValue() < LHS.getMinValue())
599 return getEmptySet();
600
601 return intersect(*LHS.Impl, *RHS.Impl);
602}
603
605 if (LHS.containsImpl(Point))
606 return getRangeSet(ValueFactory.getValue(Point));
607
608 return getEmptySet();
609}
610
612 if (What.isEmpty())
613 return getEmptySet();
614
615 const llvm::APSInt SampleValue = What.getMinValue();
616 const llvm::APSInt &MIN = ValueFactory.getMinValue(SampleValue);
617 const llvm::APSInt &MAX = ValueFactory.getMaxValue(SampleValue);
618
619 ContainerType Result;
620 Result.reserve(What.size() + (SampleValue == MIN));
621
622 // Handle a special case for MIN value.
623 const_iterator It = What.begin();
624 const_iterator End = What.end();
625
626 const llvm::APSInt &From = It->From();
627 const llvm::APSInt &To = It->To();
628
629 if (From == MIN) {
630 // If the range [From, To] is [MIN, MAX], then result is also [MIN, MAX].
631 if (To == MAX) {
632 return What;
633 }
634
635 const_iterator Last = std::prev(End);
636
637 // Try to find and unite the following ranges:
638 // [MIN, MIN] & [MIN + 1, N] => [MIN, N].
639 if (Last->To() == MAX) {
640 // It means that in the original range we have ranges
641 // [MIN, A], ... , [B, MAX]
642 // And the result should be [MIN, -B], ..., [-A, MAX]
643 Result.emplace_back(MIN, ValueFactory.getValue(-Last->From()));
644 // We already negated Last, so we can skip it.
645 End = Last;
646 } else {
647 // Add a separate range for the lowest value.
648 Result.emplace_back(MIN, MIN);
649 }
650
651 // Skip adding the second range in case when [From, To] are [MIN, MIN].
652 if (To != MIN) {
653 Result.emplace_back(ValueFactory.getValue(-To), MAX);
654 }
655
656 // Skip the first range in the loop.
657 ++It;
658 }
659
660 // Negate all other ranges.
661 for (; It != End; ++It) {
662 // Negate int values.
663 const llvm::APSInt &NewFrom = ValueFactory.getValue(-It->To());
664 const llvm::APSInt &NewTo = ValueFactory.getValue(-It->From());
665
666 // Add a negated range.
667 Result.emplace_back(NewFrom, NewTo);
668 }
669
670 llvm::sort(Result);
671 return makePersistent(std::move(Result));
672}
673
674// Convert range set to the given integral type using truncation and promotion.
675// This works similar to APSIntType::apply function but for the range set.
677 // Set is empty or NOOP (aka cast to the same type).
678 if (What.isEmpty() || What.getAPSIntType() == Ty)
679 return What;
680
681 const bool IsConversion = What.isUnsigned() != Ty.isUnsigned();
682 const bool IsTruncation = What.getBitWidth() > Ty.getBitWidth();
683 const bool IsPromotion = What.getBitWidth() < Ty.getBitWidth();
684
685 if (IsTruncation)
686 return makePersistent(truncateTo(What, Ty));
687
688 // Here we handle 2 cases:
689 // - IsConversion && !IsPromotion.
690 // In this case we handle changing a sign with same bitwidth: char -> uchar,
691 // uint -> int. Here we convert negatives to positives and positives which
692 // is out of range to negatives. We use convertTo function for that.
693 // - IsConversion && IsPromotion && !What.isUnsigned().
694 // In this case we handle changing a sign from signeds to unsigneds with
695 // higher bitwidth: char -> uint, int-> uint64. The point is that we also
696 // need convert negatives to positives and use convertTo function as well.
697 // For example, we don't need such a convertion when converting unsigned to
698 // signed with higher bitwidth, because all the values of unsigned is valid
699 // for the such signed.
700 if (IsConversion && (!IsPromotion || !What.isUnsigned()))
701 return makePersistent(convertTo(What, Ty));
702
703 assert(IsPromotion && "Only promotion operation from unsigneds left.");
704 return makePersistent(promoteTo(What, Ty));
705}
706
708 assert(T->isIntegralOrEnumerationType() && "T shall be an integral type.");
709 return castTo(What, ValueFactory.getAPSIntType(T));
710}
711
712RangeSet::ContainerType RangeSet::Factory::truncateTo(RangeSet What,
713 APSIntType Ty) {
714 using llvm::APInt;
715 using llvm::APSInt;
716 ContainerType Result;
717 ContainerType Dummy;
718 // CastRangeSize is an amount of all possible values of cast type.
719 // Example: `char` has 256 values; `short` has 65536 values.
720 // But in fact we use `amount of values` - 1, because
721 // we can't keep `amount of values of UINT64` inside uint64_t.
722 // E.g. 256 is an amount of all possible values of `char` and we can't keep
723 // it inside `char`.
724 // And it's OK, it's enough to do correct calculations.
725 uint64_t CastRangeSize = APInt::getMaxValue(Ty.getBitWidth()).getZExtValue();
726 for (const Range &R : What) {
727 // Get bounds of the given range.
728 APSInt FromInt = R.From();
729 APSInt ToInt = R.To();
730 // CurrentRangeSize is an amount of all possible values of the current
731 // range minus one.
732 uint64_t CurrentRangeSize = (ToInt - FromInt).getZExtValue();
733 // This is an optimization for a specific case when this Range covers
734 // the whole range of the target type.
735 Dummy.clear();
736 if (CurrentRangeSize >= CastRangeSize) {
737 Dummy.emplace_back(ValueFactory.getMinValue(Ty),
738 ValueFactory.getMaxValue(Ty));
739 Result = std::move(Dummy);
740 break;
741 }
742 // Cast the bounds.
743 Ty.apply(FromInt);
744 Ty.apply(ToInt);
745 const APSInt &PersistentFrom = ValueFactory.getValue(FromInt);
746 const APSInt &PersistentTo = ValueFactory.getValue(ToInt);
747 if (FromInt > ToInt) {
748 Dummy.emplace_back(ValueFactory.getMinValue(Ty), PersistentTo);
749 Dummy.emplace_back(PersistentFrom, ValueFactory.getMaxValue(Ty));
750 } else
751 Dummy.emplace_back(PersistentFrom, PersistentTo);
752 // Every range retrieved after truncation potentialy has garbage values.
753 // So, we have to unite every next range with the previouses.
754 Result = unite(Result, Dummy);
755 }
756
757 return Result;
758}
759
760// Divide the convertion into two phases (presented as loops here).
761// First phase(loop) works when casted values go in ascending order.
762// E.g. char{1,3,5,127} -> uint{1,3,5,127}
763// Interrupt the first phase and go to second one when casted values start
764// go in descending order. That means that we crossed over the middle of
765// the type value set (aka 0 for signeds and MAX/2+1 for unsigneds).
766// For instance:
767// 1: uchar{1,3,5,128,255} -> char{1,3,5,-128,-1}
768// Here we put {1,3,5} to one array and {-128, -1} to another
769// 2: char{-128,-127,-1,0,1,2} -> uchar{128,129,255,0,1,3}
770// Here we put {128,129,255} to one array and {0,1,3} to another.
771// After that we unite both arrays.
772// NOTE: We don't just concatenate the arrays, because they may have
773// adjacent ranges, e.g.:
774// 1: char(-128, 127) -> uchar -> arr1(128, 255), arr2(0, 127) ->
775// unite -> uchar(0, 255)
776// 2: uchar(0, 1)U(254, 255) -> char -> arr1(0, 1), arr2(-2, -1) ->
777// unite -> uchar(-2, 1)
778RangeSet::ContainerType RangeSet::Factory::convertTo(RangeSet What,
779 APSIntType Ty) {
780 using llvm::APInt;
781 using llvm::APSInt;
782 using Bounds = std::pair<const APSInt &, const APSInt &>;
783 ContainerType AscendArray;
784 ContainerType DescendArray;
785 auto CastRange = [Ty, &VF = ValueFactory](const Range &R) -> Bounds {
786 // Get bounds of the given range.
787 APSInt FromInt = R.From();
788 APSInt ToInt = R.To();
789 // Cast the bounds.
790 Ty.apply(FromInt);
791 Ty.apply(ToInt);
792 return {VF.getValue(FromInt), VF.getValue(ToInt)};
793 };
794 // Phase 1. Fill the first array.
795 APSInt LastConvertedInt = Ty.getMinValue();
796 const auto *It = What.begin();
797 const auto *E = What.end();
798 while (It != E) {
799 Bounds NewBounds = CastRange(*(It++));
800 // If values stop going acsending order, go to the second phase(loop).
801 if (NewBounds.first < LastConvertedInt) {
802 DescendArray.emplace_back(NewBounds.first, NewBounds.second);
803 break;
804 }
805 // If the range contains a midpoint, then split the range.
806 // E.g. char(-5, 5) -> uchar(251, 5)
807 // Here we shall add a range (251, 255) to the first array and (0, 5) to the
808 // second one.
809 if (NewBounds.first > NewBounds.second) {
810 DescendArray.emplace_back(ValueFactory.getMinValue(Ty), NewBounds.second);
811 AscendArray.emplace_back(NewBounds.first, ValueFactory.getMaxValue(Ty));
812 } else
813 // Values are going acsending order.
814 AscendArray.emplace_back(NewBounds.first, NewBounds.second);
815 LastConvertedInt = NewBounds.first;
816 }
817 // Phase 2. Fill the second array.
818 while (It != E) {
819 Bounds NewBounds = CastRange(*(It++));
820 DescendArray.emplace_back(NewBounds.first, NewBounds.second);
821 }
822 // Unite both arrays.
823 return unite(AscendArray, DescendArray);
824}
825
826/// Promotion from unsigneds to signeds/unsigneds left.
827RangeSet::ContainerType RangeSet::Factory::promoteTo(RangeSet What,
828 APSIntType Ty) {
829 ContainerType Result;
830 // We definitely know the size of the result set.
831 Result.reserve(What.size());
832
833 // Each unsigned value fits every larger type without any changes,
834 // whether the larger type is signed or unsigned. So just promote and push
835 // back each range one by one.
836 for (const Range &R : What) {
837 // Get bounds of the given range.
838 llvm::APSInt FromInt = R.From();
839 llvm::APSInt ToInt = R.To();
840 // Cast the bounds.
841 Ty.apply(FromInt);
842 Ty.apply(ToInt);
843 Result.emplace_back(ValueFactory.getValue(FromInt),
844 ValueFactory.getValue(ToInt));
845 }
846 return Result;
847}
848
850 const llvm::APSInt &Point) {
851 if (!From.contains(Point))
852 return From;
853
854 llvm::APSInt Upper = Point;
855 llvm::APSInt Lower = Point;
856
857 ++Upper;
858 --Lower;
859
860 // Notice that the lower bound is greater than the upper bound.
861 return intersect(From, Upper, Lower);
862}
863
864LLVM_DUMP_METHOD void Range::dump(raw_ostream &OS) const {
865 OS << '[' << toString(From(), 10) << ", " << toString(To(), 10) << ']';
866}
867LLVM_DUMP_METHOD void Range::dump() const { dump(llvm::errs()); }
868
869LLVM_DUMP_METHOD void RangeSet::dump(raw_ostream &OS) const {
870 OS << "{ ";
871 llvm::interleaveComma(*this, OS, [&OS](const Range &R) { R.dump(OS); });
872 OS << " }";
873}
874LLVM_DUMP_METHOD void RangeSet::dump() const { dump(llvm::errs()); }
875
877
878namespace {
879class EquivalenceClass;
880} // end anonymous namespace
881
882REGISTER_MAP_WITH_PROGRAMSTATE(ClassMap, SymbolRef, EquivalenceClass)
883REGISTER_MAP_WITH_PROGRAMSTATE(ClassMembers, EquivalenceClass, SymbolSet)
884REGISTER_MAP_WITH_PROGRAMSTATE(ConstraintRange, EquivalenceClass, RangeSet)
885
886REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(ClassSet, EquivalenceClass)
887REGISTER_MAP_WITH_PROGRAMSTATE(DisequalityMap, EquivalenceClass, ClassSet)
888
889namespace {
890/// This class encapsulates a set of symbols equal to each other.
891///
892/// The main idea of the approach requiring such classes is in narrowing
893/// and sharing constraints between symbols within the class. Also we can
894/// conclude that there is no practical need in storing constraints for
895/// every member of the class separately.
896///
897/// Main terminology:
898///
899/// * "Equivalence class" is an object of this class, which can be efficiently
900/// compared to other classes. It represents the whole class without
901/// storing the actual in it. The members of the class however can be
902/// retrieved from the state.
903///
904/// * "Class members" are the symbols corresponding to the class. This means
905/// that A == B for every member symbols A and B from the class. Members of
906/// each class are stored in the state.
907///
908/// * "Trivial class" is a class that has and ever had only one same symbol.
909///
910/// * "Merge operation" merges two classes into one. It is the main operation
911/// to produce non-trivial classes.
912/// If, at some point, we can assume that two symbols from two distinct
913/// classes are equal, we can merge these classes.
914class EquivalenceClass : public llvm::FoldingSetNode {
915public:
916 /// Find equivalence class for the given symbol in the given state.
917 [[nodiscard]] static inline EquivalenceClass find(ProgramStateRef State,
918 SymbolRef Sym);
919
920 /// Merge classes for the given symbols and return a new state.
921 [[nodiscard]] static inline ProgramStateRef merge(RangeSet::Factory &F,
922 ProgramStateRef State,
924 SymbolRef Second);
925 // Merge this class with the given class and return a new state.
926 [[nodiscard]] inline ProgramStateRef
927 merge(RangeSet::Factory &F, ProgramStateRef State, EquivalenceClass Other);
928
929 /// Return a set of class members for the given state.
930 [[nodiscard]] inline SymbolSet getClassMembers(ProgramStateRef State) const;
931
932 /// Return true if the current class is trivial in the given state.
933 /// A class is trivial if and only if there is not any member relations stored
934 /// to it in State/ClassMembers.
935 /// An equivalence class with one member might seem as it does not hold any
936 /// meaningful information, i.e. that is a tautology. However, during the
937 /// removal of dead symbols we do not remove classes with one member for
938 /// resource and performance reasons. Consequently, a class with one member is
939 /// not necessarily trivial. It could happen that we have a class with two
940 /// members and then during the removal of dead symbols we remove one of its
941 /// members. In this case, the class is still non-trivial (it still has the
942 /// mappings in ClassMembers), even though it has only one member.
943 [[nodiscard]] inline bool isTrivial(ProgramStateRef State) const;
944
945 /// Return true if the current class is trivial and its only member is dead.
946 [[nodiscard]] inline bool isTriviallyDead(ProgramStateRef State,
947 SymbolReaper &Reaper) const;
948
949 [[nodiscard]] static inline ProgramStateRef
950 markDisequal(RangeSet::Factory &F, ProgramStateRef State, SymbolRef First,
951 SymbolRef Second);
952 [[nodiscard]] static inline ProgramStateRef
953 markDisequal(RangeSet::Factory &F, ProgramStateRef State,
954 EquivalenceClass First, EquivalenceClass Second);
955 [[nodiscard]] inline ProgramStateRef
956 markDisequal(RangeSet::Factory &F, ProgramStateRef State,
957 EquivalenceClass Other) const;
958 [[nodiscard]] static inline ClassSet getDisequalClasses(ProgramStateRef State,
959 SymbolRef Sym);
960 [[nodiscard]] inline ClassSet getDisequalClasses(ProgramStateRef State) const;
961 [[nodiscard]] inline ClassSet
962 getDisequalClasses(DisequalityMapTy Map, ClassSet::Factory &Factory) const;
963
964 [[nodiscard]] static inline std::optional<bool>
965 areEqual(ProgramStateRef State, EquivalenceClass First,
966 EquivalenceClass Second);
967 [[nodiscard]] static inline std::optional<bool>
968 areEqual(ProgramStateRef State, SymbolRef First, SymbolRef Second);
969
970 /// Remove one member from the class.
971 [[nodiscard]] ProgramStateRef removeMember(ProgramStateRef State,
972 const SymbolRef Old);
973
974 /// Iterate over all symbols and try to simplify them.
975 [[nodiscard]] static inline ProgramStateRef simplify(SValBuilder &SVB,
977 ProgramStateRef State,
978 EquivalenceClass Class);
979
980 void dumpToStream(ProgramStateRef State, raw_ostream &os) const;
981 LLVM_DUMP_METHOD void dump(ProgramStateRef State) const {
982 dumpToStream(State, llvm::errs());
983 }
984
985 /// Check equivalence data for consistency.
986 [[nodiscard]] LLVM_ATTRIBUTE_UNUSED static bool
987 isClassDataConsistent(ProgramStateRef State);
988
989 [[nodiscard]] QualType getType() const {
990 return getRepresentativeSymbol()->getType();
991 }
992
993 EquivalenceClass() = delete;
994 EquivalenceClass(const EquivalenceClass &) = default;
995 EquivalenceClass &operator=(const EquivalenceClass &) = delete;
996 EquivalenceClass(EquivalenceClass &&) = default;
997 EquivalenceClass &operator=(EquivalenceClass &&) = delete;
998
999 bool operator==(const EquivalenceClass &Other) const {
1000 return ID == Other.ID;
1001 }
1002 bool operator<(const EquivalenceClass &Other) const { return ID < Other.ID; }
1003 bool operator!=(const EquivalenceClass &Other) const {
1004 return !operator==(Other);
1005 }
1006
1007 static void Profile(llvm::FoldingSetNodeID &ID, uintptr_t CID) {
1008 ID.AddInteger(CID);
1009 }
1010
1011 void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, this->ID); }
1012
1013private:
1014 /* implicit */ EquivalenceClass(SymbolRef Sym)
1015 : ID(reinterpret_cast<uintptr_t>(Sym)) {}
1016
1017 /// This function is intended to be used ONLY within the class.
1018 /// The fact that ID is a pointer to a symbol is an implementation detail
1019 /// and should stay that way.
1020 /// In the current implementation, we use it to retrieve the only member
1021 /// of the trivial class.
1022 SymbolRef getRepresentativeSymbol() const {
1023 return reinterpret_cast<SymbolRef>(ID);
1024 }
1025 static inline SymbolSet::Factory &getMembersFactory(ProgramStateRef State);
1026
1027 inline ProgramStateRef mergeImpl(RangeSet::Factory &F, ProgramStateRef State,
1028 SymbolSet Members, EquivalenceClass Other,
1029 SymbolSet OtherMembers);
1030
1031 static inline bool
1032 addToDisequalityInfo(DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
1034 EquivalenceClass First, EquivalenceClass Second);
1035
1036 /// This is a unique identifier of the class.
1037 uintptr_t ID;
1038};
1039
1040//===----------------------------------------------------------------------===//
1041// Constraint functions
1042//===----------------------------------------------------------------------===//
1043
1044[[nodiscard]] LLVM_ATTRIBUTE_UNUSED bool
1045areFeasible(ConstraintRangeTy Constraints) {
1046 return llvm::none_of(
1047 Constraints,
1048 [](const std::pair<EquivalenceClass, RangeSet> &ClassConstraint) {
1049 return ClassConstraint.second.isEmpty();
1050 });
1051}
1052
1053[[nodiscard]] inline const RangeSet *getConstraint(ProgramStateRef State,
1054 EquivalenceClass Class) {
1055 return State->get<ConstraintRange>(Class);
1056}
1057
1058[[nodiscard]] inline const RangeSet *getConstraint(ProgramStateRef State,
1059 SymbolRef Sym) {
1060 return getConstraint(State, EquivalenceClass::find(State, Sym));
1061}
1062
1063[[nodiscard]] ProgramStateRef setConstraint(ProgramStateRef State,
1064 EquivalenceClass Class,
1065 RangeSet Constraint) {
1066 return State->set<ConstraintRange>(Class, Constraint);
1067}
1068
1069[[nodiscard]] ProgramStateRef setConstraints(ProgramStateRef State,
1070 ConstraintRangeTy Constraints) {
1071 return State->set<ConstraintRange>(Constraints);
1072}
1073
1074//===----------------------------------------------------------------------===//
1075// Equality/diseqiality abstraction
1076//===----------------------------------------------------------------------===//
1077
1078/// A small helper function for detecting symbolic (dis)equality.
1079///
1080/// Equality check can have different forms (like a == b or a - b) and this
1081/// class encapsulates those away if the only thing the user wants to check -
1082/// whether it's equality/diseqiality or not.
1083///
1084/// \returns true if assuming this Sym to be true means equality of operands
1085/// false if it means disequality of operands
1086/// std::nullopt otherwise
1087std::optional<bool> meansEquality(const SymSymExpr *Sym) {
1088 switch (Sym->getOpcode()) {
1089 case BO_Sub:
1090 // This case is: A - B != 0 -> disequality check.
1091 return false;
1092 case BO_EQ:
1093 // This case is: A == B != 0 -> equality check.
1094 return true;
1095 case BO_NE:
1096 // This case is: A != B != 0 -> diseqiality check.
1097 return false;
1098 default:
1099 return std::nullopt;
1100 }
1101}
1102
1103//===----------------------------------------------------------------------===//
1104// Intersection functions
1105//===----------------------------------------------------------------------===//
1106
1107template <class SecondTy, class... RestTy>
1108[[nodiscard]] inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
1109 SecondTy Second, RestTy... Tail);
1110
1111template <class... RangeTy> struct IntersectionTraits;
1112
1113template <class... TailTy> struct IntersectionTraits<RangeSet, TailTy...> {
1114 // Found RangeSet, no need to check any further
1115 using Type = RangeSet;
1116};
1117
1118template <> struct IntersectionTraits<> {
1119 // We ran out of types, and we didn't find any RangeSet, so the result should
1120 // be optional.
1121 using Type = std::optional<RangeSet>;
1122};
1123
1124template <class OptionalOrPointer, class... TailTy>
1125struct IntersectionTraits<OptionalOrPointer, TailTy...> {
1126 // If current type is Optional or a raw pointer, we should keep looking.
1127 using Type = typename IntersectionTraits<TailTy...>::Type;
1128};
1129
1130template <class EndTy>
1131[[nodiscard]] inline EndTy intersect(RangeSet::Factory &F, EndTy End) {
1132 // If the list contains only RangeSet or std::optional<RangeSet>, simply
1133 // return that range set.
1134 return End;
1135}
1136
1137[[nodiscard]] LLVM_ATTRIBUTE_UNUSED inline std::optional<RangeSet>
1138intersect(RangeSet::Factory &F, const RangeSet *End) {
1139 // This is an extraneous conversion from a raw pointer into
1140 // std::optional<RangeSet>
1141 if (End) {
1142 return *End;
1143 }
1144 return std::nullopt;
1145}
1146
1147template <class... RestTy>
1148[[nodiscard]] inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
1149 RangeSet Second, RestTy... Tail) {
1150 // Here we call either the <RangeSet,RangeSet,...> or <RangeSet,...> version
1151 // of the function and can be sure that the result is RangeSet.
1152 return intersect(F, F.intersect(Head, Second), Tail...);
1153}
1154
1155template <class SecondTy, class... RestTy>
1156[[nodiscard]] inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
1157 SecondTy Second, RestTy... Tail) {
1158 if (Second) {
1159 // Here we call the <RangeSet,RangeSet,...> version of the function...
1160 return intersect(F, Head, *Second, Tail...);
1161 }
1162 // ...and here it is either <RangeSet,RangeSet,...> or <RangeSet,...>, which
1163 // means that the result is definitely RangeSet.
1164 return intersect(F, Head, Tail...);
1165}
1166
1167/// Main generic intersect function.
1168/// It intersects all of the given range sets. If some of the given arguments
1169/// don't hold a range set (nullptr or std::nullopt), the function will skip
1170/// them.
1171///
1172/// Available representations for the arguments are:
1173/// * RangeSet
1174/// * std::optional<RangeSet>
1175/// * RangeSet *
1176/// Pointer to a RangeSet is automatically assumed to be nullable and will get
1177/// checked as well as the optional version. If this behaviour is undesired,
1178/// please dereference the pointer in the call.
1179///
1180/// Return type depends on the arguments' types. If we can be sure in compile
1181/// time that there will be a range set as a result, the returning type is
1182/// simply RangeSet, in other cases we have to back off to
1183/// std::optional<RangeSet>.
1184///
1185/// Please, prefer optional range sets to raw pointers. If the last argument is
1186/// a raw pointer and all previous arguments are std::nullopt, it will cost one
1187/// additional check to convert RangeSet * into std::optional<RangeSet>.
1188template <class HeadTy, class SecondTy, class... RestTy>
1189[[nodiscard]] inline
1190 typename IntersectionTraits<HeadTy, SecondTy, RestTy...>::Type
1191 intersect(RangeSet::Factory &F, HeadTy Head, SecondTy Second,
1192 RestTy... Tail) {
1193 if (Head) {
1194 return intersect(F, *Head, Second, Tail...);
1195 }
1196 return intersect(F, Second, Tail...);
1197}
1198
1199//===----------------------------------------------------------------------===//
1200// Symbolic reasoning logic
1201//===----------------------------------------------------------------------===//
1202
1203/// A little component aggregating all of the reasoning we have about
1204/// the ranges of symbolic expressions.
1205///
1206/// Even when we don't know the exact values of the operands, we still
1207/// can get a pretty good estimate of the result's range.
1208class SymbolicRangeInferrer
1209 : public SymExprVisitor<SymbolicRangeInferrer, RangeSet> {
1210public:
1211 template <class SourceType>
1212 static RangeSet inferRange(RangeSet::Factory &F, ProgramStateRef State,
1213 SourceType Origin) {
1214 SymbolicRangeInferrer Inferrer(F, State);
1215 return Inferrer.infer(Origin);
1216 }
1217
1218 RangeSet VisitSymExpr(SymbolRef Sym) {
1219 if (std::optional<RangeSet> RS = getRangeForNegatedSym(Sym))
1220 return *RS;
1221 // If we've reached this line, the actual type of the symbolic
1222 // expression is not supported for advanced inference.
1223 // In this case, we simply backoff to the default "let's simply
1224 // infer the range from the expression's type".
1225 return infer(Sym->getType());
1226 }
1227
1228 RangeSet VisitUnarySymExpr(const UnarySymExpr *USE) {
1229 if (std::optional<RangeSet> RS = getRangeForNegatedUnarySym(USE))
1230 return *RS;
1231 return infer(USE->getType());
1232 }
1233
1234 RangeSet VisitSymIntExpr(const SymIntExpr *Sym) {
1235 return VisitBinaryOperator(Sym);
1236 }
1237
1238 RangeSet VisitIntSymExpr(const IntSymExpr *Sym) {
1239 return VisitBinaryOperator(Sym);
1240 }
1241
1242 RangeSet VisitSymSymExpr(const SymSymExpr *SSE) {
1243 return intersect(
1244 RangeFactory,
1245 // If Sym is a difference of symbols A - B, then maybe we have range
1246 // set stored for B - A.
1247 //
1248 // If we have range set stored for both A - B and B - A then
1249 // calculate the effective range set by intersecting the range set
1250 // for A - B and the negated range set of B - A.
1251 getRangeForNegatedSymSym(SSE),
1252 // If commutative, we may have constaints for the commuted variant.
1253 getRangeCommutativeSymSym(SSE),
1254 // If Sym is a comparison expression (except <=>),
1255 // find any other comparisons with the same operands.
1256 // See function description.
1257 getRangeForComparisonSymbol(SSE),
1258 // If Sym is (dis)equality, we might have some information
1259 // on that in our equality classes data structure.
1260 getRangeForEqualities(SSE),
1261 // And we should always check what we can get from the operands.
1262 VisitBinaryOperator(SSE));
1263 }
1264
1265private:
1266 SymbolicRangeInferrer(RangeSet::Factory &F, ProgramStateRef S)
1267 : ValueFactory(F.getValueFactory()), RangeFactory(F), State(S) {}
1268
1269 /// Infer range information from the given integer constant.
1270 ///
1271 /// It's not a real "inference", but is here for operating with
1272 /// sub-expressions in a more polymorphic manner.
1273 RangeSet inferAs(const llvm::APSInt &Val, QualType) {
1274 return {RangeFactory, Val};
1275 }
1276
1277 /// Infer range information from symbol in the context of the given type.
1278 RangeSet inferAs(SymbolRef Sym, QualType DestType) {
1279 QualType ActualType = Sym->getType();
1280 // Check that we can reason about the symbol at all.
1281 if (ActualType->isIntegralOrEnumerationType() ||
1282 Loc::isLocType(ActualType)) {
1283 return infer(Sym);
1284 }
1285 // Otherwise, let's simply infer from the destination type.
1286 // We couldn't figure out nothing else about that expression.
1287 return infer(DestType);
1288 }
1289
1290 RangeSet infer(SymbolRef Sym) {
1291 return intersect(RangeFactory,
1292 // Of course, we should take the constraint directly
1293 // associated with this symbol into consideration.
1294 getConstraint(State, Sym),
1295 // Apart from the Sym itself, we can infer quite a lot if
1296 // we look into subexpressions of Sym.
1297 Visit(Sym));
1298 }
1299
1300 RangeSet infer(EquivalenceClass Class) {
1301 if (const RangeSet *AssociatedConstraint = getConstraint(State, Class))
1302 return *AssociatedConstraint;
1303
1304 return infer(Class.getType());
1305 }
1306
1307 /// Infer range information solely from the type.
1308 RangeSet infer(QualType T) {
1309 // Lazily generate a new RangeSet representing all possible values for the
1310 // given symbol type.
1311 RangeSet Result(RangeFactory, ValueFactory.getMinValue(T),
1312 ValueFactory.getMaxValue(T));
1313
1314 // References are known to be non-zero.
1315 if (T->isReferenceType())
1316 return assumeNonZero(Result, T);
1317
1318 return Result;
1319 }
1320
1321 template <class BinarySymExprTy>
1322 RangeSet VisitBinaryOperator(const BinarySymExprTy *Sym) {
1323 // TODO #1: VisitBinaryOperator implementation might not make a good
1324 // use of the inferred ranges. In this case, we might be calculating
1325 // everything for nothing. This being said, we should introduce some
1326 // sort of laziness mechanism here.
1327 //
1328 // TODO #2: We didn't go into the nested expressions before, so it
1329 // might cause us spending much more time doing the inference.
1330 // This can be a problem for deeply nested expressions that are
1331 // involved in conditions and get tested continuously. We definitely
1332 // need to address this issue and introduce some sort of caching
1333 // in here.
1334 QualType ResultType = Sym->getType();
1335 return VisitBinaryOperator(inferAs(Sym->getLHS(), ResultType),
1336 Sym->getOpcode(),
1337 inferAs(Sym->getRHS(), ResultType), ResultType);
1338 }
1339
1340 RangeSet VisitBinaryOperator(RangeSet LHS, BinaryOperator::Opcode Op,
1341 RangeSet RHS, QualType T);
1342
1343 //===----------------------------------------------------------------------===//
1344 // Ranges and operators
1345 //===----------------------------------------------------------------------===//
1346
1347 /// Return a rough approximation of the given range set.
1348 ///
1349 /// For the range set:
1350 /// { [x_0, y_0], [x_1, y_1], ... , [x_N, y_N] }
1351 /// it will return the range [x_0, y_N].
1352 static Range fillGaps(RangeSet Origin) {
1353 assert(!Origin.isEmpty());
1354 return {Origin.getMinValue(), Origin.getMaxValue()};
1355 }
1356
1357 /// Try to convert given range into the given type.
1358 ///
1359 /// It will return std::nullopt only when the trivial conversion is possible.
1360 std::optional<Range> convert(const Range &Origin, APSIntType To) {
1361 if (To.testInRange(Origin.From(), false) != APSIntType::RTR_Within ||
1362 To.testInRange(Origin.To(), false) != APSIntType::RTR_Within) {
1363 return std::nullopt;
1364 }
1365 return Range(ValueFactory.Convert(To, Origin.From()),
1366 ValueFactory.Convert(To, Origin.To()));
1367 }
1368
1369 template <BinaryOperator::Opcode Op>
1370 RangeSet VisitBinaryOperator(RangeSet LHS, RangeSet RHS, QualType T) {
1371 assert(!LHS.isEmpty() && !RHS.isEmpty());
1372
1373 Range CoarseLHS = fillGaps(LHS);
1374 Range CoarseRHS = fillGaps(RHS);
1375
1376 APSIntType ResultType = ValueFactory.getAPSIntType(T);
1377
1378 // We need to convert ranges to the resulting type, so we can compare values
1379 // and combine them in a meaningful (in terms of the given operation) way.
1380 auto ConvertedCoarseLHS = convert(CoarseLHS, ResultType);
1381 auto ConvertedCoarseRHS = convert(CoarseRHS, ResultType);
1382
1383 // It is hard to reason about ranges when conversion changes
1384 // borders of the ranges.
1385 if (!ConvertedCoarseLHS || !ConvertedCoarseRHS) {
1386 return infer(T);
1387 }
1388
1389 return VisitBinaryOperator<Op>(*ConvertedCoarseLHS, *ConvertedCoarseRHS, T);
1390 }
1391
1392 template <BinaryOperator::Opcode Op>
1393 RangeSet VisitBinaryOperator(Range LHS, Range RHS, QualType T) {
1394 return infer(T);
1395 }
1396
1397 /// Return a symmetrical range for the given range and type.
1398 ///
1399 /// If T is signed, return the smallest range [-x..x] that covers the original
1400 /// range, or [-min(T), max(T)] if the aforementioned symmetric range doesn't
1401 /// exist due to original range covering min(T)).
1402 ///
1403 /// If T is unsigned, return the smallest range [0..x] that covers the
1404 /// original range.
1405 Range getSymmetricalRange(Range Origin, QualType T) {
1406 APSIntType RangeType = ValueFactory.getAPSIntType(T);
1407
1408 if (RangeType.isUnsigned()) {
1409 return Range(ValueFactory.getMinValue(RangeType), Origin.To());
1410 }
1411
1412 if (Origin.From().isMinSignedValue()) {
1413 // If mini is a minimal signed value, absolute value of it is greater
1414 // than the maximal signed value. In order to avoid these
1415 // complications, we simply return the whole range.
1416 return {ValueFactory.getMinValue(RangeType),
1417 ValueFactory.getMaxValue(RangeType)};
1418 }
1419
1420 // At this point, we are sure that the type is signed and we can safely
1421 // use unary - operator.
1422 //
1423 // While calculating absolute maximum, we can use the following formula
1424 // because of these reasons:
1425 // * If From >= 0 then To >= From and To >= -From.
1426 // AbsMax == To == max(To, -From)
1427 // * If To <= 0 then -From >= -To and -From >= From.
1428 // AbsMax == -From == max(-From, To)
1429 // * Otherwise, From <= 0, To >= 0, and
1430 // AbsMax == max(abs(From), abs(To))
1431 llvm::APSInt AbsMax = std::max(-Origin.From(), Origin.To());
1432
1433 // Intersection is guaranteed to be non-empty.
1434 return {ValueFactory.getValue(-AbsMax), ValueFactory.getValue(AbsMax)};
1435 }
1436
1437 /// Return a range set subtracting zero from \p Domain.
1438 RangeSet assumeNonZero(RangeSet Domain, QualType T) {
1439 APSIntType IntType = ValueFactory.getAPSIntType(T);
1440 return RangeFactory.deletePoint(Domain, IntType.getZeroValue());
1441 }
1442
1443 template <typename ProduceNegatedSymFunc>
1444 std::optional<RangeSet> getRangeForNegatedExpr(ProduceNegatedSymFunc F,
1445 QualType T) {
1446 // Do not negate if the type cannot be meaningfully negated.
1449 return std::nullopt;
1450
1451 if (SymbolRef NegatedSym = F())
1452 if (const RangeSet *NegatedRange = getConstraint(State, NegatedSym))
1453 return RangeFactory.negate(*NegatedRange);
1454
1455 return std::nullopt;
1456 }
1457
1458 std::optional<RangeSet> getRangeForNegatedUnarySym(const UnarySymExpr *USE) {
1459 // Just get the operand when we negate a symbol that is already negated.
1460 // -(-a) == a
1461 return getRangeForNegatedExpr(
1462 [USE]() -> SymbolRef {
1463 if (USE->getOpcode() == UO_Minus)
1464 return USE->getOperand();
1465 return nullptr;
1466 },
1467 USE->getType());
1468 }
1469
1470 std::optional<RangeSet> getRangeForNegatedSymSym(const SymSymExpr *SSE) {
1471 return getRangeForNegatedExpr(
1472 [SSE, State = this->State]() -> SymbolRef {
1473 if (SSE->getOpcode() == BO_Sub)
1474 return State->getSymbolManager().getSymSymExpr(
1475 SSE->getRHS(), BO_Sub, SSE->getLHS(), SSE->getType());
1476 return nullptr;
1477 },
1478 SSE->getType());
1479 }
1480
1481 std::optional<RangeSet> getRangeForNegatedSym(SymbolRef Sym) {
1482 return getRangeForNegatedExpr(
1483 [Sym, State = this->State]() {
1484 return State->getSymbolManager().getUnarySymExpr(Sym, UO_Minus,
1485 Sym->getType());
1486 },
1487 Sym->getType());
1488 }
1489
1490 std::optional<RangeSet> getRangeCommutativeSymSym(const SymSymExpr *SSE) {
1491 auto Op = SSE->getOpcode();
1492 bool IsCommutative = llvm::is_contained(
1493 // ==, !=, |, &, +, *, ^
1494 {BO_EQ, BO_NE, BO_Or, BO_And, BO_Add, BO_Mul, BO_Xor}, Op);
1495 if (!IsCommutative)
1496 return std::nullopt;
1497
1498 SymbolRef Commuted = State->getSymbolManager().getSymSymExpr(
1499 SSE->getRHS(), Op, SSE->getLHS(), SSE->getType());
1500 if (const RangeSet *Range = getConstraint(State, Commuted))
1501 return *Range;
1502 return std::nullopt;
1503 }
1504
1505 // Returns ranges only for binary comparison operators (except <=>)
1506 // when left and right operands are symbolic values.
1507 // Finds any other comparisons with the same operands.
1508 // Then do logical calculations and refuse impossible branches.
1509 // E.g. (x < y) and (x > y) at the same time are impossible.
1510 // E.g. (x >= y) and (x != y) at the same time makes (x > y) true only.
1511 // E.g. (x == y) and (y == x) are just reversed but the same.
1512 // It covers all possible combinations (see CmpOpTable description).
1513 // Note that `x` and `y` can also stand for subexpressions,
1514 // not only for actual symbols.
1515 std::optional<RangeSet> getRangeForComparisonSymbol(const SymSymExpr *SSE) {
1516 const BinaryOperatorKind CurrentOP = SSE->getOpcode();
1517
1518 // We currently do not support <=> (C++20).
1519 if (!BinaryOperator::isComparisonOp(CurrentOP) || (CurrentOP == BO_Cmp))
1520 return std::nullopt;
1521
1522 static const OperatorRelationsTable CmpOpTable{};
1523
1524 const SymExpr *LHS = SSE->getLHS();
1525 const SymExpr *RHS = SSE->getRHS();
1526 QualType T = SSE->getType();
1527
1528 SymbolManager &SymMgr = State->getSymbolManager();
1529
1530 // We use this variable to store the last queried operator (`QueriedOP`)
1531 // for which the `getCmpOpState` returned with `Unknown`. If there are two
1532 // different OPs that returned `Unknown` then we have to query the special
1533 // `UnknownX2` column. We assume that `getCmpOpState(CurrentOP, CurrentOP)`
1534 // never returns `Unknown`, so `CurrentOP` is a good initial value.
1535 BinaryOperatorKind LastQueriedOpToUnknown = CurrentOP;
1536
1537 // Loop goes through all of the columns exept the last one ('UnknownX2').
1538 // We treat `UnknownX2` column separately at the end of the loop body.
1539 for (size_t i = 0; i < CmpOpTable.getCmpOpCount(); ++i) {
1540
1541 // Let's find an expression e.g. (x < y).
1543 const SymSymExpr *SymSym = SymMgr.getSymSymExpr(LHS, QueriedOP, RHS, T);
1544 const RangeSet *QueriedRangeSet = getConstraint(State, SymSym);
1545
1546 // If ranges were not previously found,
1547 // try to find a reversed expression (y > x).
1548 if (!QueriedRangeSet) {
1549 const BinaryOperatorKind ROP =
1551 SymSym = SymMgr.getSymSymExpr(RHS, ROP, LHS, T);
1552 QueriedRangeSet = getConstraint(State, SymSym);
1553 }
1554
1555 if (!QueriedRangeSet || QueriedRangeSet->isEmpty())
1556 continue;
1557
1558 const llvm::APSInt *ConcreteValue = QueriedRangeSet->getConcreteValue();
1559 const bool isInFalseBranch =
1560 ConcreteValue ? (*ConcreteValue == 0) : false;
1561
1562 // If it is a false branch, we shall be guided by opposite operator,
1563 // because the table is made assuming we are in the true branch.
1564 // E.g. when (x <= y) is false, then (x > y) is true.
1565 if (isInFalseBranch)
1566 QueriedOP = BinaryOperator::negateComparisonOp(QueriedOP);
1567
1569 CmpOpTable.getCmpOpState(CurrentOP, QueriedOP);
1570
1571 if (BranchState == OperatorRelationsTable::Unknown) {
1572 if (LastQueriedOpToUnknown != CurrentOP &&
1573 LastQueriedOpToUnknown != QueriedOP) {
1574 // If we got the Unknown state for both different operators.
1575 // if (x <= y) // assume true
1576 // if (x != y) // assume true
1577 // if (x < y) // would be also true
1578 // Get a state from `UnknownX2` column.
1579 BranchState = CmpOpTable.getCmpOpStateForUnknownX2(CurrentOP);
1580 } else {
1581 LastQueriedOpToUnknown = QueriedOP;
1582 continue;
1583 }
1584 }
1585
1586 return (BranchState == OperatorRelationsTable::True) ? getTrueRange(T)
1587 : getFalseRange(T);
1588 }
1589
1590 return std::nullopt;
1591 }
1592
1593 std::optional<RangeSet> getRangeForEqualities(const SymSymExpr *Sym) {
1594 std::optional<bool> Equality = meansEquality(Sym);
1595
1596 if (!Equality)
1597 return std::nullopt;
1598
1599 if (std::optional<bool> AreEqual =
1600 EquivalenceClass::areEqual(State, Sym->getLHS(), Sym->getRHS())) {
1601 // Here we cover two cases at once:
1602 // * if Sym is equality and its operands are known to be equal -> true
1603 // * if Sym is disequality and its operands are disequal -> true
1604 if (*AreEqual == *Equality) {
1605 return getTrueRange(Sym->getType());
1606 }
1607 // Opposite combinations result in false.
1608 return getFalseRange(Sym->getType());
1609 }
1610
1611 return std::nullopt;
1612 }
1613
1614 RangeSet getTrueRange(QualType T) {
1615 RangeSet TypeRange = infer(T);
1616 return assumeNonZero(TypeRange, T);
1617 }
1618
1619 RangeSet getFalseRange(QualType T) {
1620 const llvm::APSInt &Zero = ValueFactory.getValue(0, T);
1621 return RangeSet(RangeFactory, Zero);
1622 }
1623
1624 BasicValueFactory &ValueFactory;
1625 RangeSet::Factory &RangeFactory;
1626 ProgramStateRef State;
1627};
1628
1629//===----------------------------------------------------------------------===//
1630// Range-based reasoning about symbolic operations
1631//===----------------------------------------------------------------------===//
1632
1633template <>
1634RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_NE>(RangeSet LHS,
1635 RangeSet RHS,
1636 QualType T) {
1637 assert(!LHS.isEmpty() && !RHS.isEmpty());
1638
1639 if (LHS.getAPSIntType() == RHS.getAPSIntType()) {
1640 if (intersect(RangeFactory, LHS, RHS).isEmpty())
1641 return getTrueRange(T);
1642
1643 } else {
1644 // We can only lose information if we are casting smaller signed type to
1645 // bigger unsigned type. For e.g.,
1646 // LHS (unsigned short): [2, USHRT_MAX]
1647 // RHS (signed short): [SHRT_MIN, 0]
1648 //
1649 // Casting RHS to LHS type will leave us with overlapping values
1650 // CastedRHS : [0, 0] U [SHRT_MAX + 1, USHRT_MAX]
1651 //
1652 // We can avoid this by checking if signed type's maximum value is lesser
1653 // than unsigned type's minimum value.
1654
1655 // If both have different signs then only we can get more information.
1656 if (LHS.isUnsigned() != RHS.isUnsigned()) {
1657 if (LHS.isUnsigned() && (LHS.getBitWidth() >= RHS.getBitWidth())) {
1658 if (RHS.getMaxValue().isNegative() ||
1659 LHS.getAPSIntType().convert(RHS.getMaxValue()) < LHS.getMinValue())
1660 return getTrueRange(T);
1661
1662 } else if (RHS.isUnsigned() && (LHS.getBitWidth() <= RHS.getBitWidth())) {
1663 if (LHS.getMaxValue().isNegative() ||
1664 RHS.getAPSIntType().convert(LHS.getMaxValue()) < RHS.getMinValue())
1665 return getTrueRange(T);
1666 }
1667 }
1668
1669 // Both RangeSets should be casted to bigger unsigned type.
1670 APSIntType CastingType(std::max(LHS.getBitWidth(), RHS.getBitWidth()),
1671 LHS.isUnsigned() || RHS.isUnsigned());
1672
1673 RangeSet CastedLHS = RangeFactory.castTo(LHS, CastingType);
1674 RangeSet CastedRHS = RangeFactory.castTo(RHS, CastingType);
1675
1676 if (intersect(RangeFactory, CastedLHS, CastedRHS).isEmpty())
1677 return getTrueRange(T);
1678 }
1679
1680 // In all other cases, the resulting range cannot be deduced.
1681 return infer(T);
1682}
1683
1684template <>
1685RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Or>(Range LHS, Range RHS,
1686 QualType T) {
1687 APSIntType ResultType = ValueFactory.getAPSIntType(T);
1688 llvm::APSInt Zero = ResultType.getZeroValue();
1689
1690 bool IsLHSPositiveOrZero = LHS.From() >= Zero;
1691 bool IsRHSPositiveOrZero = RHS.From() >= Zero;
1692
1693 bool IsLHSNegative = LHS.To() < Zero;
1694 bool IsRHSNegative = RHS.To() < Zero;
1695
1696 // Check if both ranges have the same sign.
1697 if ((IsLHSPositiveOrZero && IsRHSPositiveOrZero) ||
1698 (IsLHSNegative && IsRHSNegative)) {
1699 // The result is definitely greater or equal than any of the operands.
1700 const llvm::APSInt &Min = std::max(LHS.From(), RHS.From());
1701
1702 // We estimate maximal value for positives as the maximal value for the
1703 // given type. For negatives, we estimate it with -1 (e.g. 0x11111111).
1704 //
1705 // TODO: We basically, limit the resulting range from below, but don't do
1706 // anything with the upper bound.
1707 //
1708 // For positive operands, it can be done as follows: for the upper
1709 // bound of LHS and RHS we calculate the most significant bit set.
1710 // Let's call it the N-th bit. Then we can estimate the maximal
1711 // number to be 2^(N+1)-1, i.e. the number with all the bits up to
1712 // the N-th bit set.
1713 const llvm::APSInt &Max = IsLHSNegative
1714 ? ValueFactory.getValue(--Zero)
1715 : ValueFactory.getMaxValue(ResultType);
1716
1717 return {RangeFactory, ValueFactory.getValue(Min), Max};
1718 }
1719
1720 // Otherwise, let's check if at least one of the operands is negative.
1721 if (IsLHSNegative || IsRHSNegative) {
1722 // This means that the result is definitely negative as well.
1723 return {RangeFactory, ValueFactory.getMinValue(ResultType),
1724 ValueFactory.getValue(--Zero)};
1725 }
1726
1727 RangeSet DefaultRange = infer(T);
1728
1729 // It is pretty hard to reason about operands with different signs
1730 // (and especially with possibly different signs). We simply check if it
1731 // can be zero. In order to conclude that the result could not be zero,
1732 // at least one of the operands should be definitely not zero itself.
1733 if (!LHS.Includes(Zero) || !RHS.Includes(Zero)) {
1734 return assumeNonZero(DefaultRange, T);
1735 }
1736
1737 // Nothing much else to do here.
1738 return DefaultRange;
1739}
1740
1741template <>
1742RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_And>(Range LHS,
1743 Range RHS,
1744 QualType T) {
1745 APSIntType ResultType = ValueFactory.getAPSIntType(T);
1746 llvm::APSInt Zero = ResultType.getZeroValue();
1747
1748 bool IsLHSPositiveOrZero = LHS.From() >= Zero;
1749 bool IsRHSPositiveOrZero = RHS.From() >= Zero;
1750
1751 bool IsLHSNegative = LHS.To() < Zero;
1752 bool IsRHSNegative = RHS.To() < Zero;
1753
1754 // Check if both ranges have the same sign.
1755 if ((IsLHSPositiveOrZero && IsRHSPositiveOrZero) ||
1756 (IsLHSNegative && IsRHSNegative)) {
1757 // The result is definitely less or equal than any of the operands.
1758 const llvm::APSInt &Max = std::min(LHS.To(), RHS.To());
1759
1760 // We conservatively estimate lower bound to be the smallest positive
1761 // or negative value corresponding to the sign of the operands.
1762 const llvm::APSInt &Min = IsLHSNegative
1763 ? ValueFactory.getMinValue(ResultType)
1764 : ValueFactory.getValue(Zero);
1765
1766 return {RangeFactory, Min, Max};
1767 }
1768
1769 // Otherwise, let's check if at least one of the operands is positive.
1770 if (IsLHSPositiveOrZero || IsRHSPositiveOrZero) {
1771 // This makes result definitely positive.
1772 //
1773 // We can also reason about a maximal value by finding the maximal
1774 // value of the positive operand.
1775 const llvm::APSInt &Max = IsLHSPositiveOrZero ? LHS.To() : RHS.To();
1776
1777 // The minimal value on the other hand is much harder to reason about.
1778 // The only thing we know for sure is that the result is positive.
1779 return {RangeFactory, ValueFactory.getValue(Zero),
1780 ValueFactory.getValue(Max)};
1781 }
1782
1783 // Nothing much else to do here.
1784 return infer(T);
1785}
1786
1787template <>
1788RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Rem>(Range LHS,
1789 Range RHS,
1790 QualType T) {
1791 llvm::APSInt Zero = ValueFactory.getAPSIntType(T).getZeroValue();
1792
1793 Range ConservativeRange = getSymmetricalRange(RHS, T);
1794
1795 llvm::APSInt Max = ConservativeRange.To();
1796 llvm::APSInt Min = ConservativeRange.From();
1797
1798 if (Max == Zero) {
1799 // It's an undefined behaviour to divide by 0 and it seems like we know
1800 // for sure that RHS is 0. Let's say that the resulting range is
1801 // simply infeasible for that matter.
1802 return RangeFactory.getEmptySet();
1803 }
1804
1805 // At this point, our conservative range is closed. The result, however,
1806 // couldn't be greater than the RHS' maximal absolute value. Because of
1807 // this reason, we turn the range into open (or half-open in case of
1808 // unsigned integers).
1809 //
1810 // While we operate on integer values, an open interval (a, b) can be easily
1811 // represented by the closed interval [a + 1, b - 1]. And this is exactly
1812 // what we do next.
1813 //
1814 // If we are dealing with unsigned case, we shouldn't move the lower bound.
1815 if (Min.isSigned()) {
1816 ++Min;
1817 }
1818 --Max;
1819
1820 bool IsLHSPositiveOrZero = LHS.From() >= Zero;
1821 bool IsRHSPositiveOrZero = RHS.From() >= Zero;
1822
1823 // Remainder operator results with negative operands is implementation
1824 // defined. Positive cases are much easier to reason about though.
1825 if (IsLHSPositiveOrZero && IsRHSPositiveOrZero) {
1826 // If maximal value of LHS is less than maximal value of RHS,
1827 // the result won't get greater than LHS.To().
1828 Max = std::min(LHS.To(), Max);
1829 // We want to check if it is a situation similar to the following:
1830 //
1831 // <------------|---[ LHS ]--------[ RHS ]----->
1832 // -INF 0 +INF
1833 //
1834 // In this situation, we can conclude that (LHS / RHS) == 0 and
1835 // (LHS % RHS) == LHS.
1836 Min = LHS.To() < RHS.From() ? LHS.From() : Zero;
1837 }
1838
1839 // Nevertheless, the symmetrical range for RHS is a conservative estimate
1840 // for any sign of either LHS, or RHS.
1841 return {RangeFactory, ValueFactory.getValue(Min), ValueFactory.getValue(Max)};
1842}
1843
1844RangeSet SymbolicRangeInferrer::VisitBinaryOperator(RangeSet LHS,
1846 RangeSet RHS, QualType T) {
1847 // We should propagate information about unfeasbility of one of the
1848 // operands to the resulting range.
1849 if (LHS.isEmpty() || RHS.isEmpty()) {
1850 return RangeFactory.getEmptySet();
1851 }
1852
1853 switch (Op) {
1854 case BO_NE:
1855 return VisitBinaryOperator<BO_NE>(LHS, RHS, T);
1856 case BO_Or:
1857 return VisitBinaryOperator<BO_Or>(LHS, RHS, T);
1858 case BO_And:
1859 return VisitBinaryOperator<BO_And>(LHS, RHS, T);
1860 case BO_Rem:
1861 return VisitBinaryOperator<BO_Rem>(LHS, RHS, T);
1862 default:
1863 return infer(T);
1864 }
1865}
1866
1867//===----------------------------------------------------------------------===//
1868// Constraint manager implementation details
1869//===----------------------------------------------------------------------===//
1870
1871class RangeConstraintManager : public RangedConstraintManager {
1872public:
1873 RangeConstraintManager(ExprEngine *EE, SValBuilder &SVB)
1874 : RangedConstraintManager(EE, SVB), F(getBasicVals()) {}
1875
1876 //===------------------------------------------------------------------===//
1877 // Implementation for interface from ConstraintManager.
1878 //===------------------------------------------------------------------===//
1879
1880 bool haveEqualConstraints(ProgramStateRef S1,
1881 ProgramStateRef S2) const override {
1882 // NOTE: ClassMembers are as simple as back pointers for ClassMap,
1883 // so comparing constraint ranges and class maps should be
1884 // sufficient.
1885 return S1->get<ConstraintRange>() == S2->get<ConstraintRange>() &&
1886 S1->get<ClassMap>() == S2->get<ClassMap>();
1887 }
1888
1889 bool canReasonAbout(SVal X) const override;
1890
1891 ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
1892
1893 const llvm::APSInt *getSymVal(ProgramStateRef State,
1894 SymbolRef Sym) const override;
1895
1896 const llvm::APSInt *getSymMinVal(ProgramStateRef State,
1897 SymbolRef Sym) const override;
1898
1899 const llvm::APSInt *getSymMaxVal(ProgramStateRef State,
1900 SymbolRef Sym) const override;
1901
1902 ProgramStateRef removeDeadBindings(ProgramStateRef State,
1903 SymbolReaper &SymReaper) override;
1904
1905 void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n",
1906 unsigned int Space = 0, bool IsDot = false) const override;
1907 void printValue(raw_ostream &Out, ProgramStateRef State,
1908 SymbolRef Sym) override;
1909 void printConstraints(raw_ostream &Out, ProgramStateRef State,
1910 const char *NL = "\n", unsigned int Space = 0,
1911 bool IsDot = false) const;
1912 void printEquivalenceClasses(raw_ostream &Out, ProgramStateRef State,
1913 const char *NL = "\n", unsigned int Space = 0,
1914 bool IsDot = false) const;
1915 void printDisequalities(raw_ostream &Out, ProgramStateRef State,
1916 const char *NL = "\n", unsigned int Space = 0,
1917 bool IsDot = false) const;
1918
1919 //===------------------------------------------------------------------===//
1920 // Implementation for interface from RangedConstraintManager.
1921 //===------------------------------------------------------------------===//
1922
1923 ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym,
1924 const llvm::APSInt &V,
1925 const llvm::APSInt &Adjustment) override;
1926
1927 ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym,
1928 const llvm::APSInt &V,
1929 const llvm::APSInt &Adjustment) override;
1930
1931 ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym,
1932 const llvm::APSInt &V,
1933 const llvm::APSInt &Adjustment) override;
1934
1935 ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym,
1936 const llvm::APSInt &V,
1937 const llvm::APSInt &Adjustment) override;
1938
1939 ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym,
1940 const llvm::APSInt &V,
1941 const llvm::APSInt &Adjustment) override;
1942
1943 ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym,
1944 const llvm::APSInt &V,
1945 const llvm::APSInt &Adjustment) override;
1946
1947 ProgramStateRef assumeSymWithinInclusiveRange(
1948 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
1949 const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
1950
1951 ProgramStateRef assumeSymOutsideInclusiveRange(
1952 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
1953 const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
1954
1955private:
1956 mutable RangeSet::Factory F;
1957
1958 RangeSet getRange(ProgramStateRef State, SymbolRef Sym) const;
1959 ProgramStateRef setRange(ProgramStateRef State, SymbolRef Sym,
1960 RangeSet Range);
1961
1962 RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym,
1963 const llvm::APSInt &Int,
1964 const llvm::APSInt &Adjustment) const;
1965 RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym,
1966 const llvm::APSInt &Int,
1967 const llvm::APSInt &Adjustment) const;
1968 RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym,
1969 const llvm::APSInt &Int,
1970 const llvm::APSInt &Adjustment) const;
1971 RangeSet getSymLERange(llvm::function_ref<RangeSet()> RS,
1972 const llvm::APSInt &Int,
1973 const llvm::APSInt &Adjustment) const;
1974 RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym,
1975 const llvm::APSInt &Int,
1976 const llvm::APSInt &Adjustment) const;
1977};
1978
1979//===----------------------------------------------------------------------===//
1980// Constraint assignment logic
1981//===----------------------------------------------------------------------===//
1982
1983/// ConstraintAssignorBase is a small utility class that unifies visitor
1984/// for ranges with a visitor for constraints (rangeset/range/constant).
1985///
1986/// It is designed to have one derived class, but generally it can have more.
1987/// Derived class can control which types we handle by defining methods of the
1988/// following form:
1989///
1990/// bool handle${SYMBOL}To${CONSTRAINT}(const SYMBOL *Sym,
1991/// CONSTRAINT Constraint);
1992///
1993/// where SYMBOL is the type of the symbol (e.g. SymSymExpr, SymbolCast, etc.)
1994/// CONSTRAINT is the type of constraint (RangeSet/Range/Const)
1995/// return value signifies whether we should try other handle methods
1996/// (i.e. false would mean to stop right after calling this method)
1997template <class Derived> class ConstraintAssignorBase {
1998public:
1999 using Const = const llvm::APSInt &;
2000
2001#define DISPATCH(CLASS) return assign##CLASS##Impl(cast<CLASS>(Sym), Constraint)
2002
2003#define ASSIGN(CLASS, TO, SYM, CONSTRAINT) \
2004 if (!static_cast<Derived *>(this)->assign##CLASS##To##TO(SYM, CONSTRAINT)) \
2005 return false
2006
2007 void assign(SymbolRef Sym, RangeSet Constraint) {
2008 assignImpl(Sym, Constraint);
2009 }
2010
2011 bool assignImpl(SymbolRef Sym, RangeSet Constraint) {
2012 switch (Sym->getKind()) {
2013#define SYMBOL(Id, Parent) \
2014 case SymExpr::Id##Kind: \
2015 DISPATCH(Id);
2016#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
2017 }
2018 llvm_unreachable("Unknown SymExpr kind!");
2019 }
2020
2021#define DEFAULT_ASSIGN(Id) \
2022 bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) { \
2023 return true; \
2024 } \
2025 bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
2026 bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
2027
2028 // When we dispatch for constraint types, we first try to check
2029 // if the new constraint is the constant and try the corresponding
2030 // assignor methods. If it didn't interrupt, we can proceed to the
2031 // range, and finally to the range set.
2032#define CONSTRAINT_DISPATCH(Id) \
2033 if (const llvm::APSInt *Const = Constraint.getConcreteValue()) { \
2034 ASSIGN(Id, Const, Sym, *Const); \
2035 } \
2036 if (Constraint.size() == 1) { \
2037 ASSIGN(Id, Range, Sym, *Constraint.begin()); \
2038 } \
2039 ASSIGN(Id, RangeSet, Sym, Constraint)
2040
2041 // Our internal assign method first tries to call assignor methods for all
2042 // constraint types that apply. And if not interrupted, continues with its
2043 // parent class.
2044#define SYMBOL(Id, Parent) \
2045 bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) { \
2046 CONSTRAINT_DISPATCH(Id); \
2047 DISPATCH(Parent); \
2048 } \
2049 DEFAULT_ASSIGN(Id)
2050#define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent)
2051#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
2052
2053 // Default implementations for the top class that doesn't have parents.
2054 bool assignSymExprImpl(const SymExpr *Sym, RangeSet Constraint) {
2056 return true;
2057 }
2059
2060#undef DISPATCH
2061#undef CONSTRAINT_DISPATCH
2062#undef DEFAULT_ASSIGN
2063#undef ASSIGN
2064};
2065
2066/// A little component aggregating all of the reasoning we have about
2067/// assigning new constraints to symbols.
2068///
2069/// The main purpose of this class is to associate constraints to symbols,
2070/// and impose additional constraints on other symbols, when we can imply
2071/// them.
2072///
2073/// It has a nice symmetry with SymbolicRangeInferrer. When the latter
2074/// can provide more precise ranges by looking into the operands of the
2075/// expression in question, ConstraintAssignor looks into the operands
2076/// to see if we can imply more from the new constraint.
2077class ConstraintAssignor : public ConstraintAssignorBase<ConstraintAssignor> {
2078public:
2079 template <class ClassOrSymbol>
2080 [[nodiscard]] static ProgramStateRef
2081 assign(ProgramStateRef State, SValBuilder &Builder, RangeSet::Factory &F,
2082 ClassOrSymbol CoS, RangeSet NewConstraint) {
2083 if (!State || NewConstraint.isEmpty())
2084 return nullptr;
2085
2086 ConstraintAssignor Assignor{State, Builder, F};
2087 return Assignor.assign(CoS, NewConstraint);
2088 }
2089
2090 /// Handle expressions like: a % b != 0.
2091 template <typename SymT>
2092 bool handleRemainderOp(const SymT *Sym, RangeSet Constraint) {
2093 if (Sym->getOpcode() != BO_Rem)
2094 return true;
2095 // a % b != 0 implies that a != 0.
2096 if (!Constraint.containsZero()) {
2097 SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
2098 if (auto NonLocSymSVal = SymSVal.getAs<nonloc::SymbolVal>()) {
2099 State = State->assume(*NonLocSymSVal, true);
2100 if (!State)
2101 return false;
2102 }
2103 }
2104 return true;
2105 }
2106
2107 inline bool assignSymExprToConst(const SymExpr *Sym, Const Constraint);
2108 inline bool assignSymIntExprToRangeSet(const SymIntExpr *Sym,
2109 RangeSet Constraint) {
2110 return handleRemainderOp(Sym, Constraint);
2111 }
2112 inline bool assignSymSymExprToRangeSet(const SymSymExpr *Sym,
2113 RangeSet Constraint);
2114
2115private:
2116 ConstraintAssignor(ProgramStateRef State, SValBuilder &Builder,
2118 : State(State), Builder(Builder), RangeFactory(F) {}
2119 using Base = ConstraintAssignorBase<ConstraintAssignor>;
2120
2121 /// Base method for handling new constraints for symbols.
2122 [[nodiscard]] ProgramStateRef assign(SymbolRef Sym, RangeSet NewConstraint) {
2123 // All constraints are actually associated with equivalence classes, and
2124 // that's what we are going to do first.
2125 State = assign(EquivalenceClass::find(State, Sym), NewConstraint);
2126 if (!State)
2127 return nullptr;
2128
2129 // And after that we can check what other things we can get from this
2130 // constraint.
2131 Base::assign(Sym, NewConstraint);
2132 return State;
2133 }
2134
2135 /// Base method for handling new constraints for classes.
2136 [[nodiscard]] ProgramStateRef assign(EquivalenceClass Class,
2137 RangeSet NewConstraint) {
2138 // There is a chance that we might need to update constraints for the
2139 // classes that are known to be disequal to Class.
2140 //
2141 // In order for this to be even possible, the new constraint should
2142 // be simply a constant because we can't reason about range disequalities.
2143 if (const llvm::APSInt *Point = NewConstraint.getConcreteValue()) {
2144
2145 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2146 ConstraintRangeTy::Factory &CF = State->get_context<ConstraintRange>();
2147
2148 // Add new constraint.
2149 Constraints = CF.add(Constraints, Class, NewConstraint);
2150
2151 for (EquivalenceClass DisequalClass : Class.getDisequalClasses(State)) {
2152 RangeSet UpdatedConstraint = SymbolicRangeInferrer::inferRange(
2153 RangeFactory, State, DisequalClass);
2154
2155 UpdatedConstraint = RangeFactory.deletePoint(UpdatedConstraint, *Point);
2156
2157 // If we end up with at least one of the disequal classes to be
2158 // constrained with an empty range-set, the state is infeasible.
2159 if (UpdatedConstraint.isEmpty())
2160 return nullptr;
2161
2162 Constraints = CF.add(Constraints, DisequalClass, UpdatedConstraint);
2163 }
2164 assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
2165 "a state with infeasible constraints");
2166
2167 return setConstraints(State, Constraints);
2168 }
2169
2170 return setConstraint(State, Class, NewConstraint);
2171 }
2172
2173 ProgramStateRef trackDisequality(ProgramStateRef State, SymbolRef LHS,
2174 SymbolRef RHS) {
2175 return EquivalenceClass::markDisequal(RangeFactory, State, LHS, RHS);
2176 }
2177
2178 ProgramStateRef trackEquality(ProgramStateRef State, SymbolRef LHS,
2179 SymbolRef RHS) {
2180 return EquivalenceClass::merge(RangeFactory, State, LHS, RHS);
2181 }
2182
2183 [[nodiscard]] std::optional<bool> interpreteAsBool(RangeSet Constraint) {
2184 assert(!Constraint.isEmpty() && "Empty ranges shouldn't get here");
2185
2186 if (Constraint.getConcreteValue())
2187 return !Constraint.getConcreteValue()->isZero();
2188
2189 if (!Constraint.containsZero())
2190 return true;
2191
2192 return std::nullopt;
2193 }
2194
2195 ProgramStateRef State;
2196 SValBuilder &Builder;
2197 RangeSet::Factory &RangeFactory;
2198};
2199
2200bool ConstraintAssignor::assignSymExprToConst(const SymExpr *Sym,
2201 const llvm::APSInt &Constraint) {
2202 llvm::SmallSet<EquivalenceClass, 4> SimplifiedClasses;
2203 // Iterate over all equivalence classes and try to simplify them.
2204 ClassMembersTy Members = State->get<ClassMembers>();
2205 for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members) {
2206 EquivalenceClass Class = ClassToSymbolSet.first;
2207 State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2208 if (!State)
2209 return false;
2210 SimplifiedClasses.insert(Class);
2211 }
2212
2213 // Trivial equivalence classes (those that have only one symbol member) are
2214 // not stored in the State. Thus, we must skim through the constraints as
2215 // well. And we try to simplify symbols in the constraints.
2216 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2217 for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2218 EquivalenceClass Class = ClassConstraint.first;
2219 if (SimplifiedClasses.count(Class)) // Already simplified.
2220 continue;
2221 State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2222 if (!State)
2223 return false;
2224 }
2225
2226 // We may have trivial equivalence classes in the disequality info as
2227 // well, and we need to simplify them.
2228 DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2229 for (std::pair<EquivalenceClass, ClassSet> DisequalityEntry :
2230 DisequalityInfo) {
2231 EquivalenceClass Class = DisequalityEntry.first;
2232 ClassSet DisequalClasses = DisequalityEntry.second;
2233 State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2234 if (!State)
2235 return false;
2236 }
2237
2238 return true;
2239}
2240
2241bool ConstraintAssignor::assignSymSymExprToRangeSet(const SymSymExpr *Sym,
2242 RangeSet Constraint) {
2243 if (!handleRemainderOp(Sym, Constraint))
2244 return false;
2245
2246 std::optional<bool> ConstraintAsBool = interpreteAsBool(Constraint);
2247
2248 if (!ConstraintAsBool)
2249 return true;
2250
2251 if (std::optional<bool> Equality = meansEquality(Sym)) {
2252 // Here we cover two cases:
2253 // * if Sym is equality and the new constraint is true -> Sym's operands
2254 // should be marked as equal
2255 // * if Sym is disequality and the new constraint is false -> Sym's
2256 // operands should be also marked as equal
2257 if (*Equality == *ConstraintAsBool) {
2258 State = trackEquality(State, Sym->getLHS(), Sym->getRHS());
2259 } else {
2260 // Other combinations leave as with disequal operands.
2261 State = trackDisequality(State, Sym->getLHS(), Sym->getRHS());
2262 }
2263
2264 if (!State)
2265 return false;
2266 }
2267
2268 return true;
2269}
2270
2271} // end anonymous namespace
2272
2273std::unique_ptr<ConstraintManager>
2275 ExprEngine *Eng) {
2276 return std::make_unique<RangeConstraintManager>(Eng, StMgr.getSValBuilder());
2277}
2278
2280 ConstraintMap::Factory &F = State->get_context<ConstraintMap>();
2281 ConstraintMap Result = F.getEmptyMap();
2282
2283 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2284 for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2285 EquivalenceClass Class = ClassConstraint.first;
2286 SymbolSet ClassMembers = Class.getClassMembers(State);
2287 assert(!ClassMembers.isEmpty() &&
2288 "Class must always have at least one member!");
2289
2290 SymbolRef Representative = *ClassMembers.begin();
2291 Result = F.add(Result, Representative, ClassConstraint.second);
2292 }
2293
2294 return Result;
2295}
2296
2297//===----------------------------------------------------------------------===//
2298// EqualityClass implementation details
2299//===----------------------------------------------------------------------===//
2300
2301LLVM_DUMP_METHOD void EquivalenceClass::dumpToStream(ProgramStateRef State,
2302 raw_ostream &os) const {
2303 SymbolSet ClassMembers = getClassMembers(State);
2304 for (const SymbolRef &MemberSym : ClassMembers) {
2305 MemberSym->dump();
2306 os << "\n";
2307 }
2308}
2309
2310inline EquivalenceClass EquivalenceClass::find(ProgramStateRef State,
2311 SymbolRef Sym) {
2312 assert(State && "State should not be null");
2313 assert(Sym && "Symbol should not be null");
2314 // We store far from all Symbol -> Class mappings
2315 if (const EquivalenceClass *NontrivialClass = State->get<ClassMap>(Sym))
2316 return *NontrivialClass;
2317
2318 // This is a trivial class of Sym.
2319 return Sym;
2320}
2321
2322inline ProgramStateRef EquivalenceClass::merge(RangeSet::Factory &F,
2323 ProgramStateRef State,
2325 SymbolRef Second) {
2326 EquivalenceClass FirstClass = find(State, First);
2327 EquivalenceClass SecondClass = find(State, Second);
2328
2329 return FirstClass.merge(F, State, SecondClass);
2330}
2331
2332inline ProgramStateRef EquivalenceClass::merge(RangeSet::Factory &F,
2333 ProgramStateRef State,
2334 EquivalenceClass Other) {
2335 // It is already the same class.
2336 if (*this == Other)
2337 return State;
2338
2339 // FIXME: As of now, we support only equivalence classes of the same type.
2340 // This limitation is connected to the lack of explicit casts in
2341 // our symbolic expression model.
2342 //
2343 // That means that for `int x` and `char y` we don't distinguish
2344 // between these two very different cases:
2345 // * `x == y`
2346 // * `(char)x == y`
2347 //
2348 // The moment we introduce symbolic casts, this restriction can be
2349 // lifted.
2350 if (getType()->getCanonicalTypeUnqualified() !=
2351 Other.getType()->getCanonicalTypeUnqualified())
2352 return State;
2353
2354 SymbolSet Members = getClassMembers(State);
2355 SymbolSet OtherMembers = Other.getClassMembers(State);
2356
2357 // We estimate the size of the class by the height of tree containing
2358 // its members. Merging is not a trivial operation, so it's easier to
2359 // merge the smaller class into the bigger one.
2360 if (Members.getHeight() >= OtherMembers.getHeight()) {
2361 return mergeImpl(F, State, Members, Other, OtherMembers);
2362 } else {
2363 return Other.mergeImpl(F, State, OtherMembers, *this, Members);
2364 }
2365}
2366
2367inline ProgramStateRef
2368EquivalenceClass::mergeImpl(RangeSet::Factory &RangeFactory,
2369 ProgramStateRef State, SymbolSet MyMembers,
2370 EquivalenceClass Other, SymbolSet OtherMembers) {
2371 // Essentially what we try to recreate here is some kind of union-find
2372 // data structure. It does have certain limitations due to persistence
2373 // and the need to remove elements from classes.
2374 //
2375 // In this setting, EquialityClass object is the representative of the class
2376 // or the parent element. ClassMap is a mapping of class members to their
2377 // parent. Unlike the union-find structure, they all point directly to the
2378 // class representative because we don't have an opportunity to actually do
2379 // path compression when dealing with immutability. This means that we
2380 // compress paths every time we do merges. It also means that we lose
2381 // the main amortized complexity benefit from the original data structure.
2382 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2383 ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2384
2385 // 1. If the merged classes have any constraints associated with them, we
2386 // need to transfer them to the class we have left.
2387 //
2388 // Intersection here makes perfect sense because both of these constraints
2389 // must hold for the whole new class.
2390 if (std::optional<RangeSet> NewClassConstraint =
2391 intersect(RangeFactory, getConstraint(State, *this),
2392 getConstraint(State, Other))) {
2393 // NOTE: Essentially, NewClassConstraint should NEVER be infeasible because
2394 // range inferrer shouldn't generate ranges incompatible with
2395 // equivalence classes. However, at the moment, due to imperfections
2396 // in the solver, it is possible and the merge function can also
2397 // return infeasible states aka null states.
2398 if (NewClassConstraint->isEmpty())
2399 // Infeasible state
2400 return nullptr;
2401
2402 // No need in tracking constraints of a now-dissolved class.
2403 Constraints = CRF.remove(Constraints, Other);
2404 // Assign new constraints for this class.
2405 Constraints = CRF.add(Constraints, *this, *NewClassConstraint);
2406
2407 assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
2408 "a state with infeasible constraints");
2409
2410 State = State->set<ConstraintRange>(Constraints);
2411 }
2412
2413 // 2. Get ALL equivalence-related maps
2414 ClassMapTy Classes = State->get<ClassMap>();
2415 ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2416
2417 ClassMembersTy Members = State->get<ClassMembers>();
2418 ClassMembersTy::Factory &MF = State->get_context<ClassMembers>();
2419
2420 DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2421 DisequalityMapTy::Factory &DF = State->get_context<DisequalityMap>();
2422
2423 ClassSet::Factory &CF = State->get_context<ClassSet>();
2424 SymbolSet::Factory &F = getMembersFactory(State);
2425
2426 // 2. Merge members of the Other class into the current class.
2427 SymbolSet NewClassMembers = MyMembers;
2428 for (SymbolRef Sym : OtherMembers) {
2429 NewClassMembers = F.add(NewClassMembers, Sym);
2430 // *this is now the class for all these new symbols.
2431 Classes = CMF.add(Classes, Sym, *this);
2432 }
2433
2434 // 3. Adjust member mapping.
2435 //
2436 // No need in tracking members of a now-dissolved class.
2437 Members = MF.remove(Members, Other);
2438 // Now only the current class is mapped to all the symbols.
2439 Members = MF.add(Members, *this, NewClassMembers);
2440
2441 // 4. Update disequality relations
2442 ClassSet DisequalToOther = Other.getDisequalClasses(DisequalityInfo, CF);
2443 // We are about to merge two classes but they are already known to be
2444 // non-equal. This is a contradiction.
2445 if (DisequalToOther.contains(*this))
2446 return nullptr;
2447
2448 if (!DisequalToOther.isEmpty()) {
2449 ClassSet DisequalToThis = getDisequalClasses(DisequalityInfo, CF);
2450 DisequalityInfo = DF.remove(DisequalityInfo, Other);
2451
2452 for (EquivalenceClass DisequalClass : DisequalToOther) {
2453 DisequalToThis = CF.add(DisequalToThis, DisequalClass);
2454
2455 // Disequality is a symmetric relation meaning that if
2456 // DisequalToOther not null then the set for DisequalClass is not
2457 // empty and has at least Other.
2458 ClassSet OriginalSetLinkedToOther =
2459 *DisequalityInfo.lookup(DisequalClass);
2460
2461 // Other will be eliminated and we should replace it with the bigger
2462 // united class.
2463 ClassSet NewSet = CF.remove(OriginalSetLinkedToOther, Other);
2464 NewSet = CF.add(NewSet, *this);
2465
2466 DisequalityInfo = DF.add(DisequalityInfo, DisequalClass, NewSet);
2467 }
2468
2469 DisequalityInfo = DF.add(DisequalityInfo, *this, DisequalToThis);
2470 State = State->set<DisequalityMap>(DisequalityInfo);
2471 }
2472
2473 // 5. Update the state
2474 State = State->set<ClassMap>(Classes);
2475 State = State->set<ClassMembers>(Members);
2476
2477 return State;
2478}
2479
2480inline SymbolSet::Factory &
2481EquivalenceClass::getMembersFactory(ProgramStateRef State) {
2482 return State->get_context<SymbolSet>();
2483}
2484
2485SymbolSet EquivalenceClass::getClassMembers(ProgramStateRef State) const {
2486 if (const SymbolSet *Members = State->get<ClassMembers>(*this))
2487 return *Members;
2488
2489 // This class is trivial, so we need to construct a set
2490 // with just that one symbol from the class.
2491 SymbolSet::Factory &F = getMembersFactory(State);
2492 return F.add(F.getEmptySet(), getRepresentativeSymbol());
2493}
2494
2495bool EquivalenceClass::isTrivial(ProgramStateRef State) const {
2496 return State->get<ClassMembers>(*this) == nullptr;
2497}
2498
2499bool EquivalenceClass::isTriviallyDead(ProgramStateRef State,
2500 SymbolReaper &Reaper) const {
2501 return isTrivial(State) && Reaper.isDead(getRepresentativeSymbol());
2502}
2503
2504inline ProgramStateRef EquivalenceClass::markDisequal(RangeSet::Factory &RF,
2505 ProgramStateRef State,
2507 SymbolRef Second) {
2508 return markDisequal(RF, State, find(State, First), find(State, Second));
2509}
2510
2511inline ProgramStateRef EquivalenceClass::markDisequal(RangeSet::Factory &RF,
2512 ProgramStateRef State,
2513 EquivalenceClass First,
2514 EquivalenceClass Second) {
2515 return First.markDisequal(RF, State, Second);
2516}
2517
2518inline ProgramStateRef
2519EquivalenceClass::markDisequal(RangeSet::Factory &RF, ProgramStateRef State,
2520 EquivalenceClass Other) const {
2521 // If we know that two classes are equal, we can only produce an infeasible
2522 // state.
2523 if (*this == Other) {
2524 return nullptr;
2525 }
2526
2527 DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2528 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2529
2530 // Disequality is a symmetric relation, so if we mark A as disequal to B,
2531 // we should also mark B as disequalt to A.
2532 if (!addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, *this,
2533 Other) ||
2534 !addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, Other,
2535 *this))
2536 return nullptr;
2537
2538 assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
2539 "a state with infeasible constraints");
2540
2541 State = State->set<DisequalityMap>(DisequalityInfo);
2542 State = State->set<ConstraintRange>(Constraints);
2543
2544 return State;
2545}
2546
2547inline bool EquivalenceClass::addToDisequalityInfo(
2548 DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
2549 RangeSet::Factory &RF, ProgramStateRef State, EquivalenceClass First,
2550 EquivalenceClass Second) {
2551
2552 // 1. Get all of the required factories.
2553 DisequalityMapTy::Factory &F = State->get_context<DisequalityMap>();
2554 ClassSet::Factory &CF = State->get_context<ClassSet>();
2555 ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2556
2557 // 2. Add Second to the set of classes disequal to First.
2558 const ClassSet *CurrentSet = Info.lookup(First);
2559 ClassSet NewSet = CurrentSet ? *CurrentSet : CF.getEmptySet();
2560 NewSet = CF.add(NewSet, Second);
2561
2562 Info = F.add(Info, First, NewSet);
2563
2564 // 3. If Second is known to be a constant, we can delete this point
2565 // from the constraint asociated with First.
2566 //
2567 // So, if Second == 10, it means that First != 10.
2568 // At the same time, the same logic does not apply to ranges.
2569 if (const RangeSet *SecondConstraint = Constraints.lookup(Second))
2570 if (const llvm::APSInt *Point = SecondConstraint->getConcreteValue()) {
2571
2572 RangeSet FirstConstraint = SymbolicRangeInferrer::inferRange(
2573 RF, State, First.getRepresentativeSymbol());
2574
2575 FirstConstraint = RF.deletePoint(FirstConstraint, *Point);
2576
2577 // If the First class is about to be constrained with an empty
2578 // range-set, the state is infeasible.
2579 if (FirstConstraint.isEmpty())
2580 return false;
2581
2582 Constraints = CRF.add(Constraints, First, FirstConstraint);
2583 }
2584
2585 return true;
2586}
2587
2588inline std::optional<bool> EquivalenceClass::areEqual(ProgramStateRef State,
2589 SymbolRef FirstSym,
2590 SymbolRef SecondSym) {
2591 return EquivalenceClass::areEqual(State, find(State, FirstSym),
2592 find(State, SecondSym));
2593}
2594
2595inline std::optional<bool> EquivalenceClass::areEqual(ProgramStateRef State,
2596 EquivalenceClass First,
2597 EquivalenceClass Second) {
2598 // The same equivalence class => symbols are equal.
2599 if (First == Second)
2600 return true;
2601
2602 // Let's check if we know anything about these two classes being not equal to
2603 // each other.
2604 ClassSet DisequalToFirst = First.getDisequalClasses(State);
2605 if (DisequalToFirst.contains(Second))
2606 return false;
2607
2608 // It is not clear.
2609 return std::nullopt;
2610}
2611
2612[[nodiscard]] ProgramStateRef
2613EquivalenceClass::removeMember(ProgramStateRef State, const SymbolRef Old) {
2614
2615 SymbolSet ClsMembers = getClassMembers(State);
2616 assert(ClsMembers.contains(Old));
2617
2618 // Remove `Old`'s Class->Sym relation.
2619 SymbolSet::Factory &F = getMembersFactory(State);
2620 ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2621 ClsMembers = F.remove(ClsMembers, Old);
2622 // Ensure another precondition of the removeMember function (we can check
2623 // this only with isEmpty, thus we have to do the remove first).
2624 assert(!ClsMembers.isEmpty() &&
2625 "Class should have had at least two members before member removal");
2626 // Overwrite the existing members assigned to this class.
2627 ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2628 ClassMembersMap = EMFactory.add(ClassMembersMap, *this, ClsMembers);
2629 State = State->set<ClassMembers>(ClassMembersMap);
2630
2631 // Remove `Old`'s Sym->Class relation.
2632 ClassMapTy Classes = State->get<ClassMap>();
2633 ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2634 Classes = CMF.remove(Classes, Old);
2635 State = State->set<ClassMap>(Classes);
2636
2637 return State;
2638}
2639
2640// Re-evaluate an SVal with top-level `State->assume` logic.
2641[[nodiscard]] static ProgramStateRef
2642reAssume(ProgramStateRef State, const RangeSet *Constraint, SVal TheValue) {
2643 if (!Constraint)
2644 return State;
2645
2646 const auto DefinedVal = TheValue.castAs<DefinedSVal>();
2647
2648 // If the SVal is 0, we can simply interpret that as `false`.
2649 if (Constraint->encodesFalseRange())
2650 return State->assume(DefinedVal, false);
2651
2652 // If the constraint does not encode 0 then we can interpret that as `true`
2653 // AND as a Range(Set).
2654 if (Constraint->encodesTrueRange()) {
2655 State = State->assume(DefinedVal, true);
2656 if (!State)
2657 return nullptr;
2658 // Fall through, re-assume based on the range values as well.
2659 }
2660 // Overestimate the individual Ranges with the RangeSet' lowest and
2661 // highest values.
2662 return State->assumeInclusiveRange(DefinedVal, Constraint->getMinValue(),
2663 Constraint->getMaxValue(), true);
2664}
2665
2666// Iterate over all symbols and try to simplify them. Once a symbol is
2667// simplified then we check if we can merge the simplified symbol's equivalence
2668// class to this class. This way, we simplify not just the symbols but the
2669// classes as well: we strive to keep the number of the classes to be the
2670// absolute minimum.
2671[[nodiscard]] ProgramStateRef
2672EquivalenceClass::simplify(SValBuilder &SVB, RangeSet::Factory &F,
2673 ProgramStateRef State, EquivalenceClass Class) {
2674 SymbolSet ClassMembers = Class.getClassMembers(State);
2675 for (const SymbolRef &MemberSym : ClassMembers) {
2676
2677 const SVal SimplifiedMemberVal = simplifyToSVal(State, MemberSym);
2678 const SymbolRef SimplifiedMemberSym = SimplifiedMemberVal.getAsSymbol();
2679
2680 // The symbol is collapsed to a constant, check if the current State is
2681 // still feasible.
2682 if (const auto CI = SimplifiedMemberVal.getAs<nonloc::ConcreteInt>()) {
2683 const llvm::APSInt &SV = CI->getValue();
2684 const RangeSet *ClassConstraint = getConstraint(State, Class);
2685 // We have found a contradiction.
2686 if (ClassConstraint && !ClassConstraint->contains(SV))
2687 return nullptr;
2688 }
2689
2690 if (SimplifiedMemberSym && MemberSym != SimplifiedMemberSym) {
2691 // The simplified symbol should be the member of the original Class,
2692 // however, it might be in another existing class at the moment. We
2693 // have to merge these classes.
2694 ProgramStateRef OldState = State;
2695 State = merge(F, State, MemberSym, SimplifiedMemberSym);
2696 if (!State)
2697 return nullptr;
2698 // No state change, no merge happened actually.
2699 if (OldState == State)
2700 continue;
2701
2702 // Be aware that `SimplifiedMemberSym` might refer to an already dead
2703 // symbol. In that case, the eqclass of that might not be the same as the
2704 // eqclass of `MemberSym`. This is because the dead symbols are not
2705 // preserved in the `ClassMap`, hence
2706 // `find(State, SimplifiedMemberSym)` will result in a trivial eqclass
2707 // compared to the eqclass of `MemberSym`.
2708 // These eqclasses should be the same if `SimplifiedMemberSym` is alive.
2709 // --> assert(find(State, MemberSym) == find(State, SimplifiedMemberSym))
2710 //
2711 // Note that `MemberSym` must be alive here since that is from the
2712 // `ClassMembers` where all the symbols are alive.
2713
2714 // Remove the old and more complex symbol.
2715 State = find(State, MemberSym).removeMember(State, MemberSym);
2716
2717 // Query the class constraint again b/c that may have changed during the
2718 // merge above.
2719 const RangeSet *ClassConstraint = getConstraint(State, Class);
2720
2721 // Re-evaluate an SVal with top-level `State->assume`, this ignites
2722 // a RECURSIVE algorithm that will reach a FIXPOINT.
2723 //
2724 // About performance and complexity: Let us assume that in a State we
2725 // have N non-trivial equivalence classes and that all constraints and
2726 // disequality info is related to non-trivial classes. In the worst case,
2727 // we can simplify only one symbol of one class in each iteration. The
2728 // number of symbols in one class cannot grow b/c we replace the old
2729 // symbol with the simplified one. Also, the number of the equivalence
2730 // classes can decrease only, b/c the algorithm does a merge operation
2731 // optionally. We need N iterations in this case to reach the fixpoint.
2732 // Thus, the steps needed to be done in the worst case is proportional to
2733 // N*N.
2734 //
2735 // This worst case scenario can be extended to that case when we have
2736 // trivial classes in the constraints and in the disequality map. This
2737 // case can be reduced to the case with a State where there are only
2738 // non-trivial classes. This is because a merge operation on two trivial
2739 // classes results in one non-trivial class.
2740 State = reAssume(State, ClassConstraint, SimplifiedMemberVal);
2741 if (!State)
2742 return nullptr;
2743 }
2744 }
2745 return State;
2746}
2747
2748inline ClassSet EquivalenceClass::getDisequalClasses(ProgramStateRef State,
2749 SymbolRef Sym) {
2750 return find(State, Sym).getDisequalClasses(State);
2751}
2752
2753inline ClassSet
2754EquivalenceClass::getDisequalClasses(ProgramStateRef State) const {
2755 return getDisequalClasses(State->get<DisequalityMap>(),
2756 State->get_context<ClassSet>());
2757}
2758
2759inline ClassSet
2760EquivalenceClass::getDisequalClasses(DisequalityMapTy Map,
2761 ClassSet::Factory &Factory) const {
2762 if (const ClassSet *DisequalClasses = Map.lookup(*this))
2763 return *DisequalClasses;
2764
2765 return Factory.getEmptySet();
2766}
2767
2768bool EquivalenceClass::isClassDataConsistent(ProgramStateRef State) {
2769 ClassMembersTy Members = State->get<ClassMembers>();
2770
2771 for (std::pair<EquivalenceClass, SymbolSet> ClassMembersPair : Members) {
2772 for (SymbolRef Member : ClassMembersPair.second) {
2773 // Every member of the class should have a mapping back to the class.
2774 if (find(State, Member) == ClassMembersPair.first) {
2775 continue;
2776 }
2777
2778 return false;
2779 }
2780 }
2781
2782 DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2783 for (std::pair<EquivalenceClass, ClassSet> DisequalityInfo : Disequalities) {
2784 EquivalenceClass Class = DisequalityInfo.first;
2785 ClassSet DisequalClasses = DisequalityInfo.second;
2786
2787 // There is no use in keeping empty sets in the map.
2788 if (DisequalClasses.isEmpty())
2789 return false;
2790
2791 // Disequality is symmetrical, i.e. for every Class A and B that A != B,
2792 // B != A should also be true.
2793 for (EquivalenceClass DisequalClass : DisequalClasses) {
2794 const ClassSet *DisequalToDisequalClasses =
2795 Disequalities.lookup(DisequalClass);
2796
2797 // It should be a set of at least one element: Class
2798 if (!DisequalToDisequalClasses ||
2799 !DisequalToDisequalClasses->contains(Class))
2800 return false;
2801 }
2802 }
2803
2804 return true;
2805}
2806
2807//===----------------------------------------------------------------------===//
2808// RangeConstraintManager implementation
2809//===----------------------------------------------------------------------===//
2810
2811bool RangeConstraintManager::canReasonAbout(SVal X) const {
2812 std::optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
2813 if (SymVal && SymVal->isExpression()) {
2814 const SymExpr *SE = SymVal->getSymbol();
2815
2816 if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
2817 switch (SIE->getOpcode()) {
2818 // We don't reason yet about bitwise-constraints on symbolic values.
2819 case BO_And:
2820 case BO_Or:
2821 case BO_Xor:
2822 return false;
2823 // We don't reason yet about these arithmetic constraints on
2824 // symbolic values.
2825 case BO_Mul:
2826 case BO_Div:
2827 case BO_Rem:
2828 case BO_Shl:
2829 case BO_Shr:
2830 return false;
2831 // All other cases.
2832 default:
2833 return true;
2834 }
2835 }
2836
2837 if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
2838 // FIXME: Handle <=> here.
2841 // We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc.
2842 // We've recently started producing Loc <> NonLoc comparisons (that
2843 // result from casts of one of the operands between eg. intptr_t and
2844 // void *), but we can't reason about them yet.
2845 if (Loc::isLocType(SSE->getLHS()->getType())) {
2846 return Loc::isLocType(SSE->getRHS()->getType());
2847 }
2848 }
2849 }
2850
2851 return false;
2852 }
2853
2854 return true;
2855}
2856
2857ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
2858 SymbolRef Sym) {
2859 const RangeSet *Ranges = getConstraint(State, Sym);
2860
2861 // If we don't have any information about this symbol, it's underconstrained.
2862 if (!Ranges)
2863 return ConditionTruthVal();
2864
2865 // If we have a concrete value, see if it's zero.
2866 if (const llvm::APSInt *Value = Ranges->getConcreteValue())
2867 return *Value == 0;
2868
2869 BasicValueFactory &BV = getBasicVals();
2870 APSIntType IntType = BV.getAPSIntType(Sym->getType());
2871 llvm::APSInt Zero = IntType.getZeroValue();
2872
2873 // Check if zero is in the set of possible values.
2874 if (!Ranges->contains(Zero))
2875 return false;
2876
2877 // Zero is a possible value, but it is not the /only/ possible value.
2878 return ConditionTruthVal();
2879}
2880
2881const llvm::APSInt *RangeConstraintManager::getSymVal(ProgramStateRef St,
2882 SymbolRef Sym) const {
2883 return getRange(St, Sym).getConcreteValue();
2884}
2885
2886const llvm::APSInt *RangeConstraintManager::getSymMinVal(ProgramStateRef St,
2887 SymbolRef Sym) const {
2888 RangeSet Range = getRange(St, Sym);
2889 return Range.isEmpty() ? nullptr : &Range.getMinValue();
2890}
2891
2892const llvm::APSInt *RangeConstraintManager::getSymMaxVal(ProgramStateRef St,
2893 SymbolRef Sym) const {
2894 RangeSet Range = getRange(St, Sym);
2895 return Range.isEmpty() ? nullptr : &Range.getMaxValue();
2896}
2897
2898//===----------------------------------------------------------------------===//
2899// Remove dead symbols from existing constraints
2900//===----------------------------------------------------------------------===//
2901
2902/// Scan all symbols referenced by the constraints. If the symbol is not alive
2903/// as marked in LSymbols, mark it as dead in DSymbols.
2905RangeConstraintManager::removeDeadBindings(ProgramStateRef State,
2906 SymbolReaper &SymReaper) {
2907 ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2908 ClassMembersTy NewClassMembersMap = ClassMembersMap;
2909 ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2910 SymbolSet::Factory &SetFactory = State->get_context<SymbolSet>();
2911
2912 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2913 ConstraintRangeTy NewConstraints = Constraints;
2914 ConstraintRangeTy::Factory &ConstraintFactory =
2915 State->get_context<ConstraintRange>();
2916
2917 ClassMapTy Map = State->get<ClassMap>();
2918 ClassMapTy NewMap = Map;
2919 ClassMapTy::Factory &ClassFactory = State->get_context<ClassMap>();
2920
2921 DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2922 DisequalityMapTy::Factory &DisequalityFactory =
2923 State->get_context<DisequalityMap>();
2924 ClassSet::Factory &ClassSetFactory = State->get_context<ClassSet>();
2925
2926 bool ClassMapChanged = false;
2927 bool MembersMapChanged = false;
2928 bool ConstraintMapChanged = false;
2929 bool DisequalitiesChanged = false;
2930
2931 auto removeDeadClass = [&](EquivalenceClass Class) {
2932 // Remove associated constraint ranges.
2933 Constraints = ConstraintFactory.remove(Constraints, Class);
2934 ConstraintMapChanged = true;
2935
2936 // Update disequality information to not hold any information on the
2937 // removed class.
2938 ClassSet DisequalClasses =
2939 Class.getDisequalClasses(Disequalities, ClassSetFactory);
2940 if (!DisequalClasses.isEmpty()) {
2941 for (EquivalenceClass DisequalClass : DisequalClasses) {
2942 ClassSet DisequalToDisequalSet =
2943 DisequalClass.getDisequalClasses(Disequalities, ClassSetFactory);
2944 // DisequalToDisequalSet is guaranteed to be non-empty for consistent
2945 // disequality info.
2946 assert(!DisequalToDisequalSet.isEmpty());
2947 ClassSet NewSet = ClassSetFactory.remove(DisequalToDisequalSet, Class);
2948
2949 // No need in keeping an empty set.
2950 if (NewSet.isEmpty()) {
2951 Disequalities =
2952 DisequalityFactory.remove(Disequalities, DisequalClass);
2953 } else {
2954 Disequalities =
2955 DisequalityFactory.add(Disequalities, DisequalClass, NewSet);
2956 }
2957 }
2958 // Remove the data for the class
2959 Disequalities = DisequalityFactory.remove(Disequalities, Class);
2960 DisequalitiesChanged = true;
2961 }
2962 };
2963
2964 // 1. Let's see if dead symbols are trivial and have associated constraints.
2965 for (std::pair<EquivalenceClass, RangeSet> ClassConstraintPair :
2966 Constraints) {
2967 EquivalenceClass Class = ClassConstraintPair.first;
2968 if (Class.isTriviallyDead(State, SymReaper)) {
2969 // If this class is trivial, we can remove its constraints right away.
2970 removeDeadClass(Class);
2971 }
2972 }
2973
2974 // 2. We don't need to track classes for dead symbols.
2975 for (std::pair<SymbolRef, EquivalenceClass> SymbolClassPair : Map) {
2976 SymbolRef Sym = SymbolClassPair.first;
2977
2978 if (SymReaper.isDead(Sym)) {
2979 ClassMapChanged = true;
2980 NewMap = ClassFactory.remove(NewMap, Sym);
2981 }
2982 }
2983
2984 // 3. Remove dead members from classes and remove dead non-trivial classes
2985 // and their constraints.
2986 for (std::pair<EquivalenceClass, SymbolSet> ClassMembersPair :
2987 ClassMembersMap) {
2988 EquivalenceClass Class = ClassMembersPair.first;
2989 SymbolSet LiveMembers = ClassMembersPair.second;
2990 bool MembersChanged = false;
2991
2992 for (SymbolRef Member : ClassMembersPair.second) {
2993 if (SymReaper.isDead(Member)) {
2994 MembersChanged = true;
2995 LiveMembers = SetFactory.remove(LiveMembers, Member);
2996 }
2997 }
2998
2999 // Check if the class changed.
3000 if (!MembersChanged)
3001 continue;
3002
3003 MembersMapChanged = true;
3004
3005 if (LiveMembers.isEmpty()) {
3006 // The class is dead now, we need to wipe it out of the members map...
3007 NewClassMembersMap = EMFactory.remove(NewClassMembersMap, Class);
3008
3009 // ...and remove all of its constraints.
3010 removeDeadClass(Class);
3011 } else {
3012 // We need to change the members associated with the class.
3013 NewClassMembersMap =
3014 EMFactory.add(NewClassMembersMap, Class, LiveMembers);
3015 }
3016 }
3017
3018 // 4. Update the state with new maps.
3019 //
3020 // Here we try to be humble and update a map only if it really changed.
3021 if (ClassMapChanged)
3022 State = State->set<ClassMap>(NewMap);
3023
3024 if (MembersMapChanged)
3025 State = State->set<ClassMembers>(NewClassMembersMap);
3026
3027 if (ConstraintMapChanged)
3028 State = State->set<ConstraintRange>(Constraints);
3029
3030 if (DisequalitiesChanged)
3031 State = State->set<DisequalityMap>(Disequalities);
3032
3033 assert(EquivalenceClass::isClassDataConsistent(State));
3034
3035 return State;
3036}
3037
3038RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
3039 SymbolRef Sym) const {
3040 return SymbolicRangeInferrer::inferRange(F, State, Sym);
3041}
3042
3043ProgramStateRef RangeConstraintManager::setRange(ProgramStateRef State,
3044 SymbolRef Sym,
3045 RangeSet Range) {
3046 return ConstraintAssignor::assign(State, getSValBuilder(), F, Sym, Range);
3047}
3048
3049//===------------------------------------------------------------------------===
3050// assumeSymX methods: protected interface for RangeConstraintManager.
3051//===------------------------------------------------------------------------===
3052
3053// The syntax for ranges below is mathematical, using [x, y] for closed ranges
3054// and (x, y) for open ranges. These ranges are modular, corresponding with
3055// a common treatment of C integer overflow. This means that these methods
3056// do not have to worry about overflow; RangeSet::Intersect can handle such a
3057// "wraparound" range.
3058// As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1,
3059// UINT_MAX, 0, 1, and 2.
3060
3062RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym,
3063 const llvm::APSInt &Int,
3064 const llvm::APSInt &Adjustment) {
3065 // Before we do any real work, see if the value can even show up.
3066 APSIntType AdjustmentType(Adjustment);
3067 if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
3068 return St;
3069
3070 llvm::APSInt Point = AdjustmentType.convert(Int) - Adjustment;
3071 RangeSet New = getRange(St, Sym);
3072 New = F.deletePoint(New, Point);
3073
3074 return setRange(St, Sym, New);
3075}
3076
3078RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym,
3079 const llvm::APSInt &Int,
3080 const llvm::APSInt &Adjustment) {
3081 // Before we do any real work, see if the value can even show up.
3082 APSIntType AdjustmentType(Adjustment);
3083 if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
3084 return nullptr;
3085
3086 // [Int-Adjustment, Int-Adjustment]
3087 llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
3088 RangeSet New = getRange(St, Sym);
3089 New = F.intersect(New, AdjInt);
3090
3091 return setRange(St, Sym, New);
3092}
3093
3095RangeConstraintManager::getSymLTRange(ProgramStateRef St, SymbolRef Sym,
3096 const llvm::APSInt &Int,
3097 const llvm::APSInt &Adjustment) const {
3098 // Before we do any real work, see if the value can even show up.
3099 APSIntType AdjustmentType(Adjustment);
3100 switch (AdjustmentType.testInRange(Int, true)) {
3102 return F.getEmptySet();
3104 break;
3106 return getRange(St, Sym);
3107 }
3108
3109 // Special case for Int == Min. This is always false.
3110 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3111 llvm::APSInt Min = AdjustmentType.getMinValue();
3112 if (ComparisonVal == Min)
3113 return F.getEmptySet();
3114
3115 llvm::APSInt Lower = Min - Adjustment;
3116 llvm::APSInt Upper = ComparisonVal - Adjustment;
3117 --Upper;
3118
3119 RangeSet Result = getRange(St, Sym);
3120 return F.intersect(Result, Lower, Upper);
3121}
3122
3124RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym,
3125 const llvm::APSInt &Int,
3126 const llvm::APSInt &Adjustment) {
3127 RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
3128 return setRange(St, Sym, New);
3129}
3130
3132RangeConstraintManager::getSymGTRange(ProgramStateRef St, SymbolRef Sym,
3133 const llvm::APSInt &Int,
3134 const llvm::APSInt &Adjustment) const {
3135 // Before we do any real work, see if the value can even show up.
3136 APSIntType AdjustmentType(Adjustment);
3137 switch (AdjustmentType.testInRange(Int, true)) {
3139 return getRange(St, Sym);
3141 break;
3143 return F.getEmptySet();
3144 }
3145
3146 // Special case for Int == Max. This is always false.
3147 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3148 llvm::APSInt Max = AdjustmentType.getMaxValue();
3149 if (ComparisonVal == Max)
3150 return F.getEmptySet();
3151
3152 llvm::APSInt Lower = ComparisonVal - Adjustment;
3153 llvm::APSInt Upper = Max - Adjustment;
3154 ++Lower;
3155
3156 RangeSet SymRange = getRange(St, Sym);
3157 return F.intersect(SymRange, Lower, Upper);
3158}
3159
3161RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym,
3162 const llvm::APSInt &Int,
3163 const llvm::APSInt &Adjustment) {
3164 RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
3165 return setRange(St, Sym, New);
3166}
3167
3169RangeConstraintManager::getSymGERange(ProgramStateRef St, SymbolRef Sym,
3170 const llvm::APSInt &Int,
3171 const llvm::APSInt &Adjustment) const {
3172 // Before we do any real work, see if the value can even show up.
3173 APSIntType AdjustmentType(Adjustment);
3174 switch (AdjustmentType.testInRange(Int, true)) {
3176 return getRange(St, Sym);
3178 break;
3180 return F.getEmptySet();
3181 }
3182
3183 // Special case for Int == Min. This is always feasible.
3184 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3185 llvm::APSInt Min = AdjustmentType.getMinValue();
3186 if (ComparisonVal == Min)
3187 return getRange(St, Sym);
3188
3189 llvm::APSInt Max = AdjustmentType.getMaxValue();
3190 llvm::APSInt Lower = ComparisonVal - Adjustment;
3191 llvm::APSInt Upper = Max - Adjustment;
3192
3193 RangeSet SymRange = getRange(St, Sym);
3194 return F.intersect(SymRange, Lower, Upper);
3195}
3196
3198RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym,
3199 const llvm::APSInt &Int,
3200 const llvm::APSInt &Adjustment) {
3201 RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
3202 return setRange(St, Sym, New);
3203}
3204
3206RangeConstraintManager::getSymLERange(llvm::function_ref<RangeSet()> RS,
3207 const llvm::APSInt &Int,
3208 const llvm::APSInt &Adjustment) const {
3209 // Before we do any real work, see if the value can even show up.
3210 APSIntType AdjustmentType(Adjustment);
3211 switch (AdjustmentType.testInRange(Int, true)) {
3213 return F.getEmptySet();
3215 break;
3217 return RS();
3218 }
3219
3220 // Special case for Int == Max. This is always feasible.
3221 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3222 llvm::APSInt Max = AdjustmentType.getMaxValue();
3223 if (ComparisonVal == Max)
3224 return RS();
3225
3226 llvm::APSInt Min = AdjustmentType.getMinValue();
3227 llvm::APSInt Lower = Min - Adjustment;
3228 llvm::APSInt Upper = ComparisonVal - Adjustment;
3229
3230 RangeSet Default = RS();
3231 return F.intersect(Default, Lower, Upper);
3232}
3233
3235RangeConstraintManager::getSymLERange(ProgramStateRef St, SymbolRef Sym,
3236 const llvm::APSInt &Int,
3237 const llvm::APSInt &Adjustment) const {
3238 return getSymLERange([&] { return getRange(St, Sym); }, Int, Adjustment);
3239}
3240
3242RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym,
3243 const llvm::APSInt &Int,
3244 const llvm::APSInt &Adjustment) {
3245 RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
3246 return setRange(St, Sym, New);
3247}
3248
3249ProgramStateRef RangeConstraintManager::assumeSymWithinInclusiveRange(
3250 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
3251 const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
3252 RangeSet New = getSymGERange(State, Sym, From, Adjustment);
3253 if (New.isEmpty())
3254 return nullptr;
3255 RangeSet Out = getSymLERange([&] { return New; }, To, Adjustment);
3256 return setRange(State, Sym, Out);
3257}
3258
3259ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
3260 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
3261 const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
3262 RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
3263 RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
3264 RangeSet New(F.add(RangeLT, RangeGT));
3265 return setRange(State, Sym, New);
3266}
3267
3268//===----------------------------------------------------------------------===//
3269// Pretty-printing.
3270//===----------------------------------------------------------------------===//
3271
3272void RangeConstraintManager::printJson(raw_ostream &Out, ProgramStateRef State,
3273 const char *NL, unsigned int Space,
3274 bool IsDot) const {
3275 printConstraints(Out, State, NL, Space, IsDot);
3276 printEquivalenceClasses(Out, State, NL, Space, IsDot);
3277 printDisequalities(Out, State, NL, Space, IsDot);
3278}
3279
3280void RangeConstraintManager::printValue(raw_ostream &Out, ProgramStateRef State,
3281 SymbolRef Sym) {
3282 const RangeSet RS = getRange(State, Sym);
3283 if (RS.isEmpty()) {
3284 Out << "<empty rangeset>";
3285 return;
3286 }
3287 Out << RS.getBitWidth() << (RS.isUnsigned() ? "u:" : "s:");
3288 RS.dump(Out);
3289}
3290
3291static std::string toString(const SymbolRef &Sym) {
3292 std::string S;
3293 llvm::raw_string_ostream O(S);
3294 Sym->dumpToStream(O);
3295 return S;
3296}
3297
3298void RangeConstraintManager::printConstraints(raw_ostream &Out,
3299 ProgramStateRef State,
3300 const char *NL,
3301 unsigned int Space,
3302 bool IsDot) const {
3303 ConstraintRangeTy Constraints = State->get<ConstraintRange>();
3304
3305 Indent(Out, Space, IsDot) << "\"constraints\": ";
3306 if (Constraints.isEmpty()) {
3307 Out << "null," << NL;
3308 return;
3309 }
3310
3311 std::map<std::string, RangeSet> OrderedConstraints;
3312 for (std::pair<EquivalenceClass, RangeSet> P : Constraints) {
3313 SymbolSet ClassMembers = P.first.getClassMembers(State);
3314 for (const SymbolRef &ClassMember : ClassMembers) {
3315 bool insertion_took_place;
3316 std::tie(std::ignore, insertion_took_place) =
3317 OrderedConstraints.insert({toString(ClassMember), P.second});
3318 assert(insertion_took_place &&
3319 "two symbols should not have the same dump");
3320 }
3321 }
3322
3323 ++Space;
3324 Out << '[' << NL;
3325 bool First = true;
3326 for (std::pair<std::string, RangeSet> P : OrderedConstraints) {
3327 if (First) {
3328 First = false;
3329 } else {
3330 Out << ',';
3331 Out << NL;
3332 }
3333 Indent(Out, Space, IsDot)
3334 << "{ \"symbol\": \"" << P.first << "\", \"range\": \"";
3335 P.second.dump(Out);
3336 Out << "\" }";
3337 }
3338 Out << NL;
3339
3340 --Space;
3341 Indent(Out, Space, IsDot) << "]," << NL;
3342}
3343
3344static std::string toString(ProgramStateRef State, EquivalenceClass Class) {
3345 SymbolSet ClassMembers = Class.getClassMembers(State);
3346 llvm::SmallVector<SymbolRef, 8> ClassMembersSorted(ClassMembers.begin(),
3347 ClassMembers.end());
3348 llvm::sort(ClassMembersSorted,
3349 [](const SymbolRef &LHS, const SymbolRef &RHS) {
3350 return toString(LHS) < toString(RHS);
3351 });
3352
3353 bool FirstMember = true;
3354
3355 std::string Str;
3356 llvm::raw_string_ostream Out(Str);
3357 Out << "[ ";
3358 for (SymbolRef ClassMember : ClassMembersSorted) {
3359 if (FirstMember)
3360 FirstMember = false;
3361 else
3362 Out << ", ";
3363 Out << "\"" << ClassMember << "\"";
3364 }
3365 Out << " ]";
3366 return Str;
3367}
3368
3369void RangeConstraintManager::printEquivalenceClasses(raw_ostream &Out,
3370 ProgramStateRef State,
3371 const char *NL,
3372 unsigned int Space,
3373 bool IsDot) const {
3374 ClassMembersTy Members = State->get<ClassMembers>();
3375
3376 Indent(Out, Space, IsDot) << "\"equivalence_classes\": ";
3377 if (Members.isEmpty()) {
3378 Out << "null," << NL;
3379 return;
3380 }
3381
3382 std::set<std::string> MembersStr;
3383 for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members)
3384 MembersStr.insert(toString(State, ClassToSymbolSet.first));
3385
3386 ++Space;
3387 Out << '[' << NL;
3388 bool FirstClass = true;
3389 for (const std::string &Str : MembersStr) {
3390 if (FirstClass) {
3391 FirstClass = false;
3392 } else {
3393 Out << ',';
3394 Out << NL;
3395 }
3396 Indent(Out, Space, IsDot);
3397 Out << Str;
3398 }
3399 Out << NL;
3400
3401 --Space;
3402 Indent(Out, Space, IsDot) << "]," << NL;
3403}
3404
3405void RangeConstraintManager::printDisequalities(raw_ostream &Out,
3406 ProgramStateRef State,
3407 const char *NL,
3408 unsigned int Space,
3409 bool IsDot) const {
3410 DisequalityMapTy Disequalities = State->get<DisequalityMap>();
3411
3412 Indent(Out, Space, IsDot) << "\"disequality_info\": ";
3413 if (Disequalities.isEmpty()) {
3414 Out << "null," << NL;
3415 return;
3416 }
3417
3418 // Transform the disequality info to an ordered map of
3419 // [string -> (ordered set of strings)]
3420 using EqClassesStrTy = std::set<std::string>;
3421 using DisequalityInfoStrTy = std::map<std::string, EqClassesStrTy>;
3422 DisequalityInfoStrTy DisequalityInfoStr;
3423 for (std::pair<EquivalenceClass, ClassSet> ClassToDisEqSet : Disequalities) {
3424 EquivalenceClass Class = ClassToDisEqSet.first;
3425 ClassSet DisequalClasses = ClassToDisEqSet.second;
3426 EqClassesStrTy MembersStr;
3427 for (EquivalenceClass DisEqClass : DisequalClasses)
3428 MembersStr.insert(toString(State, DisEqClass));
3429 DisequalityInfoStr.insert({toString(State, Class), MembersStr});
3430 }
3431
3432 ++Space;
3433 Out << '[' << NL;
3434 bool FirstClass = true;
3435 for (std::pair<std::string, EqClassesStrTy> ClassToDisEqSet :
3436 DisequalityInfoStr) {
3437 const std::string &Class = ClassToDisEqSet.first;
3438 if (FirstClass) {
3439 FirstClass = false;
3440 } else {
3441 Out << ',';
3442 Out << NL;
3443 }
3444 Indent(Out, Space, IsDot) << "{" << NL;
3445 unsigned int DisEqSpace = Space + 1;
3446 Indent(Out, DisEqSpace, IsDot) << "\"class\": ";
3447 Out << Class;
3448 const EqClassesStrTy &DisequalClasses = ClassToDisEqSet.second;
3449 if (!DisequalClasses.empty()) {
3450 Out << "," << NL;
3451 Indent(Out, DisEqSpace, IsDot) << "\"disequal_to\": [" << NL;
3452 unsigned int DisEqClassSpace = DisEqSpace + 1;
3453 Indent(Out, DisEqClassSpace, IsDot);
3454 bool FirstDisEqClass = true;
3455 for (const std::string &DisEqClass : DisequalClasses) {
3456 if (FirstDisEqClass) {
3457 FirstDisEqClass = false;
3458 } else {
3459 Out << ',' << NL;
3460 Indent(Out, DisEqClassSpace, IsDot);
3461 }
3462 Out << DisEqClass;
3463 }
3464 Out << "]" << NL;
3465 }
3466 Indent(Out, Space, IsDot) << "}";
3467 }
3468 Out << NL;
3469
3470 --Space;
3471 Indent(Out, Space, IsDot) << "]," << NL;
3472}
#define V(N, I)
Definition: ASTContext.h:3443
StringRef P
static char ID
Definition: Arena.cpp:183
static bool isTrivial(ASTContext &Ctx, const Expr *E)
Checks if the expression is constant or does not have non-trivial function calls.
Expr * E
llvm::APSInt APSInt
Definition: Compiler.cpp:23
static void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)
#define X(type, name)
Definition: Value.h:144
llvm::MachO::SymbolSet SymbolSet
Definition: MachO.h:44
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
#define REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(Name, Elem)
Declares an immutable set type Name and registers the factory for such sets in the program state,...
#define CONSTRAINT_DISPATCH(Id)
static void swapIterators(T &First, T &FirstEnd, T &Second, T &SecondEnd)
static ProgramStateRef reAssume(ProgramStateRef State, const RangeSet *Constraint, SVal TheValue)
#define DEFAULT_ASSIGN(Id)
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static CharSourceRange getRange(const CharSourceRange &EditRange, const SourceManager &SM, const LangOptions &LangOpts, bool IncludeMacroExpansion)
Definition: SourceCode.cpp:152
static BinaryOperatorKind getOpFromIndex(size_t Index)
constexpr size_t getCmpOpCount() const
TriStateKind getCmpOpState(BinaryOperatorKind CurrentOP, BinaryOperatorKind QueriedOP) const
TriStateKind getCmpOpStateForUnknownX2(BinaryOperatorKind CurrentOP) const
bool isComparisonOp() const
Definition: Expr.h:4010
bool isRelationalOp() const
Definition: Expr.h:4004
static Opcode negateComparisonOp(Opcode Opc)
Definition: Expr.h:4015
static Opcode reverseComparisonOp(Opcode Opc)
Definition: Expr.h:4028
bool isEqualityOp() const
Definition: Expr.h:4007
A (possibly-)qualified type.
Definition: Type.h:929
The type-property cache.
Definition: Type.cpp:4501
The base class of the type hierarchy.
Definition: Type.h:1828
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition: Type.cpp:2201
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
Definition: Type.cpp:2251
bool isReferenceType() const
Definition: Type.h:8204
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition: Type.h:8625
A record of the "type" of an APSInt, used for conversions.
Definition: APSIntType.h:19
bool isUnsigned() const
Definition: APSIntType.h:31
llvm::APSInt getZeroValue() const LLVM_READONLY
Returns an all-zero value for this type.
Definition: APSIntType.h:55
RangeTestResultKind
Used to classify whether a value is representable using this type.
Definition: APSIntType.h:76
@ RTR_Within
Value is representable using this type.
Definition: APSIntType.h:78
@ RTR_Below
Value is less than the minimum representable value.
Definition: APSIntType.h:77
@ RTR_Above
Value is greater than the maximum representable value.
Definition: APSIntType.h:79
uint32_t getBitWidth() const
Definition: APSIntType.h:30
RangeTestResultKind testInRange(const llvm::APSInt &Val, bool AllowMixedSign) const LLVM_READONLY
Tests whether a given value is losslessly representable using this type.
Definition: APSIntType.cpp:15
void apply(llvm::APSInt &Value) const
Convert a given APSInt, in place, to match this type.
Definition: APSIntType.h:37
llvm::APSInt getMinValue() const LLVM_READONLY
Returns the minimum value for this type.
Definition: APSIntType.h:60
llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY
Convert and return a new APSInt with the given value, but this type's bit width and signedness.
Definition: APSIntType.h:48
llvm::APSInt getValue(uint64_t RawValue) const LLVM_READONLY
Definition: APSIntType.h:69
APSIntType getAPSIntType(QualType T) const
Returns the type of the APSInt used to store values of the given QualType.
Template implementation for all binary symbolic expressions.
QualType getType() const override
BinaryOperator::Opcode getOpcode() const
static bool isLocType(QualType T)
Definition: SVals.h:262
RangeSet unite(RangeSet LHS, RangeSet RHS)
Create a new set which is a union of two given ranges.
RangeSet negate(RangeSet What)
Negate the given range set.
RangeSet intersect(RangeSet LHS, RangeSet RHS)
Intersect the given range sets.
RangeSet deletePoint(RangeSet From, const llvm::APSInt &Point)
Delete the given point from the range set.
RangeSet getRangeSet(Range Origin)
Create a new set with just one range.
RangeSet add(RangeSet LHS, RangeSet RHS)
Create a new set with all ranges from both LHS and RHS.
RangeSet castTo(RangeSet What, APSIntType Ty)
Performs promotions, truncations and conversions of the given set.
persistent set of non-overlapping ranges.
const_iterator end() const
APSIntType getAPSIntType() const
const llvm::APSInt & getMaxValue() const
Get the maximal value covered by the ranges in the set.
bool encodesTrueRange() const
Test if the range doesn't contain zero.
bool encodesFalseRange() const
Test if the range is the [0,0] range.
const_iterator begin() const
const llvm::APSInt & getMinValue() const
Get the minimal value covered by the ranges in the set.
ImplType::const_iterator const_iterator
bool contains(llvm::APSInt Point) const
Test whether the given point is contained by any of the ranges.
void dump(raw_ostream &OS) const
const llvm::APSInt * getConcreteValue() const
getConcreteValue - If a symbol is constrained to equal a specific integer constant then this method r...
A Range represents the closed range [from, to].
const llvm::APSInt & From() const
void dump(raw_ostream &OS) const
bool Includes(const llvm::APSInt &Point) const
const llvm::APSInt & To() const
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition: SVals.h:56
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
Definition: SVals.cpp:104
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
Definition: SVals.h:87
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition: SVals.h:83
SymExprVisitor - this class implements a simple visitor for SymExpr subclasses.
Definition: SValVisitor.h:66
Symbolic value.
Definition: SymExpr.h:30
virtual void dumpToStream(raw_ostream &os) const
Definition: SymExpr.h:61
virtual QualType getType() const =0
Kind getKind() const
Definition: SymExpr.h:57
const SymSymExpr * getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t)
A class responsible for cleaning up unused symbols.
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
Represents a symbolic expression involving a unary operator.
QualType getType() const override
UnaryOperator::Opcode getOpcode() const
const SymExpr * getOperand() const
Value representing integer constant.
Definition: SVals.h:300
Represents symbolic expression that isn't a location.
Definition: SVals.h:279
SVal simplifyToSVal(ProgramStateRef State, SymbolRef Sym)
Try to simplify a given symbolic expression's associated SVal based on the constraints in State.
llvm::ImmutableMap< SymbolRef, RangeSet > ConstraintMap
SymbolRef simplify(ProgramStateRef State, SymbolRef Sym)
Try to simplify a given symbolic expression based on the constraints in State.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
@ CF
Indicates that the tracked object is a CF object.
std::unique_ptr< ConstraintManager > CreateRangeConstraintManager(ProgramStateManager &statemgr, ExprEngine *exprengine)
ConstraintMap getConstraintMap(ProgramStateRef State)
bool Zero(InterpState &S, CodePtr OpPC)
Definition: Interp.h:2408
bool Const(InterpState &S, CodePtr OpPC, const T &Arg)
Definition: Interp.h:1243
The JSON file list parser is used to communicate input to InstallAPI.
BinaryOperatorKind
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition: CallGraph.h:204
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
@ Result
The result type of a method or function.
bool operator!=(CanQual< T > x, CanQual< U > y)
const FunctionProtoType * T
@ Class
The "class" keyword introduces the elaborated-type-specifier.
@ Other
Other implicit parameter.
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...