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/ADT/Statistic.h"

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

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

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

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

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

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

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

78#include

79#include

80#include

81#include

82#include

83#include

84#include

85#include

86

87using namespace clang;

88using namespace ento;

89

90#define DEBUG_TYPE "ExprEngine"

91

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

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

96 "a top level function");

97STATISTIC(NumMaxBlockCountReachedInInlined,

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

99 "an inlined function");

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

102

103

104

105

106

107namespace {

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122class ConstructedObjectKey {

123 using ConstructedObjectKeyImpl =

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

125 const ConstructedObjectKeyImpl Impl;

126

127public:

130 : Impl(Item, LC) {}

131

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

134

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

137 }

138

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

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

143 if (!S)

144 I = getItem().getCXXCtorInitializer();

145

146 if (S)

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

148 else

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

150

151

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

153 << "\", \"argument_index\": ";

154

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

157 else

158 Out << "null";

159

160

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

162

163 if (S) {

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

165 } else {

167 }

168 }

169

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

171 ID.Add(Impl.first);

172 ID.AddPointer(Impl.second);

173 }

174

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

176 return Impl == RHS.Impl;

177 }

178

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

180 return Impl < RHS.Impl;

181 }

182};

183}

184

185typedef llvm::ImmutableMap<ConstructedObjectKey, SVal>

189

190

191

192

193

194

195

196typedef llvm::ImmutableMap<

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

198 IndexOfElementToConstructMap;

200 IndexOfElementToConstructMap)

201

202

203

204

205typedef llvm::ImmutableMap<

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

207 PendingInitLoopMap;

209

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

214

215

216

217

218

219static const char* TagProviderName = "ExprEngine";

220

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

225 AMgr(mgr), AnalysisDeclContexts(mgr.getAnalysisDeclContextManager()),

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

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

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

229 SymMgr(StateMgr.getSymbolManager()), MRMgr(StateMgr.getRegionManager()),

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

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

232 HowToInline(HowToInlineIn) {

233 unsigned TrimInterval = mgr.options.GraphTrimInterval;

234 if (TrimInterval != 0) {

235

237 }

238}

239

240

241

242

243

247

248

249

250

251 do {

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

253

254

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

257 break;

258

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

261 const auto *BT = dyn_cast(T);

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

263 break;

264

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

266 if (!R)

267 break;

268

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

273

274 std::optional Constraint =

276

277 if (!Constraint)

278 break;

279

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

281 state = newState;

282 }

283 break;

284 }

285 while (false);

286

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

288

289

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

293

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

295

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

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

298 }

299 }

300

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

302 if (MD->isImplicitObjectMemberFunction()) {

303

304

305

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

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

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

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

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

313 }

314 }

315 }

316 }

317

318 return state;

319}

320

321ProgramStateRef ExprEngine::createTemporaryRegionIfNeeded(

324 const SubRegion **OutRegionWithAdjustments) {

325

326

327

328

329

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

332

333

334 if (!isa(InitValWithAdjustments)) {

335 if (OutRegionWithAdjustments)

336 *OutRegionWithAdjustments = nullptr;

337 return State;

338 }

339 Result = InitWithAdjustments;

340 } else {

341

342

343 assert(!isa(InitValWithAdjustments) ||

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

346 }

347

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

375

377 CommaLHSs, Adjustments);

378

379

380

381

382

383

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

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

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

389 return State;

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

393

394

397 } else {

399 }

400 } else {

403 }

404 } else {

406 }

407

409 SVal BaseReg = Reg;

410

411

413 switch (Adj.Kind) {

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

416 break;

419 break;

421

422 State = State->invalidateRegions(Reg, InitWithAdjustments,

424 nullptr, nullptr, nullptr);

425 return State;

426 }

427 }

428

429

430

431

432

433

434

435

436

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

441 State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);

442

443

444

445 if (InitValWithAdjustments.isUnknown()) {

446

447

451 }

452 State =

453 State->bindLoc(Reg.castAs<Loc>(), InitValWithAdjustments, LC, false);

454 } else {

455 State = State->bindLoc(BaseReg.castAs<Loc>(), InitVal, LC, false);

456 }

457

458

459

460

461 if (Result->isGLValue()) {

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

463 } else {

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

465 }

466

467

469

470 if (OutRegionWithAdjustments)

471 *OutRegionWithAdjustments = cast(Reg.getAsRegion());

472 return State;

473}

474

479

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

481

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

483}

484

485std::optional

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

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

490}

491

496

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

498 return State->remove(Key);

499}

500

504 unsigned Size) {

506

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

508

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

510}

511

512std::optional

516 const unsigned *V =

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

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

519}

520

522ExprEngine::removeIndexOfElementToConstruct(ProgramStateRef State,

526

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

528 return State->remove(Key);

529}

530

531std::optional

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

535

536 const unsigned *V =

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

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

539}

540

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

544

546

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

548}

549

551ExprEngine::removePendingArrayDestruction(ProgramStateRef State,

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

554

556

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

558 return State->remove(Key);

559}

560

562ExprEngine::addObjectUnderConstruction(ProgramStateRef State,

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

566

568

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

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

571 Init = VD->getInit();

572 }

573

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

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

576

579

580

581

582

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

585

586

587

588

589

590

591

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

593 Key.getItem().getKind() ==

595 State->contains(

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

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

598 "supposed to!");

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

600}

601

602std::optional

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

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

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

609}

610

612ExprEngine::finishObjectConstruction(ProgramStateRef State,

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

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

617 return State->remove(Key);

618}

619

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

624

625

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

627}

628

630ExprEngine::cleanupElidedDestructor(ProgramStateRef State,

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

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

635 return State->remove(Key);

636}

637

638bool ExprEngine::isDestructorElided(ProgramStateRef State,

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

642 return State->contains(Key);

643}

644

645bool ExprEngine::areAllObjectsFullyConstructed(ProgramStateRef State,

649 while (LC != ToLC) {

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

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

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

653 return false;

654

656 }

657 return true;

658}

659

660

661

662

663

664

665

666

668 SVal cond, bool assumption) {

670}

671

680 Explicits, Regions,

682}

683

684static void

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

690

691 ++Space;

692 bool HasItem = false;

693

694

695 const ConstructedObjectKey *LastKey = nullptr;

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

697 const ConstructedObjectKey &Key = I.first;

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

699 continue;

700

701 if (!HasItem) {

702 Out << '[' << NL;

703 HasItem = true;

704 }

705

706 LastKey = &Key;

707 }

708

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

710 const ConstructedObjectKey &Key = I.first;

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

713 continue;

714

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

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

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

718

719 if (&Key != LastKey)

720 Out << ',';

721 Out << NL;

722 }

723

724 if (HasItem)

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

726 else {

727 Out << "null ";

728 }

729}

730

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

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

735

738

739 ++Space;

740 bool HasItem = false;

741

742

743 KeyT LastKey;

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

745 const KeyT &Key = I.first;

746 if (Key.second != LCtx)

747 continue;

748

749 if (!HasItem) {

750 Out << '[' << NL;

751 HasItem = true;

752 }

753

754 LastKey = Key;

755 }

756

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

758 const KeyT &Key = I.first;

759 unsigned Value = I.second;

760 if (Key.second != LCtx)

761 continue;

762

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

764

765

766 const Expr *E = Key.first;

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

768

769

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

771

772

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

777 Out << "'\"";

778

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

780

781 if (Key != LastKey)

782 Out << ',';

783 Out << NL;

784 }

785

786 if (HasItem)

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

788 else {

789 Out << "null ";

790 }

791}

792

794 const char *NL,

796 unsigned int Space = 0,

