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 | unsigned Count, const LocationContext *LCtx) { |

31 | QualType Ty = Expression->getType(); |

32 | if (isa<Loc>(Other) && Ty->isIntegralOrEnumerationType() && |

33 | Symbol.isUnknown()) { |

34 | return svalBuilder.conjureSymbolVal(Expression, LCtx, Ty, Count); |

35 | } |

36 | return Symbol; |

37 | } |

38 | |

39 | void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, |

40 | ExplodedNode *Pred, |

41 | ExplodedNodeSet &Dst) { |

42 | |

43 | Expr *LHS = B->getLHS()->IgnoreParens(); |

44 | Expr *RHS = B->getRHS()->IgnoreParens(); |

45 | |

46 | // FIXME: Prechecks eventually go in ::Visit(). |

47 | ExplodedNodeSet CheckedSet; |

48 | ExplodedNodeSet Tmp2; |

49 | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, B, *this); |

50 | |

51 | // With both the LHS and RHS evaluated, process the operation itself. |

52 | for (ExplodedNodeSet::iterator it=CheckedSet.begin(), ei=CheckedSet.end(); |

53 | it != ei; ++it) { |

54 | |

55 | ProgramStateRef state = (*it)->getState(); |

56 | const LocationContext *LCtx = (*it)->getLocationContext(); |

57 | SVal LeftV = state->getSVal(LHS, LCtx); |

58 | SVal RightV = state->getSVal(RHS, LCtx); |

59 | |

60 | BinaryOperator::Opcode Op = B->getOpcode(); |

61 | |

62 | if (Op == BO_Assign) { |

63 | // EXPERIMENTAL: "Conjured" symbols. |

64 | // FIXME: Handle structs. |

65 | if (RightV.isUnknown()) { |

66 | unsigned Count = currBldrCtx->blockCount(); |

67 | RightV = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, |

68 | Count); |

69 | } |

70 | // Simulate the effects of a "store": bind the value of the RHS |

71 | // to the L-Value represented by the LHS. |

72 | SVal ExprVal = B->isGLValue() ? LeftV : RightV; |

73 | evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, LCtx, ExprVal), |

74 | LeftV, RightV); |

75 | continue; |

76 | } |

77 | |

78 | if (!B->isAssignmentOp()) { |

79 | StmtNodeBuilder Bldr(*it, Tmp2, *currBldrCtx); |

80 | |

81 | if (B->isAdditiveOp()) { |

82 | // TODO: This can be removed after we enable history tracking with |

83 | // SymSymExpr. |

84 | unsigned Count = currBldrCtx->blockCount(); |

85 | RightV = conjureOffsetSymbolOnLocation( |

86 | RightV, LeftV, RHS, svalBuilder, Count, LCtx); |

87 | LeftV = conjureOffsetSymbolOnLocation( |

88 | LeftV, RightV, LHS, svalBuilder, Count, LCtx); |

89 | } |

90 | |

91 | // Although we don't yet model pointers-to-members, we do need to make |

92 | // sure that the members of temporaries have a valid 'this' pointer for |

93 | // other checks. |

94 | if (B->getOpcode() == BO_PtrMemD) |

95 | state = createTemporaryRegionIfNeeded(state, LCtx, LHS); |

96 | |

97 | // Process non-assignments except commas or short-circuited |

98 | // logical expressions (LAnd and LOr). |

99 | SVal Result = evalBinOp(state, Op, LeftV, RightV, B->getType()); |

100 | if (!Result.isUnknown()) { |

101 | state = state->BindExpr(B, LCtx, Result); |

102 | } else { |

103 | // If we cannot evaluate the operation escape the operands. |

104 | state = escapeValues(state, LeftV, PSK_EscapeOther); |

105 | state = escapeValues(state, RightV, PSK_EscapeOther); |

106 | } |

107 | |

108 | Bldr.generateNode(B, *it, state); |

109 | continue; |

110 | } |

111 | |

112 | assert (B->isCompoundAssignmentOp()); |

113 | |

114 | switch (Op) { |

115 | default: |

116 | llvm_unreachable("Invalid opcode for compound assignment."); |

117 | case BO_MulAssign: Op = BO_Mul; break; |

118 | case BO_DivAssign: Op = BO_Div; break; |

119 | case BO_RemAssign: Op = BO_Rem; break; |

120 | case BO_AddAssign: Op = BO_Add; break; |

121 | case BO_SubAssign: Op = BO_Sub; break; |

122 | case BO_ShlAssign: Op = BO_Shl; break; |

123 | case BO_ShrAssign: Op = BO_Shr; break; |

124 | case BO_AndAssign: Op = BO_And; break; |

125 | case BO_XorAssign: Op = BO_Xor; break; |

126 | case BO_OrAssign: Op = BO_Or; break; |

127 | } |

128 | |

129 | // Perform a load (the LHS). This performs the checks for |

130 | // null dereferences, and so on. |

131 | ExplodedNodeSet Tmp; |

132 | SVal location = LeftV; |

133 | evalLoad(Tmp, B, LHS, *it, state, location); |

134 | |

135 | for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; |

136 | ++I) { |

137 | |

138 | state = (*I)->getState(); |

139 | const LocationContext *LCtx = (*I)->getLocationContext(); |

140 | SVal V = state->getSVal(LHS, LCtx); |

141 | |

142 | // Get the computation type. |

143 | QualType CTy = |

144 | cast<CompoundAssignOperator>(B)->getComputationResultType(); |

145 | CTy = getContext().getCanonicalType(CTy); |

146 | |

147 | QualType CLHSTy = |

148 | cast<CompoundAssignOperator>(B)->getComputationLHSType(); |

149 | CLHSTy = getContext().getCanonicalType(CLHSTy); |

150 | |

151 | QualType LTy = getContext().getCanonicalType(LHS->getType()); |

152 | |

153 | // Promote LHS. |

154 | V = svalBuilder.evalCast(V, CLHSTy, LTy); |

155 | |

156 | // Compute the result of the operation. |

157 | SVal Result = svalBuilder.evalCast(evalBinOp(state, Op, V, RightV, CTy), |

158 | B->getType(), CTy); |

159 | |

160 | // EXPERIMENTAL: "Conjured" symbols. |

161 | // FIXME: Handle structs. |

162 | |

163 | SVal LHSVal; |

164 | |

165 | if (Result.isUnknown()) { |

166 | // The symbolic value is actually for the type of the left-hand side |

167 | // expression, not the computation type, as this is the value the |

168 | // LValue on the LHS will bind to. |

169 | LHSVal = svalBuilder.conjureSymbolVal(nullptr, B->getRHS(), LCtx, LTy, |

170 | currBldrCtx->blockCount()); |

171 | // However, we need to convert the symbol to the computation type. |

172 | Result = svalBuilder.evalCast(LHSVal, CTy, LTy); |

173 | } |

174 | else { |

175 | // The left-hand side may bind to a different value then the |

176 | // computation type. |

177 | LHSVal = svalBuilder.evalCast(Result, LTy, CTy); |

178 | } |

179 | |

180 | // In C++, assignment and compound assignment operators return an |

181 | // lvalue. |

182 | if (B->isGLValue()) |

183 | state = state->BindExpr(B, LCtx, location); |

184 | else |

185 | state = state->BindExpr(B, LCtx, Result); |

186 | |

187 | evalStore(Tmp2, B, LHS, *I, state, location, LHSVal); |

188 | } |

