1 //== RangeConstraintManager.cpp - Manage range constraints.------*- C++ -*--==// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines RangeConstraintManager, a class that tracks simple 11 // equality and inequality constraints on symbolic values of ProgramState. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "SimpleConstraintManager.h" 16 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" 17 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" 19 #include "llvm/ADT/FoldingSet.h" 20 #include "llvm/ADT/ImmutableSet.h" 21 #include "llvm/Support/raw_ostream.h" 22 23 using namespace clang; 24 using namespace ento; 25 26 /// A Range represents the closed range [from, to]. The caller must 27 /// guarantee that from <= to. Note that Range is immutable, so as not 28 /// to subvert RangeSet's immutability. 29 namespace { 30 class Range : public std::pair<const llvm::APSInt*, 31 const llvm::APSInt*> { 32 public: 33 Range(const llvm::APSInt &from, const llvm::APSInt &to) 34 : std::pair<const llvm::APSInt*, const llvm::APSInt*>(&from, &to) { 35 assert(from <= to); 36 } 37 bool Includes(const llvm::APSInt &v) const { 38 return *first <= v && v <= *second; 39 } 40 const llvm::APSInt &From() const { 41 return *first; 42 } 43 const llvm::APSInt &To() const { 44 return *second; 45 } 46 const llvm::APSInt *getConcreteValue() const { 47 return &From() == &To() ? &From() : nullptr; 48 } 49 50 void Profile(llvm::FoldingSetNodeID &ID) const { 51 ID.AddPointer(&From()); 52 ID.AddPointer(&To()); 53 } 54 }; 55 56 57 class RangeTrait : public llvm::ImutContainerInfo<Range> { 58 public: 59 // When comparing if one Range is less than another, we should compare 60 // the actual APSInt values instead of their pointers. This keeps the order 61 // consistent (instead of comparing by pointer values) and can potentially 62 // be used to speed up some of the operations in RangeSet. 63 static inline bool isLess(key_type_ref lhs, key_type_ref rhs) { 64 return *lhs.first < *rhs.first || (!(*rhs.first < *lhs.first) && 65 *lhs.second < *rhs.second); 66 } 67 }; 68 69 /// RangeSet contains a set of ranges. If the set is empty, then 70 /// there the value of a symbol is overly constrained and there are no 71 /// possible values for that symbol. 72 class RangeSet { 73 typedef llvm::ImmutableSet<Range, RangeTrait> PrimRangeSet; 74 PrimRangeSet ranges; // no need to make const, since it is an 75 // ImmutableSet - this allows default operator= 76 // to work. 77 public: 78 typedef PrimRangeSet::Factory Factory; 79 typedef PrimRangeSet::iterator iterator; 80 81 RangeSet(PrimRangeSet RS) : ranges(RS) {} 82 83 /// Create a new set with all ranges of this set and RS. 84 /// Possible intersections are not checked here. 85 RangeSet addRange(Factory &F, const RangeSet &RS) { 86 PrimRangeSet Ranges(RS.ranges); 87 for (const auto &range : ranges) 88 Ranges = F.add(Ranges, range); 89 return RangeSet(Ranges); 90 } 91 92 iterator begin() const { return ranges.begin(); } 93 iterator end() const { return ranges.end(); } 94 95 bool isEmpty() const { return ranges.isEmpty(); } 96 97 /// Construct a new RangeSet representing '{ [from, to] }'. 98 RangeSet(Factory &F, const llvm::APSInt &from, const llvm::APSInt &to) 99 : ranges(F.add(F.getEmptySet(), Range(from, to))) {} 100 101 /// Profile - Generates a hash profile of this RangeSet for use 102 /// by FoldingSet. 103 void Profile(llvm::FoldingSetNodeID &ID) const { ranges.Profile(ID); } 104 105 /// getConcreteValue - If a symbol is contrained to equal a specific integer 106 /// constant then this method returns that value. Otherwise, it returns 107 /// NULL. 108 const llvm::APSInt* getConcreteValue() const { 109 return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : nullptr; 110 } 111 112 private: 113 void IntersectInRange(BasicValueFactory &BV, Factory &F, 114 const llvm::APSInt &Lower, 115 const llvm::APSInt &Upper, 116 PrimRangeSet &newRanges, 117 PrimRangeSet::iterator &i, 118 PrimRangeSet::iterator &e) const { 119 // There are six cases for each range R in the set: 120 // 1. R is entirely before the intersection range. 121 // 2. R is entirely after the intersection range. 122 // 3. R contains the entire intersection range. 123 // 4. R starts before the intersection range and ends in the middle. 124 // 5. R starts in the middle of the intersection range and ends after it. 125 // 6. R is entirely contained in the intersection range. 126 // These correspond to each of the conditions below. 127 for (/* i = begin(), e = end() */; i != e; ++i) { 128 if (i->To() < Lower) { 129 continue; 130 } 131 if (i->From() > Upper) { 132 break; 133 } 134 135 if (i->Includes(Lower)) { 136 if (i->Includes(Upper)) { 137 newRanges = F.add(newRanges, Range(BV.getValue(Lower), 138 BV.getValue(Upper))); 139 break; 140 } else 141 newRanges = F.add(newRanges, Range(BV.getValue(Lower), i->To())); 142 } else { 143 if (i->Includes(Upper)) { 144 newRanges = F.add(newRanges, Range(i->From(), BV.getValue(Upper))); 145 break; 146 } else 147 newRanges = F.add(newRanges, *i); 148 } 149 } 150 } 151 152 const llvm::APSInt &getMinValue() const { 153 assert(!isEmpty()); 154 return ranges.begin()->From(); 155 } 156 157 bool pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const { 158 // This function has nine cases, the cartesian product of range-testing 159 // both the upper and lower bounds against the symbol's type. 160 // Each case requires a different pinning operation. 161 // The function returns false if the described range is entirely outside 162 // the range of values for the associated symbol. 163 APSIntType Type(getMinValue()); 164 APSIntType::RangeTestResultKind LowerTest = Type.testInRange(Lower, true); 165 APSIntType::RangeTestResultKind UpperTest = Type.testInRange(Upper, true); 166 167 switch (LowerTest) { 168 case APSIntType::RTR_Below: 169 switch (UpperTest) { 170 case APSIntType::RTR_Below: 171 // The entire range is outside the symbol's set of possible values. 172 // If this is a conventionally-ordered range, the state is infeasible. 173 if (Lower <= Upper) 174 return false; 175 176 // However, if the range wraps around, it spans all possible values. 177 Lower = Type.getMinValue(); 178 Upper = Type.getMaxValue(); 179 break; 180 case APSIntType::RTR_Within: 181 // The range starts below what's possible but ends within it. Pin. 182 Lower = Type.getMinValue(); 183 Type.apply(Upper); 184 break; 185 case APSIntType::RTR_Above: 186 // The range spans all possible values for the symbol. Pin. 187 Lower = Type.getMinValue(); 188 Upper = Type.getMaxValue(); 189 break; 190 } 191 break; 192 case APSIntType::RTR_Within: 193 switch (UpperTest) { 194 case APSIntType::RTR_Below: 195 // The range wraps around, but all lower values are not possible. 196 Type.apply(Lower); 197 Upper = Type.getMaxValue(); 198 break; 199 case APSIntType::RTR_Within: 200 // The range may or may not wrap around, but both limits are valid. 201 Type.apply(Lower); 202 Type.apply(Upper); 203 break; 204 case APSIntType::RTR_Above: 205 // The range starts within what's possible but ends above it. Pin. 206 Type.apply(Lower); 207 Upper = Type.getMaxValue(); 208 break; 209 } 210 break; 211 case APSIntType::RTR_Above: 212 switch (UpperTest) { 213 case APSIntType::RTR_Below: 214 // The range wraps but is outside the symbol's set of possible values. 215 return false; 216 case APSIntType::RTR_Within: 217 // The range starts above what's possible but ends within it (wrap). 218 Lower = Type.getMinValue(); 219 Type.apply(Upper); 220 break; 221 case APSIntType::RTR_Above: 222 // The entire range is outside the symbol's set of possible values. 223 // If this is a conventionally-ordered range, the state is infeasible. 224 if (Lower <= Upper) 225 return false; 226 227 // However, if the range wraps around, it spans all possible values. 228 Lower = Type.getMinValue(); 229 Upper = Type.getMaxValue(); 230 break; 231 } 232 break; 233 } 234 235 return true; 236 } 237 238 public: 239 // Returns a set containing the values in the receiving set, intersected with 240 // the closed range [Lower, Upper]. Unlike the Range type, this range uses 241 // modular arithmetic, corresponding to the common treatment of C integer 242 // overflow. Thus, if the Lower bound is greater than the Upper bound, the 243 // range is taken to wrap around. This is equivalent to taking the 244 // intersection with the two ranges [Min, Upper] and [Lower, Max], 245 // or, alternatively, /removing/ all integers between Upper and Lower. 246 RangeSet Intersect(BasicValueFactory &BV, Factory &F, 247 llvm::APSInt Lower, llvm::APSInt Upper) const { 248 if (!pin(Lower, Upper)) 249 return F.getEmptySet(); 250 251 PrimRangeSet newRanges = F.getEmptySet(); 252 253 PrimRangeSet::iterator i = begin(), e = end(); 254 if (Lower <= Upper) 255 IntersectInRange(BV, F, Lower, Upper, newRanges, i, e); 256 else { 257 // The order of the next two statements is important! 258 // IntersectInRange() does not reset the iteration state for i and e. 259 // Therefore, the lower range most be handled first. 260 IntersectInRange(BV, F, BV.getMinValue(Upper), Upper, newRanges, i, e); 261 IntersectInRange(BV, F, Lower, BV.getMaxValue(Lower), newRanges, i, e); 262 } 263 264 return newRanges; 265 } 266 267 void print(raw_ostream &os) const { 268 bool isFirst = true; 269 os << "{ "; 270 for (iterator i = begin(), e = end(); i != e; ++i) { 271 if (isFirst) 272 isFirst = false; 273 else 274 os << ", "; 275 276 os << '[' << i->From().toString(10) << ", " << i->To().toString(10) 277 << ']'; 278 } 279 os << " }"; 280 } 281 282 bool operator==(const RangeSet &other) const { 283 return ranges == other.ranges; 284 } 285 }; 286 } // end anonymous namespace 287 288 REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintRange, 289 CLANG_ENTO_PROGRAMSTATE_MAP(SymbolRef, 290 RangeSet)) 291 292 namespace { 293 class RangeConstraintManager : public SimpleConstraintManager{ 294 RangeSet GetRange(ProgramStateRef state, SymbolRef sym); 295 public: 296 RangeConstraintManager(SubEngine *subengine, SValBuilder &SVB) 297 : SimpleConstraintManager(subengine, SVB) {} 298 299 ProgramStateRef assumeSymNE(ProgramStateRef state, SymbolRef sym, 300 const llvm::APSInt& Int, 301 const llvm::APSInt& Adjustment) override; 302 303 ProgramStateRef assumeSymEQ(ProgramStateRef state, SymbolRef sym, 304 const llvm::APSInt& Int, 305 const llvm::APSInt& Adjustment) override; 306 307 ProgramStateRef assumeSymLT(ProgramStateRef state, SymbolRef sym, 308 const llvm::APSInt& Int, 309 const llvm::APSInt& Adjustment) override; 310 311 ProgramStateRef assumeSymGT(ProgramStateRef state, SymbolRef sym, 312 const llvm::APSInt& Int, 313 const llvm::APSInt& Adjustment) override; 314 315 ProgramStateRef assumeSymGE(ProgramStateRef state, SymbolRef sym, 316 const llvm::APSInt& Int, 317 const llvm::APSInt& Adjustment) override; 318 319 ProgramStateRef assumeSymLE(ProgramStateRef state, SymbolRef sym, 320 const llvm::APSInt& Int, 321 const llvm::APSInt& Adjustment) override; 322 323 ProgramStateRef assumeSymbolWithinInclusiveRange( 324 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, 325 const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; 326 327 ProgramStateRef assumeSymbolOutOfInclusiveRange( 328 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, 329 const llvm::APSInt &To, const llvm::APSInt &Adjustment) override; 330 331 const llvm::APSInt* getSymVal(ProgramStateRef St, 332 SymbolRef sym) const override; 333 ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override; 334 335 ProgramStateRef removeDeadBindings(ProgramStateRef St, 336 SymbolReaper& SymReaper) override; 337 338 void print(ProgramStateRef St, raw_ostream &Out, 339 const char* nl, const char *sep) override; 340 341 private: 342 RangeSet::Factory F; 343 RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym, 344 const llvm::APSInt &Int, 345 const llvm::APSInt &Adjustment); 346 RangeSet getSymGTRange(ProgramStateRef St, SymbolRef Sym, 347 const llvm::APSInt &Int, 348 const llvm::APSInt &Adjustment); 349 RangeSet getSymLERange(ProgramStateRef St, SymbolRef Sym, 350 const llvm::APSInt &Int, 351 const llvm::APSInt &Adjustment); 352 RangeSet getSymLERange(const RangeSet &RS, const llvm::APSInt &Int, 353 const llvm::APSInt &Adjustment); 354 RangeSet getSymGERange(ProgramStateRef St, SymbolRef Sym, 355 const llvm::APSInt &Int, 356 const llvm::APSInt &Adjustment); 357 }; 358 359 } // end anonymous namespace 360 361 std::unique_ptr<ConstraintManager> 362 ento::CreateRangeConstraintManager(ProgramStateManager &StMgr, SubEngine *Eng) { 363 return llvm::make_unique<RangeConstraintManager>(Eng, StMgr.getSValBuilder()); 364 } 365 366 const llvm::APSInt* RangeConstraintManager::getSymVal(ProgramStateRef St, 367 SymbolRef sym) const { 368 const ConstraintRangeTy::data_type *T = St->get<ConstraintRange>(sym); 369 return T ? T->getConcreteValue() : nullptr; 370 } 371 372 ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State, 373 SymbolRef Sym) { 374 const RangeSet *Ranges = State->get<ConstraintRange>(Sym); 375 376 // If we don't have any information about this symbol, it's underconstrained. 377 if (!Ranges) 378 return ConditionTruthVal(); 379 380 // If we have a concrete value, see if it's zero. 381 if (const llvm::APSInt *Value = Ranges->getConcreteValue()) 382 return *Value == 0; 383 384 BasicValueFactory &BV = getBasicVals(); 385 APSIntType IntType = BV.getAPSIntType(Sym->getType()); 386 llvm::APSInt Zero = IntType.getZeroValue(); 387 388 // Check if zero is in the set of possible values. 389 if (Ranges->Intersect(BV, F, Zero, Zero).isEmpty()) 390 return false; 391 392 // Zero is a possible value, but it is not the /only/ possible value. 393 return ConditionTruthVal(); 394 } 395 396 /// Scan all symbols referenced by the constraints. If the symbol is not alive 397 /// as marked in LSymbols, mark it as dead in DSymbols. 398 ProgramStateRef 399 RangeConstraintManager::removeDeadBindings(ProgramStateRef state, 400 SymbolReaper& SymReaper) { 401 bool Changed = false; 402 ConstraintRangeTy CR = state->get<ConstraintRange>(); 403 ConstraintRangeTy::Factory &CRFactory = state->get_context<ConstraintRange>(); 404 405 for (ConstraintRangeTy::iterator I = CR.begin(), E = CR.end(); I != E; ++I) { 406 SymbolRef sym = I.getKey(); 407 if (SymReaper.maybeDead(sym)) { 408 Changed = true; 409 CR = CRFactory.remove(CR, sym); 410 } 411 } 412 413 return Changed ? state->set<ConstraintRange>(CR) : state; 414 } 415 416 RangeSet 417 RangeConstraintManager::GetRange(ProgramStateRef state, SymbolRef sym) { 418 if (ConstraintRangeTy::data_type* V = state->get<ConstraintRange>(sym)) 419 return *V; 420 421 // Lazily generate a new RangeSet representing all possible values for the 422 // given symbol type. 423 BasicValueFactory &BV = getBasicVals(); 424 QualType T = sym->getType(); 425 426 RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T)); 427 428 // Special case: references are known to be non-zero. 429 if (T->isReferenceType()) { 430 APSIntType IntType = BV.getAPSIntType(T); 431 Result = Result.Intersect(BV, F, ++IntType.getZeroValue(), 432 --IntType.getZeroValue()); 433 } 434 435 return Result; 436 } 437 438 //===------------------------------------------------------------------------=== 439 // assumeSymX methods: public interface for RangeConstraintManager. 440 //===------------------------------------------------------------------------===/ 441 442 // The syntax for ranges below is mathematical, using [x, y] for closed ranges 443 // and (x, y) for open ranges. These ranges are modular, corresponding with 444 // a common treatment of C integer overflow. This means that these methods 445 // do not have to worry about overflow; RangeSet::Intersect can handle such a 446 // "wraparound" range. 447 // As an example, the range [UINT_MAX-1, 3) contains five values: UINT_MAX-1, 448 // UINT_MAX, 0, 1, and 2. 449 450 ProgramStateRef 451 RangeConstraintManager::assumeSymNE(ProgramStateRef St, SymbolRef Sym, 452 const llvm::APSInt &Int, 453 const llvm::APSInt &Adjustment) { 454 // Before we do any real work, see if the value can even show up. 455 APSIntType AdjustmentType(Adjustment); 456 if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within) 457 return St; 458 459 llvm::APSInt Lower = AdjustmentType.convert(Int) - Adjustment; 460 llvm::APSInt Upper = Lower; 461 --Lower; 462 ++Upper; 463 464 // [Int-Adjustment+1, Int-Adjustment-1] 465 // Notice that the lower bound is greater than the upper bound. 466 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, Upper, Lower); 467 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 468 } 469 470 ProgramStateRef 471 RangeConstraintManager::assumeSymEQ(ProgramStateRef St, SymbolRef Sym, 472 const llvm::APSInt &Int, 473 const llvm::APSInt &Adjustment) { 474 // Before we do any real work, see if the value can even show up. 475 APSIntType AdjustmentType(Adjustment); 476 if (AdjustmentType.testInRange(Int, true) != APSIntType::RTR_Within) 477 return nullptr; 478 479 // [Int-Adjustment, Int-Adjustment] 480 llvm::APSInt AdjInt = AdjustmentType.convert(Int) - Adjustment; 481 RangeSet New = GetRange(St, Sym).Intersect(getBasicVals(), F, AdjInt, AdjInt); 482 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 483 } 484 485 RangeSet RangeConstraintManager::getSymLTRange(ProgramStateRef St, 486 SymbolRef Sym, 487 const llvm::APSInt &Int, 488 const llvm::APSInt &Adjustment) { 489 // Before we do any real work, see if the value can even show up. 490 APSIntType AdjustmentType(Adjustment); 491 switch (AdjustmentType.testInRange(Int, true)) { 492 case APSIntType::RTR_Below: 493 return F.getEmptySet(); 494 case APSIntType::RTR_Within: 495 break; 496 case APSIntType::RTR_Above: 497 return GetRange(St, Sym); 498 } 499 500 // Special case for Int == Min. This is always false. 501 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 502 llvm::APSInt Min = AdjustmentType.getMinValue(); 503 if (ComparisonVal == Min) 504 return F.getEmptySet(); 505 506 llvm::APSInt Lower = Min - Adjustment; 507 llvm::APSInt Upper = ComparisonVal - Adjustment; 508 --Upper; 509 510 return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 511 } 512 513 ProgramStateRef 514 RangeConstraintManager::assumeSymLT(ProgramStateRef St, SymbolRef Sym, 515 const llvm::APSInt &Int, 516 const llvm::APSInt &Adjustment) { 517 RangeSet New = getSymLTRange(St, Sym, Int, Adjustment); 518 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 519 } 520 521 RangeSet 522 RangeConstraintManager::getSymGTRange(ProgramStateRef St, SymbolRef Sym, 523 const llvm::APSInt &Int, 524 const llvm::APSInt &Adjustment) { 525 // Before we do any real work, see if the value can even show up. 526 APSIntType AdjustmentType(Adjustment); 527 switch (AdjustmentType.testInRange(Int, true)) { 528 case APSIntType::RTR_Below: 529 return GetRange(St, Sym); 530 case APSIntType::RTR_Within: 531 break; 532 case APSIntType::RTR_Above: 533 return F.getEmptySet(); 534 } 535 536 // Special case for Int == Max. This is always false. 537 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 538 llvm::APSInt Max = AdjustmentType.getMaxValue(); 539 if (ComparisonVal == Max) 540 return F.getEmptySet(); 541 542 llvm::APSInt Lower = ComparisonVal - Adjustment; 543 llvm::APSInt Upper = Max - Adjustment; 544 ++Lower; 545 546 return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 547 } 548 549 ProgramStateRef 550 RangeConstraintManager::assumeSymGT(ProgramStateRef St, SymbolRef Sym, 551 const llvm::APSInt &Int, 552 const llvm::APSInt &Adjustment) { 553 RangeSet New = getSymGTRange(St, Sym, Int, Adjustment); 554 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 555 } 556 557 RangeSet 558 RangeConstraintManager::getSymGERange(ProgramStateRef St, SymbolRef Sym, 559 const llvm::APSInt &Int, 560 const llvm::APSInt &Adjustment) { 561 // Before we do any real work, see if the value can even show up. 562 APSIntType AdjustmentType(Adjustment); 563 switch (AdjustmentType.testInRange(Int, true)) { 564 case APSIntType::RTR_Below: 565 return GetRange(St, Sym); 566 case APSIntType::RTR_Within: 567 break; 568 case APSIntType::RTR_Above: 569 return F.getEmptySet(); 570 } 571 572 // Special case for Int == Min. This is always feasible. 573 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 574 llvm::APSInt Min = AdjustmentType.getMinValue(); 575 if (ComparisonVal == Min) 576 return GetRange(St, Sym); 577 578 llvm::APSInt Max = AdjustmentType.getMaxValue(); 579 llvm::APSInt Lower = ComparisonVal - Adjustment; 580 llvm::APSInt Upper = Max - Adjustment; 581 582 return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 583 } 584 585 ProgramStateRef 586 RangeConstraintManager::assumeSymGE(ProgramStateRef St, SymbolRef Sym, 587 const llvm::APSInt &Int, 588 const llvm::APSInt &Adjustment) { 589 RangeSet New = getSymGERange(St, Sym, Int, Adjustment); 590 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 591 } 592 593 RangeSet 594 RangeConstraintManager::getSymLERange(const RangeSet &RS, 595 const llvm::APSInt &Int, 596 const llvm::APSInt &Adjustment) { 597 // Before we do any real work, see if the value can even show up. 598 APSIntType AdjustmentType(Adjustment); 599 switch (AdjustmentType.testInRange(Int, true)) { 600 case APSIntType::RTR_Below: 601 return F.getEmptySet(); 602 case APSIntType::RTR_Within: 603 break; 604 case APSIntType::RTR_Above: 605 return RS; 606 } 607 608 // Special case for Int == Max. This is always feasible. 609 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 610 llvm::APSInt Max = AdjustmentType.getMaxValue(); 611 if (ComparisonVal == Max) 612 return RS; 613 614 llvm::APSInt Min = AdjustmentType.getMinValue(); 615 llvm::APSInt Lower = Min - Adjustment; 616 llvm::APSInt Upper = ComparisonVal - Adjustment; 617 618 return RS.Intersect(getBasicVals(), F, Lower, Upper); 619 } 620 621 RangeSet 622 RangeConstraintManager::getSymLERange(ProgramStateRef St, SymbolRef Sym, 623 const llvm::APSInt &Int, 624 const llvm::APSInt &Adjustment) { 625 // Before we do any real work, see if the value can even show up. 626 APSIntType AdjustmentType(Adjustment); 627 switch (AdjustmentType.testInRange(Int, true)) { 628 case APSIntType::RTR_Below: 629 return F.getEmptySet(); 630 case APSIntType::RTR_Within: 631 break; 632 case APSIntType::RTR_Above: 633 return GetRange(St, Sym); 634 } 635 636 // Special case for Int == Max. This is always feasible. 637 llvm::APSInt ComparisonVal = AdjustmentType.convert(Int); 638 llvm::APSInt Max = AdjustmentType.getMaxValue(); 639 if (ComparisonVal == Max) 640 return GetRange(St, Sym); 641 642 llvm::APSInt Min = AdjustmentType.getMinValue(); 643 llvm::APSInt Lower = Min - Adjustment; 644 llvm::APSInt Upper = ComparisonVal - Adjustment; 645 646 return GetRange(St, Sym).Intersect(getBasicVals(), F, Lower, Upper); 647 } 648 649 ProgramStateRef 650 RangeConstraintManager::assumeSymLE(ProgramStateRef St, SymbolRef Sym, 651 const llvm::APSInt &Int, 652 const llvm::APSInt &Adjustment) { 653 RangeSet New = getSymLERange(St, Sym, Int, Adjustment); 654 return New.isEmpty() ? nullptr : St->set<ConstraintRange>(Sym, New); 655 } 656 657 ProgramStateRef 658 RangeConstraintManager::assumeSymbolWithinInclusiveRange( 659 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, 660 const llvm::APSInt &To, const llvm::APSInt &Adjustment) { 661 RangeSet New = getSymGERange(State, Sym, From, Adjustment); 662 if (New.isEmpty()) 663 return nullptr; 664 New = getSymLERange(New, To, Adjustment); 665 return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New); 666 } 667 668 ProgramStateRef 669 RangeConstraintManager::assumeSymbolOutOfInclusiveRange( 670 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, 671 const llvm::APSInt &To, const llvm::APSInt &Adjustment) { 672 RangeSet RangeLT = getSymLTRange(State, Sym, From, Adjustment); 673 RangeSet RangeGT = getSymGTRange(State, Sym, To, Adjustment); 674 RangeSet New(RangeLT.addRange(F, RangeGT)); 675 return New.isEmpty() ? nullptr : State->set<ConstraintRange>(Sym, New); 676 } 677 678 //===------------------------------------------------------------------------=== 679 // Pretty-printing. 680 //===------------------------------------------------------------------------===/ 681 682 void RangeConstraintManager::print(ProgramStateRef St, raw_ostream &Out, 683 const char* nl, const char *sep) { 684 685 ConstraintRangeTy Ranges = St->get<ConstraintRange>(); 686 687 if (Ranges.isEmpty()) { 688 Out << nl << sep << "Ranges are empty." << nl; 689 return; 690 } 691 692 Out << nl << sep << "Ranges of symbol values:"; 693 for (ConstraintRangeTy::iterator I=Ranges.begin(), E=Ranges.end(); I!=E; ++I){ 694 Out << nl << ' ' << I.getKey() << " : "; 695 I.getData().print(Out); 696 } 697 Out << nl; 698 } 699