clang: lib/Analysis/FlowSensitive/Transfer.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

32#include "llvm/Support/Casting.h"

33#include "llvm/Support/Debug.h"

35#include

36

37#define DEBUG_TYPE "dataflow"

38

40namespace dataflow {

41

44 if (Block == nullptr) {

45 assert(false);

46 return nullptr;

47 }

49 return nullptr;

50 if (Block->getBlockID() == CurBlockID)

51 return &CurState.Env;

52 const auto &State = BlockToState[Block->getBlockID()];

53 if (!(State))

54 return nullptr;

55 return &State->Env;

56}

57

62

63 if (LHSValue == RHSValue)

65

66 if (auto *LHSBool = dyn_cast_or_null(LHSValue))

67 if (auto *RHSBool = dyn_cast_or_null(RHSValue))

68 return Env.makeIff(*LHSBool, *RHSBool);

69

70 if (auto *LHSPtr = dyn_cast_or_null(LHSValue))

71 if (auto *RHSPtr = dyn_cast_or_null(RHSValue))

72

73

74

75 if (&LHSPtr->getPointeeLoc() == &RHSPtr->getPointeeLoc())

77

79}

80

82 if (auto *Top = llvm::dyn_cast(&V)) {

84 return A.makeBoolValue(A.makeAtomRef(Top->getAtom()));

85 }

86 return V;

87}

88

89

90

91

94 if (Loc == nullptr)

95 return nullptr;

97

98 auto *B = dyn_cast_or_null(Val);

99 if (B == nullptr)

100 return Val;

101

103 if (&UnpackedVal == Val)

104 return Val;

106 return &UnpackedVal;

107}

108

111 return;

114}

115

120}

121

122

123

124

130 else

132}

133

