SimpleConstraintManager.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. //== SimpleConstraintManager.cpp --------------------------------*- 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 SimpleConstraintManager, a class that provides a
  10. // simplified constraint manager interface, compared to ConstraintManager.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h"
  14. #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
  15. #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
  16. #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
  17. namespace clang {
  18. namespace ento {
  19. SimpleConstraintManager::~SimpleConstraintManager() {}
  20. ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
  21. DefinedSVal Cond,
  22. bool Assumption) {
  23. // If we have a Loc value, cast it to a bool NonLoc first.
  24. if (Optional<Loc> LV = Cond.getAs<Loc>()) {
  25. SValBuilder &SVB = State->getStateManager().getSValBuilder();
  26. QualType T;
  27. const MemRegion *MR = LV->getAsRegion();
  28. if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))
  29. T = TR->getLocationType();
  30. else
  31. T = SVB.getContext().VoidPtrTy;
  32. Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();
  33. }
  34. return assume(State, Cond.castAs<NonLoc>(), Assumption);
  35. }
  36. ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
  37. NonLoc Cond, bool Assumption) {
  38. State = assumeAux(State, Cond, Assumption);
  39. if (NotifyAssumeClients && EE)
  40. return EE->processAssume(State, Cond, Assumption);
  41. return State;
  42. }
  43. ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State,
  44. NonLoc Cond,
  45. bool Assumption) {
  46. // We cannot reason about SymSymExprs, and can only reason about some
  47. // SymIntExprs.
  48. if (!canReasonAbout(Cond)) {
  49. // Just add the constraint to the expression without trying to simplify.
  50. SymbolRef Sym = Cond.getAsSymbol();
  51. assert(Sym);
  52. return assumeSymUnsupported(State, Sym, Assumption);
  53. }
  54. switch (Cond.getSubKind()) {
  55. default:
  56. llvm_unreachable("'Assume' not implemented for this NonLoc");
  57. case nonloc::SymbolValKind: {
  58. nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
  59. SymbolRef Sym = SV.getSymbol();
  60. assert(Sym);
  61. return assumeSym(State, Sym, Assumption);
  62. }
  63. case nonloc::ConcreteIntKind: {
  64. bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
  65. bool isFeasible = b ? Assumption : !Assumption;
  66. return isFeasible ? State : nullptr;
  67. }
  68. case nonloc::PointerToMemberKind: {
  69. bool IsNull = !Cond.castAs<nonloc::PointerToMember>().isNullMemberPointer();
  70. bool IsFeasible = IsNull ? Assumption : !Assumption;
  71. return IsFeasible ? State : nullptr;
  72. }
  73. case nonloc::LocAsIntegerKind:
  74. return assume(State, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
  75. Assumption);
  76. } // end switch
  77. }
  78. ProgramStateRef SimpleConstraintManager::assumeInclusiveRange(
  79. ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
  80. const llvm::APSInt &To, bool InRange) {
  81. assert(From.isUnsigned() == To.isUnsigned() &&
  82. From.getBitWidth() == To.getBitWidth() &&
  83. "Values should have same types!");
  84. if (!canReasonAbout(Value)) {
  85. // Just add the constraint to the expression without trying to simplify.
  86. SymbolRef Sym = Value.getAsSymbol();
  87. assert(Sym);
  88. return assumeSymInclusiveRange(State, Sym, From, To, InRange);
  89. }
  90. switch (Value.getSubKind()) {
  91. default:
  92. llvm_unreachable("'assumeInclusiveRange' is not implemented"
  93. "for this NonLoc");
  94. case nonloc::LocAsIntegerKind:
  95. case nonloc::SymbolValKind: {
  96. if (SymbolRef Sym = Value.getAsSymbol())
  97. return assumeSymInclusiveRange(State, Sym, From, To, InRange);
  98. return State;
  99. } // end switch
  100. case nonloc::ConcreteIntKind: {
  101. const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue();
  102. bool IsInRange = IntVal >= From && IntVal <= To;
  103. bool isFeasible = (IsInRange == InRange);
  104. return isFeasible ? State : nullptr;
  105. }
  106. } // end switch
  107. }
  108. } // end of namespace ento
  109. } // end of namespace clang