Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
Line
Count
Source (jump to first uncovered line)
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
14
#include "clang/Basic/JsonSupport.h"
15
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
16
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
17
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
18
#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
19
#include "clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h"
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
31
using namespace clang;
32
using namespace ento;
33
34
// This class can be extended with other tables which will help to reason
35
// about ranges more precisely.
36
class OperatorRelationsTable {
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
41
public:
42
  enum TriStateKind {
43
    False = 0,
44
    True,
45
    Unknown,
46
  };
47
48
private:
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
79
      {True, False, Unknown, False, False, Unknown, True}, // <
80
      {False, True, False, Unknown, False, Unknown, True}, // >
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
27.1k
  static size_t getIndexFromOp(BinaryOperatorKind OP) {
88
27.1k
    return static_cast<size_t>(OP - BO_LT);
89
27.1k
  }
90
91
public:
92
138k
  constexpr size_t getCmpOpCount() const { return CmpOpCount; }
93
94
120k
  static BinaryOperatorKind getOpFromIndex(size_t Index) {
95
120k
    return static_cast<BinaryOperatorKind>(Index + BO_LT);
96
120k
  }
97
98
  TriStateKind getCmpOpState(BinaryOperatorKind CurrentOP,
99
13.5k
                             BinaryOperatorKind QueriedOP) const {
100
13.5k
    return CmpOpTable[getIndexFromOp(CurrentOP)][getIndexFromOp(QueriedOP)];
101
13.5k
  }
102
103
64
  TriStateKind getCmpOpStateForUnknownX2(BinaryOperatorKind CurrentOP) const {
104
64
    return CmpOpTable[getIndexFromOp(CurrentOP)][CmpOpCount];
105
64
  }
106
};
107
108
//===----------------------------------------------------------------------===//
109
//                           RangeSet implementation
110
//===----------------------------------------------------------------------===//
111
112
RangeSet::ContainerType RangeSet::Factory::EmptySet{};
113
114
7.34k
RangeSet RangeSet::Factory::add(RangeSet LHS, RangeSet RHS) {
115
7.34k
  ContainerType Result;
116
7.34k
  Result.reserve(LHS.size() + RHS.size());
117
7.34k
  std::merge(LHS.begin(), LHS.end(), RHS.begin(), RHS.end(),
118
7.34k
             std::back_inserter(Result));
119
7.34k
  return makePersistent(std::move(Result));
120
7.34k
}
121
122
8.34k
RangeSet RangeSet::Factory::add(RangeSet Original, Range Element) {
123
8.34k
  ContainerType Result;
124
8.34k
  Result.reserve(Original.size() + 1);
125
126
8.34k
  const_iterator Lower = llvm::lower_bound(Original, Element);
127
8.34k
  Result.insert(Result.end(), Original.begin(), Lower);
128
8.34k
  Result.push_back(Element);
129
8.34k
  Result.insert(Result.end(), Lower, Original.end());
130
131
8.34k
  return makePersistent(std::move(Result));
132
8.34k
}
133
134
24
RangeSet RangeSet::Factory::add(RangeSet Original, const llvm::APSInt &Point) {
135
24
  return add(Original, Range(Point));
136
24
}
137
138
264
RangeSet RangeSet::Factory::unite(RangeSet LHS, RangeSet RHS) {
139
264
  ContainerType Result = unite(*LHS.Impl, *RHS.Impl);
140
264
  return makePersistent(std::move(Result));
141
264
}
142
143
240
RangeSet RangeSet::Factory::unite(RangeSet Original, Range R) {
144
240
  ContainerType Result;
145
240
  Result.push_back(R);
146
240
  Result = unite(*Original.Impl, Result);
147
240
  return makePersistent(std::move(Result));
148
240
}
149
150
80
RangeSet RangeSet::Factory::unite(RangeSet Original, llvm::APSInt Point) {
151
80
  return unite(Original, Range(ValueFactory.getValue(Point)));
152
80
}
153
154
RangeSet RangeSet::Factory::unite(RangeSet Original, llvm::APSInt From,
155
0
                                  llvm::APSInt To) {
156
0
  return unite(Original,
157
0
               Range(ValueFactory.getValue(From), ValueFactory.getValue(To)));
158
0
}
159
160
template <typename T>
161
350k
void swapIterators(T &First, T &FirstEnd, T &Second, T &SecondEnd) {
162
350k
  std::swap(First, Second);
163
350k
  std::swap(FirstEnd, SecondEnd);
164
350k
}
165
166
RangeSet::ContainerType RangeSet::Factory::unite(const ContainerType &LHS,
167
1.45k
                                                 const ContainerType &RHS) {
168
1.45k
  if (LHS.empty())
169
440
    return RHS;
170
1.01k
  if (RHS.empty())
171
210
    return LHS;
172
173
808
  using llvm::APSInt;
174
808
  using iterator = ContainerType::const_iterator;
175
176
808
  iterator First = LHS.begin();
177
808
  iterator FirstEnd = LHS.end();
178
808
  iterator Second = RHS.begin();
179
808
  iterator SecondEnd = RHS.end();
180
808
  APSIntType Ty = APSIntType(First->From());
181
808
  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
808
  if (Min == First->From() && 
Min == Second->From()224
) {
188
60
    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
8
      if (++Second == SecondEnd)
196
        //    [ First     ]--[ First + 1 ]--->
197
        //    [ Second ]--------------------->
198
        // MIN^
199
        // The Union is equal to First's RangeSet.
200
8
        return LHS;
201
52
    } 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
52
      if (++First == FirstEnd)
210
        //    [ First ]----------------------->
211
        //    [ Second  ]--[ Second + 1 ]---->
212
        // MIN^
213
        // The Union is equal to Second's RangeSet.
214
24
        return RHS;
215
52
    }
216
60
  }
217
218
776
  const APSInt One = Ty.getValue(1);
219
776
  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
776
  const auto AppendTheRest = [&Result](iterator I, iterator E) {
225
776
    Result.append(I, E);
226
776
    return Result;
227
776
  };
228
229
1.05k
  while (true) {
230
    // We want to keep the following invariant at all times:
231
    // ---[ First ------>
232
    // -----[ Second --->
233
1.05k
    if (First->From() > Second->From())
234
604
      swapIterators(First, FirstEnd, Second, SecondEnd);
235
236
    // The Union definitely starts with First->From().
237
    // ----------[ First ------>
238
    // ------------[ Second --->
239
    // ----------[ Union ------>
240
    // UnionStart^
241
1.05k
    const llvm::APSInt &UnionStart = First->From();
242
243
    // Loop where the invariant holds.
244
1.16k
    while (true) {
245
      // Skip all enclosed ranges.
246
      // ---[                  First                     ]--->
247
      // -----[ Second ]--[ Second + 1 ]--[ Second + N ]----->
248
1.20k
      while (First->To() >= Second->To()) {
249
        // Check if Second is the last in its RangeSet.
250
200
        if (++Second == SecondEnd) {
251
          // Append the Union.
252
          // ---[ Union      ]--->
253
          // -----[ Second ]----->
254
          // --------[ First ]--->
255
          //         UnionEnd^
256
160
          Result.emplace_back(UnionStart, First->To());
257
          // ---[ Union ]----------------->
258
          // --------------[ First + 1]--->
259
          // Append all remaining ranges from the First's RangeSet.
260
160
          return AppendTheRest(++First, FirstEnd);
261
160
        }
262
200
      }
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
1.00k
      if (First->To() < Second->From() - One)
270
710
        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
296
      if (++First == FirstEnd) {
278
        // Append the Union.
279
        // ---[ Union       ]--->
280
        // -----[ First ]------->
281
        // --------[ Second ]--->
282
        //          UnionEnd^
283
188
        Result.emplace_back(UnionStart, Second->To());
284
        // ---[ Union ]------------------>
285
        // --------------[ Second + 1]--->
286
        // Append all remaining ranges from the Second's RangeSet.
287
188
        return AppendTheRest(++Second, SecondEnd);
288
188
      }
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
108
      swapIterators(First, FirstEnd, Second, SecondEnd);
297
108
    }
298
299
    // Here First and Second are disjoint.
300
    // Append the Union.
301
    // ---[ Union    ]--------------->
302
    // -----------------[ Second ]--->
303
    // ------[ First ]--------------->
304
    //       UnionEnd^
305
710
    Result.emplace_back(UnionStart, First->To());
306
307
    // Check if First is the last in its RangeSet.
308
710
    if (++First == FirstEnd)
309
      // ---[ Union ]--------------->
310
      // --------------[ Second ]--->
311
      // Append all remaining ranges from the Second's RangeSet.
312
428
      return AppendTheRest(Second, SecondEnd);
313
710
  }
314
315
0
  llvm_unreachable("Normally, we should not reach here");
316
0
}
317
318
964k
RangeSet RangeSet::Factory::getRangeSet(Range From) {
319
964k
  ContainerType Result;
320
964k
  Result.push_back(From);
321
964k
  return makePersistent(std::move(Result));
322
964k
}
323
324
1.38M
RangeSet RangeSet::Factory::makePersistent(ContainerType &&From) {
325
1.38M
  llvm::FoldingSetNodeID ID;
326
1.38M
  void *InsertPos;
327
328
1.38M
  From.Profile(ID);
329
1.38M
  ContainerType *Result = Cache.FindNodeOrInsertPos(ID, InsertPos);
330
331
1.38M
  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
52.0k
    Result = construct(std::move(From));
336
52.0k
    Cache.InsertNode(Result, InsertPos);
337
52.0k
  }
338
339
1.38M
  return Result;
340
1.38M
}
341
342
52.0k
RangeSet::ContainerType *RangeSet::Factory::construct(ContainerType &&From) {
343
52.0k
  void *Buffer = Arena.Allocate();
344
52.0k
  return new (Buffer) ContainerType(std::move(From));
345
52.0k
}
346
347
1.28M
const llvm::APSInt &RangeSet::getMinValue() const {
348
1.28M
  assert(!isEmpty());
349
1.28M
  return begin()->From();
350
1.28M
}
351
352
774k
const llvm::APSInt &RangeSet::getMaxValue() const {
353
774k
  assert(!isEmpty());
354
774k
  return std::prev(end())->To();
355
774k
}
356
357
1.79k
bool clang::ento::RangeSet::isUnsigned() const {
358
1.79k
  assert(!isEmpty());
359
1.79k
  return begin()->From().isUnsigned();
360
1.79k
}
361
362
2.87k
uint32_t clang::ento::RangeSet::getBitWidth() const {
363
2.87k
  assert(!isEmpty());
364
2.87k
  return begin()->From().getBitWidth();
365
2.87k
}
366
367
3.43k
APSIntType clang::ento::RangeSet::getAPSIntType() const {
368
3.43k
  assert(!isEmpty());
369
3.43k
  return APSIntType(begin()->From());
370
3.43k
}
371
372
401k
bool RangeSet::containsImpl(llvm::APSInt &Point) const {
373
401k
  if (isEmpty() || 
!pin(Point)401k
)
374
32
    return false;
375
376
401k
  Range Dummy(Point);
377
401k
  const_iterator It = llvm::upper_bound(*this, Dummy);
378
401k
  if (It == begin())
379
111k
    return false;
380
381
289k
  return std::prev(It)->Includes(Point);
382
401k
}
383
384
401k
bool RangeSet::pin(llvm::APSInt &Point) const {
385
401k
  APSIntType Type(getMinValue());
386
401k
  if (Type.testInRange(Point, true) != APSIntType::RTR_Within)
387
6
    return false;
388
389
401k
  Type.apply(Point);
390
401k
  return true;
391
401k
}
392
393
138k
bool 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.
399
138k
  APSIntType Type(getMinValue());
400
138k
  APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower, true);
401
138k
  APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper, true);
402
403
138k
  switch (LowerTest) {
404
34
  case APSIntType::RTR_Below:
405
34
    switch (UpperTest) {
406
2
    case APSIntType::RTR_Below:
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
2
      if (Lower <= Upper)
410
1
        return false;
411
412
      // However, if the range wraps around, it spans all possible values.
413
1
      Lower = Type.getMinValue();
414
1
      Upper = Type.getMaxValue();
415
1
      break;
416
28
    case APSIntType::RTR_Within:
417
      // The range starts below what's possible but ends within it. Pin.
418
28
      Lower = Type.getMinValue();
419
28
      Type.apply(Upper);
420
28
      break;
421
4
    case APSIntType::RTR_Above:
422
      // The range spans all possible values for the symbol. Pin.
423
4
      Lower = Type.getMinValue();
424
4
      Upper = Type.getMaxValue();
425
4
      break;
426
34
    }
427
33
    break;
428
138k
  case APSIntType::RTR_Within:
429
138k
    switch (UpperTest) {
430
45
    case APSIntType::RTR_Below:
431
      // The range wraps around, but all lower values are not possible.
432
45
      Type.apply(Lower);
433
45
      Upper = Type.getMaxValue();
434
45
      break;
435
138k
    case APSIntType::RTR_Within:
436
      // The range may or may not wrap around, but both limits are valid.
437
138k
      Type.apply(Lower);
438
138k
      Type.apply(Upper);
439
138k
      break;
440
15
    case APSIntType::RTR_Above:
441
      // The range starts within what's possible but ends above it. Pin.
442
15
      Type.apply(Lower);
443
15
      Upper = Type.getMaxValue();
444
15
      break;
445
138k
    }
446
138k
    break;
447
138k
  case APSIntType::RTR_Above:
448
20
    switch (UpperTest) {
449
6
    case APSIntType::RTR_Below:
450
      // The range wraps but is outside the symbol's set of possible values.
451
6
      return false;
452
12
    case APSIntType::RTR_Within:
453
      // The range starts above what's possible but ends within it (wrap).
454
12
      Lower = Type.getMinValue();
455
12
      Type.apply(Upper);
456
12
      break;
457
2
    case APSIntType::RTR_Above:
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
2
      if (Lower <= Upper)
461
1
        return false;
462
463
      // However, if the range wraps around, it spans all possible values.
464
1
      Lower = Type.getMinValue();
465
1
      Upper = Type.getMaxValue();
466
1
      break;
467
20
    }
468
13
    break;
469
138k
  }
470
471
138k
  return true;
472
138k
}
473
474
RangeSet RangeSet::Factory::intersect(RangeSet What, llvm::APSInt Lower,
475
138k
                                      llvm::APSInt Upper) {
476
138k
  if (What.isEmpty() || 
!What.pin(Lower, Upper)138k
)
477
30
    return getEmptySet();
478
479
138k
  ContainerType DummyContainer;
480
481
138k
  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
84.8k
    if (What.getMaxValue() < Lower || 
Upper < What.getMinValue()76.5k
)
493
16.9k
      return getEmptySet();
494
495
67.9k
    DummyContainer.push_back(
496
67.9k
        Range(ValueFactory.getValue(Lower), ValueFactory.getValue(Upper)));
497
67.9k
  } 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
54.0k
    if (What.getMaxValue() < Lower && 
Upper < What.getMinValue()627
)
506
524
      return getEmptySet();
507
508
53.5k
    DummyContainer.push_back(
509
53.5k
        Range(ValueFactory.getMinValue(Upper), ValueFactory.getValue(Upper)));
510
53.5k
    DummyContainer.push_back(
511
53.5k
        Range(ValueFactory.getValue(Lower), ValueFactory.getMaxValue(Lower)));
512
53.5k
  }
513
514
121k
  return intersect(*What.Impl, DummyContainer);
515
138k
}
516
517
RangeSet RangeSet::Factory::intersect(const RangeSet::ContainerType &LHS,
518
399k
                                      const RangeSet::ContainerType &RHS) {
519
399k
  ContainerType Result;
520
399k
  Result.reserve(std::max(LHS.size(), RHS.size()));
521
522
399k
  const_iterator First = LHS.begin(), Second = RHS.begin(),
523
399k
                 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
835k
  while (First != FirstEnd && 
Second != SecondEnd833k
) {
529
    // We want to keep the following invariant at all times:
530
    //
531
    //    ----[ First ---------------------->
532
    //    --------[ Second ----------------->
533
435k
    if (Second->From() < First->From())
534
236k
      swapIterators(First, FirstEnd, Second, SecondEnd);
535
536
    // Loop where the invariant holds:
537
560k
    do {
538
      // Check for the following situation:
539
      //
540
      //    ----[ First ]--------------------->
541
      //    ---------------[ Second ]--------->
542
      //
543
      // which means that...
544
560k
      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
37.9k
        ++First;
550
37.9k
        break;
551
37.9k
      }
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
522k
      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
522k
      if (Second->To() > First->To()) {
566
        // Here we make a decision to keep First as the "longer"
567
        // range.
568
113k
        swapIterators(First, FirstEnd, Second, SecondEnd);
569
113k
      }
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
522k
      Result.push_back(Range(IntersectionStart, Second->To()));
583
522k
      ++Second;
584
      // ...and that the invariant will hold for a valid Second+1
585
      // because First->From <= Second->To < (Second+1)->From.
586
522k
    } while (Second != SecondEnd);
587
435k
  }
588
589
399k
  if (Result.empty())
590
127
    return getEmptySet();
591
592
399k
  return makePersistent(std::move(Result));
593
399k
}
594
595
278k
RangeSet RangeSet::Factory::intersect(RangeSet LHS, RangeSet RHS) {
596
  // Shortcut: let's see if the intersection is even possible.
597
278k
  if (LHS.isEmpty() || 
RHS.isEmpty()277k
||
LHS.getMaxValue() < RHS.getMinValue()277k
||
598
278k
      
RHS.getMaxValue() < LHS.getMinValue()277k
)
599
198
    return getEmptySet();
600
601
277k
  return intersect(*LHS.Impl, *RHS.Impl);
602
278k
}
603
604
108k
RangeSet RangeSet::Factory::intersect(RangeSet LHS, llvm::APSInt Point) {
605
108k
  if (LHS.containsImpl(Point))
606
53.1k
    return getRangeSet(ValueFactory.getValue(Point));
607
608
55.7k
  return getEmptySet();
609
108k
}
610
611
987
RangeSet RangeSet::Factory::negate(RangeSet What) {
612
987
  if (What.isEmpty())
613
0
    return getEmptySet();
614
615
987
  const llvm::APSInt SampleValue = What.getMinValue();
616
987
  const llvm::APSInt &MIN = ValueFactory.getMinValue(SampleValue);
617
987
  const llvm::APSInt &MAX = ValueFactory.getMaxValue(SampleValue);
618
619
987
  ContainerType Result;
620
987
  Result.reserve(What.size() + (SampleValue == MIN));
621
622
  // Handle a special case for MIN value.
623
987
  const_iterator It = What.begin();
624
987
  const_iterator End = What.end();
625
626
987
  const llvm::APSInt &From = It->From();
627
987
  const llvm::APSInt &To = It->To();
628
629
987
  if (From == MIN) {
630
    // If the range [From, To] is [MIN, MAX], then result is also [MIN, MAX].
631
183
    if (To == MAX) {
632
16
      return What;
633
16
    }
634
635
167
    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
167
    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
94
      Result.emplace_back(MIN, ValueFactory.getValue(-Last->From()));
644
      // We already negated Last, so we can skip it.
645
94
      End = Last;
646
94
    } else {
647
      // Add a separate range for the lowest value.
648
73
      Result.emplace_back(MIN, MIN);
649
73
    }
650
651
    // Skip adding the second range in case when [From, To] are [MIN, MIN].
652
167
    if (To != MIN) {
653
112
      Result.emplace_back(ValueFactory.getValue(-To), MAX);
654
112
    }
655
656
    // Skip the first range in the loop.
657
167
    ++It;
658
167
  }
659
660
  // Negate all other ranges.
661
2.46k
  
for (; 971
It != End;
++It1.49k
) {
662
    // Negate int values.
663
1.49k
    const llvm::APSInt &NewFrom = ValueFactory.getValue(-It->To());
664
1.49k
    const llvm::APSInt &NewTo = ValueFactory.getValue(-It->From());
665
666
    // Add a negated range.
667
1.49k
    Result.emplace_back(NewFrom, NewTo);
668
1.49k
  }
669
670
971
  llvm::sort(Result);
671
971
  return makePersistent(std::move(Result));