134namespace {

135

136class TransferVisitor : public ConstStmtVisitor {

137public:

138 TransferVisitor(const StmtToEnvMap &StmtToEnv, Environment &Env,

139 Environment::ValueModel &Model)

140 : StmtToEnv(StmtToEnv), Env(Env), Model(Model) {}

141

142 void VisitBinaryOperator(const BinaryOperator *S) {

143 const Expr *LHS = S->getLHS();

144 assert(LHS != nullptr);

145

146 const Expr *RHS = S->getRHS();

147 assert(RHS != nullptr);

148

149

150

151

152

153 if (S->isCompoundAssignmentOp())

155

156 switch (S->getOpcode()) {

157 case BO_Assign: {

158 auto *LHSLoc = Env.getStorageLocation(*LHS);

159 if (LHSLoc == nullptr)

160 break;

161

162 auto *RHSVal = Env.getValue(*RHS);

163 if (RHSVal == nullptr)

164 break;

165

166

167 Env.setValue(*LHSLoc, *RHSVal);

168

169

170 Env.setStorageLocation(*S, *LHSLoc);

171 break;

172 }

173 case BO_LAnd:

174 case BO_LOr: {

175 BoolValue &LHSVal = getLogicOperatorSubExprValue(*LHS);

176 BoolValue &RHSVal = getLogicOperatorSubExprValue(*RHS);

177

178 if (S->getOpcode() == BO_LAnd)

179 Env.setValue(*S, Env.makeAnd(LHSVal, RHSVal));

180 else

181 Env.setValue(*S, Env.makeOr(LHSVal, RHSVal));

182 break;

183 }

184 case BO_NE:

185 case BO_EQ: {

187 Env.setValue(*S, S->getOpcode() == BO_EQ ? LHSEqRHSValue

188 : Env.makeNot(LHSEqRHSValue));

189 break;

190 }

191 case BO_Comma: {

193 break;

194 }

195 default:

196 break;

197 }

198 }

199

200 void VisitDeclRefExpr(const DeclRefExpr *S) {

201 const ValueDecl *VD = S->getDecl();

202 assert(VD != nullptr);

203

204

205

206

207

208

209

210

211

212

213 if (!S->isGLValue())

214 return;

215

216 auto *DeclLoc = Env.getStorageLocation(*VD);

217 if (DeclLoc == nullptr)

218 return;

219

220 Env.setStorageLocation(*S, *DeclLoc);

221 }

222

223 void VisitDeclStmt(const DeclStmt *S) {

224

225

226 const auto &D = *cast(S->getSingleDecl());

227

228 ProcessVarDecl(D);

229 }

230

231 void ProcessVarDecl(const VarDecl &D) {

232

233 if (D.hasGlobalStorage())

234 return;

235

236

237

238

239 if (D.getType()->isReferenceType() && Env.getStorageLocation(D) != nullptr)

240 return;

241

242 assert(Env.getStorageLocation(D) == nullptr);

243

244 Env.setStorageLocation(D, Env.createObject(D));

245

246

247

248

249 if (const auto *Decomp = dyn_cast(&D)) {

250

251

252

253

254

255 for (const auto *B : Decomp->bindings()) {

256 if (auto *ME = dyn_cast_or_null(B->getBinding())) {

257 auto *DE = dyn_cast_or_null(ME->getBase());

258 if (DE == nullptr)

259 continue;

260

261

262

263 VisitDeclRefExpr(DE);

264 VisitMemberExpr(ME);

265

266 if (auto *Loc = Env.getStorageLocation(*ME))

267 Env.setStorageLocation(*B, *Loc);

268 } else if (auto *VD = B->getHoldingVar()) {

269

270

271

272

273

274

275 ProcessVarDecl(*VD);

276 auto *VDLoc = Env.getStorageLocation(*VD);

277 assert(VDLoc != nullptr);

278 Env.setStorageLocation(*B, *VDLoc);

279 }

280 }

281 }

282 }

283

284 void VisitImplicitCastExpr(const ImplicitCastExpr *S) {

285 const Expr *SubExpr = S->getSubExpr();

286 assert(SubExpr != nullptr);

287

288 switch (S->getCastKind()) {

289 case CK_IntegralToBoolean: {

290

291

292

293 if (auto *SubExprVal =

294 dyn_cast_or_null(Env.getValue(*SubExpr)))

295 Env.setValue(*S, *SubExprVal);

296 else

297

298

299 Env.setValue(*S, Env.makeAtomicBoolValue());

300 break;

301 }

302

303 case CK_LValueToRValue: {

304

305

307 if (SubExprVal == nullptr)

308 break;

309

310 Env.setValue(*S, *SubExprVal);

311 break;

312 }

313

314 case CK_IntegralCast:

315

316

317

318

319

320 case CK_UncheckedDerivedToBase:

321 case CK_ConstructorConversion:

322 case CK_UserDefinedConversion:

323

324

325 case CK_NoOp: {

326

327

328

330 break;

331 }

332 case CK_NullToPointer: {

333 auto &NullPointerVal =

334 Env.getOrCreateNullPointerValue(S->getType()->getPointeeType());

335 Env.setValue(*S, NullPointerVal);

336 break;

337 }

338 case CK_NullToMemberPointer:

339

340

341 break;

342 case CK_FunctionToPointerDecay: {

343 StorageLocation *PointeeLoc = Env.getStorageLocation(*SubExpr);

344 if (PointeeLoc == nullptr)

345 break;

346

347 Env.setValue(*S, Env.create(*PointeeLoc));

348 break;

349 }

350 case CK_BuiltinFnToFnPtr:

351

352

353

354

355 break;

356 default:

357 break;

358 }

359 }

360

361 void VisitUnaryOperator(const UnaryOperator *S) {

362 const Expr *SubExpr = S->getSubExpr();

363 assert(SubExpr != nullptr);

364

365 switch (S->getOpcode()) {

366 case UO_Deref: {

367 const auto *SubExprVal = Env.get(*SubExpr);

368 if (SubExprVal == nullptr)

369 break;

370

371 Env.setStorageLocation(*S, SubExprVal->getPointeeLoc());

372 break;

373 }

374 case UO_AddrOf: {

375

376 if (S->getType()->isMemberPointerType())

377 break;

378

379 if (StorageLocation *PointeeLoc = Env.getStorageLocation(*SubExpr))

380 Env.setValue(*S, Env.create(*PointeeLoc));

381 break;

382 }

383 case UO_LNot: {

384 auto *SubExprVal = dyn_cast_or_null(Env.getValue(*SubExpr));

385 if (SubExprVal == nullptr)

386 break;

387

388 Env.setValue(*S, Env.makeNot(*SubExprVal));

389 break;

390 }

391 case UO_PreInc:

392 case UO_PreDec:

393

394

395

396

398 if (StorageLocation *Loc = Env.getStorageLocation(*S->getSubExpr()))

399 Env.clearValue(*Loc);

400 break;

401 case UO_PostInc:

402 case UO_PostDec:

403

404

405

407 if (StorageLocation *Loc = Env.getStorageLocation(*S->getSubExpr()))

408 Env.clearValue(*Loc);

409 break;

410 default:

411 break;

412 }

413 }

414

415 void VisitCXXThisExpr(const CXXThisExpr *S) {

416 auto *ThisPointeeLoc = Env.getThisPointeeStorageLocation();

417 if (ThisPointeeLoc == nullptr)

418

419

420 return;

421

422 Env.setValue(*S, Env.create(*ThisPointeeLoc));

423 }

424

425 void VisitCXXNewExpr(const CXXNewExpr *S) {

426 if (Value *Val = Env.createValue(S->getType()))

427 Env.setValue(*S, *Val);

428 }

429

430 void VisitCXXDeleteExpr(const CXXDeleteExpr *S) {

431

432

433

434

435 }

436

437 void VisitReturnStmt(const ReturnStmt *S) {

438 if (Env.getDataflowAnalysisContext().getOptions().ContextSensitiveOpts)

439 return;

440

441 auto *Ret = S->getRetValue();

442 if (Ret == nullptr)

443 return;

444

445 if (Ret->isPRValue()) {

446 if (Ret->getType()->isRecordType())

447 return;

448

449 auto *Val = Env.getValue(*Ret);

450 if (Val == nullptr)

451 return;

452

453

454 Env.setReturnValue(Val);

455 } else {

456 auto *Loc = Env.getStorageLocation(*Ret);

457 if (Loc == nullptr)

458 return;

459

460

461 Env.setReturnStorageLocation(Loc);

462 }

463 }

464

465 void VisitMemberExpr(const MemberExpr *S) {

466 ValueDecl *Member = S->getMemberDecl();

467 assert(Member != nullptr);

468

469

470 if (Member->isFunctionOrFunctionTemplate())

471 return;

472

473

474 if (isa(Member))

475 return;

476

477 if (auto *D = dyn_cast(Member)) {

478 if (D->hasGlobalStorage()) {

479 auto *VarDeclLoc = Env.getStorageLocation(*D);

480 if (VarDeclLoc == nullptr)

481 return;

482

483 Env.setStorageLocation(*S, *VarDeclLoc);

484 return;

485 }

486 }

487

489 if (BaseLoc == nullptr)

490 return;

491

492 auto *MemberLoc = BaseLoc->getChild(*Member);

493 if (MemberLoc == nullptr)

494 return;

495 Env.setStorageLocation(*S, *MemberLoc);

496 }

497

498 void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *S) {

499 const Expr *ArgExpr = S->getExpr();

500 assert(ArgExpr != nullptr);

502

503 if (S->isPRValue() && S->getType()->isRecordType()) {

504 auto &Loc = Env.getResultObjectLocation(*S);

505 Env.initializeFieldsWithValues(Loc);

506 }

507 }

508

509 void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {

510 const Expr *InitExpr = S->getExpr();

511 assert(InitExpr != nullptr);

512

513

514

515

516 if (S->getType()->isRecordType() && S->isPRValue())

517 return;

518

520 }

521

522 void VisitCXXConstructExpr(const CXXConstructExpr *S) {

523 const CXXConstructorDecl *ConstructorDecl = S->getConstructor();

524 assert(ConstructorDecl != nullptr);

525

526

527

528

529 if (!S->getType()->isRecordType()) {

530 transferInlineCall(S, ConstructorDecl);

531 return;

532 }

533

534 RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);

535

536 if (ConstructorDecl->isCopyOrMoveConstructor()) {

537

538

539 assert(S->getNumArgs() != 0);

540

541 const Expr *Arg = S->getArg(0);

542 assert(Arg != nullptr);

543

544 auto *ArgLoc = Env.get(*Arg);

545 if (ArgLoc == nullptr)

546 return;

547

548

549

550

552 return;

553 }

554

555 Env.initializeFieldsWithValues(Loc, S->getType());

556

557 transferInlineCall(S, ConstructorDecl);

558 }