189 | } |

190 | |

191 | // FIXME: postvisits eventually go in ::Visit() |

192 | getCheckerManager().runCheckersForPostStmt(Dst, Tmp2, B, *this); |

193 | } |

194 | |

195 | void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, |

196 | ExplodedNodeSet &Dst) { |

197 | |

198 | CanQualType T = getContext().getCanonicalType(BE->getType()); |

199 | |

200 | const BlockDecl *BD = BE->getBlockDecl(); |

201 | // Get the value of the block itself. |

202 | SVal V = svalBuilder.getBlockPointer(BD, T, |

203 | Pred->getLocationContext(), |

204 | currBldrCtx->blockCount()); |

205 | |

206 | ProgramStateRef State = Pred->getState(); |

207 | |

208 | // If we created a new MemRegion for the block, we should explicitly bind |

209 | // the captured variables. |

210 | if (const BlockDataRegion *BDR = |

211 | dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) { |

212 | |

213 | BlockDataRegion::referenced_vars_iterator I = BDR->referenced_vars_begin(), |

214 | E = BDR->referenced_vars_end(); |

215 | |

216 | auto CI = BD->capture_begin(); |

217 | auto CE = BD->capture_end(); |

218 | for (; I != E; ++I) { |

219 | const VarRegion *capturedR = I.getCapturedRegion(); |

220 | const TypedValueRegion *originalR = I.getOriginalRegion(); |

221 | |

222 | // If the capture had a copy expression, use the result of evaluating |

223 | // that expression, otherwise use the original value. |

224 | // We rely on the invariant that the block declaration's capture variables |

225 | // are a prefix of the BlockDataRegion's referenced vars (which may include |

226 | // referenced globals, etc.) to enable fast lookup of the capture for a |

227 | // given referenced var. |

228 | const Expr *copyExpr = nullptr; |

229 | if (CI != CE) { |

230 | assert(CI->getVariable() == capturedR->getDecl()); |

231 | copyExpr = CI->getCopyExpr(); |

232 | CI++; |

233 | } |

234 | |

235 | if (capturedR != originalR) { |

236 | SVal originalV; |

237 | const LocationContext *LCtx = Pred->getLocationContext(); |

238 | if (copyExpr) { |

239 | originalV = State->getSVal(copyExpr, LCtx); |

240 | } else { |

241 | originalV = State->getSVal(loc::MemRegionVal(originalR)); |

242 | } |

243 | State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, LCtx); |

244 | } |

245 | } |

246 | } |

247 | |

248 | ExplodedNodeSet Tmp; |

249 | StmtNodeBuilder Bldr(Pred, Tmp, *currBldrCtx); |

250 | Bldr.generateNode(BE, Pred, |

251 | State->BindExpr(BE, Pred->getLocationContext(), V), |

252 | nullptr, ProgramPoint::PostLValueKind); |

253 | |

254 | // FIXME: Move all post/pre visits to ::Visit(). |

255 | getCheckerManager().runCheckersForPostStmt(Dst, Tmp, BE, *this); |

256 | } |

257 | |

258 | ProgramStateRef ExprEngine::handleLValueBitCast( |

259 | ProgramStateRef state, const Expr* Ex, const LocationContext* LCtx, |

260 | QualType T, QualType ExTy, const CastExpr* CastE, StmtNodeBuilder& Bldr, |

261 | ExplodedNode* Pred) { |

262 | if (T->isLValueReferenceType()) { |

263 | assert(!CastE->getType()->isLValueReferenceType()); |

264 | ExTy = getContext().getLValueReferenceType(ExTy); |

265 | } else if (T->isRValueReferenceType()) { |

266 | assert(!CastE->getType()->isRValueReferenceType()); |

267 | ExTy = getContext().getRValueReferenceType(ExTy); |

268 | } |

269 | // Delegate to SValBuilder to process. |

270 | SVal OrigV = state->getSVal(Ex, LCtx); |

271 | SVal V = svalBuilder.evalCast(OrigV, T, ExTy); |

272 | // Negate the result if we're treating the boolean as a signed i1 |

273 | if (CastE->getCastKind() == CK_BooleanToSignedIntegral && V.isValid()) |

274 | V = svalBuilder.evalMinus(V.castAs<NonLoc>()); |

275 | |

276 | state = state->BindExpr(CastE, LCtx, V); |

277 | if (V.isUnknown() && !OrigV.isUnknown()) { |

278 | state = escapeValues(state, OrigV, PSK_EscapeOther); |

279 | } |

280 | Bldr.generateNode(CastE, Pred, state); |

281 | |

282 | return state; |

283 | } |

284 | |

285 | void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, |

286 | ExplodedNode *Pred, ExplodedNodeSet &Dst) { |

287 | |

288 | ExplodedNodeSet dstPreStmt; |

289 | getCheckerManager().runCheckersForPreStmt(dstPreStmt, Pred, CastE, *this); |

290 | |

291 | if (CastE->getCastKind() == CK_LValueToRValue || |

292 | CastE->getCastKind() == CK_LValueToRValueBitCast) { |

293 | for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end(); |

294 | I!=E; ++I) { |

295 | ExplodedNode *subExprNode = *I; |

296 | ProgramStateRef state = subExprNode->getState(); |

297 | const LocationContext *LCtx = subExprNode->getLocationContext(); |

298 | evalLoad(Dst, CastE, CastE, subExprNode, state, state->getSVal(Ex, LCtx)); |

299 | } |

300 | return; |

301 | } |

302 | |

303 | // All other casts. |

304 | QualType T = CastE->getType(); |

305 | QualType ExTy = Ex->getType(); |

306 | |

307 | if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE)) |

308 | T = ExCast->getTypeAsWritten(); |

309 | |

310 | StmtNodeBuilder Bldr(dstPreStmt, Dst, *currBldrCtx); |