672
987
}
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.
676
1.58k
RangeSet RangeSet::Factory::castTo(RangeSet What, APSIntType Ty) {
677
  // Set is empty or NOOP (aka cast to the same type).
678
1.58k
  if (What.isEmpty() || What.getAPSIntType() == Ty)
679
194
    return What;
680
681
1.39k
  const bool IsConversion = What.isUnsigned() != Ty.isUnsigned();
682
1.39k
  const bool IsTruncation = What.getBitWidth() > Ty.getBitWidth();
683
1.39k
  const bool IsPromotion = What.getBitWidth() < Ty.getBitWidth();
684
685
1.39k
  if (IsTruncation)
686
648
    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
746
  if (IsConversion && 
(468
!IsPromotion468
||
!What.isUnsigned()278
))
701
330
    return makePersistent(convertTo(What, Ty));
702
703
416
  assert(IsPromotion && "Only promotion operation from unsigneds left.");
704
416
  return makePersistent(promoteTo(What, Ty));
705
416
}
706
707
0
RangeSet RangeSet::Factory::castTo(RangeSet What, QualType T) {
708
0
  assert(T->isIntegralOrEnumerationType() && "T shall be an integral type.");
709
0
  return castTo(What, ValueFactory.getAPSIntType(T));
710
0
}
711
712
RangeSet::ContainerType RangeSet::Factory::truncateTo(RangeSet What,
713
648
                                                      APSIntType Ty) {
714
648
  using llvm::APInt;
715
648
  using llvm::APSInt;
716
648
  ContainerType Result;
717
648
  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
648
  uint64_t CastRangeSize = APInt::getMaxValue(Ty.getBitWidth()).getZExtValue();
726
888
  for (const Range &R : What) {
727
    // Get bounds of the given range.
728
888
    APSInt FromInt = R.From();
729
888
    APSInt ToInt = R.To();
730
    // CurrentRangeSize is an amount of all possible values of the current
731
    // range minus one.
732
888
    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
888
    Dummy.clear();
736
888
    if (CurrentRangeSize >= CastRangeSize) {
737
264
      Dummy.emplace_back(ValueFactory.getMinValue(Ty),
738
264
                         ValueFactory.getMaxValue(Ty));
739
264
      Result = std::move(Dummy);
740
264
      break;
741
264
    }
742
    // Cast the bounds.
743
624
    Ty.apply(FromInt);
744
624
    Ty.apply(ToInt);
745
624
    const APSInt &PersistentFrom = ValueFactory.getValue(FromInt);
746
624
    const APSInt &PersistentTo = ValueFactory.getValue(ToInt);
747
624
    if (FromInt > ToInt) {
748
60
      Dummy.emplace_back(ValueFactory.getMinValue(Ty), PersistentTo);
749
60
      Dummy.emplace_back(PersistentFrom, ValueFactory.getMaxValue(Ty));
750
60
    } else
751
564
      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
624
    Result = unite(Result, Dummy);
755
624
  }
756
757
648
  return Result;
758
648
}
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)
778
RangeSet::ContainerType RangeSet::Factory::convertTo(RangeSet What,
779
330
                                                     APSIntType Ty) {
780
330
  using llvm::APInt;
781
330
  using llvm::APSInt;
782
330
  using Bounds = std::pair<const APSInt &, const APSInt &>;
783
330
  ContainerType AscendArray;
784
330
  ContainerType DescendArray;
785
470
  auto CastRange = [Ty, &VF = ValueFactory](const Range &R) -> Bounds {
786
    // Get bounds of the given range.
787
470
    APSInt FromInt = R.From();
788
470
    APSInt ToInt = R.To();
789
    // Cast the bounds.
790
470
    Ty.apply(FromInt);
791
470
    Ty.apply(ToInt);
792
470
    return {VF.getValue(FromInt), VF.getValue(ToInt)};
793
470
  };
794
  // Phase 1. Fill the first array.
795
330
  APSInt LastConvertedInt = Ty.getMinValue();
796
330
  const auto *It = What.begin();
797
330
  const auto *E = What.end();
798
716
  while (It != E) {
799
470
    Bounds NewBounds = CastRange(*(It++));
800
    // If values stop going acsending order, go to the second phase(loop).
801
470
    if (NewBounds.first < LastConvertedInt) {
802
84
      DescendArray.emplace_back(NewBounds.first, NewBounds.second);
803
84
      break;
804
84
    }
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
386
    if (NewBounds.first > NewBounds.second) {
810
90
      DescendArray.emplace_back(ValueFactory.getMinValue(Ty), NewBounds.second);
811
90
      AscendArray.emplace_back(NewBounds.first, ValueFactory.getMaxValue(Ty));
812
90
    } else
813
      // Values are going acsending order.
814
296
      AscendArray.emplace_back(NewBounds.first, NewBounds.second);
815
386
    LastConvertedInt = NewBounds.first;
816
386
  }
817
  // Phase 2. Fill the second array.
818
330
  while (It != E) {
819
0
    Bounds NewBounds = CastRange(*(It++));
820
0
    DescendArray.emplace_back(NewBounds.first, NewBounds.second);
821
0
  }
822
  // Unite both arrays.
823
330
  return unite(AscendArray, DescendArray);
824
330
}
825
826
/// Promotion from unsigneds to signeds/unsigneds left.
827
RangeSet::ContainerType RangeSet::Factory::promoteTo(RangeSet What,
828
416
                                                     APSIntType Ty) {
829
416
  ContainerType Result;
830
  // We definitely know the size of the result set.
831
416
  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
596
  for (const Range &R : What) {
837
    // Get bounds of the given range.
838
596
    llvm::APSInt FromInt = R.From();
839
596
    llvm::APSInt ToInt = R.To();
840
    // Cast the bounds.
841
596
    Ty.apply(FromInt);
842
596
    Ty.apply(ToInt);
843
596
    Result.emplace_back(ValueFactory.getValue(FromInt),
844
596
                        ValueFactory.getValue(ToInt));
845
596
  }
846
416
  return Result;
847
416
}
848
849
RangeSet RangeSet::Factory::deletePoint(RangeSet From,
850
124k
                                        const llvm::APSInt &Point) {
851
124k
  if (!From.contains(Point))
852
55.8k
    return From;
853
854
68.5k
  llvm::APSInt Upper = Point;
855
68.5k
  llvm::APSInt Lower = Point;
856
857
68.5k
  ++Upper;
858
68.5k
  --Lower;
859
860
  // Notice that the lower bound is greater than the upper bound.
861
68.5k
  return intersect(From, Upper, Lower);
862
124k
}
863
864
88
LLVM_DUMP_METHOD void Range::dump(raw_ostream &OS) const {
865
88
  OS << '[' << toString(From(), 10) << ", " << toString(To(), 10) << ']';
866
88
}
867
0
LLVM_DUMP_METHOD void Range::dump() const { dump(llvm::errs()); }
868
869
82
LLVM_DUMP_METHOD void RangeSet::dump(raw_ostream &OS) const {
870
82
  OS << "{ ";
871
88
  llvm::interleaveComma(*this, OS, [&OS](const Range &R) { R.dump(OS); });
872
82
  OS << " }";
873
82
}
874
0
LLVM_DUMP_METHOD void RangeSet::dump() const { dump(llvm::errs()); }
875
876
REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(SymbolSet, SymbolRef)
877
878
namespace {
879
class EquivalenceClass;
880
} // end anonymous namespace
881
882
REGISTER_MAP_WITH_PROGRAMSTATE(ClassMap, SymbolRef, EquivalenceClass)
883
REGISTER_MAP_WITH_PROGRAMSTATE(ClassMembers, EquivalenceClass, SymbolSet)
884
REGISTER_MAP_WITH_PROGRAMSTATE(ConstraintRange, EquivalenceClass, RangeSet)
885
886
REGISTER_SET_FACTORY_WITH_PROGRAMSTATE(ClassSet, EquivalenceClass)
887
REGISTER_MAP_WITH_PROGRAMSTATE(DisequalityMap, EquivalenceClass, ClassSet)
888
889
namespace {
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.
914
class EquivalenceClass : public llvm::FoldingSetNode {
915
public:
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,
923
                                                    SymbolRef First,
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,
976
                                                       RangeSet::Factory &F,
977
                                                       ProgramStateRef State,
978
                                                       EquivalenceClass Class);
979
980
  void dumpToStream(ProgramStateRef State, raw_ostream &os) const;
981
0
  LLVM_DUMP_METHOD void dump(ProgramStateRef State) const {
982
0
    dumpToStream(State, llvm::errs());
983
0
  }
984
985
  /// Check equivalence data for consistency.
986
  [[nodiscard]] LLVM_ATTRIBUTE_UNUSED static bool
987
  isClassDataConsistent(ProgramStateRef State);
988
989
13.0k
  [[nodiscard]] QualType getType() const {
990
13.0k
    return getRepresentativeSymbol()->getType();
991
13.0k
  }
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
53.2M
  bool operator==(const EquivalenceClass &Other) const {
1000
53.2M
    return ID == Other.ID;
1001
53.2M
  }
1002
48.2M
  bool operator<(const EquivalenceClass &Other) const { return ID < Other.ID; }
1003
0
  bool operator!=(const EquivalenceClass &Other) const {
1004
0
    return !operator==(Other);
1005
0
  }
1006
1007
1.52M
  static void Profile(llvm::FoldingSetNodeID &ID, uintptr_t CID) {
1008
1.52M
    ID.AddInteger(CID);
1009
1.52M
  }
1010
1011
1.52M
  void Profile(llvm::FoldingSetNodeID &ID) const { Profile(ID, this->ID); }
1012
1013
private:
1014
  /* implicit */ EquivalenceClass(SymbolRef Sym)
1015
9.65M
      : 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
3.77M
  SymbolRef getRepresentativeSymbol() const {
1023
3.77M
    return reinterpret_cast<SymbolRef>(ID);
1024
3.77M
  }
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,
1033
                       RangeSet::Factory &F, ProgramStateRef State,
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
1045
67.8k
areFeasible(ConstraintRangeTy Constraints) {
1046
67.8k
  return llvm::none_of(
1047
67.8k
      Constraints,
1048
1.19M
      [](const std::pair<EquivalenceClass, RangeSet> &ClassConstraint) {
1049
1.19M
        return ClassConstraint.second.isEmpty();
1050
1.19M
      });
1051
67.8k
}
1052
1053
[[nodiscard]] inline const RangeSet *getConstraint(ProgramStateRef State,
1054
9.52M
                                                   EquivalenceClass Class) {
1055
9.52M
  return State->get<ConstraintRange>(Class);
1056
9.52M
}
1057
1058
[[nodiscard]] inline const RangeSet *getConstraint(ProgramStateRef State,
1059
9.38M
                                                   SymbolRef Sym) {
1060
9.38M
  return getConstraint(State, EquivalenceClass::find(State, Sym));
1061
9.38M
}
1062
1063
[[nodiscard]] ProgramStateRef setConstraint(ProgramStateRef State,
1064
                                            EquivalenceClass Class,
1065
158k
                                            RangeSet Constraint) {
1066
158k
  return State->set<ConstraintRange>(Class, Constraint);
1067
158k
}
1068
1069
[[nodiscard]] ProgramStateRef setConstraints(ProgramStateRef State,
1070
58.2k
                                             ConstraintRangeTy Constraints) {
1071
58.2k
  return State->set<ConstraintRange>(Constraints);
1072
58.2k
}
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
1087
220k
std::optional<bool> meansEquality(const SymSymExpr *Sym) {
1088
220k
  switch (Sym->getOpcode()) {
1089
34.4k
  case BO_Sub:
1090
    // This case is: A - B != 0 -> disequality check.
1091
34.4k
    return false;
1092
892
  case BO_EQ:
1093
    // This case is: A == B != 0 -> equality check.
1094
892
    return true;
1095
1.61k
  case BO_NE:
1096
    // This case is: A != B != 0 -> diseqiality check.
1097
1.61k
    return false;
1098
183k
  default:
1099
183k
    return std::nullopt;
1100
220k
  }
1101
220k
}
1102
1103
//===----------------------------------------------------------------------===//
1104
//                            Intersection functions
1105
//===----------------------------------------------------------------------===//
1106
1107
template <class SecondTy, class... RestTy>
1108
[[nodiscard]] inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
1109
                                        SecondTy Second, RestTy... Tail);
1110
1111
template <class... RangeTy> struct IntersectionTraits;
1112
1113
template <class... TailTy> struct IntersectionTraits<RangeSet, TailTy...> {
1114
  // Found RangeSet, no need to check any further
1115
  using Type = RangeSet;
1116
};
1117
1118
template <> 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
1124
template <class OptionalOrPointer, class... TailTy>
1125
struct 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
1130
template <class EndTy>
1131
970k
[[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
970k
  return End;
1135
970k
}
1136
1137
[[nodiscard]] LLVM_ATTRIBUTE_UNUSED inline std::optional<RangeSet>
1138
477
intersect(RangeSet::Factory &F, const RangeSet *End) {
1139
  // This is an extraneous conversion from a raw pointer into
1140
  // std::optional<RangeSet>
1141
477
  if (End) {
1142
144
    return *End;
1143
144
  }
1144
333
  return std::nullopt;
1145
477
}
1146
1147
template <class... RestTy>
1148
[[nodiscard]] inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
1149
277k
                                        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
277k
  return intersect(F, F.intersect(Head, Second), Tail...);
1153
277k
}
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::intersect<>(clang::ento::RangeSet::Factory&, clang::ento::RangeSet, clang::ento::RangeSet)
Line
Count
Source
1149
277k
                                        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
277k
  return intersect(F, F.intersect(Head, Second), Tail...);
1153
277k
}
Unexecuted instantiation: RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::intersect<std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet>(clang::ento::RangeSet::Factory&, clang::ento::RangeSet, clang::ento::RangeSet, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet)
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::intersect<clang::ento::RangeSet>(clang::ento::RangeSet::Factory&, clang::ento::RangeSet, clang::ento::RangeSet, clang::ento::RangeSet)
Line
Count
Source
1149
882
                                        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
882
  return intersect(F, F.intersect(Head, Second), Tail...);
1153
882
}
1154
1155
template <class SecondTy, class... RestTy>
1156
[[nodiscard]] inline RangeSet intersect(RangeSet::Factory &F, RangeSet Head,
1157
20.4k
                                        SecondTy Second, RestTy... Tail) {
1158
20.4k
  if (Second) {
1159
    // Here we call the <RangeSet,RangeSet,...> version of the function...
1160
1.68k
    return intersect(F, Head, *Second, Tail...);
1161
1.68k
  }
1162
  // ...and here it is either <RangeSet,RangeSet,...> or <RangeSet,...>, which
1163
  // means that the result is definitely RangeSet.
1164
18.7k
  return intersect(F, Head, Tail...);
1165
20.4k
}
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::intersect<std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet>(clang::ento::RangeSet::Factory&, clang::ento::RangeSet, std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet)
Line
Count
Source
1157
726
                                        SecondTy Second, RestTy... Tail) {
1158
726
  if (Second) {
1159
    // Here we call the <RangeSet,RangeSet,...> version of the function...
1160
0
    return intersect(F, Head, *Second, Tail...);
1161
0
  }
1162
  // ...and here it is either <RangeSet,RangeSet,...> or <RangeSet,...>, which
1163
  // means that the result is definitely RangeSet.
1164
726
  return intersect(F, Head, Tail...);
1165
726
}
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::intersect<std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet>(clang::ento::RangeSet::Factory&, clang::ento::RangeSet, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet)
Line
Count
Source
1157
13.9k
                                        SecondTy Second, RestTy... Tail) {
1158
13.9k
  if (Second) {
1159
    // Here we call the <RangeSet,RangeSet,...> version of the function...
1160
882
    return intersect(F, Head, *Second, Tail...);
1161
882
  }
1162
  // ...and here it is either <RangeSet,RangeSet,...> or <RangeSet,...>, which
1163
  // means that the result is definitely RangeSet.
1164
13.0k
  return intersect(F, Head, Tail...);
1165
13.9k
}
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::intersect<clang::ento::RangeSet const*>(clang::ento::RangeSet::Factory&, clang::ento::RangeSet, clang::ento::RangeSet const*)
Line
Count
Source
1157
5.76k
                                        SecondTy Second, RestTy... Tail) {
1158
5.76k
  if (Second) {
1159
    // Here we call the <RangeSet,RangeSet,...> version of the function...
1160
805
    return intersect(F, Head, *Second, Tail...);
1161
805
  }
1162
  // ...and here it is either <RangeSet,RangeSet,...> or <RangeSet,...>, which
1163
  // means that the result is definitely RangeSet.
1164
4.96k
  return intersect(F, Head, Tail...);
1165
5.76k
}
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>.
1188
template <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
1.32M
              RestTy... Tail) {
1193
1.32M
  if (Head) {
1194
281k
    return intersect(F, *Head, Second, Tail...);
1195
281k
  }
1196
1.04M
  return intersect(F, Second, Tail...);
1197
1.32M
}
RangeConstraintManager.cpp:(anonymous namespace)::IntersectionTraits<clang::ento::RangeSet const*, clang::ento::RangeSet>::Type (anonymous namespace)::intersect<clang::ento::RangeSet const*, clang::ento::RangeSet>(clang::ento::RangeSet::Factory&, clang::ento::RangeSet const*, clang::ento::RangeSet)
Line
Count
Source
1192
778k
              RestTy... Tail) {
1193
778k
  if (Head) {
1194
259k
    return intersect(F, *Head, Second, Tail...);
1195
259k
  }
1196
519k
  return intersect(F, Second, Tail...);
1197
778k
}
RangeConstraintManager.cpp:(anonymous namespace)::IntersectionTraits<std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet>::Type (anonymous namespace)::intersect<std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet>(clang::ento::RangeSet::Factory&, std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet)
Line
Count
Source
1192
185k
              RestTy... Tail) {
1193
185k
  if (Head) {
1194
726
    return intersect(F, *Head, Second, Tail...);
1195
726
  }
1196
184k
  return intersect(F, Second, Tail...);
1197
185k
}
RangeConstraintManager.cpp:(anonymous namespace)::IntersectionTraits<std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet>::Type (anonymous namespace)::intersect<std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet>(clang::ento::RangeSet::Factory&, std::__1::optional<clang::ento::RangeSet>, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet)
Line
Count
Source
1192
184k
              RestTy... Tail) {
1193
184k
  if (Head) {
1194
13.2k
    return intersect(F, *Head, Second, Tail...);
1195
13.2k
  }
1196
171k
  return intersect(F, Second, Tail...);
1197
184k
}
RangeConstraintManager.cpp:(anonymous namespace)::IntersectionTraits<std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet>::Type (anonymous namespace)::intersect<std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet>(clang::ento::RangeSet::Factory&, std::__1::optional<clang::ento::RangeSet>, clang::ento::RangeSet)
Line
Count
Source
1192
171k
              RestTy... Tail) {
1193
171k
  if (Head) {
1194
1.83k
    return intersect(F, *Head, Second, Tail...);
1195
1.83k
  }
1196
169k
  return intersect(F, Second, Tail...);
1197
171k
}
RangeConstraintManager.cpp:(anonymous namespace)::IntersectionTraits<clang::ento::RangeSet const*, clang::ento::RangeSet const*>::Type (anonymous namespace)::intersect<clang::ento::RangeSet const*, clang::ento::RangeSet const*>(clang::ento::RangeSet::Factory&, clang::ento::RangeSet const*, clang::ento::RangeSet const*)
Line
Count
Source
1192
6.24k
              RestTy... Tail) {
1193
6.24k
  if (Head) {
1194
5.76k
    return intersect(F, *Head, Second, Tail...);
1195
5.76k
  }
1196
477
  return intersect(F, Second, Tail...);
1197
6.24k
}
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.
1208
class SymbolicRangeInferrer
1209
    : public SymExprVisitor<SymbolicRangeInferrer, RangeSet> {
1210
public:
1211
  template <class SourceType>
1212
  static RangeSet inferRange(RangeSet::Factory &F, ProgramStateRef State,
1213
291k
                             SourceType Origin) {
1214
291k
    SymbolicRangeInferrer Inferrer(F, State);
1215
291k
    return Inferrer.infer(Origin);
1216
291k
  }
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::SymbolicRangeInferrer::inferRange<clang::ento::SymExpr const*>(clang::ento::RangeSet::Factory&, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, clang::ento::SymExpr const*)
Line
Count
Source
1213
291k
                             SourceType Origin) {
1214
291k
    SymbolicRangeInferrer Inferrer(F, State);
1215
291k
    return Inferrer.infer(Origin);
1216
291k
  }
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::SymbolicRangeInferrer::inferRange<(anonymous namespace)::EquivalenceClass>(clang::ento::RangeSet::Factory&, llvm::IntrusiveRefCntPtr<clang::ento::ProgramState const>, (anonymous namespace)::EquivalenceClass)
Line
Count
Source
1213
216
                             SourceType Origin) {
1214
216
    SymbolicRangeInferrer Inferrer(F, State);
1215
216
    return Inferrer.infer(Origin);
1216
216
  }
1217
1218
476k
  RangeSet VisitSymExpr(SymbolRef Sym) {
1219
476k
    if (std::optional<RangeSet> RS = getRangeForNegatedSym(Sym))
1220
8
      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
476k
    return infer(Sym->getType());
1226
476k
  }
1227
1228
57
  RangeSet VisitUnarySymExpr(const UnarySymExpr *USE) {
1229
57
    if (std::optional<RangeSet> RS = getRangeForNegatedUnarySym(USE))
1230
29
      return *RS;
1231
28
    return infer(USE->getType());
1232
57
  }
1233
1234
106k
  RangeSet VisitSymIntExpr(const SymIntExpr *Sym) {
1235
106k
    return VisitBinaryOperator(Sym);
1236
106k
  }
1237
1238
9.78k
  RangeSet VisitIntSymExpr(const IntSymExpr *Sym) {
1239
9.78k
    return VisitBinaryOperator(Sym);
1240
9.78k
  }
1241
1242
185k
  RangeSet VisitSymSymExpr(const SymSymExpr *SSE) {
1243
185k
    return intersect(
1244
185k
        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
185k
        getRangeForNegatedSymSym(SSE),
1252
        // If Sym is a comparison expression (except <=>),
1253
        // find any other comparisons with the same operands.
1254
        // See function description.
1255
185k
        getRangeForComparisonSymbol(SSE),
1256
        // If Sym is (dis)equality, we might have some information
1257
        // on that in our equality classes data structure.
1258
185k
        getRangeForEqualities(SSE),
1259
        // And we should always check what we can get from the operands.
1260
185k
        VisitBinaryOperator(SSE));
1261
185k
  }
1262
1263
private:
1264
  SymbolicRangeInferrer(RangeSet::Factory &F, ProgramStateRef S)
