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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

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

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

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

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

32#include

33#include

34#include

35

36using namespace clang;

37using namespace ento;

38

39

40

41

42

43namespace {

44class BindingKey {

45public:

46 enum Kind {

47 Default = 0x0,

48 Direct = 0x1,

49 Symbolic = 0x2,

50 };

51

52private:

53 llvm::PointerIntPair<const MemRegion *, 2> P;

55

56

57

58 explicit BindingKey(const SubRegion *r, const SubRegion *Base, Kind k)

59 : P(r, k | Symbolic), Data(reinterpret_cast<uintptr_t>(Base)) {

60 assert(r && Base && "Must have known regions.");

61 assert(getConcreteOffsetRegion() == Base && "Failed to store base region");

62 }

63

64

65 explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)

66 : P(r, k), Data(offset) {

67 assert(r && "Must have known regions.");

68 assert(getOffset() == offset && "Failed to store offset");

71 "Not a base");

72 }

73

74public:

75 bool isDirect() const { return P.getInt() & Direct; }

76 bool isDefault() const { return !isDirect(); }

77 bool hasSymbolicOffset() const { return P.getInt() & Symbolic; }

78

79 const MemRegion *getRegion() const { return P.getPointer(); }

81 assert(!hasSymbolicOffset());

82 return Data;

83 }

84

85 const SubRegion *getConcreteOffsetRegion() const {

86 assert(hasSymbolicOffset());

87 return reinterpret_cast<const SubRegion *>(static_cast<uintptr_t>(Data));

88 }

89

90 const MemRegion *getBaseRegion() const {

91 if (hasSymbolicOffset())

92 return getConcreteOffsetRegion()->getBaseRegion();

94 }

95

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

97 ID.AddPointer(P.getOpaqueValue());

98 ID.AddInteger(Data);

99 }

100

101 static BindingKey Make(const MemRegion *R, Kind k);

102

103 bool operator<(const BindingKey &X) const {

104 if (P.getOpaqueValue() < X.P.getOpaqueValue())

105 return true;

106 if (P.getOpaqueValue() > X.P.getOpaqueValue())

107 return false;

108 return Data < X.Data;

109 }

110

111 bool operator==(const BindingKey &X) const {

112 return P.getOpaqueValue() == X.P.getOpaqueValue() &&

113 Data == X.Data;

114 }

115

116 LLVM_DUMP_METHOD void dump() const;

117};

118

119std::string locDescr(Loc L) {

120 std::string S;

121 llvm::raw_string_ostream OS(S);

123 return OS.str();

124}

125}

126

127BindingKey BindingKey::Make(const MemRegion *R, Kind k) {

128 const RegionOffset &RO = R->getAsOffset();

131

133}

134

135namespace llvm {

136static inline raw_ostream &operator<<(raw_ostream &Out, BindingKey K) {

137 Out << "\"kind\": \"" << (K.isDirect() ? "Direct" : "Default")

138 << "\", \"offset\": ";

139

140 if (!K.hasSymbolicOffset())

141 Out << K.getOffset();

142 else

143 Out << "null";

144

145 return Out;

146}

147

148}

149

150#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

151void BindingKey::dump() const { llvm::errs() << *this; }

152#endif

153

154

155

156

157

161

162typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>

164

165namespace {

166class RegionBindingsRef : public llvm::ImmutableMapRef<const MemRegion *,

167 ClusterBindings> {

168 ClusterBindings::Factory *CBFactory;

169

170

171

172

173

174

175

176

177

178

179 bool IsMainAnalysis;

180

181public:

182 typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>

183 ParentTy;

184

185 RegionBindingsRef(ClusterBindings::Factory &CBFactory,

186 const RegionBindings::TreeTy *T,

187 RegionBindings::TreeTy::Factory *F, bool IsMainAnalysis)

188 : RegionBindingsRef(ParentTy(T, F), CBFactory, IsMainAnalysis) {}

189

190 RegionBindingsRef(const ParentTy &P, ClusterBindings::Factory &CBFactory,

191 bool IsMainAnalysis)

192 : ParentTy(P), CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}

193

194 RegionBindingsRef removeCluster(const MemRegion *BaseRegion) const {

195 return RegionBindingsRef(ParentTy::remove(BaseRegion), *CBFactory,

196 IsMainAnalysis);

197 }

198

199 RegionBindingsRef addBinding(BindingKey K, SVal V) const;

200

201 RegionBindingsRef addBinding(const MemRegion *R,

202 BindingKey::Kind k, SVal V) const;

203

204 const SVal *lookup(BindingKey K) const;

205 const SVal *lookup(const MemRegion *R, BindingKey::Kind k) const;

207

208 RegionBindingsRef removeBinding(BindingKey K);

209

210 RegionBindingsRef removeBinding(const MemRegion *R,

211 BindingKey::Kind k);

212

213 RegionBindingsRef removeBinding(const MemRegion *R) {

214 return removeBinding(R, BindingKey::Direct).

215 removeBinding(R, BindingKey::Default);

216 }

217

218 std::optional getDirectBinding(const MemRegion *R) const;

219

220

221

222 std::optional getDefaultBinding(const MemRegion *R) const;

223

224

225 Store asStore() const {

226 llvm::PointerIntPair<Store, 1, bool> Ptr = {

227 asImmutableMap().getRootWithoutRetain(), IsMainAnalysis};

228 return reinterpret_cast<Store>(Ptr.getOpaqueValue());

229 }

230

231 bool isMainAnalysis() const {

232 return IsMainAnalysis;

233 }

234

235 void printJson(raw_ostream &Out, const char *NL = "\n",

236 unsigned int Space = 0, bool IsDot = false) const {

237 using namespace llvm;

238 DenseMap<const MemRegion *, std::string> StringifyCache;

239 auto ToString = [&StringifyCache](const MemRegion *R) {

240 auto [Place, Inserted] = StringifyCache.try_emplace(R);

241 if (!Inserted)

242 return Place->second;

243 std::string Res;

244 raw_string_ostream OS(Res);

245 OS << R;

246 Place->second = Res;

247 return Res;

248 };

249

250 using Cluster =

251 std::pair<const MemRegion *, ImmutableMap<BindingKey, SVal>>;

252 using Binding = std::pair<BindingKey, SVal>;

253

254 const auto MemSpaceBeforeRegionName = [&ToString](const Cluster *L,

255 const Cluster *R) {

257 return true;

259 return false;

260 return ToString(L->first) < ToString(R->first);

261 };

262

263 const auto SymbolicBeforeOffset = [&ToString](const BindingKey &L,

264 const BindingKey &R) {

265 if (L.hasSymbolicOffset() && !R.hasSymbolicOffset())

266 return true;

267 if (!L.hasSymbolicOffset() && R.hasSymbolicOffset())

268 return false;

269 if (L.hasSymbolicOffset() && R.hasSymbolicOffset())

270 return ToString(L.getRegion()) < ToString(R.getRegion());

271 return L.getOffset() < R.getOffset();

272 };

273

274 const auto DefaultBindingBeforeDirectBindings =

275 [&SymbolicBeforeOffset](const Binding *LPtr, const Binding *RPtr) {

276 const BindingKey &L = LPtr->first;

277 const BindingKey &R = RPtr->first;

278 if (L.isDefault() && !R.isDefault())

279 return true;

280 if (!L.isDefault() && R.isDefault())

281 return false;

282 assert(L.isDefault() == R.isDefault());

283 return SymbolicBeforeOffset(L, R);

284 };

285

286 const auto AddrOf = [](const auto &Item) { return &Item; };

287

288 std::vector<const Cluster *> SortedClusters;

289 SortedClusters.reserve(std::distance(begin(), end()));

290 append_range(SortedClusters, map_range(*this, AddrOf));

291 llvm::sort(SortedClusters, MemSpaceBeforeRegionName);

292

293 for (auto [Idx, C] : llvm::enumerate(SortedClusters)) {

294 const auto &[BaseRegion, Bindings] = *C;

295 Indent(Out, Space, IsDot)

296 << "{ \"cluster\": \"" << BaseRegion << "\", \"pointer\": \""

297 << (const void *)BaseRegion << "\", \"items\": [" << NL;

298

299 std::vector<const Binding *> SortedBindings;

300 SortedBindings.reserve(std::distance(Bindings.begin(), Bindings.end()));

301 append_range(SortedBindings, map_range(Bindings, AddrOf));

302 llvm::sort(SortedBindings, DefaultBindingBeforeDirectBindings);

303

304 ++Space;

305 for (auto [Idx, B] : llvm::enumerate(SortedBindings)) {

306 const auto &[Key, Value] = *B;

307 Indent(Out, Space, IsDot) << "{ " << Key << ", \"value\": ";

308 Value.printJson(Out, true);

309 Out << " }";

310 if (Idx != SortedBindings.size() - 1)

311 Out << ',';

312 Out << NL;

313 }

314 --Space;

315 Indent(Out, Space, IsDot) << "]}";

316 if (Idx != SortedClusters.size() - 1)

317 Out << ',';

318 Out << NL;

319 }

320 }

321

322 LLVM_DUMP_METHOD void dump() const { printJson(llvm::errs()); }

323

324protected:

325 RegionBindingsRef

326 commitBindingsToCluster(const MemRegion *BaseRegion,

328};

329}

330

331

332

334public:

337 std::optional BindingsLeft)

338 : RegionBindingsRef(Base),

339 EscapedValuesDuringBind(&EscapedValuesDuringBind),

340 BindingsLeft(BindingsLeft) {}

341

343 return BindingsLeft.has_value() && BindingsLeft.value() == 0;

344 }

345

347 EscapedValuesDuringBind->push_back(V);

348 return *this;

349 }

350

354 for (SVal V : llvm::make_range(Begin, End))

356 return *this;

357 }

358

361 data_type_ref BindingKeyAndValue) const {

363 BaseRegion, BindingKeyAndValue),

364 *EscapedValuesDuringBind, BindingsLeft};

365 }

366

369 RegionBindingsRef::removeCluster(BaseRegion), *EscapedValuesDuringBind,

370 BindingsLeft};

371 }

372

374 std::optional NewBindingsLeft = BindingsLeft;

375 if (NewBindingsLeft.has_value()) {

376 assert(NewBindingsLeft.value() != 0);

377 NewBindingsLeft.value() -= 1;

378

379

380

381 if (NewBindingsLeft.value() == 0) {

383 K = BindingKey::Make(K.getRegion(), BindingKey::Default);

385 }

386 }