797 bool IsDot = false) {

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

799

802

803 ++Space;

804 bool HasItem = false;

805

806

807 KeyT LastKey;

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

809 const KeyT &Key = I.first;

810 if (Key.second != LCtx)

811 continue;

812

813 if (!HasItem) {

814 Out << '[' << NL;

815 HasItem = true;

816 }

817

818 LastKey = Key;

819 }

820

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

822 const KeyT &Key = I.first;

823 unsigned Value = I.second;

824 if (Key.second != LCtx)

825 continue;

826

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

828

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

831

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

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

837 Out << "'\"";

838

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

840

841 if (Key != LastKey)

842 Out << ',';

843 Out << NL;

844 }

845

846 if (HasItem)

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

848 else {

849 Out << "null ";

850 }

851}

852

853static void

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

858

859 ++Space;

860 bool HasItem = false;

861

862

863 KeyT LastKey = nullptr;

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

865 const KeyT &Key = I.first;

866 if (Key != LCtx)

867 continue;

868

869 if (!HasItem) {

870 Out << '[' << NL;

871 HasItem = true;

872 }

873

874 LastKey = Key;

875 }

876

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

878 const KeyT &Key = I.first;

879 if (Key != LCtx)

880 continue;

881

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

883

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

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

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

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

888

889 if (Key != LastKey)

890 Out << ',';

891 Out << NL;

892 }

893

894 if (HasItem)

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

896 else {

897 Out << "null ";

898 }

899}

900

901

902

903

904

905

906

907

908

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

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

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

914

915 using RequiredType =

918

919

920

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

922 "Printer is not a function!");

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

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

925

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

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

928 ++Space;

929 Out << '[' << NL;

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

932 });

933

934 --Space;

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

936 }

937}

938

941 unsigned int Space, bool IsDot) const {

942

943 printStateTraitWithLocationContextJson(

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

946 printStateTraitWithLocationContextJson(

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

949 printStateTraitWithLocationContextJson(

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

952 printStateTraitWithLocationContextJson(

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

955

957 IsDot);

958}

959

961

964}

965

969 currStmtIdx = StmtIdx;

970 currBldrCtx = Ctx;

971

972 switch (E.getKind()) {

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

1016 if (!isa(S))

1017 return true;

1018

1019

1021 return true;

1022

1023

1024

1027}

1028

1030 const Stmt *ReferenceStmt,

1032 const Stmt *DiagnosticStmt,

1035 ReferenceStmt == nullptr || isa(ReferenceStmt))

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

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

1038

1039 if (!DiagnosticStmt) {

1040 DiagnosticStmt = ReferenceStmt;

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

1042 }

1043

1044 NumRemoveDeadBindings++;

1046

1047

1048

1049

1050 if (!ReferenceStmt) {

1052 "Use PostStmtPurgeDeadSymbolsKind for clearing a LocationContext");

1054 }

1055

1058

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

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

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

1064 }

1065

1067

1068

1069

1070

1072 CleanedState, SFC, SymReaper);

1073

1074

1075

1076

1079 DiagnosticStmt, *this, K);

1080

1081

1082

1083

1085 for (const auto I : CheckedSet) {

1087

1088

1089 CheckerState =

1091

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

1094 "checkDeadSymbols processing.");

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

1097 "checkDeadSymbols processing.");

1098

1099

1100

1104 }

1105}

1106

1109 return &cleanupTag;

1110}

1111

1113

1115

1118 "Error evaluating statement");

1119

1120

1124 removeDead(Pred, CleanedStates, currStmt,

1126 } else

1127 CleanedStates.Add(Pred);

1128

1129

1131 for (const auto I : CleanedStates) {

1133

1134 Visit(currStmt, I, DstI);

1136 }

1137

1138

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

1140}

1141

1144 S->getBeginLoc(),

1145 "Error evaluating end of the loop");

1147 Dst.Add(Pred);

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

1150

1151 if(AMgr.options.ShouldUnrollLoops)

1153

1156

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

1158}

1159

1165

1168 "Error evaluating initializer");

1169

1170

1171 const auto *stackFrame = cast(Pred->getLocationContext());

1172 const auto *decl = cast(stackFrame->getDecl());

1173

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

1176

1178 SVal FieldLoc;

1179

1180

1182

1183

1185

1186

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

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

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

1191 } else {

1196 } else {

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

1199 }

1200

1201 SVal InitVal;

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

1203

1204

1206 while ((ASE = dyn_cast(Init)))

1208

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

1210

1211

1215 Field->getType(),

1217 }

1218 } else {

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

1220 }

1221

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

1224 }

1226

1227

1228

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

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

1233 } else {

1236

1237 }

1238

1239

1240

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

1244 for (const auto I : Tmp) {

1247 }

1248

1249

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

1251}

1252

1253std::pair<ProgramStateRef, uint64_t>

1254ExprEngine::prepareStateForArrayDestruction(const ProgramStateRef State,

1258 SVal *ElementCountVal) {

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

1260

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

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

1264

1266

1267 if (ElementCountVal)

1268 *ElementCountVal = ElementCount;

1269

1270

1271 unsigned Idx = 0;

1273 Idx = *OptionalIdx;

1274 } else {

1275

1276 if (!ElementCount.isConstant())

1277 return {State, 0};

1278

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

1280 }

1281

1282 if (Idx == 0)

1283 return {State, 0};

1284

1285 --Idx;

1286

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

1288}

1289

1296 break;

1299 break;

1302 break;

1305 break;

1308 break;

1309 default:

1310 llvm_unreachable("Unexpected dtor kind.");

1311 }

1312

1313

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

1315}

1316

1322

1323

1324

1325 if (Opts.MayInlineCXXAllocator)

1327 else {

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

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

1333 }

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

1335}

1336

1343

1346

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

1349

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

1352 if (!ValueRegion) {

1353

1354

1355

1356

1357 return;

1358 }

1360 varType = cast(Region)->getValueType();

1361 }

1362

1363 unsigned Idx = 0;

1364 if (isa(varType)) {

1365 SVal ElementCount;

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

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

1368

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

1371 assert(ArrayLength &&

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

1373

1374

1375 if (!ArrayLength) {

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

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

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

1383 return;

1384 }

1385 }

1386 }

1387

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

1392

1394

1396 "Prepare for object destruction");

1398 &PT);

1400

1401 if (!Pred)

1402 return;

1404

1406 false, Pred, Dst, CallOpts);

1407}

1408

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

1418

1419

1420

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

1425

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

1429 return;

1430 }

1431

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

1435 };

1436

1437 unsigned Idx = 0;

1440

1443

1445 DTy = AT->getElementType();

1446

1447 if (ArgR) {

1448 SVal ElementCount;

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

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

1451

1452

1453

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

1456

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

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

1463 return;

1464 }

1465

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

1467 .getAsRegion();

1468 }

1469 }

1470

1473 "Prepare for object destruction");

1477

1478 if (!Pred)

1479 return;

1481

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

1483}

1484

1488

1489 const auto *CurDtor = cast(LCtx->getDecl());

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

1493

1494

1498 Base->isVirtual());

1499

1502 true, Pred, Dst, CallOpts);

1503}

1504

1507 const auto *DtorDecl = D.getDestructorDecl(getContext());

1512

1513 const auto *CurDtor = cast(LCtx->getDecl());

1514 Loc ThisStorageLoc =

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

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

1518

1519 unsigned Idx = 0;

1520 if (isa(T)) {

1521 SVal ElementCount;

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

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

1524

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

1527 assert(ArrayLength &&

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

1529

1530

1531 if (!ArrayLength) {

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

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

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

1539 return;

1540 }

1541 }

1542 }

1543

1545 FieldVal =

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

1547

1549

1551 "Prepare for object destruction");

1553 &PT);

1555

1556 if (!Pred)

1557 return;

1559

1561 false, Pred, Dst, CallOpts);

1562}

1563

1571

1574

1575

1576

