clang: lib/StaticAnalyzer/Core/ExprEngine.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

64#include "llvm/ADT/APSInt.h"

65#include "llvm/ADT/DenseMap.h"

66#include "llvm/ADT/ImmutableMap.h"

67#include "llvm/ADT/ImmutableSet.h"

68#include "llvm/ADT/STLExtras.h"

69#include "llvm/ADT/SmallVector.h"

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

71#include "llvm/Support/Compiler.h"

72#include "llvm/Support/DOTGraphTraits.h"

73#include "llvm/Support/ErrorHandling.h"

74#include "llvm/Support/GraphWriter.h"

75#include "llvm/Support/TimeProfiler.h"

76#include "llvm/Support/raw_ostream.h"

77#include

78#include

79#include

80#include

81#include

82#include

83#include

84#include

85

86using namespace clang;

87using namespace ento;

88

89#define DEBUG_TYPE "ExprEngine"

90

92 "The # of times RemoveDeadBindings is called");

94 NumMaxBlockCountReached,

95 "The # of aborted paths due to reaching the maximum block count in "

96 "a top level function");

98 NumMaxBlockCountReachedInInlined,

99 "The # of aborted paths due to reaching the maximum block count in "

100 "an inlined function");

102 "The # of times we re-evaluated a call without inlining");

103

104

105

106

107

108namespace {

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123class ConstructedObjectKey {

124 using ConstructedObjectKeyImpl =

125 std::pair<ConstructionContextItem, const LocationContext *>;

126 const ConstructedObjectKeyImpl Impl;

127

128public:

131 : Impl(Item, LC) {}

132

133 const ConstructionContextItem &getItem() const { return Impl.first; }

134 const LocationContext *getLocationContext() const { return Impl.second; }

135

136 ASTContext &getASTContext() const {

137 return getLocationContext()->getDecl()->getASTContext();

138 }

139

140 void printJson(llvm::raw_ostream &Out, PrinterHelper *Helper,

141 PrintingPolicy &PP) const {

142 const Stmt *S = getItem().getStmtOrNull();

143 const CXXCtorInitializer *I = nullptr;

144 if (!S)

145 I = getItem().getCXXCtorInitializer();

146

147 if (S)

148 Out << "\"stmt_id\": " << S->getID(getASTContext());

149 else

150 Out << "\"init_id\": " << I->getID(getASTContext());

151

152

153 Out << ", \"kind\": \"" << getItem().getKindAsString()

154 << "\", \"argument_index\": ";

155

157 Out << getItem().getIndex();

158 else

159 Out << "null";

160

161

162 Out << ", \"pretty\": ";

163

164 if (S) {

165 S->printJson(Out, Helper, PP, true);

166 } else {

168 }

169 }

170

171 void Profile(llvm::FoldingSetNodeID &ID) const {

172 ID.Add(Impl.first);

173 ID.AddPointer(Impl.second);

174 }

175

176 bool operator==(const ConstructedObjectKey &RHS) const {

177 return Impl == RHS.Impl;

178 }

179

180 bool operator<(const ConstructedObjectKey &RHS) const {

181 return Impl < RHS.Impl;

182 }

183};

184}

185

186typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>

190

191

192

193

194

195

196

197typedef llvm::ImmutableMap<

198 std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>

199 IndexOfElementToConstructMap;

201 IndexOfElementToConstructMap)

202

203

204

205

206typedef llvm::ImmutableMap<

207 std::pair<const CXXConstructExpr *, const LocationContext *>, unsigned>

208 PendingInitLoopMap;

210

211typedef llvm::ImmutableMap<const LocationContext *, unsigned>

215

216

217

218

219

220static const char* TagProviderName = "ExprEngine";

221

225 : CTU(CTU), IsCTUEnabled(mgr.getAnalyzerOptions().IsNaiveCTUEnabled),

227 Engine(*this, FS, mgr.getAnalyzerOptions()), G(Engine.getGraph()),

228 StateMgr(getContext(), mgr.getStoreManagerCreator(),

229 mgr.getConstraintManagerCreator(), G.getAllocator(), this),

231 svalBuilder(StateMgr.getSValBuilder()), ObjCNoRet(mgr.getASTContext()),

232 BR(mgr, *this), VisitedCallees(VisitedCalleesIn),

233 HowToInline(HowToInlineIn) {

234 unsigned TrimInterval = mgr.options.GraphTrimInterval;

235 if (TrimInterval != 0) {

236

237 G.enableNodeReclamation(TrimInterval);

238 }

239}

240

241

242

243

244

246 ProgramStateRef state = StateMgr.getInitialState(InitLoc);

248

249

250

251

252 do {

253 if (const auto *FD = dyn_cast(D)) {

254

255

257 if (!II || !(II->getName() == "main" && FD->getNumParams() > 0))

258 break;

259

260 const ParmVarDecl *PD = FD->getParamDecl(0);

262 const auto *BT = dyn_cast(T);

263 if (!BT || !BT->isInteger())

264 break;

265

266 const MemRegion *R = state->getRegion(PD, InitLoc);

267 if (!R)

268 break;

269

271 SVal Constraint_untested = evalBinOp(state, BO_GT, V,

272 svalBuilder.makeZeroVal(T),

273 svalBuilder.getConditionType());

274

275 std::optional Constraint =

277

278 if (!Constraint)

279 break;

280

281 if (ProgramStateRef newState = state->assume(*Constraint, true))

282 state = newState;

283 }

284 break;

285 }

286 while (false);

287

288 if (const auto *MD = dyn_cast(D)) {

289

290

292 const MemRegion *R = state->getRegion(SelfD, InitLoc);

294

295 if (std::optional LV = V.getAs<Loc>()) {

296

297 state = state->assume(*LV, true);

298 assert(state && "'self' cannot be null");

299 }

300 }

301

302 if (const auto *MD = dyn_cast(D)) {

303 if (MD->isImplicitObjectMemberFunction()) {

304

305

306

308 if (SFC->getParent() == nullptr) {

310 SVal V = state->getSVal(L);

311 if (std::optional LV = V.getAs<Loc>()) {

312 state = state->assume(*LV, true);

313 assert(state && "'this' cannot be null");

314 }

315 }

316 }

317 }

318

319 return state;

320}

321

322ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(

325 const SubRegion **OutRegionWithAdjustments) {

326

327

328

329

330

331 SVal InitValWithAdjustments = State->getSVal(InitWithAdjustments, LC);

333

334

335 if (isa<NonLoc>(InitValWithAdjustments)) {

336 if (OutRegionWithAdjustments)

337 *OutRegionWithAdjustments = nullptr;

338 return State;

339 }

340 Result = InitWithAdjustments;

341 } else {

342

343

344 assert(isa<Loc>(InitValWithAdjustments) ||

346 Result->getType()->isMemberPointerType());

347 }

348

349 ProgramStateManager &StateMgr = State->getStateManager();

350 MemRegionManager &MRMgr = StateMgr.getRegionManager();

351 StoreManager &StoreMgr = StateMgr.getStoreManager();

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374 SmallVector<const Expr *, 2> CommaLHSs;

375 SmallVector<SubobjectAdjustment, 2> Adjustments;

376

378 CommaLHSs, Adjustments);

379

380

381

382

383

384

385 const TypedValueRegion *TR = nullptr;

386 if (const auto *MT = dyn_cast(Result)) {

388 State = finishObjectConstruction(State, MT, LC);

389 State = State->BindExpr(Result, LC, *V);

390 return State;

391 } else if (const ValueDecl *VD = MT->getExtendingDecl()) {

394

395

397 TR = MRMgr.getCXXStaticLifetimeExtendedObjectRegion(Init, VD);

398 } else {

399 TR = MRMgr.getCXXLifetimeExtendedObjectRegion(Init, VD, LC);

400 }

401 } else {

403 TR = MRMgr.getCXXTempObjectRegion(Init, LC);

404 }

405 } else {

406 TR = MRMgr.getCXXTempObjectRegion(Init, LC);

407 }

408

409 SVal Reg = loc::MemRegionVal(TR);

410 SVal BaseReg = Reg;

411

412

413 for (const SubobjectAdjustment &Adj : llvm::reverse(Adjustments)) {

414 switch (Adj.Kind) {

416 Reg = StoreMgr.evalDerivedToBase(Reg, Adj.DerivedToBase.BasePath);

417 break;

420 break;

422

424 currBldrCtx->blockCount(), LC, true,

425 nullptr, nullptr, nullptr);

426 return State;

427 }

428 }

429

430

431

432

433

434

435

436

437

438 SVal InitVal = State->getSVal(Init, LC);

442 State = State->bindLoc(BaseReg.castAs(), InitVal, LC, false);

443

444

445

446 if (InitValWithAdjustments.isUnknown()) {

447

448

451 currBldrCtx->blockCount());

452 }

453 State =

454 State->bindLoc(Reg.castAs(), InitValWithAdjustments, LC, false);

455 } else {

456 State = State->bindLoc(BaseReg.castAs(), InitVal, LC, false);

457 }

458

459

460

461

462 if (Result->isGLValue()) {

463 State = State->BindExpr(Result, LC, Reg);

464 } else {

465 State = State->BindExpr(Result, LC, InitValWithAdjustments);

466 }

467

468

470

471 if (OutRegionWithAdjustments)

473 return State;

474}

475

478 const LocationContext *LCtx, unsigned Idx) {

479 auto Key = std::make_pair(E, LCtx->getStackFrame());

480

481 assert(!State->contains(Key) || Idx > 0);

482

483 return State->set(Key, Idx);

484}

485

486std::optional

489 const unsigned *V = State->get({E, LCtx->getStackFrame()});

490 return V ? std::make_optional(*V) : std::nullopt;

491}

492

496 auto Key = std::make_pair(E, LCtx->getStackFrame());

497

498 assert(E && State->contains(Key));

499 return State->remove(Key);

500}

501

505 unsigned Size) {

506 auto Key = std::make_pair(E, LCtx->getStackFrame());

507

508 assert(!State->contains(Key) && Size > 0);

509

510 return State->set(Key, Size);

511}

512

513std::optional

517 const unsigned *V =

518 State->get({E, LCtx->getStackFrame()});

519 return V ? std::make_optional(*V) : std::nullopt;

520}

521

523ExprEngine::removeIndexOfElementToConstruct(ProgramStateRef State,

526 auto Key = std::make_pair(E, LCtx->getStackFrame());

527

528 assert(E && State->contains(Key));

529 return State->remove(Key);

530}

531

532std::optional

535 assert(LCtx && "LocationContext shouldn't be null!");

536

537 const unsigned *V =

538 State->get(LCtx->getStackFrame());

539 return V ? std::make_optional(*V) : std::nullopt;

540}

541

544 assert(LCtx && "LocationContext shouldn't be null!");

545

547

548 return State->set(Key, Idx);

549}

550

552ExprEngine::removePendingArrayDestruction(ProgramStateRef State,

554 assert(LCtx && "LocationContext shouldn't be null!");

555

557

558 assert(LCtx && State->contains(Key));

559 return State->remove(Key);

560}

561

563ExprEngine::addObjectUnderConstruction(ProgramStateRef State,

566 ConstructedObjectKey Key(Item, LC->getStackFrame());

567

569

570 if (auto DS = dyn_cast_or_null(Item.getStmtOrNull())) {

571 if (auto VD = dyn_cast_or_null(DS->getSingleDecl()))

572 Init = VD->getInit();

573 }

574

575 if (auto LE = dyn_cast_or_null(Item.getStmtOrNull()))

576 Init = *(LE->capture_init_begin() + Item.getIndex());

577

580

581

582

583

584 if (const auto *AILE = dyn_cast_or_null(Init))

586

587

588

589

590

591

592

593 assert((!State->get(Key) ||

594 Key.getItem().getKind() ==

596 State->contains(

597 {dyn_cast_or_null(Init), LC})) &&

598 "The object is already marked as `UnderConstruction`, when it's not "

599 "supposed to!");

600 return State->set(Key, V);

601}

602

603std::optional

607 ConstructedObjectKey Key(Item, LC->getStackFrame());

608 const SVal *V = State->get(Key);

609 return V ? std::make_optional(*V) : std::nullopt;

610}

611

613ExprEngine::finishObjectConstruction(ProgramStateRef State,

616 ConstructedObjectKey Key(Item, LC->getStackFrame());

617 assert(State->contains(Key));

618 return State->remove(Key);

619}

620

624 ConstructedObjectKey Key({BTE, true}, LC);

625

626

627 return State->set(Key, UnknownVal());

628}

629

631ExprEngine::cleanupElidedDestructor(ProgramStateRef State,

632 const CXXBindTemporaryExpr *BTE,

633 const LocationContext *LC) {

634 ConstructedObjectKey Key({BTE, true}, LC);

635 assert(State->contains(Key));

636 return State->remove(Key);

637}

638

639bool ExprEngine::isDestructorElided(ProgramStateRef State,

640 const CXXBindTemporaryExpr *BTE,

641 const LocationContext *LC) {

642 ConstructedObjectKey Key({BTE, true}, LC);

643 return State->contains(Key);

644}

645

646bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,

647 const LocationContext *FromLC,

648 const LocationContext *ToLC) {

649 const LocationContext *LC = FromLC;

650 while (LC != ToLC) {

651 assert(LC && "ToLC must be a parent of FromLC!");

652 for (auto I : State->get())

653 if (I.first.getLocationContext() == LC)

654 return false;

655

657 }

658 return true;

659}

660

661

662

663

664

665

666

667

669 SVal cond, bool assumption) {

671}

672

681 Explicits, Regions,

683}

684

685static void

688 unsigned int Space = 0, bool IsDot = false) {

691

692 ++Space;

693 bool HasItem = false;

694

695

696 const ConstructedObjectKey *LastKey = nullptr;

697 for (const auto &I : State->get()) {

698 const ConstructedObjectKey &Key = I.first;

699 if (Key.getLocationContext() != LCtx)

700 continue;

701

702 if (!HasItem) {

703 Out << '[' << NL;

704 HasItem = true;

705 }

706

707 LastKey = &Key;

708 }

709

710 for (const auto &I : State->get()) {

711 const ConstructedObjectKey &Key = I.first;

713 if (Key.getLocationContext() != LCtx)

714 continue;

715

716 Indent(Out, Space, IsDot) << "{ ";

717 Key.printJson(Out, nullptr, PP);

718 Out << ", \"value\": \"" << Value << "\" }";

719

720 if (&Key != LastKey)

721 Out << ',';

722 Out << NL;

723 }

724

725 if (HasItem)

726 Indent(Out, --Space, IsDot) << ']';

727 else {

728 Out << "null ";

729 }

730}

731