311 | for (ExplodedNodeSet::iterator I = dstPreStmt.begin(), E = dstPreStmt.end(); |

312 | I != E; ++I) { |

313 | |

314 | Pred = *I; |

315 | ProgramStateRef state = Pred->getState(); |

316 | const LocationContext *LCtx = Pred->getLocationContext(); |

317 | |

318 | switch (CastE->getCastKind()) { |

319 | case CK_LValueToRValue: |

320 | case CK_LValueToRValueBitCast: |

321 | llvm_unreachable("LValueToRValue casts handled earlier."); |

322 | case CK_ToVoid: |

323 | continue; |

324 | // The analyzer doesn't do anything special with these casts, |

325 | // since it understands retain/release semantics already. |

326 | case CK_ARCProduceObject: |

327 | case CK_ARCConsumeObject: |

328 | case CK_ARCReclaimReturnedObject: |

329 | case CK_ARCExtendBlockObject: // Fall-through. |

330 | case CK_CopyAndAutoreleaseBlockObject: |

331 | // The analyser can ignore atomic casts for now, although some future |

332 | // checkers may want to make certain that you're not modifying the same |

333 | // value through atomic and nonatomic pointers. |

334 | case CK_AtomicToNonAtomic: |

335 | case CK_NonAtomicToAtomic: |

336 | // True no-ops. |

337 | case CK_NoOp: |

338 | case CK_ConstructorConversion: |

339 | case CK_UserDefinedConversion: |

340 | case CK_FunctionToPointerDecay: |

341 | case CK_BuiltinFnToFnPtr: { |

342 | // Copy the SVal of Ex to CastE. |

343 | ProgramStateRef state = Pred->getState(); |

344 | const LocationContext *LCtx = Pred->getLocationContext(); |

345 | SVal V = state->getSVal(Ex, LCtx); |

346 | state = state->BindExpr(CastE, LCtx, V); |

347 | Bldr.generateNode(CastE, Pred, state); |

348 | continue; |

349 | } |

350 | case CK_MemberPointerToBoolean: |

351 | case CK_PointerToBoolean: { |

352 | SVal V = state->getSVal(Ex, LCtx); |

353 | auto PTMSV = V.getAs<nonloc::PointerToMember>(); |

354 | if (PTMSV) |

355 | V = svalBuilder.makeTruthVal(!PTMSV->isNullMemberPointer(), ExTy); |

356 | if (V.isUndef() || PTMSV) { |

357 | state = state->BindExpr(CastE, LCtx, V); |

358 | Bldr.generateNode(CastE, Pred, state); |

359 | continue; |

360 | } |

361 | // Explicitly proceed with default handler for this case cascade. |

362 | state = |

363 | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |

364 | continue; |

365 | } |

366 | case CK_Dependent: |

367 | case CK_ArrayToPointerDecay: |

368 | case CK_BitCast: |

369 | case CK_AddressSpaceConversion: |

370 | case CK_BooleanToSignedIntegral: |

371 | case CK_IntegralToPointer: |

372 | case CK_PointerToIntegral: { |

373 | SVal V = state->getSVal(Ex, LCtx); |

374 | if (isa<nonloc::PointerToMember>(V)) { |

375 | state = state->BindExpr(CastE, LCtx, UnknownVal()); |

376 | Bldr.generateNode(CastE, Pred, state); |

377 | continue; |

378 | } |

379 | // Explicitly proceed with default handler for this case cascade. |

380 | state = |

381 | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |

382 | continue; |

383 | } |

384 | case CK_IntegralToBoolean: |

385 | case CK_IntegralToFloating: |

386 | case CK_FloatingToIntegral: |

387 | case CK_FloatingToBoolean: |

388 | case CK_FloatingCast: |

389 | case CK_FloatingRealToComplex: |

390 | case CK_FloatingComplexToReal: |

391 | case CK_FloatingComplexToBoolean: |

392 | case CK_FloatingComplexCast: |

393 | case CK_FloatingComplexToIntegralComplex: |

394 | case CK_IntegralRealToComplex: |

395 | case CK_IntegralComplexToReal: |

396 | case CK_IntegralComplexToBoolean: |

397 | case CK_IntegralComplexCast: |

398 | case CK_IntegralComplexToFloatingComplex: |

399 | case CK_CPointerToObjCPointerCast: |

400 | case CK_BlockPointerToObjCPointerCast: |

401 | case CK_AnyPointerToBlockPointerCast: |

402 | case CK_ObjCObjectLValueCast: |

403 | case CK_ZeroToOCLOpaqueType: |

404 | case CK_IntToOCLSampler: |

405 | case CK_LValueBitCast: |

406 | case CK_FloatingToFixedPoint: |

407 | case CK_FixedPointToFloating: |

408 | case CK_FixedPointCast: |

409 | case CK_FixedPointToBoolean: |

410 | case CK_FixedPointToIntegral: |

411 | case CK_IntegralToFixedPoint: { |

412 | state = |

413 | handleLValueBitCast(state, Ex, LCtx, T, ExTy, CastE, Bldr, Pred); |

414 | continue; |

415 | } |

416 | case CK_IntegralCast: { |

417 | // Delegate to SValBuilder to process. |

418 | SVal V = state->getSVal(Ex, LCtx); |

419 | if (AMgr.options.ShouldSupportSymbolicIntegerCasts) |

420 | V = svalBuilder.evalCast(V, T, ExTy); |

421 | else |

422 | V = svalBuilder.evalIntegralCast(state, V, T, ExTy); |

423 | state = state->BindExpr(CastE, LCtx, V); |

424 | Bldr.generateNode(CastE, Pred, state); |

425 | continue; |

426 | } |

427 | case CK_DerivedToBase: |

428 | case CK_UncheckedDerivedToBase: { |

429 | // For DerivedToBase cast, delegate to the store manager. |

430 | SVal val = state->getSVal(Ex, LCtx); |

431 | val = getStoreManager().evalDerivedToBase(val, CastE); |

432 | state = state->BindExpr(CastE, LCtx, val); |

433 | Bldr.generateNode(CastE, Pred, state); |

434 | continue; |

435 | } |

436 | // Handle C++ dyn_cast. |

437 | case CK_Dynamic: { |

438 | SVal val = state->getSVal(Ex, LCtx); |

439 | |

440 | // Compute the type of the result. |

441 | QualType resultType = CastE->getType(); |

442 | if (CastE->isGLValue()) |

443 | resultType = getContext().getPointerType(resultType); |

444 | |

445 | bool Failed = true; |

446 | |

447 | // Check if the value being cast does not evaluates to 0. |

448 | if (!val.isZeroConstant()) |

449 | if (Optional<SVal> V = |

450 | StateMgr.getStoreManager().evalBaseToDerived(val, T)) { |

451 | val = *V; |

452 | Failed = false; |

453 | } |

454 | |

455 | if (Failed) { |

456 | if (T->isReferenceType()) { |

457 | // A bad_cast exception is thrown if input value is a reference. |

458 | // Currently, we model this, by generating a sink. |

459 | Bldr.generateSink(CastE, Pred, state); |

460 | continue; |

461 | } else { |

462 | // If the cast fails on a pointer, bind to 0. |

463 | state = state->BindExpr(CastE, LCtx, |

464 | svalBuilder.makeNullWithType(resultType)); |

465 | } |

466 | } else { |

467 | // If we don't know if the cast succeeded, conjure a new symbol. |

468 | if (val.isUnknown()) { |

469 | DefinedOrUnknownSVal NewSym = |

470 | svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, |

471 | currBldrCtx->blockCount()); |

472 | state = state->BindExpr(CastE, LCtx, NewSym); |

473 | } else |

474 | // Else, bind to the derived region value. |

475 | state = state->BindExpr(CastE, LCtx, val); |

476 | } |

477 | Bldr.generateNode(CastE, Pred, state); |

478 | continue; |

479 | } |

480 | case CK_BaseToDerived: { |

481 | SVal val = state->getSVal(Ex, LCtx); |

482 | QualType resultType = CastE->getType(); |

483 | if (CastE->isGLValue()) |

484 | resultType = getContext().getPointerType(resultType); |

485 | |

486 | if (!val.isConstant()) { |

487 | Optional<SVal> V = getStoreManager().evalBaseToDerived(val, T); |

488 | val = V ? *V : UnknownVal(); |

489 | } |

490 | |

491 | // Failed to cast or the result is unknown, fall back to conservative. |

492 | if (val.isUnknown()) { |

493 | val = |

494 | svalBuilder.conjureSymbolVal(nullptr, CastE, LCtx, resultType, |

495 | currBldrCtx->blockCount()); |

496 | } |

497 | state = state->BindExpr(CastE, LCtx, val); |

498 | Bldr.generateNode(CastE, Pred, state); |

499 | continue; |

500 | } |

501 | case CK_NullToPointer: { |

502 | SVal V = svalBuilder.makeNullWithType(CastE->getType()); |

503 | state = state->BindExpr(CastE, LCtx, V); |

504 | Bldr.generateNode(CastE, Pred, state); |

505 | continue; |

506 | } |

507 | case CK_NullToMemberPointer: { |

508 | SVal V = svalBuilder.getMemberPointer(nullptr); |

509 | state = state->BindExpr(CastE, LCtx, V); |

510 | Bldr.generateNode(CastE, Pred, state); |

511 | continue; |

512 | } |

513 | case CK_DerivedToBaseMemberPointer: |

514 | case CK_BaseToDerivedMemberPointer: |

515 | case CK_ReinterpretMemberPointer: { |

516 | SVal V = state->getSVal(Ex, LCtx); |

517 | if (auto PTMSV = V.getAs<nonloc::PointerToMember>()) { |

518 | SVal CastedPTMSV = |

519 | svalBuilder.makePointerToMember(getBasicVals().accumCXXBase( |

520 | CastE->path(), *PTMSV, CastE->getCastKind())); |

521 | state = state->BindExpr(CastE, LCtx, CastedPTMSV); |

522 | Bldr.generateNode(CastE, Pred, state); |

523 | continue; |

524 | } |

525 | // Explicitly proceed with default handler for this case cascade. |

526 | } |

527 | [[fallthrough]]; |

528 | // Various C++ casts that are not handled yet. |

529 | case CK_ToUnion: |

530 | case CK_MatrixCast: |

531 | case CK_VectorSplat: { |

532 | QualType resultType = CastE->getType(); |

533 | if (CastE->isGLValue()) |

534 | resultType = getContext().getPointerType(resultType); |

535 | SVal result = svalBuilder.conjureSymbolVal( |

536 | /*symbolTag=*/nullptr, CastE, LCtx, resultType, |

537 | currBldrCtx->blockCount()); |

538 | state = state->BindExpr(CastE, LCtx, result); |

539 | Bldr.generateNode(CastE, Pred, state); |

540 | continue; |

541 | } |

542 | } |

