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

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

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

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

33#include

34#include

35

36using namespace clang;

37using namespace ento;

38

39

40

41

42

43namespace {

44class BindingKey {

45public:

47private:

48 enum { Symbolic = 0x2 };

49

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

52

53

54

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

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

59 }

60

61

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

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

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

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

67 isa<ObjCIvarRegion, CXXDerivedObjectRegion>(r)) &&

68 "Not a base");

69 }

70

71public:

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

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

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

75

78 assert(!hasSymbolicOffset());

80 }

81

82 const SubRegion *getConcreteOffsetRegion() const {

83 assert(hasSymbolicOffset());

85 }

86

87 const MemRegion *getBaseRegion() const {

88 if (hasSymbolicOffset())

89 return getConcreteOffsetRegion()->getBaseRegion();

91 }

92

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

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

95 ID.AddInteger(Data);

96 }

97

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

99

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

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

102 return true;

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

104 return false;

105 return Data < X.Data;

106 }

107

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

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

111 }

112

113 LLVM_DUMP_METHOD void dump() const;

114};

115}

116

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

120 return BindingKey(cast(R), cast(RO.getRegion()), k);

121

123}

124

125namespace llvm {

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

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

128 << "\", \"offset\": ";

129

130 if (!K.hasSymbolicOffset())

131 Out << K.getOffset();

132 else

133 Out << "null";

134

135 return Out;

136}

137

138}

139

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

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

142#endif

143

144

145

146

147

151

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

154

155namespace {

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

157 ClusterBindings> {

158 ClusterBindings::Factory *CBFactory;

159

160

161

162

163

164

165

166

167

168

169 bool IsMainAnalysis;

170

171public:

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

173 ParentTy;

174

175 RegionBindingsRef(ClusterBindings::Factory &CBFactory,

176 const RegionBindings::TreeTy *T,

177 RegionBindings::TreeTy::Factory *F,

178 bool IsMainAnalysis)

179 : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(T, F),

180 CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}

181

182 RegionBindingsRef(const ParentTy &P,

183 ClusterBindings::Factory &CBFactory,

184 bool IsMainAnalysis)

185 : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(P),

186 CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}

187

188 RegionBindingsRef add(key_type_ref K, data_type_ref D) const {

189 return RegionBindingsRef(static_cast<const ParentTy *>(this)->add(K, D),

190 *CBFactory, IsMainAnalysis);

191 }

192

193 RegionBindingsRef remove(key_type_ref K) const {

194 return RegionBindingsRef(static_cast<const ParentTy *>(this)->remove(K),

195 *CBFactory, IsMainAnalysis);

196 }

197

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

199

200 RegionBindingsRef addBinding(const MemRegion *R,

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

202

203 const SVal *lookup(BindingKey K) const;

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

206

207 RegionBindingsRef removeBinding(BindingKey K);

208

209 RegionBindingsRef removeBinding(const MemRegion *R,

210 BindingKey::Kind k);

211

212 RegionBindingsRef removeBinding(const MemRegion *R) {

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

214 removeBinding(R, BindingKey::Default);

215 }

216

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

218

219

220

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

222

223

224 Store asStore() const {

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

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

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

228 }

229

230 bool isMainAnalysis() const {

231 return IsMainAnalysis;

232 }

233

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

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

236 using namespace llvm;

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

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

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

240 if (!Inserted)

241 return Place->second;

242 std::string Res;

243 raw_string_ostream OS(Res);

244 OS << R;

245 Place->second = Res;

246 return Res;

247 };

248

249 using Cluster =

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

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

252

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

254 const Cluster *R) {

255 if (isa(L->first) && !isa(R->first))

256 return true;

257 if (!isa(L->first) && isa(R->first))

258 return false;

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

260 };

261

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

263 const BindingKey &R) {

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

265 return true;

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

267 return false;

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

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

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

271 };

272

273 const auto DefaultBindingBeforeDirectBindings =

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

275 const BindingKey &L = LPtr->first;

276 const BindingKey &R = RPtr->first;

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

278 return true;

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

280 return false;

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

282 return SymbolicBeforeOffset(L, R);

283 };

284

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

286

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

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

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

290 llvm::sort(SortedClusters, MemSpaceBeforeRegionName);

291

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

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

294 Indent(Out, Space, IsDot)

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

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

297

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

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

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

301 llvm::sort(SortedBindings, DefaultBindingBeforeDirectBindings);

302

303 ++Space;

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

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

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

307 Value.printJson(Out, true);

308 Out << " }";

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

310 Out << ',';

311 Out << NL;

312 }

313 --Space;

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

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

316 Out << ',';

317 Out << NL;

318 }

319 }

320

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

322};

323}

324

326

327std::optional

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

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

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

331}

332

333std::optional

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

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

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

337}

338

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

341

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

345

347 return add(Base, NewCluster);

348}

349

350

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

352 BindingKey::Kind k,

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

355}

356

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

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

359 if (!Cluster)

360 return nullptr;

361 return Cluster->lookup(K);

362}

363

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

365 BindingKey::Kind k) const {

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

367}

368

369RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {

372 if (!Cluster)

373 return *this;

374

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

376 if (NewCluster.isEmpty())

378 return add(Base, NewCluster);

379}

380

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

382 BindingKey::Kind k){

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

384}

385

386

387

388

389