387

389 *EscapedValuesDuringBind, NewBindingsLeft};

390 }

391

394 return addBinding(BindingKey::Make(R, k), V);

395 }

396

397private:

399 std::optional BindingsLeft;

400};

401

404

405std::optional

406RegionBindingsRef::getDirectBinding(const MemRegion *R) const {

407 const SVal *V = lookup(R, BindingKey::Direct);

408 return V ? std::optional(*V) : std::nullopt;

409}

410

411std::optional

412RegionBindingsRef::getDefaultBinding(const MemRegion *R) const {

413 const SVal *V = lookup(R, BindingKey::Default);

414 return V ? std::optional(*V) : std::nullopt;

415}

416

417RegionBindingsRef RegionBindingsRef::commitBindingsToCluster(

419 return RegionBindingsRef(ParentTy::add(BaseRegion, Bindings), *CBFactory,

420 IsMainAnalysis);

421}

422

423RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K, SVal V) const {

424 const MemRegion *Base = K.getBaseRegion();

425

428 (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());

430 return commitBindingsToCluster(Base, Bindings);

431}

432

433RegionBindingsRef RegionBindingsRef::addBinding(const MemRegion *R,

434 BindingKey::Kind k,

435 SVal V) const {

436 return addBinding(BindingKey::Make(R, k), V);

437}

438

439const SVal *RegionBindingsRef::lookup(BindingKey K) const {

440 const ClusterBindings *Cluster = lookup(K.getBaseRegion());

441 if (!Cluster)

442 return nullptr;

443 return Cluster->lookup(K);

444}

445

446const SVal *RegionBindingsRef::lookup(const MemRegion *R,

447 BindingKey::Kind k) const {

448 return lookup(BindingKey::Make(R, k));

449}

450

451RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {

452 const MemRegion *Base = K.getBaseRegion();

454 if (!Cluster)

455 return *this;

456

457 ClusterBindings NewCluster = CBFactory->remove(*Cluster, K);

458 if (NewCluster.isEmpty())

459 return removeCluster(Base);

460 return commitBindingsToCluster(Base, NewCluster);

461}

462

463RegionBindingsRef RegionBindingsRef::removeBinding(const MemRegion *R,

464 BindingKey::Kind k){

465 return removeBinding(BindingKey::Make(R, k));

466}

467

468

469

470

471

472namespace {

473class InvalidateRegionsWorker;

474

475class RegionStoreManager : public StoreManager {

476public:

477 RegionBindings::Factory RBFactory;

478 mutable ClusterBindings::Factory CBFactory;

479

480 typedef std::vector SValListTy;

481private:

482 typedef llvm::DenseMap<const LazyCompoundValData *,

483 SValListTy> LazyBindingsMapTy;

484 LazyBindingsMapTy LazyBindingsMap;

485

486

487

488

489

490

491

492

493

494 const unsigned SmallStructLimit;

495

496

497

498

499

500

501

502

503

504 const unsigned SmallArrayLimit;

505

506

507

508

509

510 const std::optional RegionStoreMaxBindingFanOutPlusOne;

511

512

513

514 void populateWorkList(InvalidateRegionsWorker &W,

515 ArrayRef Values,

516 InvalidatedRegions *TopLevelRegions);

517

518 const AnalyzerOptions &getOptions() {

519 return StateMgr.getOwningEngine().getAnalysisManager().options;

520 }

521

522public:

523 RegionStoreManager(ProgramStateManager &mgr)

524 : StoreManager(mgr), RBFactory(mgr.getAllocator()),

525 CBFactory(mgr.getAllocator()),

526 SmallStructLimit(getOptions().RegionStoreSmallStructLimit),

527 SmallArrayLimit(getOptions().RegionStoreSmallArrayLimit),

528 RegionStoreMaxBindingFanOutPlusOne([&]() -> std::optional {

529 unsigned FanOut = getOptions().RegionStoreMaxBindingFanOut;

530 assert(FanOut != std::numeric_limits::max());

531 if (FanOut == 0)

532 return std::nullopt;

533 return FanOut + 1 ;

534 }()) {}

535

536

537

538

539 LimitedRegionBindingsRef

541 QualType T);

542

543

544

545

546

547

548

549 SVal ArrayToPointer(Loc Array, QualType ElementTy) override;

550

551

552

553 StoreRef getInitialStore(const LocationContext *InitLoc) override {

554 bool IsMainAnalysis = false;

555 if (const auto *FD = dyn_cast(InitLoc->getDecl()))

556 IsMainAnalysis = FD->isMain() && !Ctx.getLangOpts().CPlusPlus;

557 return StoreRef(RegionBindingsRef(RegionBindingsRef::ParentTy(

558 RBFactory.getEmptyMap(), RBFactory),

559 CBFactory, IsMainAnalysis)

560 .asStore(),

561 *this);

562 }

563

564

565

566

567 RegionBindingsRef

569 unsigned Count, const LocationContext *LCtx,

570 RegionBindingsRef B, InvalidatedRegions *Invalidated);

571

572 StoreRef invalidateRegions(Store store, ArrayRef Values,

574 const LocationContext *LCtx, const CallEvent *Call,

576 RegionAndSymbolInvalidationTraits &ITraits,

577 InvalidatedRegions *Invalidated,

578 InvalidatedRegions *InvalidatedTopLevel) override;

579

580 bool scanReachableSymbols(Store S, const MemRegion *R,

581 ScanReachableSymbols &Callbacks) override;

582

583 LimitedRegionBindingsRef

585 std::optional

587 const ElementRegion *R);

588 std::optional

589 getSValFromInitListExpr(const InitListExpr *ILE,

590 const SmallVector<uint64_t, 2> &ConcreteOffsets,

591 QualType ElemT);

592 SVal getSValFromStringLiteral(const StringLiteral *SL, uint64_t Offset,

593 QualType ElemT);

594

595public:

596 BindResult Bind(Store store, Loc LV, SVal V) override {

597 llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;

598 LimitedRegionBindingsRef BoundedBindings =

599 getRegionBindings(store, EscapedValuesDuringBind);

600 return BindResult{StoreRef(bind(BoundedBindings, LV, V).asStore(), *this),

601 std::move(EscapedValuesDuringBind)};

602 }

603

605 SVal V);

606

607

608

609 BindResult BindDefaultInitial(Store store, const MemRegion *R,

610 SVal V) override {

611 RegionBindingsRef B = getRegionBindings(store);

612

613

614 assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&

615 "Double initialization!");

616 B = B.addBinding(BindingKey::Make(R, BindingKey::Default), V);

617 return BindResult{

618 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this), {}};

619 }

620

621

622

623 BindResult BindDefaultZero(Store store, const MemRegion *R) override {

624

625

626

627

628

629

630

631

632

633 if (const auto *BR = dyn_cast(R))

634 if (BR->getDecl()->isEmpty())

635 return BindResult{StoreRef(store, *this), {}};

636

637 llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;

638 LimitedRegionBindingsRef B =

639 getRegionBindings(store, EscapedValuesDuringBind);

640 SVal V = svalBuilder.makeZeroVal(Ctx.CharTy);

642 B = B.addBinding(BindingKey::Make(R, BindingKey::Default), V);

643 return BindResult{

644 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this),

645 std::move(EscapedValuesDuringBind)};

646 }

647

648

649

650

651

652

653

654

655

656

657

658 std::optional

660 const RecordDecl *RD, nonloc::LazyCompoundVal LCV);

661

662

664 const TypedValueRegion *R, SVal V);

665

666

668 const TypedValueRegion *R, SVal V);

669

670 std::optional

672 const ArrayType *AT, nonloc::LazyCompoundVal LCV);

673

675 const TypedValueRegion *R, SVal V);

676

677

678

680 const TypedRegion *R, SVal DefaultVal);

681

682

683

684

685 StoreRef killBinding(Store ST, Loc L) override;

686

687 void incrementReferenceCount(Store store) override {

688 getRegionBindings(store).manualRetain();

689 }

690

691

692

693

694 void decrementReferenceCount(Store store) override {

695 getRegionBindings(store).manualRelease();

696 }

697

698 bool includedInBindings(Store store, const MemRegion *region) const override;

699

700

701

702

703

704

705

706

707

708

709

710

711

712

713 SVal getBinding(Store S, Loc L, QualType T) override {

714 return getBinding(getRegionBindings(S), L, T);

715 }

716

717 std::optional getDefaultBinding(Store S, const MemRegion *R) override {

718 RegionBindingsRef B = getRegionBindings(S);

719

720

721

723 }

724

726

728

730

732

734

735 SVal getBindingForLazySymbol(const TypedValueRegion *R);

736

738 const TypedValueRegion *R,

739 QualType Ty);

740

741 SVal getLazyBinding(const SubRegion *LazyBindingRegion,

742 RegionBindingsRef LazyBinding);

743

744

745

746

747

748

752

753

754

755

756

757

758 std::optional

760 const MemRegion *superR,

761 const TypedValueRegion *R, QualType Ty);

762

763

764

765

766

767 std::pair<Store, const SubRegion *>

769 const SubRegion *originalRegion);

770

771

772

773

774

775

776

777

778

779

780

781 const SValListTy &getInterestingValues(nonloc::LazyCompoundVal LCV);

782

783

784

785

786

787

788

789 StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,

790 SymbolReaper& SymReaper) override;

791

792

793

794

795

796 RegionBindingsRef getRegionBindings(Store store) const {

797 llvm::PointerIntPair<Store, 1, bool> Ptr;

798 Ptr.setFromOpaqueValue(const_cast<void *>(store));

799 return {CBFactory,

800 static_cast<const RegionBindings::TreeTy *>(Ptr.getPointer()),

801 RBFactory.getTreeFactory(), Ptr.getInt()};

802 }

803

804 LimitedRegionBindingsRef

805 getRegionBindings(Store store,

806 SmallVectorImpl &EscapedValuesDuringBind) const {

807 return LimitedRegionBindingsRef(

808 getRegionBindings(store), EscapedValuesDuringBind,

809 RegionStoreMaxBindingFanOutPlusOne);

810 }

811

812 void printJson(raw_ostream &Out, Store S, const char *NL = "\n",

813 unsigned int Space = 0, bool IsDot = false) const override;

814