734 const LocationContext *LCtx, unsigned int Space = 0, bool IsDot = false) {

735 using KeyT = std::pair<const Expr *, const LocationContext *>;

736

739

740 ++Space;

741 bool HasItem = false;

742

743

744 KeyT LastKey;

745 for (const auto &I : State->get()) {

746 const KeyT &Key = I.first;

747 if (Key.second != LCtx)

748 continue;

749

750 if (!HasItem) {

751 Out << '[' << NL;

752 HasItem = true;

753 }

754

755 LastKey = Key;

756 }

757

758 for (const auto &I : State->get()) {

759 const KeyT &Key = I.first;

760 unsigned Value = I.second;

761 if (Key.second != LCtx)

762 continue;

763

764 Indent(Out, Space, IsDot) << "{ ";

765

766

767 const Expr *E = Key.first;

768 Out << "\"stmt_id\": " << E->getID(Context);

769

770

771 Out << ", \"kind\": null";

772

773

774 Out << ", \"pretty\": ";

778 Out << "'\"";

779

780 Out << ", \"value\": \"Current index: " << Value - 1 << "\" }";

781

782 if (Key != LastKey)

783 Out << ',';

784 Out << NL;

785 }

786

787 if (HasItem)

788 Indent(Out, --Space, IsDot) << ']';

789 else {

790 Out << "null ";

791 }

792}

793

795 const char *NL,

797 unsigned int Space = 0,

798 bool IsDot = false) {

799 using KeyT = std::pair<const CXXConstructExpr *, const LocationContext *>;

800

803

804 ++Space;

805 bool HasItem = false;

806

807

808 KeyT LastKey;

809 for (const auto &I : State->get()) {

810 const KeyT &Key = I.first;

811 if (Key.second != LCtx)

812 continue;

813

814 if (!HasItem) {

815 Out << '[' << NL;

816 HasItem = true;

817 }

818

819 LastKey = Key;

820 }

821

822 for (const auto &I : State->get()) {

823 const KeyT &Key = I.first;

824 unsigned Value = I.second;

825 if (Key.second != LCtx)

826 continue;

827

828 Indent(Out, Space, IsDot) << "{ ";

829

831 Out << "\"stmt_id\": " << E->getID(Context);

832

833 Out << ", \"kind\": null";

834 Out << ", \"pretty\": ";

838 Out << "'\"";

839

840 Out << ", \"value\": \"Flattened size: " << Value << "\"}";

841

842 if (Key != LastKey)

843 Out << ',';

844 Out << NL;

845 }

846

847 if (HasItem)

848 Indent(Out, --Space, IsDot) << ']';

849 else {

850 Out << "null ";

851 }

852}

853

854static void

857 unsigned int Space = 0, bool IsDot = false) {

859

860 ++Space;

861 bool HasItem = false;

862

863

864 KeyT LastKey = nullptr;

865 for (const auto &I : State->get()) {

866 const KeyT &Key = I.first;

867 if (Key != LCtx)

868 continue;

869

870 if (!HasItem) {

871 Out << '[' << NL;

872 HasItem = true;

873 }

874

875 LastKey = Key;

876 }

877

878 for (const auto &I : State->get()) {

879 const KeyT &Key = I.first;

880 if (Key != LCtx)

881 continue;

882

883 Indent(Out, Space, IsDot) << "{ ";

884

885 Out << "\"stmt_id\": null";

886 Out << ", \"kind\": null";

887 Out << ", \"pretty\": \"Current index: \"";

888 Out << ", \"value\": \"" << I.second << "\" }";

889

890 if (Key != LastKey)

891 Out << ',';

892 Out << NL;

893 }

894

895 if (HasItem)

896 Indent(Out, --Space, IsDot) << ']';

897 else {

898 Out << "null ";

899 }

900}

901

902

903

904

905

906

907

908

909

910template <typename Trait, typename Printer, typename... Args>

913 const char *NL, unsigned int Space, bool IsDot,

914 const char *jsonPropertyName, Printer printer, Args &&...args) {

915

916 using RequiredType =

919

920

921

922 static_assert(std::is_function_v<std::remove_pointer_t>,

923 "Printer is not a function!");

924 static_assert(std::is_convertible_v<Printer, RequiredType>,

925 "Printer doesn't have the required type!");

926

927 if (LCtx && !State->get().isEmpty()) {

928 Indent(Out, Space, IsDot) << '\"' << jsonPropertyName << "\": ";

929 ++Space;

930 Out << '[' << NL;

932 printer(Out, State, NL, LC, Space, IsDot, std::forward(args)...);

933 });

934

935 --Space;

936 Indent(Out, Space, IsDot) << "]," << NL;

937 }

938}

939

942 unsigned int Space, bool IsDot) const {

943

945 Out, State, LCtx, NL, Space, IsDot, "constructing_objects",

948 Out, State, LCtx, NL, Space, IsDot, "index_of_element",

951 Out, State, LCtx, NL, Space, IsDot, "pending_init_loops",

954 Out, State, LCtx, NL, Space, IsDot, "pending_destructors",

956

958 IsDot);

959}

960

966

969 currStmtIdx = StmtIdx;

970 currBldrCtx = Ctx;

971

977 return;

980 return;

983 Pred);

984 return;

991 return;

994 return;

999 return;

1000 }

1001}

1002

1004 const Stmt *S,

1007

1009 return false;

1010

1011

1013 return true;

1014

1015

1017 return true;

1018

1019

1021 return true;

1022

1023

1024

1027}

1028

1030 const Stmt *ReferenceStmt,

1032 const Stmt *DiagnosticStmt,

1034 llvm::TimeTraceScope TimeScope("ExprEngine::removeDead");

1036 ReferenceStmt == nullptr || isa(ReferenceStmt))

1037 && "PostStmt is not generally supported by the SymbolReaper yet");

1038 assert(LC && "Must pass the current (or expiring) LocationContext");

1039

1040 if (!DiagnosticStmt) {

1041 DiagnosticStmt = ReferenceStmt;

1042 assert(DiagnosticStmt && "Required for clearing a LocationContext");

1043 }

1044

1045 NumRemoveDeadBindings++;

1047

1048

1049

1050

1051 if (!ReferenceStmt) {

1053 "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");

1055 }

1056

1059

1060 for (auto I : CleanedState->get()) {

1061 if (SymbolRef Sym = I.second.getAsSymbol())

1063 if (const MemRegion *MR = I.second.getAsRegion())

1065 }

1066

1068

1069

1070

1071

1072 CleanedState = StateMgr.removeDeadBindingsFromEnvironmentAndStore(

1073 CleanedState, SFC, SymReaper);

1074

1075

1076

1077

1080 DiagnosticStmt, *this, K);

1081

1082

1083

1084

1086

1087

1088

1089

1091 for (const auto I : CheckedSet) {

1093

1094

1095 CheckerState =

1097

1098 assert(StateMgr.haveEqualEnvironments(CheckerState, Pred->getState()) &&

1099 "Checkers are not allowed to modify the Environment as a part of "

1100 "checkDeadSymbols processing.");

1101 assert(StateMgr.haveEqualStores(CheckerState, Pred->getState()) &&

1102 "Checkers are not allowed to modify the Store as a part of "

1103 "checkDeadSymbols processing.");

1104

1105

1106

1108 StateMgr.getPersistentStateWithGDM(CleanedState, CheckerState);

1110 }

1111}

1112

1115 return &cleanupTag;

1116}

1117

1119

1120 G.reclaimRecentlyAllocatedNodes();

1121

1124 "Error evaluating statement");

1125

1126

1130 removeDead(Pred, CleanedStates, currStmt,

1132 } else

1133 CleanedStates.Add(Pred);

1134

1135

1137 for (const auto I : CleanedStates) {

1139

1140 Visit(currStmt, I, DstI);

1142 }

1143

1144

1145 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);

1146}

1147

1151 "Error evaluating end of the loop");

1153 Dst.Add(Pred);

1154 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);

1156

1157 if(AMgr.options.ShouldUnrollLoops)

1159

1162

1163 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);

1164}

1165

1171

1174 "Error evaluating initializer");

1175

1176

1179

1181 SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame));

1182

1184 SVal FieldLoc;

1185

1186

1188

1189

1191

1192

1193 State = finishObjectConstruction(State, BMI, LC);

1194 NodeBuilder Bldr(Pred, Tmp, *currBldrCtx);

1195 PostStore PS(Init, LC, nullptr, nullptr);

1197 } else {

1202 } else {

1204 FieldLoc = State->getLValue(BMI->getMember(), thisVal);

1205 }

1206

1207 SVal InitVal;

1208 if (Init->getType()->isArrayType()) {

1209

1210

1212 while ((ASE = dyn_cast(Init)))

1214

1215 InitVal = State->getSVal(Init, stackFrame);

1216

1217

1220 InitVal =

1222 Field->getType(), currBldrCtx->blockCount());

1223 }

1224 } else {

1225 InitVal = State->getSVal(BMI->getInit(), stackFrame);

1226 }

1227

1229 evalBind(Tmp, Init, Pred, FieldLoc, InitVal, true, &PP);

1230 }

1232

1233

1234

1237 SVal InitVal = State->getSVal(Init, stackFrame);

1238 evalBind(Tmp, Init, Pred, BaseLoc, InitVal, true);

1239 } else {

1242

1243 }

1244

1245

1246

1249 NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);

1250 for (const auto I : Tmp) {

1253 }

1254

1255

1256 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);

1257}

1258

1259std::pair<ProgramStateRef, uint64_t>

1260ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,

1264 SVal *ElementCountVal) {

1265 assert(Region != nullptr && "Not-null region expected");

1266

1268 while (const auto *NTy = dyn_cast(Ty))

1269 Ty = NTy->getElementType().getDesugaredType(getContext());

1270

1272

1273 if (ElementCountVal)

1274 *ElementCountVal = ElementCount;

1275

1276

1277 unsigned Idx = 0;

1279 Idx = *OptionalIdx;

1280 } else {

1281

1282 if (!ElementCount.isConstant())

1283 return {State, 0};

1284

1285 Idx = ElementCount.getAsInteger()->getLimitedValue();

1286 }

1287

1288 if (Idx == 0)

1289 return {State, 0};

1290

1291 --Idx;

1292

1293 return {setPendingArrayDestruction(State, LCtx, Idx), Idx};

1294}

1295

1302 break;

1305 break;

1308 break;

1311 break;

1314 break;

1315 default:

1316 llvm_unreachable("Unexpected dtor kind.");

1317 }

1318

1319

1320 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);

1321}

1322

1328

1329

1330

1331 if (Opts.MayInlineCXXAllocator)

1333 else {

1334 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);

1336 PostImplicitCall PP(NE->getOperatorNew(), NE->getBeginLoc(), LCtx,

1339 }

1340 Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);

1341}

1342

1349

1352

1353 SVal dest = state->getLValue(varDecl, LCtx);

1355

1357 const MemRegion *ValueRegion = state->getSVal(Region).getAsRegion();

1358 if (!ValueRegion) {

1359

1360

1361

1362

1363 return;

1364 }

1367 }

1368

1369 unsigned Idx = 0;

1371 SVal ElementCount;

1372 std::tie(state, Idx) = prepareStateForArrayDestruction(

1373 state, Region, varType, LCtx, &ElementCount);

1374

1375 if (ElementCount.isConstant()) {

1376 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();

1377 assert(ArrayLength &&

1378 "An automatic dtor for a 0 length array shouldn't be triggered!");

1379

1380

1381 if (!ArrayLength) {

1383 "ExprEngine", "Skipping automatic 0 length array destruction, "

1384 "which shouldn't be in the CFG.");

1387 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);

1389 return;

1390 }

1391 }

1392 }

1393

1395 Region = makeElementRegion(state, loc::MemRegionVal(Region), varType,

1397 .getAsRegion();

1398

1400

1402 "Prepare for object destruction");

1404 &PT);

1406

1407 if (!Pred)

1408 return;

1410

1412 false, Pred, Dst, CallOpts);

1413}

1414

1423 SVal ArgVal = State->getSVal(Arg, LCtx);

1424

1425

1426

1427 if (State->isNull(ArgVal).isConstrainedTrue()) {

1431

1433 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);

1435 return;

1436 }

1437

1438 auto getDtorDecl = [](const QualType &DTy) {

1441 };

1442

1443 unsigned Idx = 0;

1446

1449

1450 while (const auto *AT = getContext().getAsArrayType(DTy))

1451 DTy = AT->getElementType();

1452

1453 if (ArgR) {

1454 SVal ElementCount;

1455 std::tie(State, Idx) = prepareStateForArrayDestruction(

1456 State, ArgR, DTy, LCtx, &ElementCount);

1457

1458

1459

1460 if (ElementCount.isConstant() &&

1461 ElementCount.getAsInteger()->getLimitedValue() == 0) {

1462

1464 "ExprEngine", "Skipping 0 length array delete destruction");

1467 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);

1469 return;

1470 }

1471

1472 ArgR = State->getLValue(DTy, svalBuilder.makeArrayIndex(Idx), ArgVal)

1473 .getAsRegion();

1474 }

1475 }

1476

1479 "Prepare for object destruction");

1483

1484 if (!Pred)

1485 return;

1487

1488 VisitCXXDestructor(DTy, ArgR, DE, false, Pred, Dst, CallOpts);

1489}

1490

1494

1498 SVal ThisVal = Pred->getState()->getSVal(ThisPtr);

1499

1500

1504 Base->isVirtual());

1505

1508 true, Pred, Dst, CallOpts);

1509}

1510

1518

1520 Loc ThisStorageLoc =

1522 Loc ThisLoc = State->getSVal(ThisStorageLoc).castAs<Loc>();

1523 SVal FieldVal = State->getLValue(Member, ThisLoc);

1524

1525 unsigned Idx = 0;

1527 SVal ElementCount;

1528 std::tie(State, Idx) = prepareStateForArrayDestruction(

1529 State, FieldVal.getAsRegion(), T, LCtx, &ElementCount);

1530

1531 if (ElementCount.isConstant()) {

1532 uint64_t ArrayLength = ElementCount.getAsInteger()->getLimitedValue();

1533 assert(ArrayLength &&

1534 "A member dtor for a 0 length array shouldn't be triggered!");

1535

1536

1537 if (!ArrayLength) {

1539 "ExprEngine", "Skipping member 0 length array destruction, which "

1540 "shouldn't be in the CFG.");

1543 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);

1545 return;

1546 }

1547 }

1548 }

1549

1551 FieldVal =

1552 makeElementRegion(State, FieldVal, T, CallOpts.IsArrayCtorOrDtor, Idx);

1553

1555

1557 "Prepare for object destruction");

1559 &PT);

1561

1562 if (!Pred)

1563 return;

1565

1567 false, Pred, Dst, CallOpts);

1568}

1569

1577

1580

1581

1582

1585 MR = V->getAsRegion();

1586 }

1587

1588

1589