1577 State = finishObjectConstruction(State, D.getBindTemporaryExpr(),

1579 MR = V->getAsRegion();

1580 }

1581

1582

1583

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

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

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

1591 return;

1592 }

1593

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

1596 StmtBldr.generateNode(D.getBindTemporaryExpr(), Pred, State);

1597

1598 QualType T = D.getBindTemporaryExpr()->getSubExpr()->getType();

1599

1600

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

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

1604

1607 if (!MR) {

1608

1609

1610

1611

1612

1613

1614

1615

1616

1617

1618

1619

1620

1621

1622

1623

1624

1626 T = AT->getElementType();

1627

1628

1629

1630 }

1631 } else {

1632

1633

1634

1635 }

1637 false, CleanPred, Dst, CallOpts);

1638}

1639

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

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

1651 } else {

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

1653 }

1654}

1655

1659

1660

1661

1662 if (getAnalysisManager().options.ShouldIncludeTemporaryDtorsInCFG) {

1663

1664

1665 Dst = PreVisit;

1666 return;

1667 }

1673

1674

1675

1676

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

1678 }

1680 }

1681}

1682

1687 class CollectReachableSymbolsCallback final : public SymbolVisitor {

1689

1690 public:

1691 explicit CollectReachableSymbolsCallback(InvalidatedSymbols &Symbols)

1692 : Symbols(Symbols) {}

1693

1695

1696 bool VisitSymbol(SymbolRef Sym) override {

1697 Symbols.insert(Sym);

1698 return true;

1699 }

1700 };

1702 CollectReachableSymbolsCallback CallBack(Symbols);

1703 for (SVal V : Vs)

1704 State->scanReachableSymbols(V, CallBack);

1705

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

1708}

1709

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

1716

1717 assert(!isa(S) || S == cast(S)->IgnoreParens());

1718