1265
291k
      : ValueFactory(F.getValueFactory()), RangeFactory(F), State(S) {}
1266
1267
  /// Infer range information from the given integer constant.
1268
  ///
1269
  /// It's not a real "inference", but is here for operating with
1270
  /// sub-expressions in a more polymorphic manner.
1271
116k
  RangeSet inferAs(const llvm::APSInt &Val, QualType) {
1272
116k
    return {RangeFactory, Val};
1273
116k
  }
1274
1275
  /// Infer range information from symbol in the context of the given type.
1276
487k
  RangeSet inferAs(SymbolRef Sym, QualType DestType) {
1277
487k
    QualType ActualType = Sym->getType();
1278
    // Check that we can reason about the symbol at all.
1279
487k
    if (ActualType->isIntegralOrEnumerationType() ||
1280
487k
        
Loc::isLocType(ActualType)2.24k
) {
1281
487k
      return infer(Sym);
1282
487k
    }
1283
    // Otherwise, let's simply infer from the destination type.
1284
    // We couldn't figure out nothing else about that expression.
1285
4
    return infer(DestType);
1286
487k
  }
1287
1288
778k
  RangeSet infer(SymbolRef Sym) {
1289
778k
    return intersect(RangeFactory,
1290
                     // Of course, we should take the constraint directly
1291
                     // associated with this symbol into consideration.
1292
778k
                     getConstraint(State, Sym),
1293
                     // Apart from the Sym itself, we can infer quite a lot if
1294
                     // we look into subexpressions of Sym.
1295
778k
                     Visit(Sym));
1296
778k
  }
1297
1298
216
  RangeSet infer(EquivalenceClass Class) {
1299
216
    if (const RangeSet *AssociatedConstraint = getConstraint(State, Class))
1300
32
      return *AssociatedConstraint;
1301
1302
184
    return infer(Class.getType());
1303
216
  }
1304
1305
  /// Infer range information solely from the type.
1306
757k
  RangeSet infer(QualType T) {
1307
    // Lazily generate a new RangeSet representing all possible values for the
1308
    // given symbol type.
1309
757k
    RangeSet Result(RangeFactory, ValueFactory.getMinValue(T),
1310
757k
                    ValueFactory.getMaxValue(T));
1311
1312
    // References are known to be non-zero.
1313
757k
    if (T->isReferenceType())
1314
54
      return assumeNonZero(Result, T);
1315
1316
757k
    return Result;
1317
757k
  }
1318
1319
  template <class BinarySymExprTy>
1320
301k
  RangeSet VisitBinaryOperator(const BinarySymExprTy *Sym) {
1321
    // TODO #1: VisitBinaryOperator implementation might not make a good
1322
    // use of the inferred ranges.  In this case, we might be calculating
1323
    // everything for nothing.  This being said, we should introduce some
1324
    // sort of laziness mechanism here.
1325
    //
1326
    // TODO #2: We didn't go into the nested expressions before, so it
1327
    // might cause us spending much more time doing the inference.
1328
    // This can be a problem for deeply nested expressions that are
1329
    // involved in conditions and get tested continuously.  We definitely
1330
    // need to address this issue and introduce some sort of caching
1331
    // in here.
1332
301k
    QualType ResultType = Sym->getType();
1333
301k
    return VisitBinaryOperator(inferAs(Sym->getLHS(), ResultType),
1334
301k
                               Sym->getOpcode(),
1335
301k
                               inferAs(Sym->getRHS(), ResultType), ResultType);
1336
301k
  }
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::SymbolicRangeInferrer::VisitBinaryOperator<clang::ento::BinarySymExprImpl<llvm::APSInt const&, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)1> >(clang::ento::BinarySymExprImpl<llvm::APSInt const&, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)1> const*)
Line
Count
Source
1320
9.78k
  RangeSet VisitBinaryOperator(const BinarySymExprTy *Sym) {
1321
    // TODO #1: VisitBinaryOperator implementation might not make a good
1322
    // use of the inferred ranges.  In this case, we might be calculating
1323
    // everything for nothing.  This being said, we should introduce some
1324
    // sort of laziness mechanism here.
1325
    //
1326
    // TODO #2: We didn't go into the nested expressions before, so it
1327
    // might cause us spending much more time doing the inference.
1328
    // This can be a problem for deeply nested expressions that are
1329
    // involved in conditions and get tested continuously.  We definitely
1330
    // need to address this issue and introduce some sort of caching
1331
    // in here.
1332
9.78k
    QualType ResultType = Sym->getType();
1333
9.78k
    return VisitBinaryOperator(inferAs(Sym->getLHS(), ResultType),
1334
9.78k
                               Sym->getOpcode(),
1335
9.78k
                               inferAs(Sym->getRHS(), ResultType), ResultType);
1336
9.78k
  }
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::SymbolicRangeInferrer::VisitBinaryOperator<clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, llvm::APSInt const&, (clang::ento::SymExpr::Kind)2> >(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, llvm::APSInt const&, (clang::ento::SymExpr::Kind)2> const*)
Line
Count
Source
1320
106k
  RangeSet VisitBinaryOperator(const BinarySymExprTy *Sym) {
1321
    // TODO #1: VisitBinaryOperator implementation might not make a good
1322
    // use of the inferred ranges.  In this case, we might be calculating
1323
    // everything for nothing.  This being said, we should introduce some
1324
    // sort of laziness mechanism here.
1325
    //
1326
    // TODO #2: We didn't go into the nested expressions before, so it
1327
    // might cause us spending much more time doing the inference.
1328
    // This can be a problem for deeply nested expressions that are
1329
    // involved in conditions and get tested continuously.  We definitely
1330
    // need to address this issue and introduce some sort of caching
1331
    // in here.
1332
106k
    QualType ResultType = Sym->getType();
1333
106k
    return VisitBinaryOperator(inferAs(Sym->getLHS(), ResultType),
1334
106k
                               Sym->getOpcode(),
1335
106k
                               inferAs(Sym->getRHS(), ResultType), ResultType);
1336
106k
  }
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::SymbolicRangeInferrer::VisitBinaryOperator<clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)3> >(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)3> const*)
Line
Count
Source
1320
185k
  RangeSet VisitBinaryOperator(const BinarySymExprTy *Sym) {
1321
    // TODO #1: VisitBinaryOperator implementation might not make a good
1322
    // use of the inferred ranges.  In this case, we might be calculating
1323
    // everything for nothing.  This being said, we should introduce some
1324
    // sort of laziness mechanism here.
1325
    //
1326
    // TODO #2: We didn't go into the nested expressions before, so it
1327
    // might cause us spending much more time doing the inference.
1328
    // This can be a problem for deeply nested expressions that are
1329
    // involved in conditions and get tested continuously.  We definitely
1330
    // need to address this issue and introduce some sort of caching
1331
    // in here.
1332
185k
    QualType ResultType = Sym->getType();
1333
185k
    return VisitBinaryOperator(inferAs(Sym->getLHS(), ResultType),
1334
185k
                               Sym->getOpcode(),
1335
185k
                               inferAs(Sym->getRHS(), ResultType), ResultType);
1336
185k
  }
1337
1338
  RangeSet VisitBinaryOperator(RangeSet LHS, BinaryOperator::Opcode Op,
1339
                               RangeSet RHS, QualType T);
1340
1341
  //===----------------------------------------------------------------------===//
1342
  //                         Ranges and operators
1343
  //===----------------------------------------------------------------------===//
1344
1345
  /// Return a rough approximation of the given range set.
1346
  ///
1347
  /// For the range set:
1348
  ///   { [x_0, y_0], [x_1, y_1], ... , [x_N, y_N] }
1349
  /// it will return the range [x_0, y_N].
1350
74.6k
  static Range fillGaps(RangeSet Origin) {
1351
74.6k
    assert(!Origin.isEmpty());
1352
74.6k
    return {Origin.getMinValue(), Origin.getMaxValue()};
1353
74.6k
  }
1354
1355
  /// Try to convert given range into the given type.
1356
  ///
1357
  /// It will return std::nullopt only when the trivial conversion is possible.
1358
74.6k
  std::optional<Range> convert(const Range &Origin, APSIntType To) {
1359
74.6k
    if (To.testInRange(Origin.From(), false) != APSIntType::RTR_Within ||
1360
74.6k
        
To.testInRange(Origin.To(), false) != APSIntType::RTR_Within74.6k
) {
1361
42
      return std::nullopt;
1362
42
    }
1363
74.6k
    return Range(ValueFactory.Convert(To, Origin.From()),
1364
74.6k
                 ValueFactory.Convert(To, Origin.To()));
1365
74.6k
  }
1366
1367
  template <BinaryOperator::Opcode Op>
1368
37.3k
  RangeSet VisitBinaryOperator(RangeSet LHS, RangeSet RHS, QualType T) {
1369
37.3k
    assert(!LHS.isEmpty() && !RHS.isEmpty());
1370
1371
37.3k
    Range CoarseLHS = fillGaps(LHS);
1372
37.3k
    Range CoarseRHS = fillGaps(RHS);
1373
1374
37.3k
    APSIntType ResultType = ValueFactory.getAPSIntType(T);
1375
1376
    // We need to convert ranges to the resulting type, so we can compare values
1377
    // and combine them in a meaningful (in terms of the given operation) way.
1378
37.3k
    auto ConvertedCoarseLHS = convert(CoarseLHS, ResultType);
1379
37.3k
    auto ConvertedCoarseRHS = convert(CoarseRHS, ResultType);
1380
1381
    // It is hard to reason about ranges when conversion changes
1382
    // borders of the ranges.
1383
37.3k
    if (!ConvertedCoarseLHS || 
!ConvertedCoarseRHS37.3k
) {
1384
42
      return infer(T);
1385
42
    }
1386
1387
37.3k
    return VisitBinaryOperator<Op>(*ConvertedCoarseLHS, *ConvertedCoarseRHS, T);
1388
37.3k
  }
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::SymbolicRangeInferrer::VisitBinaryOperator<(clang::BinaryOperatorKind)18>(clang::ento::RangeSet, clang::ento::RangeSet, clang::QualType)
Line
Count
Source
1368
134
  RangeSet VisitBinaryOperator(RangeSet LHS, RangeSet RHS, QualType T) {
1369
134
    assert(!LHS.isEmpty() && !RHS.isEmpty());
1370
1371
134
    Range CoarseLHS = fillGaps(LHS);
1372
134
    Range CoarseRHS = fillGaps(RHS);
1373
1374
134
    APSIntType ResultType = ValueFactory.getAPSIntType(T);
1375
1376
    // We need to convert ranges to the resulting type, so we can compare values
1377
    // and combine them in a meaningful (in terms of the given operation) way.
1378
134
    auto ConvertedCoarseLHS = convert(CoarseLHS, ResultType);
1379
134
    auto ConvertedCoarseRHS = convert(CoarseRHS, ResultType);
1380
1381
    // It is hard to reason about ranges when conversion changes
1382
    // borders of the ranges.
1383
134
    if (!ConvertedCoarseLHS || !ConvertedCoarseRHS) {
1384
0
      return infer(T);
1385
0
    }
1386
1387
134
    return VisitBinaryOperator<Op>(*ConvertedCoarseLHS, *ConvertedCoarseRHS, T);
1388
134
  }
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::SymbolicRangeInferrer::VisitBinaryOperator<(clang::BinaryOperatorKind)16>(clang::ento::RangeSet, clang::ento::RangeSet, clang::QualType)
Line
Count
Source
1368
36.9k
  RangeSet VisitBinaryOperator(RangeSet LHS, RangeSet RHS, QualType T) {
1369
36.9k
    assert(!LHS.isEmpty() && !RHS.isEmpty());
1370
1371
36.9k
    Range CoarseLHS = fillGaps(LHS);
1372
36.9k
    Range CoarseRHS = fillGaps(RHS);
1373
1374
36.9k
    APSIntType ResultType = ValueFactory.getAPSIntType(T);
1375
1376
    // We need to convert ranges to the resulting type, so we can compare values
1377
    // and combine them in a meaningful (in terms of the given operation) way.
1378
36.9k
    auto ConvertedCoarseLHS = convert(CoarseLHS, ResultType);
1379
36.9k
    auto ConvertedCoarseRHS = convert(CoarseRHS, ResultType);
1380
1381
    // It is hard to reason about ranges when conversion changes
1382
    // borders of the ranges.
1383
36.9k
    if (!ConvertedCoarseLHS || !ConvertedCoarseRHS) {
1384
6
      return infer(T);
1385
6
    }
1386
1387
36.9k
    return VisitBinaryOperator<Op>(*ConvertedCoarseLHS, *ConvertedCoarseRHS, T);
1388
36.9k
  }
RangeConstraintManager.cpp:clang::ento::RangeSet (anonymous namespace)::SymbolicRangeInferrer::VisitBinaryOperator<(clang::BinaryOperatorKind)4>(clang::ento::RangeSet, clang::ento::RangeSet, clang::QualType)
Line
Count
Source
1368
291
  RangeSet VisitBinaryOperator(RangeSet LHS, RangeSet RHS, QualType T) {
1369
291
    assert(!LHS.isEmpty() && !RHS.isEmpty());
1370
1371
291
    Range CoarseLHS = fillGaps(LHS);
1372
291
    Range CoarseRHS = fillGaps(RHS);
1373
1374
291
    APSIntType ResultType = ValueFactory.getAPSIntType(T);
1375
1376
    // We need to convert ranges to the resulting type, so we can compare values
1377
    // and combine them in a meaningful (in terms of the given operation) way.
1378
291
    auto ConvertedCoarseLHS = convert(CoarseLHS, ResultType);
1379
291
    auto ConvertedCoarseRHS = convert(CoarseRHS, ResultType);
1380
1381
    // It is hard to reason about ranges when conversion changes
1382
    // borders of the ranges.
1383
291
    if (!ConvertedCoarseLHS || 
!ConvertedCoarseRHS273
) {
1384
36
      return infer(T);
1385
36
    }
1386
1387
255
    return VisitBinaryOperator<Op>(*ConvertedCoarseLHS, *ConvertedCoarseRHS, T);
1388
291
  }
1389
1390
  template <BinaryOperator::Opcode Op>
1391
  RangeSet VisitBinaryOperator(Range LHS, Range RHS, QualType T) {
1392
    return infer(T);
1393
  }
1394
1395
  /// Return a symmetrical range for the given range and type.
1396
  ///
1397
  /// If T is signed, return the smallest range [-x..x] that covers the original
1398
  /// range, or [-min(T), max(T)] if the aforementioned symmetric range doesn't
1399
  /// exist due to original range covering min(T)).
1400
  ///
1401
  /// If T is unsigned, return the smallest range [0..x] that covers the
1402
  /// original range.
1403
255
  Range getSymmetricalRange(Range Origin, QualType T) {
1404
255
    APSIntType RangeType = ValueFactory.getAPSIntType(T);
1405
1406
255
    if (RangeType.isUnsigned()) {
1407
64
      return Range(ValueFactory.getMinValue(RangeType), Origin.To());
1408
64
    }
1409
1410
191
    if (Origin.From().isMinSignedValue()) {
1411
      // If mini is a minimal signed value, absolute value of it is greater
1412
      // than the maximal signed value.  In order to avoid these
1413
      // complications, we simply return the whole range.
1414
33
      return {ValueFactory.getMinValue(RangeType),
1415
33
              ValueFactory.getMaxValue(RangeType)};
1416
33
    }
1417
1418
    // At this point, we are sure that the type is signed and we can safely
1419
    // use unary - operator.
1420
    //
1421
    // While calculating absolute maximum, we can use the following formula
1422
    // because of these reasons:
1423
    //   * If From >= 0 then To >= From and To >= -From.
1424
    //     AbsMax == To == max(To, -From)
1425
    //   * If To <= 0 then -From >= -To and -From >= From.
1426
    //     AbsMax == -From == max(-From, To)
1427
    //   * Otherwise, From <= 0, To >= 0, and
1428
    //     AbsMax == max(abs(From), abs(To))
1429
158
    llvm::APSInt AbsMax = std::max(-Origin.From(), Origin.To());
1430
1431
    // Intersection is guaranteed to be non-empty.
1432
158
    return {ValueFactory.getValue(-AbsMax), ValueFactory.getValue(AbsMax)};
1433
191
  }
1434
1435
  /// Return a range set subtracting zero from \p Domain.
1436
15.1k
  RangeSet assumeNonZero(RangeSet Domain, QualType T) {
1437
15.1k
    APSIntType IntType = ValueFactory.getAPSIntType(T);
1438
15.1k
    return RangeFactory.deletePoint(Domain, IntType.getZeroValue());
1439
15.1k
  }
1440
1441
  template <typename ProduceNegatedSymFunc>
1442
  std::optional<RangeSet> getRangeForNegatedExpr(ProduceNegatedSymFunc F,
1443
662k
                                                 QualType T) {
1444
    // Do not negate if the type cannot be meaningfully negated.
1445
662k
    if (!T->isUnsignedIntegerOrEnumerationType() &&
1446
662k
        
!T->isSignedIntegerOrEnumerationType()602k
)
1447
120k
      return std::nullopt;
1448
1449
542k
    if (SymbolRef NegatedSym = F())
1450
387k
      if (const RangeSet *NegatedRange = getConstraint(State, NegatedSym))
1451
763
        return RangeFactory.negate(*NegatedRange);
1452
1453
541k
    return std::nullopt;
1454
542k
  }
RangeConstraintManager.cpp:std::__1::optional<clang::ento::RangeSet> (anonymous namespace)::SymbolicRangeInferrer::getRangeForNegatedExpr<(anonymous namespace)::SymbolicRangeInferrer::getRangeForNegatedUnarySym(clang::ento::UnarySymExpr const*)::'lambda'()>((anonymous namespace)::SymbolicRangeInferrer::getRangeForNegatedUnarySym(clang::ento::UnarySymExpr const*)::'lambda'(), clang::QualType)
Line
Count
Source
1443
57
                                                 QualType T) {
1444
    // Do not negate if the type cannot be meaningfully negated.
1445
57
    if (!T->isUnsignedIntegerOrEnumerationType() &&
1446
57
        
!T->isSignedIntegerOrEnumerationType()54
)
1447
0
      return std::nullopt;
1448
1449
57
    if (SymbolRef NegatedSym = F())
1450
41
      if (const RangeSet *NegatedRange = getConstraint(State, NegatedSym))
1451
29
        return RangeFactory.negate(*NegatedRange);
1452
1453
28
    return std::nullopt;
1454
57
  }
RangeConstraintManager.cpp:std::__1::optional<clang::ento::RangeSet> (anonymous namespace)::SymbolicRangeInferrer::getRangeForNegatedExpr<(anonymous namespace)::SymbolicRangeInferrer::getRangeForNegatedSymSym(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)3> const*)::'lambda'()>((anonymous namespace)::SymbolicRangeInferrer::getRangeForNegatedSymSym(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)3> const*)::'lambda'(), clang::QualType)
Line
Count
Source
1443
185k
                                                 QualType T) {
1444
    // Do not negate if the type cannot be meaningfully negated.
1445
185k
    if (!T->isUnsignedIntegerOrEnumerationType() &&
1446
185k
        
!T->isSignedIntegerOrEnumerationType()175k
)
1447
0
      return std::nullopt;
1448
1449
185k
    if (SymbolRef NegatedSym = F())
1450
30.6k
      if (const RangeSet *NegatedRange = getConstraint(State, NegatedSym))
1451
726
        return RangeFactory.negate(*NegatedRange);
1452
1453
184k
    return std::nullopt;
1454
185k
  }
RangeConstraintManager.cpp:std::__1::optional<clang::ento::RangeSet> (anonymous namespace)::SymbolicRangeInferrer::getRangeForNegatedExpr<(anonymous namespace)::SymbolicRangeInferrer::getRangeForNegatedSym(clang::ento::SymExpr const*)::'lambda'()>((anonymous namespace)::SymbolicRangeInferrer::getRangeForNegatedSym(clang::ento::SymExpr const*)::'lambda'(), clang::QualType)
Line
Count
Source
1443
476k
                                                 QualType T) {
1444
    // Do not negate if the type cannot be meaningfully negated.
1445
476k
    if (!T->isUnsignedIntegerOrEnumerationType() &&
1446
476k
        
!T->isSignedIntegerOrEnumerationType()426k
)
1447
120k
      return std::nullopt;
1448
1449
356k
    if (SymbolRef NegatedSym = F())
1450
356k
      if (const RangeSet *NegatedRange = getConstraint(State, NegatedSym))
1451
8
        return RangeFactory.negate(*NegatedRange);
1452
1453
356k
    return std::nullopt;
1454
356k
  }
1455
1456
57
  std::optional<RangeSet> getRangeForNegatedUnarySym(const UnarySymExpr *USE) {
1457
    // Just get the operand when we negate a symbol that is already negated.
1458
    // -(-a) == a
1459
57
    return getRangeForNegatedExpr(
1460
57
        [USE]() -> SymbolRef {
1461
57
          if (USE->getOpcode() == UO_Minus)
1462
41
            return USE->getOperand();
1463
16
          return nullptr;
1464
57
        },
1465
57
        USE->getType());
1466
57
  }