1590 if (isDestructorElided(State, BTE, LC)) {

1591 State = cleanupElidedDestructor(State, BTE, LC);

1592 NodeBuilder Bldr(Pred, Dst, *currBldrCtx);

1597 return;

1598 }

1599

1601 StmtNodeBuilder StmtBldr(Pred, CleanDtorState, *currBldrCtx);

1603

1605

1606

1607 assert(CleanDtorState.size() <= 1);

1609 CleanDtorState.empty() ? Pred : *CleanDtorState.begin();

1610

1613 if (!MR) {

1614

1615

1616

1617

1618

1619

1620

1621

1622

1623

1624

1625

1626

1627

1628

1629

1630

1632 T = AT->getElementType();

1633

1634

1635

1636 }

1637 } else {

1638

1639

1640

1641 }

1643 false, CleanPred, Dst, CallOpts);

1644}

1645

1652 BranchNodeBuilder TempDtorBuilder(Pred, Dst, BldCtx, DstT, DstF);

1656 TempDtorBuilder.generateNode(State, true, Pred);

1657 } else {

1658 TempDtorBuilder.generateNode(State, false, Pred);

1659 }

1660}

1661

1665

1666

1667

1669

1670

1671 Dst = PreVisit;

1672 return;

1673 }

1679

1680

1681

1682

1683 State = addObjectUnderConstruction(State, BTE, LC, UnknownVal());

1684 }

1686 }

1687}

1688

1693 class CollectReachableSymbolsCallback final : public SymbolVisitor {

1695

1696 public:

1697 explicit CollectReachableSymbolsCallback(InvalidatedSymbols &Symbols)

1698 : Symbols(Symbols) {}

1699

1701

1702 bool VisitSymbol(SymbolRef Sym) override {

1703 Symbols.insert(Sym);

1704 return true;

1705 }

1706 };

1708 CollectReachableSymbolsCallback CallBack(Symbols);

1709 for (SVal V : Vs)

1710 State->scanReachableSymbols(V, CallBack);

1711

1713 State, CallBack.getSymbols(), Call, K, nullptr);

1714}

1715

1719 S->getBeginLoc(), "Error evaluating statement");

1722

1724

1726

1727 case Stmt::CXXDependentScopeMemberExprClass:

1728 case Stmt::CXXTryStmtClass:

1729 case Stmt::CXXTypeidExprClass:

1730 case Stmt::CXXUuidofExprClass:

1731 case Stmt::CXXFoldExprClass:

1732 case Stmt::MSPropertyRefExprClass:

1733 case Stmt::MSPropertySubscriptExprClass:

1734 case Stmt::CXXUnresolvedConstructExprClass:

1735 case Stmt::DependentScopeDeclRefExprClass:

1736 case Stmt::ArrayTypeTraitExprClass:

1737 case Stmt::ExpressionTraitExprClass:

1738 case Stmt::UnresolvedLookupExprClass:

1739 case Stmt::UnresolvedMemberExprClass:

1740 case Stmt::RecoveryExprClass:

1741 case Stmt::CXXNoexceptExprClass:

1742 case Stmt::PackExpansionExprClass:

1743 case Stmt::PackIndexingExprClass:

1744 case Stmt::SubstNonTypeTemplateParmPackExprClass:

1745 case Stmt::FunctionParmPackExprClass:

1746 case Stmt::CoroutineBodyStmtClass:

1747 case Stmt::CoawaitExprClass:

1748 case Stmt::DependentCoawaitExprClass:

1749 case Stmt::CoreturnStmtClass:

1750 case Stmt::CoyieldExprClass:

1751 case Stmt::SEHTryStmtClass:

1752 case Stmt::SEHExceptStmtClass:

1753 case Stmt::SEHLeaveStmtClass:

1754 case Stmt::SEHFinallyStmtClass:

1755 case Stmt::OMPCanonicalLoopClass:

1756 case Stmt::OMPParallelDirectiveClass:

1757 case Stmt::OMPSimdDirectiveClass:

1758 case Stmt::OMPForDirectiveClass:

1759 case Stmt::OMPForSimdDirectiveClass:

1760 case Stmt::OMPSectionsDirectiveClass:

1761 case Stmt::OMPSectionDirectiveClass:

1762 case Stmt::OMPScopeDirectiveClass:

1763 case Stmt::OMPSingleDirectiveClass:

1764 case Stmt::OMPMasterDirectiveClass:

1765 case Stmt::OMPCriticalDirectiveClass:

1766 case Stmt::OMPParallelForDirectiveClass:

1767 case Stmt::OMPParallelForSimdDirectiveClass:

1768 case Stmt::OMPParallelSectionsDirectiveClass:

1769 case Stmt::OMPParallelMasterDirectiveClass:

1770 case Stmt::OMPParallelMaskedDirectiveClass:

1771 case Stmt::OMPTaskDirectiveClass:

1772 case Stmt::OMPTaskyieldDirectiveClass:

1773 case Stmt::OMPBarrierDirectiveClass:

1774 case Stmt::OMPTaskwaitDirectiveClass:

1775 case Stmt::OMPErrorDirectiveClass:

1776 case Stmt::OMPTaskgroupDirectiveClass:

1777 case Stmt::OMPFlushDirectiveClass:

1778 case Stmt::OMPDepobjDirectiveClass:

1779 case Stmt::OMPScanDirectiveClass:

1780 case Stmt::OMPOrderedDirectiveClass:

1781 case Stmt::OMPAtomicDirectiveClass:

1782 case Stmt::OMPAssumeDirectiveClass:

1783 case Stmt::OMPTargetDirectiveClass:

1784 case Stmt::OMPTargetDataDirectiveClass:

1785 case Stmt::OMPTargetEnterDataDirectiveClass:

1786 case Stmt::OMPTargetExitDataDirectiveClass:

1787 case Stmt::OMPTargetParallelDirectiveClass:

1788 case Stmt::OMPTargetParallelForDirectiveClass:

1789 case Stmt::OMPTargetUpdateDirectiveClass:

1790 case Stmt::OMPTeamsDirectiveClass:

1791 case Stmt::OMPCancellationPointDirectiveClass:

1792 case Stmt::OMPCancelDirectiveClass:

1793 case Stmt::OMPTaskLoopDirectiveClass:

1794 case Stmt::OMPTaskLoopSimdDirectiveClass:

1795 case Stmt::OMPMasterTaskLoopDirectiveClass:

1796 case Stmt::OMPMaskedTaskLoopDirectiveClass:

1797 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:

1798 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:

1799 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:

1800 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:

1801 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:

1802 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:

1803 case Stmt::OMPDistributeDirectiveClass:

1804 case Stmt::OMPDistributeParallelForDirectiveClass:

1805 case Stmt::OMPDistributeParallelForSimdDirectiveClass:

1806 case Stmt::OMPDistributeSimdDirectiveClass:

1807 case Stmt::OMPTargetParallelForSimdDirectiveClass:

1808 case Stmt::OMPTargetSimdDirectiveClass:

1809 case Stmt::OMPTeamsDistributeDirectiveClass:

1810 case Stmt::OMPTeamsDistributeSimdDirectiveClass:

1811 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:

1812 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:

1813 case Stmt::OMPTargetTeamsDirectiveClass:

1814 case Stmt::OMPTargetTeamsDistributeDirectiveClass:

1815 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:

1816 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:

1817 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:

1818 case Stmt::OMPReverseDirectiveClass:

1819 case Stmt::OMPStripeDirectiveClass:

1820 case Stmt::OMPTileDirectiveClass:

1821 case Stmt::OMPInterchangeDirectiveClass:

1822 case Stmt::OMPFuseDirectiveClass:

1823 case Stmt::OMPInteropDirectiveClass:

1824 case Stmt::OMPDispatchDirectiveClass:

1825 case Stmt::OMPMaskedDirectiveClass:

1826 case Stmt::OMPGenericLoopDirectiveClass:

1827 case Stmt::OMPTeamsGenericLoopDirectiveClass:

1828 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:

1829 case Stmt::OMPParallelGenericLoopDirectiveClass:

1830 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:

1831 case Stmt::CapturedStmtClass:

1832 case Stmt::SYCLKernelCallStmtClass:

1833 case Stmt::OpenACCComputeConstructClass:

1834 case Stmt::OpenACCLoopConstructClass:

1835 case Stmt::OpenACCCombinedConstructClass:

1836 case Stmt::OpenACCDataConstructClass:

1837 case Stmt::OpenACCEnterDataConstructClass:

1838 case Stmt::OpenACCExitDataConstructClass:

1839 case Stmt::OpenACCHostDataConstructClass:

1840 case Stmt::OpenACCWaitConstructClass:

1841 case Stmt::OpenACCCacheConstructClass:

1842 case Stmt::OpenACCInitConstructClass:

1843 case Stmt::OpenACCShutdownConstructClass:

1844 case Stmt::OpenACCSetConstructClass:

1845 case Stmt::OpenACCUpdateConstructClass:

1846 case Stmt::OpenACCAtomicConstructClass:

1847 case Stmt::OMPUnrollDirectiveClass:

1848 case Stmt::OMPMetaDirectiveClass:

1849 case Stmt::HLSLOutArgExprClass: {

1851 Engine.addAbortedBlock(node, currBldrCtx->getBlock());

1852 break;

1853 }

1854

1855 case Stmt::ParenExprClass:

1856 llvm_unreachable("ParenExprs already handled.");

1857 case Stmt::GenericSelectionExprClass:

1858 llvm_unreachable("GenericSelectionExprs already handled.");

1859

1860

1861 case Stmt::BreakStmtClass:

1862 case Stmt::CaseStmtClass:

1863 case Stmt::CompoundStmtClass:

1864 case Stmt::ContinueStmtClass:

1865 case Stmt::CXXForRangeStmtClass:

1866 case Stmt::DefaultStmtClass:

1867 case Stmt::DoStmtClass:

1868 case Stmt::ForStmtClass:

1869 case Stmt::GotoStmtClass:

1870 case Stmt::IfStmtClass:

1871 case Stmt::IndirectGotoStmtClass:

1872 case Stmt::LabelStmtClass:

1874 case Stmt::NullStmtClass:

1875 case Stmt::SwitchStmtClass:

1876 case Stmt::WhileStmtClass:

1877 case Stmt::DeferStmtClass:

1878 case Expr::MSDependentExistsStmtClass:

1879 llvm_unreachable("Stmt should not be in analyzer evaluation loop");

1880 case Stmt::ImplicitValueInitExprClass:

1881

1882

1883

1884 llvm_unreachable("Should be pruned from CFG");

1885

1886 case Stmt::ObjCSubscriptRefExprClass:

1887 case Stmt::ObjCPropertyRefExprClass:

1888 llvm_unreachable("These are handled by PseudoObjectExpr");

1889

1890 case Stmt::GNUNullExprClass: {

1891

1893 state = state->BindExpr(

1895 svalBuilder.makeIntValWithWidth(getContext().VoidPtrTy, 0));

1897 break;

1898 }

1899

1900 case Stmt::ObjCAtSynchronizedStmtClass:

1904 break;

1905

1906 case Expr::ConstantExprClass:

1907 case Stmt::ExprWithCleanupsClass:

1908

1909 break;

1910

1911 case Stmt::CXXBindTemporaryExprClass: {

1919 break;

1920 }

1921

1922 case Stmt::ArrayInitLoopExprClass:

1926 break;

1927

1928 case Stmt::DesignatedInitExprClass:

1929 case Stmt::DesignatedInitUpdateExprClass:

1930 case Stmt::ArrayInitIndexExprClass:

1931 case Stmt::ExtVectorElementExprClass:

1932 case Stmt::ImaginaryLiteralClass:

1933 case Stmt::ObjCAtCatchStmtClass:

1934 case Stmt::ObjCAtFinallyStmtClass:

1935 case Stmt::ObjCAtTryStmtClass:

1936 case Stmt::ObjCAutoreleasePoolStmtClass:

1937 case Stmt::ObjCEncodeExprClass:

1938 case Stmt::ObjCIsaExprClass:

1939 case Stmt::ObjCProtocolExprClass:

1940 case Stmt::ObjCSelectorExprClass:

1941 case Stmt::ParenListExprClass:

1942 case Stmt::ShuffleVectorExprClass:

1943 case Stmt::ConvertVectorExprClass:

1944 case Stmt::VAArgExprClass:

1945 case Stmt::CUDAKernelCallExprClass:

1946 case Stmt::OpaqueValueExprClass:

1947 case Stmt::AsTypeExprClass:

1948 case Stmt::ConceptSpecializationExprClass:

1949 case Stmt::CXXRewrittenBinaryOperatorClass:

1950 case Stmt::RequiresExprClass:

1951 case Stmt::EmbedExprClass:

1952

1953

1954

1955

1956 case Stmt::PredefinedExprClass:

1957 case Stmt::AddrLabelExprClass:

1958 case Stmt::IntegerLiteralClass:

1959 case Stmt::FixedPointLiteralClass:

1960 case Stmt::CharacterLiteralClass:

1961 case Stmt::CXXScalarValueInitExprClass:

1962 case Stmt::CXXBoolLiteralExprClass:

1963 case Stmt::ObjCBoolLiteralExprClass:

1964 case Stmt::ObjCAvailabilityCheckExprClass:

1965 case Stmt::FloatingLiteralClass:

1966 case Stmt::NoInitExprClass:

1967 case Stmt::SizeOfPackExprClass:

1968 case Stmt::StringLiteralClass:

1969 case Stmt::SourceLocExprClass:

1970 case Stmt::ObjCStringLiteralClass:

1971 case Stmt::CXXPseudoDestructorExprClass:

1972 case Stmt::SubstNonTypeTemplateParmExprClass:

1973 case Stmt::CXXNullPtrLiteralExprClass:

1974 case Stmt::ArraySectionExprClass:

1975 case Stmt::OMPArrayShapingExprClass:

1976 case Stmt::OMPIteratorExprClass:

1977 case Stmt::SYCLUniqueStableNameExprClass:

1978 case Stmt::OpenACCAsteriskSizeExprClass:

1979 case Stmt::TypeTraitExprClass: {

1985 break;

1986 }

1987

1988 case Stmt::AttributedStmtClass: {

1992 break;

1993 }

1994

1995 case Stmt::CXXDefaultArgExprClass:

1996 case Stmt::CXXDefaultInitExprClass: {

2000

2003

2004 const Expr *ArgE;

2005 if (const auto *DefE = dyn_cast(S))

2006 ArgE = DefE->getExpr();

2007 else if (const auto *DefE = dyn_cast(S))

2008 ArgE = DefE->getExpr();

2009 else

2010 llvm_unreachable("unknown constant wrapper kind");

2011

2012 bool IsTemporary = false;

2013 if (const auto *MTE = dyn_cast(ArgE)) {

2014 ArgE = MTE->getSubExpr();

2015 IsTemporary = true;

2016 }

2017

2018 std::optional ConstantVal = svalBuilder.getConstantVal(ArgE);

2019 if (!ConstantVal)

2021

2023 for (const auto I : PreVisit) {

2025 State = State->BindExpr(S, LCtx, *ConstantVal);

2026 if (IsTemporary)

2027 State = createTemporaryRegionIfNeeded(State, LCtx,

2031 }

2032

2035 break;

2036 }

2037

2038

2039 case Stmt::CXXStdInitializerListExprClass:

2040 case Expr::ObjCArrayLiteralClass:

2041 case Expr::ObjCDictionaryLiteralClass:

2042 case Expr::ObjCBoxedExprClass: {

2044

2047

2050

2052 QualType resultType = Ex->getType();

2053

2054 for (const auto N : preVisit) {

2056 SVal result = svalBuilder.conjureSymbolVal(

2057 nullptr, getCFGElementRef(), LCtx, resultType,

2058 currBldrCtx->blockCount());

2059 ProgramStateRef State = N->getState()->BindExpr(Ex, LCtx, result);

2060

2061

2062

2066 for (auto Child : Ex->children()) {

2067 assert(Child);

2068 SVal Val = State->getSVal(Child, LCtx);

2070 }

2071

2073 }

2074

2077 break;

2078 }

2079

2080 case Stmt::ArraySubscriptExprClass:

2084 break;

2085

2086 case Stmt::MatrixSubscriptExprClass:

2087 llvm_unreachable("Support for MatrixSubscriptExpr is not implemented.");

2088 break;

2089

2090 case Stmt::GCCAsmStmtClass: {

2099 break;

2100 }

2101

2102 case Stmt::MSAsmStmtClass:

2106 break;

2107

2108 case Stmt::BlockExprClass:

2112 break;

2113

2114 case Stmt::LambdaExprClass:

2115 if (AMgr.options.ShouldInlineLambdas) {

2119 } else {

2121 Engine.addAbortedBlock(node, currBldrCtx->getBlock());

2122 }

2123 break;

2124

2125 case Stmt::BinaryOperatorClass: {

2127 if (B->isLogicalOp()) {

2131 break;

2132 }

2133 else if (B->getOpcode() == BO_Comma) {

2137 state->getSVal(B->getRHS(),

2139 break;

2140 }

2141

2143

2144 if (AMgr.options.ShouldEagerlyAssume &&

2145 (B->isRelationalOp() || B->isEqualityOp())) {

2149 }

2150 else

2152

2154 break;

2155 }

2156

2157 case Stmt::CXXOperatorCallExprClass: {

2159

2160

2161

2162 const Decl *Callee = OCE->getCalleeDecl();

2163 if (const auto *MD = dyn_cast_or_null(Callee)) {

2164 if (MD->isImplicitObjectMemberFunction()) {

2168 createTemporaryRegionIfNeeded(State, LCtx, OCE->getArg(0));

2169 if (NewState != State) {

2170 Pred = Bldr.generateNode(OCE, Pred, NewState, nullptr,

2172

2173 if (!Pred)

2174 break;

2175 }

2176 }

2177 }

2178 [[fallthrough]];

2179 }

2180

2181 case Stmt::CallExprClass:

2182 case Stmt::CXXMemberCallExprClass:

2183 case Stmt::UserDefinedLiteralClass:

2187 break;

2188

2189 case Stmt::CXXCatchStmtClass:

2193 break;

2194

2195 case Stmt::CXXTemporaryObjectExprClass:

2196 case Stmt::CXXConstructExprClass:

2200 break;

2201

2202 case Stmt::CXXInheritedCtorInitExprClass:

2205 Dst);

2207 break;

2208

2209 case Stmt::CXXNewExprClass: {

2211

2214

2216 for (const auto i : PreVisit)

2218

2221 break;

2222 }

2223

2224 case Stmt::CXXDeleteExprClass: {

2231

2232 for (const auto i : PostVisit)

2234

2236 break;

2237 }

2238

2239

2240

2241 case Stmt::ChooseExprClass: {

2246 break;

2247 }

2248

2249 case Stmt::CompoundAssignOperatorClass:

2253 break;

2254

2255 case Stmt::CompoundLiteralExprClass:

2259 break;

2260

2261 case Stmt::BinaryConditionalOperatorClass:

2262 case Stmt::ConditionalOperatorClass: {

2267 break;

2268 }

2269

2270 case Stmt::CXXThisExprClass:

2274 break;

2275

2276 case Stmt::DeclRefExprClass: {

2281 break;

2282 }

2283

2284 case Stmt::DeclStmtClass:

2288 break;

2289

2290 case Stmt::ImplicitCastExprClass:

2291 case Stmt::CStyleCastExprClass:

2292 case Stmt::CXXStaticCastExprClass:

2293 case Stmt::CXXDynamicCastExprClass:

2294 case Stmt::CXXReinterpretCastExprClass:

2295 case Stmt::CXXConstCastExprClass:

2296 case Stmt::CXXFunctionalCastExprClass:

2297 case Stmt::BuiltinBitCastExprClass:

2298 case Stmt::ObjCBridgedCastExprClass:

2299 case Stmt::CXXAddrspaceCastExprClass: {

2303 VisitCast(C, C->getSubExpr(), Pred, dstExpr);

2304

2305

2308 break;

2309 }

2310

2311 case Expr::MaterializeTemporaryExprClass: {

2317 for (const auto i : dstPrevisit)

2321 break;

2322 }

2323

2324 case Stmt::InitListExprClass: {

2329 break;

2330 }

2331

2332 case Expr::CXXParenListInitExprClass: {

2336 Dst);

2338 break;

2339 }

2340

2341 case Stmt::MemberExprClass:

2345 break;

2346

2347 case Stmt::AtomicExprClass:

2351 break;

2352

2353 case Stmt::ObjCIvarRefExprClass:

2357 break;

2358

2359 case Stmt::ObjCForCollectionStmtClass:

2363 break;

2364

2365 case Stmt::ObjCMessageExprClass:

2369 break;

2370

2371 case Stmt::ObjCAtThrowStmtClass:

2372 case Stmt::CXXThrowExprClass:

2373

2374

2376 break;

2377

2378 case Stmt::ReturnStmtClass:

2382 break;

2383

2384 case Stmt::OffsetOfExprClass: {

2388

2390 for (const auto Node : PreVisit)

2392

2395 break;

2396 }

2397

2398 case Stmt::UnaryExprOrTypeTraitExprClass:

2401 Pred, Dst);

2403 break;

2404

2405 case Stmt::StmtExprClass: {

2407

2408 if (SE->getSubStmt()->body_empty()) {

2409

2410 assert(SE->getType() == getContext().VoidTy

2411 && "Empty statement expression must have void type.");

2412 break;

2413 }

2414

2415 if (const auto *LastExpr =

2416 dyn_cast(*SE->getSubStmt()->body_rbegin())) {

2420 state->getSVal(LastExpr,

2422 }

2423 break;

2424 }

2425

2426 case Stmt::UnaryOperatorClass: {

2429 if (AMgr.options.ShouldEagerlyAssume && (U->getOpcode() == UO_LNot)) {

2433 }

2434 else

2437 break;

2438 }

2439

2440 case Stmt::PseudoObjectExprClass: {

2444 if (const Expr *Result = PE->getResultExpr()) {

2448 }

2449 else

2453

2455 break;

2456 }

2457

2458 case Expr::ObjCIndirectCopyRestoreExprClass: {

2459

2460

2461

2465 const Expr *E = OIE->getSubExpr();

2470 break;

2471 }

2472 }

2473}

2474

2475bool ExprEngine::replayWithoutInlining(ExplodedNode *N,

2479 assert(CalleeSF && CallerSF);

2480 ExplodedNode *BeforeProcessingCall = nullptr;

2482

2483

2484 while (N) {

2486 BeforeProcessingCall = N;

2488

2489

2491 continue;

2492

2493

2495 continue;

2497 continue;

2499 continue;

2500 if (std::optional SP = L.getAs<StmtPoint>())

2501 if (SP->getStmt() == CE)

2502 continue;

2503 break;

2504 }

2505

2506 if (!BeforeProcessingCall)

2507 return false;

2508

2509

2510

2511

2512

2516

2517

2519 NewNodeState =

2521

2522

2523 bool IsNew = false;

2524 ExplodedNode *NewNode = G.getNode(NewNodeLoc, NewNodeState, false, &IsNew);

2525

2526

2527 if (!IsNew)

2528 return true;

2529

2531

2532

2535 NumTimesRetriedWithoutInlining++;

2536 return true;

2537}

2538

2539

2540

2546

2548 return nullptr;

2549

2550 return CalleeLC;

2551}

2552

2553

2557

2558

2559 if(AMgr.options.ShouldUnrollLoops) {

2560 unsigned maxBlockVisitOnPath = AMgr.options.maxBlockVisitOnPath;

2562 if (Term) {

2564 Pred, maxBlockVisitOnPath);

2565 if (NewState != Pred->getState()) {

2567 if (!UpdatedNode)

2568 return;

2569 Pred = UpdatedNode;

2570 }

2571 }

2572

2574 return;

2575 }

2576

2577

2578

2580 if (BlockCount == AMgr.options.maxBlockVisitOnPath - 1 &&

2581 AMgr.options.ShouldWidenLoops) {

2583 if (!isa_and_nonnull<ForStmt, WhileStmt, DoStmt, CXXForRangeStmt>(Term))

2584 return;

2585

2586

2588

2589

2590

2591

2592

2593

2594

2598 nodeBuilder.generateNode(WidenedState, Pred);

2599 return;

2600 }

2601

2602

2603 if (BlockCount >= AMgr.options.maxBlockVisitOnPath) {

2607

2609

2610

2611

2612

2613

2614

2615

2616

2617

2618 Engine.FunctionSummaries->markShouldNotInline(

2620

2621

2622

2623

2624

2625 if ((!AMgr.options.NoRetryExhausted && replayWithoutInlining(Pred, LC)))

2626 return;

2627 NumMaxBlockCountReachedInInlined++;

2628 } else

2629 NumMaxBlockCountReached++;

2630

2631

2632 Engine.blocksExhausted.push_back(std::make_pair(L, Sink));

2633 }

2634}

2635

2640 llvm::PrettyStackTraceFormat CrashInfo(

2641 "Processing block entrance B%d -> B%d",

2644 currBldrCtx = &BldCtx;

2646 currBldrCtx = nullptr;

2647}

2648

2649

2650

2651

2652

2653

2654

2655

2656

2657

2662

2663 const auto *Ex = dyn_cast(Condition);

2664 if (!Ex)

2666

2667 uint64_t bits = 0;

2668 bool bitsInit = false;

2669

2670 while (const auto *CE = dyn_cast(Ex)) {

2672

2673 if (T->isIntegralOrEnumerationType())

2675

2677 if (!bitsInit || newBits < bits) {

2678 bitsInit = true;

2679 bits = newBits;

2680 }

2681

2682 Ex = CE->getSubExpr();

2683 }

2684

2685

2687

2688 if (!bitsInit || T->isIntegralOrEnumerationType() ||

2691

2692 return state->getSVal(Ex, LCtx);

2693}

2694

2695#ifndef NDEBUG

2698 const auto *BO = dyn_cast(Condition);

2699 if (!BO || !BO->isLogicalOp()) {

2701 }

2702 Condition = BO->getRHS()->IgnoreParens();

2703 }

2704 return nullptr;

2705}

2706#endif

2707

2708

2709

2710

2711

2712

2713

2714

2715

2716

2717

2718

2719

2720

2721

2724 if (const auto *Ex = dyn_cast(Condition))

2726

2727 const auto *BO = dyn_cast(Condition);

2728 if (!BO || !BO->isLogicalOp())

2730

2732 "Other kinds of branches are handled separately!");

2733

2734

2735

2736

2737

2738

2739

2740

2741

2742 for (CFGElement Elem : llvm::reverse(*B)) {

2743 std::optional CS = Elem.getAs<CFGStmt>();

2744 if (!CS)

2745 continue;

2746 const Stmt *LastStmt = CS->getStmt();

2748 return LastStmt;

2749 }

2750 llvm_unreachable("could not resolve condition");

2751}

2752

2754 std::pair<const ObjCForCollectionStmt *, const LocationContext *>;

2755

2757

2761 assert(!State->contains({O, LC}));

2762 return State->set({O, LC}, HasMoreIteraton);

2763}

2764

2769 assert(State->contains({O, LC}));

2770 return State->remove({O, LC});

2771}

2772

2776 assert(State->contains({O, LC}));

2777 return *State->get({O, LC});

2778}

2779

2780

2781

2782

2783static std::optional<std::pair<ProgramStateRef, ProgramStateRef>>

2786 if (const auto *ObjCFor = dyn_cast(Condition)) {

2787 bool HasMoreIteraton =

2789

2790

2791

2794 if (HasMoreIteraton)

2795 return std::pair<ProgramStateRef, ProgramStateRef>{State, nullptr};

2796 else

2797 return std::pair<ProgramStateRef, ProgramStateRef>{nullptr, State};

2798 }

2800

2801 if (X.isUnknownOrUndef()) {

2802

2803 if (const auto *Ex = dyn_cast(Condition)) {

2804 if (Ex->getType()->isIntegralOrEnumerationType()) {

2805

2806

2807

2808

2809 SVal recovered =

2811 N->getState()->getStateManager().getContext());

2812

2814 X = recovered;

2815 }

2816 }

2817 }

2818 }

2819

2820

2821 if (X.isUnknownOrUndef())

2822 return std::nullopt;

2823

2825

2827 return State->assume(V);

2828}

2829

2833 std::optional IterationsCompletedInLoop) {

2835 "CXXBindTemporaryExprs are handled by processBindTemporary.");

2836 currBldrCtx = &BldCtx;

2837

2838

2842 return;

2843 }

2844

2845 if (const auto *Ex = dyn_cast(Condition))

2847

2851 "Error evaluating branch");

2852

2855 Pred, *this);

2856

2857 if (CheckersOutSet.empty())

2858 return;

2859

2860 BranchNodeBuilder Builder(CheckersOutSet, Dst, BldCtx, DstT, DstF);

2861 for (ExplodedNode *PredN : CheckersOutSet) {

2862 if (PredN->isSink())

2863 continue;

2864

2866

2867 ProgramStateRef StTrue = PrevState, StFalse = PrevState;

2869 std::tie(StTrue, StFalse) = *KnownCondValueAssumption;

2870

2871 if (StTrue && StFalse)

2873

2874

2875

2876

2877

2878

2879

2880

2881 bool BothFeasible =

2882 (StTrue && StFalse) ||

2884

2885 if (StTrue) {

2886

2887

2888

2889

2890

2891

2892

2893

2894

2895

2896

2897

2898

2899

2900

2901 bool CompletedTwoIterations = IterationsCompletedInLoop.value_or(0) >= 2;

2902 bool SkipTrueBranch = BothFeasible && CompletedTwoIterations;

2903

2904

2905

2906

2907

2908 if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops) {

2909 Builder.generateNode(StTrue, true, PredN);

2910 } else if (!AMgr.options.InlineFunctionsWithAmbiguousLoops) {

2911

2912

2913

2914

2915

2916

2917

2918

2919

2920

2921

2922

2923

2924

2925

2927 Engine.FunctionSummaries->markShouldNotInline(

2929 }

2930 }

2931 }