1719 switch (S->getStmtClass()) {

1720

1721 case Stmt::CXXDependentScopeMemberExprClass:

1722 case Stmt::CXXTryStmtClass:

1723 case Stmt::CXXTypeidExprClass:

1724 case Stmt::CXXUuidofExprClass:

1725 case Stmt::CXXFoldExprClass:

1726 case Stmt::MSPropertyRefExprClass:

1727 case Stmt::MSPropertySubscriptExprClass:

1728 case Stmt::CXXUnresolvedConstructExprClass:

1729 case Stmt::DependentScopeDeclRefExprClass:

1730 case Stmt::ArrayTypeTraitExprClass:

1731 case Stmt::ExpressionTraitExprClass:

1732 case Stmt::UnresolvedLookupExprClass:

1733 case Stmt::UnresolvedMemberExprClass:

1734 case Stmt::TypoExprClass:

1735 case Stmt::RecoveryExprClass:

1736 case Stmt::CXXNoexceptExprClass:

1737 case Stmt::PackExpansionExprClass:

1738 case Stmt::PackIndexingExprClass:

1739 case Stmt::SubstNonTypeTemplateParmPackExprClass:

1740 case Stmt::FunctionParmPackExprClass:

1741 case Stmt::CoroutineBodyStmtClass:

1742 case Stmt::CoawaitExprClass:

1743 case Stmt::DependentCoawaitExprClass:

1744 case Stmt::CoreturnStmtClass:

1745 case Stmt::CoyieldExprClass:

1746 case Stmt::SEHTryStmtClass:

1747 case Stmt::SEHExceptStmtClass:

1748 case Stmt::SEHLeaveStmtClass:

1749 case Stmt::SEHFinallyStmtClass:

1750 case Stmt::OMPCanonicalLoopClass:

1751 case Stmt::OMPParallelDirectiveClass:

1752 case Stmt::OMPSimdDirectiveClass:

1753 case Stmt::OMPForDirectiveClass:

1754 case Stmt::OMPForSimdDirectiveClass:

1755 case Stmt::OMPSectionsDirectiveClass:

1756 case Stmt::OMPSectionDirectiveClass:

1757 case Stmt::OMPScopeDirectiveClass:

1758 case Stmt::OMPSingleDirectiveClass:

1759 case Stmt::OMPMasterDirectiveClass:

1760 case Stmt::OMPCriticalDirectiveClass:

1761 case Stmt::OMPParallelForDirectiveClass:

1762 case Stmt::OMPParallelForSimdDirectiveClass:

1763 case Stmt::OMPParallelSectionsDirectiveClass:

1764 case Stmt::OMPParallelMasterDirectiveClass:

1765 case Stmt::OMPParallelMaskedDirectiveClass:

1766 case Stmt::OMPTaskDirectiveClass:

1767 case Stmt::OMPTaskyieldDirectiveClass:

1768 case Stmt::OMPBarrierDirectiveClass:

1769 case Stmt::OMPTaskwaitDirectiveClass:

1770 case Stmt::OMPErrorDirectiveClass:

1771 case Stmt::OMPTaskgroupDirectiveClass:

1772 case Stmt::OMPFlushDirectiveClass:

1773 case Stmt::OMPDepobjDirectiveClass:

1774 case Stmt::OMPScanDirectiveClass:

1775 case Stmt::OMPOrderedDirectiveClass:

1776 case Stmt::OMPAtomicDirectiveClass:

1777 case Stmt::OMPAssumeDirectiveClass:

1778 case Stmt::OMPTargetDirectiveClass:

1779 case Stmt::OMPTargetDataDirectiveClass:

1780 case Stmt::OMPTargetEnterDataDirectiveClass:

1781 case Stmt::OMPTargetExitDataDirectiveClass:

1782 case Stmt::OMPTargetParallelDirectiveClass:

1783 case Stmt::OMPTargetParallelForDirectiveClass:

1784 case Stmt::OMPTargetUpdateDirectiveClass:

1785 case Stmt::OMPTeamsDirectiveClass:

1786 case Stmt::OMPCancellationPointDirectiveClass:

1787 case Stmt::OMPCancelDirectiveClass:

1788 case Stmt::OMPTaskLoopDirectiveClass:

1789 case Stmt::OMPTaskLoopSimdDirectiveClass:

1790 case Stmt::OMPMasterTaskLoopDirectiveClass:

1791 case Stmt::OMPMaskedTaskLoopDirectiveClass:

1792 case Stmt::OMPMasterTaskLoopSimdDirectiveClass:

1793 case Stmt::OMPMaskedTaskLoopSimdDirectiveClass:

1794 case Stmt::OMPParallelMasterTaskLoopDirectiveClass:

1795 case Stmt::OMPParallelMaskedTaskLoopDirectiveClass:

1796 case Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass:

1797 case Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass:

1798 case Stmt::OMPDistributeDirectiveClass:

1799 case Stmt::OMPDistributeParallelForDirectiveClass:

1800 case Stmt::OMPDistributeParallelForSimdDirectiveClass:

1801 case Stmt::OMPDistributeSimdDirectiveClass:

1802 case Stmt::OMPTargetParallelForSimdDirectiveClass:

1803 case Stmt::OMPTargetSimdDirectiveClass:

1804 case Stmt::OMPTeamsDistributeDirectiveClass:

1805 case Stmt::OMPTeamsDistributeSimdDirectiveClass:

1806 case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:

1807 case Stmt::OMPTeamsDistributeParallelForDirectiveClass:

1808 case Stmt::OMPTargetTeamsDirectiveClass:

1809 case Stmt::OMPTargetTeamsDistributeDirectiveClass:

1810 case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:

1811 case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:

1812 case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:

1813 case Stmt::OMPReverseDirectiveClass:

1814 case Stmt::OMPTileDirectiveClass:

1815 case Stmt::OMPInterchangeDirectiveClass:

1816 case Stmt::OMPInteropDirectiveClass:

1817 case Stmt::OMPDispatchDirectiveClass:

1818 case Stmt::OMPMaskedDirectiveClass:

1819 case Stmt::OMPGenericLoopDirectiveClass:

1820 case Stmt::OMPTeamsGenericLoopDirectiveClass:

1821 case Stmt::OMPTargetTeamsGenericLoopDirectiveClass:

1822 case Stmt::OMPParallelGenericLoopDirectiveClass:

1823 case Stmt::OMPTargetParallelGenericLoopDirectiveClass:

1824 case Stmt::CapturedStmtClass:

1825 case Stmt::SYCLKernelCallStmtClass:

1826 case Stmt::OpenACCComputeConstructClass:

1827 case Stmt::OpenACCLoopConstructClass:

1828 case Stmt::OpenACCCombinedConstructClass:

1829 case Stmt::OpenACCDataConstructClass:

1830 case Stmt::OpenACCEnterDataConstructClass:

1831 case Stmt::OpenACCExitDataConstructClass:

1832 case Stmt::OpenACCHostDataConstructClass:

1833 case Stmt::OpenACCWaitConstructClass:

1834 case Stmt::OpenACCInitConstructClass:

1835 case Stmt::OpenACCShutdownConstructClass:

1836 case Stmt::OpenACCSetConstructClass:

1837 case Stmt::OpenACCUpdateConstructClass:

1838 case Stmt::OMPUnrollDirectiveClass:

1839 case Stmt::OMPMetaDirectiveClass:

1840 case Stmt::HLSLOutArgExprClass: {

1843 break;

1844 }

1845

1846 case Stmt::ParenExprClass:

1847 llvm_unreachable("ParenExprs already handled.");

1848 case Stmt::GenericSelectionExprClass:

1849 llvm_unreachable("GenericSelectionExprs already handled.");

1850

1851

1852 case Stmt::BreakStmtClass:

1853 case Stmt::CaseStmtClass:

1854 case Stmt::CompoundStmtClass:

1855 case Stmt::ContinueStmtClass:

1856 case Stmt::CXXForRangeStmtClass:

1857 case Stmt::DefaultStmtClass:

1858 case Stmt::DoStmtClass:

1859 case Stmt::ForStmtClass:

1860 case Stmt::GotoStmtClass:

1861 case Stmt::IfStmtClass:

1862 case Stmt::IndirectGotoStmtClass:

1863 case Stmt::LabelStmtClass:

1865 case Stmt::NullStmtClass:

1866 case Stmt::SwitchStmtClass:

1867 case Stmt::WhileStmtClass:

1868 case Expr::MSDependentExistsStmtClass:

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

1870 case Stmt::ImplicitValueInitExprClass:

1871

1872

1873

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

1875

1876 case Stmt::ObjCSubscriptRefExprClass:

1877 case Stmt::ObjCPropertyRefExprClass:

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

1879

1880 case Stmt::GNUNullExprClass: {

1881

1883 state = state->BindExpr(

1887 break;

1888 }

1889

1890 case Stmt::ObjCAtSynchronizedStmtClass:

1894 break;

1895

1896 case Expr::ConstantExprClass:

1897 case Stmt::ExprWithCleanupsClass:

1898

1899 break;

1900

1901 case Stmt::CXXBindTemporaryExprClass: {

1909 break;

1910 }

1911

1912 case Stmt::ArrayInitLoopExprClass:

1916 break;

1917

1918 case Stmt::DesignatedInitExprClass:

1919 case Stmt::DesignatedInitUpdateExprClass:

1920 case Stmt::ArrayInitIndexExprClass:

1921 case Stmt::ExtVectorElementExprClass:

1922 case Stmt::ImaginaryLiteralClass:

1923 case Stmt::ObjCAtCatchStmtClass:

1924 case Stmt::ObjCAtFinallyStmtClass:

1925 case Stmt::ObjCAtTryStmtClass:

1926 case Stmt::ObjCAutoreleasePoolStmtClass:

1927 case Stmt::ObjCEncodeExprClass:

1928 case Stmt::ObjCIsaExprClass:

1929 case Stmt::ObjCProtocolExprClass:

1930 case Stmt::ObjCSelectorExprClass:

1931 case Stmt::ParenListExprClass:

1932 case Stmt::ShuffleVectorExprClass:

1933 case Stmt::ConvertVectorExprClass:

1934 case Stmt::VAArgExprClass:

1935 case Stmt::CUDAKernelCallExprClass:

1936 case Stmt::OpaqueValueExprClass:

1937 case Stmt::AsTypeExprClass:

1938 case Stmt::ConceptSpecializationExprClass:

1939 case Stmt::CXXRewrittenBinaryOperatorClass:

1940 case Stmt::RequiresExprClass:

1941 case Expr::CXXParenListInitExprClass:

1942 case Stmt::EmbedExprClass:

1943

1944

1945

1946

1947 case Stmt::PredefinedExprClass:

1948 case Stmt::AddrLabelExprClass:

1949 case Stmt::AttributedStmtClass:

1950 case Stmt::IntegerLiteralClass:

1951 case Stmt::FixedPointLiteralClass:

1952 case Stmt::CharacterLiteralClass:

1953 case Stmt::CXXScalarValueInitExprClass:

1954 case Stmt::CXXBoolLiteralExprClass:

1955 case Stmt::ObjCBoolLiteralExprClass:

1956 case Stmt::ObjCAvailabilityCheckExprClass:

1957 case Stmt::FloatingLiteralClass:

1958 case Stmt::NoInitExprClass:

1959 case Stmt::SizeOfPackExprClass:

1960 case Stmt::StringLiteralClass:

1961 case Stmt::SourceLocExprClass:

1962 case Stmt::ObjCStringLiteralClass:

1963 case Stmt::CXXPseudoDestructorExprClass:

1964 case Stmt::SubstNonTypeTemplateParmExprClass:

1965 case Stmt::CXXNullPtrLiteralExprClass:

1966 case Stmt::ArraySectionExprClass:

1967 case Stmt::OMPArrayShapingExprClass:

1968 case Stmt::OMPIteratorExprClass:

1969 case Stmt::SYCLUniqueStableNameExprClass:

1970 case Stmt::OpenACCAsteriskSizeExprClass:

1971 case Stmt::TypeTraitExprClass: {

1977 break;

1978 }

1979

1980 case Stmt::CXXDefaultArgExprClass:

1981 case Stmt::CXXDefaultInitExprClass: {

1985

1988

1989 const Expr *ArgE;

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

1991 ArgE = DefE->getExpr();

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

1993 ArgE = DefE->getExpr();

1994 else

1995 llvm_unreachable("unknown constant wrapper kind");

1996

1997 bool IsTemporary = false;

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

1999 ArgE = MTE->getSubExpr();

2000 IsTemporary = true;

2001 }

2002

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

2004 if (!ConstantVal)

2006

2008 for (const auto I : PreVisit) {

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

2011 if (IsTemporary)

2012 State = createTemporaryRegionIfNeeded(State, LCtx,

2013 cast(S),

2014 cast(S));

2016 }

2017

2020 break;

2021 }

2022

2023

2024 case Stmt::CXXStdInitializerListExprClass:

2025 case Expr::ObjCArrayLiteralClass:

2026 case Expr::ObjCDictionaryLiteralClass:

2027 case Expr::ObjCBoxedExprClass: {

2029

2032

2035

2036 const auto *Ex = cast(S);

2037 QualType resultType = Ex->getType();

2038

2039 for (const auto N : preVisit) {

2042 resultType,

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

2045

2046

2047

2048 if (!(isa(Ex) &&

2049 !cast(Ex)->getSubExpr()

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

2052 assert(Child);

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

2055 }

2056

2058 }

2059

2062 break;

2063 }

2064

2065 case Stmt::ArraySubscriptExprClass:

2069 break;

2070

2071 case Stmt::MatrixSubscriptExprClass:

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

2073 break;

2074

2075 case Stmt::GCCAsmStmtClass: {

2084 break;

2085 }

2086

2087 case Stmt::MSAsmStmtClass:

2091 break;

2092

2093 case Stmt::BlockExprClass:

2097 break;

2098

2099 case Stmt::LambdaExprClass:

2100 if (AMgr.options.ShouldInlineLambdas) {

2104 } else {

2107 }

2108 break;

2109

2110 case Stmt::BinaryOperatorClass: {

2111 const auto *B = cast(S);

2112 if (B->isLogicalOp()) {

2116 break;

2117 }

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

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

2124 break;

2125 }

2126

2128

2129 if (AMgr.options.ShouldEagerlyAssume &&

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

2134 }

2135 else

2137

2139 break;

2140 }

2141

2142 case Stmt::CXXOperatorCallExprClass: {

2143 const auto *OCE = cast(S);

2144

2145

2146

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

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

2149 if (MD->isImplicitObjectMemberFunction()) {

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

2154 if (NewState != State) {

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

2157

2158 if (!Pred)

2159 break;

2160 }

2161 }

2162 }

2163 [[fallthrough]];

2164 }