1467
1468
185k
  std::optional<RangeSet> getRangeForNegatedSymSym(const SymSymExpr *SSE) {
1469
185k
    return getRangeForNegatedExpr(
1470
185k
        [SSE, State = this->State]() -> SymbolRef {
1471
185k
          if (SSE->getOpcode() == BO_Sub)
1472
30.6k
            return State->getSymbolManager().getSymSymExpr(
1473
30.6k
                SSE->getRHS(), BO_Sub, SSE->getLHS(), SSE->getType());
1474
154k
          return nullptr;
1475
185k
        },
1476
185k
        SSE->getType());
1477
185k
  }
1478
1479
476k
  std::optional<RangeSet> getRangeForNegatedSym(SymbolRef Sym) {
1480
476k
    return getRangeForNegatedExpr(
1481
476k
        [Sym, State = this->State]() {
1482
356k
          return State->getSymbolManager().getUnarySymExpr(Sym, UO_Minus,
1483
356k
                                                           Sym->getType());
1484
356k
        },
1485
476k
        Sym->getType());
1486
476k
  }
1487
1488
  // Returns ranges only for binary comparison operators (except <=>)
1489
  // when left and right operands are symbolic values.
1490
  // Finds any other comparisons with the same operands.
1491
  // Then do logical calculations and refuse impossible branches.
1492
  // E.g. (x < y) and (x > y) at the same time are impossible.
1493
  // E.g. (x >= y) and (x != y) at the same time makes (x > y) true only.
1494
  // E.g. (x == y) and (y == x) are just reversed but the same.
1495
  // It covers all possible combinations (see CmpOpTable description).
1496
  // Note that `x` and `y` can also stand for subexpressions,
1497
  // not only for actual symbols.
1498
185k
  std::optional<RangeSet> getRangeForComparisonSymbol(const SymSymExpr *SSE) {
1499
185k
    const BinaryOperatorKind CurrentOP = SSE->getOpcode();
1500
1501
    // We currently do not support <=> (C++20).
1502
185k
    if (!BinaryOperator::isComparisonOp(CurrentOP) || 
(CurrentOP == BO_Cmp)30.8k
)
1503
154k
      return std::nullopt;
1504
1505
30.8k
    static const OperatorRelationsTable CmpOpTable{};
1506
1507
30.8k
    const SymExpr *LHS = SSE->getLHS();
1508
30.8k
    const SymExpr *RHS = SSE->getRHS();
1509
30.8k
    QualType T = SSE->getType();
1510
1511
30.8k
    SymbolManager &SymMgr = State->getSymbolManager();
1512
1513
    // We use this variable to store the last queried operator (`QueriedOP`)
1514
    // for which the `getCmpOpState` returned with `Unknown`. If there are two
1515
    // different OPs that returned `Unknown` then we have to query the special
1516
    // `UnknownX2` column. We assume that `getCmpOpState(CurrentOP, CurrentOP)`
1517
    // never returns `Unknown`, so `CurrentOP` is a good initial value.
1518
30.8k
    BinaryOperatorKind LastQueriedOpToUnknown = CurrentOP;
1519
1520
    // Loop goes through all of the columns exept the last one ('UnknownX2').
1521
    // We treat `UnknownX2` column separately at the end of the loop body.
1522
138k
    for (size_t i = 0; i < CmpOpTable.getCmpOpCount(); 
++i107k
) {
1523
1524
      // Let's find an expression e.g. (x < y).
1525
120k
      BinaryOperatorKind QueriedOP = OperatorRelationsTable::getOpFromIndex(i);
1526
120k
      const SymSymExpr *SymSym = SymMgr.getSymSymExpr(LHS, QueriedOP, RHS, T);
1527
120k
      const RangeSet *QueriedRangeSet = getConstraint(State, SymSym);
1528
1529
      // If ranges were not previously found,
1530
      // try to find a reversed expression (y > x).
1531
120k
      if (!QueriedRangeSet) {
1532
106k
        const BinaryOperatorKind ROP =
1533
106k
            BinaryOperator::reverseComparisonOp(QueriedOP);
1534
106k
        SymSym = SymMgr.getSymSymExpr(RHS, ROP, LHS, T);
1535
106k
        QueriedRangeSet = getConstraint(State, SymSym);
1536
106k
      }
1537
1538
120k
      if (!QueriedRangeSet || 
QueriedRangeSet->isEmpty()13.5k
)
1539
106k
        continue;
1540
1541
13.5k
      const llvm::APSInt *ConcreteValue = QueriedRangeSet->getConcreteValue();
1542
13.5k
      const bool isInFalseBranch =
1543
13.5k
          ConcreteValue ? 
(*ConcreteValue == 0)900
:
false12.6k
;
1544
1545
      // If it is a false branch, we shall be guided by opposite operator,
1546
      // because the table is made assuming we are in the true branch.
1547
      // E.g. when (x <= y) is false, then (x > y) is true.
1548
13.5k
      if (isInFalseBranch)
1549
624
        QueriedOP = BinaryOperator::negateComparisonOp(QueriedOP);
1550
1551
13.5k
      OperatorRelationsTable::TriStateKind BranchState =
1552
13.5k
          CmpOpTable.getCmpOpState(CurrentOP, QueriedOP);
1553
1554
13.5k
      if (BranchState == OperatorRelationsTable::Unknown) {
1555
364
        if (LastQueriedOpToUnknown != CurrentOP &&
1556
364
            
LastQueriedOpToUnknown != QueriedOP68
) {
1557
          // If we got the Unknown state for both different operators.
1558
          // if (x <= y)    // assume true
1559
          //   if (x != y)  // assume true
1560
          //     if (x < y) // would be also true
1561
          // Get a state from `UnknownX2` column.
1562
64
          BranchState = CmpOpTable.getCmpOpStateForUnknownX2(CurrentOP);
1563
300
        } else {
1564
300
          LastQueriedOpToUnknown = QueriedOP;
1565
300
          continue;
1566
300
        }
1567
364
      }
1568
1569
13.2k
      return (BranchState == OperatorRelationsTable::True) ? 
getTrueRange(T)12.7k
1570
13.2k
                                                           : 
getFalseRange(T)502
;
1571
13.5k
    }
1572
1573
17.6k
    return std::nullopt;
1574
30.8k
  }
1575
1576
185k
  std::optional<RangeSet> getRangeForEqualities(const SymSymExpr *Sym) {
1577
185k
    std::optional<bool> Equality = meansEquality(Sym);
1578
1579
185k
    if (!Equality)
1580
153k
      return std::nullopt;
1581
1582
32.0k
    if (std::optional<bool> AreEqual =
1583
32.0k
            EquivalenceClass::areEqual(State, Sym->getLHS(), Sym->getRHS())) {
1584
      // Here we cover two cases at once:
1585
      //   * if Sym is equality and its operands are known to be equal -> true
1586
      //   * if Sym is disequality and its operands are disequal -> true
1587
2.71k
      if (*AreEqual == *Equality) {
1588
2.20k
        return getTrueRange(Sym->getType());
1589
2.20k
      }
1590
      // Opposite combinations result in false.
1591
513
      return getFalseRange(Sym->getType());
1592
2.71k
    }
1593
1594
29.3k
    return std::nullopt;
1595
32.0k
  }
1596
1597
15.1k
  RangeSet getTrueRange(QualType T) {
1598
15.1k
    RangeSet TypeRange = infer(T);
1599
15.1k
    return assumeNonZero(TypeRange, T);
1600
15.1k
  }
1601
1602
1.01k
  RangeSet getFalseRange(QualType T) {
1603
1.01k
    const llvm::APSInt &Zero = ValueFactory.getValue(0, T);
1604
1.01k
    return RangeSet(RangeFactory, Zero);
1605
1.01k
  }
1606
1607
  BasicValueFactory &ValueFactory;
1608
  RangeSet::Factory &RangeFactory;
1609
  ProgramStateRef State;
1610
};
1611
1612
//===----------------------------------------------------------------------===//
1613
//               Range-based reasoning about symbolic operations
1614
//===----------------------------------------------------------------------===//
1615
1616
template <>
1617
RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_NE>(RangeSet LHS,
1618
                                                           RangeSet RHS,
1619
917
                                                           QualType T) {
1620
917
  assert(!LHS.isEmpty() && !RHS.isEmpty());
1621
1622
917
  if (LHS.getAPSIntType() == RHS.getAPSIntType()) {
1623
889
    if (intersect(RangeFactory, LHS, RHS).isEmpty())
1624
179
      return getTrueRange(T);
1625
1626
889
  } else {
1627
    // We can only lose information if we are casting smaller signed type to
1628
    // bigger unsigned type. For e.g.,
1629
    //    LHS (unsigned short): [2, USHRT_MAX]
1630
    //    RHS   (signed short): [SHRT_MIN, 0]
1631
    //
1632
    // Casting RHS to LHS type will leave us with overlapping values
1633
    //    CastedRHS : [0, 0] U [SHRT_MAX + 1, USHRT_MAX]
1634
    //
1635
    // We can avoid this by checking if signed type's maximum value is lesser
1636
    // than unsigned type's minimum value.
1637
1638
    // If both have different signs then only we can get more information.
1639
28
    if (LHS.isUnsigned() != RHS.isUnsigned()) {
1640
26
      if (LHS.isUnsigned() && 
(LHS.getBitWidth() >= RHS.getBitWidth())20
) {
1641
20
        if (RHS.getMaxValue().isNegative() ||
1642
20
            
LHS.getAPSIntType().convert(RHS.getMaxValue()) < LHS.getMinValue()10
)
1643
14
          return getTrueRange(T);
1644
1645
20
      } else 
if (6
RHS.isUnsigned()6
&&
(LHS.getBitWidth() <= RHS.getBitWidth())6
) {
1646
6
        if (LHS.getMaxValue().isNegative() ||
1647
6
            
RHS.getAPSIntType().convert(LHS.getMaxValue()) < RHS.getMinValue()4
)
1648
4
          return getTrueRange(T);
1649
6
      }
1650
26
    }
1651
1652
    // Both RangeSets should be casted to bigger unsigned type.
1653
10
    APSIntType CastingType(std::max(LHS.getBitWidth(), RHS.getBitWidth()),
1654
10
                           LHS.isUnsigned() || 
RHS.isUnsigned()4
);
1655
1656
10
    RangeSet CastedLHS = RangeFactory.castTo(LHS, CastingType);
1657
10
    RangeSet CastedRHS = RangeFactory.castTo(RHS, CastingType);
1658
1659
10
    if (intersect(RangeFactory, CastedLHS, CastedRHS).isEmpty())
1660
2
      return getTrueRange(T);
1661
10
  }
1662
1663
  // In all other cases, the resulting range cannot be deduced.
1664
718
  return infer(T);
1665
917
}
1666
1667
template <>
1668
RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Or>(Range LHS, Range RHS,
1669
134
                                                           QualType T) {
1670
134
  APSIntType ResultType = ValueFactory.getAPSIntType(T);
1671
134
  llvm::APSInt Zero = ResultType.getZeroValue();
1672
1673
134
  bool IsLHSPositiveOrZero = LHS.From() >= Zero;
1674
134
  bool IsRHSPositiveOrZero = RHS.From() >= Zero;
1675
1676
134
  bool IsLHSNegative = LHS.To() < Zero;
1677
134
  bool IsRHSNegative = RHS.To() < Zero;
1678
1679
  // Check if both ranges have the same sign.
1680
134
  if ((IsLHSPositiveOrZero && 
IsRHSPositiveOrZero84
) ||
1681
134
      
(50
IsLHSNegative50
&&
IsRHSNegative28
)) {
1682
    // The result is definitely greater or equal than any of the operands.
1683
104
    const llvm::APSInt &Min = std::max(LHS.From(), RHS.From());
1684
1685
    // We estimate maximal value for positives as the maximal value for the
1686
    // given type.  For negatives, we estimate it with -1 (e.g. 0x11111111).
1687
    //
1688
    // TODO: We basically, limit the resulting range from below, but don't do
1689
    //       anything with the upper bound.
1690
    //
1691
    //       For positive operands, it can be done as follows: for the upper
1692
    //       bound of LHS and RHS we calculate the most significant bit set.
1693
    //       Let's call it the N-th bit.  Then we can estimate the maximal
1694
    //       number to be 2^(N+1)-1, i.e. the number with all the bits up to
1695
    //       the N-th bit set.
1696
104
    const llvm::APSInt &Max = IsLHSNegative
1697
104
                                  ? 
ValueFactory.getValue(--Zero)20
1698
104
                                  : 
ValueFactory.getMaxValue(ResultType)84
;
1699
1700
104
    return {RangeFactory, ValueFactory.getValue(Min), Max};
1701
104
  }
1702
1703
  // Otherwise, let's check if at least one of the operands is negative.
1704
30
  if (IsLHSNegative || 
IsRHSNegative22
) {
1705
    // This means that the result is definitely negative as well.
1706
12
    return {RangeFactory, ValueFactory.getMinValue(ResultType),
1707
12
            ValueFactory.getValue(--Zero)};
1708
12
  }
1709
1710
18
  RangeSet DefaultRange = infer(T);
1711
1712
  // It is pretty hard to reason about operands with different signs
1713
  // (and especially with possibly different signs).  We simply check if it
1714
  // can be zero.  In order to conclude that the result could not be zero,
1715
  // at least one of the operands should be definitely not zero itself.
1716
18
  if (!LHS.Includes(Zero) || !RHS.Includes(Zero)) {
1717
16
    return assumeNonZero(DefaultRange, T);
1718
16
  }
1719
1720
  // Nothing much else to do here.
1721
2
  return DefaultRange;
1722
18
}
1723
1724
template <>
1725
RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_And>(Range LHS,
1726
                                                            Range RHS,
1727
36.9k
                                                            QualType T) {
1728
36.9k
  APSIntType ResultType = ValueFactory.getAPSIntType(T);
1729
36.9k
  llvm::APSInt Zero = ResultType.getZeroValue();
1730
1731
36.9k
  bool IsLHSPositiveOrZero = LHS.From() >= Zero;
1732
36.9k
  bool IsRHSPositiveOrZero = RHS.From() >= Zero;
1733
1734
36.9k
  bool IsLHSNegative = LHS.To() < Zero;
1735
36.9k
  bool IsRHSNegative = RHS.To() < Zero;
1736
1737
  // Check if both ranges have the same sign.
1738
36.9k
  if ((IsLHSPositiveOrZero && 
IsRHSPositiveOrZero73
) ||
1739
36.9k
      
(36.8k
IsLHSNegative36.8k
&&
IsRHSNegative12
)) {
1740
    // The result is definitely less or equal than any of the operands.
1741
65
    const llvm::APSInt &Max = std::min(LHS.To(), RHS.To());
1742
1743
    // We conservatively estimate lower bound to be the smallest positive
1744
    // or negative value corresponding to the sign of the operands.
1745
65
    const llvm::APSInt &Min = IsLHSNegative
1746
65
                                  ? 
ValueFactory.getMinValue(ResultType)10
1747
65
                                  : 
ValueFactory.getValue(Zero)55
;
1748
1749
65
    return {RangeFactory, Min, Max};
1750
65
  }
1751
1752
  // Otherwise, let's check if at least one of the operands is positive.
1753
36.8k
  if (IsLHSPositiveOrZero || 
IsRHSPositiveOrZero36.8k
) {
1754
    // This makes result definitely positive.
1755
    //
1756
    // We can also reason about a maximal value by finding the maximal
1757
    // value of the positive operand.
1758
36.0k
    const llvm::APSInt &Max = IsLHSPositiveOrZero ? 
LHS.To()18
:
RHS.To()36.0k
;
1759
1760
    // The minimal value on the other hand is much harder to reason about.
1761
    // The only thing we know for sure is that the result is positive.
1762
36.0k
    return {RangeFactory, ValueFactory.getValue(Zero),
1763
36.0k
            ValueFactory.getValue(Max)};
1764
36.0k
  }
1765
1766
  // Nothing much else to do here.
1767
788
  return infer(T);
1768
36.8k
}
1769
1770
template <>
1771
RangeSet SymbolicRangeInferrer::VisitBinaryOperator<BO_Rem>(Range LHS,
1772
                                                            Range RHS,
1773
255
                                                            QualType T) {
1774
255
  llvm::APSInt Zero = ValueFactory.getAPSIntType(T).getZeroValue();
1775
1776
255
  Range ConservativeRange = getSymmetricalRange(RHS, T);
1777
1778
255
  llvm::APSInt Max = ConservativeRange.To();
1779
255
  llvm::APSInt Min = ConservativeRange.From();
1780
1781
255
  if (Max == Zero) {
1782
    // It's an undefined behaviour to divide by 0 and it seems like we know
1783
    // for sure that RHS is 0.  Let's say that the resulting range is
1784
    // simply infeasible for that matter.
1785
0
    return RangeFactory.getEmptySet();
1786
0
  }
1787
1788
  // At this point, our conservative range is closed.  The result, however,
1789
  // couldn't be greater than the RHS' maximal absolute value.  Because of
1790
  // this reason, we turn the range into open (or half-open in case of
1791
  // unsigned integers).
1792
  //
1793
  // While we operate on integer values, an open interval (a, b) can be easily
1794
  // represented by the closed interval [a + 1, b - 1].  And this is exactly
1795
  // what we do next.
1796
  //
1797
  // If we are dealing with unsigned case, we shouldn't move the lower bound.
1798
255
  if (Min.isSigned()) {
1799
191
    ++Min;
1800
191
  }
1801
255
  --Max;
1802
1803
255
  bool IsLHSPositiveOrZero = LHS.From() >= Zero;
1804
255
  bool IsRHSPositiveOrZero = RHS.From() >= Zero;
1805
1806
  // Remainder operator results with negative operands is implementation
1807
  // defined.  Positive cases are much easier to reason about though.
1808
255
  if (IsLHSPositiveOrZero && 
IsRHSPositiveOrZero155
) {
1809
    // If maximal value of LHS is less than maximal value of RHS,
1810
    // the result won't get greater than LHS.To().
1811
114
    Max = std::min(LHS.To(), Max);
1812
    // We want to check if it is a situation similar to the following:
1813
    //
1814
    // <------------|---[  LHS  ]--------[  RHS  ]----->
1815
    //  -INF        0                              +INF
1816
    //
1817
    // In this situation, we can conclude that (LHS / RHS) == 0 and
1818
    // (LHS % RHS) == LHS.
1819
114
    Min = LHS.To() < RHS.From() ? 
LHS.From()14
:
Zero100
;
1820
114
  }
1821
1822
  // Nevertheless, the symmetrical range for RHS is a conservative estimate
1823
  // for any sign of either LHS, or RHS.
1824
255
  return {RangeFactory, ValueFactory.getValue(Min), ValueFactory.getValue(Max)};
1825
255
}
1826
1827
RangeSet SymbolicRangeInferrer::VisitBinaryOperator(RangeSet LHS,
1828
                                                    BinaryOperator::Opcode Op,
1829
301k
                                                    RangeSet RHS, QualType T) {
1830
  // We should propagate information about unfeasbility of one of the
1831
  // operands to the resulting range.
1832
301k
  if (LHS.isEmpty() || 
RHS.isEmpty()301k
) {
1833
2
    return RangeFactory.getEmptySet();
1834
2
  }
1835
1836
301k
  switch (Op) {
1837
917
  case BO_NE:
1838
917
    return VisitBinaryOperator<BO_NE>(LHS, RHS, T);
1839
134
  case BO_Or:
1840
134
    return VisitBinaryOperator<BO_Or>(LHS, RHS, T);
1841
36.9k
  case BO_And:
1842
36.9k
    return VisitBinaryOperator<BO_And>(LHS, RHS, T);
1843
291
  case BO_Rem:
1844
291
    return VisitBinaryOperator<BO_Rem>(LHS, RHS, T);
1845
263k
  default:
1846
263k
    return infer(T);
1847
301k
  }
1848
301k
}
1849
1850
//===----------------------------------------------------------------------===//
1851
//                  Constraint manager implementation details
1852
//===----------------------------------------------------------------------===//
1853
1854
class RangeConstraintManager : public RangedConstraintManager {
1855
public:
1856
  RangeConstraintManager(ExprEngine *EE, SValBuilder &SVB)
1857
16.2k
      : RangedConstraintManager(EE, SVB), F(getBasicVals()) {}
1858
1859
  //===------------------------------------------------------------------===//
1860
  // Implementation for interface from ConstraintManager.
1861
  //===------------------------------------------------------------------===//
1862
1863
  bool haveEqualConstraints(ProgramStateRef S1,
1864
12.1k
                            ProgramStateRef S2) const override {
1865
    // NOTE: ClassMembers are as simple as back pointers for ClassMap,
1866
    //       so comparing constraint ranges and class maps should be
1867
    //       sufficient.
1868
12.1k
    return S1->get<ConstraintRange>() == S2->get<ConstraintRange>() &&
1869
12.1k
           
S1->get<ClassMap>() == S2->get<ClassMap>()4.04k
;
1870
12.1k
  }
1871
1872
  bool canReasonAbout(SVal X) const override;
1873
1874
  ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override;
1875
1876
  const llvm::APSInt *getSymVal(ProgramStateRef State,
1877
                                SymbolRef Sym) const override;
1878
1879
  ProgramStateRef removeDeadBindings(ProgramStateRef State,
1880
                                     SymbolReaper &SymReaper) override;
1881
1882
  void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL = "\n",
1883
                 unsigned int Space = 0, bool IsDot = false) const override;
1884
  void printValue(raw_ostream &Out, ProgramStateRef State,
1885
                  SymbolRef Sym) override;
1886
  void printConstraints(raw_ostream &Out, ProgramStateRef State,
1887
                        const char *NL = "\n", unsigned int Space = 0,
1888
                        bool IsDot = false) const;