2932

2933 if (StFalse) {

2934

2935

2936

2937

2938

2939

2940

2941

2942

2943

2944

2945

2946 bool BeforeFirstIteration = IterationsCompletedInLoop == std::optional{0};

2947 bool SkipFalseBranch = BothFeasible && BeforeFirstIteration &&

2948 AMgr.options.ShouldAssumeAtLeastOneIteration;

2949 if (!SkipFalseBranch)

2950 Builder.generateNode(StFalse, false, PredN);

2951 }

2952 }

2953 currBldrCtx = nullptr;

2954}

2955

2956

2957

2959 llvm::ImmutableSet<const VarDecl *>)

2960

2964 currBldrCtx = &BuilderCtx;

2965

2968 bool initHasRun = state->contains(VD);

2970

2971 if (!initHasRun) {

2972 state = state->add(VD);

2973 }

2974

2975 Builder.generateNode(state, initHasRun, Pred);

2976

2977 currBldrCtx = nullptr;

2978}

2979

2980

2981

2985

2986

2987

2988

2989

2990

2991

2992

2994

2995 if (std::optionalloc::GotoLabel LV = V.getAs<loc::GotoLabel>()) {

2996 const LabelDecl *L = LV->getLabel();

2997

2998 for (iterator Succ : builder) {

2999 if (Succ.getLabel() == L) {

3000 builder.generateNode(Succ, state);

3001 return;

3002 }

3003 }

3004

3005 llvm_unreachable("No block with label.");

3006 }

3007

3009

3010

3011

3012

3013 return;

3014 }

3015

3016

3017

3018

3019 for (iterator Succ : builder)

3021}

3022

3030

3031

3032

3037

3039 State = finishArgumentConstruction(

3040 State, *getStateManager().getCallEventManager().getCaller(

3042

3043

3044

3045

3046

3047

3048

3049

3050 {

3054 while (LC != ToLC) {

3055 assert(LC && "ToLC must be a parent of FromLC!");

3056 for (auto I : State->get())

3057 if (I.first.getLocationContext() == LC) {

3058

3059

3060

3061 assert(I.first.getItem().getKind() ==

3063 I.first.getItem().getKind() ==

3065 State = State->remove(I.first);

3066 }

3068 }

3069 }

3070

3071

3072 if (State != Pred->getState()) {

3074 NodeBuilder Bldr(Pred, PostCleanup, BC);

3076 if (!Pred) {

3077

3078

3079 return;

3080 }

3081 }

3082

3083 assert(areAllObjectsFullyConstructed(Pred->getState(),

3088

3091

3092

3093 for (const auto I : AfterRemovedDead)

3095 } else {

3097 }

3098

3099 Engine.enqueueEndOfFunction(Dst, RS);

3100}

3101

3102

3103

3106

3110

3111 if (CondV_untested.isUndef()) {

3112

3113

3114

3115

3116 return;

3117 }

3119

3121

3123 bool defaultIsFeasible = I == EI;

3124

3125 for ( ; I != EI; ++I) {

3126

3127 if (!I.getBlock())

3128 continue;

3129

3130 const CaseStmt *Case = I.getCase();

3131

3132

3134 assert(V1.getBitWidth() == getContext().getIntWidth(CondE->getType()));

3135

3136

3137 llvm::APSInt V2;

3139 V2 = E->EvaluateKnownConstInt(getContext());

3140 else

3141 V2 = V1;

3142

3144 if (std::optional NL = CondV.getAs<NonLoc>())

3145 std::tie(StateCase, DefaultSt) =

3146 DefaultSt->assumeInclusiveRange(*NL, V1, V2);

3147 else

3148 StateCase = DefaultSt;

3149

3150 if (StateCase)

3152

3153

3154

3155 if (DefaultSt)

3156 defaultIsFeasible = true;

3157 else {

3158 defaultIsFeasible = false;

3159 break;

3160 }

3161 }

3162

3163 if (!defaultIsFeasible)

3164 return;

3165

3166

3167

3168

3169

3170

3171

3172

3177 return;

3178 }

3179

3181}

3182

3183

3184

3185

3186

3191

3194

3195 auto resolveAsLambdaCapturedVar =

3196 [&](const ValueDecl *VD) -> std::optional<std::pair<SVal, QualType>> {

3197 const auto *MD = dyn_cast(LCtx->getDecl());

3198 const auto *DeclRefEx = dyn_cast(Ex);

3199 if (AMgr.options.ShouldInlineLambdas && DeclRefEx &&

3200 DeclRefEx->refersToEnclosingVariableOrCapture() && MD &&

3201 MD->getParent()->isLambda()) {

3202

3204 llvm::DenseMap<const ValueDecl *, FieldDecl *> LambdaCaptureFields;

3205 FieldDecl *LambdaThisCaptureField;

3206 CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);

3207

3208

3209

3210 if (const FieldDecl *FD = LambdaCaptureFields[VD]) {

3212 SVal CXXThisVal = state->getSVal(CXXThis);

3213 return std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());

3214 }

3215 }

3216

3217 return std::nullopt;

3218 };

3219

3220 if (const auto *VD = dyn_cast(D)) {

3221

3222

3223 assert(Ex->isGLValue() || VD->getType()->isVoidType());

3225 std::optional<std::pair<SVal, QualType>> VInfo =

3226 resolveAsLambdaCapturedVar(VD);

3227

3228 if (!VInfo)

3229 VInfo = std::make_pair(state->getLValue(VD, LocCtxt), VD->getType());

3230

3231 SVal V = VInfo->first;

3232 bool IsReference = VInfo->second->isReferenceType();

3233

3234

3235

3236 if (IsReference) {

3237 if (const MemRegion *R = V.getAsRegion())

3238 V = state->getSVal(R);

3239 else

3241 }

3242

3243 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,

3245 return;

3246 }

3247 if (const auto *ED = dyn_cast(D)) {

3249 SVal V = svalBuilder.makeIntVal(ED->getInitVal());

3250 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V));

3251 return;

3252 }

3253 if (const auto *FD = dyn_cast(D)) {

3254 SVal V = svalBuilder.getFunctionPointer(FD);

3255 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,

3257 return;

3258 }

3260

3261

3262 return;

3263 }

3264 if (const auto *BD = dyn_cast(D)) {

3265

3266 if (std::optional<std::pair<SVal, QualType>> VInfo =

3267 resolveAsLambdaCapturedVar(BD)) {

3268 auto [V, T] = VInfo.value();

3269

3270 if (T->isReferenceType()) {

3271 if (const MemRegion *R = V.getAsRegion())

3272 V = state->getSVal(R);

3273 else

3275 }

3276

3277 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,

3279 return;

3280 }

3281

3283

3284 SVal Base = state->getLValue(DD, LCtx);

3285 if (DD->getType()->isReferenceType()) {

3287 Base = state->getSVal(R);

3288 else

3290 }

3291

3293

3294

3295 if (const auto *ME = dyn_cast(BD->getBinding())) {

3296 const auto *Field = cast(ME->getMemberDecl());

3297 V = state->getLValue(Field, Base);

3298 }

3299

3300 else if (const auto *ASE = dyn_cast(BD->getBinding())) {

3301 SVal Idx = state->getSVal(ASE->getIdx(), LCtx);

3302

3303

3304

3305

3306 assert(Idx.isConstant() && "BindingDecl array index is not a constant!");

3307

3308 V = state->getLValue(BD->getType(), Idx, Base);

3309 }

3310

3311 else if (const auto *HV = BD->getHoldingVar()) {

3312 V = state->getLValue(HV, LCtx);

3313

3314 if (HV->getType()->isReferenceType()) {

3315 if (const MemRegion *R = V.getAsRegion())

3316 V = state->getSVal(R);

3317 else

3319 }

3320 } else

3321 llvm_unreachable("An unknown case of structured binding encountered!");

3322

3323

3324

3325 if (BD->getType()->isReferenceType() && !BD->getHoldingVar()) {

3326 if (const MemRegion *R = V.getAsRegion())

3327 V = state->getSVal(R);

3328 else

3330 }

3331

3332 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), nullptr,

3334

3335 return;

3336 }

3337

3338 if (const auto *TPO = dyn_cast(D)) {

3339

3340 (void)TPO;

3341 return;

3342 }

3343

3344 llvm_unreachable("Support for this Decl not implemented.");

3345}

3346

3347

3353

3355 StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);

3356

3358

3359 for (auto *Node : CheckerPreStmt) {

3360

3361

3363 break;

3364

3365 const LocationContext *LCtx = Node->getLocationContext();

3367

3369

3370

3371

3372

3373

3374

3375

3376

3377

3378

3379

3380

3381

3382

3383

3384

3385

3386

3387

3388

3389

3390

3391

3392

3393

3394

3395

3396

3397

3398

3399

3400

3401

3402

3403

3404 if (const auto *ME = dyn_cast(Arr)) {

3405 Expr *MEBase = ME->getBase();

3406

3407

3408 if (auto CXXSCE = dyn_cast(MEBase)) {

3409 MEBase = CXXSCE->getSubExpr();

3410 }

3411

3413 SVal Obj = state->getLValue(cast(ObjDeclExpr->getDecl()), LCtx);

3414

3416 }

3417

3418

3419

3420

3421

3422

3423

3424

3425

3426

3427

3428

3429

3430 if (const DeclRefExpr *DRE = dyn_cast(Arr))

3432

3433

3435 Base = state->getSVal(R);

3436 else

3438

3439 Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, Base));

3440 }

3441

3443}

3444

3445

3451

3454

3456 StmtNodeBuilder Bldr(CheckerPreStmt, EvalSet, *currBldrCtx);

3457

3459

3460

3461

3462

3463 bool IsGLValueLike = A->isGLValue() ||

3464 (A->getType().isCForbiddenLValueType() && !AMgr.getLangOpts().CPlusPlus);

3465

3466 for (auto *Node : CheckerPreStmt) {

3467 const LocationContext *LCtx = Node->getLocationContext();

3469

3470 if (IsGLValueLike) {

3472

3473

3474

3475

3476 if (T->isVoidType())

3478

3479 SVal V = state->getLValue(T,

3480 state->getSVal(Idx, LCtx),

3481 state->getSVal(Base, LCtx));

3482 Bldr.generateNode(A, Node, state->BindExpr(A, LCtx, V), nullptr,

3484 } else if (IsVectorType) {

3485

3487 } else {

3488 llvm_unreachable("Array subscript should be an lValue when not \

3489a vector and not a forbidden lvalue type");

3490 }

3491 }

3492

3494}

3495

3496

3499

3502

3505

3506

3507

3509 for (const auto I : CheckedSet)

3511 } else {

3512 StmtNodeBuilder Bldr(CheckedSet, EvalSet, *currBldrCtx);

3514

3515 for (const auto I : CheckedSet) {

3519

3520

3521 if (const auto *MD = dyn_cast(Member)) {

3522 if (MD->isImplicitObjectMemberFunction())

3523 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr);

3524

3525 SVal MDVal = svalBuilder.getFunctionPointer(MD);

3526 state = state->BindExpr(M, LCtx, MDVal);

3527

3529 continue;

3530 }

3531

3532

3534 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,

3535 nullptr,

3536 &MR);

3537 SVal baseExprVal =

3539

3540

3541 if (const auto *SR =

3542 dyn_cast_or_null(baseExprVal.getAsRegion())) {

3543 QualType T = SR->getPointeeStaticType();

3544 baseExprVal =

3546 }

3547

3549 SVal L = state->getLValue(field, baseExprVal);

3550

3552

3553

3554

3555

3558 const auto *PE =

3559 dyn_cast(I->getParentMap().getParentIgnoreParens(M));

3560 if (!PE || PE->getCastKind() != CK_ArrayToPointerDecay) {

3561 llvm_unreachable("should always be wrapped in ArrayToPointerDecay");

3562 }

3563 }

3564

3565 if (field->getType()->isReferenceType()) {

3567 L = state->getSVal(R);

3568 else

3570 }

3571

3572 Bldr.generateNode(M, I, state->BindExpr(M, LCtx, L), nullptr,

3574 } else {

3576 evalLoad(Tmp, M, M, I, state, L);

3578 }

3579 }

3580 }

3581

3583}

3584

3589

3590

3591

3592

3594 StmtNodeBuilder Bldr(AfterPreSet, AfterInvalidateSet, *currBldrCtx);

3595

3596 for (const auto I : AfterPreSet) {

3599

3601 for (unsigned SI = 0, Count = AE->getNumSubExprs(); SI != Count; SI++) {

3603 SVal SubExprVal = State->getSVal(SubExpr, LCtx);

3604 ValuesToInvalidate.push_back(SubExprVal);

3605 }

3606

3607 State = State->invalidateRegions(ValuesToInvalidate, getCFGElementRef(),

3608 currBldrCtx->blockCount(), LCtx,

3609 true,

3610 nullptr);

3611

3613 State = State->BindExpr(AE, LCtx, ResultVal);

3616 }

3617

3619}

3620

3621

3622

3623

3624

3625

3626

3627

3633 for (const std::pair<SVal, SVal> &LocAndVal : LocAndVals) {

3634

3635 const MemRegion *MR = LocAndVal.first.getAsRegion();

3638 Escaped.push_back(LocAndVal.second);

3639 continue;

3640 }

3641

3642

3643 if (const auto *VR = dyn_cast(MR->getBaseRegion()))

3645 VR->getStackFrame()->inTopFrame())

3646 if (const auto *RD = VR->getValueType()->getAsCXXRecordDecl())

3647 if (!RD->hasTrivialDestructor()) {

3648 Escaped.push_back(LocAndVal.second);

3649 continue;

3650 }

3651

3652

3653

3654

3655

3656

3657 SVal StoredVal = State->getSVal(MR);

3658 if (StoredVal != LocAndVal.second)

3659 if (State ==

3660 (State->bindLoc(loc::MemRegionVal(MR), LocAndVal.second, LCtx)))

3661 Escaped.push_back(LocAndVal.second);

3662 }

3663

3664 if (Escaped.empty())

3665 return State;

3666

3668}

3669

3673 std::pair<SVal, SVal> LocAndVal(Loc, Val);

3675 nullptr);

3676}

3677

3684 if (!Invalidated || Invalidated->empty())

3685 return State;

3686

3689 *Invalidated,

3690 nullptr,