543 | } |

544 | } |

545 | |

546 | void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, |

547 | ExplodedNode *Pred, |

548 | ExplodedNodeSet &Dst) { |

549 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |

550 | |

551 | ProgramStateRef State = Pred->getState(); |

552 | const LocationContext *LCtx = Pred->getLocationContext(); |

553 | |

554 | const Expr *Init = CL->getInitializer(); |

555 | SVal V = State->getSVal(CL->getInitializer(), LCtx); |

556 | |

557 | if (isa<CXXConstructExpr, CXXStdInitializerListExpr>(Init)) { |

558 | // No work needed. Just pass the value up to this expression. |

559 | } else { |

560 | assert(isa<InitListExpr>(Init)); |

561 | Loc CLLoc = State->getLValue(CL, LCtx); |

562 | State = State->bindLoc(CLLoc, V, LCtx); |

563 | |

564 | if (CL->isGLValue()) |

565 | V = CLLoc; |

566 | } |

567 | |

568 | B.generateNode(CL, Pred, State->BindExpr(CL, LCtx, V)); |

569 | } |

570 | |

571 | void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, |

572 | ExplodedNodeSet &Dst) { |

573 | if (isa<TypedefNameDecl>(*DS->decl_begin())) { |

574 | // C99 6.7.7 "Any array size expressions associated with variable length |

575 | // array declarators are evaluated each time the declaration of the typedef |

576 | // name is reached in the order of execution." |

577 | // The checkers should know about typedef to be able to handle VLA size |

578 | // expressions. |

579 | ExplodedNodeSet DstPre; |

580 | getCheckerManager().runCheckersForPreStmt(DstPre, Pred, DS, *this); |

581 | getCheckerManager().runCheckersForPostStmt(Dst, DstPre, DS, *this); |

582 | return; |

583 | } |

584 | |

585 | // Assumption: The CFG has one DeclStmt per Decl. |

586 | const VarDecl *VD = dyn_cast_or_null<VarDecl>(*DS->decl_begin()); |

587 | |

588 | if (!VD) { |

589 | //TODO:AZ: remove explicit insertion after refactoring is done. |

590 | Dst.insert(Pred); |

591 | return; |

592 | } |

593 | |

594 | // FIXME: all pre/post visits should eventually be handled by ::Visit(). |

595 | ExplodedNodeSet dstPreVisit; |

596 | getCheckerManager().runCheckersForPreStmt(dstPreVisit, Pred, DS, *this); |

597 | |

598 | ExplodedNodeSet dstEvaluated; |

599 | StmtNodeBuilder B(dstPreVisit, dstEvaluated, *currBldrCtx); |

600 | for (ExplodedNodeSet::iterator I = dstPreVisit.begin(), E = dstPreVisit.end(); |

601 | I!=E; ++I) { |

602 | ExplodedNode *N = *I; |

603 | ProgramStateRef state = N->getState(); |

604 | const LocationContext *LC = N->getLocationContext(); |

605 | |

606 | // Decls without InitExpr are not initialized explicitly. |

607 | if (const Expr *InitEx = VD->getInit()) { |

608 | |

609 | // Note in the state that the initialization has occurred. |

610 | ExplodedNode *UpdatedN = N; |

611 | SVal InitVal = state->getSVal(InitEx, LC); |

612 | |

613 | assert(DS->isSingleDecl()); |

614 | if (getObjectUnderConstruction(state, DS, LC)) { |

615 | state = finishObjectConstruction(state, DS, LC); |

616 | // We constructed the object directly in the variable. |

617 | // No need to bind anything. |

618 | B.generateNode(DS, UpdatedN, state); |

619 | } else { |

620 | // Recover some path-sensitivity if a scalar value evaluated to |

621 | // UnknownVal. |

622 | if (InitVal.isUnknown()) { |

623 | QualType Ty = InitEx->getType(); |

624 | if (InitEx->isGLValue()) { |

625 | Ty = getContext().getPointerType(Ty); |

626 | } |

627 | |

628 | InitVal = svalBuilder.conjureSymbolVal(nullptr, InitEx, LC, Ty, |

629 | currBldrCtx->blockCount()); |

630 | } |

631 | |

632 | |

633 | B.takeNodes(UpdatedN); |

634 | ExplodedNodeSet Dst2; |

635 | evalBind(Dst2, DS, UpdatedN, state->getLValue(VD, LC), InitVal, true); |

636 | B.addNodes(Dst2); |

637 | } |

638 | } |

639 | else { |

640 | B.generateNode(DS, N, state); |

641 | } |

642 | } |

643 | |

644 | getCheckerManager().runCheckersForPostStmt(Dst, B.getResults(), DS, *this); |

645 | } |

