1 //== SimpleConstraintManager.cpp --------------------------------*- C++ -*--==//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines SimpleConstraintManager, a class that provides a
10 // simplified constraint manager interface, compared to ConstraintManager.
12 //===----------------------------------------------------------------------===//
14 #include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h"
15 #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
16 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
17 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
23 SimpleConstraintManager::~SimpleConstraintManager() {}
25 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
28 // If we have a Loc value, cast it to a bool NonLoc first.
29 if (Optional<Loc> LV = Cond.getAs<Loc>()) {
30 SValBuilder &SVB = State->getStateManager().getSValBuilder();
32 const MemRegion *MR = LV->getAsRegion();
33 if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))
34 T = TR->getLocationType();
36 T = SVB.getContext().VoidPtrTy;
38 Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();
41 return assume(State, Cond.castAs<NonLoc>(), Assumption);
44 ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
45 NonLoc Cond, bool Assumption) {
46 State = assumeAux(State, Cond, Assumption);
47 if (NotifyAssumeClients && SU)
48 return SU->processAssume(State, Cond, Assumption);
52 ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State,
56 // We cannot reason about SymSymExprs, and can only reason about some
58 if (!canReasonAbout(Cond)) {
59 // Just add the constraint to the expression without trying to simplify.
60 SymbolRef Sym = Cond.getAsSymExpr();
62 return assumeSymUnsupported(State, Sym, Assumption);
65 switch (Cond.getSubKind()) {
67 llvm_unreachable("'Assume' not implemented for this NonLoc");
69 case nonloc::SymbolValKind: {
70 nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
71 SymbolRef Sym = SV.getSymbol();
73 return assumeSym(State, Sym, Assumption);
76 case nonloc::ConcreteIntKind: {
77 bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
78 bool isFeasible = b ? Assumption : !Assumption;
79 return isFeasible ? State : nullptr;
82 case nonloc::PointerToMemberKind: {
83 bool IsNull = !Cond.castAs<nonloc::PointerToMember>().isNullMemberPointer();
84 bool IsFeasible = IsNull ? Assumption : !Assumption;
85 return IsFeasible ? State : nullptr;
88 case nonloc::LocAsIntegerKind:
89 return assume(State, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
94 ProgramStateRef SimpleConstraintManager::assumeInclusiveRange(
95 ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
96 const llvm::APSInt &To, bool InRange) {
98 assert(From.isUnsigned() == To.isUnsigned() &&
99 From.getBitWidth() == To.getBitWidth() &&
100 "Values should have same types!");
102 if (!canReasonAbout(Value)) {
103 // Just add the constraint to the expression without trying to simplify.
104 SymbolRef Sym = Value.getAsSymExpr();
106 return assumeSymInclusiveRange(State, Sym, From, To, InRange);
109 switch (Value.getSubKind()) {
111 llvm_unreachable("'assumeInclusiveRange' is not implemented"
114 case nonloc::LocAsIntegerKind:
115 case nonloc::SymbolValKind: {
116 if (SymbolRef Sym = Value.getAsSymbol())
117 return assumeSymInclusiveRange(State, Sym, From, To, InRange);
121 case nonloc::ConcreteIntKind: {
122 const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue();
123 bool IsInRange = IntVal >= From && IntVal <= To;
124 bool isFeasible = (IsInRange == InRange);
125 return isFeasible ? State : nullptr;
130 } // end of namespace ento
132 } // end of namespace clang