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