390namespace {

391class InvalidateRegionsWorker;

392

393class RegionStoreManager : public StoreManager {

394public:

395 RegionBindings::Factory RBFactory;

396 mutable ClusterBindings::Factory CBFactory;

397

398 typedef std::vector SValListTy;

399private:

401 SValListTy> LazyBindingsMapTy;

402 LazyBindingsMapTy LazyBindingsMap;

403

404

405

406

407

408

409

410

411

412 unsigned SmallStructLimit;

413

414

415

416

417

418

419

420

421

422 unsigned SmallArrayLimit;

423

424

425

426 void populateWorkList(InvalidateRegionsWorker &W,

428 InvalidatedRegions *TopLevelRegions);

429

430public:

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

433 CBFactory(mgr.getAllocator()), SmallStructLimit(0), SmallArrayLimit(0) {

434 ExprEngine &Eng = StateMgr.getOwningEngine();

436 SmallStructLimit = Options.RegionStoreSmallStructLimit;

437 SmallArrayLimit = Options.RegionStoreSmallArrayLimit;

438 }

439

440

441

442

445

446

447

448

449

450

451

453

454

455

457 bool IsMainAnalysis = false;

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

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

460 return StoreRef(RegionBindingsRef(

461 RegionBindingsRef::ParentTy(RBFactory.getEmptyMap(), RBFactory),

462 CBFactory, IsMainAnalysis).asStore(), *this);

463 }

464

465

466

467

468 RegionBindingsRef invalidateGlobalRegion(MemRegion::Kind K, const Stmt *S,

469 unsigned Count,

471 RegionBindingsRef B,

472 InvalidatedRegions *Invalidated);

473

478 InvalidatedRegions *Invalidated,

479 InvalidatedRegions *InvalidatedTopLevel) override;

480

483

486 std::optional

489 std::optional

490 getSValFromInitListExpr(const InitListExpr *ILE,

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

495

496public:

497

499 return StoreRef(bind(getRegionBindings(store), LV, V).asStore(), *this);

500 }

501

503

504

505

507 SVal V) override {

508 RegionBindingsRef B = getRegionBindings(store);

509

510

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

512 "Double initialization!");

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

514 return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);

515 }

516

517

518

520

521

522

523

524

525

526

527

528

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

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

531 return StoreRef(store, *this);

532

533 RegionBindingsRef B = getRegionBindings(store);

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

535 B = removeSubRegionBindings(B, cast(R));

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

537 return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);

538 }

539

540

541

542

543

544

545

546

547

548

549

550 std::optional

553

554

557

558

561

562 std::optional

565

569

570

571

574 SVal DefaultVal);

575

576

577

578

580

582 getRegionBindings(store).manualRetain();

583 }

584

585

586

587

589 getRegionBindings(store).manualRelease();

590 }

591

593

594

595

596

597

598

599

600

601

602

603

604

605

606

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

609 }

610

613 std::optional

615

617 RegionBindingsRef B = getRegionBindings(S);

618

619

620

622 }

623

625

627

629

631

633

635

639

640 SVal getLazyBinding(const SubRegion *LazyBindingRegion,

641 RegionBindingsRef LazyBinding);

642

643

644

645

646

647

651

652

653

654

655

656

657 std::optional

661

662

663

664

665

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

668 const SubRegion *originalRegion);

669

670

671

672

673

674

675

676

677

678

679

681

682

683

684

685

686

687

690

691

692

693

694

695 RegionBindingsRef getRegionBindings(Store store) const {

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

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

698 return RegionBindingsRef(

699 CBFactory,

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

701 RBFactory.getTreeFactory(),

702 Ptr.getInt());

703 }

704

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

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

707

709 RegionBindingsRef B = getRegionBindings(store);

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

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

712 if (!Key.isDirect())

713 continue;

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

715

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

717 return;

718 }

719 }

720 }

721 }

722};

723

724}

725

726

727

728

729

730std::unique_ptr

732 return std::make_unique(StMgr);

733}

734

735

736

737

738

739namespace {

740

741

742enum GlobalsFilterKind {

743

744 GFK_None,

745

746 GFK_SystemOnly,

747

748 GFK_All

749};

750

751template

752class ClusterAnalysis {

753protected:

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

755 typedef const MemRegion * WorkListElement;

757

759

761

762 RegionStoreManager &RM;

765

766 RegionBindingsRef B;

767

768

769protected:

771 return B.lookup(R);

772 }

773

774

775

776

777 bool includeEntireMemorySpace(const MemRegion *Base) {

778 return false;

779 }

780

781public:

783 RegionBindingsRef b)

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

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

786

787 RegionBindingsRef getRegionBindings() const { return B; }

788

789 bool isVisited(const MemRegion *R) {

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

791 }

792

793 void GenerateClusters() {

794

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

796 RI != RE; ++RI){

798

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

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

802

803

804

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

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

807 }

808 }

809

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

811 if (C && Visited.insert(C).second)

812 return false;

813 WL.push_back(E);

814 return true;

815 }

816

817 bool AddToWorkList(const MemRegion *R) {

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

819 }

820

821 void RunWorkList() {

822 while (!WL.empty()) {

823 WorkListElement E = WL.pop_back_val();

825

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

827 }

828 }

829

832

834 bool Flag) {

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

836 }

837};

838}

839

840

841

842

843

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

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

847 RegionBindingsRef B = getRegionBindings(S);

849

850 if (!Cluster)

851 return true;

852

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

854 RI != RE; ++RI) {

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

856 return false;

857 }

858

859 return true;

860}

861

864}

865

867

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

870

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

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

873

874 while (R != Base) {

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

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

878

879 R = cast(R)->getSuperRegion();

880 }

881}

882

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

885

886 if (Fields.empty())

887 return true;

888

891

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

893 if (Delta >= 0)

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

895 FieldsInBindingKey.end(),

896 Fields.begin());

897 else

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

899 Fields.begin() - Delta);

900}

901

902

903

904

905

906

907

908

909

910

911static void

914 const SubRegion *Top, BindingKey TopKey,