646 | |

647 | void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, |

648 | ExplodedNodeSet &Dst) { |

649 | // This method acts upon CFG elements for logical operators && and || |

650 | // and attaches the value (true or false) to them as expressions. |

651 | // It doesn't produce any state splits. |

652 | // If we made it that far, we're past the point when we modeled the short |

653 | // circuit. It means that we should have precise knowledge about whether |

654 | // we've short-circuited. If we did, we already know the value we need to |

655 | // bind. If we didn't, the value of the RHS (casted to the boolean type) |

656 | // is the answer. |

657 | // Currently this method tries to figure out whether we've short-circuited |

658 | // by looking at the ExplodedGraph. This method is imperfect because there |

659 | // could inevitably have been merges that would have resulted in multiple |

660 | // potential path traversal histories. We bail out when we fail. |

661 | // Due to this ambiguity, a more reliable solution would have been to |

662 | // track the short circuit operation history path-sensitively until |

663 | // we evaluate the respective logical operator. |

664 | assert(B->getOpcode() == BO_LAnd || |

665 | B->getOpcode() == BO_LOr); |

666 | |

667 | StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx); |

668 | ProgramStateRef state = Pred->getState(); |

669 | |

670 | if (B->getType()->isVectorType()) { |

671 | // FIXME: We do not model vector arithmetic yet. When adding support for |

672 | // that, note that the CFG-based reasoning below does not apply, because |

673 | // logical operators on vectors are not short-circuit. Currently they are |

674 | // modeled as short-circuit in Clang CFG but this is incorrect. |

675 | // Do not set the value for the expression. It'd be UnknownVal by default. |

676 | Bldr.generateNode(B, Pred, state); |

677 | return; |

678 | } |

679 | |

680 | ExplodedNode *N = Pred; |

681 | while (!N->getLocation().getAs<BlockEntrance>()) { |

682 | ProgramPoint P = N->getLocation(); |

683 | assert(P.getAs<PreStmt>()|| P.getAs<PreStmtPurgeDeadSymbols>()); |

684 | (void) P; |

685 | if (N->pred_size() != 1) { |

686 | // We failed to track back where we came from. |

687 | Bldr.generateNode(B, Pred, state); |

688 | return; |

689 | } |

690 | N = *N->pred_begin(); |

691 | } |

692 | |

693 | if (N->pred_size() != 1) { |

694 | // We failed to track back where we came from. |

695 | Bldr.generateNode(B, Pred, state); |

696 | return; |

697 | } |

698 | |

699 | N = *N->pred_begin(); |

700 | BlockEdge BE = N->getLocation().castAs<BlockEdge>(); |

701 | SVal X; |

702 | |

703 | // Determine the value of the expression by introspecting how we |

704 | // got this location in the CFG. This requires looking at the previous |

705 | // block we were in and what kind of control-flow transfer was involved. |

706 | const CFGBlock *SrcBlock = BE.getSrc(); |

707 | // The only terminator (if there is one) that makes sense is a logical op. |

708 | CFGTerminator T = SrcBlock->getTerminator(); |

709 | if (const BinaryOperator *Term = cast_or_null<BinaryOperator>(T.getStmt())) { |

710 | (void) Term; |

711 | assert(Term->isLogicalOp()); |

712 | assert(SrcBlock->succ_size() == 2); |

713 | // Did we take the true or false branch? |

714 | unsigned constant = (*SrcBlock->succ_begin() == BE.getDst()) ? 1 : 0; |

715 | X = svalBuilder.makeIntVal(constant, B->getType()); |

716 | } |

717 | else { |

718 | // If there is no terminator, by construction the last statement |

719 | // in SrcBlock is the value of the enclosing expression. |

720 | // However, we still need to constrain that value to be 0 or 1. |

721 | assert(!SrcBlock->empty()); |

722 | CFGStmt Elem = SrcBlock->rbegin()->castAs<CFGStmt>(); |

723 | const Expr *RHS = cast<Expr>(Elem.getStmt()); |

724 | SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext()); |

725 | |

