/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/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 | | |
19 | | namespace clang { |
20 | | |
21 | | namespace ento { |
22 | | |
23 | 10.8k | SimpleConstraintManager::~SimpleConstraintManager() {} |
24 | | |
25 | | ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State, |
26 | | DefinedSVal Cond, |
27 | 665k | bool Assumption) { |
28 | 665k | // If we have a Loc value, cast it to a bool NonLoc first. |
29 | 665k | if (Optional<Loc> LV = Cond.getAs<Loc>()) { |
30 | 548k | SValBuilder &SVB = State->getStateManager().getSValBuilder(); |
31 | 548k | QualType T; |
32 | 548k | const MemRegion *MR = LV->getAsRegion(); |
33 | 548k | if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR)) |
34 | 530k | T = TR->getLocationType(); |
35 | 17.7k | else |
36 | 17.7k | T = SVB.getContext().VoidPtrTy; |
37 | 548k | |
38 | 548k | Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>(); |
39 | 548k | } |
40 | 665k | |
41 | 665k | return assume(State, Cond.castAs<NonLoc>(), Assumption); |
42 | 665k | } |
43 | | |
44 | | ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State, |
45 | 665k | NonLoc Cond, bool Assumption) { |
46 | 665k | State = assumeAux(State, Cond, Assumption); |
47 | 665k | if (NotifyAssumeClients && SU) |
48 | 665k | return SU->processAssume(State, Cond, Assumption); |
49 | 0 | return State; |
50 | 0 | } |
51 | | |
52 | | ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State, |
53 | | NonLoc Cond, |
54 | 665k | bool Assumption) { |
55 | 665k | |
56 | 665k | // We cannot reason about SymSymExprs, and can only reason about some |
57 | 665k | // SymIntExprs. |
58 | 665k | if (!canReasonAbout(Cond)) { |
59 | 3.74k | // Just add the constraint to the expression without trying to simplify. |
60 | 3.74k | SymbolRef Sym = Cond.getAsSymExpr(); |
61 | 3.74k | assert(Sym); |
62 | 3.74k | return assumeSymUnsupported(State, Sym, Assumption); |
63 | 3.74k | } |
64 | 661k | |
65 | 661k | switch (Cond.getSubKind()) { |
66 | 661k | default: |
67 | 0 | llvm_unreachable("'Assume' not implemented for this NonLoc"); |
68 | 661k | |
69 | 661k | case nonloc::SymbolValKind: { |
70 | 160k | nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>(); |
71 | 160k | SymbolRef Sym = SV.getSymbol(); |
72 | 160k | assert(Sym); |
73 | 160k | return assumeSym(State, Sym, Assumption); |
74 | 661k | } |
75 | 661k | |
76 | 661k | case nonloc::ConcreteIntKind: { |
77 | 500k | bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0; |
78 | 500k | bool isFeasible = b ? Assumption486k : !Assumption14.8k ; |
79 | 500k | return isFeasible ? State243k : nullptr257k ; |
80 | 661k | } |
81 | 661k | |
82 | 661k | case nonloc::PointerToMemberKind: { |
83 | 16 | bool IsNull = !Cond.castAs<nonloc::PointerToMember>().isNullMemberPointer(); |
84 | 16 | bool IsFeasible = IsNull ? Assumption : !Assumption0 ; |
85 | 16 | return IsFeasible ? State8 : nullptr8 ; |
86 | 661k | } |
87 | 661k | |
88 | 661k | case nonloc::LocAsIntegerKind: |
89 | 34 | return assume(State, Cond.castAs<nonloc::LocAsInteger>().getLoc(), |
90 | 34 | Assumption); |
91 | 661k | } // end switch |
92 | 661k | } |
93 | | |
94 | | ProgramStateRef SimpleConstraintManager::assumeInclusiveRange( |
95 | | ProgramStateRef State, NonLoc Value, const llvm::APSInt &From, |
96 | 2.49k | const llvm::APSInt &To, bool InRange) { |
97 | 2.49k | |
98 | 2.49k | assert(From.isUnsigned() == To.isUnsigned() && |
99 | 2.49k | From.getBitWidth() == To.getBitWidth() && |
100 | 2.49k | "Values should have same types!"); |
101 | 2.49k | |
102 | 2.49k | if (!canReasonAbout(Value)) { |
103 | 12 | // Just add the constraint to the expression without trying to simplify. |
104 | 12 | SymbolRef Sym = Value.getAsSymExpr(); |
105 | 12 | assert(Sym); |
106 | 12 | return assumeSymInclusiveRange(State, Sym, From, To, InRange); |
107 | 12 | } |
108 | 2.47k | |
109 | 2.47k | switch (Value.getSubKind()) { |
110 | 2.47k | default: |
111 | 0 | llvm_unreachable("'assumeInclusiveRange' is not implemented" |
112 | 2.47k | "for this NonLoc"); |
113 | 2.47k | |
114 | 2.47k | case nonloc::LocAsIntegerKind: |
115 | 1.76k | case nonloc::SymbolValKind: { |
116 | 1.76k | if (SymbolRef Sym = Value.getAsSymbol()) |
117 | 1.76k | return assumeSymInclusiveRange(State, Sym, From, To, InRange); |
118 | 2 | return State; |
119 | 2 | } // end switch |
120 | 2 | |
121 | 714 | case nonloc::ConcreteIntKind: { |
122 | 714 | const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue(); |
123 | 714 | bool IsInRange = IntVal >= From && IntVal <= To490 ; |
124 | 714 | bool isFeasible = (IsInRange == InRange); |
125 | 714 | return isFeasible ? State464 : nullptr250 ; |
126 | 2 | } |
127 | 2.47k | } // end switch |
128 | 2.47k | } |
129 | | |
130 | | } // end of namespace ento |
131 | | |
132 | | } // end of namespace clang |