1889
  void printEquivalenceClasses(raw_ostream &Out, ProgramStateRef State,
1890
                               const char *NL = "\n", unsigned int Space = 0,
1891
                               bool IsDot = false) const;
1892
  void printDisequalities(raw_ostream &Out, ProgramStateRef State,
1893
                          const char *NL = "\n", unsigned int Space = 0,
1894
                          bool IsDot = false) const;
1895
1896
  //===------------------------------------------------------------------===//
1897
  // Implementation for interface from RangedConstraintManager.
1898
  //===------------------------------------------------------------------===//
1899
1900
  ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym,
1901
                              const llvm::APSInt &V,
1902
                              const llvm::APSInt &Adjustment) override;
1903
1904
  ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym,
1905
                              const llvm::APSInt &V,
1906
                              const llvm::APSInt &Adjustment) override;
1907
1908
  ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym,
1909
                              const llvm::APSInt &V,
1910
                              const llvm::APSInt &Adjustment) override;
1911
1912
  ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym,
1913
                              const llvm::APSInt &V,
1914
                              const llvm::APSInt &Adjustment) override;
1915
1916
  ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym,
1917
                              const llvm::APSInt &V,
1918
                              const llvm::APSInt &Adjustment) override;
1919
1920
  ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym,
1921
                              const llvm::APSInt &V,
1922
                              const llvm::APSInt &Adjustment) override;
1923
1924
  ProgramStateRef assumeSymWithinInclusiveRange(
1925
      ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
1926
      const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
1927
1928
  ProgramStateRef assumeSymOutsideInclusiveRange(
1929
      ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
1930
      const llvm::APSInt &To, const llvm::APSInt &Adjustment) override;
1931
1932
private:
1933
  RangeSet::Factory F;
1934
1935
  RangeSet getRange(ProgramStateRef State, SymbolRef Sym);
1936
  RangeSet getRange(ProgramStateRef State, EquivalenceClass Class);
1937
  ProgramStateRef setRange(ProgramStateRef State, SymbolRef Sym,
1938
                           RangeSet Range);
1939
  ProgramStateRef setRange(ProgramStateRef State, EquivalenceClass Class,
1940
                           RangeSet Range);
1941
1942
  RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym,
1943
                         const llvm::APSInt &Int,
1944
                         const llvm::APSInt &Adjustment);
1945
  RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym,
1946
                         const llvm::APSInt &Int,
1947
                         const llvm::APSInt &Adjustment);
1948
  RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym,
1949
                         const llvm::APSInt &Int,
1950
                         const llvm::APSInt &Adjustment);
1951
  RangeSet getSymLERange(llvm::function_ref<RangeSet()> RS,
1952
                         const llvm::APSInt &Int,
1953
                         const llvm::APSInt &Adjustment);
1954
  RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym,
1955
                         const llvm::APSInt &Int,
1956
                         const llvm::APSInt &Adjustment);
1957
};
1958
1959
//===----------------------------------------------------------------------===//
1960
//                         Constraint assignment logic
1961
//===----------------------------------------------------------------------===//
1962
1963
/// ConstraintAssignorBase is a small utility class that unifies visitor
1964
/// for ranges with a visitor for constraints (rangeset/range/constant).
1965
///
1966
/// It is designed to have one derived class, but generally it can have more.
1967
/// Derived class can control which types we handle by defining methods of the
1968
/// following form:
1969
///
1970
///   bool handle${SYMBOL}To${CONSTRAINT}(const SYMBOL *Sym,
1971
///                                       CONSTRAINT Constraint);
1972
///
1973
/// where SYMBOL is the type of the symbol (e.g. SymSymExpr, SymbolCast, etc.)
1974
///       CONSTRAINT is the type of constraint (RangeSet/Range/Const)
1975
///       return value signifies whether we should try other handle methods
1976
///          (i.e. false would mean to stop right after calling this method)
1977
template <class Derived> class ConstraintAssignorBase {
1978
public:
1979
  using Const = const llvm::APSInt &;
1980
1981
590k
#define DISPATCH(CLASS) return assign##CLASS##Impl(cast<CLASS>(Sym), Constraint)
1982
1983
#define ASSIGN(CLASS, TO, SYM, CONSTRAINT)                                     \
1984
1.37M
  if (!static_cast<Derived *>(this)->assign##CLASS##To##TO(SYM, CONSTRAINT))   \
1985
1.37M
  
return false818
1986
1987
217k
  void assign(SymbolRef Sym, RangeSet Constraint) {
1988
217k
    assignImpl(Sym, Constraint);
1989
217k
  }
1990
1991
217k
  bool assignImpl(SymbolRef Sym, RangeSet Constraint) {
1992
217k
    switch (Sym->getKind()) {
1993
0
#define SYMBOL(Id, Parent)                                                     \
1994
217k
  case SymExpr::Id##Kind:                                                      \
1995
217k
    
DISPATCH156k
(Id);
1996
217k
#include 
"clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"0
1997
217k
    }
1998
0
    llvm_unreachable("Unknown SymExpr kind!");
1999
0
  }
2000
2001
#define DEFAULT_ASSIGN(Id)                                                     \
2002
575k
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
575k
    return true;                                                               \
2004
575k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignUnarySymExprToRangeSet(clang::ento::UnarySymExpr const*, clang::ento::RangeSet)
Line
Count
Source
2002
36
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
36
    return true;                                                               \
2004
36
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymExprToRangeSet(clang::ento::SymExpr const*, clang::ento::RangeSet)
Line
Count
Source
2002
216k
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
216k
    return true;                                                               \
2004
216k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignIntSymExprToRangeSet(clang::ento::BinarySymExprImpl<llvm::APSInt const&, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)1> const*, clang::ento::RangeSet)
Line
Count
Source
2002
980
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
980
    return true;                                                               \
2004
980
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignBinarySymExprToRangeSet(clang::ento::BinarySymExpr const*, clang::ento::RangeSet)
Line
Count
Source
2002
76.2k
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
76.2k
    return true;                                                               \
2004
76.2k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolCastToRangeSet(clang::ento::SymbolCast const*, clang::ento::RangeSet)
Line
Count
Source
2002
53
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
53
    return true;                                                               \
2004
53
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolConjuredToRangeSet(clang::ento::SymbolConjured const*, clang::ento::RangeSet)
Line
Count
Source
2002
58.4k
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
58.4k
    return true;                                                               \
2004
58.4k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolDataToRangeSet(clang::ento::SymbolData const*, clang::ento::RangeSet)
Line
Count
Source
2002
140k
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
140k
    return true;                                                               \
2004
140k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolDerivedToRangeSet(clang::ento::SymbolDerived const*, clang::ento::RangeSet)
Line
Count
Source
2002
19.8k
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
19.8k
    return true;                                                               \
2004
19.8k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolExtentToRangeSet(clang::ento::SymbolExtent const*, clang::ento::RangeSet)
Line
Count
Source
2002
1.67k
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
1.67k
    return true;                                                               \
2004
1.67k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolMetadataToRangeSet(clang::ento::SymbolMetadata const*, clang::ento::RangeSet)
Line
Count
Source
2002
2.25k
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
2.25k
    return true;                                                               \
2004
2.25k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolRegionValueToRangeSet(clang::ento::SymbolRegionValue const*, clang::ento::RangeSet)
Line
Count
Source
2002
58.5k
  bool assign##Id##To##RangeSet(const Id *Sym, RangeSet Constraint) {          \
2003
58.5k
    return true;                                                               \
2004
58.5k
  }                                                                            \
2005
545k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignUnarySymExprToRange(clang::ento::UnarySymExpr const*, clang::ento::Range)
Line
Count
Source
2005
30
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymExprToRange(clang::ento::SymExpr const*, clang::ento::Range)
Line
Count
Source
2005
181k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignIntSymExprToRange(clang::ento::BinarySymExprImpl<llvm::APSInt const&, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)1> const*, clang::ento::Range)
Line
Count
Source
2005
921
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignBinarySymExprToRange(clang::ento::BinarySymExpr const*, clang::ento::Range)
Line
Count
Source
2005
53.5k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymIntExprToRange(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, llvm::APSInt const&, (clang::ento::SymExpr::Kind)2> const*, clang::ento::Range)
Line
Count
Source
2005
36.4k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymSymExprToRange(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)3> const*, clang::ento::Range)
Line
Count
Source
2005
16.1k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolCastToRange(clang::ento::SymbolCast const*, clang::ento::Range)
Line
Count
Source
2005
39
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolConjuredToRange(clang::ento::SymbolConjured const*, clang::ento::Range)
Line
Count
Source
2005
50.4k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolDataToRange(clang::ento::SymbolData const*, clang::ento::Range)
Line
Count
Source
2005
128k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolDerivedToRange(clang::ento::SymbolDerived const*, clang::ento::Range)
Line
Count
Source
2005
19.2k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolExtentToRange(clang::ento::SymbolExtent const*, clang::ento::Range)
Line
Count
Source
2005
1.67k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolMetadataToRange(clang::ento::SymbolMetadata const*, clang::ento::Range)
Line
Count
Source
2005
2.14k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolRegionValueToRange(clang::ento::SymbolRegionValue const*, clang::ento::Range)
Line
Count
Source
2005
54.9k
  bool assign##Id##To##Range(const Id *Sym, Range Constraint) { return true; } \
2006
116k
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignUnarySymExprToConst(clang::ento::UnarySymExpr const*, llvm::APSInt const&)
Line
Count
Source
2006
15
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignIntSymExprToConst(clang::ento::BinarySymExprImpl<llvm::APSInt const&, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)1> const*, llvm::APSInt const&)
Line
Count
Source
2006
58
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignBinarySymExprToConst(clang::ento::BinarySymExpr const*, llvm::APSInt const&)
Line
Count
Source
2006
30.2k
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymIntExprToConst(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, llvm::APSInt const&, (clang::ento::SymExpr::Kind)2> const*, llvm::APSInt const&)
Line
Count
Source
2006
18.2k
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymSymExprToConst(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)3> const*, llvm::APSInt const&)
Line
Count
Source
2006
11.9k
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolCastToConst(clang::ento::SymbolCast const*, llvm::APSInt const&)
Line
Count
Source
2006
15
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolConjuredToConst(clang::ento::SymbolConjured const*, llvm::APSInt const&)
Line
Count
Source
2006
15.1k
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolDataToConst(clang::ento::SymbolData const*, llvm::APSInt const&)
Line
Count
Source
2006
28.0k
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolDerivedToConst(clang::ento::SymbolDerived const*, llvm::APSInt const&)
Line
Count
Source
2006
3.39k
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolExtentToConst(clang::ento::SymbolExtent const*, llvm::APSInt const&)
Line
Count
Source
2006
170
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolMetadataToConst(clang::ento::SymbolMetadata const*, llvm::APSInt const&)
Line
Count
Source
2006
204
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolRegionValueToConst(clang::ento::SymbolRegionValue const*, llvm::APSInt const&)
Line
Count
Source
2006
9.14k
  bool assign##Id##To##Const(const Id *Sym, Const Constraint) { return true; }
2007
2008
  // When we dispatch for constraint types, we first try to check
2009
  // if the new constraint is the constant and try the corresponding
2010
  // assignor methods.  If it didn't interrupt, we can proceed to the
2011
  // range, and finally to the range set.
2012
#define CONSTRAINT_DISPATCH(Id)                                                \
2013
651k
  if (const llvm::APSInt *Const = Constraint.getConcreteValue()) {             \
2014
174k
    ASSIGN(Id, Const, Sym, *Const);                                            \
2015
174k
  }                                                                            \
2016
651k
  
if (650k
Constraint.size() == 1650k
) { \
2017
545k
    ASSIGN(Id, Range, Sym, *Constraint.begin());                               \
2018
545k
  }                                                                            \
2019
650k
  ASSIGN(Id, RangeSet, Sym, Constraint)
2020
2021
  // Our internal assign method first tries to call assignor methods for all
2022
  // constraint types that apply.  And if not interrupted, continues with its
2023
  // parent class.
2024
#define SYMBOL(Id, Parent)                                                     \
2025
434k
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
868k
    
CONSTRAINT_DISPATCH434k
(Id); \
2027
868k
    
DISPATCH434k
(Parent); \
2028
868k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignUnarySymExprImpl(clang::ento::UnarySymExpr const*, clang::ento::RangeSet)
Line
Count
Source
2025
36
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
72
    
CONSTRAINT_DISPATCH36
(Id); \
2027
72
    
DISPATCH36
0
(Parent); \
2028
72
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignIntSymExprImpl(clang::ento::BinarySymExprImpl<llvm::APSInt const&, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)1> const*, clang::ento::RangeSet)
Line
Count
Source
2025
980
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
1.96k
    
CONSTRAINT_DISPATCH980
(Id); \
2027
1.96k
    
DISPATCH980
0
(Parent); \
2028
1.96k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignBinarySymExprImpl(clang::ento::BinarySymExpr const*, clang::ento::RangeSet)
Line
Count
Source
2025
76.2k
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
152k
    
CONSTRAINT_DISPATCH76.2k
(Id); \
2027
152k
    
DISPATCH76.2k
0
(Parent); \
2028
152k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymIntExprImpl(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, llvm::APSInt const&, (clang::ento::SymExpr::Kind)2> const*, clang::ento::RangeSet)
Line
Count
Source
2025
38.7k
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
77.4k
    
CONSTRAINT_DISPATCH38.7k
(Id); \
2027
77.4k
    
DISPATCH38.7k
0
(Parent); \
2028
77.4k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymSymExprImpl(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)3> const*, clang::ento::RangeSet)
Line
Count
Source
2025
36.5k
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
73.1k
    
CONSTRAINT_DISPATCH36.5k
(Id); \
2027
73.1k
    
DISPATCH36.5k
0
(Parent); \
2028
73.1k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolCastImpl(clang::ento::SymbolCast const*, clang::ento::RangeSet)
Line
Count
Source
2025
53
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
106
    
CONSTRAINT_DISPATCH53
(Id); \
2027
106
    
DISPATCH53
0
(Parent); \
2028
106
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolConjuredImpl(clang::ento::SymbolConjured const*, clang::ento::RangeSet)
Line
Count
Source
2025
58.4k
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
116k
    
CONSTRAINT_DISPATCH58.4k
(Id); \
2027
116k
    
DISPATCH58.4k
0
(Parent); \
2028
116k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolDataImpl(clang::ento::SymbolData const*, clang::ento::RangeSet)
Line
Count
Source
2025
140k
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
281k
    
CONSTRAINT_DISPATCH140k
(Id); \
2027
281k
    
DISPATCH140k
0
(Parent); \
2028
281k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolDerivedImpl(clang::ento::SymbolDerived const*, clang::ento::RangeSet)
Line
Count
Source
2025
19.8k
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
39.6k
    
CONSTRAINT_DISPATCH19.8k
(Id); \
2027
39.6k
    
DISPATCH19.8k
0
(Parent); \
2028
39.6k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolExtentImpl(clang::ento::SymbolExtent const*, clang::ento::RangeSet)
Line
Count
Source
2025
1.67k
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
3.34k
    
CONSTRAINT_DISPATCH1.67k
(Id); \
2027
3.34k
    
DISPATCH1.67k
0
(Parent); \
2028
3.34k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolMetadataImpl(clang::ento::SymbolMetadata const*, clang::ento::RangeSet)
Line
Count
Source
2025
2.25k
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
4.50k
    
CONSTRAINT_DISPATCH2.25k
(Id); \
2027
4.50k
    
DISPATCH2.25k
0
(Parent); \
2028
4.50k
  }                                                                            \
RangeConstraintManager.cpp:(anonymous namespace)::ConstraintAssignorBase<(anonymous namespace)::ConstraintAssignor>::assignSymbolRegionValueImpl(clang::ento::SymbolRegionValue const*, clang::ento::RangeSet)
Line
Count
Source
2025
58.5k
  bool assign##Id##Impl(const Id *Sym, RangeSet Constraint) {                  \
2026
117k
    
CONSTRAINT_DISPATCH58.5k
(Id); \
2027
117k
    
DISPATCH58.5k
0
(Parent); \
2028
117k
  }                                                                            \
2029
  DEFAULT_ASSIGN(Id)
2030
#define ABSTRACT_SYMBOL(Id, Parent) SYMBOL(Id, Parent)
2031
#include "clang/StaticAnalyzer/Core/PathSensitive/Symbols.def"
2032
2033
  // Default implementations for the top class that doesn't have parents.
2034
217k
  bool assignSymExprImpl(const SymExpr *Sym, RangeSet Constraint) {
2035
432k
    
CONSTRAINT_DISPATCH217k
(SymExpr);
2036
216k
    return true;
2037
432k
  }
2038
  DEFAULT_ASSIGN(SymExpr);
2039
2040
#undef DISPATCH
2041
#undef CONSTRAINT_DISPATCH
2042
#undef DEFAULT_ASSIGN
2043
#undef ASSIGN
2044
};
2045
2046
/// A little component aggregating all of the reasoning we have about
2047
/// assigning new constraints to symbols.
2048
///
2049
/// The main purpose of this class is to associate constraints to symbols,
2050
/// and impose additional constraints on other symbols, when we can imply
2051
/// them.
2052
///
2053
/// It has a nice symmetry with SymbolicRangeInferrer.  When the latter
2054
/// can provide more precise ranges by looking into the operands of the
2055
/// expression in question, ConstraintAssignor looks into the operands
2056
/// to see if we can imply more from the new constraint.
2057
class ConstraintAssignor : public ConstraintAssignorBase<ConstraintAssignor> {
2058
public:
2059
  template <class ClassOrSymbol>
2060
  [[nodiscard]] static ProgramStateRef
2061
  assign(ProgramStateRef State, SValBuilder &Builder, RangeSet::Factory &F,
2062
294k
         ClassOrSymbol CoS, RangeSet NewConstraint) {
2063
294k
    if (!State || NewConstraint.isEmpty())
2064
77.4k
      return nullptr;
2065
2066
217k
    ConstraintAssignor Assignor{State, Builder, F};
2067
217k
    return Assignor.assign(CoS, NewConstraint);
2068
294k
  }
2069
2070
  /// Handle expressions like: a % b != 0.
2071
  template <typename SymT>
2072
75.2k
  bool handleRemainderOp(const SymT *Sym, RangeSet Constraint) {
2073
75.2k
    if (Sym->getOpcode() != BO_Rem)
2074
75.1k
      return true;
2075
    // a % b != 0 implies that a != 0.
2076
98
    if (!Constraint.containsZero()) {
2077
20
      SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
2078
20
      if (auto NonLocSymSVal = SymSVal.getAs<nonloc::SymbolVal>()) {
2079
20
        State = State->assume(*NonLocSymSVal, true);
2080
20
        if (!State)
2081
0
          return false;
2082
20
      }
2083
20
    }
2084
98
    return true;
2085
98
  }
RangeConstraintManager.cpp:bool (anonymous namespace)::ConstraintAssignor::handleRemainderOp<clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, llvm::APSInt const&, (clang::ento::SymExpr::Kind)2> >(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, llvm::APSInt const&, (clang::ento::SymExpr::Kind)2> const*, clang::ento::RangeSet)
Line
Count
Source
2072
38.7k
  bool handleRemainderOp(const SymT *Sym, RangeSet Constraint) {
2073
38.7k
    if (Sym->getOpcode() != BO_Rem)
2074
38.6k
      return true;
2075
    // a % b != 0 implies that a != 0.
2076
36
    if (!Constraint.containsZero()) {
2077
10
      SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
2078
10
      if (auto NonLocSymSVal = SymSVal.getAs<nonloc::SymbolVal>()) {
2079
10
        State = State->assume(*NonLocSymSVal, true);
2080
10
        if (!State)
2081
0
          return false;
2082
10
      }
2083
10
    }
2084
36
    return true;
2085
36
  }
RangeConstraintManager.cpp:bool (anonymous namespace)::ConstraintAssignor::handleRemainderOp<clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)3> >(clang::ento::BinarySymExprImpl<clang::ento::SymExpr const*, clang::ento::SymExpr const*, (clang::ento::SymExpr::Kind)3> const*, clang::ento::RangeSet)
Line
Count
Source
2072
36.5k
  bool handleRemainderOp(const SymT *Sym, RangeSet Constraint) {
2073
36.5k
    if (Sym->getOpcode() != BO_Rem)
2074
36.4k
      return true;
2075
    // a % b != 0 implies that a != 0.
2076
62
    if (!Constraint.containsZero()) {
2077
10
      SVal SymSVal = Builder.makeSymbolVal(Sym->getLHS());
2078
10
      if (auto NonLocSymSVal = SymSVal.getAs<nonloc::SymbolVal>()) {
2079
10
        State = State->assume(*NonLocSymSVal, true);
2080
10
        if (!State)
2081
0
          return false;
2082
10
      }
2083
10
    }
2084
62
    return true;
2085
62
  }
2086
2087
  inline bool assignSymExprToConst(const SymExpr *Sym, Const Constraint);
2088
  inline bool assignSymIntExprToRangeSet(const SymIntExpr *Sym,
2089
38.7k
                                         RangeSet Constraint) {
2090
38.7k
    return handleRemainderOp(Sym, Constraint);
2091
38.7k
  }
2092
  inline bool assignSymSymExprToRangeSet(const SymSymExpr *Sym,
2093
                                         RangeSet Constraint);