915 bool IncludeAllDefaultBindings) {

917 if (TopKey.hasSymbolicOffset()) {

919 Top = TopKey.getConcreteOffsetRegion();

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

921 }

922

923

924 uint64_t Length = UINT64_MAX;

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

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

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

930

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

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

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

935 }

936

937 for (const auto &StoreEntry : Cluster) {

938 BindingKey NextKey = StoreEntry.first;

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

940

941

942

943

944

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

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

947

948

949 Bindings.push_back(StoreEntry);

950

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

952

953

954

955

956

957

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

959 Bindings.push_back(StoreEntry);

960 }

961

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

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

965

966

967

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

970 Bindings.push_back(StoreEntry);

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

972

973

974 if (BaseSR->isSubRegionOf(Top))

976 Bindings.push_back(StoreEntry);

977 }

978 }

979 }

980}

981

982static void

985 const SubRegion *Top, bool IncludeAllDefaultBindings) {

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

988 IncludeAllDefaultBindings);

989}

990

991RegionBindingsRef

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

996

997 if (Top == ClusterHead) {

998

999 return B.remove(Top);

1000 }

1001

1003 if (!Cluster) {

1004

1005

1006 if (TopKey.hasSymbolicOffset()) {

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

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

1009 }

1010 return B;

1011 }

1012

1015 false);

1016

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

1019 Result = Result.remove(Key);

1020

1021

1022

1023

1024

1025 if (TopKey.hasSymbolicOffset()) {

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

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

1029 }

1030

1031 if (Result.isEmpty())

1032 return B.remove(ClusterHead);

1033 return B.add(ClusterHead, Result.asImmutableMap());

1034}

1035

1036namespace {

1037class InvalidateRegionsWorker : public ClusterAnalysis

1038{

1039 const Stmt *S;

1040 unsigned Count;

1045 GlobalsFilterKind GlobalsFilter;

1046public:

1047 InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,

1048 RegionBindingsRef b, const Stmt *S, unsigned count,

1052 GlobalsFilterKind GFK)

1053 : ClusterAnalysis(rm, stateMgr, b), S(S),

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

1055 GlobalsFilter(GFK) {}

1056

1058 void VisitBinding(SVal V);

1059

1060 using ClusterAnalysis::AddToWorkList;

1061

1062 bool AddToWorkList(const MemRegion *R);

1063

1064

1065

1066 bool includeEntireMemorySpace(const MemRegion *Base);

1067

1068

1069

1070 bool isInitiallyIncludedGlobalRegion(const MemRegion *R);

1071};

1072}

1073

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

1075 bool doNotInvalidateSuperRegion = ITraits.hasTrait(

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

1079}

1080

1081void InvalidateRegionsWorker::VisitBinding(SVal V) {

1082

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

1084 IS.insert(Sym);

1085

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

1087 AddToWorkList(R);

1088 return;

1089 }

1090

1091

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

1094

1095

1096

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

1098 if (!isanonloc::LazyCompoundVal(V))

1099 VisitBinding(V);

1100

1101 return;

1102 }

1103}

1104

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

1107

1108 bool PreserveRegionsContents =

1109 ITraits.hasTrait(baseR,

1111

1112 if (C) {

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

1114 VisitBinding(Val);

1115

1116

1117 if (!PreserveRegionsContents)

1118 B = B.remove(baseR);

1119 }

1120

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

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

1123

1124

1125

1126

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

1128 using namespace ast_matchers;

1129

1130 const char *DeclBind = "DeclBind";

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

1133 auto Matches =

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

1135 RD->getASTContext());

1136

1138 auto *VD = Match.getNodeAs<VarDecl>(DeclBind);

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

1141 AddToWorkList(ToInvalidate);

1142 }

1143 }

1144 }

1145 }

1146

1147

1148

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

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

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

1154 AddToWorkList(VR);

1155 }

1157

1158

1159

1160

1161

1163 if (std::optional L = V.getAs<Loc>()) {

1165 AddToWorkList(LR);

1166 }

1167 }

1168 }

1169 return;

1170 }

1171

1172

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

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

1175

1176

1177 if (PreserveRegionsContents)

1178 return;

1179

1180

1181 if (Regions)

1182 Regions->push_back(baseR);

1183

1184 if (isa<AllocaRegion, SymbolicRegion>(baseR)) {

1185

1186

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

1190 return;

1191 }

1192

1194 return;

1195

1198

1199 if (isInitiallyIncludedGlobalRegion(baseR)) {

1200

1201

1202

1203 return;

1204 }

1205

1207

1208

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

1212 return;

1213 }

1214

1216 bool doNotInvalidateSuperRegion = ITraits.hasTrait(

1217 baseR,

1219

1220 if (doNotInvalidateSuperRegion) {

1221

1222

1223 std::optional<uint64_t> NumElements;

1224

1225

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

1227 NumElements = CAT->getZExtSize();

1228 if (!NumElements)

1229 goto conjure_default;

1230 QualType ElementTy = AT->getElementType();

1235

1236

1237 if (SuperR)

1238 AddToWorkList(SuperR);

1239 goto conjure_default;

1240 }

1241

1243 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;

1244 bool UpperOverflow = UpperOffset < LowerOffset;

1245

1246

1247

1248 if (!SuperR)

1249 goto conjure_default;

1250

1252 if (C)

1253 goto conjure_default;

1254

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

1256 std::optional<uint64_t> ROffset =

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

1258

1259

1260

1261 if (!ROffset ||

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

1263 (UpperOverflow &&

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

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

1266 B = B.removeBinding(BK);

1267

1268

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

1270 if (isa_and_nonnull(R))

1271 VisitBinding(V);

1272 }

1273 }

1274 }

1275 conjure_default:

1276

1278 baseR, S, LCtx, AT->getElementType(), Count);

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