559

560 void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *S) {

561 if (S->getOperator() == OO_Equal) {

562 assert(S->getNumArgs() == 2);

563

564 const Expr *Arg0 = S->getArg(0);

565 assert(Arg0 != nullptr);

566

567 const Expr *Arg1 = S->getArg(1);

568 assert(Arg1 != nullptr);

569

570

571 const auto *Method =

572 dyn_cast_or_null(S->getDirectCallee());

573 if (!Method)

574 return;

575 if (!Method->isCopyAssignmentOperator() &&

576 !Method->isMoveAssignmentOperator())

577 return;

578

579 RecordStorageLocation *LocSrc = nullptr;

580 if (Arg1->isPRValue()) {

581 LocSrc = &Env.getResultObjectLocation(*Arg1);

582 } else {

583 LocSrc = Env.get(*Arg1);

584 }

585 auto *LocDst = Env.get(*Arg0);

586

587 if (LocSrc == nullptr || LocDst == nullptr)

588 return;

589

591

592

593

594

595 if (S->getType().getCanonicalType().getUnqualifiedType() !=

596 LocDst->getType().getCanonicalType().getUnqualifiedType()) {

597 auto ReturnDecl = S->getType()->getAsCXXRecordDecl();

598 auto DstDecl = LocDst->getType()->getAsCXXRecordDecl();

599 if (ReturnDecl == nullptr || DstDecl == nullptr)

600 return;

601 if (!DstDecl->isDerivedFrom(ReturnDecl))

602 return;

603 }

604

605 if (S->isGLValue())

606 Env.setStorageLocation(*S, *LocDst);

607 else

608 copyRecord(*LocDst, Env.getResultObjectLocation(*S), Env);

609

610 return;

611 }

612

613

614

615 VisitCallExpr(S);

616 }