2094
2095
private:
2096
  ConstraintAssignor(ProgramStateRef State, SValBuilder &Builder,
2097
                     RangeSet::Factory &F)
2098
217k
      : State(State), Builder(Builder), RangeFactory(F) {}
2099
  using Base = ConstraintAssignorBase<ConstraintAssignor>;
2100
2101
  /// Base method for handling new constraints for symbols.
2102
217k
  [[nodiscard]] ProgramStateRef assign(SymbolRef Sym, RangeSet NewConstraint) {
2103
    // All constraints are actually associated with equivalence classes, and
2104
    // that's what we are going to do first.
2105
217k
    State = assign(EquivalenceClass::find(State, Sym), NewConstraint);
2106
217k
    if (!State)
2107
1
      return nullptr;
2108
2109
    // And after that we can check what other things we can get from this
2110
    // constraint.
2111
217k
    Base::assign(Sym, NewConstraint);
2112
217k
    return State;
2113
217k
  }
2114
2115
  /// Base method for handling new constraints for classes.
2116
  [[nodiscard]] ProgramStateRef assign(EquivalenceClass Class,
2117
217k
                                       RangeSet NewConstraint) {
2118
    // There is a chance that we might need to update constraints for the
2119
    // classes that are known to be disequal to Class.
2120
    //
2121
    // In order for this to be even possible, the new constraint should
2122
    // be simply a constant because we can't reason about range disequalities.
2123
217k
    if (const llvm::APSInt *Point = NewConstraint.getConcreteValue()) {
2124
2125
58.2k
      ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2126
58.2k
      ConstraintRangeTy::Factory &CF = State->get_context<ConstraintRange>();
2127
2128
      // Add new constraint.
2129
58.2k
      Constraints = CF.add(Constraints, Class, NewConstraint);
2130
2131
58.2k
      for (EquivalenceClass DisequalClass : Class.getDisequalClasses(State)) {
2132
216
        RangeSet UpdatedConstraint = SymbolicRangeInferrer::inferRange(
2133
216
            RangeFactory, State, DisequalClass);
2134
2135
216
        UpdatedConstraint = RangeFactory.deletePoint(UpdatedConstraint, *Point);
2136
2137
        // If we end up with at least one of the disequal classes to be
2138
        // constrained with an empty range-set, the state is infeasible.
2139
216
        if (UpdatedConstraint.isEmpty())
2140
1
          return nullptr;
2141
2142
215
        Constraints = CF.add(Constraints, DisequalClass, UpdatedConstraint);
2143
215
      }
2144
58.2k
      assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
2145
58.2k
                                         "a state with infeasible constraints");
2146
2147
58.2k
      return setConstraints(State, Constraints);
2148
58.2k
    }
2149
2150
158k
    return setConstraint(State, Class, NewConstraint);
2151
217k
  }
2152
2153
  ProgramStateRef trackDisequality(ProgramStateRef State, SymbolRef LHS,
2154
3.61k
                                   SymbolRef RHS) {
2155
3.61k
    return EquivalenceClass::markDisequal(RangeFactory, State, LHS, RHS);
2156
3.61k
  }
2157
2158
  ProgramStateRef trackEquality(ProgramStateRef State, SymbolRef LHS,
2159
1.31k
                                SymbolRef RHS) {
2160
1.31k
    return EquivalenceClass::merge(RangeFactory, State, LHS, RHS);
2161
1.31k
  }
2162
2163
36.5k
  [[nodiscard]] std::optional<bool> interpreteAsBool(RangeSet Constraint) {
2164
36.5k
    assert(!Constraint.isEmpty() && "Empty ranges shouldn't get here");
2165
2166
36.5k
    if (Constraint.getConcreteValue())
2167
11.9k
      return !Constraint.getConcreteValue()->isZero();
2168
2169
24.6k
    if (!Constraint.containsZero())
2170
22.9k
      return true;
2171
2172
1.70k
    return std::nullopt;
2173
24.6k
  }
2174
2175
  ProgramStateRef State;
2176
  SValBuilder &Builder;
2177
  RangeSet::Factory &RangeFactory;
2178
};
2179
2180
bool ConstraintAssignor::assignSymExprToConst(const SymExpr *Sym,
2181
58.2k
                                              const llvm::APSInt &Constraint) {
2182
58.2k
  llvm::SmallSet<EquivalenceClass, 4> SimplifiedClasses;
2183
  // Iterate over all equivalence classes and try to simplify them.
2184
58.2k
  ClassMembersTy Members = State->get<ClassMembers>();
2185
58.2k
  for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members) {
2186
14.7k
    EquivalenceClass Class = ClassToSymbolSet.first;
2187
14.7k
    State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2188
14.7k
    if (!State)
2189
275
      return false;
2190
14.5k
    SimplifiedClasses.insert(Class);
2191
14.5k
  }
2192
2193
  // Trivial equivalence classes (those that have only one symbol member) are
2194
  // not stored in the State. Thus, we must skim through the constraints as
2195
  // well. And we try to simplify symbols in the constraints.
2196
58.0k
  ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2197
935k
  for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2198
935k
    EquivalenceClass Class = ClassConstraint.first;
2199
935k
    if (SimplifiedClasses.count(Class)) // Already simplified.
2200
12.0k
      continue;
2201
923k
    State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2202
923k
    if (!State)
2203
535
      return false;
2204
923k
  }
2205
2206
  // We may have trivial equivalence classes in the disequality info as
2207
  // well, and we need to simplify them.
2208
57.4k
  DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2209
57.4k
  for (std::pair<EquivalenceClass, ClassSet> DisequalityEntry :
2210
57.4k
       DisequalityInfo) {
2211
11.7k
    EquivalenceClass Class = DisequalityEntry.first;
2212
11.7k
    ClassSet DisequalClasses = DisequalityEntry.second;
2213
11.7k
    State = EquivalenceClass::simplify(Builder, RangeFactory, State, Class);
2214
11.7k
    if (!State)
2215
2
      return false;
2216
11.7k
  }
2217
2218
57.4k
  return true;
2219
57.4k
}
2220
2221
bool ConstraintAssignor::assignSymSymExprToRangeSet(const SymSymExpr *Sym,
2222
36.5k
                                                    RangeSet Constraint) {
2223
36.5k
  if (!handleRemainderOp(Sym, Constraint))
2224
0
    return false;
2225
2226
36.5k
  std::optional<bool> ConstraintAsBool = interpreteAsBool(Constraint);
2227
2228
36.5k
  if (!ConstraintAsBool)
2229
1.70k
    return true;
2230
2231
34.8k
  if (std::optional<bool> Equality = meansEquality(Sym)) {
2232
    // Here we cover two cases:
2233
    //   * if Sym is equality and the new constraint is true -> Sym's operands
2234
    //     should be marked as equal
2235
    //   * if Sym is disequality and the new constraint is false -> Sym's
2236
    //     operands should be also marked as equal
2237
4.93k
    if (*Equality == *ConstraintAsBool) {
2238
1.31k
      State = trackEquality(State, Sym->getLHS(), Sym->getRHS());
2239
3.61k
    } else {
2240
      // Other combinations leave as with disequal operands.
2241
3.61k
      State = trackDisequality(State, Sym->getLHS(), Sym->getRHS());
2242
3.61k
    }
2243
2244
4.93k
    if (!State)
2245
6
      return false;
2246
4.93k
  }
2247
2248
34.8k
  return true;
2249
34.8k
}
2250
2251
} // end anonymous namespace
2252
2253
std::unique_ptr<ConstraintManager>
2254
ento::CreateRangeConstraintManager(ProgramStateManager &StMgr,
2255
16.2k
                                   ExprEngine *Eng) {
2256
16.2k
  return std::make_unique<RangeConstraintManager>(Eng, StMgr.getSValBuilder());
2257
16.2k
}
2258
2259
0
ConstraintMap ento::getConstraintMap(ProgramStateRef State) {
2260
0
  ConstraintMap::Factory &F = State->get_context<ConstraintMap>();
2261
0
  ConstraintMap Result = F.getEmptyMap();
2262
2263
0
  ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2264
0
  for (std::pair<EquivalenceClass, RangeSet> ClassConstraint : Constraints) {
2265
0
    EquivalenceClass Class = ClassConstraint.first;
2266
0
    SymbolSet ClassMembers = Class.getClassMembers(State);
2267
0
    assert(!ClassMembers.isEmpty() &&
2268
0
           "Class must always have at least one member!");
2269
2270
0
    SymbolRef Representative = *ClassMembers.begin();
2271
0
    Result = F.add(Result, Representative, ClassConstraint.second);
2272
0
  }
2273
2274
0
  return Result;
2275
0
}
2276
2277
//===----------------------------------------------------------------------===//
2278
//                     EqualityClass implementation details
2279
//===----------------------------------------------------------------------===//
2280
2281
LLVM_DUMP_METHOD void EquivalenceClass::dumpToStream(ProgramStateRef State,
2282
0
                                                     raw_ostream &os) const {
2283
0
  SymbolSet ClassMembers = getClassMembers(State);
2284
0
  for (const SymbolRef &MemberSym : ClassMembers) {
2285
0
    MemberSym->dump();
2286
0
    os << "\n";
2287
0
  }
2288
0
}
2289
2290
inline EquivalenceClass EquivalenceClass::find(ProgramStateRef State,
2291
9.74M
                                               SymbolRef Sym) {
2292
9.74M
  assert(State && "State should not be null");
2293
9.74M
  assert(Sym && "Symbol should not be null");
2294
  // We store far from all Symbol -> Class mappings
2295
9.74M
  if (const EquivalenceClass *NontrivialClass = State->get<ClassMap>(Sym))
2296
90.3k
    return *NontrivialClass;
2297
2298
  // This is a trivial class of Sym.
2299
9.65M
  return Sym;
2300
9.74M
}
2301
2302
inline ProgramStateRef EquivalenceClass::merge(RangeSet::Factory &F,
2303
                                               ProgramStateRef State,
2304
                                               SymbolRef First,
2305
6.67k
                                               SymbolRef Second) {
2306
6.67k
  EquivalenceClass FirstClass = find(State, First);
2307
6.67k
  EquivalenceClass SecondClass = find(State, Second);
2308
2309
6.67k
  return FirstClass.merge(F, State, SecondClass);
2310
6.67k
}
2311
2312
inline ProgramStateRef EquivalenceClass::merge(RangeSet::Factory &F,
2313
                                               ProgramStateRef State,
2314
6.67k
                                               EquivalenceClass Other) {
2315
  // It is already the same class.
2316
6.67k
  if (*this == Other)
2317
247
    return State;
2318
2319
  // FIXME: As of now, we support only equivalence classes of the same type.
2320
  //        This limitation is connected to the lack of explicit casts in
2321
  //        our symbolic expression model.
2322
  //
2323
  //        That means that for `int x` and `char y` we don't distinguish
2324
  //        between these two very different cases:
2325
  //          * `x == y`
2326
  //          * `(char)x == y`
2327
  //
2328
  //        The moment we introduce symbolic casts, this restriction can be
2329
  //        lifted.
2330
6.42k
  if (getType() != Other.getType())
2331
179
    return State;
2332
2333
6.24k
  SymbolSet Members = getClassMembers(State);
2334
6.24k
  SymbolSet OtherMembers = Other.getClassMembers(State);
2335
2336
  // We estimate the size of the class by the height of tree containing
2337
  // its members.  Merging is not a trivial operation, so it's easier to
2338
  // merge the smaller class into the bigger one.
2339
6.24k
  if (Members.getHeight() >= OtherMembers.getHeight()) {
2340
6.24k
    return mergeImpl(F, State, Members, Other, OtherMembers);
2341
6.24k
  } else {
2342
3
    return Other.mergeImpl(F, State, OtherMembers, *this, Members);
2343
3
  }
2344
6.24k
}
2345
2346
inline ProgramStateRef
2347
EquivalenceClass::mergeImpl(RangeSet::Factory &RangeFactory,
2348
                            ProgramStateRef State, SymbolSet MyMembers,
2349
6.24k
                            EquivalenceClass Other, SymbolSet OtherMembers) {
2350
  // Essentially what we try to recreate here is some kind of union-find
2351
  // data structure.  It does have certain limitations due to persistence
2352
  // and the need to remove elements from classes.
2353
  //
2354
  // In this setting, EquialityClass object is the representative of the class
2355
  // or the parent element.  ClassMap is a mapping of class members to their
2356
  // parent. Unlike the union-find structure, they all point directly to the
2357
  // class representative because we don't have an opportunity to actually do
2358
  // path compression when dealing with immutability.  This means that we
2359
  // compress paths every time we do merges.  It also means that we lose
2360
  // the main amortized complexity benefit from the original data structure.
2361
6.24k
  ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2362
6.24k
  ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2363
2364
  // 1. If the merged classes have any constraints associated with them, we
2365
  //    need to transfer them to the class we have left.
2366
  //
2367
  // Intersection here makes perfect sense because both of these constraints
2368
  // must hold for the whole new class.
2369
6.24k
  if (std::optional<RangeSet> NewClassConstraint =
2370
6.24k
          intersect(RangeFactory, getConstraint(State, *this),
2371
6.24k
                    getConstraint(State, Other))) {
2372
    // NOTE: Essentially, NewClassConstraint should NEVER be infeasible because
2373
    //       range inferrer shouldn't generate ranges incompatible with
2374
    //       equivalence classes. However, at the moment, due to imperfections
2375
    //       in the solver, it is possible and the merge function can also
2376
    //       return infeasible states aka null states.
2377
5.91k
    if (NewClassConstraint->isEmpty())
2378
      // Infeasible state
2379
4
      return nullptr;
2380
2381
    // No need in tracking constraints of a now-dissolved class.
2382
5.90k
    Constraints = CRF.remove(Constraints, Other);
2383
    // Assign new constraints for this class.
2384
5.90k
    Constraints = CRF.add(Constraints, *this, *NewClassConstraint);
2385
2386
5.90k
    assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
2387
5.90k
                                       "a state with infeasible constraints");
2388
2389
5.90k
    State = State->set<ConstraintRange>(Constraints);
2390
5.90k
  }
2391
2392
  // 2. Get ALL equivalence-related maps
2393
6.24k
  ClassMapTy Classes = State->get<ClassMap>();
2394
6.24k
  ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2395
2396
6.24k
  ClassMembersTy Members = State->get<ClassMembers>();
2397
6.24k
  ClassMembersTy::Factory &MF = State->get_context<ClassMembers>();
2398
2399
6.24k
  DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2400
6.24k
  DisequalityMapTy::Factory &DF = State->get_context<DisequalityMap>();
2401
2402
6.24k
  ClassSet::Factory &CF = State->get_context<ClassSet>();
2403
6.24k
  SymbolSet::Factory &F = getMembersFactory(State);
2404
2405
  // 2. Merge members of the Other class into the current class.
2406
6.24k
  SymbolSet NewClassMembers = MyMembers;
2407
6.24k
  for (SymbolRef Sym : OtherMembers) {
2408
6.24k
    NewClassMembers = F.add(NewClassMembers, Sym);
2409
    // *this is now the class for all these new symbols.
2410
6.24k
    Classes = CMF.add(Classes, Sym, *this);
2411
6.24k
  }
2412
2413
  // 3. Adjust member mapping.
2414
  //
2415
  // No need in tracking members of a now-dissolved class.
2416
6.24k
  Members = MF.remove(Members, Other);
2417
  // Now only the current class is mapped to all the symbols.
2418
6.24k
  Members = MF.add(Members, *this, NewClassMembers);
2419
2420
  // 4. Update disequality relations
2421
6.24k
  ClassSet DisequalToOther = Other.getDisequalClasses(DisequalityInfo, CF);
2422
  // We are about to merge two classes but they are already known to be
2423
  // non-equal. This is a contradiction.
2424
6.24k
  if (DisequalToOther.contains(*this))
2425
4
    return nullptr;
2426
2427
6.23k
  if (!DisequalToOther.isEmpty()) {
2428
24
    ClassSet DisequalToThis = getDisequalClasses(DisequalityInfo, CF);
2429
24
    DisequalityInfo = DF.remove(DisequalityInfo, Other);
2430
2431
42
    for (EquivalenceClass DisequalClass : DisequalToOther) {
2432
42
      DisequalToThis = CF.add(DisequalToThis, DisequalClass);
2433
2434
      // Disequality is a symmetric relation meaning that if
2435
      // DisequalToOther not null then the set for DisequalClass is not
2436
      // empty and has at least Other.
2437
42
      ClassSet OriginalSetLinkedToOther =
2438
42
          *DisequalityInfo.lookup(DisequalClass);
2439
2440
      // Other will be eliminated and we should replace it with the bigger
2441
      // united class.
2442
42
      ClassSet NewSet = CF.remove(OriginalSetLinkedToOther, Other);
2443
42
      NewSet = CF.add(NewSet, *this);
2444
2445
42
      DisequalityInfo = DF.add(DisequalityInfo, DisequalClass, NewSet);
2446
42
    }
2447
2448
24
    DisequalityInfo = DF.add(DisequalityInfo, *this, DisequalToThis);
2449
24
    State = State->set<DisequalityMap>(DisequalityInfo);
2450
24
  }
2451
2452
  // 5. Update the state
2453
6.23k
  State = State->set<ClassMap>(Classes);
2454
6.23k
  State = State->set<ClassMembers>(Members);
2455
2456
6.23k
  return State;
2457
6.24k
}
2458
2459
inline SymbolSet::Factory &
2460
957k
EquivalenceClass::getMembersFactory(ProgramStateRef State) {
2461
957k
  return State->get_context<SymbolSet>();
2462
957k
}
2463
2464
967k
SymbolSet EquivalenceClass::getClassMembers(ProgramStateRef State) const {
2465
967k
  if (const SymbolSet *Members = State->get<ClassMembers>(*this))
2466
21.8k
    return *Members;
2467
2468
  // This class is trivial, so we need to construct a set
2469
  // with just that one symbol from the class.
2470
945k
  SymbolSet::Factory &F = getMembersFactory(State);
2471
945k
  return F.add(F.getEmptySet(), getRepresentativeSymbol());
2472
967k
}
2473
2474
2.86M
bool EquivalenceClass::isTrivial(ProgramStateRef State) const {
2475
2.86M
  return State->get<ClassMembers>(*this) == nullptr;
2476
2.86M
}
2477
2478
bool EquivalenceClass::isTriviallyDead(ProgramStateRef State,
2479
2.86M
                                       SymbolReaper &Reaper) const {
2480
2.86M
  return isTrivial(State) && 
Reaper.isDead(getRepresentativeSymbol())2.81M
;
2481
2.86M
}
2482
2483
inline ProgramStateRef EquivalenceClass::markDisequal(RangeSet::Factory &RF,
2484
                                                      ProgramStateRef State,
2485
                                                      SymbolRef First,
2486
3.61k
                                                      SymbolRef Second) {
2487
3.61k
  return markDisequal(RF, State, find(State, First), find(State, Second));
2488
3.61k
}
2489
2490
inline ProgramStateRef EquivalenceClass::markDisequal(RangeSet::Factory &RF,
2491
                                                      ProgramStateRef State,
2492
                                                      EquivalenceClass First,
2493
3.61k
                                                      EquivalenceClass Second) {
2494
3.61k
  return First.markDisequal(RF, State, Second);
2495
3.61k
}
2496
2497
inline ProgramStateRef
2498
EquivalenceClass::markDisequal(RangeSet::Factory &RF, ProgramStateRef State,
2499
3.61k
                               EquivalenceClass Other) const {
2500
  // If we know that two classes are equal, we can only produce an infeasible
2501
  // state.
2502
3.61k
  if (*this == Other) {
2503
0
    return nullptr;
2504
0
  }
2505
2506
3.61k
  DisequalityMapTy DisequalityInfo = State->get<DisequalityMap>();
2507
3.61k
  ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2508
2509
  // Disequality is a symmetric relation, so if we mark A as disequal to B,
2510
  // we should also mark B as disequalt to A.
2511
3.61k
  if (!addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, *this,
2512
3.61k
                            Other) ||
2513
3.61k
      !addToDisequalityInfo(DisequalityInfo, Constraints, RF, State, Other,
2514
3.60k
                            *this))
2515
5
    return nullptr;
2516
2517
3.60k
  assert(areFeasible(Constraints) && "Constraint manager shouldn't produce "
2518
3.60k
                                     "a state with infeasible constraints");
2519
2520
3.60k
  State = State->set<DisequalityMap>(DisequalityInfo);
2521
3.60k
  State = State->set<ConstraintRange>(Constraints);
2522
2523
3.60k
  return State;