726 | if (RHSVal.isUndef()) { |

727 | X = RHSVal; |

728 | } else { |

729 | // We evaluate "RHSVal != 0" expression which result in 0 if the value is |

730 | // known to be false, 1 if the value is known to be true and a new symbol |

731 | // when the assumption is unknown. |

732 | nonloc::ConcreteInt Zero(getBasicVals().getValue(0, B->getType())); |

733 | X = evalBinOp(N->getState(), BO_NE, |

734 | svalBuilder.evalCast(RHSVal, B->getType(), RHS->getType()), |

735 | Zero, B->getType()); |

736 | } |

737 | } |

738 | Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X)); |

739 | } |

740 | |

741 | void ExprEngine::VisitInitListExpr(const InitListExpr *IE, |

742 | ExplodedNode *Pred, |

743 | ExplodedNodeSet &Dst) { |

744 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |

745 | |

746 | ProgramStateRef state = Pred->getState(); |

747 | const LocationContext *LCtx = Pred->getLocationContext(); |

748 | QualType T = getContext().getCanonicalType(IE->getType()); |

749 | unsigned NumInitElements = IE->getNumInits(); |

750 | |

751 | if (!IE->isGLValue() && !IE->isTransparent() && |

752 | (T->isArrayType() || T->isRecordType() || T->isVectorType() || |

753 | T->isAnyComplexType())) { |

754 | llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList(); |

755 | |

756 | // Handle base case where the initializer has no elements. |

757 | // e.g: static int* myArray[] = {}; |

758 | if (NumInitElements == 0) { |

759 | SVal V = svalBuilder.makeCompoundVal(T, vals); |

760 | B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); |

761 | return; |

762 | } |

763 | |

764 | for (const Stmt *S : llvm::reverse(*IE)) { |

765 | SVal V = state->getSVal(cast<Expr>(S), LCtx); |

766 | vals = getBasicVals().prependSVal(V, vals); |

767 | } |

768 | |

769 | B.generateNode(IE, Pred, |

770 | state->BindExpr(IE, LCtx, |

771 | svalBuilder.makeCompoundVal(T, vals))); |

772 | return; |

773 | } |

774 | |

775 | // Handle scalars: int{5} and int{} and GLvalues. |

776 | // Note, if the InitListExpr is a GLvalue, it means that there is an address |

777 | // representing it, so it must have a single init element. |

778 | assert(NumInitElements <= 1); |

779 | |

780 | SVal V; |

781 | if (NumInitElements == 0) |

782 | V = getSValBuilder().makeZeroVal(T); |

783 | else |

784 | V = state->getSVal(IE->getInit(0), LCtx); |

785 | |

786 | B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); |

787 | } |

788 | |

789 | void ExprEngine::VisitGuardedExpr(const Expr *Ex, |

790 | const Expr *L, |

791 | const Expr *R, |

792 | ExplodedNode *Pred, |

793 | ExplodedNodeSet &Dst) { |

794 | assert(L && R); |

795 | |

796 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |

797 | ProgramStateRef state = Pred->getState(); |

798 | const LocationContext *LCtx = Pred->getLocationContext(); |

799 | const CFGBlock *SrcBlock = nullptr; |

800 | |

801 | // Find the predecessor block. |

802 | ProgramStateRef SrcState = state; |

803 | for (const ExplodedNode *N = Pred ; N ; N = *N->pred_begin()) { |

804 | ProgramPoint PP = N->getLocation(); |

805 | if (PP.getAs<PreStmtPurgeDeadSymbols>() || PP.getAs<BlockEntrance>()) { |

806 | // If the state N has multiple predecessors P, it means that successors |

807 | // of P are all equivalent. |

808 | // In turn, that means that all nodes at P are equivalent in terms |

809 | // of observable behavior at N, and we can follow any of them. |

810 | // FIXME: a more robust solution which does not walk up the tree. |

811 | continue; |

812 | } |

813 | SrcBlock = PP.castAs<BlockEdge>().getSrc(); |

814 | SrcState = N->getState(); |

815 | break; |

816 | } |

817 | |

818 | assert(SrcBlock && "missing function entry"); |

819 | |

820 | // Find the last expression in the predecessor block. That is the |

821 | // expression that is used for the value of the ternary expression. |

822 | bool hasValue = false; |

823 | SVal V; |

824 | |

825 | for (CFGElement CE : llvm::reverse(*SrcBlock)) { |

826 | if (Optional<CFGStmt> CS = CE.getAs<CFGStmt>()) { |

827 | const Expr *ValEx = cast<Expr>(CS->getStmt()); |

828 | ValEx = ValEx->IgnoreParens(); |

829 | |

830 | // For GNU extension '?:' operator, the left hand side will be an |

831 | // OpaqueValueExpr, so get the underlying expression. |

832 | if (const OpaqueValueExpr *OpaqueEx = dyn_cast<OpaqueValueExpr>(L)) |

833 | L = OpaqueEx->getSourceExpr(); |

834 | |

835 | // If the last expression in the predecessor block matches true or false |

836 | // subexpression, get its the value. |

837 | if (ValEx == L->IgnoreParens() || ValEx == R->IgnoreParens()) { |

838 | hasValue = true; |

839 | V = SrcState->getSVal(ValEx, LCtx); |

840 | } |

841 | break; |

842 | } |

843 | } |

844 | |

845 | if (!hasValue) |

846 | V = svalBuilder.conjureSymbolVal(nullptr, Ex, LCtx, |

847 | currBldrCtx->blockCount()); |

848 | |

849 | // Generate a new node with the binding from the appropriate path. |

850 | B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V, true)); |

851 | } |

852 | |

853 | void ExprEngine:: |

854 | VisitOffsetOfExpr(const OffsetOfExpr *OOE, |

855 | ExplodedNode *Pred, ExplodedNodeSet &Dst) { |

856 | StmtNodeBuilder B(Pred, Dst, *currBldrCtx); |

857 | Expr::EvalResult Result; |

858 | if (OOE->EvaluateAsInt(Result, getContext())) { |

859 | APSInt IV = Result.Val.getInt(); |

860 | assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType())); |

861 | assert(OOE->getType()->castAs<BuiltinType>()->isInteger()); |

862 | assert(IV.isSigned() == OOE->getType()->isSignedIntegerType()); |

863 | SVal X = svalBuilder.makeIntVal(IV); |

864 | B.generateNode(OOE, Pred, |

865 | Pred->getState()->BindExpr(OOE, Pred->getLocationContext(), |

866 | X)); |

867 | } |

868 | // FIXME: Handle the case where __builtin_offsetof is not a constant. |

869 | } |

870 | |

871 | |

872 | void ExprEngine:: |

873 | VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, |

874 | ExplodedNode *Pred, |