815 void iterBindings(Store store, BindingsHandler& f) override {

816 RegionBindingsRef B = getRegionBindings(store);

817 for (const auto &[Region, Cluster] : B) {

818 for (const auto &[Key, Value] : Cluster) {

819 if (!Key.isDirect())

820 continue;

821 if (const SubRegion *R = dyn_cast(Key.getRegion())) {

822

823 if (!f.HandleBinding(*this, store, R, Value))

824 return;

825 }

826 }

827 }

828 }

829};

830

831}

832

833

834

835

836

837std::unique_ptr

839 return std::make_unique(StMgr);

840}

841

842

843

844

845

846namespace {

847

848

849enum GlobalsFilterKind {

850

851 GFK_None,

852

853 GFK_SystemOnly,

854

855 GFK_All

856};

857

858template

859class ClusterAnalysis {

860protected:

861 typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;

862 typedef const MemRegion * WorkListElement;

864

866

868

869 RegionStoreManager &RM;

872

873 RegionBindingsRef B;

874

875

876protected:

878 return B.lookup(R);

879 }

880

881

882

883

884 bool includeEntireMemorySpace(const MemRegion *Base) {

885 return false;

886 }

887

888public:

889 ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,

890 RegionBindingsRef b)

891 : RM(rm), Ctx(StateMgr.getContext()),

892 svalBuilder(StateMgr.getSValBuilder()), B(std::move(b)) {}

893

894 RegionBindingsRef getRegionBindings() const { return B; }

895

896 bool isVisited(const MemRegion *R) {

897 return Visited.count(getCluster(R));

898 }

899

900 void GenerateClusters() {

901

902 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();

903 RI != RE; ++RI){

904 const MemRegion *Base = RI.getKey();

905

907 assert(!Cluster.isEmpty() && "Empty clusters should be removed");

908 static_cast<DERIVED*>(this)->VisitAddedToCluster(Base, Cluster);

909

910

911

912 if (static_cast<DERIVED*>(this)->includeEntireMemorySpace(Base))

913 AddToWorkList(WorkListElement(Base), &Cluster);

914 }

915 }

916

917 bool AddToWorkList(WorkListElement E, const ClusterBindings *C) {

918 if (C && !Visited.insert(C).second)

919 return false;

920 WL.push_back(E);

921 return true;

922 }

923

924 bool AddToWorkList(const MemRegion *R) {

925 return static_cast<DERIVED*>(this)->AddToWorkList(R);

926 }

927

928 void RunWorkList() {

929 while (!WL.empty()) {

930 WorkListElement E = WL.pop_back_val();

931 const MemRegion *BaseR = E;

932

933 static_cast<DERIVED*>(this)->VisitCluster(BaseR, getCluster(BaseR));

934 }

935 }

936

937 void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C) {}

938 void VisitCluster(const MemRegion *baseR, const ClusterBindings *C) {}

939

940 void VisitCluster(const MemRegion *BaseR, const ClusterBindings *C,

941 bool Flag) {

942 static_cast<DERIVED*>(this)->VisitCluster(BaseR, C);

943 }

944};

945}

946

947

948

949

950

951bool RegionStoreManager::scanReachableSymbols(Store S, const MemRegion *R,

952 ScanReachableSymbols &Callbacks) {

953 assert(R == R->getBaseRegion() && "Should only be called for base regions");

954 RegionBindingsRef B = getRegionBindings(S);

956

957 if (!Cluster)

958 return true;

959

960 for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();

961 RI != RE; ++RI) {

962 if (!Callbacks.scan(RI.getData()))

963 return false;

964 }

965

966 return true;

967}

968

972

974

976 assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");

977

978 const MemRegion *Base = K.getConcreteOffsetRegion();

979 const MemRegion *R = K.getRegion();

980

981 while (R != Base) {

982 if (const FieldRegion *FR = dyn_cast(R))

984 Fields.push_back(FR->getDecl());

985

987 }

988}

989

991 assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");

992

993 if (Fields.empty())

994 return true;

995

998

999 ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();

1000 if (Delta >= 0)

1001 return std::equal(FieldsInBindingKey.begin() + Delta,

1002 FieldsInBindingKey.end(),

1003 Fields.begin());

1004 else

1005 return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),

1006 Fields.begin() - Delta);

1007}

1008

1009

1010

1011

1012

1013

1014

1015

1016

1017

1018static void

1021 const SubRegion *Top, BindingKey TopKey,

1022 bool IncludeAllDefaultBindings) {

1024 if (TopKey.hasSymbolicOffset()) {

1026 Top = TopKey.getConcreteOffsetRegion();

1027 TopKey = BindingKey::Make(Top, BindingKey::Default);

1028 }

1029

1030

1031 uint64_t Length = UINT64_MAX;

1033 if (std::optionalnonloc::ConcreteInt ExtentCI =

1035 const llvm::APSInt &ExtentInt = ExtentCI->getValue();

1036 assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());

1037

1039 } else if (const FieldRegion *FR = dyn_cast(Top)) {

1040 if (FR->getDecl()->isBitField())

1041 Length = FR->getDecl()->getBitWidthValue();

1042 }

1043

1044 for (const auto &StoreEntry : Cluster) {

1045 BindingKey NextKey = StoreEntry.first;

1046 if (NextKey.getRegion() == TopKey.getRegion()) {

1047

1048

1049

1050

1051

1052 if (NextKey.getOffset() > TopKey.getOffset() &&

1053 NextKey.getOffset() - TopKey.getOffset() < Length) {

1054

1055

1056 Bindings.push_back(StoreEntry);

1057

1058 } else if (NextKey.getOffset() == TopKey.getOffset()) {

1059

1060

1061

1062

1063

1064

1065 if (IncludeAllDefaultBindings || NextKey.isDirect())

1066 Bindings.push_back(StoreEntry);

1067 }

1068

1069 } else if (NextKey.hasSymbolicOffset()) {

1070 const MemRegion *Base = NextKey.getConcreteOffsetRegion();

1072

1073

1074

1075 if (IncludeAllDefaultBindings || NextKey.isDirect())

1077 Bindings.push_back(StoreEntry);

1078 } else if (const SubRegion *BaseSR = dyn_cast(Base)) {

1079

1080

1081 if (BaseSR->isSubRegionOf(Top))

1083 Bindings.push_back(StoreEntry);

1084 }

1085 }

1086 }

1087}

1088

1089static void

1092 const SubRegion *Top, bool IncludeAllDefaultBindings) {

1094 BindingKey::Make(Top, BindingKey::Default),

1095 IncludeAllDefaultBindings);

1096}

1097

1098LimitedRegionBindingsRef

1100 const SubRegion *Top) {

1101 BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);

1102 const MemRegion *ClusterHead = TopKey.getBaseRegion();

1103

1104 if (Top == ClusterHead) {

1105

1107 }

1108

1110 if (!Cluster) {

1111

1112

1113 if (TopKey.hasSymbolicOffset()) {

1114 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();

1115 return B.addBinding(Concrete, BindingKey::Default, UnknownVal());

1116 }

1117 return B;

1118 }

1119

1120 SmallVector<BindingPair, 32> Bindings;

1122 false);

1123

1125 for (BindingKey Key : llvm::make_first_range(Bindings))

1127

1128

1129

1130

1131

1132 if (TopKey.hasSymbolicOffset()) {

1133 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();

1134 Result = Result.add(BindingKey::Make(Concrete, BindingKey::Default),

1135 UnknownVal());

1136 }

1137

1138 if (Result.isEmpty())

1141}

1142

1143namespace {

1144class InvalidateRegionsWorker : public ClusterAnalysis

1145{

1147 unsigned Count;

1148 const LocationContext *LCtx;

1150 RegionAndSymbolInvalidationTraits &ITraits;

1152 GlobalsFilterKind GlobalsFilter;

1153public:

1154 InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,

1156 unsigned count, const LocationContext *lctx,

1158 RegionAndSymbolInvalidationTraits &ITraitsIn,

1160 GlobalsFilterKind GFK)

1161 : ClusterAnalysis(rm, stateMgr, b), Elem(elem),

1162 Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),

1163 GlobalsFilter(GFK) {}

1164

1165 void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);

1166 void VisitBinding(SVal V);

1167

1168 using ClusterAnalysis::AddToWorkList;

1169

1170 bool AddToWorkList(const MemRegion *R);

1171

1172

1173

1174 bool includeEntireMemorySpace(const MemRegion *Base);

1175

1176

1177

1178 bool isInitiallyIncludedGlobalRegion(const MemRegion *R);

1179};

1180}

1181

1182bool InvalidateRegionsWorker::AddToWorkList(const MemRegion *R) {

1183 bool doNotInvalidateSuperRegion = ITraits.hasTrait(

1185 const MemRegion *BaseR = doNotInvalidateSuperRegion ? R : R->getBaseRegion();

1186 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));

1187}

1188

1189void InvalidateRegionsWorker::VisitBinding(SVal V) {

1190

1191 if (SymbolRef Sym = V.getAsSymbol())

1192 IS.insert(Sym);

1193

1194 if (const MemRegion *R = V.getAsRegion()) {

1195 AddToWorkList(R);

1196 return;

1197 }

1198

1199

1200 if (std::optionalnonloc::LazyCompoundVal LCS =

1201 V.getAsnonloc::LazyCompoundVal()) {

1202

1203

1204

1205 for (SVal V : RM.getInterestingValues(*LCS))

1207 VisitBinding(V);

1208

1209 return;

1210 }

1211}

1212

1213void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,

1215

1216 bool PreserveRegionsContents =

1219

1220 if (C) {

1221 for (SVal Val : llvm::make_second_range(*C))

1222 VisitBinding(Val);

1223

1224

1225 if (!PreserveRegionsContents)

1227 }

1228

1229 if (const auto *TO = dyn_cast(baseR)) {

1230 if (const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {

1231

1232

1233

1234

1235 if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {

1236 using namespace ast_matchers;

1237

1238 const char *DeclBind = "DeclBind";

1240 to(varDecl(hasStaticStorageDuration()).bind(DeclBind)))));

1241 auto Matches =

1242 match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),

1243 RD->getASTContext());

1244

1245 for (BoundNodes &Match : Matches) {

1246 auto *VD = Match.getNodeAs(DeclBind);

1247 const VarRegion *ToInvalidate =

1248 RM.getRegionManager().getVarRegion(VD, LCtx);

1249 AddToWorkList(ToInvalidate);

1250 }