617

618 void VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator *RBO) {

620 }

621

622 void VisitCallExpr(const CallExpr *S) {

623

624

625

626 if (S->isCallToStdMove()) {

627 assert(S->getNumArgs() == 1);

628

629 const Expr *Arg = S->getArg(0);

630 assert(Arg != nullptr);

631

632 auto *ArgLoc = Env.getStorageLocation(*Arg);

633 if (ArgLoc == nullptr)

634 return;

635

636 Env.setStorageLocation(*S, *ArgLoc);

637 } else if (S->getDirectCallee() != nullptr &&

638 S->getDirectCallee()->getBuiltinID() ==

639 Builtin::BI__builtin_expect) {

640 assert(S->getNumArgs() > 0);

641 assert(S->getArg(0) != nullptr);

642 auto *ArgVal = Env.getValue(*S->getArg(0));

643 if (ArgVal == nullptr)

644 return;

645 Env.setValue(*S, *ArgVal);

646 } else if (const FunctionDecl *F = S->getDirectCallee()) {

647 transferInlineCall(S, F);

648

649

650

651 if (S->getType()->isRecordType() && S->isPRValue()) {

652 RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);

653 Env.initializeFieldsWithValues(Loc);

654 }

655 }

656 }

657

658 void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {

659 const Expr *SubExpr = S->getSubExpr();

660 assert(SubExpr != nullptr);

661

662 StorageLocation &Loc = Env.createStorageLocation(*S);

663 Env.setStorageLocation(*S, Loc);

664

665 if (SubExpr->getType()->isRecordType())

666

667

668 return;

669

670 if (Value *SubExprVal = Env.getValue(*SubExpr))

671 Env.setValue(Loc, *SubExprVal);

672 }

673

674 void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *S) {

675 const Expr *SubExpr = S->getSubExpr();

676 assert(SubExpr != nullptr);

677

679 }

680

681 void VisitCXXStaticCastExpr(const CXXStaticCastExpr *S) {

682 if (S->getCastKind() == CK_NoOp) {

683 const Expr *SubExpr = S->getSubExpr();

684 assert(SubExpr != nullptr);

685

687 }

688 }

689

690 void VisitConditionalOperator(const ConditionalOperator *S) {

691 const Environment *TrueEnv = StmtToEnv.getEnvironment(*S->getTrueExpr());

692 const Environment *FalseEnv = StmtToEnv.getEnvironment(*S->getFalseExpr());

693

694 if (TrueEnv == nullptr || FalseEnv == nullptr) {

695

696

697

698

699 return;

700 }

701

702 if (S->isGLValue()) {

703 StorageLocation *TrueLoc = TrueEnv->getStorageLocation(*S->getTrueExpr());

704 StorageLocation *FalseLoc =

705 FalseEnv->getStorageLocation(*S->getFalseExpr());

706 if (TrueLoc == FalseLoc && TrueLoc != nullptr)

707 Env.setStorageLocation(*S, *TrueLoc);

708 } else if (!S->getType()->isRecordType()) {

709

710

711

712

713

714

715

716

717

718

719

720

721

722

723

725 S->getType(), TrueEnv->getValue(*S->getTrueExpr()), *TrueEnv,

726 FalseEnv->getValue(*S->getFalseExpr()), *FalseEnv, Env, Model))