2165

2166 case Stmt::CallExprClass:

2167 case Stmt::CXXMemberCallExprClass:

2168 case Stmt::UserDefinedLiteralClass:

2172 break;

2173

2174 case Stmt::CXXCatchStmtClass:

2178 break;

2179

2180 case Stmt::CXXTemporaryObjectExprClass:

2181 case Stmt::CXXConstructExprClass:

2185 break;

2186

2187 case Stmt::CXXInheritedCtorInitExprClass:

2190 Dst);

2192 break;

2193

2194 case Stmt::CXXNewExprClass: {

2196

2199

2201 for (const auto i : PreVisit)

2203

2206 break;

2207 }

2208

2209 case Stmt::CXXDeleteExprClass: {

2212 const auto *CDE = cast(S);

2216

2219

2221 break;

2222 }

2223

2224

2225

2226 case Stmt::ChooseExprClass: {

2228 const auto *C = cast(S);

2231 break;

2232 }

2233

2234 case Stmt::CompoundAssignOperatorClass:

2238 break;

2239

2240 case Stmt::CompoundLiteralExprClass:

2244 break;

2245

2246 case Stmt::BinaryConditionalOperatorClass:

2247 case Stmt::ConditionalOperatorClass: {

2249 const auto *C = cast(S);

2252 break;

2253 }

2254

2255 case Stmt::CXXThisExprClass:

2259 break;

2260

2261 case Stmt::DeclRefExprClass: {

2263 const auto *DE = cast(S);

2266 break;

2267 }

2268

2269 case Stmt::DeclStmtClass:

2273 break;

2274

2275 case Stmt::ImplicitCastExprClass:

2276 case Stmt::CStyleCastExprClass:

2277 case Stmt::CXXStaticCastExprClass:

2278 case Stmt::CXXDynamicCastExprClass:

2279 case Stmt::CXXReinterpretCastExprClass:

2280 case Stmt::CXXConstCastExprClass:

2281 case Stmt::CXXFunctionalCastExprClass:

2282 case Stmt::BuiltinBitCastExprClass:

2283 case Stmt::ObjCBridgedCastExprClass:

2284 case Stmt::CXXAddrspaceCastExprClass: {

2286 const auto *C = cast(S);

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

2289

2290

2293 break;

2294 }

2295

2296 case Expr::MaterializeTemporaryExprClass: {

2298 const auto *MTE = cast(S);

2302 for (const auto i : dstPrevisit)

2306 break;

2307 }

2308

2309 case Stmt::InitListExprClass:

2313 break;

2314

2315 case Stmt::MemberExprClass:

2319 break;

2320

2321 case Stmt::AtomicExprClass:

2325 break;

2326

2327 case Stmt::ObjCIvarRefExprClass:

2331 break;

2332

2333 case Stmt::ObjCForCollectionStmtClass:

2337 break;

2338

2339 case Stmt::ObjCMessageExprClass:

2343 break;

2344

2345 case Stmt::ObjCAtThrowStmtClass:

2346 case Stmt::CXXThrowExprClass:

2347

2348

2350 break;

2351

2352 case Stmt::ReturnStmtClass:

2356 break;

2357

2358 case Stmt::OffsetOfExprClass: {

2362

2364 for (const auto Node : PreVisit)

2366

2369 break;

2370 }

2371

2372 case Stmt::UnaryExprOrTypeTraitExprClass:

2375 Pred, Dst);

2377 break;

2378

2379 case Stmt::StmtExprClass: {

2380 const auto *SE = cast(S);

2381

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

2383

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

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

2386 break;

2387 }

2388

2389 if (const auto *LastExpr =

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

2394 state->getSVal(LastExpr,

2396 }

2397 break;

2398 }

2399

2400 case Stmt::UnaryOperatorClass: {

2402 const auto *U = cast(S);

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

2407 }

2408 else

2411 break;

2412 }

2413

2414 case Stmt::PseudoObjectExprClass: {

2417 const auto *PE = cast(S);

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

2422 }

2423 else

2427

2429 break;

2430 }

2431

2432 case Expr::ObjCIndirectCopyRestoreExprClass: {

2433

2434

2435

2438 const auto *OIE = cast(S);

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

2444 break;

2445 }

2446 }

2447}

2448

2449bool ExprEngine::replayWithoutInlining(ExplodedNode *N,

2453 assert(CalleeSF && CallerSF);

2454 ExplodedNode *BeforeProcessingCall = nullptr;

2456

2457

2458 while (N) {

2460 BeforeProcessingCall = N;

2462

2463

2465 continue;

2466

2467

2469 continue;

2471 continue;

2473 continue;

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

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

2476 continue;

2477 break;

2478 }

2479

2480 if (!BeforeProcessingCall)

2481 return false;

2482

2483

2484

2485

2486

2490

2491

2493 NewNodeState =

2495

2496

2497 bool IsNew = false;

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

2499

2500

2501 if (!IsNew)

2502 return true;

2503

2505

2506

2509 NumTimesRetriedWithoutInlining++;

2510 return true;

2511}

2512

2513

2518

2519

2520 if(AMgr.options.ShouldUnrollLoops) {

2523 if (Term) {

2525 Pred, maxBlockVisitOnPath);

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

2528 if (!UpdatedNode)

2529 return;

2530 Pred = UpdatedNode;

2531 }

2532 }

2533

2535 return;

2536 }

2537

2538

2539

2542 AMgr.options.ShouldWidenLoops) {

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

2545 return;

2546

2550 nodeBuilder.generateNode(WidenedState, Pred);

2551 return;

2552 }

2553

2554

2559

2560

2561

2565 (*G.roots_begin())->getLocation().getLocationContext();

2568

2569

2570

2571

2572

2574 replayWithoutInlining(Pred, CalleeLC)))

2575 return;

2576 NumMaxBlockCountReachedInInlined++;

2577 } else

2578 NumMaxBlockCountReached++;

2579

2580

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

2582 }

2583}

2584

2585

2586

2587

2588

2589

2590

2591

2592

2593

2598

2599 const auto *Ex = dyn_cast(Condition);

2600 if (!Ex)

2602

2603 uint64_t bits = 0;

2604 bool bitsInit = false;

2605

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

2608

2611

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

2614 bitsInit = true;

2615 bits = newBits;

2616 }

2617

2618 Ex = CE->getSubExpr();

2619 }

2620

2621

2623

2627

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

2629}

2630

2631#ifndef NDEBUG

2634 const auto *BO = dyn_cast(Condition);

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

2637 }

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

2639 }

2640 return nullptr;

2641}

2642#endif

2643

2644

2645

2646

2647

2648

2649

2650

2651

2652

2653

2654

2655

2656

2657

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

2662