1280 return;

1281 }

1282

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

1287}

1288

1289bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(

1291 switch (GlobalsFilter) {

1292 case GFK_None:

1293 return false;

1294 case GFK_SystemOnly:

1295 return isa(R->getMemorySpace());

1296 case GFK_All:

1297 return isa(R->getMemorySpace());

1298 }

1299

1300 llvm_unreachable("unknown globals filter");

1301}

1302

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

1304 if (isInitiallyIncludedGlobalRegion(Base))

1305 return true;

1306

1308 return ITraits.hasTrait(MemSpace,

1310}

1311

1312RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(

1315 InvalidatedRegions *Invalidated) {

1316

1317

1320 svalBuilder.conjureSymbolVal( (const void *)GS, S, LCtx,

1321 Ctx.IntTy, Count);

1322

1323 B = B.removeBinding(GS)

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

1325

1326

1327

1328 if (Invalidated)

1329 Invalidated->push_back(GS);

1330

1331 return B;

1332}

1333

1334void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,

1336 InvalidatedRegions *TopLevelRegions) {

1337 for (SVal V : Values) {

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

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

1341 W.AddToWorkList(R);

1342

1343 continue;

1344 }

1345

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

1347 if (TopLevelRegions)

1348 TopLevelRegions->push_back(R);

1349 W.AddToWorkList(R);

1350 continue;

1351 }

1352 }

1353}

1354

1355StoreRef RegionStoreManager::invalidateRegions(

1359 InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {

1360 GlobalsFilterKind GlobalsFilter;

1362 if (Call->isInSystemHeader())

1363 GlobalsFilter = GFK_SystemOnly;

1364 else

1365 GlobalsFilter = GFK_All;

1366 } else {

1367 GlobalsFilter = GFK_None;

1368 }

1369

1370 RegionBindingsRef B = getRegionBindings(store);

1371 InvalidateRegionsWorker W(*this, StateMgr, B, S, Count, LCtx, IS, ITraits,

1372 Invalidated, GlobalsFilter);

1373

1374

1375 W.GenerateClusters();

1376

1377

1378 populateWorkList(W, Values, TopLevelRegions);

1379

1380 W.RunWorkList();

1381

1382

1383 B = W.getRegionBindings();

1384

1385

1386

1387

1388

1389 switch (GlobalsFilter) {

1390 case GFK_All:

1391 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, S,

1392 Count, LCtx, B, Invalidated);

1393 [[fallthrough]];

1394 case GFK_SystemOnly:

1395 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, S, Count,

1396 LCtx, B, Invalidated);

1397 [[fallthrough]];

1398 case GFK_None:

1399 break;

1400 }

1401

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

1403}

1404

1405

1406

1407

1408

1409

1410

1411

1412

1413

1414

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

1416 if (isaloc::ConcreteInt(Array))

1417 return Array;

1418

1419 if (!isaloc::MemRegionVal(Array))

1421

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

1426}

1427

1428

1429

1430

1431

1433 assert(!isa(L) && "location unknown");

1434 assert(!isa(L) && "location undefined");

1435

1436

1437

1438

1439

1440

1441

1444 }

1447 }

1448

1450

1451 if (isa(MR)) {

1453 }

1454

1455

1456 if (T.isNull()) {

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

1458 T = TVR->getValueType();

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

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

1462 T = SR->getPointeeStaticType();

1463 }

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

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

1466

1467 if (!isa(MR))

1468 MR = GetElementZeroRegion(cast(MR), T);

1469

1470

1471

1474

1475

1476

1479

1480

1481

1482

1483

1484

1485

1486

1487

1489 return getBindingForStruct(B, R);

1490

1491

1493 return createLazyBinding(B, R);

1494

1497 return getBindingForArray(B, R);

1498 else

1500 }

1501

1502

1505

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

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

1508

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

1510

1511

1512

1513

1514

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

1516 }

1517

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

1519

1520

1521

1522

1523

1524

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

1526 }

1527

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

1529

1530

1531

1532

1533

1534

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

1536 }

1537

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

1539

1540

1541 if (V)

1542 return *V;

1543

1544

1545

1546

1548

1549

1550

1551

1553 }

1554

1555

1557}

1558

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

1562 RegionTy = TVR->getValueType();

1563

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

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

1566

1567 return RegionTy;

1568}

1569

1570

1571

1572

1573

1574

1575

1576

1577static std::optionalnonloc::LazyCompoundVal

1579 const SubRegion *R, bool AllowSubregionBindings) {

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

1581 if (V)

1582 return std::nullopt;

1583

1584 std::optionalnonloc::LazyCompoundVal LCV =

1586 if (!LCV)

1587 return std::nullopt;

1588

1589

1590

1592 if (!RegionTy.isNull() &&

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

1596 return std::nullopt;

1597 }

1598

1599 if (!AllowSubregionBindings) {

1600

1601

1604 true);

1606 return std::nullopt;

1607 }

1608

1609 return *LCV;

1610}

1611

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

1615 const SubRegion *originalRegion) {

1616 if (originalRegion != R) {

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

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

1620 }

1621

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

1623 StoreRegionPair Result = StoreRegionPair();

1624

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

1626 Result = findLazyBinding(B, cast(ER->getSuperRegion()),

1627 originalRegion);

1628

1629 if (Result.second)

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

1631

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

1633 Result = findLazyBinding(B, cast(FR->getSuperRegion()),

1634 originalRegion);

1635

1636 if (Result.second)

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

1638

1640 dyn_cast(R)) {

1641

1642

1643 Result = findLazyBinding(B, cast(BaseReg->getSuperRegion()),

1644 originalRegion);

1645

1646 if (Result.second)

1647 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,

1648 Result.second);