727 Env.setValue(*S, *Val);

728 }

729 }

730

731 void VisitInitListExpr(const InitListExpr *S) {

732 QualType Type = S->getType();

733

734 if (Type->isRecordType()) {

735

736

737 if (Type->isArrayType() && S->getNumInits() == 1)

739 return;

740 }

741

742

743 if (S->isSemanticForm() && S->isTransparent())

744 return;

745

746 RecordStorageLocation &Loc = Env.getResultObjectLocation(*S);

747

748

749

750

751

752

753 RecordInitListHelper InitListHelper(S);

754

755 for (auto [Field, Init] : InitListHelper.field_inits()) {

756 if (Field->getType()->isRecordType())

757 continue;

758 if (Field->getType()->isReferenceType()) {

759 assert(Field->getType().getCanonicalType()->getPointeeType() ==

760 Init->getType().getCanonicalType());

761 Loc.setChild(*Field, &Env.createObject(Field->getType(), Init));

762 continue;

763 }

764 assert(Field->getType().getCanonicalType().getUnqualifiedType() ==

765 Init->getType().getCanonicalType().getUnqualifiedType());

766 StorageLocation *FieldLoc = Loc.getChild(*Field);

767

768 assert(FieldLoc != nullptr);

770 if (Val == nullptr && isa(Init) &&

771 Init->getType()->isPointerType())

772 Val =

773 &Env.getOrCreateNullPointerValue(Init->getType()->getPointeeType());

774 if (Val == nullptr)

775 Val = Env.createValue(Field->getType());

776 if (Val != nullptr)

777 Env.setValue(*FieldLoc, *Val);

778 }

779

780 for (const auto &[FieldName, FieldLoc] : Loc.synthetic_fields()) {

781 QualType FieldType = FieldLoc->getType();

782 if (FieldType->isRecordType()) {

783 Env.initializeFieldsWithValues(*cast(FieldLoc));

784 } else {

785 if (Value *Val = Env.createValue(FieldType))

786 Env.setValue(*FieldLoc, *Val);

787 }

788 }

789

790

791 }

792

793 void VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *S) {

794 Env.setValue(*S, Env.getBoolLiteralValue(S->getValue()));

795 }

796

797 void VisitIntegerLiteral(const IntegerLiteral *S) {

798 Env.setValue(*S, Env.getIntLiteralValue(S->getValue()));

799 }

800

801 void VisitParenExpr(const ParenExpr *S) {

802

803

804

805 auto *SubExpr = S->getSubExpr();

806 assert(SubExpr != nullptr);

807 Visit(SubExpr);

808 }

809

810 void VisitExprWithCleanups(const ExprWithCleanups *S) {

811

812

813

814 auto *SubExpr = S->getSubExpr();

815 assert(SubExpr != nullptr);

816 Visit(SubExpr);

817 }

818

819private:

820

821 BoolValue &getLogicOperatorSubExprValue(const Expr &SubExpr) {

822

823

824

825 if (const Environment *SubExprEnv = StmtToEnv.getEnvironment(SubExpr))

826 if (auto *Val =

827 dyn_cast_or_null(SubExprEnv->getValue(SubExpr)))

828 return *Val;

829

830

831

832

833

834

835 if (Env.getValue(SubExpr) == nullptr)

836 Visit(&SubExpr);

837 if (auto *Val = dyn_cast_or_null(Env.getValue(SubExpr)))

838 return *Val;

839

840

841

842 return Env.makeAtomicBoolValue();

843 }

844

845

846

847 template

848 void transferInlineCall(const E *S, const FunctionDecl *F) {

849 const auto &Options = Env.getDataflowAnalysisContext().getOptions();

850 if (!(Options.ContextSensitiveOpts &&

851 Env.canDescend(Options.ContextSensitiveOpts->Depth, F)))

852 return;

853

854 const AdornedCFG *ACFG = Env.getDataflowAnalysisContext().getAdornedCFG(F);

855 if (!ACFG)

856 return;

857

858

859

860

861

862 auto ExitBlock = ACFG->getCFG().getExit().getBlockID();

863

864 auto CalleeEnv = Env.pushCall(S);

865

866

867

868

869 auto Analysis = NoopAnalysis(ACFG->getDecl().getASTContext(),

870 DataflowAnalysisOptions{Options});

871

872 auto BlockToOutputState =

874 assert(BlockToOutputState);

875 assert(ExitBlock < BlockToOutputState->size());

876

877 auto &ExitState = (*BlockToOutputState)[ExitBlock];

878 assert(ExitState);

879

880 Env.popCall(S, ExitState->Env);

881 }