3692 &ITraits);

3693

3694

3695

3697 for (const auto I : ExplicitRegions) {

3699 SymbolsDirectlyInvalidated.insert(R->getSymbol());

3700 }

3701

3703 for (const auto &sym : *Invalidated) {

3704 if (SymbolsDirectlyInvalidated.count(sym))

3705 continue;

3706 SymbolsIndirectlyInvalidated.insert(sym);

3707 }

3708

3709 if (!SymbolsDirectlyInvalidated.empty())

3712

3713

3714 if (!SymbolsIndirectlyInvalidated.empty())

3717

3718 return State;

3719}

3720

3721

3722

3728 if (!PP)

3729 PP = &PS;

3730

3731

3734 StoreE, AtDeclInit, *this, *PP);

3735

3737

3738

3739

3742 nullptr);

3745 Bldr.generateNode(L, state, Pred);

3746 return;

3747 }

3748

3749 for (const auto PredI : CheckedSet) {

3751

3753

3754

3755

3756

3757 state = state->bindLoc(location.castAs<Loc>(), Val, LC,

3758 !AtDeclInit);

3759

3760 const MemRegion *LocReg = nullptr;

3761 if (std::optionalloc::MemRegionVal LocRegVal =

3763 LocReg = LocRegVal->getRegion();

3764 }

3765

3767 Bldr.generateNode(L, state, PredI);

3768 }

3769}

3770

3771

3772

3773

3774

3775

3776

3777

3778

3780 const Expr *LocationE,

3784

3785

3786 const Expr *StoreE = AssignE ? AssignE : LocationE;

3787

3788

3790 evalLocation(Tmp, AssignE, LocationE, Pred, state, location, false);

3791

3792 if (Tmp.empty())

3793 return;

3794

3796 return;

3797

3798 for (const auto I : Tmp)

3799 evalBind(Dst, StoreE, I, location, Val, false);

3800}

3801

3803 const Expr *NodeEx,

3804 const Expr *BoundEx,

3807 SVal location,

3810 assert(isa<NonLoc>(location) && "location cannot be a NonLoc.");

3811 assert(NodeEx);

3812 assert(BoundEx);

3813

3815 evalLocation(Tmp, NodeEx, BoundEx, Pred, state, location, true);

3816 if (Tmp.empty())

3817 return;

3818

3821 return;

3822

3823

3824 for (const auto I : Tmp) {

3825 state = I->getState();

3827

3829 if (location.isValid()) {

3830 if (LoadTy.isNull())

3831 LoadTy = BoundEx->getType();

3832 V = state->getSVal(location.castAs<Loc>(), LoadTy);

3833 }

3834

3835 Bldr.generateNode(NodeEx, I, state->BindExpr(BoundEx, LCtx, V), tag,

3837 }

3838}

3839

3841 const Stmt *NodeEx,

3842 const Stmt *BoundEx,

3845 SVal location,

3846 bool isLoad) {

3848

3850 return;

3851 }

3852

3854 BldrTop.takeNodes(Pred);

3856 if (Pred->getState() != state) {

3857

3858

3859

3860

3861

3862

3863

3864

3865

3867 Bldr.generateNode(NodeEx, Pred, state, &tag);

3868 }

3871 NodeEx, BoundEx, *this);

3872 BldrTop.addNodes(Tmp);

3873}

3874

3875std::pair<const ProgramPointTag *, const ProgramPointTag *>

3878 FalseTag(TagProviderName, "Eagerly Assume False");

3879

3880 return std::make_pair(&TrueTag, &FalseTag);

3881}

3882

3883

3884

3885

3887 const Expr *)

3888

3891 const Expr *Ex) {

3893

3895

3896

3897

3900 continue;

3901 }

3902

3904 State = State->set(nullptr);

3906 std::optionalnonloc::SymbolVal SEV = V.getAs<nonloc::SymbolVal>();

3907 if (SEV && SEV->isExpression()) {

3909

3910 auto [StateTrue, StateFalse] = State->assume(*SEV);

3911

3912 if (StateTrue && StateFalse) {

3913 StateTrue = StateTrue->set(Ex);

3914 StateFalse = StateFalse->set(Ex);

3915 }

3916

3917

3918 if (StateTrue) {

3920 StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val);

3921 Bldr.generateNode(Ex, Pred, StateTrue, TrueTag);

3922 }

3923

3924

3925 if (StateFalse) {

3927 StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val);

3928 Bldr.generateNode(Ex, Pred, StateFalse, FalseTag);

3929 }

3930 }

3931 }

3932}

3933

3935 const Expr *Ex) const {

3936 return Ex && State->get() == Ex;

3937}

3938

3942

3943

3944

3945

3946

3947

3948

3950

3953 assert(isa<NonLoc>(X));

3954

3955 if (std::optional LV = X.getAs<Loc>())

3957 currBldrCtx->blockCount(),

3959 true);

3960 }

3961

3962

3965

3966 if (std::optional LV = X.getAs<Loc>())

3968 currBldrCtx->blockCount(),

3970 true);

3971 }

3972

3974}

3975

3981

3982

3983

3984

3985

3986namespace llvm {

3987

3988template<>

3991

3995

3997 for (const auto &Report : Class.getReports()) {

3998 const auto *PR = dyn_cast(Report.get());

3999 if (!PR)

4000 continue;

4001 const ExplodedNode *EN = PR->getErrorNode();

4004 return true;

4005 }

4006 }

4007 return false;

4008 }

4009

4010

4011

4012

4013

4016 llvm::function_ref<void(const ExplodedNode *)> PreCallback,

4017 llvm::function_ref<void(const ExplodedNode *)> PostCallback,

4018 llvm::function_ref<bool(const ExplodedNode *)> Stop) {

4019 while (true) {

4020 PreCallback(N);

4021 if (Stop(N))

4022 return true;

4023

4025 break;

4026 PostCallback(N);

4027

4029 }

4030 return false;

4031 }

4032

4036

4038 std::string Buf;

4039 llvm::raw_string_ostream Out(Buf);

4040

4041 const bool IsDot = true;

4042 const unsigned int Space = 1;

4044

4045 Out << "{ \"state_id\": " << State->getID()

4046 << ",\\l";

4047

4048 Indent(Out, Space, IsDot) << "\"program_points\": [\\l";

4049

4050

4052 N,

4054 Indent(Out, Space + 1, IsDot) << "{ ";

4056 Out << ", \"tag\": ";

4058 Out << '\"' << Tag->getDebugTag() << '\"';

4059 else

4060 Out << "null";

4061 Out << ", \"node_id\": " << OtherNode->getID() <<

4062 ", \"is_sink\": " << OtherNode->isSink() <<

4063 ", \"has_report\": " << nodeHasBugReport(OtherNode) << " }";

4064 },

4065

4066 [&](const ExplodedNode *) { Out << ",\\l"; },

4067 [&](const ExplodedNode *) { return false; });

4068

4069 Out << "\\l";

4070 Indent(Out, Space, IsDot) << "],\\l";

4071

4073

4074 Out << "\\l}\\l";

4075 return Buf;

4076 }

4077};

4078

4079}

4080

4082 std::string Filename = DumpGraph(trim);

4083 llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);

4084}

4085

4087 std::string Filename = DumpGraph(Nodes);

4088 llvm::DisplayGraph(Filename, false, llvm::GraphProgram::DOT);

4089}

4090

4092 if (trim) {

4093 std::vector<const ExplodedNode *> Src;

4094

4095

4096 for (const auto &Class : BR.equivalenceClasses()) {

4097 const auto *R =

4098 dyn_cast(Class.getReports()[0].get());

4099 if (!R)

4100 continue;

4101 const auto *N = const_cast<ExplodedNode *>(R->getErrorNode());

4102 Src.push_back(N);

4103 }

4104 return DumpGraph(Src, Filename);

4105 }

4106

4107 return llvm::WriteGraph(&G, "ExprEngine", false,

4108 "Exploded Graph",

4109 std::string(Filename));

4110}

4111

4113 StringRef Filename) {

4114 std::unique_ptr TrimmedG(G.trim(Nodes));

4115

4116 if (!TrimmedG) {

4117 llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";

4118 return "";

4119 }

4120

4121 return llvm::WriteGraph(TrimmedG.get(), "TrimmedExprEngine",

4122 false,

4123 "Trimmed Exploded Graph",

4124 std::string(Filename));

4125}

4126

4128 static int index = 0;

4130}

4131

4132void ExprEngine::anchor() { }

4133

4138

4140

4144

4145 bool IsCompound = T->isArrayType() || T->isRecordType() ||

4146 T->isAnyComplexType() || T->isVectorType();

4147

4148 if (Args.size() > 1 || (E->isPRValue() && IsCompound && !IsTransparent)) {

4150 for (Expr *E : llvm::reverse(Args))

4152

4154 S->BindExpr(E, LC, svalBuilder.makeCompoundVal(T, ArgList)));

4155 } else {

4157 S->BindExpr(E, LC,

4158 Args.size() == 0

4160 : S->getSVal(Args.front(), LC)));

4161 }

4162}

Defines the clang::ASTContext interface.

This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...

static const MemRegion * getRegion(const CallEvent &Call, const MutexDescriptor &Descriptor, bool IsLock)

static Decl::Kind getKind(const Decl *D)

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

#define STAT_COUNTER(VARNAME, DESC)

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

static const Stmt * getRightmostLeaf(const Stmt *Condition)

Definition ExprEngine.cpp:2696

static SVal RecoverCastedSymbol(ProgramStateRef state, const Stmt *Condition, const LocationContext *LCtx, ASTContext &Ctx)

RecoverCastedSymbol - A helper function for ProcessBranch that is used to try to recover some path-se...

Definition ExprEngine.cpp:2658

static void printObjectsUnderConstructionJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)

Definition ExprEngine.cpp:686

static void printIndicesOfElementsToConstructJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)

Definition ExprEngine.cpp:732

static void printStateTraitWithLocationContextJson(raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx, const char *NL, unsigned int Space, bool IsDot, const char *jsonPropertyName, Printer printer, Args &&...args)

A helper function to generalize program state trait printing.

Definition ExprEngine.cpp:911

static void printPendingArrayDestructionsJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)

Definition ExprEngine.cpp:855

static bool shouldRemoveDeadBindings(AnalysisManager &AMgr, const Stmt *S, const ExplodedNode *Pred, const LocationContext *LC)

Definition ExprEngine.cpp:1003

static const Stmt * ResolveCondition(const Stmt *Condition, const CFGBlock *B)

Definition ExprEngine.cpp:2722

REGISTER_TRAIT_WITH_PROGRAMSTATE(ObjectsUnderConstruction, ObjectsUnderConstructionMap) typedef llvm REGISTER_TRAIT_WITH_PROGRAMSTATE(IndexOfElementToConstruct, IndexOfElementToConstructMap) typedef llvm typedef llvm::ImmutableMap< const LocationContext *, unsigned > PendingArrayDestructionMap

Definition ExprEngine.cpp:200

static void printPendingInitLoopJson(raw_ostream &Out, ProgramStateRef State, const char *NL, const LocationContext *LCtx, unsigned int Space=0, bool IsDot=false)

Definition ExprEngine.cpp:794

llvm::ImmutableMap< ConstructedObjectKey, SVal > ObjectsUnderConstructionMap

Definition ExprEngine.cpp:187

static const LocationContext * getInlinedLocationContext(ExplodedNode *Node, ExplodedGraph &G)

Return the innermost location context which is inlined at Node, unless it's the top-level (entry poin...

Definition ExprEngine.cpp:2541

static std::optional< std::pair< ProgramStateRef, ProgramStateRef > > assumeCondition(const Stmt *Condition, ExplodedNode *N)

Split the state on whether there are any more iterations left for this loop.

Definition ExprEngine.cpp:2784

std::pair< const ObjCForCollectionStmt *, const LocationContext * > ObjCForLctxPair

Definition ExprEngine.cpp:2753

TokenType getType() const

Returns the token's type, e.g.

FormatToken * Next

The next token in the unwrapped line.

Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.

Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.

Defines the clang::LangOptions interface.

This header contains the declarations of functions which are used to decide which loops should be com...

This header contains the declarations of functions which are used to widen loops which do not otherwi...

Defines the PrettyStackTraceEntry class, which is used to make crashes give more contextual informati...

#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)

Declares an immutable map of type NameTy, suitable for placement into the ProgramState.

#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)

Declares a program state trait for type Type called Name, and introduce a type named NameTy.

static bool isRecordType(QualType T)

Defines the clang::SourceLocation class and associated facilities.

Defines various enumerations that describe declaration and type specifiers.

Defines the Objective-C statement AST node classes.

C Language Family Type Representation.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

const clang::PrintingPolicy & getPrintingPolicy() const

uint64_t getTypeSize(QualType T) const

Return the size of the specified (complete) type T, in bits.

ParentMap & getParentMap()

ASTContext & getASTContext() const

Stores options for the analyzer from the command line.

AnalysisPurgeMode AnalysisPurgeOpt

Represents a loop initializing the elements of an array.

OpaqueValueExpr * getCommonExpr() const

Get the common subexpression shared by all initializations (the source array).

Expr * getSubExpr() const

Get the initializer to use for each array element.

ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.

Represents an array type, per C99 6.7.5.2 - Array Declarators.

AtomicExpr - Variadic atomic builtins: __atomic_exchange, __atomic_fetch_*, __atomic_load,...

static unsigned getNumSubExprs(AtomicOp Op)

Determine the number of arguments the specified atomic builtin should have.

const CFGBlock * getPreviousBlock() const

const CFGBlock * getBlock() const

Represents C++ object destructor implicitly generated for automatic object or temporary bound to cons...

const VarDecl * getVarDecl() const

const Stmt * getTriggerStmt() const

Represents C++ object destructor implicitly generated for base object in destructor.

const CXXBaseSpecifier * getBaseSpecifier() const

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

CFGTerminator getTerminator() const

Stmt * getTerminatorStmt()

unsigned getBlockID() const

Represents C++ object destructor generated from a call to delete.

const CXXDeleteExpr * getDeleteExpr() const

Represents a top-level expression in a basic block.

T castAs() const

Convert to the specified CFGElement type, asserting that this CFGElement is of the desired type.

Represents C++ object destructor implicitly generated by compiler on various occasions.

const CXXDestructorDecl * getDestructorDecl(ASTContext &astContext) const

Represents C++ base or member initializer from constructor's initialization list.

CXXCtorInitializer * getInitializer() const

Represents the point where a loop ends.

const Stmt * getLoopStmt() const

Represents C++ object destructor implicitly generated for member object in destructor.

const FieldDecl * getFieldDecl() const

Represents C++ allocator call.

const CXXNewExpr * getAllocatorExpr() const

const Stmt * getStmt() const

Represents C++ object destructor implicitly generated at the end of full expression for temporary obj...