1649 }

1650

1651 return Result;

1652}

1653

1654

1655

1656

1657

1658

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

1664 do {

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

1667 return Extents;

1668}

1669

1670

1671

1672

1673

1674

1675

1676

1677

1678

1679

1680

1681

1682

1683

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

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

1689 do {

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

1692 ER = dyn_cast(Base);

1693 } while (ER);

1694 return {SValOffsets, Base};

1695}

1696

1697

1698

1699

1700

1701

1702

1703

1704

1705

1706

1707

1708

1709

1710

1711

1712

1713

1714

1715

1716

1717

1718static std::optional

1722

1723

1724

1725

1726

1727

1728

1729

1730

1731

1732

1733

1734

1735

1736

1737

1738

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

1740 auto ExtentIt = ArrayExtents.begin();

1741 auto OffsetIt = DstOffsets.begin();

1742

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

1745

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

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

1749

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

1751 continue;

1752 }

1753

1754

1755

1757 }

1758 return std::nullopt;

1759}

1760

1761std::optional RegionStoreManager::getConstantValFromConstArrayInitializer(

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

1764

1765

1769 const VarRegion *VR = dyn_cast(Base);

1770 if (!VR)

1771 return std::nullopt;

1772

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

1774 "offsets vector is not empty.");

1775

1776

1777

1782 return std::nullopt;

1783

1784

1785

1786

1787

1788

1789

1790

1791

1792

1794

1795

1797 return std::nullopt;

1798

1799

1800

1802 if (!CAT)

1803 return std::nullopt;

1804

1805

1807

1808

1809

1810

1811

1812

1813

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

1815 return std::nullopt;

1816

1819 SValOffsets, Extents, ConcreteOffsets))

1820 return *V;

1821

1822

1823

1824

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

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

1827

1828

1829

1830

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

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

1834

1835

1836

1837 return std::nullopt;

1838}

1839

1840

1841

1842

1843

1844

1845

1846

1847

1848

1849

1850

1851

1852

1853

1854

1855

1856

1857std::optional RegionStoreManager::getSValFromInitListExpr(

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

1861

1862 for (uint64_t Offset : Offsets) {

1863

1864

1865

1866

1867

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

1870 return getSValFromStringLiteral(SL, Offset, ElemT);

1871

1872

1873

1874

1877

1879 const auto *IL = dyn_cast(E);

1880 if (!IL)

1881

1882

1884

1885

1886 ILE = IL;

1887 }

1888

1889 assert(ILE);

1890

1891

1892

1893 return std::nullopt;

1894}

1895

1896

1897

1898

1899

1900

1901

1902

1903

1904

1905

1906

1907

1908

1909

1910

1911

1912

1913

1914

1915

1916

1917

1918

1919

1920

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

1922 uint64_t Offset,

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

1925

1926

1927

1929 return svalBuilder.makeIntVal(Code, ElemT);

1930}

1931

1935 assert(BaseRegion);

1940 if (const std::optional &ParentValue =

1941 B.getDirectBinding(BaseRegion)) {

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

1944

1945 if (ParentValue->isUndef())

1947

1948

1949

1951 }

1952 }

1953 }

1954 return std::nullopt;

1955}

1956

1959

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

1961 return *V;

1962

1964

1965

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

1967

1968

1969

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

1975 if (Idx < 0)

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

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

1979 }

1980 } else if (isa<ElementRegion, VarRegion>(superR)) {

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

1982 return *V;

1983 }

1984

1985

1986 if (isa(superR))

1988

1989

1990

1991

1992

1993

1994

1996

1997

2000

2003 return *V;

2004

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

2006}

2007

2010

2011

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

2013 return *V;

2014

2015

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

2023

2024

2025

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

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

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

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

2033 return *V;

2034 } else {

2036 }

2037 }

2038 }

2039

2040

2041

2042

2043

2044

2045

2046

2047

2048

2049

2050

2051

2052

2053

2054

2055

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

2058 return *V;

2059

2060 return getBindingForFieldOrElementCommon(B, R, Ty);

2061}

2062

2063std::optional RegionStoreManager::getBindingForDerivedDefaultValue(

2066

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

2071

2074

2076 return val;

2077

2078

2079

2080 if (isa<nonloc::LazyCompoundVal, nonloc::CompoundVal>(val))

2081 return val;

2082

2083 llvm_unreachable("Unknown default value");

2084 }

2085

2086 return std::nullopt;

2087}

2088

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

2090 RegionBindingsRef LazyBinding) {

2091 SVal Result;

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

2093 Result = getBindingForElement(LazyBinding, ER);

2094 else

2095 Result = getBindingForField(LazyBinding,

2096 cast(LazyBindingRegion));

2097

2098

2099

2100

2101

2102

2103

2104

2105

2106

2107

2108

2109

2110

2111

2112 if (Result.isUndef())

2114

2115 return Result;

2116}

2117

2122

2123

2124

2125

2126

2127 Store lazyBindingStore = nullptr;

2128 const SubRegion *lazyBindingRegion = nullptr;

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

2130 if (lazyBindingRegion)

2131 return getLazyBinding(lazyBindingRegion,

2132 getRegionBindings(lazyBindingStore));

2133

2134

2135

2136 bool hasSymbolicIndex = false;

2137

2138

2139

2140

2141

2142

2143

2144

2145

2146

2147

2148

2149

2150

2151

2152 bool hasPartialLazyBinding = false;

2153

2155 while (SR) {

2157 if (std::optional D =

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

2160 hasPartialLazyBinding = true;

2161 break;

2162 }

2163

2164 return *D;

2165 }

2166

2168 NonLoc index = ER->getIndex();

2170 hasSymbolicIndex = true;

2171 }

2172

2173

