SimpleConstraintManager.cpp 4.6 KB

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