/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //=-- ExprEngineC.cpp - ExprEngine support for C expressions ----*- 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 ExprEngine's support for C expressions. |
10 | | // |
11 | | //===----------------------------------------------------------------------===// |
12 | | |
13 | | #include "clang/AST/ExprCXX.h" |
14 | | #include "clang/AST/DeclCXX.h" |
15 | | #include "clang/StaticAnalyzer/Core/CheckerManager.h" |
16 | | #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" |
17 | | |
18 | | using namespace clang; |
19 | | using namespace ento; |
20 | | using llvm::APSInt; |
21 | | |
22 | | /// Optionally conjure and return a symbol for offset when processing |
23 | | /// an expression \p Expression. |
24 | | /// If \p Other is a location, conjure a symbol for \p Symbol |
25 | | /// (offset) if it is unknown so that memory arithmetic always |
26 | | /// results in an ElementRegion. |
27 | | /// \p Count The number of times the current basic block was visited. |
28 | | static SVal conjureOffsetSymbolOnLocation( |
29 | | SVal Symbol, SVal Other, Expr* Expression, SValBuilder &svalBuilder, |
30 | 26.4k | unsigned Count, const LocationContext *LCtx) { |
31 | 26.4k | QualType Ty = Expression->getType(); |
32 | 26.4k | if (Other.getAs<Loc>() && |
33 | 26.4k | Ty->isIntegralOrEnumerationType()10.0k && |
34 | 26.4k | Symbol.isUnknown()9.91k ) { |
35 | 0 | return svalBuilder.conjureSymbolVal(Expression, LCtx, Ty, Count); |
36 | 0 | } |
37 | 26.4k | return Symbol; |
38 | 26.4k | } |
39 | | |
40 | | void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, |
41 | | ExplodedNode *Pred, |
42 | 71.7k | ExplodedNodeSet &Dst) { |
43 | 71.7k | |
44 | 71.7k | Expr *LHS = B->getLHS()->IgnoreParens(); |
45 | 71.7k | Expr *RHS = B->getRHS()->IgnoreParens(); |
46 | 71.7k | |
47 | 71.7k | // FIXME: Prechecks eventually go in ::Visit(). |
48 | 71.7k | ExplodedNodeSet CheckedSet; |
49 | 71.7k | ExplodedNodeSet Tmp2; |
50 | 71.7k | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, B, *this); |
51 | 71.7k | |
52 | 71.7k | // With both the LHS and RHS evaluated, process the operation itself. |
53 | 71.7k | for (ExplodedNodeSet::iterator it=CheckedSet.begin(), ei=CheckedSet.end(); |
54 | 143k | it != ei; ++it71.5k ) { |
55 | 71.5k | |
56 | 71.5k | ProgramStateRef state = (*it)->getState(); |
57 | 71.5k | const LocationContext *LCtx = (*it)->getLocationContext(); |
58 | 71.5k | SVal LeftV = state->getSVal(LHS, LCtx); |
59 | 71.5k | SVal RightV = state->getSVal(RHS, LCtx); |
60 | 71.5k | |
61 | 71.5k | BinaryOperator::Opcode Op = B->getOpcode(); |
62 | 71.5k | |
63 | 71.5k | if (Op == BO_Assign) { |
64 | 21.5k | // EXPERIMENTAL: "Conjured" symbols. |
65 | 21.5k | // FIXME: Handle structs. |
66 | 21.5k | if (RightV.isUnknown()) { |
67 | 4.10k | unsigned Count = currBldrCtx->blockCount(); |
68 | 4.10k | RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, |
69 | 4.10k | Count); |
70 | 4.10k | } |
71 | 21.5k | // Simulate the effects of a "store": bind the value of the RHS |
72 | 21.5k | // to the L-Value represented by the LHS. |
73 | 21.5k | SVal ExprVal = B->isGLValue() ? LeftV14.4k : RightV7.02k ; |
74 | 21.5k | evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, LCtx, ExprVal), |
75 | 21.5k | LeftV, RightV); |
76 | 21.5k | continue; |
77 | 21.5k | } |
78 | 50.0k | |
79 | 50.0k | if (!B->isAssignmentOp()) { |
80 | 49.3k | StmtNodeBuilder Bldr(*it, Tmp2, *currBldrCtx); |
81 | 49.3k | |
82 | 49.3k | if (B->isAdditiveOp()) { |
83 | 13.2k | // TODO: This can be removed after we enable history tracking with |
84 | 13.2k | // SymSymExpr. |
85 | 13.2k | unsigned Count = currBldrCtx->blockCount(); |
86 | 13.2k | RightV = conjureOffsetSymbolOnLocation( |
87 | 13.2k | RightV, LeftV, RHS, svalBuilder, Count, LCtx); |
88 | 13.2k | LeftV = conjureOffsetSymbolOnLocation( |
89 | 13.2k | LeftV, RightV, LHS, svalBuilder, Count, LCtx); |
90 | 13.2k | } |
91 | 49.3k | |
92 | 49.3k | // Although we don't yet model pointers-to-members, we do need to make |
93 | 49.3k | // sure that the members of temporaries have a valid 'this' pointer for |
94 | 49.3k | // other checks. |
95 | 49.3k | if (B->getOpcode() == BO_PtrMemD) |
96 | 18 | state = createTemporaryRegionIfNeeded(state, LCtx, LHS); |
97 | 49.3k | |
98 | 49.3k | // Process non-assignments except commas or short-circuited |
99 | 49.3k | // logical expressions (LAnd and LOr). |
100 | 49.3k | SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType()); |
101 | 49.3k | if (!Result.isUnknown()) { |
102 | 48.5k | state = state->BindExpr(B, LCtx, Result); |
103 | 48.5k | } else { |
104 | 798 | // If we cannot evaluate the operation escape the operands. |
105 | 798 | state = escapeValue(state, LeftV, PSK_EscapeOther); |
106 | 798 | state = escapeValue(state, RightV, PSK_EscapeOther); |
107 | 798 | } |
108 | 49.3k | |
109 | 49.3k | Bldr.generateNode(B, *it, state); |
110 | 49.3k | continue; |
111 | 49.3k | } |
112 | 685 | |
113 | 685 | assert (B->isCompoundAssignmentOp()); |
114 | 685 | |
115 | 685 | switch (Op) { |
116 | 685 | default: |
117 | 0 | llvm_unreachable("Invalid opcode for compound assignment."); |
118 | 685 | case BO_MulAssign: Op = BO_Mul; break32 ; |
119 | 685 | case BO_DivAssign: Op = BO_Div; break29 ; |
120 | 685 | case BO_RemAssign: Op = BO_Rem; break12 ; |
121 | 685 | case BO_AddAssign: Op = BO_Add; break317 ; |
122 | 685 | case BO_SubAssign: Op = BO_Sub; break164 ; |
123 | 685 | case BO_ShlAssign: Op = BO_Shl; break20 ; |
124 | 685 | case BO_ShrAssign: Op = BO_Shr; break8 ; |
125 | 685 | case BO_AndAssign: Op = BO_And; break17 ; |
126 | 685 | case BO_XorAssign: Op = BO_Xor; break66 ; |
127 | 685 | case BO_OrAssign: Op = BO_Or; break20 ; |
128 | 685 | } |
129 | 685 | |
130 | 685 | // Perform a load (the LHS). This performs the checks for |
131 | 685 | // null dereferences, and so on. |
132 | 685 | ExplodedNodeSet Tmp; |
133 | 685 | SVal location = LeftV; |
134 | 685 | evalLoad(Tmp, B, LHS, *it, state, location); |
135 | 685 | |
136 | 1.36k | for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; |
137 | 685 | ++I683 ) { |
138 | 683 | |
139 | 683 | state = (*I)->getState(); |
140 | 683 | const LocationContext *LCtx = (*I)->getLocationContext(); |
141 | 683 | SVal V = state->getSVal(LHS, LCtx); |
142 | 683 | |
143 | 683 | // Get the computation type. |
144 | 683 | QualType CTy = |
145 | 683 | cast<CompoundAssignOperator>(B)->getComputationResultType(); |
146 | 683 | CTy = getContext().getCanonicalType(CTy); |
147 | 683 | |
148 | 683 | QualType CLHSTy = |
149 | 683 | cast<CompoundAssignOperator>(B)->getComputationLHSType(); |
150 | 683 | CLHSTy = getContext().getCanonicalType(CLHSTy); |
151 | 683 | |
152 | 683 | QualType LTy = getContext().getCanonicalType(LHS->getType()); |
153 | 683 | |
154 | 683 | // Promote LHS. |
155 | 683 | V = svalBuilder.evalCast(V, CLHSTy, LTy); |
156 | 683 | |
157 | 683 | // Compute the result of the operation. |
158 | 683 | SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy), |
159 | 683 | B->getType(), CTy); |
160 | 683 | |
161 | 683 | // EXPERIMENTAL: "Conjured" symbols. |
162 | 683 | // FIXME: Handle structs. |
163 | 683 | |
164 | 683 | SVal LHSVal; |
165 | 683 | |
166 | 683 | if (Result.isUnknown()) { |
167 | 113 | // The symbolic value is actually for the type of the left-hand side |
168 | 113 | // expression, not the computation type, as this is the value the |
169 | 113 | // LValue on the LHS will bind to. |
170 | 113 | LHSVal = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, LTy, |
171 | 113 | currBldrCtx->blockCount()); |
172 | 113 | // However, we need to convert the symbol to the computation type. |
173 | 113 | Result = svalBuilder.evalCast(LHSVal, CTy, LTy); |
174 | 113 | } |
175 | 570 | else { |
176 | 570 | // The left-hand side may bind to a different value then the |
177 | 570 | // computation type. |
178 | 570 | LHSVal = svalBuilder.evalCast(Result, LTy, CTy); |
179 | 570 | } |
180 | 683 | |
181 | 683 | // In C++, assignment and compound assignment operators return an |
182 | 683 | // lvalue. |
183 | 683 | if (B->isGLValue()) |
184 | 152 | state = state->BindExpr(B, LCtx, location); |
185 | 531 | else |
186 | 531 | state = state->BindExpr(B, LCtx, Result); |
187 | 683 | |
188 | 683 | evalStore(Tmp2, B, LHS, *I, state, location, LHSVal); |
189 | 683 | } |
190 | 685 | } |
191 | 71.7k | |
192 | 71.7k | // FIXME: postvisits eventually go in ::Visit() |
193 | 71.7k | getCheckerManager().runCheckersForPostStmt(Dst, Tmp2, B, *this); |
194 | 71.7k | } |
195 | | |
196 | | void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, |
197 | 373 | ExplodedNodeSet &Dst) { |
198 | 373 | |
199 | 373 | CanQualType T = getContext().getCanonicalType(BE->getType()); |
200 | 373 | |
201 | 373 | const BlockDecl *BD = BE->getBlockDecl(); |
202 | 373 | // Get the value of the block itself. |
203 | 373 | SVal V = svalBuilder.getBlockPointer(BD, T, |
204 | 373 | Pred->getLocationContext(), |
205 | 373 | currBldrCtx->blockCount()); |
206 | 373 | |
207 | 373 | ProgramStateRef State = Pred->getState(); |
208 | 373 | |
209 | 373 | // If we created a new MemRegion for the block, we should explicitly bind |
210 | 373 | // the captured variables. |
211 | 373 | if (const BlockDataRegion *BDR = |
212 | 373 | dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { |
213 | 373 | |
214 | 373 | BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(), |
215 | 373 | E = BDR->referenced_vars_end(); |
216 | 373 | |
217 | 373 | auto CI = BD->capture_begin(); |
218 | 373 | auto CE = BD->capture_end(); |
219 | 685 | for (; I != E; ++I312 ) { |
220 | 312 | const VarRegion *capturedR = I.getCapturedRegion(); |
221 | 312 | const VarRegion *originalR = I.getOriginalRegion(); |
222 | 312 | |
223 | 312 | // If the capture had a copy expression, use the result of evaluating |
224 | 312 | // that expression, otherwise use the original value. |
225 | 312 | // We rely on the invariant that the block declaration's capture variables |
226 | 312 | // are a prefix of the BlockDataRegion's referenced vars (which may include |
227 | 312 | // referenced globals, etc.) to enable fast lookup of the capture for a |
228 | 312 | // given referenced var. |
229 | 312 | const Expr *copyExpr = nullptr; |
230 | 312 | if (CI != CE) { |
231 | 272 | assert(CI->getVariable() == capturedR->getDecl()); |
232 | 272 | copyExpr = CI->getCopyExpr(); |
233 | 272 | CI++; |
234 | 272 | } |
235 | 312 | |
236 | 312 | if (capturedR != originalR) { |
237 | 200 | SVal originalV; |
238 | 200 | const LocationContext *LCtx = Pred->getLocationContext(); |
239 | 200 | if (copyExpr) { |
240 | 10 | originalV = State->getSVal(copyExpr, LCtx); |
241 | 190 | } else { |
242 | 190 | originalV = State->getSVal(loc::MemRegionVal(originalR)); |
243 | 190 | } |
244 | 200 | State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, LCtx); |
245 | 200 | } |
246 | 312 | } |
247 | 373 | } |
248 | 373 | |
249 | 373 | ExplodedNodeSet Tmp; |
250 | 373 | StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); |
251 | 373 | Bldr.generateNode(BE, Pred, |
252 | 373 | State->BindExpr(BE, Pred->getLocationContext(), V), |
253 | 373 | nullptr, ProgramPoint::PostLValueKind); |
254 | 373 | |
255 | 373 | // FIXME: Move all post/pre visits to ::Visit(). |
256 | 373 | getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this); |
257 | 373 | } |
258 | | |
259 | | ProgramStateRef ExprEngine::handleLValueBitCast( |
260 | | ProgramStateRef state, const Expr* Ex, const LocationContext* LCtx, |
261 | | QualType T, QualType ExTy, const CastExpr* CastE, StmtNodeBuilder& Bldr, |
262 | 44.0k | ExplodedNode* Pred) { |
263 | 44.0k | if (T->isLValueReferenceType()) { |
264 | 6 | assert(!CastE->getType()->isLValueReferenceType()); |
265 | 6 | ExTy = getContext().getLValueReferenceType(ExTy); |
266 | 44.0k | } else if (T->isRValueReferenceType()) { |
267 | 1 | assert(!CastE->getType()->isRValueReferenceType()); |
268 | 1 | ExTy = getContext().getRValueReferenceType(ExTy); |
269 | 1 | } |
270 | 44.0k | // Delegate to SValBuilder to process. |
271 | 44.0k | SVal OrigV = state->getSVal(Ex, LCtx); |
272 | 44.0k | SVal V = svalBuilder.evalCast(OrigV, T, ExTy); |
273 | 44.0k | // Negate the result if we're treating the boolean as a signed i1 |
274 | 44.0k | if (CastE->getCastKind() == CK_BooleanToSignedIntegral) |
275 | 0 | V = evalMinus(V); |
276 | 44.0k | state = state->BindExpr(CastE, LCtx, V); |
277 | 44.0k | if (V.isUnknown() && !OrigV.isUnknown()1.22k ) { |
278 | 234 | state = escapeValue(state, OrigV, PSK_EscapeOther); |
279 | 234 | } |
280 | 44.0k | Bldr.generateNode(CastE, Pred, state); |
281 | 44.0k | |
282 | 44.0k | return state; |
283 | 44.0k | } |
284 | | |
285 | | ProgramStateRef ExprEngine::handleLVectorSplat( |
286 | | ProgramStateRef state, const LocationContext* LCtx, const CastExpr* CastE, |
287 | 0 | StmtNodeBuilder &Bldr, ExplodedNode* Pred) { |
288 | 0 | // Recover some path sensitivity by conjuring a new value. |
289 | 0 | QualType resultType = CastE->getType(); |
290 | 0 | if (CastE->isGLValue()) |
291 | 0 | resultType = getContext().getPointerType(resultType); |
292 | 0 | SVal result = svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, |
293 | 0 | resultType, |
294 | 0 | currBldrCtx->blockCount()); |
295 | 0 | state = state->BindExpr(CastE, LCtx, result); |
296 | 0 | Bldr.generateNode(CastE, Pred, state); |
297 | 0 |
|
298 | 0 | return state; |
299 | 0 | } |
300 | | |
301 | | void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, |
302 | 297k | ExplodedNode *Pred, ExplodedNodeSet &Dst) { |
303 | 297k | |
304 | 297k | ExplodedNodeSet dstPreStmt; |
305 | 297k | getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this); |
306 | 297k | |
307 | 297k | if (CastE->getCastKind() == CK_LValueToRValue) { |
308 | 140k | for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end(); |
309 | 281k | I!=E; ++I140k ) { |
310 | 140k | ExplodedNode *subExprNode = *I; |
311 | 140k | ProgramStateRef state = subExprNode->getState(); |
312 | 140k | const LocationContext *LCtx = subExprNode->getLocationContext(); |
313 | 140k | evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, LCtx)); |
314 | 140k | } |
315 | 140k | return; |
316 | 140k | } |
317 | 156k | |
318 | 156k | // All other casts. |
319 | 156k | QualType T = CastE->getType(); |
320 | 156k | QualType ExTy = Ex->getType(); |
321 | 156k | |
322 | 156k | if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE)) |
323 | 16.5k | T = ExCast->getTypeAsWritten(); |
324 | 156k | |
325 | 156k | StmtNodeBuilder Bldr(dstPreStmt, Dst, *currBldrCtx); |
326 | 156k | for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end(); |
327 | 313k | I != E; ++I156k ) { |
328 | 156k | |
329 | 156k | Pred = *I; |
330 | 156k | ProgramStateRef state = Pred->getState(); |
331 | 156k | const LocationContext *LCtx = Pred->getLocationContext(); |
332 | 156k | |
333 | 156k | switch (CastE->getCastKind()) { |
334 | 156k | case CK_LValueToRValue: |
335 | 0 | llvm_unreachable("LValueToRValue casts handled earlier."); |
336 | 156k | case CK_ToVoid: |
337 | 800 | continue; |
338 | 156k | // The analyzer doesn't do anything special with these casts, |
339 | 156k | // since it understands retain/release semantics already. |
340 | 156k | case CK_ARCProduceObject: |
341 | 74.8k | case CK_ARCConsumeObject: |
342 | 74.8k | case CK_ARCReclaimReturnedObject: |
343 | 74.8k | case CK_ARCExtendBlockObject: // Fall-through. |
344 | 74.8k | case CK_CopyAndAutoreleaseBlockObject: |
345 | 74.8k | // The analyser can ignore atomic casts for now, although some future |
346 | 74.8k | // checkers may want to make certain that you're not modifying the same |
347 | 74.8k | // value through atomic and nonatomic pointers. |
348 | 74.8k | case CK_AtomicToNonAtomic: |
349 | 74.8k | case CK_NonAtomicToAtomic: |
350 | 74.8k | // True no-ops. |
351 | 74.8k | case CK_NoOp: |
352 | 74.8k | case CK_ConstructorConversion: |
353 | 74.8k | case CK_UserDefinedConversion: |
354 | 74.8k | case CK_FunctionToPointerDecay: |
355 | 74.8k | case CK_BuiltinFnToFnPtr: { |
356 | 74.8k | // Copy the SVal of Ex to CastE. |
357 | 74.8k | ProgramStateRef state = Pred->getState(); |
358 | 74.8k | const LocationContext *LCtx = Pred->getLocationContext(); |
359 | 74.8k | SVal V = state->getSVal(Ex, LCtx); |
360 | 74.8k | state = state->BindExpr(CastE, LCtx, V); |
361 | 74.8k | Bldr.generateNode(CastE, Pred, state); |
362 | 74.8k | continue; |
363 | 74.8k | } |
364 | 74.8k | case CK_MemberPointerToBoolean: |
365 | 754 | case CK_PointerToBoolean: { |
366 | 754 | SVal V = state->getSVal(Ex, LCtx); |
367 | 754 | auto PTMSV = V.getAs<nonloc::PointerToMember>(); |
368 | 754 | if (PTMSV) |
369 | 6 | V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy); |
370 | 754 | if (V.isUndef() || PTMSV) { |
371 | 6 | state = state->BindExpr(CastE, LCtx, V); |
372 | 6 | Bldr.generateNode(CastE, Pred, state); |
373 | 6 | continue; |
374 | 6 | } |
375 | 748 | // Explicitly proceed with default handler for this case cascade. |
376 | 748 | state = |
377 | 748 | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |
378 | 748 | continue; |
379 | 748 | } |
380 | 18.3k | case CK_Dependent: |
381 | 18.3k | case CK_ArrayToPointerDecay: |
382 | 18.3k | case CK_BitCast: |
383 | 18.3k | case CK_LValueToRValueBitCast: |
384 | 18.3k | case CK_AddressSpaceConversion: |
385 | 18.3k | case CK_BooleanToSignedIntegral: |
386 | 18.3k | case CK_IntegralToPointer: |
387 | 18.3k | case CK_PointerToIntegral: { |
388 | 18.3k | SVal V = state->getSVal(Ex, LCtx); |
389 | 18.3k | if (V.getAs<nonloc::PointerToMember>()) { |
390 | 0 | state = state->BindExpr(CastE, LCtx, UnknownVal()); |
391 | 0 | Bldr.generateNode(CastE, Pred, state); |
392 | 0 | continue; |
393 | 0 | } |
394 | 18.3k | // Explicitly proceed with default handler for this case cascade. |
395 | 18.3k | state = |
396 | 18.3k | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |
397 | 18.3k | continue; |
398 | 18.3k | } |
399 | 24.9k | case CK_IntegralToBoolean: |
400 | 24.9k | case CK_IntegralToFloating: |
401 | 24.9k | case CK_FloatingToIntegral: |
402 | 24.9k | case CK_FloatingToBoolean: |
403 | 24.9k | case CK_FloatingCast: |
404 | 24.9k | case CK_FloatingRealToComplex: |
405 | 24.9k | case CK_FloatingComplexToReal: |
406 | 24.9k | case CK_FloatingComplexToBoolean: |
407 | 24.9k | case CK_FloatingComplexCast: |
408 | 24.9k | case CK_FloatingComplexToIntegralComplex: |
409 | 24.9k | case CK_IntegralRealToComplex: |
410 | 24.9k | case CK_IntegralComplexToReal: |
411 | 24.9k | case CK_IntegralComplexToBoolean: |
412 | 24.9k | case CK_IntegralComplexCast: |
413 | 24.9k | case CK_IntegralComplexToFloatingComplex: |
414 | 24.9k | case CK_CPointerToObjCPointerCast: |
415 | 24.9k | case CK_BlockPointerToObjCPointerCast: |
416 | 24.9k | case CK_AnyPointerToBlockPointerCast: |
417 | 24.9k | case CK_ObjCObjectLValueCast: |
418 | 24.9k | case CK_ZeroToOCLOpaqueType: |
419 | 24.9k | case CK_IntToOCLSampler: |
420 | 24.9k | case CK_LValueBitCast: |
421 | 24.9k | case CK_FixedPointCast: |
422 | 24.9k | case CK_FixedPointToBoolean: |
423 | 24.9k | case CK_FixedPointToIntegral: |
424 | 24.9k | case CK_IntegralToFixedPoint: { |
425 | 24.9k | state = |
426 | 24.9k | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |
427 | 24.9k | continue; |
428 | 24.9k | } |
429 | 33.1k | case CK_IntegralCast: { |
430 | 33.1k | // Delegate to SValBuilder to process. |
431 | 33.1k | SVal V = state->getSVal(Ex, LCtx); |
432 | 33.1k | V = svalBuilder.evalIntegralCast(state, V, T, ExTy); |
433 | 33.1k | state = state->BindExpr(CastE, LCtx, V); |
434 | 33.1k | Bldr.generateNode(CastE, Pred, state); |
435 | 33.1k | continue; |
436 | 24.9k | } |
437 | 24.9k | case CK_DerivedToBase: |
438 | 791 | case CK_UncheckedDerivedToBase: { |
439 | 791 | // For DerivedToBase cast, delegate to the store manager. |
440 | 791 | SVal val = state->getSVal(Ex, LCtx); |
441 | 791 | val = getStoreManager().evalDerivedToBase(val, CastE); |
442 | 791 | state = state->BindExpr(CastE, LCtx, val); |
443 | 791 | Bldr.generateNode(CastE, Pred, state); |
444 | 791 | continue; |
445 | 791 | } |
446 | 791 | // Handle C++ dyn_cast. |
447 | 791 | case CK_Dynamic: { |
448 | 38 | SVal val = state->getSVal(Ex, LCtx); |
449 | 38 | |
450 | 38 | // Compute the type of the result. |
451 | 38 | QualType resultType = CastE->getType(); |
452 | 38 | if (CastE->isGLValue()) |
453 | 3 | resultType = getContext().getPointerType(resultType); |
454 | 38 | |
455 | 38 | bool Failed = false; |
456 | 38 | |
457 | 38 | // Check if the value being cast evaluates to 0. |
458 | 38 | if (val.isZeroConstant()) |
459 | 2 | Failed = true; |
460 | 36 | // Else, evaluate the cast. |
461 | 36 | else |
462 | 36 | val = getStoreManager().attemptDownCast(val, T, Failed); |
463 | 38 | |
464 | 38 | if (Failed) { |
465 | 8 | if (T->isReferenceType()) { |
466 | 1 | // A bad_cast exception is thrown if input value is a reference. |
467 | 1 | // Currently, we model this, by generating a sink. |
468 | 1 | Bldr.generateSink(CastE, Pred, state); |
469 | 1 | continue; |
470 | 7 | } else { |
471 | 7 | // If the cast fails on a pointer, bind to 0. |
472 | 7 | state = state->BindExpr(CastE, LCtx, svalBuilder.makeNull()); |
473 | 7 | } |
474 | 30 | } else { |
475 | 30 | // If we don't know if the cast succeeded, conjure a new symbol. |
476 | 30 | if (val.isUnknown()) { |
477 | 0 | DefinedOrUnknownSVal NewSym = |
478 | 0 | svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, |
479 | 0 | currBldrCtx->blockCount()); |
480 | 0 | state = state->BindExpr(CastE, LCtx, NewSym); |
481 | 0 | } else |
482 | 30 | // Else, bind to the derived region value. |
483 | 30 | state = state->BindExpr(CastE, LCtx, val); |
484 | 30 | } |
485 | 38 | Bldr.generateNode(CastE, Pred, state); |
486 | 37 | continue; |
487 | 38 | } |
488 | 127 | case CK_BaseToDerived: { |
489 | 127 | SVal val = state->getSVal(Ex, LCtx); |
490 | 127 | QualType resultType = CastE->getType(); |
491 | 127 | if (CastE->isGLValue()) |
492 | 0 | resultType = getContext().getPointerType(resultType); |
493 | 127 | |
494 | 127 | bool Failed = false; |
495 | 127 | |
496 | 127 | if (!val.isConstant()) { |
497 | 119 | val = getStoreManager().attemptDownCast(val, T, Failed); |
498 | 119 | } |
499 | 127 | |
500 | 127 | // Failed to cast or the result is unknown, fall back to conservative. |
501 | 127 | if (Failed || val.isUnknown()123 ) { |
502 | 4 | val = |
503 | 4 | svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, |
504 | 4 | currBldrCtx->blockCount()); |
505 | 4 | } |
506 | 127 | state = state->BindExpr(CastE, LCtx, val); |
507 | 127 | Bldr.generateNode(CastE, Pred, state); |
508 | 127 | continue; |
509 | 38 | } |
510 | 3.15k | case CK_NullToPointer: { |
511 | 3.15k | SVal V = svalBuilder.makeNull(); |
512 | 3.15k | state = state->BindExpr(CastE, LCtx, V); |
513 | 3.15k | Bldr.generateNode(CastE, Pred, state); |
514 | 3.15k | continue; |
515 | 38 | } |
516 | 38 | case CK_NullToMemberPointer: { |
517 | 5 | SVal V = svalBuilder.getMemberPointer(nullptr); |
518 | 5 | state = state->BindExpr(CastE, LCtx, V); |
519 | 5 | Bldr.generateNode(CastE, Pred, state); |
520 | 5 | continue; |
521 | 38 | } |
522 | 38 | case CK_DerivedToBaseMemberPointer: |
523 | 24 | case CK_BaseToDerivedMemberPointer: |
524 | 24 | case CK_ReinterpretMemberPointer: { |
525 | 24 | SVal V = state->getSVal(Ex, LCtx); |
526 | 24 | if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) { |
527 | 24 | SVal CastedPTMSV = svalBuilder.makePointerToMember( |
528 | 24 | getBasicVals().accumCXXBase( |
529 | 24 | llvm::make_range<CastExpr::path_const_iterator>( |
530 | 24 | CastE->path_begin(), CastE->path_end()), *PTMSV)); |
531 | 24 | state = state->BindExpr(CastE, LCtx, CastedPTMSV); |
532 | 24 | Bldr.generateNode(CastE, Pred, state); |
533 | 24 | continue; |
534 | 24 | } |
535 | 0 | // Explicitly proceed with default handler for this case cascade. |
536 | 0 | state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred); |
537 | 0 | continue; |
538 | 0 | } |
539 | 0 | // Various C++ casts that are not handled yet. |
540 | 0 | case CK_ToUnion: |
541 | 0 | case CK_VectorSplat: { |
542 | 0 | state = handleLVectorSplat(state, LCtx, CastE, Bldr, Pred); |
543 | 0 | continue; |
544 | 0 | } |
545 | 156k | } |
546 | 156k | } |
547 | 156k | } |
548 | | |
549 | | void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, |
550 | | ExplodedNode *Pred, |
551 | 62 | ExplodedNodeSet &Dst) { |
552 | 62 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
553 | 62 | |
554 | 62 | ProgramStateRef State = Pred->getState(); |
555 | 62 | const LocationContext *LCtx = Pred->getLocationContext(); |
556 | 62 | |
557 | 62 | const Expr *Init = CL->getInitializer(); |
558 | 62 | SVal V = State->getSVal(CL->getInitializer(), LCtx); |
559 | 62 | |
560 | 62 | if (isa<CXXConstructExpr>(Init) || isa<CXXStdInitializerListExpr>(Init)56 ) { |
561 | 10 | // No work needed. Just pass the value up to this expression. |
562 | 52 | } else { |
563 | 52 | assert(isa<InitListExpr>(Init)); |
564 | 52 | Loc CLLoc = State->getLValue(CL, LCtx); |
565 | 52 | State = State->bindLoc(CLLoc, V, LCtx); |
566 | 52 | |
567 | 52 | if (CL->isGLValue()) |
568 | 33 | V = CLLoc; |
569 | 52 | } |
570 | 62 | |
571 | 62 | B.generateNode(CL, Pred, State->BindExpr(CL, LCtx, V)); |
572 | 62 | } |
573 | | |
574 | | void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, |
575 | 27.3k | ExplodedNodeSet &Dst) { |
576 | 27.3k | // Assumption: The CFG has one DeclStmt per Decl. |
577 | 27.3k | const VarDecl *VD = dyn_cast_or_null<VarDecl>(*DS->decl_begin()); |
578 | 27.3k | |
579 | 27.3k | if (!VD) { |
580 | 0 | //TODO:AZ: remove explicit insertion after refactoring is done. |
581 | 0 | Dst.insert(Pred); |
582 | 0 | return; |
583 | 0 | } |
584 | 27.3k | |
585 | 27.3k | // FIXME: all pre/post visits should eventually be handled by ::Visit(). |
586 | 27.3k | ExplodedNodeSet dstPreVisit; |
587 | 27.3k | getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this); |
588 | 27.3k | |
589 | 27.3k | ExplodedNodeSet dstEvaluated; |
590 | 27.3k | StmtNodeBuilder B(dstPreVisit, dstEvaluated, *currBldrCtx); |
591 | 27.3k | for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end(); |
592 | 54.7k | I!=E; ++I27.3k ) { |
593 | 27.3k | ExplodedNode *N = *I; |
594 | 27.3k | ProgramStateRef state = N->getState(); |
595 | 27.3k | const LocationContext *LC = N->getLocationContext(); |
596 | 27.3k | |
597 | 27.3k | // Decls without InitExpr are not initialized explicitly. |
598 | 27.3k | if (const Expr *InitEx = VD->getInit()) { |
599 | 24.9k | |
600 | 24.9k | // Note in the state that the initialization has occurred. |
601 | 24.9k | ExplodedNode *UpdatedN = N; |
602 | 24.9k | SVal InitVal = state->getSVal(InitEx, LC); |
603 | 24.9k | |
604 | 24.9k | assert(DS->isSingleDecl()); |
605 | 24.9k | if (getObjectUnderConstruction(state, DS, LC)) { |
606 | 4.72k | state = finishObjectConstruction(state, DS, LC); |
607 | 4.72k | // We constructed the object directly in the variable. |
608 | 4.72k | // No need to bind anything. |
609 | 4.72k | B.generateNode(DS, UpdatedN, state); |
610 | 20.2k | } else { |
611 | 20.2k | // Recover some path-sensitivity if a scalar value evaluated to |
612 | 20.2k | // UnknownVal. |
613 | 20.2k | if (InitVal.isUnknown()) { |
614 | 5.16k | QualType Ty = InitEx->getType(); |
615 | 5.16k | if (InitEx->isGLValue()) { |
616 | 0 | Ty = getContext().getPointerType(Ty); |
617 | 0 | } |
618 | 5.16k | |
619 | 5.16k | InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty, |
620 | 5.16k | currBldrCtx->blockCount()); |
621 | 5.16k | } |
622 | 20.2k | |
623 | 20.2k | |
624 | 20.2k | B.takeNodes(UpdatedN); |
625 | 20.2k | ExplodedNodeSet Dst2; |
626 | 20.2k | evalBind(Dst2, DS, UpdatedN, state->getLValue(VD, LC), InitVal, true); |
627 | 20.2k | B.addNodes(Dst2); |
628 | 20.2k | } |
629 | 24.9k | } |
630 | 2.42k | else { |
631 | 2.42k | B.generateNode(DS, N, state); |
632 | 2.42k | } |
633 | 27.3k | } |
634 | 27.3k | |
635 | 27.3k | getCheckerManager().runCheckersForPostStmt(Dst, B.getResults(), DS, *this); |
636 | 27.3k | } |
637 | | |
638 | | void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, |
639 | 795 | ExplodedNodeSet &Dst) { |
640 | 795 | // This method acts upon CFG elements for logical operators && and || |
641 | 795 | // and attaches the value (true or false) to them as expressions. |
642 | 795 | // It doesn't produce any state splits. |
643 | 795 | // If we made it that far, we're past the point when we modeled the short |
644 | 795 | // circuit. It means that we should have precise knowledge about whether |
645 | 795 | // we've short-circuited. If we did, we already know the value we need to |
646 | 795 | // bind. If we didn't, the value of the RHS (casted to the boolean type) |
647 | 795 | // is the answer. |
648 | 795 | // Currently this method tries to figure out whether we've short-circuited |
649 | 795 | // by looking at the ExplodedGraph. This method is imperfect because there |
650 | 795 | // could inevitably have been merges that would have resulted in multiple |
651 | 795 | // potential path traversal histories. We bail out when we fail. |
652 | 795 | // Due to this ambiguity, a more reliable solution would have been to |
653 | 795 | // track the short circuit operation history path-sensitively until |
654 | 795 | // we evaluate the respective logical operator. |
655 | 795 | assert(B->getOpcode() == BO_LAnd || |
656 | 795 | B->getOpcode() == BO_LOr); |
657 | 795 | |
658 | 795 | StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); |
659 | 795 | ProgramStateRef state = Pred->getState(); |
660 | 795 | |
661 | 795 | if (B->getType()->isVectorType()) { |
662 | 2 | // FIXME: We do not model vector arithmetic yet. When adding support for |
663 | 2 | // that, note that the CFG-based reasoning below does not apply, because |
664 | 2 | // logical operators on vectors are not short-circuit. Currently they are |
665 | 2 | // modeled as short-circuit in Clang CFG but this is incorrect. |
666 | 2 | // Do not set the value for the expression. It'd be UnknownVal by default. |
667 | 2 | Bldr.generateNode(B, Pred, state); |
668 | 2 | return; |
669 | 2 | } |
670 | 793 | |
671 | 793 | ExplodedNode *N = Pred; |
672 | 1.61k | while (!N->getLocation().getAs<BlockEntrance>()) { |
673 | 817 | ProgramPoint P = N->getLocation(); |
674 | 817 | assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>()); |
675 | 817 | (void) P; |
676 | 817 | if (N->pred_size() != 1) { |
677 | 0 | // We failed to track back where we came from. |
678 | 0 | Bldr.generateNode(B, Pred, state); |
679 | 0 | return; |
680 | 0 | } |
681 | 817 | N = *N->pred_begin(); |
682 | 817 | } |
683 | 793 | |
684 | 793 | if (N->pred_size() != 1) { |
685 | 7 | // We failed to track back where we came from. |
686 | 7 | Bldr.generateNode(B, Pred, state); |
687 | 7 | return; |
688 | 7 | } |
689 | 786 | |
690 | 786 | N = *N->pred_begin(); |
691 | 786 | BlockEdge BE = N->getLocation().castAs<BlockEdge>(); |
692 | 786 | SVal X; |
693 | 786 | |
694 | 786 | // Determine the value of the expression by introspecting how we |
695 | 786 | // got this location in the CFG. This requires looking at the previous |
696 | 786 | // block we were in and what kind of control-flow transfer was involved. |
697 | 786 | const CFGBlock *SrcBlock = BE.getSrc(); |
698 | 786 | // The only terminator (if there is one) that makes sense is a logical op. |
699 | 786 | CFGTerminator T = SrcBlock->getTerminator(); |
700 | 786 | if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) { |
701 | 454 | (void) Term; |
702 | 454 | assert(Term->isLogicalOp()); |
703 | 454 | assert(SrcBlock->succ_size() == 2); |
704 | 454 | // Did we take the true or false branch? |
705 | 454 | unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 188 : 0366 ; |
706 | 454 | X = svalBuilder.makeIntVal(constant, B->getType()); |
707 | 454 | } |
708 | 332 | else { |
709 | 332 | // If there is no terminator, by construction the last statement |
710 | 332 | // in SrcBlock is the value of the enclosing expression. |
711 | 332 | // However, we still need to constrain that value to be 0 or 1. |
712 | 332 | assert(!SrcBlock->empty()); |
713 | 332 | CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>(); |
714 | 332 | const Expr *RHS = cast<Expr>(Elem.getStmt()); |
715 | 332 | SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext()); |
716 | 332 | |
717 | 332 | if (RHSVal.isUndef()) { |
718 | 1 | X = RHSVal; |
719 | 331 | } else { |
720 | 331 | // We evaluate "RHSVal != 0" expression which result in 0 if the value is |
721 | 331 | // known to be false, 1 if the value is known to be true and a new symbol |
722 | 331 | // when the assumption is unknown. |
723 | 331 | nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType())); |
724 | 331 | X = evalBinOp(N->getState(), BO_NE, |
725 | 331 | svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()), |
726 | 331 | Zero, B->getType()); |
727 | 331 | } |
728 | 332 | } |
729 | 786 | Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); |
730 | 786 | } |
731 | | |
732 | | void ExprEngine::VisitInitListExpr(const InitListExpr *IE, |
733 | | ExplodedNode *Pred, |
734 | 1.16k | ExplodedNodeSet &Dst) { |
735 | 1.16k | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
736 | 1.16k | |
737 | 1.16k | ProgramStateRef state = Pred->getState(); |
738 | 1.16k | const LocationContext *LCtx = Pred->getLocationContext(); |
739 | 1.16k | QualType T = getContext().getCanonicalType(IE->getType()); |
740 | 1.16k | unsigned NumInitElements = IE->getNumInits(); |
741 | 1.16k | |
742 | 1.16k | if (!IE->isGLValue() && !IE->isTransparent()1.16k && |
743 | 1.16k | (1.14k T->isArrayType()1.14k || T->isRecordType()623 || T->isVectorType()68 || |
744 | 1.14k | T->isAnyComplexType()62 )) { |
745 | 1.08k | llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList(); |
746 | 1.08k | |
747 | 1.08k | // Handle base case where the initializer has no elements. |
748 | 1.08k | // e.g: static int* myArray[] = {}; |
749 | 1.08k | if (NumInitElements == 0) { |
750 | 168 | SVal V = svalBuilder.makeCompoundVal(T, vals); |
751 | 168 | B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); |
752 | 168 | return; |
753 | 168 | } |
754 | 915 | |
755 | 915 | for (InitListExpr::const_reverse_iterator it = IE->rbegin(), |
756 | 3.00k | ei = IE->rend(); it != ei; ++it2.08k ) { |
757 | 2.08k | SVal V = state->getSVal(cast<Expr>(*it), LCtx); |
758 | 2.08k | vals = getBasicVals().prependSVal(V, vals); |
759 | 2.08k | } |
760 | 915 | |
761 | 915 | B.generateNode(IE, Pred, |
762 | 915 | state->BindExpr(IE, LCtx, |
763 | 915 | svalBuilder.makeCompoundVal(T, vals))); |
764 | 915 | return; |
765 | 915 | } |
766 | 86 | |
767 | 86 | // Handle scalars: int{5} and int{} and GLvalues. |
768 | 86 | // Note, if the InitListExpr is a GLvalue, it means that there is an address |
769 | 86 | // representing it, so it must have a single init element. |
770 | 86 | assert(NumInitElements <= 1); |
771 | 86 | |
772 | 86 | SVal V; |
773 | 86 | if (NumInitElements == 0) |
774 | 57 | V = getSValBuilder().makeZeroVal(T); |
775 | 29 | else |
776 | 29 | V = state->getSVal(IE->getInit(0), LCtx); |
777 | 86 | |
778 | 86 | B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); |
779 | 86 | } |
780 | | |
781 | | void ExprEngine::VisitGuardedExpr(const Expr *Ex, |
782 | | const Expr *L, |
783 | | const Expr *R, |
784 | | ExplodedNode *Pred, |
785 | 889 | ExplodedNodeSet &Dst) { |
786 | 889 | assert(L && R); |
787 | 889 | |
788 | 889 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
789 | 889 | ProgramStateRef state = Pred->getState(); |
790 | 889 | const LocationContext *LCtx = Pred->getLocationContext(); |
791 | 889 | const CFGBlock *SrcBlock = nullptr; |
792 | 889 | |
793 | 889 | // Find the predecessor block. |
794 | 889 | ProgramStateRef SrcState = state; |
795 | 2.67k | for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()1.78k ) { |
796 | 2.67k | ProgramPoint PP = N->getLocation(); |
797 | 2.67k | if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()1.77k ) { |
798 | 1.78k | // If the state N has multiple predecessors P, it means that successors |
799 | 1.78k | // of P are all equivalent. |
800 | 1.78k | // In turn, that means that all nodes at P are equivalent in terms |
801 | 1.78k | // of observable behavior at N, and we can follow any of them. |
802 | 1.78k | // FIXME: a more robust solution which does not walk up the tree. |
803 | 1.78k | continue; |
804 | 1.78k | } |
805 | 889 | SrcBlock = PP.castAs<BlockEdge>().getSrc(); |
806 | 889 | SrcState = N->getState(); |
807 | 889 | break; |
808 | 889 | } |
809 | 889 | |
810 | 889 | assert(SrcBlock && "missing function entry"); |
811 | 889 | |
812 | 889 | // Find the last expression in the predecessor block. That is the |
813 | 889 | // expression that is used for the value of the ternary expression. |
814 | 889 | bool hasValue = false; |
815 | 889 | SVal V; |
816 | 889 | |
817 | 889 | for (CFGElement CE : llvm::reverse(*SrcBlock)) { |
818 | 889 | if (Optional<CFGStmt> CS = CE.getAs<CFGStmt>()) { |
819 | 889 | const Expr *ValEx = cast<Expr>(CS->getStmt()); |
820 | 889 | ValEx = ValEx->IgnoreParens(); |
821 | 889 | |
822 | 889 | // For GNU extension '?:' operator, the left hand side will be an |
823 | 889 | // OpaqueValueExpr, so get the underlying expression. |
824 | 889 | if (const OpaqueValueExpr *OpaqueEx = dyn_cast<OpaqueValueExpr>(L)) |
825 | 21 | L = OpaqueEx->getSourceExpr(); |
826 | 889 | |
827 | 889 | // If the last expression in the predecessor block matches true or false |
828 | 889 | // subexpression, get its the value. |
829 | 889 | if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()270 ) { |
830 | 887 | hasValue = true; |
831 | 887 | V = SrcState->getSVal(ValEx, LCtx); |
832 | 887 | } |
833 | 889 | break; |
834 | 889 | } |
835 | 889 | } |
836 | 889 | |
837 | 889 | if (!hasValue) |
838 | 2 | V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, |
839 | 2 | currBldrCtx->blockCount()); |
840 | 889 | |
841 | 889 | // Generate a new node with the binding from the appropriate path. |
842 | 889 | B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true)); |
843 | 889 | } |
844 | | |
845 | | void ExprEngine:: |
846 | | VisitOffsetOfExpr(const OffsetOfExpr *OOE, |
847 | 21 | ExplodedNode *Pred, ExplodedNodeSet &Dst) { |
848 | 21 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |
849 | 21 | Expr::EvalResult Result; |
850 | 21 | if (OOE->EvaluateAsInt(Result, getContext())) { |
851 | 21 | APSInt IV = Result.Val.getInt(); |
852 | 21 | assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType())); |
853 | 21 | assert(OOE->getType()->isBuiltinType()); |
854 | 21 | assert(OOE->getType()->getAs<BuiltinType>()->isInteger()); |
855 | 21 | assert(IV.isSigned() == OOE->getType()->isSignedIntegerType()); |
856 | 21 | SVal X = svalBuilder.makeIntVal(IV); |
857 | 21 | B.generateNode(OOE, Pred, |
858 | 21 | Pred->getState()->BindExpr(OOE, Pred->getLocationContext(), |
859 | 21 | X)); |
860 | 21 | } |
861 | 21 | // FIXME: Handle the case where __builtin_offsetof is not a constant. |
862 | 21 | } |
863 | | |
864 | | |
865 | | void ExprEngine:: |
866 | | VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, |
867 | | ExplodedNode *Pred, |
868 | 929 | ExplodedNodeSet &Dst) { |
869 | 929 | // FIXME: Prechecks eventually go in ::Visit(). |
870 | 929 | ExplodedNodeSet CheckedSet; |
871 | 929 | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this); |
872 | 929 | |
873 | 929 | ExplodedNodeSet EvalSet; |
874 | 929 | StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); |
875 | 929 | |
876 | 929 | QualType T = Ex->getTypeOfArgument(); |
877 | 929 | |
878 | 929 | for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); |
879 | 1.85k | I != E; ++I929 ) { |
880 | 929 | if (Ex->getKind() == UETT_SizeOf) { |
881 | 926 | if (!T->isIncompleteType() && !T->isConstantSizeType()922 ) { |
882 | 9 | assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); |
883 | 9 | |
884 | 9 | // FIXME: Add support for VLA type arguments and VLA expressions. |
885 | 9 | // When that happens, we should probably refactor VLASizeChecker's code. |
886 | 9 | continue; |
887 | 917 | } else if (T->getAs<ObjCObjectType>()) { |
888 | 0 | // Some code tries to take the sizeof an ObjCObjectType, relying that |
889 | 0 | // the compiler has laid out its representation. Just report Unknown |
890 | 0 | // for these. |
891 | 0 | continue; |
892 | 0 | } |
893 | 920 | } |
894 | 920 | |
895 | 920 | APSInt Value = Ex->EvaluateKnownConstInt(getContext()); |
896 | 920 | CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); |
897 | 920 | |
898 | 920 | ProgramStateRef state = (*I)->getState(); |
899 | 920 | state = state->BindExpr(Ex, (*I)->getLocationContext(), |
900 | 920 | svalBuilder.makeIntVal(amt.getQuantity(), |
901 | 920 | Ex->getType())); |
902 | 920 | Bldr.generateNode(Ex, *I, state); |
903 | 920 | } |
904 | 929 | |
905 | 929 | getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this); |
906 | 929 | } |
907 | | |
908 | | void ExprEngine::handleUOExtension(ExplodedNodeSet::iterator I, |
909 | | const UnaryOperator *U, |
910 | 16.3k | StmtNodeBuilder &Bldr) { |
911 | 16.3k | // FIXME: We can probably just have some magic in Environment::getSVal() |
912 | 16.3k | // that propagates values, instead of creating a new node here. |
913 | 16.3k | // |
914 | 16.3k | // Unary "+" is a no-op, similar to a parentheses. We still have places |
915 | 16.3k | // where it may be a block-level expression, so we need to |
916 | 16.3k | // generate an extra node that just propagates the value of the |
917 | 16.3k | // subexpression. |
918 | 16.3k | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
919 | 16.3k | ProgramStateRef state = (*I)->getState(); |
920 | 16.3k | const LocationContext *LCtx = (*I)->getLocationContext(); |
921 | 16.3k | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, |
922 | 16.3k | state->getSVal(Ex, LCtx))); |
923 | 16.3k | } |
924 | | |
925 | | void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred, |
926 | 27.7k | ExplodedNodeSet &Dst) { |
927 | 27.7k | // FIXME: Prechecks eventually go in ::Visit(). |
928 | 27.7k | ExplodedNodeSet CheckedSet; |
929 | 27.7k | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, U, *this); |
930 | 27.7k | |
931 | 27.7k | ExplodedNodeSet EvalSet; |
932 | 27.7k | StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); |
933 | 27.7k | |
934 | 27.7k | for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); |
935 | 55.4k | I != E; ++I27.7k ) { |
936 | 27.7k | switch (U->getOpcode()) { |
937 | 27.7k | default: { |
938 | 8.45k | Bldr.takeNodes(*I); |
939 | 8.45k | ExplodedNodeSet Tmp; |
940 | 8.45k | VisitIncrementDecrementOperator(U, *I, Tmp); |
941 | 8.45k | Bldr.addNodes(Tmp); |
942 | 8.45k | break; |
943 | 27.7k | } |
944 | 27.7k | case UO_Real: { |
945 | 14 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
946 | 14 | |
947 | 14 | // FIXME: We don't have complex SValues yet. |
948 | 14 | if (Ex->getType()->isAnyComplexType()) { |
949 | 10 | // Just report "Unknown." |
950 | 10 | break; |
951 | 10 | } |
952 | 4 | |
953 | 4 | // For all other types, UO_Real is an identity operation. |
954 | 4 | assert (U->getType() == Ex->getType()); |
955 | 4 | ProgramStateRef state = (*I)->getState(); |
956 | 4 | const LocationContext *LCtx = (*I)->getLocationContext(); |
957 | 4 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, |
958 | 4 | state->getSVal(Ex, LCtx))); |
959 | 4 | break; |
960 | 4 | } |
961 | 4 | |
962 | 11 | case UO_Imag: { |
963 | 11 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
964 | 11 | // FIXME: We don't have complex SValues yet. |
965 | 11 | if (Ex->getType()->isAnyComplexType()) { |
966 | 8 | // Just report "Unknown." |
967 | 8 | break; |
968 | 8 | } |
969 | 3 | // For all other types, UO_Imag returns 0. |
970 | 3 | ProgramStateRef state = (*I)->getState(); |
971 | 3 | const LocationContext *LCtx = (*I)->getLocationContext(); |
972 | 3 | SVal X = svalBuilder.makeZeroVal(Ex->getType()); |
973 | 3 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, X)); |
974 | 3 | break; |
975 | 3 | } |
976 | 3 | |
977 | 3.28k | case UO_AddrOf: { |
978 | 3.28k | // Process pointer-to-member address operation. |
979 | 3.28k | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
980 | 3.28k | if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex)) { |
981 | 2.56k | const ValueDecl *VD = DRE->getDecl(); |
982 | 2.56k | |
983 | 2.56k | if (isa<CXXMethodDecl>(VD) || isa<FieldDecl>(VD)2.54k ) { |
984 | 37 | ProgramStateRef State = (*I)->getState(); |
985 | 37 | const LocationContext *LCtx = (*I)->getLocationContext(); |
986 | 37 | SVal SV = svalBuilder.getMemberPointer(cast<DeclaratorDecl>(VD)); |
987 | 37 | Bldr.generateNode(U, *I, State->BindExpr(U, LCtx, SV)); |
988 | 37 | break; |
989 | 37 | } |
990 | 3.24k | } |
991 | 3.24k | // Explicitly proceed with default handler for this case cascade. |
992 | 3.24k | handleUOExtension(I, U, Bldr); |
993 | 3.24k | break; |
994 | 3.24k | } |
995 | 3.24k | case UO_Plus: |
996 | 0 | assert(!U->isGLValue()); |
997 | 0 | LLVM_FALLTHROUGH; |
998 | 13.0k | case UO_Deref: |
999 | 13.0k | case UO_Extension: { |
1000 | 13.0k | handleUOExtension(I, U, Bldr); |
1001 | 13.0k | break; |
1002 | 13.0k | } |
1003 | 13.0k | |
1004 | 13.0k | case UO_LNot: |
1005 | 2.85k | case UO_Minus: |
1006 | 2.85k | case UO_Not: { |
1007 | 2.85k | assert (!U->isGLValue()); |
1008 | 2.85k | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
1009 | 2.85k | ProgramStateRef state = (*I)->getState(); |
1010 | 2.85k | const LocationContext *LCtx = (*I)->getLocationContext(); |
1011 | 2.85k | |
1012 | 2.85k | // Get the value of the subexpression. |
1013 | 2.85k | SVal V = state->getSVal(Ex, LCtx); |
1014 | 2.85k | |
1015 | 2.85k | if (V.isUnknownOrUndef()) { |
1016 | 10 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V)); |
1017 | 10 | break; |
1018 | 10 | } |
1019 | 2.84k | |
1020 | 2.84k | switch (U->getOpcode()) { |
1021 | 2.84k | default: |
1022 | 0 | llvm_unreachable("Invalid Opcode."); |
1023 | 2.84k | case UO_Not: |
1024 | 929 | // FIXME: Do we need to handle promotions? |
1025 | 929 | state = state->BindExpr(U, LCtx, evalComplement(V.castAs<NonLoc>())); |
1026 | 929 | break; |
1027 | 2.84k | case UO_Minus: |
1028 | 985 | // FIXME: Do we need to handle promotions? |
1029 | 985 | state = state->BindExpr(U, LCtx, evalMinus(V.castAs<NonLoc>())); |
1030 | 985 | break; |
1031 | 2.84k | case UO_LNot: |
1032 | 929 | // C99 6.5.3.3: "The expression !E is equivalent to (0==E)." |
1033 | 929 | // |
1034 | 929 | // Note: technically we do "E == 0", but this is the same in the |
1035 | 929 | // transfer functions as "0 == E". |
1036 | 929 | SVal Result; |
1037 | 929 | if (Optional<Loc> LV = V.getAs<Loc>()) { |
1038 | 198 | Loc X = svalBuilder.makeNullWithType(Ex->getType()); |
1039 | 198 | Result = evalBinOp(state, BO_EQ, *LV, X, U->getType()); |
1040 | 731 | } else if (Ex->getType()->isFloatingType()) { |
1041 | 1 | // FIXME: handle floating point types. |
1042 | 1 | Result = UnknownVal(); |
1043 | 730 | } else { |
1044 | 730 | nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType())); |
1045 | 730 | Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X, |
1046 | 730 | U->getType()); |
1047 | 730 | } |
1048 | 929 | |
1049 | 929 | state = state->BindExpr(U, LCtx, Result); |
1050 | 929 | break; |
1051 | 2.84k | } |
1052 | 2.84k | Bldr.generateNode(U, *I, state); |
1053 | 2.84k | break; |
1054 | 2.84k | } |
1055 | 27.7k | } |
1056 | 27.7k | } |
1057 | 27.7k | |
1058 | 27.7k | getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, U, *this); |
1059 | 27.7k | } |
1060 | | |
1061 | | void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, |
1062 | | ExplodedNode *Pred, |
1063 | 8.45k | ExplodedNodeSet &Dst) { |
1064 | 8.45k | // Handle ++ and -- (both pre- and post-increment). |
1065 | 8.45k | assert (U->isIncrementDecrementOp()); |
1066 | 8.45k | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |
1067 | 8.45k | |
1068 | 8.45k | const LocationContext *LCtx = Pred->getLocationContext(); |
1069 | 8.45k | ProgramStateRef state = Pred->getState(); |
1070 | 8.45k | SVal loc = state->getSVal(Ex, LCtx); |
1071 | 8.45k | |
1072 | 8.45k | // Perform a load. |
1073 | 8.45k | ExplodedNodeSet Tmp; |
1074 | 8.45k | evalLoad(Tmp, U, Ex, Pred, state, loc); |
1075 | 8.45k | |
1076 | 8.45k | ExplodedNodeSet Dst2; |
1077 | 8.45k | StmtNodeBuilder Bldr(Tmp, Dst2, *currBldrCtx); |
1078 | 16.8k | for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end();I!=E;++I8.44k ) { |
1079 | 8.44k | |
1080 | 8.44k | state = (*I)->getState(); |
1081 | 8.44k | assert(LCtx == (*I)->getLocationContext()); |
1082 | 8.44k | SVal V2_untested = state->getSVal(Ex, LCtx); |
1083 | 8.44k | |
1084 | 8.44k | // Propagate unknown and undefined values. |
1085 | 8.44k | if (V2_untested.isUnknownOrUndef()) { |
1086 | 37 | state = state->BindExpr(U, LCtx, V2_untested); |
1087 | 37 | |
1088 | 37 | // Perform the store, so that the uninitialized value detection happens. |
1089 | 37 | Bldr.takeNodes(*I); |
1090 | 37 | ExplodedNodeSet Dst3; |
1091 | 37 | evalStore(Dst3, U, Ex, *I, state, loc, V2_untested); |
1092 | 37 | Bldr.addNodes(Dst3); |
1093 | 37 | |
1094 | 37 | continue; |
1095 | 37 | } |
1096 | 8.41k | DefinedSVal V2 = V2_untested.castAs<DefinedSVal>(); |
1097 | 8.41k | |
1098 | 8.41k | // Handle all other values. |
1099 | 8.41k | BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add8.19k : BO_Sub211 ; |
1100 | 8.41k | |
1101 | 8.41k | // If the UnaryOperator has non-location type, use its type to create the |
1102 | 8.41k | // constant value. If the UnaryOperator has location type, create the |
1103 | 8.41k | // constant with int type and pointer width. |
1104 | 8.41k | SVal RHS; |
1105 | 8.41k | SVal Result; |
1106 | 8.41k | |
1107 | 8.41k | if (U->getType()->isAnyPointerType()) |
1108 | 611 | RHS = svalBuilder.makeArrayIndex(1); |
1109 | 7.79k | else if (U->getType()->isIntegralOrEnumerationType()) |
1110 | 7.79k | RHS = svalBuilder.makeIntVal(1, U->getType()); |
1111 | 1 | else |
1112 | 1 | RHS = UnknownVal(); |
1113 | 8.41k | |
1114 | 8.41k | // The use of an operand of type bool with the ++ operators is deprecated |
1115 | 8.41k | // but valid until C++17. And if the operand of the ++ operator is of type |
1116 | 8.41k | // bool, it is set to true until C++17. Note that for '_Bool', it is also |
1117 | 8.41k | // set to true when it encounters ++ operator. |
1118 | 8.41k | if (U->getType()->isBooleanType() && U->isIncrementOp()70 ) |
1119 | 52 | Result = svalBuilder.makeTruthVal(true, U->getType()); |
1120 | 8.35k | else |
1121 | 8.35k | Result = evalBinOp(state, Op, V2, RHS, U->getType()); |
1122 | 8.41k | |
1123 | 8.41k | // Conjure a new symbol if necessary to recover precision. |
1124 | 8.41k | if (Result.isUnknown()){ |
1125 | 3 | DefinedOrUnknownSVal SymVal = |
1126 | 3 | svalBuilder.conjureSymbolVal(nullptr, U, LCtx, |
1127 | 3 | currBldrCtx->blockCount()); |
1128 | 3 | Result = SymVal; |
1129 | 3 | |
1130 | 3 | // If the value is a location, ++/-- should always preserve |
1131 | 3 | // non-nullness. Check if the original value was non-null, and if so |
1132 | 3 | // propagate that constraint. |
1133 | 3 | if (Loc::isLocType(U->getType())) { |
1134 | 0 | DefinedOrUnknownSVal Constraint = |
1135 | 0 | svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType())); |
1136 | 0 |
|
1137 | 0 | if (!state->assume(Constraint, true)) { |
1138 | 0 | // It isn't feasible for the original value to be null. |
1139 | 0 | // Propagate this constraint. |
1140 | 0 | Constraint = svalBuilder.evalEQ(state, SymVal, |
1141 | 0 | svalBuilder.makeZeroVal(U->getType())); |
1142 | 0 |
|
1143 | 0 | state = state->assume(Constraint, false); |
1144 | 0 | assert(state); |
1145 | 0 | } |
1146 | 0 | } |
1147 | 3 | } |
1148 | 8.41k | |
1149 | 8.41k | // Since the lvalue-to-rvalue conversion is explicit in the AST, |
1150 | 8.41k | // we bind an l-value if the operator is prefix and an lvalue (in C++). |
1151 | 8.41k | if (U->isGLValue()) |
1152 | 1.06k | state = state->BindExpr(U, LCtx, loc); |
1153 | 7.34k | else |
1154 | 7.34k | state = state->BindExpr(U, LCtx, U->isPostfix() ? V26.81k : Result529 ); |
1155 | 8.41k | |
1156 | 8.41k | // Perform the store. |
1157 | 8.41k | Bldr.takeNodes(*I); |
1158 | 8.41k | ExplodedNodeSet Dst3; |
1159 | 8.41k | evalStore(Dst3, U, Ex, *I, state, loc, Result); |
1160 | 8.41k | Bldr.addNodes(Dst3); |
1161 | 8.41k | } |
1162 | 8.45k | Dst.insert(Dst2); |
1163 | 8.45k | } |