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"
24 SimpleConstraintManager::~SimpleConstraintManager() {}
26 ProgramStateRef
SimpleConstraintManager::assumeInternal(ProgramStateRef State
,
29 // If we have a Loc value, cast it to a bool NonLoc first.
30 if (std::optional
<Loc
> LV
= Cond
.getAs
<Loc
>()) {
31 SValBuilder
&SVB
= State
->getStateManager().getSValBuilder();
33 const MemRegion
*MR
= LV
->getAsRegion();
34 if (const TypedRegion
*TR
= dyn_cast_or_null
<TypedRegion
>(MR
))
35 T
= TR
->getLocationType();
37 T
= SVB
.getContext().VoidPtrTy
;
39 Cond
= SVB
.evalCast(*LV
, SVB
.getContext().BoolTy
, T
).castAs
<DefinedSVal
>();
42 return assume(State
, Cond
.castAs
<NonLoc
>(), Assumption
);
45 ProgramStateRef
SimpleConstraintManager::assume(ProgramStateRef State
,
46 NonLoc Cond
, bool Assumption
) {
47 State
= assumeAux(State
, Cond
, Assumption
);
49 return EE
->processAssume(State
, Cond
, Assumption
);
53 ProgramStateRef
SimpleConstraintManager::assumeAux(ProgramStateRef State
,
57 // We cannot reason about SymSymExprs, and can only reason about some
59 if (!canReasonAbout(Cond
)) {
60 // Just add the constraint to the expression without trying to simplify.
61 SymbolRef Sym
= Cond
.getAsSymbol();
63 return assumeSymUnsupported(State
, Sym
, Assumption
);
66 switch (Cond
.getSubKind()) {
68 llvm_unreachable("'Assume' not implemented for this NonLoc");
70 case nonloc::SymbolValKind
: {
71 nonloc::SymbolVal SV
= Cond
.castAs
<nonloc::SymbolVal
>();
72 SymbolRef Sym
= SV
.getSymbol();
74 return assumeSym(State
, Sym
, Assumption
);
77 case nonloc::ConcreteIntKind
: {
78 bool b
= Cond
.castAs
<nonloc::ConcreteInt
>().getValue() != 0;
79 bool isFeasible
= b
? Assumption
: !Assumption
;
80 return isFeasible
? State
: nullptr;
83 case nonloc::PointerToMemberKind
: {
84 bool IsNull
= !Cond
.castAs
<nonloc::PointerToMember
>().isNullMemberPointer();
85 bool IsFeasible
= IsNull
? Assumption
: !Assumption
;
86 return IsFeasible
? State
: nullptr;
89 case nonloc::LocAsIntegerKind
:
90 return assumeInternal(State
, Cond
.castAs
<nonloc::LocAsInteger
>().getLoc(),
95 ProgramStateRef
SimpleConstraintManager::assumeInclusiveRangeInternal(
96 ProgramStateRef State
, NonLoc Value
, const llvm::APSInt
&From
,
97 const llvm::APSInt
&To
, bool InRange
) {
99 assert(From
.isUnsigned() == To
.isUnsigned() &&
100 From
.getBitWidth() == To
.getBitWidth() &&
101 "Values should have same types!");
103 if (!canReasonAbout(Value
)) {
104 // Just add the constraint to the expression without trying to simplify.
105 SymbolRef Sym
= Value
.getAsSymbol();
107 return assumeSymInclusiveRange(State
, Sym
, From
, To
, InRange
);
110 switch (Value
.getSubKind()) {
112 llvm_unreachable("'assumeInclusiveRange' is not implemented"
115 case nonloc::LocAsIntegerKind
:
116 case nonloc::SymbolValKind
: {
117 if (SymbolRef Sym
= Value
.getAsSymbol())
118 return assumeSymInclusiveRange(State
, Sym
, From
, To
, InRange
);
122 case nonloc::ConcreteIntKind
: {
123 const llvm::APSInt
&IntVal
= Value
.castAs
<nonloc::ConcreteInt
>().getValue();
124 bool IsInRange
= IntVal
>= From
&& IntVal
<= To
;
125 bool isFeasible
= (IsInRange
== InRange
);
126 return isFeasible
? State
: nullptr;
131 } // end of namespace ento
133 } // end of namespace clang