875 | ExplodedNodeSet &Dst) { |

876 | // FIXME: Prechecks eventually go in ::Visit(). |

877 | ExplodedNodeSet CheckedSet; |

878 | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, Ex, *this); |

879 | |

880 | ExplodedNodeSet EvalSet; |

881 | StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); |

882 | |

883 | QualType T = Ex->getTypeOfArgument(); |

884 | |

885 | for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); |

886 | I != E; ++I) { |

887 | if (Ex->getKind() == UETT_SizeOf) { |

888 | if (!T->isIncompleteType() && !T->isConstantSizeType()) { |

889 | assert(T->isVariableArrayType() && "Unknown non-constant-sized type."); |

890 | |

891 | // FIXME: Add support for VLA type arguments and VLA expressions. |

892 | // When that happens, we should probably refactor VLASizeChecker's code. |

893 | continue; |

894 | } else if (T->getAs<ObjCObjectType>()) { |

895 | // Some code tries to take the sizeof an ObjCObjectType, relying that |

896 | // the compiler has laid out its representation. Just report Unknown |

897 | // for these. |

898 | continue; |

899 | } |

900 | } |

901 | |

902 | APSInt Value = Ex->EvaluateKnownConstInt(getContext()); |

903 | CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); |

904 | |

905 | ProgramStateRef state = (*I)->getState(); |

906 | state = state->BindExpr(Ex, (*I)->getLocationContext(), |

907 | svalBuilder.makeIntVal(amt.getQuantity(), |

908 | Ex->getType())); |

909 | Bldr.generateNode(Ex, *I, state); |

910 | } |

911 | |

912 | getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, Ex, *this); |

913 | } |

914 | |

915 | void ExprEngine::handleUOExtension(ExplodedNodeSet::iterator I, |

916 | const UnaryOperator *U, |

917 | StmtNodeBuilder &Bldr) { |

918 | // FIXME: We can probably just have some magic in Environment::getSVal() |

919 | // that propagates values, instead of creating a new node here. |

920 | // |

921 | // Unary "+" is a no-op, similar to a parentheses. We still have places |

922 | // where it may be a block-level expression, so we need to |

923 | // generate an extra node that just propagates the value of the |

924 | // subexpression. |

925 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |

926 | ProgramStateRef state = (*I)->getState(); |

927 | const LocationContext *LCtx = (*I)->getLocationContext(); |

928 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, |

929 | state->getSVal(Ex, LCtx))); |

930 | } |

931 | |

932 | void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, ExplodedNode *Pred, |

933 | ExplodedNodeSet &Dst) { |

934 | // FIXME: Prechecks eventually go in ::Visit(). |

935 | ExplodedNodeSet CheckedSet; |

936 | getCheckerManager().runCheckersForPreStmt(CheckedSet, Pred, U, *this); |

937 | |

938 | ExplodedNodeSet EvalSet; |

939 | StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx); |

940 | |

941 | for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end(); |

942 | I != E; ++I) { |

943 | switch (U->getOpcode()) { |

944 | default: { |

945 | Bldr.takeNodes(*I); |

946 | ExplodedNodeSet Tmp; |

947 | VisitIncrementDecrementOperator(U, *I, Tmp); |

948 | Bldr.addNodes(Tmp); |

949 | break; |

950 | } |

951 | case UO_Real: { |

952 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |

953 | |

954 | // FIXME: We don't have complex SValues yet. |

955 | if (Ex->getType()->isAnyComplexType()) { |

956 | // Just report "Unknown." |

957 | break; |

958 | } |

959 | |

960 | // For all other types, UO_Real is an identity operation. |

961 | assert (U->getType() == Ex->getType()); |

962 | ProgramStateRef state = (*I)->getState(); |

963 | const LocationContext *LCtx = (*I)->getLocationContext(); |

964 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, |

965 | state->getSVal(Ex, LCtx))); |

966 | break; |

967 | } |

968 | |

969 | case UO_Imag: { |

970 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |

971 | // FIXME: We don't have complex SValues yet. |

972 | if (Ex->getType()->isAnyComplexType()) { |

973 | // Just report "Unknown." |

974 | break; |

975 | } |

976 | // For all other types, UO_Imag returns 0. |

977 | ProgramStateRef state = (*I)->getState(); |

978 | const LocationContext *LCtx = (*I)->getLocationContext(); |

979 | SVal X = svalBuilder.makeZeroVal(Ex->getType()); |

980 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, X)); |

981 | break; |

982 | } |

983 | |

984 | case UO_AddrOf: { |

985 | // Process pointer-to-member address operation. |

986 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |

987 | if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Ex)) { |

988 | const ValueDecl *VD = DRE->getDecl(); |

989 | |

990 | if (isa<CXXMethodDecl, FieldDecl, IndirectFieldDecl>(VD)) { |

991 | ProgramStateRef State = (*I)->getState(); |

992 | const LocationContext *LCtx = (*I)->getLocationContext(); |

993 | SVal SV = svalBuilder.getMemberPointer(cast<NamedDecl>(VD)); |

994 | Bldr.generateNode(U, *I, State->BindExpr(U, LCtx, SV)); |

995 | break; |

996 | } |

997 | } |

998 | // Explicitly proceed with default handler for this case cascade. |

999 | handleUOExtension(I, U, Bldr); |

1000 | break; |

1001 | } |

1002 | case UO_Plus: |

1003 | assert(!U->isGLValue()); |

1004 | [[fallthrough]]; |

1005 | case UO_Deref: |

1006 | case UO_Extension: { |

1007 | handleUOExtension(I, U, Bldr); |

1008 | break; |

1009 | } |

1010 | |

1011 | case UO_LNot: |

1012 | case UO_Minus: |

1013 | case UO_Not: { |

1014 | assert (!U->isGLValue()); |

1015 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |

1016 | ProgramStateRef state = (*I)->getState(); |

1017 | const LocationContext *LCtx = (*I)->getLocationContext(); |

1018 | |

1019 | // Get the value of the subexpression. |

1020 | SVal V = state->getSVal(Ex, LCtx); |

1021 | |

1022 | if (V.isUnknownOrUndef()) { |

1023 | Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V)); |

1024 | break; |

1025 | } |

1026 | |