const CXXBindTemporaryExpr * getBindTemporaryExpr() const

bool isStmtBranch() const

Represents a base class of a C++ class.

Represents binding an expression to a temporary.

const Expr * getSubExpr() const

SourceLocation getBeginLoc() const LLVM_READONLY

Represents a call to a C++ constructor.

Represents a C++ base or member initializer.

FieldDecl * getMember() const

If this is a member initializer, returns the declaration of the non-static data member being initiali...

bool isDelegatingInitializer() const

Determine whether this initializer is creating a delegating constructor.

Expr * getInit() const

Get the initializer.

SourceLocation getSourceLocation() const

Determine the source location of the initializer.

bool isAnyMemberInitializer() const

bool isBaseInitializer() const

Determine whether this initializer is initializing a base class.

bool isIndirectMemberInitializer() const

int64_t getID(const ASTContext &Context) const

const Type * getBaseClass() const

If this is a base class initializer, returns the type of the base class.

FieldDecl * getAnyMember() const

IndirectFieldDecl * getIndirectMember() const

bool isBaseVirtual() const

Returns whether the base is virtual or not.

Represents a delete expression for memory deallocation and destructor calls, e.g.

SourceLocation getBeginLoc() const

QualType getDestroyedType() const

Retrieve the type being destroyed.

Represents a C++ destructor within a class.

Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".

Represents a list-initialization with parenthesis.

MutableArrayRef< Expr * > getInitExprs()

Represents a C++ struct/union/class.

void getCaptureFields(llvm::DenseMap< const ValueDecl *, FieldDecl * > &Captures, FieldDecl *&ThisCapture) const

For a closure type, retrieve the mapping from captured variables and this to the non-static data memb...

CXXDestructorDecl * getDestructor() const

Returns the destructor decl for this class.

Represents a point when we begin processing an inlined call.

CaseStmt - Represent a case statement.

Represents a single point (AST node) in the program that requires attention during construction of an...

unsigned getIndex() const

If a single trigger statement triggers multiple constructors, they are usually being enumerated.

const CXXCtorInitializer * getCXXCtorInitializer() const

The construction site is not necessarily a statement.

@ TemporaryDestructorKind

const Stmt * getStmtOrNull() const

DeclContext * getParent()

getParent - Returns the containing DeclContext.

A reference to a declared variable, function, enum, etc.

DeclStmt - Adaptor class for mixing declarations with statements and expressions.

const Decl * getSingleDecl() const

Decl - This represents one declaration (or definition), e.g.

This is a meta program point, which should be skipped by all the diagnostic reasoning etc.

This represents one expression.

const Expr * skipRValueSubobjectAdjustments(SmallVectorImpl< const Expr * > &CommaLHS, SmallVectorImpl< SubobjectAdjustment > &Adjustments) const

Walk outwards from an expression we want to bind a reference to and find the expression whose lifetim...

llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx) const

EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded integer.

Expr * IgnoreParenImpCasts() LLVM_READONLY

Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...

Expr * IgnoreImplicit() LLVM_READONLY

Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.

Expr * IgnoreParens() LLVM_READONLY

Skip past any parentheses which might surround this expression until reaching a fixed point.

Represents a member of a struct/union/class.

This represents a GCC inline-assembly statement extension.

One of these records is kept for each identifier that is lexed.

StringRef getName() const

Return the actual identifier string.

Describes an C or C++ initializer list.

bool isTransparent() const

Is this a transparent initializer list (that is, an InitListExpr that is purely syntactic,...

ArrayRef< Expr * > inits()

Represents the declaration of a label.

It wraps the AnalysisDeclContext to represent both the call stack with the help of StackFrameContext ...

const Decl * getDecl() const

LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const

const LocationContext * getParent() const

It might return null.

const StackFrameContext * getStackFrame() const

virtual bool inTopFrame() const

void printJson(raw_ostream &Out, const char *NL="\n", unsigned int Space=0, bool IsDot=false, std::function< void(const LocationContext *)> printMoreInfoPerContext=[](const LocationContext *) {}) const

Prints out the call stack in json format.

Represents a point when we exit a loop.

This represents a Microsoft inline-assembly statement extension.

MemberExpr - [C99 6.5.2.3] Structure and Union Members.

ValueDecl * getMemberDecl() const

Retrieve the member declaration to which this expression refers.

This represents a decl that may have a name.

DeclarationName getDeclName() const

Get the actual, stored name of the declaration, which may be a special name.

Represents Objective-C's collection statement.

Expr * getSourceExpr() const

The source expression of an opaque value expression is the expression which originally generated the ...

bool isConsumedExpr(Expr *E) const

Represents a parameter to a function.

Represents a program point just after an implicit call event.

Represents a program point after a store evaluation.

Represents a program point just before an implicit call event.

If a crash happens while one of these objects are live, the message is printed out along with the spe...

ProgramPoints can be "tagged" as representing points specific to a given analysis entity.

const ProgramPointTag * getTag() const

bool isPurgeKind()

Is this a program point corresponding to purge/removal of dead symbols and bindings.

T castAs() const

Convert to the specified ProgramPoint type, asserting that this ProgramPoint is of the desired type.

void printJson(llvm::raw_ostream &Out, const char *NL="\n") const

@ PreStmtPurgeDeadSymbolsKind

@ PostStmtPurgeDeadSymbolsKind

const StackFrameContext * getStackFrame() const

std::optional< T > getAs() const

Convert to the specified ProgramPoint type, returning std::nullopt if this ProgramPoint is not of the...

const LocationContext * getLocationContext() const

A (possibly-)qualified type.

QualType getDesugaredType(const ASTContext &Context) const

Return the specified type with any "sugar" removed from the type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

QualType getCanonicalType() const

SplitQualType split() const

Divides a QualType into its unqualified type and a set of local qualifiers.

std::string getAsString() const

ReturnStmt - This represents a return, optionally of an expression: return; return 4;.

std::string printToString(const SourceManager &SM) const

It represents a stack frame of the call stack (based on CallEvent).

unsigned getIndex() const

const Stmt * getCallSite() const

const CFGBlock * getCallSiteBlock() const

bool inTopFrame() const override

const Stmt * getStmt() const

Stmt - This represents one statement.

void printJson(raw_ostream &Out, PrinterHelper *Helper, const PrintingPolicy &Policy, bool AddQuotes) const

Pretty-prints in JSON format.

StmtClass getStmtClass() const

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

const char * getStmtClassName() const

int64_t getID(const ASTContext &Context) const

SourceLocation getBeginLoc() const LLVM_READONLY

SwitchStmt - This represents a 'switch' stmt.

bool isAllEnumCasesCovered() const

Returns true if the SwitchStmt is a switch of an enum value and all cases have been explicitly covere...

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isReferenceType() const

bool isEnumeralType() const

bool isVectorType() const

Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...

Represents a variable declaration or definition.

This class is used for tools that requires cross translation unit capability.

AnalyzerOptions & options

llvm::ImmutableList< SVal > getEmptySValList()

llvm::ImmutableList< SVal > prependSVal(SVal X, llvm::ImmutableList< SVal > L)

BranchNodeBuilder is responsible for constructing the nodes corresponding to the two branches of the ...

ExplodedNode * generateNode(ProgramStateRef State, bool branch, ExplodedNode *Pred)

BugReporter is a utility class for generating PathDiagnostics for analysis.

llvm::iterator_range< EQClasses_iterator > equivalenceClasses()

Represents an abstract call to a function or method along a particular path.

static bool isCallStmt(const Stmt *S)

Returns true if this is a statement is a function or method call of some kind.

void runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng, const ReturnStmt *RS)

Run checkers on end of function.

void runCheckersForLocation(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, bool isLoad, const Stmt *NodeEx, const Stmt *BoundEx, ExprEngine &Eng)

Run checkers for load/store of a location.

void runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, bool AtDeclInit, ExprEngine &Eng, const ProgramPoint &PP)

Run checkers for binding of a value to a location.

void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng)

Run checkers for end of analysis.

void runCheckersForPrintStateJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const

Run checkers for debug-printing a ProgramState.

void runCheckersForDeadSymbols(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SymbolReaper &SymReaper, const Stmt *S, ExprEngine &Eng, ProgramPoint::Kind K)

Run checkers for dead symbols.

ProgramStateRef runCheckersForRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call)

Run checkers for region changes.

void runCheckersForLiveSymbols(ProgramStateRef state, SymbolReaper &SymReaper)

Run checkers for live symbols.

void runCheckersForBeginFunction(ExplodedNodeSet &Dst, const BlockEdge &L, ExplodedNode *Pred, ExprEngine &Eng)

Run checkers on beginning of function.

void runCheckersForPostStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined=false)

Run checkers for post-visiting Stmts.

void runCheckersForPreStmt(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng)

Run checkers for pre-visiting Stmts.

void runCheckersForBlockEntrance(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const BlockEntrance &Entrance, ExprEngine &Eng) const

Run checkers after taking a control flow edge.

void runCheckersForBranchCondition(const Stmt *condition, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng)

Run checkers for branch condition.

ProgramStateRef runCheckersForPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, RegionAndSymbolInvalidationTraits *ITraits)

Run checkers when pointers escape.

ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, SVal Cond, bool Assumption)

Run checkers for handling assumptions on symbolic values.

virtual ProgramStateRef removeDeadBindings(ProgramStateRef state, SymbolReaper &SymReaper)=0

Scan all symbols referenced by the constraints.

void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx)

Enqueue a single node created as a result of statement processing.

ExplodedNode * getNode(const ProgramPoint &L, ProgramStateRef State, bool IsSink=false, bool *IsNew=nullptr)

Retrieve the node associated with a (Location, State) pair, where the 'Location' is a ProgramPoint in...

ExplodedNode * getRoot() const

Get the root node of the graph.

void insert(const ExplodedNodeSet &S)

void Add(ExplodedNode *N)

const ProgramStateRef & getState() const

pred_iterator pred_begin()

bool isTrivial() const

The node is trivial if it has only one successor, only one predecessor, it's predecessor has only one...

ProgramPoint getLocation() const

getLocation - Returns the edge associated with the given node.

void addPredecessor(ExplodedNode *V, ExplodedGraph &G)

addPredeccessor - Adds a predecessor to the current node, and in tandem add this node as a successor ...

ExplodedNode * getFirstSucc()

const StackFrameContext * getStackFrame() const

const LocationContext * getLocationContext() const

unsigned succ_size() const

void processEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, const ReturnStmt *RS=nullptr)

Called by CoreEngine.

Definition ExprEngine.cpp:3033