1251 }

1252 }

1253 }

1254

1255

1256

1257 if (const BlockDataRegion *BR = dyn_cast(baseR)) {

1258 for (auto Var : BR->referenced_vars()) {

1259 const VarRegion *VR = Var.getCapturedRegion();

1260 const VarDecl *VD = VR->getDecl();

1262 AddToWorkList(VR);

1263 }

1265

1266

1267

1268

1269

1270 SVal V = RM.getBinding(B, loc::MemRegionVal(VR));

1271 if (std::optional L = V.getAs()) {

1272 if (const MemRegion *LR = L->getAsRegion())

1273 AddToWorkList(LR);

1274 }

1275 }

1276 }

1277 return;

1278 }

1279

1280

1281 if (const SymbolicRegion *SR = dyn_cast(baseR))

1282 IS.insert(SR->getSymbol());

1283

1284

1285 if (PreserveRegionsContents)

1286 return;

1287

1288

1289 if (Regions)

1290 Regions->push_back(baseR);

1291

1293

1294

1295 DefinedOrUnknownSVal V =

1297 B = B.addBinding(baseR, BindingKey::Default, V);

1298 return;

1299 }

1300

1302 return;

1303

1306

1307 if (isInitiallyIncludedGlobalRegion(baseR)) {

1308

1309

1310

1311 return;

1312 }

1313

1315

1316

1317 DefinedOrUnknownSVal V =

1319 B = B.addBinding(baseR, BindingKey::Default, V);

1320 return;

1321 }

1322

1324 bool doNotInvalidateSuperRegion = ITraits.hasTrait(

1325 baseR,

1327

1328 if (doNotInvalidateSuperRegion) {

1329

1330

1331 std::optional<uint64_t> NumElements;

1332

1333

1334 if (const ConstantArrayType *CAT = dyn_cast(AT))

1335 NumElements = CAT->getZExtSize();

1336 if (!NumElements)

1337 goto conjure_default;

1338 QualType ElementTy = AT->getElementType();

1340 const RegionOffset &RO = baseR->getAsOffset();

1341 const MemRegion *SuperR = baseR->getBaseRegion();

1343

1344

1345 if (SuperR)

1346 AddToWorkList(SuperR);

1347 goto conjure_default;

1348 }

1349

1351 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;

1352 bool UpperOverflow = UpperOffset < LowerOffset;

1353

1354

1355

1356 if (!SuperR)

1357 goto conjure_default;

1358

1360 if (C)

1361 goto conjure_default;

1362

1363 for (const auto &[BK, V] : *C) {

1364 std::optional<uint64_t> ROffset =

1365 BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();

1366

1367

1368

1369 if (!ROffset ||

1370 ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||

1371 (UpperOverflow &&

1372 (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||

1373 (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {

1374 B = B.removeBinding(BK);

1375

1376

1377 const MemRegion *R = V.getAsRegion();

1378 if (isa_and_nonnull(R))

1379 VisitBinding(V);

1380 }

1381 }

1382 }

1383 conjure_default:

1384

1386 baseR, Elem, LCtx, AT->getElementType(), Count);

1387 B = B.addBinding(baseR, BindingKey::Default, V);

1388 return;

1389 }

1390

1391 DefinedOrUnknownSVal V =

1394 B = B.addBinding(baseR, BindingKey::Direct, V);

1395}

1396

1397bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(

1398 const MemRegion *R) {

1399 switch (GlobalsFilter) {

1400 case GFK_None:

1401 return false;

1402 case GFK_SystemOnly:

1404 case GFK_All:

1406 }

1407

1408 llvm_unreachable("unknown globals filter");

1409}

1410

1411bool InvalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {

1412 if (isInitiallyIncludedGlobalRegion(Base))

1413 return true;

1414

1415 const MemSpaceRegion *MemSpace = Base->getRawMemorySpace();

1416 return ITraits.hasTrait(MemSpace,

1418}

1419

1420RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(

1422 const LocationContext *LCtx, RegionBindingsRef B,

1423 InvalidatedRegions *Invalidated) {

1424

1425

1426 const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);

1428 (const void *)GS, Elem, LCtx,

1429 Ctx.IntTy, Count);

1430

1431 B = B.removeBinding(GS)

1432 .addBinding(BindingKey::Make(GS, BindingKey::Default), V);

1433

1434

1435

1436 if (Invalidated)

1437 Invalidated->push_back(GS);

1438

1439 return B;

1440}

1441

1442void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,

1443 ArrayRef Values,

1444 InvalidatedRegions *TopLevelRegions) {

1445 for (SVal V : Values) {

1446 if (auto LCS = V.getAsnonloc::LazyCompoundVal()) {

1447 for (SVal S : getInterestingValues(*LCS))

1448 if (const MemRegion *R = S.getAsRegion())

1449 W.AddToWorkList(R);

1450

1451 continue;

1452 }

1453

1454 if (const MemRegion *R = V.getAsRegion()) {

1455 if (TopLevelRegions)

1456 TopLevelRegions->push_back(R);

1457 W.AddToWorkList(R);

1458 continue;

1459 }

1460 }

1461}

1462

1463StoreRef RegionStoreManager::invalidateRegions(

1466 RegionAndSymbolInvalidationTraits &ITraits,

1467 InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {

1468 GlobalsFilterKind GlobalsFilter;

1470 if (Call->isInSystemHeader())

1471 GlobalsFilter = GFK_SystemOnly;

1472 else

1473 GlobalsFilter = GFK_All;

1474 } else {

1475 GlobalsFilter = GFK_None;

1476 }

1477

1478 RegionBindingsRef B = getRegionBindings(store);

1479 InvalidateRegionsWorker W(*this, StateMgr, B, Elem, Count, LCtx, IS, ITraits,

1480 Invalidated, GlobalsFilter);

1481

1482

1483 W.GenerateClusters();

1484

1485

1486 populateWorkList(W, Values, TopLevelRegions);

1487

1488 W.RunWorkList();

1489

1490

1491 B = W.getRegionBindings();

1492

1493

1494

1495

1496

1497 switch (GlobalsFilter) {

1498 case GFK_All:

1499 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, Elem,

1500 Count, LCtx, B, Invalidated);

1501 [[fallthrough]];

1502 case GFK_SystemOnly:

1503 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, Elem,

1504 Count, LCtx, B, Invalidated);

1505 [[fallthrough]];

1506 case GFK_None:

1507 break;

1508 }

1509

1510 return StoreRef(B.asStore(), *this);

1511}

1512

1513

1514

1515

1516

1517

1518

1519

1520

1521

1522

1523SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) {

1525 return Array;

1526

1528 return UnknownVal();

1529

1530 const SubRegion *R =

1531 cast(Array.castAsloc::MemRegionVal().getRegion());

1533 return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));

1534}

1535

1536

1537

1538

1539

1543

1544

1545

1546

1547

1548

1549

1550 if (L.getAsloc::ConcreteInt()) {

1551 return UnknownVal();

1552 }

1553 if (!L.getAsloc::MemRegionVal()) {

1554 return UnknownVal();

1555 }

1556

1557 const MemRegion *MR = L.castAsloc::MemRegionVal().getRegion();

1558

1560 return UnknownVal();

1561 }

1562

1563

1564 if (T.isNull()) {

1565 if (const auto *TVR = dyn_cast(MR))

1566 T = TVR->getValueType();

1567 else if (const auto *TR = dyn_cast(MR))

1569 else if (const auto *SR = dyn_cast(MR))

1570 T = SR->getPointeeStaticType();

1571 }

1572 assert(T.isNull() && "Unable to auto-detect binding type!");

1573 assert(T->isVoidType() && "Attempting to dereference a void pointer!");

1574

1577

1578

1579

1582

1583

1584

1586 return UnknownVal();

1587

1588

1589

1590

1591

1592

1593

1594

1595

1597 return getBindingForStruct(B, R);

1598

1599

1601 return createLazyBinding(B, R);

1602

1605 return getBindingForArray(B, R);

1606 else

1607 return UnknownVal();

1608 }

1609

1610

1612 return UnknownVal();

1613

1614 if (const FieldRegion* FR = dyn_cast(R))

1615 return svalBuilder.evalCast(getBindingForField(B, FR), T, QualType{});

1616

1617 if (const ElementRegion* ER = dyn_cast(R)) {

1618

1619

1620

1621

1622

1623 return svalBuilder.evalCast(getBindingForElement(B, ER), T, QualType{});

1624 }

1625

1626 if (const ObjCIvarRegion *IVR = dyn_cast(R)) {

1627

1628

1629

1630

1631

1632

1633 return svalBuilder.evalCast(getBindingForObjCIvar(B, IVR), T, QualType{});

1634 }

1635

1636 if (const VarRegion *VR = dyn_cast(R)) {

1637

1638

1639

1640

1641

1642

1643 return svalBuilder.evalCast(getBindingForVar(B, VR), T, QualType{});

1644 }

1645

1646 const SVal *V = B.lookup(R, BindingKey::Direct);

1647

1648

1649 if (V)

1650 return *V;

1651

1652

1653

1654

1656

1657

1658

1659

1660 return UndefinedVal();

1661 }

1662

1663

1665}

1666

1669 if (const TypedValueRegion *TVR = dyn_cast(R))

1670 RegionTy = TVR->getValueType();

1671

1672 if (const SymbolicRegion *SR = dyn_cast(R))

1673 RegionTy = SR->getSymbol()->getType();

1674

1675 return RegionTy;

1676}

1677

1678

1679

1680

1681

1682

1683

1684

1685static std::optionalnonloc::LazyCompoundVal

1687 const SubRegion *R, bool AllowSubregionBindings) {

1688 std::optional V = B.getDefaultBinding(R);

1689 if (V)

1690 return std::nullopt;

1691

1692 std::optionalnonloc::LazyCompoundVal LCV =

1694 if (!LCV)

1695 return std::nullopt;

1696

1697

1698

1700 if (!RegionTy.isNull() &&

1702 QualType SourceRegionTy = LCV->getRegion()->getValueType();

1704 return std::nullopt;

1705 }

1706

1707 if (!AllowSubregionBindings) {

1708

1709

1712 true);

1714 return std::nullopt;

1715 }

1716

1717 return *LCV;

1718}

1719

1720std::pair<Store, const SubRegion *>