2663 const auto *BO = dyn_cast(Condition);

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

2666

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

2669

2670

2671

2672

2673

2674

2675

2676

2677

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

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

2680 if (!CS)

2681 continue;

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

2684 return LastStmt;

2685 }

2686 llvm_unreachable("could not resolve condition");

2687}

2688

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

2691

2693

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

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

2699}

2700

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

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

2707}

2708

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

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

2714}

2715

2716

2717

2718

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

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

2723 bool HasMoreIteraton =

2725

2726

2727

2730 if (HasMoreIteraton)

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

2732 else

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

2734 }

2736

2737 if (X.isUnknownOrUndef()) {

2738

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

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

2741

2742

2743

2744

2745 SVal recovered =

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

2748

2750 X = recovered;

2751 }

2752 }

2753 }

2754 }

2755

2756

2757 if (X.isUnknownOrUndef())

2758 return std::nullopt;

2759

2761

2763 return State->assume(V);

2764}

2765

2769 std::optional IterationsCompletedInLoop) {

2771 "CXXBindTemporaryExprs are handled by processBindTemporary.");

2774 currBldrCtx = &BldCtx;

2775

2776

2780 return;

2781 }

2782

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

2785

2789 "Error evaluating branch");

2790

2793 Pred, *this);

2794

2795 if (CheckersOutSet.empty())

2796 return;

2797

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

2799 for (ExplodedNode *PredN : CheckersOutSet) {

2800 if (PredN->isSink())

2801 continue;

2802

2804

2805 ProgramStateRef StTrue = PrevState, StFalse = PrevState;

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

2808

2809 if (StTrue && StFalse)

2810 assert(!isa(Condition));

2811

2812 if (StTrue) {

2813

2814

2815

2816

2817

2818

2819

2820

2821

2822

2823

2824

2825

2826

2827

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

2829 bool FalseAlsoFeasible =

2830 StFalse ||

2832 bool SkipTrueBranch = CompletedTwoIterations && FalseAlsoFeasible;

2833

2834

2835

2836

2837

2838 if (!SkipTrueBranch || AMgr.options.ShouldWidenLoops)

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

2840 }

2841

2842 if (StFalse)

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

2844 }

2845 currBldrCtx = nullptr;

2846}

2847

2848

2849

2851 llvm::ImmutableSet<const VarDecl *>)

2852

2860 currBldrCtx = &BuilderCtx;

2861

2862 const auto *VD = cast(DS->getSingleDecl());

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

2866

2867 if (!initHasRun) {

2868 state = state->add(VD);

2869 }

2870

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

2872

2873 currBldrCtx = nullptr;

2874}

2875

2876

2877

2881

2882

2883

2884

2885

2886

2887

2888

2890

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

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

2893

2894 for (iterator Succ : builder) {

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

2896 builder.generateNode(Succ, state);

2897 return;

2898 }

2899 }

2900

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

2902 }

2903

2904 if (isa<UndefinedVal, loc::ConcreteInt>(V)) {

2905

2906

2907

2908

2909 return;

2910 }

2911

2912

2913

2914

2915 for (iterator Succ : builder)

2917}

2918

2925}

2926

2927

2928

2933

2935 State = finishArgumentConstruction(

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

2938

2939

2940

2941

2942

2943

2944

2945

2946 {

2950 while (LC != ToLC) {

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

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

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

2954

2955

2956

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

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

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

2962 }

2964 }

2965 }

2966

2967

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

2970 NodeBuilder Bldr(Pred, PostCleanup, BC);

2972 if (!Pred) {

2973

2974

2975 return;

2976 }

2977 }

2978

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

2982

2984

2987

2990

2991

2992 for (const auto I : AfterRemovedDead)

2994 } else {

2996 }

2997

2999}

3000

3001

3002

3005

3009

3010 if (CondV_untested.isUndef()) {

3011

3012

3013

3014

3015 return;

3016 }

3018

3020

3021 iterator I = builder.begin(), EI = builder.end();

3022 bool defaultIsFeasible = I == EI;

3023

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

3025

3026 if (!I.getBlock())

3027 continue;

3028

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

3030

3031

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

3034

3035

3036 llvm::APSInt V2;

3039 else

3040 V2 = V1;

3041

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

3044 std::tie(StateCase, DefaultSt) =

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

3046 else

3047 StateCase = DefaultSt;

3048

3049 if (StateCase)

3051

3052

3053

3054 if (DefaultSt)

3055 defaultIsFeasible = true;

3056 else {

3057 defaultIsFeasible = false;

3058 break;

3059 }

3060 }

3061

3062 if (!defaultIsFeasible)

3063 return;

3064

3065

3066

3067

3068

3069

3070

3071

3076 return;

3077 }

3078

3080}

3081

3082

3083

3084

3085

3090

3093

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

3095

3096

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

3100 const auto *MD = dyn_cast_or_null(D);

3101 const auto *DeclRefEx = dyn_cast(Ex);

3102 std::optional<std::pair<SVal, QualType>> VInfo;

3103

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

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

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

3107

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

3110 FieldDecl *LambdaThisCaptureField;

3111 CXXRec->getCaptureFields(LambdaCaptureFields, LambdaThisCaptureField);

3112

3113

3114

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

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

3119 VInfo = std::make_pair(state->getLValue(FD, CXXThisVal), FD->getType());

3120 }

3121 }

3122

3123 if (!VInfo)

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

3125

3126 SVal V = VInfo->first;

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

3128

3129

3130

3131 if (IsReference) {

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

3133 V = state->getSVal(R);

3134 else

3136 }

3137

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

3140 return;

3141 }

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

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

3146 return;

3147 }

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

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

3152 return;

3153 }

3154 if (isa<FieldDecl, IndirectFieldDecl>(D)) {

3155

3156

3157 return;

3158 }

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

3160 const auto *DD = cast(BD->getDecomposedDecl());

3161

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

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

3165 Base = state->getSVal(R);

3166 else

3168 }

3169

3171

3172

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

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

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

3176 }

3177

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

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

3180

3181

3182

3183

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

3185

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

3187 }

3188

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

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

3191

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

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

3194 V = state->getSVal(R);

3195 else

3197 }

3198 } else

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

3200

3201

3202

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

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

3205 V = state->getSVal(R);

3206 else

3208 }

3209

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

3212

3213 return;

3214 }

3215

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

3217

3218 (void)TPO;

3219 return;

3220 }

3221

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

3223}

3224

3225

3231

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

3234

3236

3237 for (auto *Node : CheckerPreStmt) {

3238

3239

3240 if (isa(Ex->getSubExpr()))

3241 break;

3242

3245

3247

3248

3249

3250

3251

3252

3253

3254

3255

3256

3257

3258

3259

3260

3261

3262

3263

3264

3265

3266

3267

3268

3269

3270

3271

3272

3273

3274

3275

3276

3277

3278

3279

3280

3281

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

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

3284

3285

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

3287 MEBase = CXXSCE->getSubExpr();

3288 }

3289

3290 auto ObjDeclExpr = cast(MEBase);

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

3292

3293 Base = state->getLValue(cast(ME->getMemberDecl()), Obj);

3294 }

3295

3296

3297

3298

3299

3300

3301

3302

3303

3304

3305

3306

3307

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

3309 Base = state->getLValue(cast(DRE->getDecl()), LCtx);

3310

3311

3313 Base = state->getSVal(R);

3314 else

3316

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

3318 }

3319

3321}

3322

3323

3329

3332

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

3335

3337

3338

3339

3340

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

3343

3344 for (auto *Node : CheckerPreStmt) {

3347

3348 if (IsGLValueLike) {

3350

3351

3352

3353

3356

3357 SVal V = state->getLValue(T,

3358 state->getSVal(Idx, LCtx),

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

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

3362 } else if (IsVectorType) {

3363

3365 } else {

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

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

3368 }

3369 }

3370

3372}