void VisitBinaryOperator(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitBinaryOperator - Transfer function logic for binary operators.

ProgramStateManager & getStateManager()

void VisitArraySubscriptExpr(const ArraySubscriptExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitArraySubscriptExpr - Transfer function for array accesses.

Definition ExprEngine.cpp:3446

void VisitCommonDeclRefExpr(const Expr *DR, const NamedDecl *D, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Transfer function logic for DeclRefExprs and BlockDeclRefExprs.

Definition ExprEngine.cpp:3187

void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred)

Definition ExprEngine.cpp:1166

void VisitObjCMessage(const ObjCMessageExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst)

void ProcessTemporaryDtor(const CFGTemporaryDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Definition ExprEngine.cpp:1570

void VisitGuardedExpr(const Expr *Ex, const Expr *L, const Expr *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitGuardedExpr - Transfer function logic for ?, __builtin_choose.

void processBeginOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst, const BlockEdge &L)

Called by CoreEngine.

Definition ExprEngine.cpp:3023

void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitCast - Transfer function logic for all casts (implicit and explicit).

void removeDead(ExplodedNode *Node, ExplodedNodeSet &Out, const Stmt *ReferenceStmt, const LocationContext *LC, const Stmt *DiagnosticStmt=nullptr, ProgramPoint::Kind K=ProgramPoint::PreStmtPurgeDeadSymbolsKind)

Run the analyzer's garbage collection - remove dead symbols and bindings from the state.

Definition ExprEngine.cpp:1029

BasicValueFactory & getBasicVals()

void VisitLogicalExpr(const BinaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitLogicalExpr - Transfer function logic for '&&', '||'.

void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, bool IsBaseDtor, ExplodedNode *Pred, ExplodedNodeSet &Dst, EvalCallOptions &Options)

void evalEagerlyAssumeBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const Expr *Ex)

evalEagerlyAssumeBifurcation - Given the nodes in 'Src', eagerly assume concrete boolean values for '...

void VisitObjCAtSynchronizedStmt(const ObjCAtSynchronizedStmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Transfer function logic for ObjCAtSynchronizedStmts.

void VisitReturnStmt(const ReturnStmt *R, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitReturnStmt - Transfer function logic for return statements.

SVal evalBinOp(ProgramStateRef ST, BinaryOperator::Opcode Op, SVal LHS, SVal RHS, QualType T)

void VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst)

ProgramStateRef processRegionChange(ProgramStateRef state, const MemRegion *MR, const LocationContext *LCtx)

void VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitLambdaExpr - Transfer function logic for LambdaExprs.

void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred)

Definition ExprEngine.cpp:1296

void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitObjCForCollectionStmt - Transfer function logic for ObjCForCollectionStmt.

void VisitUnaryOperator(const UnaryOperator *B, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitUnaryOperator - Transfer function logic for unary operators.

ProgramStateRef getInitialState(const LocationContext *InitLoc)

getInitialState - Return the initial state used for the root vertex in the ExplodedGraph.

Definition ExprEngine.cpp:245

void VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *DR, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Transfer function logic for computing the lvalue of an Objective-C ivar.

static bool hasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)

Definition ExprEngine.cpp:2773

void VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitDeclStmt - Transfer function logic for DeclStmts.

void VisitMSAsmStmt(const MSAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitMSAsmStmt - Transfer function logic for MS inline asm.

Definition ExprEngine.cpp:3976

static std::optional< SVal > getObjectUnderConstruction(ProgramStateRef State, const ConstructionContextItem &Item, const LocationContext *LC)

By looking at a certain item that may be potentially part of an object's ConstructionContext,...

Definition ExprEngine.cpp:604

std::string DumpGraph(bool trim=false, StringRef Filename="")

Dump graph to the specified filename.

Definition ExprEngine.cpp:4091

void printJson(raw_ostream &Out, ProgramStateRef State, const LocationContext *LCtx, const char *NL, unsigned int Space, bool IsDot) const

printJson - Called by ProgramStateManager to print checker-specific data.

Definition ExprEngine.cpp:940

InliningModes

The modes of inlining, which override the default analysis-wide settings.

ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State, ArrayRef< std::pair< SVal, SVal > > LocAndVals, const LocationContext *LCtx, PointerEscapeKind Kind, const CallEvent *Call)

Call PointerEscape callback when a value escapes as a result of bind.

Definition ExprEngine.cpp:3628

const LocationContext * getRootLocationContext() const

static ProgramStateRef removeIterationState(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC)

Definition ExprEngine.cpp:2766

ProgramStateRef processAssume(ProgramStateRef state, SVal cond, bool assumption)

evalAssume - Callback function invoked by the ConstraintManager when making assumptions about state v...

Definition ExprEngine.cpp:668

AnalysisDeclContextManager & getAnalysisDeclContextManager()

static std::optional< unsigned > getIndexOfElementToConstruct(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)

Retreives which element is being constructed in a non-POD type array.

Definition ExprEngine.cpp:514

void VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitBlockExpr - Transfer function logic for BlockExprs.

void ProcessBaseDtor(const CFGBaseDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Definition ExprEngine.cpp:1491

static std::pair< const ProgramPointTag *, const ProgramPointTag * > getEagerlyAssumeBifurcationTags()

Definition ExprEngine.cpp:3876

void VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitCall - Transfer function for function calls.

ASTContext & getContext() const

getContext - Return the ASTContext associated with this analysis.

StoreManager & getStoreManager()

void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, ExplodedNode *Pred, ExplodedNodeSet &Dst)

void CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Create a C++ temporary object for an rvalue.

void VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitGCCAsmStmt - Transfer function logic for inline asm.

Definition ExprEngine.cpp:3939

BugReporter & getBugReporter()

void processCFGBlockEntrance(const BlockEdge &L, NodeBuilderWithSinks &nodeBuilder, ExplodedNode *Pred)

Called by CoreEngine when processing the entrance of a CFGBlock.

Definition ExprEngine.cpp:2554

ProgramStateRef processRegionChanges(ProgramStateRef state, const InvalidatedSymbols *invalidated, ArrayRef< const MemRegion * > ExplicitRegions, ArrayRef< const MemRegion * > Regions, const LocationContext *LCtx, const CallEvent *Call)

processRegionChanges - Called by ProgramStateManager whenever a change is made to the store.

Definition ExprEngine.cpp:674

void ProcessStmt(const Stmt *S, ExplodedNode *Pred)

Definition ExprEngine.cpp:1118

ConstCFGElementRef getCFGElementRef() const

ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr, SetOfConstDecls *VisitedCalleesIn, FunctionSummariesTy *FS, InliningModes HowToInlineIn)

Definition ExprEngine.cpp:222

void ViewGraph(bool trim=false)

Visualize the ExplodedGraph created by executing the simulation.

Definition ExprEngine.cpp:4081

static std::optional< unsigned > getPendingArrayDestruction(ProgramStateRef State, const LocationContext *LCtx)

Retreives which element is being destructed in a non-POD type array.

Definition ExprEngine.cpp:533

ProgramStateRef notifyCheckersOfPointerEscape(ProgramStateRef State, const InvalidatedSymbols *Invalidated, ArrayRef< const MemRegion * > ExplicitRegions, const CallEvent *Call, RegionAndSymbolInvalidationTraits &ITraits)

Call PointerEscape callback when a value escapes as a result of region invalidation.

Definition ExprEngine.cpp:3679

static const ProgramPointTag * cleanupNodeTag()

A tag to track convenience transitions, which can be removed at cleanup.

Definition ExprEngine.cpp:1113

void processCFGElement(const CFGElement E, ExplodedNode *Pred, unsigned StmtIdx, NodeBuilderContext *Ctx)

processCFGElement - Called by CoreEngine.

Definition ExprEngine.cpp:967

void processStaticInitializer(const DeclStmt *DS, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)

Called by CoreEngine.

void ConstructInitList(const Expr *Source, ArrayRef< Expr * > Args, bool IsTransparent, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Definition ExprEngine.cpp:4134

void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.

ProgramStateRef escapeValues(ProgramStateRef State, ArrayRef< SVal > Vs, PointerEscapeKind K, const CallEvent *Call=nullptr) const

A simple wrapper when you only need to notify checkers of pointer-escape of some values.

Definition ExprEngine.cpp:1689

void processBranch(const Stmt *Condition, NodeBuilderContext &BuilderCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF, std::optional< unsigned > IterationsCompletedInLoop)

ProcessBranch - Called by CoreEngine.

Definition ExprEngine.cpp:2830

void ProcessLoopExit(const Stmt *S, ExplodedNode *Pred)

Definition ExprEngine.cpp:1148

void processSwitch(SwitchNodeBuilder &builder)

ProcessSwitch - Called by CoreEngine.

Definition ExprEngine.cpp:3104

void processEndWorklist()

Called by CoreEngine when the analysis worklist has terminated.

Definition ExprEngine.cpp:961

CheckerManager & getCheckerManager() const

SymbolManager & getSymbolManager()

void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitAtomicExpr - Transfer function for builtin atomic expressions.

Definition ExprEngine.cpp:3585

MemRegionManager & getRegionManager()

void ProcessMemberDtor(const CFGMemberDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Definition ExprEngine.cpp:1511

void VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, ExplodedNodeSet &Dst)

void VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, ExplodedNode *Pred, ExplodedNodeSet &Dst)

void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitMemberExpr - Transfer function for member expressions.

Definition ExprEngine.cpp:3497

void VisitCXXConstructExpr(const CXXConstructExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)

void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)

bool didEagerlyAssumeBifurcateAt(ProgramStateRef State, const Expr *Ex) const

Definition ExprEngine.cpp:3934

ConstraintManager & getConstraintManager()

void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, NodeBuilderContext &BldCtx, ExplodedNode *Pred, ExplodedNodeSet &Dst, const CFGBlock *DstT, const CFGBlock *DstF)

Called by CoreEngine.

Definition ExprEngine.cpp:1646

void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Definition ExprEngine.cpp:1343

void VisitOffsetOfExpr(const OffsetOfExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitOffsetOfExpr - Transfer function for offsetof.

void evalLoad(ExplodedNodeSet &Dst, const Expr *NodeEx, const Expr *BoundExpr, ExplodedNode *Pred, ProgramStateRef St, SVal location, const ProgramPointTag *tag=nullptr, QualType LoadTy=QualType())

Simulate a read of the result of Ex.

Definition ExprEngine.cpp:3802

void removeDeadOnEndOfFunction(NodeBuilderContext &BC, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Remove dead bindings/symbols before exiting a function.

void Visit(const Stmt *S, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Visit - Transfer function logic for all statements.

Definition ExprEngine.cpp:1716

AnalysisManager & getAnalysisManager()

ExplodedGraph & getGraph()

void runCheckersForBlockEntrance(const NodeBuilderContext &BldCtx, const BlockEntrance &Entrance, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Definition ExprEngine.cpp:2636

void ProcessDeleteDtor(const CFGDeleteDtor D, ExplodedNode *Pred, ExplodedNodeSet &Dst)

Definition ExprEngine.cpp:1415

void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, ExplodedNodeSet &Dst)

void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitCompoundLiteralExpr - Transfer function logic for compound literals.

SValBuilder & getSValBuilder()

void VisitArrayInitLoopExpr(const ArrayInitLoopExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitArrayInitLoopExpr - Transfer function for array init loop.

Definition ExprEngine.cpp:3348

void evalStore(ExplodedNodeSet &Dst, const Expr *AssignE, const Expr *StoreE, ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, const ProgramPointTag *tag=nullptr)

evalStore - Handle the semantics of a store via an assignment.

Definition ExprEngine.cpp:3779

void VisitAttributedStmt(const AttributedStmt *A, ExplodedNode *Pred, ExplodedNodeSet &Dst)

VisitAttributedStmt - Transfer function logic for AttributedStmt.

void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, ExplodedNodeSet &PreVisit, ExplodedNodeSet &Dst)

Definition ExprEngine.cpp:1662

void processIndirectGoto(IndirectGotoNodeBuilder &builder)

processIndirectGoto - Called by CoreEngine.

Definition ExprEngine.cpp:2982

const NodeBuilderContext & getBuilderContext()

static ProgramStateRef setWhetherHasMoreIteration(ProgramStateRef State, const ObjCForCollectionStmt *O, const LocationContext *LC, bool HasMoreIteraton)

Note whether this loop has any more iterations to model. These methods.

Definition ExprEngine.cpp:2758

static std::optional< unsigned > getPendingInitLoop(ProgramStateRef State, const CXXConstructExpr *E, const LocationContext *LCtx)

Retreives the size of the array in the pending ArrayInitLoopExpr.

Definition ExprEngine.cpp:487

void ProcessNewAllocator(const CXXNewExpr *NE, ExplodedNode *Pred)

Definition ExprEngine.cpp:1323

const Expr * getTarget() const

const LocationContext * getLocationContext() const

ProgramStateRef getState() const

ExplodedNode * generateNode(const iterator &I, ProgramStateRef State, bool isSink=false)

static bool isLocType(QualType T)

MemRegion - The root abstract class for all memory regions.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace(ProgramStateRef State) const

Returns the most specific memory space for this memory region in the given ProgramStateRef.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const

MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...

const CFGBlock * getBlock() const

Return the CFGBlock associated with this builder.

unsigned blockCount() const

Returns the number of times the current basic block has been visited on the exploded graph path.

This node builder keeps track of the generated sink nodes.

ExplodedNode * generateNode(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)

ExplodedNode * generateSink(ProgramStateRef State, ExplodedNode *Pred, const ProgramPointTag *Tag=nullptr)

This is the simplest builder which generates nodes in the ExplodedGraph.

ExplodedNode * generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)

Generates a node in the ExplodedGraph.

void takeNodes(const ExplodedNodeSet &S)

ExplodedNode * generateSink(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred)

Generates a sink in the ExplodedGraph.

void addNodes(const ExplodedNodeSet &S)

const NodeBuilderContext & getContext()

While alive, includes the current analysis stack in a crash trace.

Information about invalidation for a particular region/symbol.

nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)

loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC)

Return a memory region for the 'this' object reference.

DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, ConstCFGElementRef elem, const LocationContext *LCtx, unsigned count)

Create a new symbol with a unique 'name'.

SVal - This represents a symbolic expression, which can be either an L-value or an R-value.

bool isUnknownOrUndef() const

std::optional< T > getAs() const

Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.

const MemRegion * getAsRegion() const

T castAs() const

Convert to the specified SVal type, asserting that this SVal is of the desired type.

This builder class is useful for generating nodes that resulted from visiting a statement.

ExplodedNode * generateNode(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)

ExplodedNode * generateSink(const Stmt *S, ExplodedNode *Pred, ProgramStateRef St, const ProgramPointTag *tag=nullptr, ProgramPoint::Kind K=ProgramPoint::PostStmtKind)

SVal evalDerivedToBase(SVal Derived, const CastExpr *Cast)

Evaluates a chain of derived-to-base casts through the path specified in Cast.

virtual SVal getLValueField(const FieldDecl *D, SVal Base)

SubRegion - A region that subsets another larger region.

ProgramStateRef getState() const

const Expr * getCondition() const

ExplodedNode * generateDefaultCaseNode(ProgramStateRef State, bool isSink=false)

ExplodedNode * generateCaseStmtNode(const iterator &I, ProgramStateRef State)

const LocationContext * getLocationContext() const

const SwitchStmt * getSwitch() const

A class responsible for cleaning up unused symbols.

void markLive(SymbolRef sym)

Unconditionally marks a symbol as live.

SymbolicRegion - A special, "non-concrete" region.

Represents symbolic expression that isn't a location.

const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl

Matches variable declarations.

const internal::VariadicAllOfMatcher< Decl > decl

Matches declarations.

PointerEscapeKind

Describes the different reasons a pointer escapes during analysis.

@ PSK_DirectEscapeOnCall

The pointer has been passed to a function call directly.

@ PSK_EscapeOnBind

A pointer escapes due to binding its value to a location that the analyzer cannot track.

@ PSK_IndirectEscapeOnCall

The pointer has been passed to a function indirectly.

@ PSK_EscapeOther

The reason for pointer escape is unknown.

DefinedOrUnknownSVal getDynamicElementCount(ProgramStateRef State, const MemRegion *MR, SValBuilder &SVB, QualType Ty)

llvm::DenseSet< const Decl * > SetOfConstDecls

llvm::DenseSet< SymbolRef > InvalidatedSymbols

IntrusiveRefCntPtr< const ProgramState > ProgramStateRef

const SymExpr * SymbolRef

ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State)

Updates the given ProgramState.

bool isUnrolledState(ProgramStateRef State)

Returns if the given State indicates that is inside a completely unrolled loop.

void markAllDynamicExtentLive(ProgramStateRef State, SymbolReaper &SymReaper)

ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, const LocationContext *LCtx, unsigned BlockCount, ConstCFGElementRef Elem)

Get the states that result from widening the loop.

ProgramStateRef updateLoopStack(const Stmt *LoopStmt, ASTContext &ASTCtx, ExplodedNode *Pred, unsigned maxVisitOnPath)

Updates the stack of loops contained by the ProgramState.

bool LE(InterpState &S, CodePtr OpPC)

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

bool isa(CodeGen::Address addr)

bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)

nullptr

This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...

bool operator<(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)

StorageDuration

The storage duration for an object (per C++ [basic.stc]).

@ SD_Thread

Thread storage duration.

@ SD_Static

Static storage duration.

@ SD_FullExpression

Full-expression storage duration (for temporaries).

@ Result

The result type of a method or function.

const FunctionProtoType * T

U cast(CodeGen::Address addr)

@ Class

The "class" keyword introduces the elaborated-type-specifier.

Expr * extractElementInitializerFromNestedAILE(const ArrayInitLoopExpr *AILE)

@ CXXThis

Parameter for C++ 'this' argument.

Diagnostic wrappers for TextAPI types for error reporting.

Describes how types, statements, expressions, and declarations should be printed.

@ DerivedToBaseAdjustment

@ MemberPointerAdjustment

Hints for figuring out of a call should be inlined during evalCall().

bool IsTemporaryCtorOrDtor

This call is a constructor or a destructor of a temporary value.

bool IsArrayCtorOrDtor

This call is a constructor or a destructor for a single element within an array, a part of array cons...

Traits for storing the call processing policy inside GDM.

DOTGraphTraits(bool isSimple=false)

Definition ExprEngine.cpp:3990

static std::string getNodeLabel(const ExplodedNode *N, ExplodedGraph *G)

Definition ExprEngine.cpp:4037

static bool nodeHasBugReport(const ExplodedNode *N)

Definition ExprEngine.cpp:3992

static bool traverseHiddenNodes(const ExplodedNode *N, llvm::function_ref< void(const ExplodedNode *)> PreCallback, llvm::function_ref< void(const ExplodedNode *)> PostCallback, llvm::function_ref< bool(const ExplodedNode *)> Stop)

PreCallback: callback before break.

Definition ExprEngine.cpp:4014

static bool isNodeHidden(const ExplodedNode *N, const ExplodedGraph *G)

Definition ExprEngine.cpp:4033