1722 const SubRegion *R,

1723 const SubRegion *originalRegion) {

1724 if (originalRegion != R) {

1725 if (std::optionalnonloc::LazyCompoundVal V =

1727 return std::make_pair(V->getStore(), V->getRegion());

1728 }

1729

1730 typedef std::pair<Store, const SubRegion *> StoreRegionPair;

1731 StoreRegionPair Result = StoreRegionPair();

1732

1733 if (const ElementRegion *ER = dyn_cast(R)) {

1735 originalRegion);

1736

1738 Result.second = MRMgr.getElementRegionWithSuper(ER, Result.second);

1739

1740 } else if (const FieldRegion *FR = dyn_cast(R)) {

1742 originalRegion);

1743

1745 Result.second = MRMgr.getFieldRegionWithSuper(FR, Result.second);

1746

1747 } else if (const CXXBaseObjectRegion *BaseReg =

1748 dyn_cast(R)) {

1749

1750

1752 originalRegion);

1753

1755 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,

1757 }

1758

1760}

1761

1762

1763

1764

1765

1766

1767static SmallVector<uint64_t, 2>

1769 assert(CAT && "ConstantArrayType should not be null");

1772 do {

1774 } while ((CAT = dyn_cast(CAT->getElementType())));

1775 return Extents;

1776}

1777

1778

1779

1780

1781

1782

1783

1784

1785

1786

1787

1788

1789

1790

1791

1792static std::pair<SmallVector<SVal, 2>, const MemRegion *>

1794 assert(ER && "ConstantArrayType should not be null");

1797 do {

1798 SValOffsets.push_back(ER->getIndex());

1800 ER = dyn_cast(Base);

1801 } while (ER);

1802 return {SValOffsets, Base};

1803}

1804

1805

1806

1807

1808

1809

1810

1811

1812

1813

1814

1815

1816

1817

1818

1819

1820

1821

1822

1823

1824

1825

1826static std::optional

1830

1831

1832

1833

1834

1835

1836

1837

1838

1839

1840

1841

1842

1843

1844

1845

1846

1847 DstOffsets.resize(SrcOffsets.size());

1848 auto ExtentIt = ArrayExtents.begin();

1849 auto OffsetIt = DstOffsets.begin();

1850

1851 for (SVal V : llvm::reverse(SrcOffsets)) {

1853

1854 const llvm::APSInt &Offset = CI->getValue();

1855 if (Offset.isNegative() || Offset.uge(*(ExtentIt++)))

1857

1858 *(OffsetIt++) = Offset.getZExtValue();

1859 continue;

1860 }

1861

1862

1863

1865 }

1866 return std::nullopt;

1867}

1868

1869std::optional RegionStoreManager::getConstantValFromConstArrayInitializer(

1871 assert(R && "ElementRegion should not be null");

1872

1873

1874 SmallVector<SVal, 2> SValOffsets;

1875 const MemRegion *Base;

1877 const VarRegion *VR = dyn_cast(Base);

1878 if (!VR)

1879 return std::nullopt;

1880

1881 assert(!SValOffsets.empty() && "getElementRegionOffsets guarantees the "

1882 "offsets vector is not empty.");

1883

1884

1885

1886 const VarDecl *VD = VR->getDecl();

1890 return std::nullopt;

1891

1892

1893

1894

1895

1896

1897

1898

1899

1900

1902

1903

1905 return std::nullopt;

1906

1907

1908

1910 if (!CAT)

1911 return std::nullopt;

1912

1913

1915

1916

1917

1918

1919

1920

1921

1922 if (SValOffsets.size() != Extents.size())

1923 return std::nullopt;

1924

1925 SmallVector<uint64_t, 2> ConcreteOffsets;

1927 SValOffsets, Extents, ConcreteOffsets))

1928 return *V;

1929

1930

1931

1932

1933 if (const auto *ILE = dyn_cast(Init))

1934 return getSValFromInitListExpr(ILE, ConcreteOffsets, R->getElementType());

1935

1936

1937

1938

1939 if (const auto *SL = dyn_cast(Init))

1940 return getSValFromStringLiteral(SL, ConcreteOffsets.front(),

1942

1943

1944

1945 return std::nullopt;

1946}

1947

1948

1949

1950

1951

1952

1953

1954

1955

1956

1957

1958

1959

1960

1961

1962

1963

1964

1965std::optional RegionStoreManager::getSValFromInitListExpr(

1966 const InitListExpr *ILE, const SmallVector<uint64_t, 2> &Offsets,

1967 QualType ElemT) {

1968 assert(ILE && "InitListExpr should not be null");

1969

1970 for (uint64_t Offset : Offsets) {

1971

1972

1973

1974

1975

1977 if (const auto *SL = dyn_cast(ILE->getInit(0)))

1978 return getSValFromStringLiteral(SL, Offset, ElemT);

1979

1980

1981

1982

1985

1986 const Expr *E = ILE->getInit(Offset);

1987 const auto *IL = dyn_cast(E);

1988 if (!IL)

1989

1990

1992

1993

1994 ILE = IL;

1995 }

1996

1997 assert(ILE);

1998

1999

2000

2001 return std::nullopt;

2002}

2003

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013

2014

2015

2016

2017

2018

2019

2020

2021

2022

2023

2024

2025

2026

2027

2028

2029SVal RegionStoreManager::getSValFromStringLiteral(const StringLiteral *SL,

2030 uint64_t Offset,

2031 QualType ElemT) {

2032 assert(SL && "StringLiteral should not be null");

2033

2034

2035

2037 return svalBuilder.makeIntVal(Code, ElemT);

2038}

2039

2043 assert(BaseRegion);

2048 if (const std::optional &ParentValue =

2049 B.getDirectBinding(BaseRegion)) {

2050 if (SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())

2052

2053 if (ParentValue->isUndef())

2055

2056

2057

2059 }

2060 }

2061 }

2062 return std::nullopt;

2063}

2064

2066 const ElementRegion* R) {

2067

2068 if (const std::optional &V = B.getDirectBinding(R))

2069 return *V;

2070

2072

2073

2074 if (const StringRegion *StrR = dyn_cast(superR)) {

2075

2076

2077

2080 return UnknownVal();

2081 if (const auto CI = R->getIndex().getAsnonloc::ConcreteInt()) {

2082 const llvm::APSInt &Idx = CI->getValue();

2083 if (Idx < 0)

2084 return UndefinedVal();

2085 const StringLiteral *SL = StrR->getStringLiteral();

2086 return getSValFromStringLiteral(SL, Idx.getZExtValue(), T);

2087 }

2089 if (std::optional V = getConstantValFromConstArrayInitializer(B, R))

2090 return *V;

2091 }

2092

2093

2095 return UnknownVal();

2096

2097

2098

2099

2100

2101

2102

2104

2105

2107 return UnknownVal();

2108

2109 if (const TypedValueRegion *baseR = dyn_cast(O.getRegion()))

2111 return *V;

2112

2113 return getBindingForFieldOrElementCommon(B, R, R->getElementType());

2114}

2115

2117 const FieldRegion* R) {

2118

2119

2120 if (const std::optional &V = B.getDirectBinding(R))

2121 return *V;

2122

2123

2124 const FieldDecl *FD = R->getDecl();

2125 QualType Ty = FD->getType();

2127 if (const auto *VR = dyn_cast(superR)) {

2128 const VarDecl *VD = VR->getDecl();

2129 QualType RecordVarTy = VD->getType();

2131

2132

2133

2137 if (const auto *InitList = dyn_cast(Init)) {

2138 if (Index < InitList->getNumInits()) {

2139 if (const Expr *FieldInit = InitList->getInit(Index))

2140 if (std::optional V = svalBuilder.getConstantVal(FieldInit))

2141 return *V;

2142 } else {

2144 }

2145 }

2146 }

2147

2148

2149

2150

2151

2152

2153

2154

2155

2156

2157

2158

2159

2160

2161

2162

2163

2164 if (const auto *Base = dyn_cast(R->getBaseRegion()))

2166 return *V;

2167

2168 return getBindingForFieldOrElementCommon(B, R, Ty);

2169}

2170

2171std::optional RegionStoreManager::getBindingForDerivedDefaultValue(

2173 const TypedValueRegion *R, QualType Ty) {

2174

2175 if (const std::optional &D = B.getDefaultBinding(superR)) {

2176 SVal val = *D;

2179

2182

2184 return val;

2185

2186

2187

2189 return val;

2190

2191 llvm_unreachable("Unknown default value");

2192 }

2193

2194 return std::nullopt;

2195}

2196

2197SVal RegionStoreManager::getLazyBinding(const SubRegion *LazyBindingRegion,

2198 RegionBindingsRef LazyBinding) {

2200 if (const ElementRegion *ER = dyn_cast(LazyBindingRegion))

2201 Result = getBindingForElement(LazyBinding, ER);

2202 else

2203 Result = getBindingForField(LazyBinding,

2205

2206

2207

2208

2209

2210

2211

2212

2213

2214

2215

2216

2217

2218

2219

2220 if (Result.isUndef())

2221 Result = UnknownVal();

2222

2224}

2225

2226SVal

2228 const TypedValueRegion *R,

2229 QualType Ty) {

2230

2231

2232

2233

2234

2235 Store lazyBindingStore = nullptr;

2236 const SubRegion *lazyBindingRegion = nullptr;

2237 std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);

2238 if (lazyBindingRegion)

2239 return getLazyBinding(lazyBindingRegion,

2240 getRegionBindings(lazyBindingStore));

2241

2242

2243

2244 bool hasSymbolicIndex = false;

2245

2246

2247

2248

2249

2250

2251

2252

2253

2254

2255

2256

2257

2258

2259

2260 bool hasPartialLazyBinding = false;

2261

2262 const SubRegion *SR = R;

2263 while (SR) {

2265 if (std::optional D =

2266 getBindingForDerivedDefaultValue(B, Base, R, Ty)) {

2267 if (D->getAsnonloc::LazyCompoundVal()) {

2268 hasPartialLazyBinding = true;

2269 break;

2270 }

2271

2272 return *D;

2273 }

2274

2275 if (const ElementRegion *ER = dyn_cast(Base)) {

2276 NonLoc index = ER->getIndex();

2278 hasSymbolicIndex = true;

2279 }

2280

2281

2282

2283 SR = dyn_cast(Base);

2284 }

2285

2288

2289