2174

2175 SR = dyn_cast(Base);

2176 }

2177

2179 if (isa(R)) {

2180

2181

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

2186 }

2187 }

2188

2189

2190

2191

2192

2193 if (hasSymbolicIndex)

2195

2196

2197

2198

2199 if (!hasPartialLazyBinding && !isa(R->getBaseRegion())) {

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

2201 return *V;

2203 }

2204 }

2205

2206

2208}

2209

2212

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

2214 return *V;

2215

2217

2218

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

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

2222

2223

2225 }

2226

2227 return getBindingForLazySymbol(R);

2228}

2229

2232

2233

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

2235 return *V;

2236

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

2238 return *V;

2239

2240

2243

2244

2245 if (isa(MS))

2247

2248

2252 return *V;

2253

2254

2255

2256

2258 }

2259 }

2260

2261

2262

2263 if (isa(MS))

2265

2266 if (isa(MS)) {

2268

2269

2270 if (B.isMainAnalysis())

2273 return *V;

2274

2275

2276

2277

2278

2279 if (isa(MS))

2281

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

2284 return *V;

2285 }

2286

2288 }

2289

2291}

2292

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

2294

2296}

2297

2298const RegionStoreManager::SValListTy &

2300

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

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

2303 return I->second;

2304

2305

2306 SValListTy List;

2307

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

2310

2311

2312

2314 if (!Cluster)

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

2316

2319 true);

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

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

2322 continue;

2323

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

2326 List.insert(List.end(), InnerList.begin(), InnerList.end());

2327 }

2328

2329 List.push_back(V);

2330 }

2331

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

2333}

2334

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

2339 return *V;

2340

2342}

2343

2349

2350

2351

2352

2353

2354

2355

2356

2357 if (std::optional Val = getUniqueDefaultBinding(B, R))

2358 return *Val;

2359 return createLazyBinding(B, R);

2360}

2361

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

2366

2367 return createLazyBinding(B, R);

2368}

2369

2370bool RegionStoreManager::includedInBindings(Store store,

2371 const MemRegion *region) const {

2372 RegionBindingsRef B = getRegionBindings(store);

2374

2375

2376 if (B.lookup(region))

2377 return true;

2378

2379

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

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

2383 CI != CE; ++CI) {

2384 SVal D = CI.getData();

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

2387 return true;

2388 }

2389 }

2390

2391 return false;

2392}

2393

2394

2395

2396

2397

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

2401 return StoreRef(getRegionBindings(ST).removeBinding(R)

2402 .asImmutableMap()

2403 .getRootWithoutRetain(),

2404 *this);

2405

2407}

2408

2409RegionBindingsRef

2411

2413 if (!MemRegVal)

2414 return B;

2415

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

2417

2418

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

2422 return bindArray(B, TR, V);

2424 return bindStruct(B, TR, V);

2426 return bindVector(B, TR, V);

2428 return bindAggregate(B, TR, V);

2429 }

2430

2431

2432

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

2434 QualType Ty = SymReg->getPointeeStaticType();

2436 Ty = StateMgr.getContext().CharTy;

2437 R = GetElementZeroRegion(SymReg, Ty);

2438 }

2439

2440 assert((!isa(R) || !B.lookup(R)) &&

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

2442

2443

2444 RegionBindingsRef NewB = removeSubRegionBindings(B, cast(R));

2445

2446

2447 auto KeyKind = isanonloc::LazyCompoundVal(V) ? BindingKey::Default

2448 : BindingKey::Direct;

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

2450}

2451

2452RegionBindingsRef

2457

2463

2464

2466 }

2467 else {

2468

2469

2470

2471

2474 }

2475

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

2477}

2478

2479std::optional RegionStoreManager::tryBindSmallArray(

2482

2483 auto CAT = dyn_cast(AT);

2484

2485

2486 if (!CAT)

2487 return std::nullopt;

2488

2491 return std::nullopt;

2492

2493

2495 if (ArrSize > SmallArrayLimit)

2496 return std::nullopt;

2497

2498 RegionBindingsRef NewB = B;

2499

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

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

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

2505

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

2508 }

2509

2510 return NewB;

2511}

2512

2513RegionBindingsRef

2517

2520 std::optional<uint64_t> Size;

2521

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

2524

2525

2526

2527

2530 return bindAggregate(B, R, V);

2531 }

2532

2533

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

2536 if (std::optional NewB =

2537 tryBindSmallArray(B, R, AT, *LCV))

2538 return *NewB;

2539

2540 return bindAggregate(B, R, Init);

2541 }

2542

2543 if (Init.isUnknown())

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

2545

2546

2550

2551 RegionBindingsRef NewB(B);

2552

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

2554

2555 if (VI == VE)

2556 break;

2557

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

2560

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

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

2565 else

2567 }

2568

2569

2570

2571

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

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

2574

2575 return NewB;

2576}

2577

2583

2584

2585 if (isa<nonloc::LazyCompoundVal, nonloc::SymbolVal>(V))

2586 return bindAggregate(B, R, V);

2587

2588

2589

2590

2591 if (!isanonloc::CompoundVal(V)) {

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

2593 }

2594

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

2599 RegionBindingsRef NewB(B);

2600

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

2602 if (VI == VE)

2603 break;

2604

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

2607

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

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

2612 else

2614 }

2615 return NewB;

2616}

2617

2618std::optional

2622 return std::nullopt;

2623

2624 const auto *Cluster = B.lookup(R);

2625 if (!Cluster || !llvm::hasSingleElement(*Cluster))

2626 return std::nullopt;

2627

2628 const auto [Key, Value] = *Cluster->begin();

2629 return Key.isDirect() ? std::optional{} : Value;

2630}

2631

2632std::optional