882

883 const StmtToEnvMap &StmtToEnv;

884 Environment &Env;

885 Environment::ValueModel &Model;

886};

887

888}

889

892 TransferVisitor(StmtToEnv, Env, Model).Visit(&S);

893}

894

895}

896}

Defines enum values for all the target-independent builtin functions.

Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....

Defines the clang::Expr interface and subclasses for C++ expressions.

Defines an enumeration for C++ overloaded operators.

TypeErasedDataflowAnalysis & Analysis

The analysis to be run.

Represents a single basic block in a source-level CFG.

ConstStmtVisitor - This class implements a simple visitor for Stmt subclasses.

This represents one expression.

Stmt - This represents one statement.

bool isRecordType() const

const CFGBlock * blockForStmt(const Stmt &S) const

Returns the basic block that contains S, or null if no basic block containing S is found.

bool isBlockReachable(const CFGBlock &B) const

Returns whether B is reachable from the entry block.

BoolValue & makeBoolValue(const Formula &)

Creates a BoolValue wrapping a particular formula.

Supplements Environment with non-standard comparison and join operations.

Holds the state of the program (store and heap) at a given program point.

BoolValue & makeIff(BoolValue &LHS, BoolValue &RHS) const

Returns a boolean value represents LHS <=> RHS.

StorageLocation * getStorageLocation(const ValueDecl &D) const

Returns the storage location assigned to D in the environment, or null if D isn't assigned a storage ...

BoolValue & makeAtomicBoolValue() const

Returns an atomic boolean value.

Value * getValue(const StorageLocation &Loc) const

Returns the value assigned to Loc in the environment or null if Loc isn't assigned a value in the env...

BoolValue & getBoolLiteralValue(bool Value) const

Returns a symbolic boolean value that models a boolean literal equal to Value

DataflowAnalysisContext & getDataflowAnalysisContext() const

Returns the DataflowAnalysisContext used by the environment.

static Value * joinValues(QualType Ty, Value *Val1, const Environment &Env1, Value *Val2, const Environment &Env2, Environment &JoinedEnv, Environment::ValueModel &Model)

Returns a value that approximates both Val1 and Val2, or null if no such value can be produced.

void setStorageLocation(const ValueDecl &D, StorageLocation &Loc)

Assigns Loc as the storage location of D in the environment.

void setValue(const StorageLocation &Loc, Value &Val)

Assigns Val as the value of Loc in the environment.

Maps statements to the environments of basic blocks that contain them.

const Environment * getEnvironment(const Stmt &S) const

Returns the environment of the basic block that contains S.

Base class for all values computed by abstract interpretation.

void transfer(const StmtToEnvMap &StmtToEnv, const Stmt &S, Environment &Env, Environment::ValueModel &Model)

Evaluates S and updates Env accordingly.

static void propagateValueOrStorageLocation(const Expr &From, const Expr &To, Environment &Env)

static void propagateStorageLocation(const Expr &From, const Expr &To, Environment &Env)

static void propagateValue(const Expr &From, const Expr &To, Environment &Env)

static Value * maybeUnpackLValueExpr(const Expr &E, Environment &Env)

void copyRecord(RecordStorageLocation &Src, RecordStorageLocation &Dst, Environment &Env)

Copies a record (struct, class, or union) from Src to Dst.

static BoolValue & unpackValue(BoolValue &V, Environment &Env)

static BoolValue & evaluateBooleanEquality(const Expr &LHS, const Expr &RHS, Environment &Env)

RecordStorageLocation * getBaseObjectLocation(const MemberExpr &ME, const Environment &Env)

Returns the storage location for the base object of a MemberExpr, or null if none is defined in the e...

llvm::Expected< std::vector< std::optional< DataflowAnalysisState< typename AnalysisT::Lattice > > > > runDataflowAnalysis(const AdornedCFG &ACFG, AnalysisT &Analysis, const Environment &InitEnv, CFGEltCallbacks< AnalysisT > PostAnalysisCallbacks={}, std::int32_t MaxBlockVisits=kDefaultMaxBlockVisits)

Performs dataflow analysis and returns a mapping from basic block IDs to dataflow analysis states tha...

bool Ret(InterpState &S, CodePtr &PC)

The JSON file list parser is used to communicate input to InstallAPI.

Environment Env

Model of the state of the program (store and heap).