2290 if (const TypedValueRegion *typedSuperR =

2292 if (typedSuperR->getValueType()->isVectorType())

2293 return UnknownVal();

2294 }

2295 }

2296

2297

2298

2299

2300

2301 if (hasSymbolicIndex)

2302 return UnknownVal();

2303

2304

2305

2306

2308 if (const std::optional &V = B.getDefaultBinding(R))

2309 return *V;

2310 return UndefinedVal();

2311 }

2312 }

2313

2314

2316}

2317

2319 const ObjCIvarRegion* R) {

2320

2321 if (const std::optional &V = B.getDirectBinding(R))

2322 return *V;

2323

2325

2326

2327 if (const std::optional &V = B.getDefaultBinding(superR)) {

2328 if (SymbolRef parentSym = V->getAsSymbol())

2330

2331

2332 return UnknownVal();

2333 }

2334

2335 return getBindingForLazySymbol(R);

2336}

2337

2339 const VarRegion *R) {

2340

2341

2342 if (std::optional V = B.getDirectBinding(R))

2343 return *V;

2344

2345 if (std::optional V = B.getDefaultBinding(R))

2346 return *V;

2347

2348

2349 const VarDecl *VD = R->getDecl();

2351

2352

2355

2356

2360 return *V;

2361

2362

2363

2364

2365 return UnknownVal();

2366 }

2367 }

2368

2369

2370

2373

2376

2377

2378 if (B.isMainAnalysis())

2381 return *V;

2382

2383

2384

2385

2386

2389

2390 if (std::optional V = getBindingForDerivedDefaultValue(B, MS, R, T)) {

2391 assert(V->getAsnonloc::LazyCompoundVal());

2392 return *V;

2393 }

2394

2396 }

2397

2398 return UndefinedVal();

2399}

2400

2401SVal RegionStoreManager::getBindingForLazySymbol(const TypedValueRegion *R) {

2402

2404}

2405

2406const RegionStoreManager::SValListTy &

2407RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {

2408

2409 LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.getCVData());

2410 if (I != LazyBindingsMap.end())

2411 return I->second;

2412

2413

2414 SValListTy List;

2415

2416 const SubRegion *LazyR = LCV.getRegion();

2417 RegionBindingsRef B = getRegionBindings(LCV.getStore());

2418

2419

2420

2422 if (!Cluster)

2423 return (LazyBindingsMap[LCV.getCVData()] = std::move(List));

2424

2425 SmallVector<BindingPair, 32> Bindings;

2427 true);

2428 for (SVal V : llvm::make_second_range(Bindings)) {

2429 if (V.isUnknownOrUndef() || V.isConstant())

2430 continue;

2431

2432 if (auto InnerLCV = V.getAsnonloc::LazyCompoundVal()) {

2433 const SValListTy &InnerList = getInterestingValues(*InnerLCV);

2434 llvm::append_range(List, InnerList);

2435 }

2436

2437 List.push_back(V);

2438 }

2439

2440 return (LazyBindingsMap[LCV.getCVData()] = std::move(List));

2441}

2442

2444 const TypedValueRegion *R) {

2445 if (std::optionalnonloc::LazyCompoundVal V =

2447 return *V;

2448

2449 return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R);

2450}

2451

2453 const TypedValueRegion *R) {

2454 const RecordDecl *RD =

2457 return UnknownVal();

2458

2459

2460

2461

2462

2463 return createLazyBinding(B, R);

2464}

2465

2467 const TypedValueRegion *R) {

2469 "Only constant array types can have compound bindings.");

2470

2471 return createLazyBinding(B, R);

2472}

2473

2474bool RegionStoreManager::includedInBindings(Store store,

2475 const MemRegion *region) const {

2476 RegionBindingsRef B = getRegionBindings(store);

2478

2479

2480 if (B.lookup(region))

2481 return true;

2482

2483

2484 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {

2486 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();

2487 CI != CE; ++CI) {

2488 SVal D = CI.getData();

2489 if (const MemRegion *R = D.getAsRegion())

2491 return true;

2492 }

2493 }

2494

2495 return false;

2496}

2497

2498

2499

2500

2501

2502StoreRef RegionStoreManager::killBinding(Store ST, Loc L) {

2503 if (std::optionalloc::MemRegionVal LV = L.getAsloc::MemRegionVal())

2504 if (const MemRegion* R = LV->getRegion())

2505 return StoreRef(getRegionBindings(ST)

2506 .removeBinding(R)

2507 .asImmutableMap()

2508 .getRootWithoutRetain(),

2509 *this);

2510

2511 return StoreRef(ST, *this);

2512}

2513

2514LimitedRegionBindingsRef

2516 llvm::TimeTraceScope TimeScope("RegionStoreManager::bind",

2517 [&L]() { return locDescr(L); });

2518

2521

2522

2523 auto MemRegVal = L.getAsloc::MemRegionVal();

2524 if (!MemRegVal)

2525 return B;

2526

2527 const MemRegion *R = MemRegVal->getRegion();

2528

2529

2530

2531 if (const auto *SymReg = dyn_cast(R)) {

2532 QualType Ty = SymReg->getPointeeStaticType();

2534 Ty = StateMgr.getContext().CharTy;

2535 R = GetElementZeroRegion(SymReg, Ty);

2536 }

2537

2538

2539 if (const TypedValueRegion* TR = dyn_cast(R)) {

2542 return bindArray(B, TR, V);

2544 return bindStruct(B, TR, V);

2546 return bindVector(B, TR, V);

2548 return bindAggregate(B, TR, V);

2549 }

2550

2552 "'this' pointer is not an l-value and is not assignable");

2553

2554

2555 auto NewB = removeSubRegionBindings(B, cast(R));

2556

2557

2559 : BindingKey::Direct;

2560 return NewB.addBinding(BindingKey::Make(R, KeyKind), V);

2561}

2562

2563LimitedRegionBindingsRef

2565 const MemRegion *R, QualType T) {

2567 return B;

2568

2569 SVal V;

2570

2576

2577

2579 }

2580 else {

2581

2582

2583

2584

2586 V = UnknownVal();

2587 }

2588

2589 return B.addBinding(R, BindingKey::Default, V);

2590}

2591

2592std::optional RegionStoreManager::tryBindSmallArray(

2594 const ArrayType *AT, nonloc::LazyCompoundVal LCV) {

2597

2598 auto CAT = dyn_cast(AT);

2599

2600

2601 if (!CAT)

2602 return std::nullopt;

2603

2606 return std::nullopt;

2607

2608

2610 if (ArrSize > SmallArrayLimit)

2611 return std::nullopt;

2612

2613 LimitedRegionBindingsRef NewB = B;

2614

2615 for (uint64_t i = 0; i < ArrSize; ++i) {

2617 const ElementRegion *SrcER =

2618 MRMgr.getElementRegion(Ty, Idx, LCV.getRegion(), Ctx);

2619 SVal V = getBindingForElement(getRegionBindings(LCV.getStore()), SrcER);

2620

2621 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);

2622 NewB = bind(NewB, loc::MemRegionVal(DstER), V);

2623 }

2624

2625 return NewB;

2626}

2627

2628LimitedRegionBindingsRef

2630 const TypedValueRegion *R, SVal Init) {

2631 llvm::TimeTraceScope TimeScope("RegionStoreManager::bindArray",

2635

2638 std::optional<uint64_t> Size;

2639

2640 if (const ConstantArrayType* CAT = dyn_cast(AT))

2642

2643

2644

2645

2646 if (std::optionalloc::MemRegionVal MRV = Init.getAsloc::MemRegionVal()) {

2647 SVal V = getBinding(B.asStore(), *MRV, R->getValueType());

2648 return bindAggregate(B, R, V);

2649 }

2650

2651

2652

2653 if (Init.isConstant())

2654 return bindAggregate(B, R, Init);

2655

2656 if (std::optional LCV = Init.getAsnonloc::LazyCompoundVal()) {

2657 if (std::optional NewB = tryBindSmallArray(B, R, AT, *LCV))

2658 return *NewB;

2659 return bindAggregate(B, R, Init);

2660 }

2661

2663 return bindAggregate(B, R, Init);

2664

2665 if (Init.isUnknown())

2666 return bindAggregate(B, R, UnknownVal());

2667

2668

2669 const nonloc::CompoundVal& CV = Init.castAsnonloc::CompoundVal();

2672

2673 LimitedRegionBindingsRef NewB = B;

2674

2675 for (; Size ? i < *Size : true; ++i, ++VI) {

2676

2677 if (VI == VE)

2678 break;

2681

2683 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);

2684

2686 NewB = bindStruct(NewB, ER, *VI);

2688 NewB = bindArray(NewB, ER, *VI);

2689 else

2690 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);

2691 }

2692

2693

2694

2695

2696 if (!Size || i < *Size)

2697 NewB = setImplicitDefaultValue(NewB, R, ElementTy);

2698

2699 return NewB;

2700}

2701

2702LimitedRegionBindingsRef

2704 const TypedValueRegion *R, SVal V) {

2705 llvm::TimeTraceScope TimeScope("RegionStoreManager::bindVector",

2709

2711 const VectorType *VT = T->castAs();

2712

2713

2715 return bindAggregate(B, R, V);

2716

2717

2718

2719

2721 return bindAggregate(B, R, UnknownVal());

2722 }

2723

2725 nonloc::CompoundVal CV = V.castAsnonloc::CompoundVal();

2727 unsigned index = 0, numElements = VT->getNumElements();

2728 LimitedRegionBindingsRef NewB = B;

2729

2730 for ( ; index != numElements ; ++index) {

2731 if (VI == VE)

2732 break;

2733

2736

2738 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);

2739

2741 NewB = bindArray(NewB, ER, *VI);

2743 NewB = bindStruct(NewB, ER, *VI);

2744 else

2745 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);

2746 }

2747 return NewB;

2748}

2749

