/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
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" |
18 | | #include <optional> |
19 | | |
20 | | namespace clang { |
21 | | |
22 | | namespace ento { |
23 | | |
24 | 16.2k | SimpleConstraintManager::~SimpleConstraintManager() {} |
25 | | |
26 | | ProgramStateRef SimpleConstraintManager::assumeInternal(ProgramStateRef State, |
27 | | DefinedSVal Cond, |
28 | 1.32M | bool Assumption) { |
29 | | // If we have a Loc value, cast it to a bool NonLoc first. |
30 | 1.32M | if (std::optional<Loc> LV = Cond.getAs<Loc>()) { |
31 | 805k | SValBuilder &SVB = State->getStateManager().getSValBuilder(); |
32 | 805k | QualType T; |
33 | 805k | const MemRegion *MR = LV->getAsRegion(); |
34 | 805k | if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR)) |
35 | 766k | T = TR->getLocationType(); |
36 | 39.4k | else |
37 | 39.4k | T = SVB.getContext().VoidPtrTy; |
38 | | |
39 | 805k | Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>(); |
40 | 805k | } |
41 | | |
42 | 1.32M | return assume(State, Cond.castAs<NonLoc>(), Assumption); |
43 | 1.32M | } |
44 | | |
45 | | ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State, |
46 | 1.32M | NonLoc Cond, bool Assumption) { |
47 | 1.32M | State = assumeAux(State, Cond, Assumption); |
48 | 1.32M | if (EE) |
49 | 1.32M | return EE->processAssume(State, Cond, Assumption); |
50 | 0 | return State; |
51 | 1.32M | } |
52 | | |
53 | | ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State, |
54 | | NonLoc Cond, |
55 | 1.32M | bool Assumption) { |
56 | | |
57 | | // We cannot reason about SymSymExprs, and can only reason about some |
58 | | // SymIntExprs. |
59 | 1.32M | if (!canReasonAbout(Cond)) { |
60 | | // Just add the constraint to the expression without trying to simplify. |
61 | 35.0k | SymbolRef Sym = Cond.getAsSymbol(); |
62 | 35.0k | assert(Sym); |
63 | 35.0k | return assumeSymUnsupported(State, Sym, Assumption); |
64 | 35.0k | } |
65 | | |
66 | 1.28M | switch (Cond.getSubKind()) { |
67 | 0 | default: |
68 | 0 | llvm_unreachable("'Assume' not implemented for this NonLoc"); |
69 | |
|
70 | 243k | case nonloc::SymbolValKind: { |
71 | 243k | nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>(); |
72 | 243k | SymbolRef Sym = SV.getSymbol(); |
73 | 243k | assert(Sym); |
74 | 243k | return assumeSym(State, Sym, Assumption); |
75 | 243k | } |
76 | | |
77 | 1.04M | case nonloc::ConcreteIntKind: { |
78 | 1.04M | bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0; |
79 | 1.04M | bool isFeasible = b ? Assumption868k : !Assumption173k ; |
80 | 1.04M | return isFeasible ? State521k : nullptr521k ; |
81 | 243k | } |
82 | | |
83 | 36 | case nonloc::PointerToMemberKind: { |
84 | 36 | bool IsNull = !Cond.castAs<nonloc::PointerToMember>().isNullMemberPointer(); |
85 | 36 | bool IsFeasible = IsNull ? Assumption : !Assumption0 ; |
86 | 36 | return IsFeasible ? State18 : nullptr18 ; |
87 | 243k | } |
88 | | |
89 | 74 | case nonloc::LocAsIntegerKind: |
90 | 74 | return assumeInternal(State, Cond.castAs<nonloc::LocAsInteger>().getLoc(), |
91 | 74 | Assumption); |
92 | 1.28M | } // end switch |
93 | 1.28M | } |
94 | | |
95 | | ProgramStateRef SimpleConstraintManager::assumeInclusiveRangeInternal( |
96 | | ProgramStateRef State, NonLoc Value, const llvm::APSInt &From, |
97 | 15.9k | const llvm::APSInt &To, bool InRange) { |
98 | | |
99 | 15.9k | assert(From.isUnsigned() == To.isUnsigned() && |
100 | 15.9k | From.getBitWidth() == To.getBitWidth() && |
101 | 15.9k | "Values should have same types!"); |
102 | | |
103 | 15.9k | if (!canReasonAbout(Value)) { |
104 | | // Just add the constraint to the expression without trying to simplify. |
105 | 5.43k | SymbolRef Sym = Value.getAsSymbol(); |
106 | 5.43k | assert(Sym); |
107 | 5.43k | return assumeSymInclusiveRange(State, Sym, From, To, InRange); |
108 | 5.43k | } |
109 | | |
110 | 10.5k | switch (Value.getSubKind()) { |
111 | 0 | default: |
112 | 0 | llvm_unreachable("'assumeInclusiveRange' is not implemented" |
113 | 0 | "for this NonLoc"); |
114 | |
|
115 | 10 | case nonloc::LocAsIntegerKind: |
116 | 7.17k | case nonloc::SymbolValKind: { |
117 | 7.17k | if (SymbolRef Sym = Value.getAsSymbol()) |
118 | 7.17k | return assumeSymInclusiveRange(State, Sym, From, To, InRange); |
119 | 2 | return State; |
120 | 7.17k | } // end switch |
121 | | |
122 | 3.32k | case nonloc::ConcreteIntKind: { |
123 | 3.32k | const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue(); |
124 | 3.32k | bool IsInRange = IntVal >= From && IntVal <= To2.51k ; |
125 | 3.32k | bool isFeasible = (IsInRange == InRange); |
126 | 3.32k | return isFeasible ? State1.66k : nullptr1.66k ; |
127 | 7.17k | } |
128 | 10.5k | } // end switch |
129 | 10.5k | } |
130 | | |
131 | | } // end of namespace ento |
132 | | |
133 | | } // end of namespace clang |