2524
3.60k
}
2525
2526
inline bool EquivalenceClass::addToDisequalityInfo(
2527
    DisequalityMapTy &Info, ConstraintRangeTy &Constraints,
2528
    RangeSet::Factory &RF, ProgramStateRef State, EquivalenceClass First,
2529
7.22k
    EquivalenceClass Second) {
2530
2531
  // 1. Get all of the required factories.
2532
7.22k
  DisequalityMapTy::Factory &F = State->get_context<DisequalityMap>();
2533
7.22k
  ClassSet::Factory &CF = State->get_context<ClassSet>();
2534
7.22k
  ConstraintRangeTy::Factory &CRF = State->get_context<ConstraintRange>();
2535
2536
  // 2. Add Second to the set of classes disequal to First.
2537
7.22k
  const ClassSet *CurrentSet = Info.lookup(First);
2538
7.22k
  ClassSet NewSet = CurrentSet ? 
*CurrentSet2.87k
:
CF.getEmptySet()4.34k
;
2539
7.22k
  NewSet = CF.add(NewSet, Second);
2540
2541
7.22k
  Info = F.add(Info, First, NewSet);
2542
2543
  // 3. If Second is known to be a constant, we can delete this point
2544
  //    from the constraint asociated with First.
2545
  //
2546
  //    So, if Second == 10, it means that First != 10.
2547
  //    At the same time, the same logic does not apply to ranges.
2548
7.22k
  if (const RangeSet *SecondConstraint = Constraints.lookup(Second))
2549
5.57k
    if (const llvm::APSInt *Point = SecondConstraint->getConcreteValue()) {
2550
2551
6
      RangeSet FirstConstraint = SymbolicRangeInferrer::inferRange(
2552
6
          RF, State, First.getRepresentativeSymbol());
2553
2554
6
      FirstConstraint = RF.deletePoint(FirstConstraint, *Point);
2555
2556
      // If the First class is about to be constrained with an empty
2557
      // range-set, the state is infeasible.
2558
6
      if (FirstConstraint.isEmpty())
2559
5
        return false;
2560
2561
1
      Constraints = CRF.add(Constraints, First, FirstConstraint);
2562
1
    }
2563
2564
7.21k
  return true;
2565
7.22k
}
2566
2567
inline std::optional<bool> EquivalenceClass::areEqual(ProgramStateRef State,
2568
                                                      SymbolRef FirstSym,
2569
32.0k
                                                      SymbolRef SecondSym) {
2570
32.0k
  return EquivalenceClass::areEqual(State, find(State, FirstSym),
2571
32.0k
                                    find(State, SecondSym));
2572
32.0k
}
2573
2574
inline std::optional<bool> EquivalenceClass::areEqual(ProgramStateRef State,
2575
                                                      EquivalenceClass First,
2576
32.0k
                                                      EquivalenceClass Second) {
2577
  // The same equivalence class => symbols are equal.
2578
32.0k
  if (First == Second)
2579
503
    return true;
2580
2581
  // Let's check if we know anything about these two classes being not equal to
2582
  // each other.
2583
31.5k
  ClassSet DisequalToFirst = First.getDisequalClasses(State);
2584
31.5k
  if (DisequalToFirst.contains(Second))
2585
2.21k
    return false;
2586
2587
  // It is not clear.
2588
29.3k
  return std::nullopt;
2589
31.5k
}
2590
2591
[[nodiscard]] ProgramStateRef
2592
5.34k
EquivalenceClass::removeMember(ProgramStateRef State, const SymbolRef Old) {
2593
2594
5.34k
  SymbolSet ClsMembers = getClassMembers(State);
2595
5.34k
  assert(ClsMembers.contains(Old));
2596
2597
  // Remove `Old`'s Class->Sym relation.
2598
5.34k
  SymbolSet::Factory &F = getMembersFactory(State);
2599
5.34k
  ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2600
5.34k
  ClsMembers = F.remove(ClsMembers, Old);
2601
  // Ensure another precondition of the removeMember function (we can check
2602
  // this only with isEmpty, thus we have to do the remove first).
2603
5.34k
  assert(!ClsMembers.isEmpty() &&
2604
5.34k
         "Class should have had at least two members before member removal");
2605
  // Overwrite the existing members assigned to this class.
2606
5.34k
  ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2607
5.34k
  ClassMembersMap = EMFactory.add(ClassMembersMap, *this, ClsMembers);
2608
5.34k
  State = State->set<ClassMembers>(ClassMembersMap);
2609
2610
  // Remove `Old`'s Sym->Class relation.
2611
5.34k
  ClassMapTy Classes = State->get<ClassMap>();
2612
5.34k
  ClassMapTy::Factory &CMF = State->get_context<ClassMap>();
2613
5.34k
  Classes = CMF.remove(Classes, Old);
2614
5.34k
  State = State->set<ClassMap>(Classes);
2615
2616
5.34k
  return State;
2617
5.34k
}
2618
2619
// Re-evaluate an SVal with top-level `State->assume` logic.
2620
[[nodiscard]] ProgramStateRef
2621
5.34k
reAssume(ProgramStateRef State, const RangeSet *Constraint, SVal TheValue) {
2622
5.34k
  if (!Constraint)
2623
8
    return State;
2624
2625
5.34k
  const auto DefinedVal = TheValue.castAs<DefinedSVal>();
2626
2627
  // If the SVal is 0, we can simply interpret that as `false`.
2628
5.34k
  if (Constraint->encodesFalseRange())
2629
450
    return State->assume(DefinedVal, false);
2630
2631
  // If the constraint does not encode 0 then we can interpret that as `true`
2632
  // AND as a Range(Set).
2633
4.89k
  if (Constraint->encodesTrueRange()) {
2634
4.72k
    State = State->assume(DefinedVal, true);
2635
4.72k
    if (!State)
2636
166
      return nullptr;
2637
    // Fall through, re-assume based on the range values as well.
2638
4.72k
  }
2639
  // Overestimate the individual Ranges with the RangeSet' lowest and
2640
  // highest values.
2641
4.72k
  return State->assumeInclusiveRange(DefinedVal, Constraint->getMinValue(),
2642
4.72k
                                     Constraint->getMaxValue(), true);
2643
4.89k
}
2644
2645
// Iterate over all symbols and try to simplify them. Once a symbol is
2646
// simplified then we check if we can merge the simplified symbol's equivalence
2647
// class to this class. This way, we simplify not just the symbols but the
2648
// classes as well: we strive to keep the number of the classes to be the
2649
// absolute minimum.
2650
[[nodiscard]] ProgramStateRef
2651
EquivalenceClass::simplify(SValBuilder &SVB, RangeSet::Factory &F,
2652
949k
                           ProgramStateRef State, EquivalenceClass Class) {
2653
949k
  SymbolSet ClassMembers = Class.getClassMembers(State);
2654
951k
  for (const SymbolRef &MemberSym : ClassMembers) {
2655
2656
951k
    const SVal SimplifiedMemberVal = simplifyToSVal(State, MemberSym);
2657
951k
    const SymbolRef SimplifiedMemberSym = SimplifiedMemberVal.getAsSymbol();
2658
2659
    // The symbol is collapsed to a constant, check if the current State is
2660
    // still feasible.
2661
951k
    if (const auto CI = SimplifiedMemberVal.getAs<nonloc::ConcreteInt>()) {
2662
121k
      const llvm::APSInt &SV = CI->getValue();
2663
121k
      const RangeSet *ClassConstraint = getConstraint(State, Class);
2664
      // We have found a contradiction.
2665
121k
      if (ClassConstraint && !ClassConstraint->contains(SV))
2666
538
        return nullptr;
2667
121k
    }
2668
2669
950k
    if (SimplifiedMemberSym && 
MemberSym != SimplifiedMemberSym829k
) {
2670
      // The simplified symbol should be the member of the original Class,
2671
      // however, it might be in another existing class at the moment. We
2672
      // have to merge these classes.
2673
5.35k
      ProgramStateRef OldState = State;
2674
5.35k
      State = merge(F, State, MemberSym, SimplifiedMemberSym);
2675
5.35k
      if (!State)
2676
7
        return nullptr;
2677
      // No state change, no merge happened actually.
2678
5.34k
      if (OldState == State)
2679
0
        continue;
2680
2681
      // Be aware that `SimplifiedMemberSym` might refer to an already dead
2682
      // symbol. In that case, the eqclass of that might not be the same as the
2683
      // eqclass of `MemberSym`. This is because the dead symbols are not
2684
      // preserved in the `ClassMap`, hence
2685
      // `find(State, SimplifiedMemberSym)` will result in a trivial eqclass
2686
      // compared to the eqclass of `MemberSym`.
2687
      // These eqclasses should be the same if `SimplifiedMemberSym` is alive.
2688
      // --> assert(find(State, MemberSym) == find(State, SimplifiedMemberSym))
2689
      //
2690
      // Note that `MemberSym` must be alive here since that is from the
2691
      // `ClassMembers` where all the symbols are alive.
2692
2693
      // Remove the old and more complex symbol.
2694
5.34k
      State = find(State, MemberSym).removeMember(State, MemberSym);
2695
2696
      // Query the class constraint again b/c that may have changed during the
2697
      // merge above.
2698
5.34k
      const RangeSet *ClassConstraint = getConstraint(State, Class);
2699
2700
      // Re-evaluate an SVal with top-level `State->assume`, this ignites
2701
      // a RECURSIVE algorithm that will reach a FIXPOINT.
2702
      //
2703
      // About performance and complexity: Let us assume that in a State we
2704
      // have N non-trivial equivalence classes and that all constraints and
2705
      // disequality info is related to non-trivial classes. In the worst case,
2706
      // we can simplify only one symbol of one class in each iteration. The
2707
      // number of symbols in one class cannot grow b/c we replace the old
2708
      // symbol with the simplified one. Also, the number of the equivalence
2709
      // classes can decrease only, b/c the algorithm does a merge operation
2710
      // optionally. We need N iterations in this case to reach the fixpoint.
2711
      // Thus, the steps needed to be done in the worst case is proportional to
2712
      // N*N.
2713
      //
2714
      // This worst case scenario can be extended to that case when we have
2715
      // trivial classes in the constraints and in the disequality map. This
2716
      // case can be reduced to the case with a State where there are only
2717
      // non-trivial classes. This is because a merge operation on two trivial
2718
      // classes results in one non-trivial class.
2719
5.34k
      State = reAssume(State, ClassConstraint, SimplifiedMemberVal);
2720
5.34k
      if (!State)
2721
267
        return nullptr;
2722
5.34k
    }
2723
950k
  }
2724
948k
  return State;
2725
949k
}
2726
2727
inline ClassSet EquivalenceClass::getDisequalClasses(ProgramStateRef State,
2728
0
                                                     SymbolRef Sym) {
2729
0
  return find(State, Sym).getDisequalClasses(State);
2730
0
}
2731
2732
inline ClassSet
2733
89.8k
EquivalenceClass::getDisequalClasses(ProgramStateRef State) const {
2734
89.8k
  return getDisequalClasses(State->get<DisequalityMap>(),
2735
89.8k
                            State->get_context<ClassSet>());
2736
89.8k
}
2737
2738
inline ClassSet
2739
EquivalenceClass::getDisequalClasses(DisequalityMapTy Map,
2740
262k
                                     ClassSet::Factory &Factory) const {
2741
262k
  if (const ClassSet *DisequalClasses = Map.lookup(*this))
2742
3.68k
    return *DisequalClasses;
2743
2744
259k
  return Factory.getEmptySet();
2745
262k
}
2746
2747
427k
bool EquivalenceClass::isClassDataConsistent(ProgramStateRef State) {
2748
427k
  ClassMembersTy Members = State->get<ClassMembers>();
2749
2750
427k
  for (std::pair<EquivalenceClass, SymbolSet> ClassMembersPair : Members) {
2751
48.0k
    for (SymbolRef Member : ClassMembersPair.second) {
2752
      // Every member of the class should have a mapping back to the class.
2753
48.0k
      if (find(State, Member) == ClassMembersPair.first) {
2754
48.0k
        continue;
2755
48.0k
      }
2756
2757
0
      return false;
2758
48.0k
    }
2759
46.6k
  }
2760
2761
427k
  DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2762
427k
  for (std::pair<EquivalenceClass, ClassSet> DisequalityInfo : Disequalities) {
2763
48.2k
    EquivalenceClass Class = DisequalityInfo.first;
2764
48.2k
    ClassSet DisequalClasses = DisequalityInfo.second;
2765
2766
    // There is no use in keeping empty sets in the map.
2767
48.2k
    if (DisequalClasses.isEmpty())
2768
0
      return false;
2769
2770
    // Disequality is symmetrical, i.e. for every Class A and B that A != B,
2771
    // B != A should also be true.
2772
54.1k
    
for (EquivalenceClass DisequalClass : DisequalClasses)48.2k
{
2773
54.1k
      const ClassSet *DisequalToDisequalClasses =
2774
54.1k
          Disequalities.lookup(DisequalClass);
2775
2776
      // It should be a set of at least one element: Class
2777
54.1k
      if (!DisequalToDisequalClasses ||
2778
54.1k
          !DisequalToDisequalClasses->contains(Class))
2779
0
        return false;
2780
54.1k
    }
2781
48.2k
  }
2782
2783
427k
  return true;
2784
427k
}
2785
2786
//===----------------------------------------------------------------------===//
2787
//                    RangeConstraintManager implementation
2788
//===----------------------------------------------------------------------===//
2789
2790
1.34M
bool RangeConstraintManager::canReasonAbout(SVal X) const {
2791
1.34M
  std::optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
2792
1.34M
  if (SymVal && 
SymVal->isExpression()294k
) {
2793
283k
    const SymExpr *SE = SymVal->getSymbol();
2794
2795
283k
    if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
2796
241k
      switch (SIE->getOpcode()) {
2797
      // We don't reason yet about bitwise-constraints on symbolic values.
2798
42
      case BO_And:
2799
42
      case BO_Or:
2800
42
      case BO_Xor:
2801
42
        return false;
2802
      // We don't reason yet about these arithmetic constraints on
2803
      // symbolic values.
2804
2.55k
      case BO_Mul:
2805
2.55k
      case BO_Div:
2806
2.55k
      case BO_Rem:
2807
2.55k
      case BO_Shl:
2808
2.55k
      case BO_Shr:
2809
2.55k
        return false;
2810
      // All other cases.
2811
239k
      default:
2812
239k
        return true;
2813
241k
      }
2814
241k
    }
2815
2816
41.6k
    if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
2817
      // FIXME: Handle <=> here.
2818
41.6k
      if (BinaryOperator::isEqualityOp(SSE->getOpcode()) ||
2819
41.6k
          
BinaryOperator::isRelationalOp(SSE->getOpcode())39.4k
) {
2820
        // We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc.
2821
        // We've recently started producing Loc <> NonLoc comparisons (that
2822
        // result from casts of one of the operands between eg. intptr_t and
2823
        // void *), but we can't reason about them yet.
2824
34.4k
        if (Loc::isLocType(SSE->getLHS()->getType())) {
2825
986
          return Loc::isLocType(SSE->getRHS()->getType());
2826
986
        }
2827
34.4k
      }
2828
41.6k
    }
2829
2830
40.7k
    return false;
2831
41.6k
  }
2832
2833
1.05M
  return true;
2834
1.34M
}
2835
2836
ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
2837
71.1k
                                                    SymbolRef Sym) {
2838
71.1k
  const RangeSet *Ranges = getConstraint(State, Sym);
2839
2840
  // If we don't have any information about this symbol, it's underconstrained.
2841
71.1k
  if (!Ranges)
2842
37.3k
    return ConditionTruthVal();
2843
2844
  // If we have a concrete value, see if it's zero.
2845
33.7k
  if (const llvm::APSInt *Value = Ranges->getConcreteValue())
2846
17.1k
    return *Value == 0;
2847
2848
16.6k
  BasicValueFactory &BV = getBasicVals();
2849
16.6k
  APSIntType IntType = BV.getAPSIntType(Sym->getType());
2850
16.6k
  llvm::APSInt Zero = IntType.getZeroValue();
2851
2852
  // Check if zero is in the set of possible values.
2853
16.6k
  if (!Ranges->contains(Zero))
2854
16.5k
    return false;
2855
2856
  // Zero is a possible value, but it is not the /only/ possible value.
2857
130
  return ConditionTruthVal();
2858
16.6k
}
2859
2860
const llvm::APSInt *RangeConstraintManager::getSymVal(ProgramStateRef St,
2861
7.92M
                                                      SymbolRef Sym) const {
2862
7.92M
  const RangeSet *T = getConstraint(St, Sym);
2863
7.92M
  return T ? 
T->getConcreteValue()1.76M
:
nullptr6.15M
;
2864
7.92M
}
2865
2866
//===----------------------------------------------------------------------===//
2867
//                Remove dead symbols from existing constraints
2868
//===----------------------------------------------------------------------===//
2869
2870
/// Scan all symbols referenced by the constraints. If the symbol is not alive
2871
/// as marked in LSymbols, mark it as dead in DSymbols.
2872
ProgramStateRef
2873
RangeConstraintManager::removeDeadBindings(ProgramStateRef State,
2874
427k
                                           SymbolReaper &SymReaper) {
2875
427k
  ClassMembersTy ClassMembersMap = State->get<ClassMembers>();
2876
427k
  ClassMembersTy NewClassMembersMap = ClassMembersMap;
2877
427k
  ClassMembersTy::Factory &EMFactory = State->get_context<ClassMembers>();
2878
427k
  SymbolSet::Factory &SetFactory = State->get_context<SymbolSet>();
2879
2880
427k
  ConstraintRangeTy Constraints = State->get<ConstraintRange>();
2881
427k
  ConstraintRangeTy NewConstraints = Constraints;
2882
427k
  ConstraintRangeTy::Factory &ConstraintFactory =
2883
427k
      State->get_context<ConstraintRange>();
2884
2885
427k
  ClassMapTy Map = State->get<ClassMap>();
2886
427k
  ClassMapTy NewMap = Map;
2887
427k
  ClassMapTy::Factory &ClassFactory = State->get_context<ClassMap>();
2888
2889
427k
  DisequalityMapTy Disequalities = State->get<DisequalityMap>();
2890
427k
  DisequalityMapTy::Factory &DisequalityFactory =
2891
427k
      State->get_context<DisequalityMap>();
2892
427k
  ClassSet::Factory &ClassSetFactory = State->get_context<ClassSet>();
2893
2894
427k
  bool ClassMapChanged = false;
2895
427k
  bool MembersMapChanged = false;
2896
427k
  bool ConstraintMapChanged = false;
2897
427k
  bool DisequalitiesChanged = false;
2898
2899
427k
  auto removeDeadClass = [&](EquivalenceClass Class) {
2900
    // Remove associated constraint ranges.
2901
166k
    Constraints = ConstraintFactory.remove(Constraints, Class);
2902
166k
    ConstraintMapChanged = true;
2903
2904
    // Update disequality information to not hold any information on the
2905
    // removed class.
2906
166k
    ClassSet DisequalClasses =
2907
166k
        Class.getDisequalClasses(Disequalities, ClassSetFactory);
2908
166k
    if (!DisequalClasses.isEmpty()) {
2909
500
      for (EquivalenceClass DisequalClass : DisequalClasses) {
2910
500
        ClassSet DisequalToDisequalSet =
2911
500
            DisequalClass.getDisequalClasses(Disequalities, ClassSetFactory);
2912
        // DisequalToDisequalSet is guaranteed to be non-empty for consistent
2913
        // disequality info.
2914
500
        assert(!DisequalToDisequalSet.isEmpty());
2915
500
        ClassSet NewSet = ClassSetFactory.remove(DisequalToDisequalSet, Class);
2916
2917
        // No need in keeping an empty set.
2918
500
        if (NewSet.isEmpty()) {
2919
499
          Disequalities =
2920
499
              DisequalityFactory.remove(Disequalities, DisequalClass);
2921
499
        } else {
2922
1
          Disequalities =
2923
1
              DisequalityFactory.add(Disequalities, DisequalClass, NewSet);
2924
1
        }
2925
500
      }
2926
      // Remove the data for the class
2927
474
      Disequalities = DisequalityFactory.remove(Disequalities, Class);
2928
474
      DisequalitiesChanged = true;
2929
474
    }
2930
166k
  };
2931
2932
  // 1. Let's see if dead symbols are trivial and have associated constraints.
2933
427k
  for (std::pair<EquivalenceClass, RangeSet> ClassConstraintPair :
2934
2.86M
       Constraints) {
2935
2.86M
    EquivalenceClass Class = ClassConstraintPair.first;
2936
2.86M
    if (Class.isTriviallyDead(State, SymReaper)) {
2937
      // If this class is trivial, we can remove its constraints right away.
2938
164k
      removeDeadClass(Class);
2939
164k
    }
2940
2.86M
  }
2941
2942
  // 2. We don't need to track classes for dead symbols.
2943
427k
  for (std::pair<SymbolRef, EquivalenceClass> SymbolClassPair : Map) {
2944
46.4k
    SymbolRef Sym = SymbolClassPair.first;
2945
2946
46.4k
    if (SymReaper.isDead(Sym)) {
2947
1.58k
      ClassMapChanged = true;
2948
1.58k
      NewMap = ClassFactory.remove(NewMap, Sym);
2949
1.58k
    }
2950
46.4k
  }
2951
2952
  // 3. Remove dead members from classes and remove dead non-trivial classes
2953
  //    and their constraints.
2954
427k
  for (std::pair<EquivalenceClass, SymbolSet> ClassMembersPair :
2955
427k
       ClassMembersMap) {
2956
48.2k
    EquivalenceClass Class = ClassMembersPair.first;
2957
48.2k
    SymbolSet LiveMembers = ClassMembersPair.second;
2958
48.2k
    bool MembersChanged = false;
2959
2960
49.9k
    for (SymbolRef Member : ClassMembersPair.second) {
2961
49.9k
      if (SymReaper.isDead(Member)) {
2962
1.91k
        MembersChanged = true;
2963
1.91k
        LiveMembers = SetFactory.remove(LiveMembers, Member);
2964
1.91k
      }
2965
49.9k
    }
2966
2967
    // Check if the class changed.
2968
48.2k
    if (!MembersChanged)
2969
46.5k
      continue;
2970
2971
1.71k
    MembersMapChanged = true;
2972
2973
1.71k
    if (LiveMembers.isEmpty()) {
2974
      // The class is dead now, we need to wipe it out of the members map...
2975
1.57k
      NewClassMembersMap = EMFactory.remove(NewClassMembersMap, Class);
2976
2977
      // ...and remove all of its constraints.
2978
1.57k
      removeDeadClass(Class);
2979
1.57k
    } else {
2980
      // We need to change the members associated with the class.
2981
135
      NewClassMembersMap =
2982
135
          EMFactory.add(NewClassMembersMap, Class, LiveMembers);
2983
135
    }
2984
1.71k
  }
2985
2986
  // 4. Update the state with new maps.
2987
  //
2988
  // Here we try to be humble and update a map only if it really changed.
2989
427k
  if (ClassMapChanged)
2990
623
    State = State->set<ClassMap>(NewMap);
2991
2992
427k
  if (MembersMapChanged)
2993
750
    State = State->set<ClassMembers>(NewClassMembersMap);
2994
2995
427k
  if (ConstraintMapChanged)
2996
35.1k
    State = State->set<ConstraintRange>(Constraints);
2997
2998
427k
  if (DisequalitiesChanged)
2999
422
    State = State->set<DisequalityMap>(Disequalities);
3000
3001
427k
  assert(EquivalenceClass::isClassDataConsistent(State));
3002
3003
427k
  return State;
3004
427k
}
3005
3006
RangeSet RangeConstraintManager::getRange(ProgramStateRef State,
3007
291k
                                          SymbolRef Sym) {
3008
291k
  return SymbolicRangeInferrer::inferRange(F, State, Sym);
3009
291k
}
3010
3011
ProgramStateRef RangeConstraintManager::setRange(ProgramStateRef State,
3012
                                                 SymbolRef Sym,
3013
294k
                                                 RangeSet Range) {
3014
294k
  return ConstraintAssignor::assign(State, getSValBuilder(), F, Sym, Range);
3015
294k
}
3016
3017
//===------------------------------------------------------------------------===
3018
// assumeSymX methods: protected interface for RangeConstraintManager.
3019
//===------------------------------------------------------------------------===/
3020
3021
// The syntax for ranges below is mathematical, using [x, y] for closed ranges
3022
// and (x, y) for open ranges. These ranges are modular, corresponding with
3023
// a common treatment of C integer overflow. This means that these methods
3024
// do not have to worry about overflow; RangeSet::Intersect can handle such a
3025
// "wraparound" range.
3026
// As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1,
3027
// UINT_MAX, 0, 1, and 2.
3028
3029
ProgramStateRef
3030
RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym,
3031
                                    const llvm::APSInt &Int,