1027 | switch (U->getOpcode()) { |

1028 | default: |

1029 | llvm_unreachable("Invalid Opcode."); |

1030 | case UO_Not: |

1031 | // FIXME: Do we need to handle promotions? |

1032 | state = state->BindExpr( |

1033 | U, LCtx, svalBuilder.evalComplement(V.castAs<NonLoc>())); |

1034 | break; |

1035 | case UO_Minus: |

1036 | // FIXME: Do we need to handle promotions? |

1037 | state = state->BindExpr(U, LCtx, |

1038 | svalBuilder.evalMinus(V.castAs<NonLoc>())); |

1039 | break; |

1040 | case UO_LNot: |

1041 | // C99 6.5.3.3: "The expression !E is equivalent to (0==E)." |

1042 | // |

1043 | // Note: technically we do "E == 0", but this is the same in the |

1044 | // transfer functions as "0 == E". |

1045 | SVal Result; |

1046 | if (Optional<Loc> LV = V.getAs<Loc>()) { |

1047 | Loc X = svalBuilder.makeNullWithType(Ex->getType()); |

1048 | Result = evalBinOp(state, BO_EQ, *LV, X, U->getType()); |

1049 | } else if (Ex->getType()->isFloatingType()) { |

1050 | // FIXME: handle floating point types. |

1051 | Result = UnknownVal(); |

1052 | } else { |

1053 | nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType())); |

1054 | Result = evalBinOp(state, BO_EQ, V.castAs<NonLoc>(), X, |

1055 | U->getType()); |

1056 | } |

1057 | |

1058 | state = state->BindExpr(U, LCtx, Result); |

1059 | break; |

1060 | } |

1061 | Bldr.generateNode(U, *I, state); |

1062 | break; |

1063 | } |

1064 | } |

1065 | } |

1066 | |

1067 | getCheckerManager().runCheckersForPostStmt(Dst, EvalSet, U, *this); |

1068 | } |

1069 | |

1070 | void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, |

1071 | ExplodedNode *Pred, |

1072 | ExplodedNodeSet &Dst) { |

1073 | // Handle ++ and -- (both pre- and post-increment). |

1074 | assert (U->isIncrementDecrementOp()); |

1075 | const Expr *Ex = U->getSubExpr()->IgnoreParens(); |

1076 | |

1077 | const LocationContext *LCtx = Pred->getLocationContext(); |

1078 | ProgramStateRef state = Pred->getState(); |

1079 | SVal loc = state->getSVal(Ex, LCtx); |

1080 | |

1081 | // Perform a load. |

1082 | ExplodedNodeSet Tmp; |

1083 | evalLoad(Tmp, U, Ex, Pred, state, loc); |

1084 | |

1085 | ExplodedNodeSet Dst2; |

1086 | StmtNodeBuilder Bldr(Tmp, Dst2, *currBldrCtx); |

1087 | for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end();I!=E;++I) { |

1088 | |

1089 | state = (*I)->getState(); |

1090 | assert(LCtx == (*I)->getLocationContext()); |

1091 | SVal V2_untested = state->getSVal(Ex, LCtx); |

1092 | |

1093 | // Propagate unknown and undefined values. |

1094 | if (V2_untested.isUnknownOrUndef()) { |

1095 | state = state->BindExpr(U, LCtx, V2_untested); |

1096 | |

1097 | // Perform the store, so that the uninitialized value detection happens. |

1098 | Bldr.takeNodes(*I); |

1099 | ExplodedNodeSet Dst3; |

1100 | evalStore(Dst3, U, Ex, *I, state, loc, V2_untested); |

1101 | Bldr.addNodes(Dst3); |

1102 | |

1103 | continue; |

1104 | } |

1105 | DefinedSVal V2 = V2_untested.castAs<DefinedSVal>(); |

1106 | |

1107 | // Handle all other values. |

1108 | BinaryOperator::Opcode Op = U->isIncrementOp() ? BO_Add : BO_Sub; |

1109 | |

1110 | // If the UnaryOperator has non-location type, use its type to create the |

1111 | // constant value. If the UnaryOperator has location type, create the |

1112 | // constant with int type and pointer width. |

1113 | SVal RHS; |

1114 | SVal Result; |

1115 | |

1116 | if (U->getType()->isAnyPointerType()) |

1117 | RHS = svalBuilder.makeArrayIndex(1); |

1118 | else if (U->getType()->isIntegralOrEnumerationType()) |

1119 | RHS = svalBuilder.makeIntVal(1, U->getType()); |

1120 | else |

1121 | RHS = UnknownVal(); |

1122 | |

1123 | // The use of an operand of type bool with the ++ operators is deprecated |

1124 | // but valid until C++17. And if the operand of the ++ operator is of type |

1125 | // bool, it is set to true until C++17. Note that for '_Bool', it is also |

1126 | // set to true when it encounters ++ operator. |

1127 | if (U->getType()->isBooleanType() && U->isIncrementOp()) |

1128 | Result = svalBuilder.makeTruthVal(true, U->getType()); |

1129 | else |

1130 | Result = evalBinOp(state, Op, V2, RHS, U->getType()); |

1131 | |

1132 | // Conjure a new symbol if necessary to recover precision. |

1133 | if (Result.isUnknown()){ |

1134 | DefinedOrUnknownSVal SymVal = |

1135 | svalBuilder.conjureSymbolVal(nullptr, U, LCtx, |

1136 | currBldrCtx->blockCount()); |

1137 | Result = SymVal; |

1138 | |

1139 | // If the value is a location, ++/-- should always preserve |

1140 | // non-nullness. Check if the original value was non-null, and if so |

1141 | // propagate that constraint. |

1142 | if (Loc::isLocType(U->getType())) { |

1143 | DefinedOrUnknownSVal Constraint = |

1144 | svalBuilder.evalEQ(state, V2,svalBuilder.makeZeroVal(U->getType())); |

1145 | |

1146 | if (!state->assume(Constraint, true)) { |

1147 | // It isn't feasible for the original value to be null. |

1148 | // Propagate this constraint. |

1149 | Constraint = svalBuilder.evalEQ(state, SymVal, |

1150 | svalBuilder.makeZeroVal(U->getType())); |

1151 | |

1152 | state = state->assume(Constraint, false); |

1153 | assert(state); |

1154 | } |

1155 | } |

1156 | } |

1157 | |

1158 | // Since the lvalue-to-rvalue conversion is explicit in the AST, |

1159 | // we bind an l-value if the operator is prefix and an lvalue (in C++). |

1160 | if (U->isGLValue()) |

1161 | state = state->BindExpr(U, LCtx, loc); |

1162 | else |

1163 | state = state->BindExpr(U, LCtx, U->isPostfix() ? V2 : Result); |

1164 | |

1165 | // Perform the store. |

1166 | Bldr.takeNodes(*I); |

1167 | ExplodedNodeSet Dst3; |

1168 | evalStore(Dst3, U, Ex, *I, state, loc, Result); |

1169 | Bldr.addNodes(Dst3); |

1170 | } |

1171 | Dst.insert(Dst2); |

1172 | } |

1173 |