2750std::optional RegionStoreManager::tryBindSmallStruct(

2752 const RecordDecl *RD, nonloc::LazyCompoundVal LCV) {

2755

2757

2758 if (const CXXRecordDecl *Class = dyn_cast(RD))

2759 if (Class->getNumBases() != 0 || Class->getNumVBases() != 0)

2760 return std::nullopt;

2761

2762 for (const auto *FD : RD->fields()) {

2764 continue;

2765

2766

2767

2768 if (Fields.size() == SmallStructLimit)

2769 return std::nullopt;

2770

2771 QualType Ty = FD->getType();

2772

2773

2776 continue;

2777

2779 return std::nullopt;

2780

2781 Fields.push_back(FD);

2782 }

2783

2784 LimitedRegionBindingsRef NewB = B;

2785

2786 for (const FieldDecl *Field : Fields) {

2787 const FieldRegion *SourceFR = MRMgr.getFieldRegion(Field, LCV.getRegion());

2788 SVal V = getBindingForField(getRegionBindings(LCV.getStore()), SourceFR);

2789

2790 const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);

2791 NewB = bind(NewB, loc::MemRegionVal(DestFR), V);

2792 }

2793

2794 return NewB;

2795}

2796

2797LimitedRegionBindingsRef

2799 const TypedValueRegion *R, SVal V) {

2800 llvm::TimeTraceScope TimeScope("RegionStoreManager::bindStruct",

2804

2807

2810 return B;

2811

2812

2813 if (std::optionalnonloc::LazyCompoundVal LCV =

2814 V.getAsnonloc::LazyCompoundVal()) {

2815 if (std::optional NewB = tryBindSmallStruct(B, R, RD, *LCV))

2816 return *NewB;

2817 return bindAggregate(B, R, V);

2818 }

2820 return bindAggregate(B, R, V);

2821

2822

2823

2824

2826 return bindAggregate(B, R, UnknownVal());

2827

2828

2829

2830

2831

2832

2833

2834

2835

2836

2837

2838

2839

2840

2841

2842

2843

2844 const nonloc::CompoundVal& CV = V.castAsnonloc::CompoundVal();

2846

2847 LimitedRegionBindingsRef NewB = B;

2848

2849

2850

2851 if (const auto *CRD = dyn_cast(RD)) {

2852

2853

2854

2855

2856

2857

2858

2859 assert((CRD->isAggregate() || (Ctx.getLangOpts().ObjC && VI == VE)) &&

2860 "Non-aggregates are constructed with a constructor!");

2861

2862 for (const auto &B : CRD->bases()) {

2863

2864 assert(!B.isVirtual() && "Aggregates cannot have virtual base classes!");

2865

2866 if (VI == VE)

2867 break;

2870

2871 QualType BTy = B.getType();

2873

2875 assert(BRD && "Base classes must be C++ classes!");

2876

2877 const CXXBaseObjectRegion *BR =

2878 MRMgr.getCXXBaseObjectRegion(BRD, R, false);

2879

2880 NewB = bindStruct(NewB, BR, *VI);

2881

2882 ++VI;

2883 }

2884 }

2885

2887

2889

2890 if (VI == VE)

2891 break;

2892

2895

2896

2897 if (FI->isUnnamedBitField())

2898 continue;

2899

2900 QualType FTy = FI->getType();

2901 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);

2902

2904 NewB = bindArray(NewB, FR, *VI);

2906 NewB = bindStruct(NewB, FR, *VI);

2907 else

2908 NewB = bind(NewB, loc::MemRegionVal(FR), *VI);

2909 ++VI;

2910 }

2911

2914

2915

2916 if (FI != FE) {

2917 NewB = NewB.addBinding(R, BindingKey::Default,

2919 }

2920

2921 return NewB;

2922}

2923

2924LimitedRegionBindingsRef

2926 const TypedRegion *R, SVal Val) {

2927 llvm::TimeTraceScope TimeScope("RegionStoreManager::bindAggregate",

2931

2932

2933

2934 return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val);

2935}

2936

2937

2938

2939

2940

2941namespace {

2942class RemoveDeadBindingsWorker

2943 : public ClusterAnalysis {

2944 SmallVector<const SymbolicRegion *, 12> Postponed;

2945 SymbolReaper &SymReaper;

2946 const StackFrameContext *CurrentLCtx;

2947

2948public:

2949 RemoveDeadBindingsWorker(RegionStoreManager &rm,

2950 ProgramStateManager &stateMgr,

2951 RegionBindingsRef b, SymbolReaper &symReaper,

2952 const StackFrameContext *LCtx)

2953 : ClusterAnalysis(rm, stateMgr, b),

2954 SymReaper(symReaper), CurrentLCtx(LCtx) {}

2955

2956

2957 void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C);

2958 void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);

2959 using ClusterAnalysis::VisitCluster;

2960

2961 using ClusterAnalysis::AddToWorkList;

2962

2963 bool AddToWorkList(const MemRegion *R);

2964

2965 bool UpdatePostponed();

2966 void VisitBinding(SVal V);

2967};

2968}

2969

2970bool RemoveDeadBindingsWorker::AddToWorkList(const MemRegion *R) {

2972 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));

2973}

2974

2975void RemoveDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,

2977

2978 if (const VarRegion *VR = dyn_cast(baseR)) {

2979 if (SymReaper.isLive(VR))

2980 AddToWorkList(baseR, &C);

2981

2982 return;

2983 }

2984

2985 if (const SymbolicRegion *SR = dyn_cast(baseR)) {

2986 if (SymReaper.isLive(SR->getSymbol()))

2987 AddToWorkList(SR, &C);

2988 else

2989 Postponed.push_back(SR);

2990

2991 return;

2992 }

2993

2995 AddToWorkList(baseR, &C);

2996 return;

2997 }

2998

2999

3000 if (const CXXThisRegion *TR = dyn_cast(baseR)) {

3001 const auto *StackReg =

3003 const StackFrameContext *RegCtx = StackReg->getStackFrame();

3004 if (CurrentLCtx &&

3005 (RegCtx == CurrentLCtx || RegCtx->isParentOf(CurrentLCtx)))

3006 AddToWorkList(TR, &C);

3007 }

3008}

3009

3010void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR,

3012 if (C)

3013 return;

3014

3015

3016

3017 if (const SymbolicRegion *SymR = dyn_cast(baseR))

3018 SymReaper.markLive(SymR->getSymbol());

3019

3020 for (const auto &[Key, Val] : *C) {

3021

3023

3024 VisitBinding(Val);

3025 }

3026}

3027

3028void RemoveDeadBindingsWorker::VisitBinding(SVal V) {

3029

3030

3031 if (auto LCS = V.getAsnonloc::LazyCompoundVal()) {

3033

3034 for (SVal V : RM.getInterestingValues(*LCS)) {

3035 if (auto DepLCS = V.getAsnonloc::LazyCompoundVal())

3037 else

3038 VisitBinding(V);

3039 }

3040

3041 return;

3042 }

3043

3044

3045 if (const MemRegion *R = V.getAsRegion()) {

3046 AddToWorkList(R);

3048

3049

3050 if (const BlockDataRegion *BR = dyn_cast(R)) {

3051 for (auto Var : BR->referenced_vars())

3052 AddToWorkList(Var.getCapturedRegion());

3053 }

3054 }

3055

3056

3057

3060}

3061

3062bool RemoveDeadBindingsWorker::UpdatePostponed() {

3063

3064

3066

3067 for (const SymbolicRegion *SR : Postponed) {

3068 if (SymReaper.isLive(SR->getSymbol())) {

3069 Changed |= AddToWorkList(SR);

3070 SR = nullptr;

3071 }

3072 }

3073

3075}

3076

3077StoreRef RegionStoreManager::removeDeadBindings(Store store,

3078 const StackFrameContext *LCtx,

3079 SymbolReaper& SymReaper) {

3080 RegionBindingsRef B = getRegionBindings(store);

3081 RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);

3082 W.GenerateClusters();

3083

3084

3085 for (const MemRegion *Reg : SymReaper.regions()) {

3086 W.AddToWorkList(Reg);

3087 }

3088

3089 do W.RunWorkList(); while (W.UpdatePostponed());

3090

3091

3092

3093

3094 for (const MemRegion *Base : llvm::make_first_range(B)) {

3095

3096

3097 if (!W.isVisited(Base))

3098 B = B.removeCluster(Base);

3099 }

3100

3101 return StoreRef(B.asStore(), *this);

3102}

3103

3104

3105

3106

3107

3108void RegionStoreManager::printJson(raw_ostream &Out, Store S, const char *NL,

3109 unsigned int Space, bool IsDot) const {

3110 RegionBindingsRef Bindings = getRegionBindings(S);

3111

3112 Indent(Out, Space, IsDot) << "\"store\": ";

3113

3115 Out << "null," << NL;

3116 return;

3117 }

3118

3119 Out << "{ \"pointer\": \"" << Bindings.asStore() << "\", \"items\": [" << NL;

3120 Bindings.printJson(Out, NL, Space + 1, IsDot);

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

3122}

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 void dump(llvm::raw_ostream &OS, StringRef FunctionName, ArrayRef< CounterExpression > Expressions, ArrayRef< CounterMappingRegion > Regions)

bool is(tok::TokenKind Kind) const

static std::optional< SVal > convertOffsetsFromSvalToUnsigneds(const SmallVector< SVal, 2 > &SrcOffsets, const SmallVector< uint64_t, 2 > ArrayExtents, SmallVector< uint64_t, 2 > &DstOffsets)

Definition RegionStore.cpp:1827

llvm::ImmutableMap< const MemRegion *, ClusterBindings > RegionBindings

Definition RegionStore.cpp:163

static std::optional< SVal > getDerivedSymbolForBinding(RegionBindingsConstRef B, const TypedValueRegion *BaseRegion, const TypedValueRegion *SubReg, const ASTContext &Ctx, SValBuilder &SVB)

Definition RegionStore.cpp:2040

std::pair< BindingKey, SVal > BindingPair

Definition RegionStore.cpp:160

static bool isCompatibleWithFields(BindingKey K, const FieldVector &Fields)

Definition RegionStore.cpp:990

SmallVector< const FieldDecl *, 8 > FieldVector

Definition RegionStore.cpp:973

llvm::ImmutableMap< BindingKey, SVal > ClusterBindings

Definition RegionStore.cpp:158

static bool isUnionField(const FieldRegion *FR)

Definition RegionStore.cpp:969

const LimitedRegionBindingsRef & LimitedRegionBindingsConstRef

Definition RegionStore.cpp:403

static void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields)

Definition RegionStore.cpp:975

static QualType getUnderlyingType(const SubRegion *R)

Definition RegionStore.cpp:1667

llvm::ImmutableMapRef< BindingKey, SVal > ClusterBindingsRef

Definition RegionStore.cpp:159