3032
108k
                                    const llvm::APSInt &Adjustment) {
3033
  // Before we do any real work, see if the value can even show up.
3034
108k
  APSIntType AdjustmentType(Adjustment);
3035
108k
  if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
3036
4
    return St;
3037
3038
108k
  llvm::APSInt Point = AdjustmentType.convert(Int) - Adjustment;
3039
108k
  RangeSet New = getRange(St, Sym);
3040
108k
  New = F.deletePoint(New, Point);
3041
3042
108k
  return setRange(St, Sym, New);
3043
108k
}
3044
3045
ProgramStateRef
3046
RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym,
3047
                                    const llvm::APSInt &Int,
3048
108k
                                    const llvm::APSInt &Adjustment) {
3049
  // Before we do any real work, see if the value can even show up.
3050
108k
  APSIntType AdjustmentType(Adjustment);
3051
108k
  if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within)
3052
4
    return nullptr;
3053
3054
  // [Int-Adjustment, Int-Adjustment]
3055
108k
  llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment;
3056
108k
  RangeSet New = getRange(St, Sym);
3057
108k
  New = F.intersect(New, AdjInt);
3058
3059
108k
  return setRange(St, Sym, New);
3060
108k
}
3061
3062
RangeSet RangeConstraintManager::getSymLTRange(ProgramStateRef St,
3063
                                               SymbolRef Sym,
3064
                                               const llvm::APSInt &Int,
3065
22.0k
                                               const llvm::APSInt &Adjustment) {
3066
  // Before we do any real work, see if the value can even show up.
3067
22.0k
  APSIntType AdjustmentType(Adjustment);
3068
22.0k
  switch (AdjustmentType.testInRange(Int, true)) {
3069
10
  case APSIntType::RTR_Below:
3070
10
    return F.getEmptySet();
3071
22.0k
  case APSIntType::RTR_Within:
3072
22.0k
    break;
3073
5
  case APSIntType::RTR_Above:
3074
5
    return getRange(St, Sym);
3075
22.0k
  }
3076
3077
  // Special case for Int == Min. This is always false.
3078
22.0k
  llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3079
22.0k
  llvm::APSInt Min = AdjustmentType.getMinValue();
3080
22.0k
  if (ComparisonVal == Min)
3081
5.33k
    return F.getEmptySet();
3082
3083
16.6k
  llvm::APSInt Lower = Min - Adjustment;
3084
16.6k
  llvm::APSInt Upper = ComparisonVal - Adjustment;
3085
16.6k
  --Upper;
3086
3087
16.6k
  RangeSet Result = getRange(St, Sym);
3088
16.6k
  return F.intersect(Result, Lower, Upper);
3089
22.0k
}
3090
3091
ProgramStateRef
3092
RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym,
3093
                                    const llvm::APSInt &Int,
3094
14.7k
                                    const llvm::APSInt &Adjustment) {
3095
14.7k
  RangeSet New = getSymLTRange(St, Sym, Int, Adjustment);
3096
14.7k
  return setRange(St, Sym, New);
3097
14.7k
}
3098
3099
RangeSet RangeConstraintManager::getSymGTRange(ProgramStateRef St,
3100
                                               SymbolRef Sym,
3101
                                               const llvm::APSInt &Int,
3102
23.6k
                                               const llvm::APSInt &Adjustment) {
3103
  // Before we do any real work, see if the value can even show up.
3104
23.6k
  APSIntType AdjustmentType(Adjustment);
3105
23.6k
  switch (AdjustmentType.testInRange(Int, true)) {
3106
2
  case APSIntType::RTR_Below:
3107
2
    return getRange(St, Sym);
3108
23.6k
  case APSIntType::RTR_Within:
3109
23.6k
    break;
3110
11
  case APSIntType::RTR_Above:
3111
11
    return F.getEmptySet();
3112
23.6k
  }
3113
3114
  // Special case for Int == Max. This is always false.
3115
23.6k
  llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3116
23.6k
  llvm::APSInt Max = AdjustmentType.getMaxValue();
3117
23.6k
  if (ComparisonVal == Max)
3118
5.11k
    return F.getEmptySet();
3119
3120
18.5k
  llvm::APSInt Lower = ComparisonVal - Adjustment;
3121
18.5k
  llvm::APSInt Upper = Max - Adjustment;
3122
18.5k
  ++Lower;
3123
3124
18.5k
  RangeSet SymRange = getRange(St, Sym);
3125
18.5k
  return F.intersect(SymRange, Lower, Upper);
3126
23.6k
}
3127
3128
ProgramStateRef
3129
RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym,
3130
                                    const llvm::APSInt &Int,
3131
16.3k
                                    const llvm::APSInt &Adjustment) {
3132
16.3k
  RangeSet New = getSymGTRange(St, Sym, Int, Adjustment);
3133
16.3k
  return setRange(St, Sym, New);
3134
16.3k
}
3135
3136
RangeSet RangeConstraintManager::getSymGERange(ProgramStateRef St,
3137
                                               SymbolRef Sym,
3138
                                               const llvm::APSInt &Int,
3139
22.0k
                                               const llvm::APSInt &Adjustment) {
3140
  // Before we do any real work, see if the value can even show up.
3141
22.0k
  APSIntType AdjustmentType(Adjustment);
3142
22.0k
  switch (AdjustmentType.testInRange(Int, true)) {
3143
10
  case APSIntType::RTR_Below:
3144
10
    return getRange(St, Sym);
3145
22.0k
  case APSIntType::RTR_Within:
3146
22.0k
    break;
3147
5
  case APSIntType::RTR_Above:
3148
5
    return F.getEmptySet();
3149
22.0k
  }
3150
3151
  // Special case for Int == Min. This is always feasible.
3152
22.0k
  llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3153
22.0k
  llvm::APSInt Min = AdjustmentType.getMinValue();
3154
22.0k
  if (ComparisonVal == Min)
3155
5.33k
    return getRange(St, Sym);
3156
3157
16.6k
  llvm::APSInt Max = AdjustmentType.getMaxValue();
3158
16.6k
  llvm::APSInt Lower = ComparisonVal - Adjustment;
3159
16.6k
  llvm::APSInt Upper = Max - Adjustment;
3160
3161
16.6k
  RangeSet SymRange = getRange(St, Sym);
3162
16.6k
  return F.intersect(SymRange, Lower, Upper);
3163
22.0k
}
3164
3165
ProgramStateRef
3166
RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym,
3167
                                    const llvm::APSInt &Int,
3168
14.7k
                                    const llvm::APSInt &Adjustment) {
3169
14.7k
  RangeSet New = getSymGERange(St, Sym, Int, Adjustment);
3170
14.7k
  return setRange(St, Sym, New);
3171
14.7k
}
3172
3173
RangeSet
3174
RangeConstraintManager::getSymLERange(llvm::function_ref<RangeSet()> RS,
3175
                                      const llvm::APSInt &Int,
3176
23.5k
                                      const llvm::APSInt &Adjustment) {
3177
  // Before we do any real work, see if the value can even show up.
3178
23.5k
  APSIntType AdjustmentType(Adjustment);
3179
23.5k
  switch (AdjustmentType.testInRange(Int, true)) {
3180
2
  case APSIntType::RTR_Below:
3181
2
    return F.getEmptySet();
3182
23.5k
  case APSIntType::RTR_Within:
3183
23.5k
    break;
3184
8
  case APSIntType::RTR_Above:
3185
8
    return RS();
3186
23.5k
  }
3187
3188
  // Special case for Int == Max. This is always feasible.
3189
23.5k
  llvm::APSInt ComparisonVal = AdjustmentType.convert(Int);
3190
23.5k
  llvm::APSInt Max = AdjustmentType.getMaxValue();
3191
23.5k
  if (ComparisonVal == Max)
3192
5.07k
    return RS();
3193
3194
18.4k
  llvm::APSInt Min = AdjustmentType.getMinValue();
3195
18.4k
  llvm::APSInt Lower = Min - Adjustment;
3196
18.4k
  llvm::APSInt Upper = ComparisonVal - Adjustment;
3197
3198
18.4k
  RangeSet Default = RS();
3199
18.4k
  return F.intersect(Default, Lower, Upper);
3200
23.5k
}
3201
3202
RangeSet RangeConstraintManager::getSymLERange(ProgramStateRef St,
3203
                                               SymbolRef Sym,
3204
                                               const llvm::APSInt &Int,
3205
16.3k
                                               const llvm::APSInt &Adjustment) {
3206
16.3k
  return getSymLERange([&] 
{ return getRange(St, Sym); }16.3k
, Int, Adjustment);
3207
16.3k
}
3208
3209
ProgramStateRef
3210
RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym,
3211
                                    const llvm::APSInt &Int,
3212
16.3k
                                    const llvm::APSInt &Adjustment) {
3213
16.3k
  RangeSet New = getSymLERange(St, Sym, Int, Adjustment);
3214
16.3k
  return setRange(St, Sym, New);
3215
16.3k
}
3216
3217
ProgramStateRef RangeConstraintManager::assumeSymWithinInclusiveRange(
3218
    ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
3219
7.31k
    const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
3220
7.31k
  RangeSet New = getSymGERange(State, Sym, From, Adjustment);
3221
7.31k
  if (New.isEmpty())
3222
157
    return nullptr;
3223
7.15k
  RangeSet Out = getSymLERange([&] { return New; }, To, Adjustment);
3224
7.15k
  return setRange(State, Sym, Out);
3225
7.31k
}
3226
3227
ProgramStateRef RangeConstraintManager::assumeSymOutsideInclusiveRange(
3228
    ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
3229
7.31k
    const llvm::APSInt &To, const llvm::APSInt &Adjustment) {
3230
7.31k
  RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment);
3231
7.31k
  RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment);
3232
7.31k
  RangeSet New(F.add(RangeLT, RangeGT));
3233
7.31k
  return setRange(State, Sym, New);
3234
7.31k
}
3235
3236
//===----------------------------------------------------------------------===//
3237
// Pretty-printing.
3238
//===----------------------------------------------------------------------===//
3239
3240
void RangeConstraintManager::printJson(raw_ostream &Out, ProgramStateRef State,
3241
                                       const char *NL, unsigned int Space,
3242
158
                                       bool IsDot) const {
3243
158
  printConstraints(Out, State, NL, Space, IsDot);
3244
158
  printEquivalenceClasses(Out, State, NL, Space, IsDot);
3245
158
  printDisequalities(Out, State, NL, Space, IsDot);
3246
158
}
3247
3248
void RangeConstraintManager::printValue(raw_ostream &Out, ProgramStateRef State,
3249
19
                                        SymbolRef Sym) {
3250
19
  const RangeSet RS = getRange(State, Sym);
3251
19
  Out << RS.getBitWidth() << (RS.isUnsigned() ? 
"u:"4
:
"s:"15
);
3252
19
  RS.dump(Out);
3253
19
}
3254
3255
75
static std::string toString(const SymbolRef &Sym) {
3256
75
  std::string S;
3257
75
  llvm::raw_string_ostream O(S);
3258
75
  Sym->dumpToStream(O);
3259
75
  return O.str();
3260
75
}
3261
3262
void RangeConstraintManager::printConstraints(raw_ostream &Out,
3263
                                              ProgramStateRef State,
3264
                                              const char *NL,
3265
                                              unsigned int Space,
3266
158
                                              bool IsDot) const {
3267
158
  ConstraintRangeTy Constraints = State->get<ConstraintRange>();
3268
3269
158
  Indent(Out, Space, IsDot) << "\"constraints\": ";
3270
158
  if (Constraints.isEmpty()) {
3271
113
    Out << "null," << NL;
3272
113
    return;
3273
113
  }
3274
3275
45
  std::map<std::string, RangeSet> OrderedConstraints;
3276
63
  for (std::pair<EquivalenceClass, RangeSet> P : Constraints) {
3277
63
    SymbolSet ClassMembers = P.first.getClassMembers(State);
3278
63
    for (const SymbolRef &ClassMember : ClassMembers) {
3279
63
      bool insertion_took_place;
3280
63
      std::tie(std::ignore, insertion_took_place) =
3281
63
          OrderedConstraints.insert({toString(ClassMember), P.second});
3282
63
      assert(insertion_took_place &&
3283
63
             "two symbols should not have the same dump");
3284
63
    }
3285
63
  }
3286
3287
45
  ++Space;
3288
45
  Out << '[' << NL;
3289
45
  bool First = true;
3290
63
  for (std::pair<std::string, RangeSet> P : OrderedConstraints) {
3291
63
    if (First) {
3292
45
      First = false;
3293
45
    } else {
3294
18
      Out << ',';
3295
18
      Out << NL;
3296
18
    }
3297
63
    Indent(Out, Space, IsDot)
3298
63
        << "{ \"symbol\": \"" << P.first << "\", \"range\": \"";
3299
63
    P.second.dump(Out);
3300
63
    Out << "\" }";
3301
63
  }
3302
45
  Out << NL;
3303
3304
45
  --Space;
3305
45
  Indent(Out, Space, IsDot) << "]," << NL;
3306
45
}
3307
3308
32
static std::string toString(ProgramStateRef State, EquivalenceClass Class) {
3309
32
  SymbolSet ClassMembers = Class.getClassMembers(State);
3310
32
  llvm::SmallVector<SymbolRef, 8> ClassMembersSorted(ClassMembers.begin(),
3311
32
                                                     ClassMembers.end());
3312
32
  llvm::sort(ClassMembersSorted,
3313
32
             [](const SymbolRef &LHS, const SymbolRef &RHS) {
3314
6
               return toString(LHS) < toString(RHS);
3315
6
             });
3316
3317
32
  bool FirstMember = true;
3318
3319
32
  std::string Str;
3320
32
  llvm::raw_string_ostream Out(Str);
3321
32
  Out << "[ ";
3322
38
  for (SymbolRef ClassMember : ClassMembersSorted) {
3323
38
    if (FirstMember)
3324
32
      FirstMember = false;
3325
6
    else
3326
6
      Out << ", ";
3327
38
    Out << "\"" << ClassMember << "\"";
3328
38
  }
3329
32
  Out << " ]";
3330
32
  return Out.str();
3331
32
}
3332
3333
void RangeConstraintManager::printEquivalenceClasses(raw_ostream &Out,
3334
                                                     ProgramStateRef State,
3335
                                                     const char *NL,
3336
                                                     unsigned int Space,
3337
158
                                                     bool IsDot) const {
3338
158
  ClassMembersTy Members = State->get<ClassMembers>();
3339
3340
158
  Indent(Out, Space, IsDot) << "\"equivalence_classes\": ";
3341
158
  if (Members.isEmpty()) {
3342
151
    Out << "null," << NL;
3343
151
    return;
3344
151
  }
3345
3346
7
  std::set<std::string> MembersStr;
3347
7
  for (std::pair<EquivalenceClass, SymbolSet> ClassToSymbolSet : Members)
3348
13
    MembersStr.insert(toString(State, ClassToSymbolSet.first));
3349
3350
7
  ++Space;
3351
7
  Out << '[' << NL;
3352
7
  bool FirstClass = true;
3353
13
  for (const std::string &Str : MembersStr) {
3354
13
    if (FirstClass) {
3355
7
      FirstClass = false;
3356
7
    } else {
3357
6
      Out << ',';
3358
6
      Out << NL;
3359
6
    }
3360
13
    Indent(Out, Space, IsDot);
3361
13
    Out << Str;
3362
13
  }
3363
7
  Out << NL;
3364
3365
7
  --Space;
3366
7
  Indent(Out, Space, IsDot) << "]," << NL;
3367
7
}
3368
3369
void RangeConstraintManager::printDisequalities(raw_ostream &Out,
3370
                                                ProgramStateRef State,
3371
                                                const char *NL,
3372
                                                unsigned int Space,
3373
158
                                                bool IsDot) const {
3374
158
  DisequalityMapTy Disequalities = State->get<DisequalityMap>();
3375
3376
158
  Indent(Out, Space, IsDot) << "\"disequality_info\": ";
3377
158
  if (Disequalities.isEmpty()) {
3378
154
    Out << "null," << NL;
3379
154
    return;
3380
154
  }
3381
3382
  // Transform the disequality info to an ordered map of
3383
  // [string -> (ordered set of strings)]
3384
4
  using EqClassesStrTy = std::set<std::string>;
3385
4
  using DisequalityInfoStrTy = std::map<std::string, EqClassesStrTy>;
3386
4
  DisequalityInfoStrTy DisequalityInfoStr;
3387
9
  for (std::pair<EquivalenceClass, ClassSet> ClassToDisEqSet : Disequalities) {
3388
9
    EquivalenceClass Class = ClassToDisEqSet.first;
3389
9
    ClassSet DisequalClasses = ClassToDisEqSet.second;
3390
9
    EqClassesStrTy MembersStr;
3391
9
    for (EquivalenceClass DisEqClass : DisequalClasses)
3392
10
      MembersStr.insert(toString(State, DisEqClass));
3393
9
    DisequalityInfoStr.insert({toString(State, Class), MembersStr});
3394
9
  }
3395
3396
4
  ++Space;
3397
4
  Out << '[' << NL;
3398
4
  bool FirstClass = true;
3399
4
  for (std::pair<std::string, EqClassesStrTy> ClassToDisEqSet :
3400
9
       DisequalityInfoStr) {
3401
9
    const std::string &Class = ClassToDisEqSet.first;
3402
9
    if (FirstClass) {
3403
4
      FirstClass = false;
3404
5
    } else {
3405
5
      Out << ',';
3406
5
      Out << NL;
3407
5
    }
3408
9
    Indent(Out, Space, IsDot) << "{" << NL;
3409
9
    unsigned int DisEqSpace = Space + 1;
3410
9
    Indent(Out, DisEqSpace, IsDot) << "\"class\": ";
3411
9
    Out << Class;
3412
9
    const EqClassesStrTy &DisequalClasses = ClassToDisEqSet.second;
3413
9
    if (!DisequalClasses.empty()) {
3414
9
      Out << "," << NL;
3415
9
      Indent(Out, DisEqSpace, IsDot) << "\"disequal_to\": [" << NL;
3416
9
      unsigned int DisEqClassSpace = DisEqSpace + 1;
3417
9
      Indent(Out, DisEqClassSpace, IsDot);
3418
9
      bool FirstDisEqClass = true;
3419
10
      for (const std::string &DisEqClass : DisequalClasses) {
3420
10
        if (FirstDisEqClass) {
3421
9
          FirstDisEqClass = false;
3422
9
        } else {
3423
1
          Out << ',' << NL;
3424
1
          Indent(Out, DisEqClassSpace, IsDot);
3425
1
        }
3426
10
        Out << DisEqClass;
3427
10
      }
3428
9
      Out << "]" << NL;
3429
9
    }
3430
9
    Indent(Out, Space, IsDot) << "}";
3431
9
  }
3432
4
  Out << NL;
3433
3434
4
  --Space;
3435
4
  Indent(Out, Space, IsDot) << "]," << NL;
3436
4
}