3373

3374

3377

3380

3383

3384

3385

3386 if (isa<VarDecl, EnumConstantDecl>(Member)) {

3387 for (const auto I : CheckedSet)

3389 } else {

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

3392

3393 for (const auto I : CheckedSet) {

3397

3398

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

3400 if (MD->isImplicitObjectMemberFunction())

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

3402

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

3405

3407 continue;

3408 }

3409

3410

3412 state = createTemporaryRegionIfNeeded(state, LCtx, BaseExpr,

3413 nullptr,

3414 &MR);

3415 SVal baseExprVal =

3417

3418

3419 if (const auto *SR =

3420 dyn_cast_or_null(baseExprVal.getAsRegion())) {

3421 QualType T = SR->getPointeeStaticType();

3422 baseExprVal =

3424 }

3425

3426 const auto *field = cast(Member);

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

3428

3430

3431

3432

3433

3436 const auto *PE =

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

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

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

3440 }

3441 }

3442

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

3445 L = state->getSVal(R);

3446 else

3448 }

3449

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

3452 } else {

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

3456 }

3457 }

3458 }

3459

3461}

3462

3467

3468

3469

3470

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

3473

3474 for (const auto I : AfterPreSet) {

3477

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

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

3482 ValuesToInvalidate.push_back(SubExprVal);

3483 }

3484

3485 State = State->invalidateRegions(ValuesToInvalidate, AE,

3487 LCtx,

3488 true,

3489 nullptr);

3490

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

3495 }

3496

3498}

3499

3500

3501

3502

3503

3504

3505

3506

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

3513

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

3515 if (!MR ||

3516 !isa<StackSpaceRegion, StaticGlobalSpaceRegion>(MR->getMemorySpace())) {

3517 Escaped.push_back(LocAndVal.second);

3518 continue;

3519 }

3520

3521

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

3523 if (VR->hasStackParametersStorage() && VR->getStackFrame()->inTopFrame())

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

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

3526 Escaped.push_back(LocAndVal.second);

3527 continue;

3528 }

3529

3530

3531

3532

3533

3534

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

3536 if (StoredVal != LocAndVal.second)

3537 if (State ==

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

3539 Escaped.push_back(LocAndVal.second);

3540 }

3541

3542 if (Escaped.empty())

3543 return State;

3544

3545 return escapeValues(State, Escaped, Kind, Call);

3546}

3547

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

3553 nullptr);

3554}

3555

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

3563 return State;

3564

3567 *Invalidated,

3568 nullptr,

3570 &ITraits);

3571

3572

3573

3575 for (const auto I : ExplicitRegions) {

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

3578 }

3579

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

3582 if (SymbolsDirectlyInvalidated.count(sym))

3583 continue;

3584 SymbolsIndirectlyInvalidated.insert(sym);

3585 }

3586

3587 if (!SymbolsDirectlyInvalidated.empty())

3590

3591

3592 if (!SymbolsIndirectlyInvalidated.empty())

3595

3596 return State;

3597}

3598

3599

3600

3607 if (!PP)

3608 PP = &PS;

3609

3610

3613 StoreE, *this, *PP);

3614

3616

3617

3618

3619 if (!isa(location)) {

3621 nullptr);

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

3625 return;

3626 }

3627

3628 for (const auto PredI : CheckedSet) {

3630

3632

3633

3634

3635

3636 state = state->bindLoc(location.castAs<Loc>(),

3637 Val, LC, !atDeclInit);

3638

3639 const MemRegion *LocReg = nullptr;

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

3642 LocReg = LocRegVal->getRegion();

3643 }

3644

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

3647 }

3648}

3649

3650

3651

3652

3653

3654

3655

3656

3657

3659 const Expr *LocationE,

3663

3664

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

3666

3667

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

3670

3671 if (Tmp.empty())

3672 return;

3673

3675 return;

3676

3677 for (const auto I : Tmp)

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

3679}

3680

3682 const Expr *NodeEx,

3683 const Expr *BoundEx,

3686 SVal location,

3689 assert(!isa(location) && "location cannot be a NonLoc.");

3690 assert(NodeEx);

3691 assert(BoundEx);

3692

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

3695 if (Tmp.empty())

3696 return;

3697

3700 return;

3701

3702

3703 for (const auto I : Tmp) {

3704 state = I->getState();

3706

3708 if (location.isValid()) {

3709 if (LoadTy.isNull())

3710 LoadTy = BoundEx->getType();

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

3712 }

3713

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

3716 }

3717}

3718

3720 const Stmt *NodeEx,

3721 const Stmt *BoundEx,

3724 SVal location,

3725 bool isLoad) {

3727

3729 return;

3730 }

3731

3733 BldrTop.takeNodes(Pred);

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

3736

3737

3738

3739

3740

3741

3742

3743

3744

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

3747 }

3750 NodeEx, BoundEx, *this);

3751 BldrTop.addNodes(Tmp);

3752}

3753

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

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

3758

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

3760}

3761

3762

3763

3764

3766 const Expr *)

3767

3770 const Expr *Ex) {

3772

3774

3775

3776

3779 continue;

3780 }

3781

3783 State = State->set(nullptr);

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

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

3788

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

3790

3791 if (StateTrue && StateFalse) {

3792 StateTrue = StateTrue->set(Ex);

3793 StateFalse = StateFalse->set(Ex);

3794 }

3795

3796

3797 if (StateTrue) {

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

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

3801 }

3802

3803

3804 if (StateFalse) {

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

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

3808 }

3809 }

3810 }

3811}

3812

3814 const Expr *Ex) const {

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

3816}

3817

3821

3822

3823

3824

3825

3826

3827

3829

3832 assert(!isa(X));

3833

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

3835 state = state->invalidateRegions(*LV, A, currBldrCtx->blockCount(),

3837 true);

3838 }

3839

3840

3843

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

3845 state = state->invalidateRegions(*LV, A, currBldrCtx->blockCount(),

3847 true);

3848 }

3849

3851}

3852

3857}

3858

3859

3860

3861

3862

3863namespace llvm {

3864

3865template<>

3868

3871 N->getState()->getStateManager().getOwningEngine()).getBugReporter();

3872

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

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

3876 if (!PR)

3877 continue;

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

3881 return true;

3882 }

3883 }

3884 return false;

3885 }

3886

3887

3888

3889

3890

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

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

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

3896 while (true) {

3897 PreCallback(N);

3898 if (Stop(N))

3899 return true;

3900

3902 break;

3903 PostCallback(N);

3904

3906 }

3907 return false;

3908 }

3909

3912 }

3913

3915 std::string Buf;

3916 llvm::raw_string_ostream Out(Buf);

3917

3918 const bool IsDot = true;

3919 const unsigned int Space = 1;

3921

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

3923 << ",\\l";

3924

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

3926

3927

3928 traverseHiddenNodes(

3929 N,

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

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

3935 Out << '\"' << Tag->getTagDescription() << '\"';

3936 else

3937 Out << "null";

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

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

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

3941 },

3942

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

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

3945

3946 Out << "\\l";

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

3948

3950

3951 Out << "\\l}\\l";

3952 return Buf;

3953 }

3954};

3955

3956}

3957

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

3961}

3962

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

3966}

3967

3969 if (trim) {

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

3971

3972

3974 const auto *R =

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

3976 if (!R)

3977 continue;

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

3979 Src.push_back(N);

3980 }

3982 }

3983

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

3985 "Exploded Graph",

3986 std::string(Filename));

3987}

3988

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

3992

3993 if (!TrimmedG.get()) {

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

3995 return "";

3996 }

3997

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

3999 false,

4000 "Trimmed Exploded Graph",

4001 std::string(Filename));

4002}

4003

4005 static int index = 0;