static SmallVector< uint64_t, 2 > getConstantArrayExtents(const ConstantArrayType *CAT)

This is a helper function for getConstantValFromConstArrayInitializer.

Definition RegionStore.cpp:1768

static std::pair< SmallVector< SVal, 2 >, const MemRegion * > getElementRegionOffsetsWithBase(const ElementRegion *ER)

This is a helper function for getConstantValFromConstArrayInitializer.

Definition RegionStore.cpp:1793

const RegionBindingsRef & RegionBindingsConstRef

Definition RegionStore.cpp:402

static std::optional< nonloc::LazyCompoundVal > getExistingLazyBinding(SValBuilder &SVB, RegionBindingsConstRef B, const SubRegion *R, bool AllowSubregionBindings)

Checks to see if store B has a lazy binding for region R.

Definition RegionStore.cpp:1686

static void collectSubRegionBindings(SmallVectorImpl< BindingPair > &Bindings, SValBuilder &SVB, const ClusterBindings &Cluster, const SubRegion *Top, BindingKey TopKey, bool IncludeAllDefaultBindings)

Collects all bindings in Cluster that may refer to bindings within Top.

Definition RegionStore.cpp:1019

llvm::SmallVector< std::pair< const MemRegion *, SVal >, 4 > Bindings

__PTRDIFF_TYPE__ ptrdiff_t

A signed integer type that is the result of subtracting two pointers.

This class represents the same as RegionBindingsRef, but with a limit on the number of bindings that ...

Definition RegionStore.cpp:333

LimitedRegionBindingsRef removeCluster(const MemRegion *BaseRegion) const

Definition RegionStore.cpp:367

LimitedRegionBindingsRef withValuesEscaped(nonloc::CompoundVal::iterator Begin, nonloc::CompoundVal::iterator End) const

Definition RegionStore.cpp:352

LimitedRegionBindingsRef withValuesEscaped(SVal V) const

Definition RegionStore.cpp:346

LimitedRegionBindingsRef(RegionBindingsRef Base, SmallVectorImpl< SVal > &EscapedValuesDuringBind, std::optional< unsigned > BindingsLeft)

Definition RegionStore.cpp:335

bool hasExhaustedBindingLimit() const

Definition RegionStore.cpp:342

LimitedRegionBindingsRef addBinding(BindingKey K, SVal V) const

Definition RegionStore.cpp:373

LimitedRegionBindingsRef addBinding(const MemRegion *R, BindingKey::Kind k, SVal V) const

Definition RegionStore.cpp:392

LimitedRegionBindingsRef addWithoutDecreasingLimit(const MemRegion *BaseRegion, data_type_ref BindingKeyAndValue) const

Definition RegionStore.cpp:360

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

const ConstantArrayType * getAsConstantArrayType(QualType T) const

static CanQualType getCanonicalType(QualType T)

Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...

const LangOptions & getLangOpts() 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.

CharUnits getTypeSizeInChars(QualType T) const

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

uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const

Return number of constant array elements.

static bool hasSameUnqualifiedType(QualType T1, QualType T2)

Determine whether the given types are equivalent after cvr-qualifiers have been removed.

uint64_t getCharWidth() const

Return the size of the character type, in bits.

QualType getElementType() const

Represents the canonical version of C arrays with a specified constant size.

uint64_t getLimitedSize() const

Return the size zero-extended to uint64_t or UINT64_MAX if the value is larger than UINT64_MAX.

uint64_t getZExtSize() const

Return the size zero-extended as a uint64_t.

unsigned getFieldIndex() const

Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...

const RecordDecl * getParent() const

Returns the parent of this field declaration, which is the struct in which this field is defined.

bool isUnnamedBitField() const

Determines whether this is an unnamed bitfield.

bool isStringLiteralInit() const

Is this an initializer for an array of characters, initialized by a string literal or an @encode?

unsigned getNumInits() const

const Expr * getInit(unsigned Init) const

bool isParentOf(const LocationContext *LC) const

const Decl * getDecl() const

A (possibly-)qualified type.

bool isNull() const

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

bool isConstQualified() const

Determine whether this type is const-qualified.

field_iterator field_end() const

field_range fields() const

RecordDecl * getDefinition() const

Returns the RecordDecl that actually defines this struct/union/class.

specific_decl_iterator< FieldDecl > field_iterator

field_iterator field_begin() const

unsigned getLength() const

uint32_t getCodeUnit(size_t i) const

bool isCompleteDefinition() const

Return true if this decl has its body fully specified.

CXXRecordDecl * getAsCXXRecordDecl() const

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

bool isConstantArrayType() const

bool isVoidPointerType() const

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

bool isScalarType() const

QualType getPointeeType() const

If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.

bool isIntegralOrEnumerationType() const

Determine whether this type is an integral or enumeration type.

RecordDecl * castAsRecordDecl() const

bool isAnyComplexType() const

QualType getCanonicalTypeInternal() const

bool isStructureOrClassType() const

bool isVectorType() const

const T * castAsCanonical() const

Return this type's canonical type cast to the specified type.

bool isRecordType() const

bool hasGlobalStorage() const

Returns true for all variables that do not have local storage.

bool hasLocalStorage() const

Returns true if a variable with function scope is a non-static local variable.

const Expr * getAnyInitializer() const

Get the initializer for this variable, no matter which declaration it is attached to.

unsigned getNumElements() const

QualType getElementType() const

ElementRegion is used to represent both array elements and casts.

QualType getElementType() const

RegionRawOffset getAsArrayOffset() const

Compute the offset within the array. The array might also be a subobject.

LLVM_ATTRIBUTE_RETURNS_NONNULL const FieldDecl * getDecl() const override

void dumpToStream(raw_ostream &Out) const

static bool isLocType(QualType T)

DefinedOrUnknownSVal getStaticSize(const MemRegion *MR, SValBuilder &SVB) const

MemRegion - The root abstract class for all memory regions.

virtual bool isBoundable() const

RegionOffset getAsOffset() const

Compute the offset within the top level memory object.

std::string getDescriptiveName(bool UseQuotes=true) const

Get descriptive name for memory region.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getRawMemorySpace() const

Deprecated.

@ TK_PreserveContents

Tells that a region's contents is not changed.

@ TK_DoNotInvalidateSuperRegion

@ TK_EntireMemSpace

When applied to a MemSpaceRegion, indicates the entire memory space should be invalidated.

bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const

bool hasSymbolicOffset() const

const MemRegion * getRegion() const

It might return null.

int64_t getOffset() const

const MemRegion * getRegion() const

DefinedOrUnknownSVal makeZeroVal(QualType type)

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

NonLoc makeArrayIndex(uint64_t idx)

ASTContext & getContext()

nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)

SVal evalCast(SVal V, QualType CastTy, QualType OriginalTy)

Cast a given SVal to another SVal using given QualType's.

DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(SymbolRef parentSymbol, const TypedValueRegion *region)

loc::ConcreteInt makeNullWithType(QualType type)

Create NULL pointer, with proper pointer bit-width for given address space.

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

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

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

Create a new symbol with a unique 'name'.

NonLoc makeZeroArrayIndex()

DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region)

Make a unique symbol for value of region.

NonLoc makeLazyCompoundVal(const StoreRef &store, const TypedValueRegion *region)

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

bool isZeroConstant() const

bool isUnknownOrUndef() const

SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const

If this SVal wraps a symbol return that SymbolRef.

std::optional< T > getAs() const

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

const MemRegion * getAsRegion() const

T castAs() const

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

bool scan(nonloc::LazyCompoundVal val)

SmallVector< const MemRegion *, 8 > InvalidatedRegions

SubRegion - A region that subsets another larger region.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const

bool isSubRegionOf(const MemRegion *R) const override

Check if the region is a subregion of the given region.

MemRegionManager & getMemRegionManager() const override

llvm::iterator_range< symbol_iterator > symbols() const

static bool canSymbolicate(QualType T)

void markLive(SymbolRef sym)

Unconditionally marks a symbol as live.

void markElementIndicesLive(const MemRegion *region)

void markLazilyCopied(const MemRegion *region)

bool isLive(SymbolRef sym)

llvm::iterator_range< RegionSetTy::const_iterator > regions() const

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

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

virtual QualType getValueType() const =0

QualType getLocationType() const override

QualType getValueType() const override

const VarDecl * getDecl() const override=0

llvm::ImmutableList< SVal >::iterator iterator

Value representing integer constant.

While nonloc::CompoundVal covers a few simple use cases, nonloc::LazyCompoundVal is a more performant...

LLVM_ATTRIBUTE_RETURNS_NONNULL const LazyCompoundValData * getCVData() const

LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const

This function itself is immaterial.

const void * getStore() const

It might return null.

Defines the clang::TargetInfo interface.

const internal::VariadicDynCastAllOfMatcher< Decl, VarDecl > varDecl

Matches variable declarations.

const internal::VariadicDynCastAllOfMatcher< Stmt, DeclRefExpr > declRefExpr

Matches expressions that refer to declarations.

const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher > hasDescendant

Matches AST nodes that have descendant AST nodes that match the provided matcher.

SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)

Returns the results of matching Matcher on Node.

internal::Matcher< Stmt > StatementMatcher

const internal::VariadicAllOfMatcher< Stmt > stmt

Matches statements.

llvm::DenseSet< SymbolRef > InvalidatedSymbols

const SymExpr * SymbolRef

@ OS

Indicates that the tracking object is a descendant of a referenced-counted OSObject,...

std::unique_ptr< StoreManager > CreateRegionStoreManager(ProgramStateManager &StMgr)

Definition RegionStore.cpp:838

const void * Store

Store - This opaque type encapsulates an immutable mapping from locations to values.

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

@ Match

This is not an overload because the signature exactly matches an existing declaration.

bool isa(CodeGen::Address addr)

CFGBlock::ConstCFGElementRef ConstCFGElementRef

@ Bind

'bind' clause, allowed on routine constructs.

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

bool operator<(DeclarationName LHS, DeclarationName RHS)

Ordering on two declaration names.

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

@ Result

The result type of a method or function.

const FunctionProtoType * T

const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ConceptReference *C)

Insertion operator for diagnostics.

U cast(CodeGen::Address addr)

@ Class

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

Diagnostic wrappers for TextAPI types for error reporting.

__UINTPTR_TYPE__ uintptr_t

An unsigned integer type with the property that any valid pointer to void can be converted to this ty...