2635 return getUniqueDefaultBinding(B, LCV.getRegion());

2636}

2637

2638std::optional RegionStoreManager::tryBindSmallStruct(

2641

2642

2643

2644

2645

2646

2647

2648

2649

2650

2651

2652

2653

2654

2655 if (std::optional Val = getUniqueDefaultBinding(LCV)) {

2656 return B.addBinding(BindingKey::Make(R, BindingKey::Default), Val.value());

2657 }

2658

2660

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

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

2663 return std::nullopt;

2664

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

2667 continue;

2668

2669

2670

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

2672 return std::nullopt;

2673

2675

2676

2679 continue;

2680

2682 return std::nullopt;

2683

2684 Fields.push_back(FD);

2685 }

2686

2687 RegionBindingsRef NewB = B;

2688

2689 for (const FieldDecl *Field : Fields) {

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

2692

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

2695 }

2696

2697 return NewB;

2698}

2699

2705

2708

2709 if (!RD->isCompleteDefinition())

2710 return B;

2711

2712

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

2715 if (std::optional NewB =

2716 tryBindSmallStruct(B, R, RD, *LCV))

2717 return *NewB;

2718 return bindAggregate(B, R, V);

2719 }

2720 if (isanonloc::SymbolVal(V))

2721 return bindAggregate(B, R, V);

2722

2723

2724

2725

2726 if (V.isUnknown() || !isanonloc::CompoundVal(V))

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

2728

2729

2730

2731

2732

2733

2734

2735

2736

2737

2738

2739

2740

2741

2742

2743

2744

2747

2748 RegionBindingsRef NewB(B);

2749

2750

2751

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

2753

2754

2755

2756

2757

2758

2759

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

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

2762

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

2764

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

2766

2767 if (VI == VE)

2768 break;

2769

2772

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

2775

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

2778

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

2780

2781 ++VI;

2782 }

2783 }

2784

2786

2787 for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) {

2788

2789 if (VI == VE)

2790 break;

2791

2792

2793 if (FI->isUnnamedBitField())

2794 continue;

2795

2796 QualType FTy = FI->getType();

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

2798

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

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

2803 else

2805 ++VI;

2806 }

2807

2808

2809 if (FI != FE) {

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

2812 }

2813

2814 return NewB;

2815}

2816

2817RegionBindingsRef

2821

2822

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

2824}

2825

2826

2827

2828

2829

2830namespace {

2831class RemoveDeadBindingsWorker

2832 : public ClusterAnalysis {

2836

2837public:

2838 RemoveDeadBindingsWorker(RegionStoreManager &rm,

2842 : ClusterAnalysis(rm, stateMgr, b),

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

2844

2845

2848 using ClusterAnalysis::VisitCluster;

2849

2850 using ClusterAnalysis::AddToWorkList;

2851

2852 bool AddToWorkList(const MemRegion *R);

2853

2854 bool UpdatePostponed();

2855 void VisitBinding(SVal V);

2856};

2857}

2858

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

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

2862}

2863

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

2866

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

2868 if (SymReaper.isLive(VR))

2869 AddToWorkList(baseR, &C);

2870

2871 return;

2872 }

2873

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

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

2876 AddToWorkList(SR, &C);

2877 else

2878 Postponed.push_back(SR);

2879

2880 return;

2881 }

2882

2883 if (isa(baseR)) {

2884 AddToWorkList(baseR, &C);

2885 return;

2886 }

2887

2888

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

2890 const auto *StackReg =

2891 cast(TR->getSuperRegion());

2893 if (CurrentLCtx &&

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

2895 AddToWorkList(TR, &C);

2896 }

2897}

2898

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

2901 if (C)

2902 return;

2903

2904

2905

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

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

2908

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

2910

2911 SymReaper.markElementIndicesLive(Key.getRegion());

2912

2913 VisitBinding(Val);

2914 }

2915}

2916

2917void RemoveDeadBindingsWorker::VisitBinding(SVal V) {

2918

2919

2921 SymReaper.markLazilyCopied(LCS->getRegion());

2922

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

2925 SymReaper.markLazilyCopied(DepLCS->getRegion());

2926 else

2927 VisitBinding(V);

2928 }

2929

2930 return;

2931 }

2932

2933

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

2935 AddToWorkList(R);

2936 SymReaper.markLive(R);

2937

2938

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

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

2941 AddToWorkList(Var.getCapturedRegion());

2942 }

2943 }

2944

2945

2946

2948 SymReaper.markLive(Sym);

2949}

2950

2951bool RemoveDeadBindingsWorker::UpdatePostponed() {

2952

2953

2955

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

2958 Changed |= AddToWorkList(SR);

2959 SR = nullptr;

2960 }

2961 }

2962

2964}

2965

2966StoreRef RegionStoreManager::removeDeadBindings(Store store,

2969 RegionBindingsRef B = getRegionBindings(store);

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

2971 W.GenerateClusters();

2972

2973

2975 W.AddToWorkList(Reg);

2976 }

2977

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

2979

2980

2981

2982

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

2984

2985

2986 if (!W.isVisited(Base))

2987 B = B.remove(Base);

2988 }

2989

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

2991}

2992

2993

2994

2995

2996

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

2998 unsigned int Space, bool IsDot) const {

2999 RegionBindingsRef Bindings = getRegionBindings(S);

3000

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

3002

3004 Out << "null," << NL;

3005 return;

3006 }

3007

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

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

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

3011}

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)

llvm::DenseSet< const void * > Visited

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

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

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

std::pair< BindingKey, SVal > BindingPair

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

SmallVector< const FieldDecl *, 8 > FieldVector

llvm::ImmutableMap< BindingKey, SVal > ClusterBindings