4006 return &index;

4007}

4008

4009void ExprEngine::anchor() { }

Defines the clang::ASTContext interface.

BoundNodesTreeBuilder Nodes

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....

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

static const Stmt * getRightmostLeaf(const Stmt *Condition)

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

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...

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

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

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.

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

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

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

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

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

llvm::ImmutableMap< ConstructedObjectKey, SVal > ObjectsUnderConstructionMap

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.

STATISTIC(NumRemoveDeadBindings, "The # of times RemoveDeadBindings is called")

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 the SourceManager interface.

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 ...

SourceManager & getSourceManager()

QualType getBaseElementType(const ArrayType *VAT) const

Return the innermost element type of an array type.

const clang::PrintingPolicy & getPrintingPolicy() const

const ArrayType * getAsArrayType(QualType T) const

Type Query functions.

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.

unsigned NoRetryExhausted

Do not re-analyze paths leading to exhausted nodes with a different strategy.

unsigned maxBlockVisitOnPath

The maximum number of times the analyzer visits a block.

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.

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.

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

CFGTerminator getTerminator() const

Stmt * getTerminatorStmt()

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

const CXXDeleteExpr * getDeleteExpr() const

Represents a top-level expression in a basic block.

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.

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...

bool isStmtBranch() const

Represents a base class of a C++ class.

Represents binding an expression to a temporary.

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 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.

SourceLocation getBeginLoc() const LLVM_READONLY

A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.

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, SmallVectorImpl< PartialDiagnosticAt > *Diag=nullptr) 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.

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.

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.

SplitQualType split() const

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

bool isCForbiddenLValueType() const

Determine whether expressions of the given type are forbidden from being lvalues in C.

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.

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 isIntegralOrEnumerationType() const

Determine whether this type is an integral or enumeration type.

bool isVectorType() const

const T * getAs() const

Member-template getAs'.

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.

const LangOptions & getLangOpts() const

ASTContext & getASTContext() override

AnalyzerOptions & options

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 runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, ExprEngine &Eng, const ProgramPoint &PP)

Run checkers for binding of a value to a location.

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 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 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 addAbortedBlock(const ExplodedNode *node, const CFGBlock *block)

Inform the CoreEngine that a basic block was aborted because it could not be completely analyzed.

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

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

void enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS)

enqueue the nodes corresponding to the end of function onto the end of path / work list.

void enqueue(ExplodedNodeSet &Set)

Enqueue the given set of nodes onto the work list.

std::unique_ptr< ExplodedGraph > trim(ArrayRef< const NodeTy * > Nodes, InterExplodedGraphMap *ForwardMap=nullptr, InterExplodedGraphMap *InverseMap=nullptr) const

Creates a trimmed version of the graph that only contains paths leading to the given nodes.

void enableNodeReclamation(unsigned Interval)

Enable tracking of recently allocated nodes for potential reclamation when calling reclaimRecentlyAll...

void reclaimRecentlyAllocatedNodes()

Reclaim "uninteresting" nodes created since the last time this method was called.

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 ...

roots_iterator roots_begin()

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.

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.

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

Transfer function logic for DeclRefExprs and BlockDeclRefExprs.

void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred)

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

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

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.

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.

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)

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.

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)

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.

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,...

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

Dump graph to the specified filename.

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.

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.

const LocationContext * getRootLocationContext() const

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

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

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

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.

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

VisitBlockExpr - Transfer function logic for BlockExprs.

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

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

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.

CFGBlock::ConstCFGElementRef getCFGElementRef() const

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

VisitGCCAsmStmt - Transfer function logic for inline asm.

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

Called by CoreEngine when processing the entrance of a CFGBlock.

void VisitInitListExpr(const InitListExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst)

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.

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

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

void ViewGraph(bool trim=false)

Visualize the ExplodedGraph created by executing the simulation.

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

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

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.

static const ProgramPointTag * cleanupNodeTag()

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

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

processCFGElement - Called by CoreEngine.

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

Called by CoreEngine.

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

VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof.

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.

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

void processSwitch(SwitchNodeBuilder &builder)

ProcessSwitch - Called by CoreEngine.

void processEndWorklist()

Called by CoreEngine when the analysis worklist has terminated.

CheckerManager & getCheckerManager() const

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

VisitAtomicExpr - Transfer function for builtin atomic expressions.

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

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.

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

ConstraintManager & getConstraintManager()

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

Called by CoreEngine.

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

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.

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.

AnalysisManager & getAnalysisManager()

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

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.

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.

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

void processIndirectGoto(IndirectGotoNodeBuilder &builder)

processIndirectGoto - Called by CoreEngine.

const NodeBuilderContext & getBuilderContext()

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

Retreives the size of the array in the pending ArrayInitLoopExpr.

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

void markReachedMaxBlockCount(const Decl *D)

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)

const CXXLifetimeExtendedObjectRegion * getCXXLifetimeExtendedObjectRegion(Expr const *Ex, ValueDecl const *VD, LocationContext const *LC)

Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by local referen...

const CXXTempObjectRegion * getCXXTempObjectRegion(Expr const *Ex, LocationContext const *LC)

const CXXLifetimeExtendedObjectRegion * getCXXStaticLifetimeExtendedObjectRegion(const Expr *Ex, ValueDecl const *VD)

Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by static refere...

MemRegion - The root abstract class for all memory regions.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace() const

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const

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.

ProgramStateRef removeDeadBindingsFromEnvironmentAndStore(ProgramStateRef St, const StackFrameContext *LCtx, SymbolReaper &SymReaper)

bool haveEqualStores(ProgramStateRef S1, ProgramStateRef S2) const

bool haveEqualEnvironments(ProgramStateRef S1, ProgramStateRef S2) const

ProgramStateRef getPersistentStateWithGDM(ProgramStateRef FromState, ProgramStateRef GDMState)

MemRegionManager & getRegionManager()

ProgramStateRef getInitialState(const LocationContext *InitLoc)

StoreManager & getStoreManager()

Information about invalidation for a particular region/symbol.

DefinedOrUnknownSVal makeZeroVal(QualType type)

Construct an SVal representing '0' for the specified type.

DefinedSVal getFunctionPointer(const FunctionDecl *func)

NonLoc makeIntValWithWidth(QualType ptrType, uint64_t integer)

NonLoc makeArrayIndex(uint64_t idx)

nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)

DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)

Create a new symbol with a unique 'name'.

QualType getConditionType() const

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

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

std::optional< SVal > getConstantVal(const Expr *E)

Returns the value of E, if it can be determined in a non-path-sensitive manner.

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 llvm::APSInt * getAsInteger() const

If this SVal is loc::ConcreteInt or nonloc::ConcreteInt, return a pointer to APSInt which is held in ...

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.

TypedValueRegion - An abstract class representing regions having a typed value.

Represents symbolic expression that isn't a location.

const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl

Matches variable declarations.

const internal::VariadicAllOfMatcher< Decl > decl

Matches declarations.

llvm::DenseSet< const Decl * > SetOfConstDecls

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)

IntrusiveRefCntPtr< const ProgramState > ProgramStateRef

ProgramStateRef processLoopEnd(const Stmt *LoopStmt, ProgramStateRef State)

Updates the given ProgramState.

ProgramStateRef getWidenedLoopState(ProgramStateRef PrevState, const LocationContext *LCtx, unsigned BlockCount, const Stmt *LoopStmt)

Get the states that result from widening the loop.

llvm::DenseSet< SymbolRef > InvalidatedSymbols

bool isUnrolledState(ProgramStateRef State)

Returns if the given State indicates that is inside a completely unrolled 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 operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)

bool operator<(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

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

@ 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.

An adjustment to be made to the temporary created when emitting a reference binding,...

@ 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)

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

static bool nodeHasBugReport(const ExplodedNode *N)

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.

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