static bool isUnionField(const FieldRegion *FR)

static void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields)

static QualType getUnderlyingType(const SubRegion *R)

llvm::ImmutableMapRef< BindingKey, SVal > ClusterBindingsRef

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

This is a helper function for getConstantValFromConstArrayInitializer.

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

This is a helper function for getConstantValFromConstArrayInitializer.

const RegionBindingsRef & RegionBindingsConstRef

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.

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.

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

__PTRDIFF_TYPE__ ptrdiff_t

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

const ConstantArrayType * getAsConstantArrayType(QualType T) const

CanQualType getCanonicalType(QualType T) const

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

const LangOptions & getLangOpts() const

bool hasSameUnqualifiedType(QualType T1, QualType T2) const

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

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.

uint64_t getCharWidth() const

Return the size of the character type, in bits.

Stores options for the analyzer from the command line.

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

QualType getElementType() const

Represents a C++ struct/union/class.

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.

specific_decl_iterator - Iterates over a subrange of declarations stored in a DeclContext,...

This represents one expression.

Represents a member of a struct/union/class.

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.

Describes an C or C++ initializer list.

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

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

bool isParentOf(const LocationContext *LC) const

const Decl * getDecl() const

const StackFrameContext * getStackFrame() 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.

Represents a struct/union/class.

field_range fields() const

RecordDecl * getDefinition() const

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

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

RecordDecl * getDecl() const

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

Stmt - This represents one statement.

StringLiteral - This represents a string literal expression, e.g.

unsigned getLength() const

uint32_t getCodeUnit(size_t i) const

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.

bool isAnyComplexType() const

QualType getCanonicalTypeInternal() const

bool isStructureOrClassType() const

bool isVectorType() const

bool isRecordType() const

Represents a variable declaration or definition.

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.

Represents a GCC generic vector type.

unsigned getNumElements() const

QualType getElementType() const

Maps string IDs to AST nodes matched by parts of a matcher.

AnalyzerOptions & options

BlockDataRegion - A region that represents a block instance.

CXXThisRegion - Represents the region for the implicit 'this' parameter in a call to a C++ method.

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

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.

AnalysisManager & getAnalysisManager()

LLVM_ATTRIBUTE_RETURNS_NONNULL const FieldDecl * getDecl() const override

static bool isLocType(QualType T)

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

MemRegion - The root abstract class for all memory regions.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace() const

virtual bool isBoundable() const

RegionOffset getAsOffset() const

Compute the offset within the top level memory object.

LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const

bool hasStackNonParametersStorage() const

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

Information about invalidation for a particular region/symbol.

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

Represent a region's offset within the top level base region.

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 conjureSymbolVal(const void *symbolTag, const Expr *expr, const LocationContext *LCtx, unsigned count)

Create a new symbol with a unique 'name'.

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.

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.

A utility class that visits the reachable symbols using a custom SymbolVisitor.

bool scan(nonloc::LazyCompoundVal val)

virtual StoreRef invalidateRegions(Store store, ArrayRef< SVal > Values, const Stmt *S, unsigned Count, const LocationContext *LCtx, const CallEvent *Call, InvalidatedSymbols &IS, RegionAndSymbolInvalidationTraits &ITraits, InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated)=0

invalidateRegions - Clears out the specified regions from the store, marking their values as unknown.

virtual bool scanReachableSymbols(Store S, const MemRegion *R, ScanReachableSymbols &Visitor)=0

Finds the transitive closure of symbols within the given region.

virtual void iterBindings(Store store, BindingsHandler &f)=0

iterBindings - Iterate over the bindings in the Store.

virtual StoreRef getInitialStore(const LocationContext *InitLoc)=0

getInitialStore - Returns the initial "empty" store representing the value bindings upon entry to an ...

virtual StoreRef BindDefaultZero(Store store, const MemRegion *R)=0

Return a store with in which all values within the given region are reset to zero.

virtual std::optional< SVal > getDefaultBinding(Store store, const MemRegion *R)=0

Return the default value bound to a region in a given store.

virtual StoreRef killBinding(Store ST, Loc L)=0

Create a new store with the specified binding removed.

virtual void decrementReferenceCount(Store store)

If the StoreManager supports it, decrement the reference count of the specified Store object.

virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx, SymbolReaper &SymReaper)=0

virtual void incrementReferenceCount(Store store)

If the StoreManager supports it, increment the reference count of the specified Store object.

virtual SVal ArrayToPointer(Loc Array, QualType ElementTy)=0

ArrayToPointer - Used by ExprEngine::VistCast to handle implicit conversions between arrays and point...

virtual bool includedInBindings(Store store, const MemRegion *region) const =0

virtual SVal getBinding(Store store, Loc loc, QualType T=QualType())=0

Return the value bound to specified location in a given state.

virtual StoreRef BindDefaultInitial(Store store, const MemRegion *R, SVal V)=0

Return a store with the specified value bound to all sub-regions of the region.

virtual void printJson(raw_ostream &Out, Store S, const char *NL, unsigned int Space, bool IsDot) const =0

StringRegion - Region associated with a StringLiteral.

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

static bool canSymbolicate(QualType T)

A class responsible for cleaning up unused symbols.

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

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

TypedRegion - An abstract class representing regions that are typed.

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_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getRegion() const

Get the underlining region.

The simplest example of a concrete compound value is nonloc::CompoundVal, which represents a concrete...

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

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

const void * Store

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

ASTEdit remove(RangeSelector S)

Removes the source selected by S.

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

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

const FunctionProtoType * T

@ Class

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

Diagnostic wrappers for TextAPI types for error reporting.

static raw_ostream & operator<<(raw_ostream &Out, BindingKey K)

__UINTPTR_TYPE__ uintptr_t

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