clang 23.0.0git
RegionStore.cpp
Go to the documentation of this file.
1//== RegionStore.cpp - Field-sensitive store model --------------*- C++ -*--==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines a basic region store model. In this model, we do have field
10// sensitivity. But we assume nothing about the heap shape. So recursive data
11// structures are largely ignored. Basically we do 1-limiting analysis.
12// Parameter pointers are assumed with no aliasing. Pointee objects of
13// parameters are created lazily.
14//
15//===----------------------------------------------------------------------===//
16
17#include "clang/AST/Attr.h"
18#include "clang/AST/CharUnits.h"
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 <limits>
33#include <optional>
34#include <utility>
35
36using namespace clang;
37using namespace ento;
38
39//===----------------------------------------------------------------------===//
40// Representation of binding keys.
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;
54 uint64_t Data;
55
56 /// Create a key for a binding to region \p r, which has a symbolic offset
57 /// from region \p Base.
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 /// Create a key for a binding at \p offset from base region \p r.
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");
69 assert((r == r->getBaseRegion() ||
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(); }
80 uint64_t getOffset() const {
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();
93 return getRegion()->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);
122 L.dumpToStream(OS);
123 return OS.str();
124}
125} // end anonymous namespace
126
127BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
128 const RegionOffset &RO = R->getAsOffset();
129 if (RO.hasSymbolicOffset())
130 return BindingKey(cast<SubRegion>(R), cast<SubRegion>(RO.getRegion()), k);
131
132 return BindingKey(RO.getRegion(), RO.getOffset(), k);
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} // namespace llvm
149
150#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
151void BindingKey::dump() const { llvm::errs() << *this; }
152#endif
153
154//===----------------------------------------------------------------------===//
155// Actual Store type.
156//===----------------------------------------------------------------------===//
157
158typedef llvm::ImmutableMap<BindingKey, SVal> ClusterBindings;
159typedef llvm::ImmutableMapRef<BindingKey, SVal> ClusterBindingsRef;
160typedef std::pair<BindingKey, SVal> BindingPair;
161
162typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
164
165namespace {
166class RegionBindingsRef : public llvm::ImmutableMapRef<const MemRegion *,
167 ClusterBindings> {
168 ClusterBindings::Factory *CBFactory;
169
170 // This flag indicates whether the current bindings are within the analysis
171 // that has started from main(). It affects how we perform loads from
172 // global variables that have initializers: if we have observed the
173 // program execution from the start and we know that these variables
174 // have not been overwritten yet, we can be sure that their initializers
175 // are still relevant. This flag never gets changed when the bindings are
176 // updated, so it could potentially be moved into RegionStoreManager
177 // (as if it's the same bindings but a different loading procedure)
178 // however that would have made the manager needlessly stateful.
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;
206 using llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>::lookup;
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<SVal> getDirectBinding(const MemRegion *R) const;
219
220 /// getDefaultBinding - Returns an SVal* representing an optional default
221 /// binding associated with a region and its subregions.
222 std::optional<SVal> getDefaultBinding(const MemRegion *R) const;
223
224 /// Return the internal tree as a Store.
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) {
256 if (isa<MemSpaceRegion>(L->first) && !isa<MemSpaceRegion>(R->first))
257 return true;
258 if (!isa<MemSpaceRegion>(L->first) && isa<MemSpaceRegion>(R->first))
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, /*AddQuotes=*/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,
327 const ClusterBindings &Bindings) const;
328};
329} // end anonymous namespace
330
331/// This class represents the same as \c RegionBindingsRef, but with a limit on
332/// the number of bindings that can be added.
333class LimitedRegionBindingsRef : public RegionBindingsRef {
334public:
336 SmallVectorImpl<SVal> &EscapedValuesDuringBind,
337 std::optional<unsigned> 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 {
362 return LimitedRegionBindingsRef{RegionBindingsRef::commitBindingsToCluster(
363 BaseRegion, BindingKeyAndValue),
364 *EscapedValuesDuringBind, BindingsLeft};
365 }
366
369 RegionBindingsRef::removeCluster(BaseRegion), *EscapedValuesDuringBind,
370 BindingsLeft};
371 }
372
374 std::optional<unsigned> NewBindingsLeft = BindingsLeft;
375 if (NewBindingsLeft.has_value()) {
376 assert(NewBindingsLeft.value() != 0);
377 NewBindingsLeft.value() -= 1;
378
379 // If we just exhausted the binding limit, highjack
380 // this bind call for the default binding.
381 if (NewBindingsLeft.value() == 0) {
383 K = BindingKey::Make(K.getRegion(), BindingKey::Default);
384 V = UnknownVal();
385 }
386 }
387
388 return LimitedRegionBindingsRef{RegionBindingsRef::addBinding(K, V),
389 *EscapedValuesDuringBind, NewBindingsLeft};
390 }
391
392 LimitedRegionBindingsRef addBinding(const MemRegion *R, BindingKey::Kind k,
393 SVal V) const {
394 return addBinding(BindingKey::Make(R, k), V);
395 }
396
397private:
398 SmallVectorImpl<SVal> *EscapedValuesDuringBind; // nonnull
399 std::optional<unsigned> BindingsLeft;
400};
401
402typedef const RegionBindingsRef& RegionBindingsConstRef;
404
405std::optional<SVal>
406RegionBindingsRef::getDirectBinding(const MemRegion *R) const {
407 const SVal *V = lookup(R, BindingKey::Direct);
408 return V ? std::optional<SVal>(*V) : std::nullopt;
409}
410
411std::optional<SVal>
412RegionBindingsRef::getDefaultBinding(const MemRegion *R) const {
413 const SVal *V = lookup(R, BindingKey::Default);
414 return V ? std::optional<SVal>(*V) : std::nullopt;
415}
416
417RegionBindingsRef RegionBindingsRef::commitBindingsToCluster(
418 const MemRegion *BaseRegion, const ClusterBindings &Bindings) const {
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
426 const ClusterBindings *ExistingCluster = lookup(Base);
428 (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
429 Bindings = CBFactory->add(Bindings, K, V);
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();
453 const ClusterBindings *Cluster = lookup(Base);
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// Main RegionStore logic.
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<SVal> SValListTy;
481private:
482 typedef llvm::DenseMap<const LazyCompoundValData *,
483 SValListTy> LazyBindingsMapTy;
484 LazyBindingsMapTy LazyBindingsMap;
485
486 /// The largest number of fields a struct can have and still be
487 /// considered "small".
488 ///
489 /// This is currently used to decide whether or not it is worth "forcing" a
490 /// LazyCompoundVal on bind.
491 ///
492 /// This is controlled by 'region-store-small-struct-limit' option.
493 /// To disable all small-struct-dependent behavior, set the option to "0".
494 const unsigned SmallStructLimit;
495
496 /// The largest number of element an array can have and still be
497 /// considered "small".
498 ///
499 /// This is currently used to decide whether or not it is worth "forcing" a
500 /// LazyCompoundVal on bind.
501 ///
502 /// This is controlled by 'region-store-small-struct-limit' option.
503 /// To disable all small-struct-dependent behavior, set the option to "0".
504 const unsigned SmallArrayLimit;
505
506 /// The number of bindings a single bind operation can scatter into.
507 /// For example, binding the initializer-list of an array would recurse and
508 /// bind all the individual array elements, potentially causing scalability
509 /// issues. Nullopt if the limit is disabled.
510 const std::optional<unsigned> RegionStoreMaxBindingFanOutPlusOne;
511
512 /// A helper used to populate the work list with the given set of
513 /// regions.
514 void populateWorkList(InvalidateRegionsWorker &W,
515 ArrayRef<SVal> 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<unsigned> {
529 unsigned FanOut = getOptions().RegionStoreMaxBindingFanOut;
530 assert(FanOut != std::numeric_limits<unsigned>::max());
531 if (FanOut == 0)
532 return std::nullopt;
533 return FanOut + 1 /*for the default binding*/;
534 }()) {}
535
536 /// setImplicitDefaultValue - Set the default binding for the provided
537 /// MemRegion to the value implicitly defined for compound literals when
538 /// the value is not specified.
539 LimitedRegionBindingsRef
540 setImplicitDefaultValue(LimitedRegionBindingsConstRef B, const MemRegion *R,
541 QualType T);
542
543 /// ArrayToPointer - Emulates the "decay" of an array to a pointer
544 /// type. 'Array' represents the lvalue of the array being decayed
545 /// to a pointer, and the returned SVal represents the decayed
546 /// version of that lvalue (i.e., a pointer to the first element of
547 /// the array). This is called by ExprEngine when evaluating
548 /// casts from arrays to pointers.
549 SVal ArrayToPointer(Loc Array, QualType ElementTy) override;
550
551 /// Creates the Store that correctly represents memory contents before
552 /// the beginning of the analysis of the given top-level stack frame.
553 StoreRef getInitialStore(const StackFrame *SF) override {
554 bool IsMainAnalysis = false;
555 if (const auto *FD = dyn_cast<FunctionDecl>(SF->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 // Binding values to regions.
566 //===-------------------------------------------------------------------===//
567 RegionBindingsRef invalidateGlobalRegion(MemRegion::Kind K,
569 unsigned Count, const StackFrame *SF,
570 RegionBindingsRef B,
571 InvalidatedRegions *Invalidated);
572
573 StoreRef invalidateRegions(Store store, ArrayRef<SVal> Values,
574 ConstCFGElementRef Elem, unsigned Count,
575 const StackFrame *SF, const CallEvent *Call,
577 RegionAndSymbolInvalidationTraits &ITraits,
578 InvalidatedRegions *Invalidated,
579 InvalidatedRegions *InvalidatedTopLevel) override;
580
581 bool scanReachableSymbols(Store S, const MemRegion *R,
582 ScanReachableSymbols &Callbacks) override;
583
584 LimitedRegionBindingsRef
585 removeSubRegionBindings(LimitedRegionBindingsConstRef B, const SubRegion *R);
586 std::optional<SVal>
587 getConstantValFromConstArrayInitializer(RegionBindingsConstRef B,
588 const ElementRegion *R);
589 std::optional<SVal>
590 getSValFromInitListExpr(const InitListExpr *ILE,
591 const SmallVector<uint64_t, 2> &ConcreteOffsets,
592 QualType ElemT);
593 SVal getSValFromStringLiteral(const StringLiteral *SL, uint64_t Offset,
594 QualType ElemT);
595
596public: // Part of public interface to class.
597 BindResult Bind(Store store, Loc LV, SVal V) override {
598 llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;
599 LimitedRegionBindingsRef BoundedBindings =
600 getRegionBindings(store, EscapedValuesDuringBind);
601 return BindResult{StoreRef(bind(BoundedBindings, LV, V).asStore(), *this),
602 std::move(EscapedValuesDuringBind)};
603 }
604
605 LimitedRegionBindingsRef bind(LimitedRegionBindingsConstRef B, Loc LV,
606 SVal V);
607
608 // BindDefaultInitial is only used to initialize a region with
609 // a default value.
610 BindResult BindDefaultInitial(Store store, const MemRegion *R,
611 SVal V) override {
612 RegionBindingsRef B = getRegionBindings(store);
613 // Use other APIs when you have to wipe the region that was initialized
614 // earlier.
615 assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
616 "Double initialization!");
617 B = B.addBinding(BindingKey::Make(R, BindingKey::Default), V);
618 return BindResult{
619 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this), {}};
620 }
621
622 // BindDefaultZero is used for zeroing constructors that may accidentally
623 // overwrite existing bindings.
624 BindResult BindDefaultZero(Store store, const MemRegion *R) override {
625 // FIXME: The offsets of empty bases can be tricky because of
626 // of the so called "empty base class optimization".
627 // If a base class has been optimized out
628 // we should not try to create a binding, otherwise we should.
629 // Unfortunately, at the moment ASTRecordLayout doesn't expose
630 // the actual sizes of the empty bases
631 // and trying to infer them from offsets/alignments
632 // seems to be error-prone and non-trivial because of the trailing padding.
633 // As a temporary mitigation we don't create bindings for empty bases.
634 if (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
635 if (BR->getDecl()->isEmpty())
636 return BindResult{StoreRef(store, *this), {}};
637
638 llvm::SmallVector<SVal, 0> EscapedValuesDuringBind;
639 LimitedRegionBindingsRef B =
640 getRegionBindings(store, EscapedValuesDuringBind);
641 SVal V = svalBuilder.makeZeroVal(Ctx.CharTy);
642 B = removeSubRegionBindings(B, cast<SubRegion>(R));
643 B = B.addBinding(BindingKey::Make(R, BindingKey::Default), V);
644 return BindResult{
645 StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this),
646 std::move(EscapedValuesDuringBind)};
647 }
648
649 /// Attempt to extract the fields of \p LCV and bind them to the struct region
650 /// \p R.
651 ///
652 /// This path is used when it seems advantageous to "force" loading the values
653 /// within a LazyCompoundVal to bind memberwise to the struct region, rather
654 /// than using a Default binding at the base of the entire region. This is a
655 /// heuristic attempting to avoid building long chains of LazyCompoundVals.
656 ///
657 /// \returns The updated store bindings, or \c std::nullopt if binding
658 /// non-lazily would be too expensive.
659 std::optional<LimitedRegionBindingsRef>
660 tryBindSmallStruct(LimitedRegionBindingsConstRef B, const TypedValueRegion *R,
661 const RecordDecl *RD, nonloc::LazyCompoundVal LCV);
662
663 /// BindStruct - Bind a compound value to a structure.
664 LimitedRegionBindingsRef bindStruct(LimitedRegionBindingsConstRef B,
665 const TypedValueRegion *R, SVal V);
666
667 /// BindVector - Bind a compound value to a vector.
668 LimitedRegionBindingsRef bindVector(LimitedRegionBindingsConstRef B,
669 const TypedValueRegion *R, SVal V);
670
671 std::optional<LimitedRegionBindingsRef>
672 tryBindSmallArray(LimitedRegionBindingsConstRef B, const TypedValueRegion *R,
673 const ArrayType *AT, nonloc::LazyCompoundVal LCV);
674
675 LimitedRegionBindingsRef bindArray(LimitedRegionBindingsConstRef B,
676 const TypedValueRegion *R, SVal V);
677
678 /// Clears out all bindings in the given region and assigns a new value
679 /// as a Default binding.
680 LimitedRegionBindingsRef bindAggregate(LimitedRegionBindingsConstRef B,
681 const TypedRegion *R, SVal DefaultVal);
682
683 /// Create a new store with the specified binding removed.
684 /// \param ST the original store, that is the basis for the new store.
685 /// \param L the location whose binding should be removed.
686 StoreRef killBinding(Store ST, Loc L) override;
687
688 void incrementReferenceCount(Store store) override {
689 getRegionBindings(store).manualRetain();
690 }
691
692 /// If the StoreManager supports it, decrement the reference count of
693 /// the specified Store object. If the reference count hits 0, the memory
694 /// associated with the object is recycled.
695 void decrementReferenceCount(Store store) override {
696 getRegionBindings(store).manualRelease();
697 }
698
699 bool includedInBindings(Store store, const MemRegion *region) const override;
700
701 /// Return the value bound to specified location in a given state.
702 ///
703 /// The high level logic for this method is this:
704 /// getBinding (L)
705 /// if L has binding
706 /// return L's binding
707 /// else if L is in killset
708 /// return unknown
709 /// else
710 /// if L is on stack or heap
711 /// return undefined
712 /// else
713 /// return symbolic
714 SVal getBinding(Store S, Loc L, QualType T) override {
715 return getBinding(getRegionBindings(S), L, T);
716 }
717
718 std::optional<SVal> getDefaultBinding(Store S, const MemRegion *R) override {
719 RegionBindingsRef B = getRegionBindings(S);
720 // Default bindings are always applied over a base region so look up the
721 // base region's default binding, otherwise the lookup will fail when R
722 // is at an offset from R->getBaseRegion().
723 return B.getDefaultBinding(R->getBaseRegion());
724 }
725
726 SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
727
728 SVal getBindingForElement(RegionBindingsConstRef B, const ElementRegion *R);
729
730 SVal getBindingForField(RegionBindingsConstRef B, const FieldRegion *R);
731
732 SVal getBindingForObjCIvar(RegionBindingsConstRef B, const ObjCIvarRegion *R);
733
734 SVal getBindingForVar(RegionBindingsConstRef B, const VarRegion *R);
735
736 SVal getBindingForLazySymbol(const TypedValueRegion *R);
737
738 SVal getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
739 const TypedValueRegion *R,
740 QualType Ty);
741
742 SVal getLazyBinding(const SubRegion *LazyBindingRegion,
743 RegionBindingsRef LazyBinding);
744
745 /// Get bindings for the values in a struct and return a CompoundVal, used
746 /// when doing struct copy:
747 /// struct s x, y;
748 /// x = y;
749 /// y's value is retrieved by this method.
750 SVal getBindingForStruct(RegionBindingsConstRef B, const TypedValueRegion *R);
751 SVal getBindingForArray(RegionBindingsConstRef B, const TypedValueRegion *R);
752 NonLoc createLazyBinding(RegionBindingsConstRef B, const TypedValueRegion *R);
753
754 /// Used to lazily generate derived symbols for bindings that are defined
755 /// implicitly by default bindings in a super region.
756 ///
757 /// Note that callers may need to specially handle LazyCompoundVals, which
758 /// are returned as is in case the caller needs to treat them differently.
759 std::optional<SVal>
760 getBindingForDerivedDefaultValue(RegionBindingsConstRef B,
761 const MemRegion *superR,
762 const TypedValueRegion *R, QualType Ty);
763
764 /// Get the state and region whose binding this region \p R corresponds to.
765 ///
766 /// If there is no lazy binding for \p R, the returned value will have a null
767 /// \c second. Note that a null pointer can represents a valid Store.
768 std::pair<Store, const SubRegion *>
769 findLazyBinding(RegionBindingsConstRef B, const SubRegion *R,
770 const SubRegion *originalRegion);
771
772 /// Returns the cached set of interesting SVals contained within a lazy
773 /// binding.
774 ///
775 /// The precise value of "interesting" is determined for the purposes of
776 /// RegionStore's internal analysis. It must always contain all regions and
777 /// symbols, but may omit constants and other kinds of SVal.
778 ///
779 /// In contrast to compound values, LazyCompoundVals are also added
780 /// to the 'interesting values' list in addition to the child interesting
781 /// values.
782 const SValListTy &getInterestingValues(nonloc::LazyCompoundVal LCV);
783
784 //===------------------------------------------------------------------===//
785 // State pruning.
786 //===------------------------------------------------------------------===//
787
788 /// removeDeadBindings - Scans the RegionStore of 'state' for dead values.
789 /// It returns a new Store with these values removed.
790 StoreRef removeDeadBindings(Store store, const StackFrame *SF,
791 SymbolReaper &SymReaper) override;
792
793 //===------------------------------------------------------------------===//
794 // Utility methods.
795 //===------------------------------------------------------------------===//
796
797 RegionBindingsRef getRegionBindings(Store store) const {
798 llvm::PointerIntPair<Store, 1, bool> Ptr;
799 Ptr.setFromOpaqueValue(const_cast<void *>(store));
800 return {CBFactory,
801 static_cast<const RegionBindings::TreeTy *>(Ptr.getPointer()),
802 RBFactory.getTreeFactory(), Ptr.getInt()};
803 }
804
805 LimitedRegionBindingsRef
806 getRegionBindings(Store store,
807 SmallVectorImpl<SVal> &EscapedValuesDuringBind) const {
808 return LimitedRegionBindingsRef(
809 getRegionBindings(store), EscapedValuesDuringBind,
810 /*BindingsLeft=*/RegionStoreMaxBindingFanOutPlusOne);
811 }
812
813 void printJson(raw_ostream &Out, Store S, const char *NL = "\n",
814 unsigned int Space = 0, bool IsDot = false) const override;
815
816 void iterBindings(Store store, BindingsHandler& f) override {
817 RegionBindingsRef B = getRegionBindings(store);
818 for (const auto &[Region, Cluster] : B) {
819 for (const auto &[Key, Value] : Cluster) {
820 if (!Key.isDirect())
821 continue;
822 if (const SubRegion *R = dyn_cast<SubRegion>(Key.getRegion())) {
823 // FIXME: Possibly incorporate the offset?
824 if (!f.HandleBinding(*this, store, R, Value))
825 return;
826 }
827 }
828 }
829 }
830};
831
832} // end anonymous namespace
833
834//===----------------------------------------------------------------------===//
835// RegionStore creation.
836//===----------------------------------------------------------------------===//
837
838std::unique_ptr<StoreManager>
840 return std::make_unique<RegionStoreManager>(StMgr);
841}
842
843//===----------------------------------------------------------------------===//
844// Region Cluster analysis.
845//===----------------------------------------------------------------------===//
846
847namespace {
848/// Used to determine which global regions are automatically included in the
849/// initial worklist of a ClusterAnalysis.
850enum GlobalsFilterKind {
851 /// Don't include any global regions.
852 GFK_None,
853 /// Only include system globals.
854 GFK_SystemOnly,
855 /// Include all global regions.
856 GFK_All
857};
858
859template <typename DERIVED>
860class ClusterAnalysis {
861protected:
862 typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
863 typedef const MemRegion * WorkListElement;
865
867
868 WorkList WL;
869
870 RegionStoreManager &RM;
871 ASTContext &Ctx;
872 SValBuilder &svalBuilder;
873
874 RegionBindingsRef B;
875
876
877protected:
878 const ClusterBindings *getCluster(const MemRegion *R) {
879 return B.lookup(R);
880 }
881
882 /// Returns true if all clusters in the given memspace should be initially
883 /// included in the cluster analysis. Subclasses may provide their
884 /// own implementation.
885 bool includeEntireMemorySpace(const MemRegion *Base) {
886 return false;
887 }
888
889public:
890 ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
891 RegionBindingsRef b)
892 : RM(rm), Ctx(StateMgr.getContext()),
893 svalBuilder(StateMgr.getSValBuilder()), B(std::move(b)) {}
894
895 RegionBindingsRef getRegionBindings() const { return B; }
896
897 bool isVisited(const MemRegion *R) {
898 return Visited.count(getCluster(R));
899 }
900
901 void GenerateClusters() {
902 // Scan the entire set of bindings and record the region clusters.
903 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
904 RI != RE; ++RI){
905 const MemRegion *Base = RI.getKey();
906
907 const ClusterBindings &Cluster = RI.getData();
908 assert(!Cluster.isEmpty() && "Empty clusters should be removed");
909 static_cast<DERIVED*>(this)->VisitAddedToCluster(Base, Cluster);
910
911 // If the base's memspace should be entirely invalidated, add the cluster
912 // to the workspace up front.
913 if (static_cast<DERIVED*>(this)->includeEntireMemorySpace(Base))
914 AddToWorkList(WorkListElement(Base), &Cluster);
915 }
916 }
917
918 bool AddToWorkList(WorkListElement E, const ClusterBindings *C) {
919 if (C && !Visited.insert(C).second)
920 return false;
921 WL.push_back(E);
922 return true;
923 }
924
925 bool AddToWorkList(const MemRegion *R) {
926 return static_cast<DERIVED*>(this)->AddToWorkList(R);
927 }
928
929 void RunWorkList() {
930 while (!WL.empty()) {
931 WorkListElement E = WL.pop_back_val();
932 const MemRegion *BaseR = E;
933
934 static_cast<DERIVED*>(this)->VisitCluster(BaseR, getCluster(BaseR));
935 }
936 }
937
938 void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C) {}
939 void VisitCluster(const MemRegion *baseR, const ClusterBindings *C) {}
940
941 void VisitCluster(const MemRegion *BaseR, const ClusterBindings *C,
942 bool Flag) {
943 static_cast<DERIVED*>(this)->VisitCluster(BaseR, C);
944 }
945};
946}
947
948//===----------------------------------------------------------------------===//
949// Binding invalidation.
950//===----------------------------------------------------------------------===//
951
952bool RegionStoreManager::scanReachableSymbols(Store S, const MemRegion *R,
953 ScanReachableSymbols &Callbacks) {
954 assert(R == R->getBaseRegion() && "Should only be called for base regions");
955 RegionBindingsRef B = getRegionBindings(S);
956 const ClusterBindings *Cluster = B.lookup(R);
957
958 if (!Cluster)
959 return true;
960
961 for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
962 RI != RE; ++RI) {
963 if (!Callbacks.scan(RI.getData()))
964 return false;
965 }
966
967 return true;
968}
969
970static inline bool isUnionField(const FieldRegion *FR) {
971 return FR->getDecl()->getParent()->isUnion();
972}
973
975
976static void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields) {
977 assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
978
979 const MemRegion *Base = K.getConcreteOffsetRegion();
980 const MemRegion *R = K.getRegion();
981
982 while (R != Base) {
983 if (const FieldRegion *FR = dyn_cast<FieldRegion>(R))
984 if (!isUnionField(FR))
985 Fields.push_back(FR->getDecl());
986
987 R = cast<SubRegion>(R)->getSuperRegion();
988 }
989}
990
991static bool isCompatibleWithFields(BindingKey K, const FieldVector &Fields) {
992 assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
993
994 if (Fields.empty())
995 return true;
996
997 FieldVector FieldsInBindingKey;
998 getSymbolicOffsetFields(K, FieldsInBindingKey);
999
1000 ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
1001 if (Delta >= 0)
1002 return std::equal(FieldsInBindingKey.begin() + Delta,
1003 FieldsInBindingKey.end(),
1004 Fields.begin());
1005 else
1006 return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
1007 Fields.begin() - Delta);
1008}
1009
1010/// Collects all bindings in \p Cluster that may refer to bindings within
1011/// \p Top.
1012///
1013/// Each binding is a pair whose \c first is the key (a BindingKey) and whose
1014/// \c second is the value (an SVal).
1015///
1016/// The \p IncludeAllDefaultBindings parameter specifies whether to include
1017/// default bindings that may extend beyond \p Top itself, e.g. if \p Top is
1018/// an aggregate within a larger aggregate with a default binding.
1019static void
1021 SValBuilder &SVB, const ClusterBindings &Cluster,
1022 const SubRegion *Top, BindingKey TopKey,
1023 bool IncludeAllDefaultBindings) {
1024 FieldVector FieldsInSymbolicSubregions;
1025 if (TopKey.hasSymbolicOffset()) {
1026 getSymbolicOffsetFields(TopKey, FieldsInSymbolicSubregions);
1027 Top = TopKey.getConcreteOffsetRegion();
1028 TopKey = BindingKey::Make(Top, BindingKey::Default);
1029 }
1030
1031 // Find the length (in bits) of the region being invalidated.
1032 uint64_t Length = UINT64_MAX;
1033 SVal Extent = Top->getMemRegionManager().getStaticSize(Top, SVB);
1034 if (std::optional<nonloc::ConcreteInt> ExtentCI =
1035 Extent.getAs<nonloc::ConcreteInt>()) {
1036 const llvm::APSInt &ExtentInt = ExtentCI->getValue();
1037 assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
1038 // Extents are in bytes but region offsets are in bits. Be careful!
1039 Length = ExtentInt.getLimitedValue() * SVB.getContext().getCharWidth();
1040 } else if (const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
1041 if (FR->getDecl()->isBitField())
1042 Length = FR->getDecl()->getBitWidthValue();
1043 }
1044
1045 for (const auto &StoreEntry : Cluster) {
1046 BindingKey NextKey = StoreEntry.first;
1047 if (NextKey.getRegion() == TopKey.getRegion()) {
1048 // FIXME: This doesn't catch the case where we're really invalidating a
1049 // region with a symbolic offset. Example:
1050 // R: points[i].y
1051 // Next: points[0].x
1052
1053 if (NextKey.getOffset() > TopKey.getOffset() &&
1054 NextKey.getOffset() - TopKey.getOffset() < Length) {
1055 // Case 1: The next binding is inside the region we're invalidating.
1056 // Include it.
1057 Bindings.push_back(StoreEntry);
1058
1059 } else if (NextKey.getOffset() == TopKey.getOffset()) {
1060 // Case 2: The next binding is at the same offset as the region we're
1061 // invalidating. In this case, we need to leave default bindings alone,
1062 // since they may be providing a default value for a regions beyond what
1063 // we're invalidating.
1064 // FIXME: This is probably incorrect; consider invalidating an outer
1065 // struct whose first field is bound to a LazyCompoundVal.
1066 if (IncludeAllDefaultBindings || NextKey.isDirect())
1067 Bindings.push_back(StoreEntry);
1068 }
1069
1070 } else if (NextKey.hasSymbolicOffset()) {
1071 const MemRegion *Base = NextKey.getConcreteOffsetRegion();
1072 if (Top->isSubRegionOf(Base) && Top != Base) {
1073 // Case 3: The next key is symbolic and we just changed something within
1074 // its concrete region. We don't know if the binding is still valid, so
1075 // we'll be conservative and include it.
1076 if (IncludeAllDefaultBindings || NextKey.isDirect())
1077 if (isCompatibleWithFields(NextKey, FieldsInSymbolicSubregions))
1078 Bindings.push_back(StoreEntry);
1079 } else if (const SubRegion *BaseSR = dyn_cast<SubRegion>(Base)) {
1080 // Case 4: The next key is symbolic, but we changed a known
1081 // super-region. In this case the binding is certainly included.
1082 if (BaseSR->isSubRegionOf(Top))
1083 if (isCompatibleWithFields(NextKey, FieldsInSymbolicSubregions))
1084 Bindings.push_back(StoreEntry);
1085 }
1086 }
1087 }
1088}
1089
1090static void
1092 SValBuilder &SVB, const ClusterBindings &Cluster,
1093 const SubRegion *Top, bool IncludeAllDefaultBindings) {
1094 collectSubRegionBindings(Bindings, SVB, Cluster, Top,
1095 BindingKey::Make(Top, BindingKey::Default),
1096 IncludeAllDefaultBindings);
1097}
1098
1099LimitedRegionBindingsRef
1100RegionStoreManager::removeSubRegionBindings(LimitedRegionBindingsConstRef B,
1101 const SubRegion *Top) {
1102 BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
1103 const MemRegion *ClusterHead = TopKey.getBaseRegion();
1104
1105 if (Top == ClusterHead) {
1106 // We can remove an entire cluster's bindings all in one go.
1107 return B.removeCluster(Top);
1108 }
1109
1110 const ClusterBindings *Cluster = B.lookup(ClusterHead);
1111 if (!Cluster) {
1112 // If we're invalidating a region with a symbolic offset, we need to make
1113 // sure we don't treat the base region as uninitialized anymore.
1114 if (TopKey.hasSymbolicOffset()) {
1115 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1116 return B.addBinding(Concrete, BindingKey::Default, UnknownVal());
1117 }
1118 return B;
1119 }
1120
1121 SmallVector<BindingPair, 32> Bindings;
1122 collectSubRegionBindings(Bindings, svalBuilder, *Cluster, Top, TopKey,
1123 /*IncludeAllDefaultBindings=*/false);
1124
1125 ClusterBindingsRef Result(*Cluster, CBFactory);
1126 for (BindingKey Key : llvm::make_first_range(Bindings))
1127 Result = Result.remove(Key);
1128
1129 // If we're invalidating a region with a symbolic offset, we need to make sure
1130 // we don't treat the base region as uninitialized anymore.
1131 // FIXME: This isn't very precise; see the example in
1132 // collectSubRegionBindings.
1133 if (TopKey.hasSymbolicOffset()) {
1134 const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
1135 Result = Result.add(BindingKey::Make(Concrete, BindingKey::Default),
1136 UnknownVal());
1137 }
1138
1139 if (Result.isEmpty())
1140 return B.removeCluster(ClusterHead);
1141 return B.addWithoutDecreasingLimit(ClusterHead, Result.asImmutableMap());
1142}
1143
1144namespace {
1145class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
1146{
1147 ConstCFGElementRef Elem;
1148 unsigned Count;
1149 const StackFrame *SF;
1151 RegionAndSymbolInvalidationTraits &ITraits;
1153 GlobalsFilterKind GlobalsFilter;
1154public:
1155 InvalidateRegionsWorker(RegionStoreManager &rm, ProgramStateManager &stateMgr,
1156 RegionBindingsRef b, ConstCFGElementRef elem,
1157 unsigned count, const StackFrame *SF,
1159 RegionAndSymbolInvalidationTraits &ITraitsIn,
1161 GlobalsFilterKind GFK)
1162 : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b), Elem(elem),
1163 Count(count), SF(SF), IS(is), ITraits(ITraitsIn), Regions(r),
1164 GlobalsFilter(GFK) {}
1165
1166 void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);
1167 void VisitBinding(SVal V);
1168
1169 using ClusterAnalysis::AddToWorkList;
1170
1171 bool AddToWorkList(const MemRegion *R);
1172
1173 /// Returns true if all clusters in the memory space for \p Base should be
1174 /// be invalidated.
1175 bool includeEntireMemorySpace(const MemRegion *Base);
1176
1177 /// Returns true if the memory space of the given region is one of the global
1178 /// regions specially included at the start of invalidation.
1179 bool isInitiallyIncludedGlobalRegion(const MemRegion *R);
1180};
1181}
1182
1183bool InvalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
1184 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1186 const MemRegion *BaseR = doNotInvalidateSuperRegion ? R : R->getBaseRegion();
1187 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
1188}
1189
1190void InvalidateRegionsWorker::VisitBinding(SVal V) {
1191 // A symbol? Mark it touched by the invalidation.
1192 if (SymbolRef Sym = V.getAsSymbol())
1193 IS.insert(Sym);
1194
1195 if (const MemRegion *R = V.getAsRegion()) {
1196 AddToWorkList(R);
1197 return;
1198 }
1199
1200 // Is it a LazyCompoundVal? All references get invalidated as well.
1201 if (std::optional<nonloc::LazyCompoundVal> LCS =
1202 V.getAs<nonloc::LazyCompoundVal>()) {
1203
1204 // `getInterestingValues()` returns SVals contained within LazyCompoundVals,
1205 // so there is no need to visit them.
1206 for (SVal V : RM.getInterestingValues(*LCS))
1208 VisitBinding(V);
1209
1210 return;
1211 }
1212}
1213
1214void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
1215 const ClusterBindings *C) {
1216
1217 bool PreserveRegionsContents =
1218 ITraits.hasTrait(baseR,
1220
1221 if (C) {
1222 for (SVal Val : llvm::make_second_range(*C))
1223 VisitBinding(Val);
1224
1225 // Invalidate regions contents.
1226 if (!PreserveRegionsContents)
1227 B = B.removeCluster(baseR);
1228 }
1229
1230 if (const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
1231 if (const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
1232
1233 // Lambdas can affect all static local variables without explicitly
1234 // capturing those.
1235 // We invalidate all static locals referenced inside the lambda body.
1236 if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
1237 using namespace ast_matchers;
1238
1239 const char *DeclBind = "DeclBind";
1241 to(varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
1242 auto Matches =
1243 match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
1244 RD->getASTContext());
1245
1246 for (BoundNodes &Match : Matches) {
1247 auto *VD = Match.getNodeAs<VarDecl>(DeclBind);
1248 const VarRegion *ToInvalidate =
1249 RM.getRegionManager().getVarRegion(VD, SF);
1250 AddToWorkList(ToInvalidate);
1251 }
1252 }
1253 }
1254 }
1255
1256 // BlockDataRegion? If so, invalidate captured variables that are passed
1257 // by reference.
1258 if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
1259 for (auto Var : BR->referenced_vars()) {
1260 const VarRegion *VR = Var.getCapturedRegion();
1261 const VarDecl *VD = VR->getDecl();
1262 if (VD->hasAttr<BlocksAttr>() || !VD->hasLocalStorage()) {
1263 AddToWorkList(VR);
1264 }
1265 else if (Loc::isLocType(VR->getValueType())) {
1266 // Map the current bindings to a Store to retrieve the value
1267 // of the binding. If that binding itself is a region, we should
1268 // invalidate that region. This is because a block may capture
1269 // a pointer value, but the thing pointed by that pointer may
1270 // get invalidated.
1271 SVal V = RM.getBinding(B, loc::MemRegionVal(VR));
1272 if (std::optional<Loc> L = V.getAs<Loc>()) {
1273 if (const MemRegion *LR = L->getAsRegion())
1274 AddToWorkList(LR);
1275 }
1276 }
1277 }
1278 return;
1279 }
1280
1281 // Symbolic region?
1282 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
1283 IS.insert(SR->getSymbol());
1284
1285 // Nothing else should be done in the case when we preserve regions context.
1286 if (PreserveRegionsContents)
1287 return;
1288
1289 // Otherwise, we have a normal data region. Record that we touched the region.
1290 if (Regions)
1291 Regions->push_back(baseR);
1292
1294 // Invalidate the region by setting its default value to
1295 // conjured symbol. The type of the symbol is irrelevant.
1296 DefinedOrUnknownSVal V =
1297 svalBuilder.conjureSymbolVal(baseR, Elem, SF, Ctx.IntTy, Count);
1298 B = B.addBinding(baseR, BindingKey::Default, V);
1299 return;
1300 }
1301
1302 if (!baseR->isBoundable())
1303 return;
1304
1305 const TypedValueRegion *TR = cast<TypedValueRegion>(baseR);
1306 QualType T = TR->getValueType();
1307
1308 if (isInitiallyIncludedGlobalRegion(baseR)) {
1309 // If the region is a global and we are invalidating all globals,
1310 // erasing the entry is good enough. This causes all globals to be lazily
1311 // symbolicated from the same base symbol.
1312 return;
1313 }
1314
1315 if (T->isRecordType()) {
1316 // Invalidate the region by setting its default value to
1317 // conjured symbol. The type of the symbol is irrelevant.
1318 DefinedOrUnknownSVal V =
1319 svalBuilder.conjureSymbolVal(baseR, Elem, SF, Ctx.IntTy, Count);
1320 B = B.addBinding(baseR, BindingKey::Default, V);
1321 return;
1322 }
1323
1324 if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
1325 bool doNotInvalidateSuperRegion = ITraits.hasTrait(
1326 baseR,
1328
1329 if (doNotInvalidateSuperRegion) {
1330 // We are not doing blank invalidation of the whole array region so we
1331 // have to manually invalidate each elements.
1332 std::optional<uint64_t> NumElements;
1333
1334 // Compute lower and upper offsets for region within array.
1335 if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
1336 NumElements = CAT->getZExtSize();
1337 if (!NumElements) // We are not dealing with a constant size array
1338 goto conjure_default;
1339 QualType ElementTy = AT->getElementType();
1340 uint64_t ElemSize = Ctx.getTypeSize(ElementTy);
1341 const RegionOffset &RO = baseR->getAsOffset();
1342 const MemRegion *SuperR = baseR->getBaseRegion();
1343 if (RO.hasSymbolicOffset()) {
1344 // If base region has a symbolic offset,
1345 // we revert to invalidating the super region.
1346 if (SuperR)
1347 AddToWorkList(SuperR);
1348 goto conjure_default;
1349 }
1350
1351 uint64_t LowerOffset = RO.getOffset();
1352 uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
1353 bool UpperOverflow = UpperOffset < LowerOffset;
1354
1355 // Invalidate regions which are within array boundaries,
1356 // or have a symbolic offset.
1357 if (!SuperR)
1358 goto conjure_default;
1359
1360 const ClusterBindings *C = B.lookup(SuperR);
1361 if (!C)
1362 goto conjure_default;
1363
1364 for (const auto &[BK, V] : *C) {
1365 std::optional<uint64_t> ROffset =
1366 BK.hasSymbolicOffset() ? std::optional<uint64_t>() : BK.getOffset();
1367
1368 // Check offset is not symbolic and within array's boundaries.
1369 // Handles arrays of 0 elements and of 0-sized elements as well.
1370 if (!ROffset ||
1371 ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
1372 (UpperOverflow &&
1373 (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
1374 (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
1375 B = B.removeBinding(BK);
1376 // Bound symbolic regions need to be invalidated for dead symbol
1377 // detection.
1378 const MemRegion *R = V.getAsRegion();
1379 if (isa_and_nonnull<SymbolicRegion>(R))
1380 VisitBinding(V);
1381 }
1382 }
1383 }
1384 conjure_default:
1385 // Set the default value of the array to conjured symbol.
1386 DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(
1387 baseR, Elem, SF, AT->getElementType(), Count);
1388 B = B.addBinding(baseR, BindingKey::Default, V);
1389 return;
1390 }
1391
1392 DefinedOrUnknownSVal V =
1393 svalBuilder.conjureSymbolVal(baseR, Elem, SF, T, Count);
1394 assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
1395 B = B.addBinding(baseR, BindingKey::Direct, V);
1396}
1397
1398bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
1399 const MemRegion *R) {
1400 switch (GlobalsFilter) {
1401 case GFK_None:
1402 return false;
1403 case GFK_SystemOnly:
1404 return isa<GlobalSystemSpaceRegion>(R->getRawMemorySpace());
1405 case GFK_All:
1406 return isa<NonStaticGlobalSpaceRegion>(R->getRawMemorySpace());
1407 }
1408
1409 llvm_unreachable("unknown globals filter");
1410}
1411
1412bool InvalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {
1413 if (isInitiallyIncludedGlobalRegion(Base))
1414 return true;
1415
1416 const MemSpaceRegion *MemSpace = Base->getRawMemorySpace();
1417 return ITraits.hasTrait(MemSpace,
1419}
1420
1421RegionBindingsRef RegionStoreManager::invalidateGlobalRegion(
1422 MemRegion::Kind K, ConstCFGElementRef Elem, unsigned Count,
1423 const StackFrame *SF, RegionBindingsRef B,
1424 InvalidatedRegions *Invalidated) {
1425 // Bind the globals memory space to a new symbol that we will use to derive
1426 // the bindings for all globals.
1427 const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);
1428 SVal V = svalBuilder.conjureSymbolVal(
1429 /* symbolTag = */ (const void *)GS, Elem, SF,
1430 /* type does not matter */ Ctx.IntTy, Count);
1431
1432 B = B.removeBinding(GS)
1433 .addBinding(BindingKey::Make(GS, BindingKey::Default), V);
1434
1435 // Even if there are no bindings in the global scope, we still need to
1436 // record that we touched it.
1437 if (Invalidated)
1438 Invalidated->push_back(GS);
1439
1440 return B;
1441}
1442
1443void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
1444 ArrayRef<SVal> Values,
1445 InvalidatedRegions *TopLevelRegions) {
1446 for (SVal V : Values) {
1447 if (auto LCS = V.getAs<nonloc::LazyCompoundVal>()) {
1448 for (SVal S : getInterestingValues(*LCS))
1449 if (const MemRegion *R = S.getAsRegion())
1450 W.AddToWorkList(R);
1451
1452 continue;
1453 }
1454
1455 if (const MemRegion *R = V.getAsRegion()) {
1456 if (TopLevelRegions)
1457 TopLevelRegions->push_back(R);
1458 W.AddToWorkList(R);
1459 continue;
1460 }
1461 }
1462}
1463
1464StoreRef RegionStoreManager::invalidateRegions(
1465 Store store, ArrayRef<SVal> Values, ConstCFGElementRef Elem, unsigned Count,
1466 const StackFrame *SF, const CallEvent *Call, InvalidatedSymbols &IS,
1467 RegionAndSymbolInvalidationTraits &ITraits,
1468 InvalidatedRegions *TopLevelRegions, InvalidatedRegions *Invalidated) {
1469 GlobalsFilterKind GlobalsFilter;
1470 if (Call) {
1471 if (Call->isInSystemHeader())
1472 GlobalsFilter = GFK_SystemOnly;
1473 else
1474 GlobalsFilter = GFK_All;
1475 } else {
1476 GlobalsFilter = GFK_None;
1477 }
1478
1479 RegionBindingsRef B = getRegionBindings(store);
1480 InvalidateRegionsWorker W(*this, StateMgr, B, Elem, Count, SF, IS, ITraits,
1481 Invalidated, GlobalsFilter);
1482
1483 // Scan the bindings and generate the clusters.
1484 W.GenerateClusters();
1485
1486 // Add the regions to the worklist.
1487 populateWorkList(W, Values, TopLevelRegions);
1488
1489 W.RunWorkList();
1490
1491 // Return the new bindings.
1492 B = W.getRegionBindings();
1493
1494 // For calls, determine which global regions should be invalidated and
1495 // invalidate them. (Note that function-static and immutable globals are never
1496 // invalidated by this.)
1497 // TODO: This could possibly be more precise with modules.
1498 switch (GlobalsFilter) {
1499 case GFK_All:
1500 B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind, Elem,
1501 Count, SF, B, Invalidated);
1502 [[fallthrough]];
1503 case GFK_SystemOnly:
1504 B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind, Elem,
1505 Count, SF, B, Invalidated);
1506 [[fallthrough]];
1507 case GFK_None:
1508 break;
1509 }
1510
1511 return StoreRef(B.asStore(), *this);
1512}
1513
1514//===----------------------------------------------------------------------===//
1515// Location and region casting.
1516//===----------------------------------------------------------------------===//
1517
1518/// ArrayToPointer - Emulates the "decay" of an array to a pointer
1519/// type. 'Array' represents the lvalue of the array being decayed
1520/// to a pointer, and the returned SVal represents the decayed
1521/// version of that lvalue (i.e., a pointer to the first element of
1522/// the array). This is called by ExprEngine when evaluating casts
1523/// from arrays to pointers.
1524SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) {
1526 return Array;
1527
1529 return UnknownVal();
1530
1531 const SubRegion *R =
1532 cast<SubRegion>(Array.castAs<loc::MemRegionVal>().getRegion());
1533 NonLoc ZeroIdx = svalBuilder.makeZeroArrayIndex();
1534 return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));
1535}
1536
1537//===----------------------------------------------------------------------===//
1538// Loading values from regions.
1539//===----------------------------------------------------------------------===//
1540
1541SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T) {
1542 assert(!isa<UnknownVal>(L) && "location unknown");
1543 assert(!isa<UndefinedVal>(L) && "location undefined");
1544
1545 // For access to concrete addresses, return UnknownVal. Checks
1546 // for null dereferences (and similar errors) are done by checkers, not
1547 // the Store.
1548 // FIXME: We can consider lazily symbolicating such memory, but we really
1549 // should defer this when we can reason easily about symbolicating arrays
1550 // of bytes.
1551 if (L.getAs<loc::ConcreteInt>()) {
1552 return UnknownVal();
1553 }
1554 if (!L.getAs<loc::MemRegionVal>()) {
1555 return UnknownVal();
1556 }
1557
1558 const MemRegion *MR = L.castAs<loc::MemRegionVal>().getRegion();
1559
1560 if (isa<BlockDataRegion>(MR)) {
1561 return UnknownVal();
1562 }
1563
1564 // Auto-detect the binding type.
1565 if (T.isNull()) {
1566 if (const auto *TVR = dyn_cast<TypedValueRegion>(MR))
1567 T = TVR->getValueType();
1568 else if (const auto *TR = dyn_cast<TypedRegion>(MR))
1569 T = TR->getLocationType()->getPointeeType();
1570 else if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
1571 T = SR->getPointeeStaticType();
1572 }
1573 assert(!T.isNull() && "Unable to auto-detect binding type!");
1574 assert(!T->isVoidType() && "Attempting to dereference a void pointer!");
1575
1576 if (!isa<TypedValueRegion>(MR))
1577 MR = GetElementZeroRegion(cast<SubRegion>(MR), T);
1578
1579 // FIXME: Perhaps this method should just take a 'const MemRegion*' argument
1580 // instead of 'Loc', and have the other Loc cases handled at a higher level.
1581 const TypedValueRegion *R = cast<TypedValueRegion>(MR);
1582 QualType RTy = R->getValueType();
1583
1584 // FIXME: we do not yet model the parts of a complex type, so treat the
1585 // whole thing as "unknown".
1586 if (RTy->isAnyComplexType())
1587 return UnknownVal();
1588
1589 // FIXME: We should eventually handle funny addressing. e.g.:
1590 //
1591 // int x = ...;
1592 // int *p = &x;
1593 // char *q = (char*) p;
1594 // char c = *q; // returns the first byte of 'x'.
1595 //
1596 // Such funny addressing will occur due to layering of regions.
1597 if (RTy->isStructureOrClassType())
1598 return getBindingForStruct(B, R);
1599
1600 // FIXME: Handle unions.
1601 if (RTy->isUnionType())
1602 return createLazyBinding(B, R);
1603
1604 if (RTy->isArrayType()) {
1605 if (RTy->isConstantArrayType())
1606 return getBindingForArray(B, R);
1607 else
1608 return UnknownVal();
1609 }
1610
1611 // FIXME: handle Vector types.
1612 if (RTy->isVectorType())
1613 return UnknownVal();
1614
1615 if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
1616 return svalBuilder.evalCast(getBindingForField(B, FR), T, QualType{});
1617
1618 if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
1619 // FIXME: Here we actually perform an implicit conversion from the loaded
1620 // value to the element type. Eventually we want to compose these values
1621 // more intelligently. For example, an 'element' can encompass multiple
1622 // bound regions (e.g., several bound bytes), or could be a subset of
1623 // a larger value.
1624 return svalBuilder.evalCast(getBindingForElement(B, ER), T, QualType{});
1625 }
1626
1627 if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
1628 // FIXME: Here we actually perform an implicit conversion from the loaded
1629 // value to the ivar type. What we should model is stores to ivars
1630 // that blow past the extent of the ivar. If the address of the ivar is
1631 // reinterpretted, it is possible we stored a different value that could
1632 // fit within the ivar. Either we need to cast these when storing them
1633 // or reinterpret them lazily (as we do here).
1634 return svalBuilder.evalCast(getBindingForObjCIvar(B, IVR), T, QualType{});
1635 }
1636
1637 if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
1638 // FIXME: Here we actually perform an implicit conversion from the loaded
1639 // value to the variable type. What we should model is stores to variables
1640 // that blow past the extent of the variable. If the address of the
1641 // variable is reinterpretted, it is possible we stored a different value
1642 // that could fit within the variable. Either we need to cast these when
1643 // storing them or reinterpret them lazily (as we do here).
1644 return svalBuilder.evalCast(getBindingForVar(B, VR), T, QualType{});
1645 }
1646
1647 const SVal *V = B.lookup(R, BindingKey::Direct);
1648
1649 // Check if the region has a binding.
1650 if (V)
1651 return *V;
1652
1653 // The location does not have a bound value. This means that it has
1654 // the value it had upon its creation and/or entry to the analyzed
1655 // function/method. These are either symbolic values or 'undefined'.
1656 if (isa<StackLocalsSpaceRegion>(R->getRawMemorySpace())) {
1657 // All stack variables are considered to have undefined values
1658 // upon creation. All heap allocated blocks are considered to
1659 // have undefined values as well unless they are explicitly bound
1660 // to specific values.
1661 return UndefinedVal();
1662 }
1663
1664 // All other values are symbolic.
1665 return svalBuilder.getRegionValueSymbolVal(R);
1666}
1667
1669 QualType RegionTy;
1670 if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R))
1671 RegionTy = TVR->getValueType();
1672
1673 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
1674 RegionTy = SR->getSymbol()->getType();
1675
1676 return RegionTy;
1677}
1678
1679/// Checks to see if store \p B has a lazy binding for region \p R.
1680///
1681/// If \p AllowSubregionBindings is \c false, a lazy binding will be rejected
1682/// if there are additional bindings within \p R.
1683///
1684/// Note that unlike RegionStoreManager::findLazyBinding, this will not search
1685/// for lazy bindings for super-regions of \p R.
1686static std::optional<nonloc::LazyCompoundVal>
1688 const SubRegion *R, bool AllowSubregionBindings) {
1689 std::optional<SVal> V = B.getDefaultBinding(R);
1690 if (!V)
1691 return std::nullopt;
1692
1693 std::optional<nonloc::LazyCompoundVal> LCV =
1694 V->getAs<nonloc::LazyCompoundVal>();
1695 if (!LCV)
1696 return std::nullopt;
1697
1698 // If the LCV is for a subregion, the types might not match, and we shouldn't
1699 // reuse the binding.
1700 QualType RegionTy = getUnderlyingType(R);
1701 if (!RegionTy.isNull() &&
1702 !RegionTy->isVoidPointerType()) {
1703 QualType SourceRegionTy = LCV->getRegion()->getValueType();
1704 if (!SVB.getContext().hasSameUnqualifiedType(RegionTy, SourceRegionTy))
1705 return std::nullopt;
1706 }
1707
1708 if (!AllowSubregionBindings) {
1709 // If there are any other bindings within this region, we shouldn't reuse
1710 // the top-level binding.
1712 collectSubRegionBindings(Bindings, SVB, *B.lookup(R->getBaseRegion()), R,
1713 /*IncludeAllDefaultBindings=*/true);
1714 if (Bindings.size() > 1)
1715 return std::nullopt;
1716 }
1717
1718 return *LCV;
1719}
1720
1721std::pair<Store, const SubRegion *>
1722RegionStoreManager::findLazyBinding(RegionBindingsConstRef B,
1723 const SubRegion *R,
1724 const SubRegion *originalRegion) {
1725 if (originalRegion != R) {
1726 if (std::optional<nonloc::LazyCompoundVal> V =
1727 getExistingLazyBinding(svalBuilder, B, R, true))
1728 return std::make_pair(V->getStore(), V->getRegion());
1729 }
1730
1731 typedef std::pair<Store, const SubRegion *> StoreRegionPair;
1732 StoreRegionPair Result = StoreRegionPair();
1733
1734 if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
1735 Result = findLazyBinding(B, cast<SubRegion>(ER->getSuperRegion()),
1736 originalRegion);
1737
1738 if (Result.second)
1739 Result.second = MRMgr.getElementRegionWithSuper(ER, Result.second);
1740
1741 } else if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
1742 Result = findLazyBinding(B, cast<SubRegion>(FR->getSuperRegion()),
1743 originalRegion);
1744
1745 if (Result.second)
1746 Result.second = MRMgr.getFieldRegionWithSuper(FR, Result.second);
1747
1748 } else if (const CXXBaseObjectRegion *BaseReg =
1749 dyn_cast<CXXBaseObjectRegion>(R)) {
1750 // C++ base object region is another kind of region that we should blast
1751 // through to look for lazy compound value. It is like a field region.
1752 Result = findLazyBinding(B, cast<SubRegion>(BaseReg->getSuperRegion()),
1753 originalRegion);
1754
1755 if (Result.second)
1756 Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
1757 Result.second);
1758 }
1759
1760 return Result;
1761}
1762
1763/// This is a helper function for `getConstantValFromConstArrayInitializer`.
1764///
1765/// Return an array of extents of the declared array type.
1766///
1767/// E.g. for `int x[1][2][3];` returns { 1, 2, 3 }.
1768static SmallVector<uint64_t, 2>
1770 assert(CAT && "ConstantArrayType should not be null");
1773 do {
1774 Extents.push_back(CAT->getZExtSize());
1775 } while ((CAT = dyn_cast<ConstantArrayType>(CAT->getElementType())));
1776 return Extents;
1777}
1778
1779/// This is a helper function for `getConstantValFromConstArrayInitializer`.
1780///
1781/// Return an array of offsets from nested ElementRegions and a root base
1782/// region. The array is never empty and a base region is never null.
1783///
1784/// E.g. for `Element{Element{Element{VarRegion},1},2},3}` returns { 3, 2, 1 }.
1785/// This represents an access through indirection: `arr[1][2][3];`
1786///
1787/// \param ER The given (possibly nested) ElementRegion.
1788///
1789/// \note The result array is in the reverse order of indirection expression:
1790/// arr[1][2][3] -> { 3, 2, 1 }. This helps to provide complexity O(n), where n
1791/// is a number of indirections. It may not affect performance in real-life
1792/// code, though.
1793static std::pair<SmallVector<SVal, 2>, const MemRegion *>
1795 assert(ER && "ConstantArrayType should not be null");
1796 const MemRegion *Base;
1797 SmallVector<SVal, 2> SValOffsets;
1798 do {
1799 SValOffsets.push_back(ER->getIndex());
1800 Base = ER->getSuperRegion();
1801 ER = dyn_cast<ElementRegion>(Base);
1802 } while (ER);
1803 return {SValOffsets, Base};
1804}
1805
1806/// This is a helper function for `getConstantValFromConstArrayInitializer`.
1807///
1808/// Convert array of offsets from `SVal` to `uint64_t` in consideration of
1809/// respective array extents.
1810/// \param SrcOffsets [in] The array of offsets of type `SVal` in reversed
1811/// order (expectedly received from `getElementRegionOffsetsWithBase`).
1812/// \param ArrayExtents [in] The array of extents.
1813/// \param DstOffsets [out] The array of offsets of type `uint64_t`.
1814/// \returns:
1815/// - `std::nullopt` for successful convertion.
1816/// - `UndefinedVal` or `UnknownVal` otherwise. It's expected that this SVal
1817/// will be returned as a suitable value of the access operation.
1818/// which should be returned as a correct
1819///
1820/// \example:
1821/// const int arr[10][20][30] = {}; // ArrayExtents { 10, 20, 30 }
1822/// int x1 = arr[4][5][6]; // SrcOffsets { NonLoc(6), NonLoc(5), NonLoc(4) }
1823/// // DstOffsets { 4, 5, 6 }
1824/// // returns std::nullopt
1825/// int x2 = arr[42][5][-6]; // returns UndefinedVal
1826/// int x3 = arr[4][5][x2]; // returns UnknownVal
1827static std::optional<SVal>
1829 const SmallVector<uint64_t, 2> ArrayExtents,
1830 SmallVector<uint64_t, 2> &DstOffsets) {
1831 // Check offsets for being out of bounds.
1832 // C++20 [expr.add] 7.6.6.4 (excerpt):
1833 // If P points to an array element i of an array object x with n
1834 // elements, where i < 0 or i > n, the behavior is undefined.
1835 // Dereferencing is not allowed on the "one past the last
1836 // element", when i == n.
1837 // Example:
1838 // const int arr[3][2] = {{1, 2}, {3, 4}};
1839 // arr[0][0]; // 1
1840 // arr[0][1]; // 2
1841 // arr[0][2]; // UB
1842 // arr[1][0]; // 3
1843 // arr[1][1]; // 4
1844 // arr[1][-1]; // UB
1845 // arr[2][0]; // 0
1846 // arr[2][1]; // 0
1847 // arr[-2][0]; // UB
1848 DstOffsets.resize(SrcOffsets.size());
1849 auto ExtentIt = ArrayExtents.begin();
1850 auto OffsetIt = DstOffsets.begin();
1851 // Reverse `SValOffsets` to make it consistent with `ArrayExtents`.
1852 for (SVal V : llvm::reverse(SrcOffsets)) {
1853 if (auto CI = V.getAs<nonloc::ConcreteInt>()) {
1854 // When offset is out of array's bounds, result is UB.
1855 const llvm::APSInt &Offset = CI->getValue();
1856 if (Offset.isNegative() || Offset.uge(*(ExtentIt++)))
1857 return UndefinedVal();
1858 // Store index in a reversive order.
1859 *(OffsetIt++) = Offset.getZExtValue();
1860 continue;
1861 }
1862 // Symbolic index presented. Return Unknown value.
1863 // FIXME: We also need to take ElementRegions with symbolic indexes into
1864 // account.
1865 return UnknownVal();
1866 }
1867 return std::nullopt;
1868}
1869
1870std::optional<SVal> RegionStoreManager::getConstantValFromConstArrayInitializer(
1871 RegionBindingsConstRef B, const ElementRegion *R) {
1872 assert(R && "ElementRegion should not be null");
1873
1874 // Treat an n-dimensional array.
1875 SmallVector<SVal, 2> SValOffsets;
1876 const MemRegion *Base;
1877 std::tie(SValOffsets, Base) = getElementRegionOffsetsWithBase(R);
1878 const VarRegion *VR = dyn_cast<VarRegion>(Base);
1879 if (!VR)
1880 return std::nullopt;
1881
1882 assert(!SValOffsets.empty() && "getElementRegionOffsets guarantees the "
1883 "offsets vector is not empty.");
1884
1885 // Check if the containing array has an initialized value that we can trust.
1886 // We can trust a const value or a value of a global initializer in main().
1887 const VarDecl *VD = VR->getDecl();
1888 if (!VD->getType().isConstQualified() &&
1889 !R->getElementType().isConstQualified() &&
1890 (!B.isMainAnalysis() || !VD->hasGlobalStorage()))
1891 return std::nullopt;
1892
1893 // Array's declaration should have `ConstantArrayType` type, because only this
1894 // type contains an array extent. It may happen that array type can be of
1895 // `IncompleteArrayType` type. To get the declaration of `ConstantArrayType`
1896 // type, we should find the declaration in the redeclarations chain that has
1897 // the initialization expression.
1898 // NOTE: `getAnyInitializer` has an out-parameter, which returns a new `VD`
1899 // from which an initializer is obtained. We replace current `VD` with the new
1900 // `VD`. If the return value of the function is null than `VD` won't be
1901 // replaced.
1902 const Expr *Init = VD->getAnyInitializer(VD);
1903 // NOTE: If `Init` is non-null, then a new `VD` is non-null for sure. So check
1904 // `Init` for null only and don't worry about the replaced `VD`.
1905 if (!Init)
1906 return std::nullopt;
1907
1908 // Array's declaration should have ConstantArrayType type, because only this
1909 // type contains an array extent.
1910 const ConstantArrayType *CAT = Ctx.getAsConstantArrayType(VD->getType());
1911 if (!CAT)
1912 return std::nullopt;
1913
1914 // Get array extents.
1915 SmallVector<uint64_t, 2> Extents = getConstantArrayExtents(CAT);
1916
1917 // The number of offsets should equal to the numbers of extents,
1918 // otherwise wrong type punning occurred. For instance:
1919 // int arr[1][2][3];
1920 // auto ptr = (int(*)[42])arr;
1921 // auto x = ptr[4][2]; // UB
1922 // FIXME: Should return UndefinedVal.
1923 if (SValOffsets.size() != Extents.size())
1924 return std::nullopt;
1925
1926 SmallVector<uint64_t, 2> ConcreteOffsets;
1927 if (std::optional<SVal> V = convertOffsetsFromSvalToUnsigneds(
1928 SValOffsets, Extents, ConcreteOffsets))
1929 return *V;
1930
1931 // Handle InitListExpr.
1932 // Example:
1933 // const char arr[4][2] = { { 1, 2 }, { 3 }, 4, 5 };
1934 if (const auto *ILE = dyn_cast<InitListExpr>(Init))
1935 return getSValFromInitListExpr(ILE, ConcreteOffsets, R->getElementType());
1936
1937 // Handle StringLiteral.
1938 // Example:
1939 // const char arr[] = "abc";
1940 if (const auto *SL = dyn_cast<StringLiteral>(Init))
1941 return getSValFromStringLiteral(SL, ConcreteOffsets.front(),
1942 R->getElementType());
1943
1944 // FIXME: Handle CompoundLiteralExpr.
1945
1946 return std::nullopt;
1947}
1948
1949/// Returns an SVal, if possible, for the specified position of an
1950/// initialization list.
1951///
1952/// \param ILE The given initialization list.
1953/// \param Offsets The array of unsigned offsets. E.g. for the expression
1954/// `int x = arr[1][2][3];` an array should be { 1, 2, 3 }.
1955/// \param ElemT The type of the result SVal expression.
1956/// \return Optional SVal for the particular position in the initialization
1957/// list. E.g. for the list `{{1, 2},[3, 4],{5, 6}, {}}` offsets:
1958/// - {1, 1} returns SVal{4}, because it's the second position in the second
1959/// sublist;
1960/// - {3, 0} returns SVal{0}, because there's no explicit value at this
1961/// position in the sublist.
1962///
1963/// NOTE: Inorder to get a valid SVal, a caller shall guarantee valid offsets
1964/// for the given initialization list. Otherwise SVal can be an equivalent to 0
1965/// or lead to assertion.
1966std::optional<SVal> RegionStoreManager::getSValFromInitListExpr(
1967 const InitListExpr *ILE, const SmallVector<uint64_t, 2> &Offsets,
1968 QualType ElemT) {
1969 assert(ILE && "InitListExpr should not be null");
1970
1971 for (uint64_t Offset : Offsets) {
1972 // C++20 [dcl.init.string] 9.4.2.1:
1973 // An array of ordinary character type [...] can be initialized by [...]
1974 // an appropriately-typed string-literal enclosed in braces.
1975 // Example:
1976 // const char arr[] = { "abc" };
1977 if (ILE->isStringLiteralInit())
1978 if (const auto *SL = dyn_cast<StringLiteral>(ILE->getInit(0)))
1979 return getSValFromStringLiteral(SL, Offset, ElemT);
1980
1981 // C++20 [expr.add] 9.4.17.5 (excerpt):
1982 // i-th array element is value-initialized for each k < i ≤ n,
1983 // where k is an expression-list size and n is an array extent.
1984 if (Offset >= ILE->getNumInits())
1985 return svalBuilder.makeZeroVal(ElemT);
1986
1987 const Expr *E = ILE->getInit(Offset);
1988 const auto *IL = dyn_cast<InitListExpr>(E);
1989 if (!IL)
1990 // Return a constant value, if it is presented.
1991 // FIXME: Support other SVals.
1992 return svalBuilder.getConstantVal(E);
1993
1994 // Go to the nested initializer list.
1995 ILE = IL;
1996 }
1997
1998 assert(ILE);
1999
2000 // FIXME: Unhandeled InitListExpr sub-expression, possibly constructing an
2001 // enum?
2002 return std::nullopt;
2003}
2004
2005/// Returns an SVal, if possible, for the specified position in a string
2006/// literal.
2007///
2008/// \param SL The given string literal.
2009/// \param Offset The unsigned offset. E.g. for the expression
2010/// `char x = str[42];` an offset should be 42.
2011/// E.g. for the string "abc" offset:
2012/// - 1 returns SVal{b}, because it's the second position in the string.
2013/// - 42 returns SVal{0}, because there's no explicit value at this
2014/// position in the string.
2015/// \param ElemT The type of the result SVal expression.
2016///
2017/// NOTE: We return `0` for every offset >= the literal length for array
2018/// declarations, like:
2019/// const char str[42] = "123"; // Literal length is 4.
2020/// char c = str[41]; // Offset is 41.
2021/// FIXME: Nevertheless, we can't do the same for pointer declaraions, like:
2022/// const char * const str = "123"; // Literal length is 4.
2023/// char c = str[41]; // Offset is 41. Returns `0`, but Undef
2024/// // expected.
2025/// It should be properly handled before reaching this point.
2026/// The main problem is that we can't distinguish between these declarations,
2027/// because in case of array we can get the Decl from VarRegion, but in case
2028/// of pointer the region is a StringRegion, which doesn't contain a Decl.
2029/// Possible solution could be passing an array extent along with the offset.
2030SVal RegionStoreManager::getSValFromStringLiteral(const StringLiteral *SL,
2031 uint64_t Offset,
2032 QualType ElemT) {
2033 assert(SL && "StringLiteral should not be null");
2034 // C++20 [dcl.init.string] 9.4.2.3:
2035 // If there are fewer initializers than there are array elements, each
2036 // element not explicitly initialized shall be zero-initialized [dcl.init].
2037 uint32_t Code = (Offset >= SL->getLength()) ? 0 : SL->getCodeUnit(Offset);
2038 return svalBuilder.makeIntVal(Code, ElemT);
2039}
2040
2041static std::optional<SVal> getDerivedSymbolForBinding(
2042 RegionBindingsConstRef B, const TypedValueRegion *BaseRegion,
2043 const TypedValueRegion *SubReg, const ASTContext &Ctx, SValBuilder &SVB) {
2044 assert(BaseRegion);
2045 QualType BaseTy = BaseRegion->getValueType();
2046 QualType Ty = SubReg->getValueType();
2047 if (BaseTy->isScalarType() && Ty->isScalarType()) {
2048 if (Ctx.getTypeSizeInChars(BaseTy) >= Ctx.getTypeSizeInChars(Ty)) {
2049 if (const std::optional<SVal> &ParentValue =
2050 B.getDirectBinding(BaseRegion)) {
2051 if (SymbolRef ParentValueAsSym = ParentValue->getAsSymbol())
2052 return SVB.getDerivedRegionValueSymbolVal(ParentValueAsSym, SubReg);
2053
2054 if (ParentValue->isUndef())
2055 return UndefinedVal();
2056
2057 // Other cases: give up. We are indexing into a larger object
2058 // that has some value, but we don't know how to handle that yet.
2059 return UnknownVal();
2060 }
2061 }
2062 }
2063 return std::nullopt;
2064}
2065
2066SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
2067 const ElementRegion* R) {
2068 // Check if the region has a binding.
2069 if (const std::optional<SVal> &V = B.getDirectBinding(R))
2070 return *V;
2071
2072 const MemRegion* superR = R->getSuperRegion();
2073
2074 // Check if the region is an element region of a string literal.
2075 if (const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
2076 // FIXME: Handle loads from strings where the literal is treated as
2077 // an integer, e.g., *((unsigned int*)"hello"). Such loads are UB according
2078 // to C++20 7.2.1.11 [basic.lval].
2079 QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType();
2080 if (!Ctx.hasSameUnqualifiedType(T, R->getElementType()))
2081 return UnknownVal();
2082 if (const auto CI = R->getIndex().getAs<nonloc::ConcreteInt>()) {
2083 const llvm::APSInt &Idx = CI->getValue();
2084 if (Idx < 0)
2085 return UndefinedVal();
2086 const StringLiteral *SL = StrR->getStringLiteral();
2087 return getSValFromStringLiteral(SL, Idx.getZExtValue(), T);
2088 }
2089 } else if (isa<ElementRegion, VarRegion>(superR)) {
2090 if (std::optional<SVal> V = getConstantValFromConstArrayInitializer(B, R))
2091 return *V;
2092 }
2093
2094 // Check for loads from a code text region. For such loads, just give up.
2095 if (isa<CodeTextRegion>(superR))
2096 return UnknownVal();
2097
2098 // Handle the case where we are indexing into a larger scalar object.
2099 // For example, this handles:
2100 // int x = ...
2101 // char *y = &x;
2102 // return *y;
2103 // FIXME: This is a hack, and doesn't do anything really intelligent yet.
2104 const RegionRawOffset &O = R->getAsArrayOffset();
2105
2106 // If we cannot reason about the offset, return an unknown value.
2107 if (!O.getRegion())
2108 return UnknownVal();
2109
2110 if (const TypedValueRegion *baseR = dyn_cast<TypedValueRegion>(O.getRegion()))
2111 if (auto V = getDerivedSymbolForBinding(B, baseR, R, Ctx, svalBuilder))
2112 return *V;
2113
2114 return getBindingForFieldOrElementCommon(B, R, R->getElementType());
2115}
2116
2117SVal RegionStoreManager::getBindingForField(RegionBindingsConstRef B,
2118 const FieldRegion* R) {
2119
2120 // Check if the region has a binding.
2121 if (const std::optional<SVal> &V = B.getDirectBinding(R))
2122 return *V;
2123
2124 // If the containing record was initialized, try to get its constant value.
2125 const FieldDecl *FD = R->getDecl();
2126 QualType Ty = FD->getType();
2127 const MemRegion* superR = R->getSuperRegion();
2128 if (const auto *VR = dyn_cast<VarRegion>(superR)) {
2129 const VarDecl *VD = VR->getDecl();
2130 QualType RecordVarTy = VD->getType();
2131 unsigned Index = FD->getFieldIndex();
2132 // Either the record variable or the field has an initializer that we can
2133 // trust. We trust initializers of constants and, additionally, respect
2134 // initializers of globals when analyzing main().
2135 if (RecordVarTy.isConstQualified() || Ty.isConstQualified() ||
2136 (B.isMainAnalysis() && VD->hasGlobalStorage()))
2137 if (const Expr *Init = VD->getAnyInitializer())
2138 if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
2139 if (Index < InitList->getNumInits()) {
2140 if (const Expr *FieldInit = InitList->getInit(Index))
2141 if (std::optional<SVal> V = svalBuilder.getConstantVal(FieldInit))
2142 return *V;
2143 } else {
2144 return svalBuilder.makeZeroVal(Ty);
2145 }
2146 }
2147 }
2148
2149 // Handle the case where we are accessing into a larger scalar object.
2150 // For example, this handles:
2151 // struct header {
2152 // unsigned a : 1;
2153 // unsigned b : 1;
2154 // };
2155 // struct parse_t {
2156 // unsigned bits0 : 1;
2157 // unsigned bits2 : 2; // <-- header
2158 // unsigned bits4 : 4;
2159 // };
2160 // int parse(parse_t *p) {
2161 // unsigned copy = p->bits2;
2162 // header *bits = (header *)&copy;
2163 // return bits->b; <-- here
2164 // }
2165 if (const auto *Base = dyn_cast<TypedValueRegion>(R->getBaseRegion()))
2166 if (auto V = getDerivedSymbolForBinding(B, Base, R, Ctx, svalBuilder))
2167 return *V;
2168
2169 return getBindingForFieldOrElementCommon(B, R, Ty);
2170}
2171
2172std::optional<SVal> RegionStoreManager::getBindingForDerivedDefaultValue(
2173 RegionBindingsConstRef B, const MemRegion *superR,
2174 const TypedValueRegion *R, QualType Ty) {
2175
2176 if (const std::optional<SVal> &D = B.getDefaultBinding(superR)) {
2177 SVal val = *D;
2178 if (SymbolRef parentSym = val.getAsSymbol())
2179 return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
2180
2181 if (val.isZeroConstant())
2182 return svalBuilder.makeZeroVal(Ty);
2183
2184 if (val.isUnknownOrUndef())
2185 return val;
2186
2187 // Lazy bindings are usually handled through getExistingLazyBinding().
2188 // We should unify these two code paths at some point.
2190 return val;
2191
2192 llvm_unreachable("Unknown default value");
2193 }
2194
2195 return std::nullopt;
2196}
2197
2198SVal RegionStoreManager::getLazyBinding(const SubRegion *LazyBindingRegion,
2199 RegionBindingsRef LazyBinding) {
2200 SVal Result;
2201 if (const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
2202 Result = getBindingForElement(LazyBinding, ER);
2203 else
2204 Result = getBindingForField(LazyBinding,
2205 cast<FieldRegion>(LazyBindingRegion));
2206
2207 // FIXME: This is a hack to deal with RegionStore's inability to distinguish a
2208 // default value for /part/ of an aggregate from a default value for the
2209 // /entire/ aggregate. The most common case of this is when struct Outer
2210 // has as its first member a struct Inner, which is copied in from a stack
2211 // variable. In this case, even if the Outer's default value is symbolic, 0,
2212 // or unknown, it gets overridden by the Inner's default value of undefined.
2213 //
2214 // This is a general problem -- if the Inner is zero-initialized, the Outer
2215 // will now look zero-initialized. The proper way to solve this is with a
2216 // new version of RegionStore that tracks the extent of a binding as well
2217 // as the offset.
2218 //
2219 // This hack only takes care of the undefined case because that can very
2220 // quickly result in a warning.
2221 if (Result.isUndef())
2222 Result = UnknownVal();
2223
2224 return Result;
2225}
2226
2227SVal
2228RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
2229 const TypedValueRegion *R,
2230 QualType Ty) {
2231
2232 // At this point we have already checked in either getBindingForElement or
2233 // getBindingForField if 'R' has a direct binding.
2234
2235 // Lazy binding?
2236 Store lazyBindingStore = nullptr;
2237 const SubRegion *lazyBindingRegion = nullptr;
2238 std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
2239 if (lazyBindingRegion)
2240 return getLazyBinding(lazyBindingRegion,
2241 getRegionBindings(lazyBindingStore));
2242
2243 // Record whether or not we see a symbolic index. That can completely
2244 // be out of scope of our lookup.
2245 bool hasSymbolicIndex = false;
2246
2247 // FIXME: This is a hack to deal with RegionStore's inability to distinguish a
2248 // default value for /part/ of an aggregate from a default value for the
2249 // /entire/ aggregate. The most common case of this is when struct Outer
2250 // has as its first member a struct Inner, which is copied in from a stack
2251 // variable. In this case, even if the Outer's default value is symbolic, 0,
2252 // or unknown, it gets overridden by the Inner's default value of undefined.
2253 //
2254 // This is a general problem -- if the Inner is zero-initialized, the Outer
2255 // will now look zero-initialized. The proper way to solve this is with a
2256 // new version of RegionStore that tracks the extent of a binding as well
2257 // as the offset.
2258 //
2259 // This hack only takes care of the undefined case because that can very
2260 // quickly result in a warning.
2261 bool hasPartialLazyBinding = false;
2262
2263 const SubRegion *SR = R;
2264 while (SR) {
2265 const MemRegion *Base = SR->getSuperRegion();
2266 if (std::optional<SVal> D =
2267 getBindingForDerivedDefaultValue(B, Base, R, Ty)) {
2268 if (D->getAs<nonloc::LazyCompoundVal>()) {
2269 hasPartialLazyBinding = true;
2270 break;
2271 }
2272
2273 return *D;
2274 }
2275
2276 if (const ElementRegion *ER = dyn_cast<ElementRegion>(Base)) {
2277 NonLoc index = ER->getIndex();
2278 if (!index.isConstant())
2279 hasSymbolicIndex = true;
2280 }
2281
2282 // If our super region is a field or element itself, walk up the region
2283 // hierarchy to see if there is a default value installed in an ancestor.
2284 SR = dyn_cast<SubRegion>(Base);
2285 }
2286
2287 if (isa<StackLocalsSpaceRegion>(R->getRawMemorySpace())) {
2288 if (isa<ElementRegion>(R)) {
2289 // Currently we don't reason specially about Clang-style vectors. Check
2290 // if superR is a vector and if so return Unknown.
2291 if (const TypedValueRegion *typedSuperR =
2292 dyn_cast<TypedValueRegion>(R->getSuperRegion())) {
2293 if (typedSuperR->getValueType()->isVectorType())
2294 return UnknownVal();
2295 }
2296 }
2297
2298 // FIXME: We also need to take ElementRegions with symbolic indexes into
2299 // account. This case handles both directly accessing an ElementRegion
2300 // with a symbolic offset, but also fields within an element with
2301 // a symbolic offset.
2302 if (hasSymbolicIndex)
2303 return UnknownVal();
2304
2305 // Additionally allow introspection of a block's internal layout.
2306 // Try to get direct binding if all other attempts failed thus far.
2307 // Else, return UndefinedVal()
2308 if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->getBaseRegion())) {
2309 if (const std::optional<SVal> &V = B.getDefaultBinding(R))
2310 return *V;
2311 return UndefinedVal();
2312 }
2313 }
2314
2315 // All other values are symbolic.
2316 return svalBuilder.getRegionValueSymbolVal(R);
2317}
2318
2319SVal RegionStoreManager::getBindingForObjCIvar(RegionBindingsConstRef B,
2320 const ObjCIvarRegion* R) {
2321 // Check if the region has a binding.
2322 if (const std::optional<SVal> &V = B.getDirectBinding(R))
2323 return *V;
2324
2325 const MemRegion *superR = R->getSuperRegion();
2326
2327 // Check if the super region has a default binding.
2328 if (const std::optional<SVal> &V = B.getDefaultBinding(superR)) {
2329 if (SymbolRef parentSym = V->getAsSymbol())
2330 return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
2331
2332 // Other cases: give up.
2333 return UnknownVal();
2334 }
2335
2336 return getBindingForLazySymbol(R);
2337}
2338
2339SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B,
2340 const VarRegion *R) {
2341
2342 // Check if the region has a binding.
2343 if (std::optional<SVal> V = B.getDirectBinding(R))
2344 return *V;
2345
2346 if (std::optional<SVal> V = B.getDefaultBinding(R))
2347 return *V;
2348
2349 // Lazily derive a value for the VarRegion.
2350 const VarDecl *VD = R->getDecl();
2351 const MemSpaceRegion *MS = R->getRawMemorySpace();
2352
2353 // Arguments are always symbolic.
2355 return svalBuilder.getRegionValueSymbolVal(R);
2356
2357 // Is 'VD' declared constant? If so, retrieve the constant value.
2358 if (VD->getType().isConstQualified()) {
2359 if (const Expr *Init = VD->getAnyInitializer()) {
2360 if (std::optional<SVal> V = svalBuilder.getConstantVal(Init))
2361 return *V;
2362
2363 // If the variable is const qualified and has an initializer but
2364 // we couldn't evaluate initializer to a value, treat the value as
2365 // unknown.
2366 return UnknownVal();
2367 }
2368 }
2369
2370 // This must come after the check for constants because closure-captured
2371 // constant variables may appear in UnknownSpaceRegion.
2373 return svalBuilder.getRegionValueSymbolVal(R);
2374
2375 if (isa<GlobalsSpaceRegion>(MS)) {
2376 QualType T = VD->getType();
2377
2378 // If we're in main(), then global initializers have not become stale yet.
2379 if (B.isMainAnalysis())
2380 if (const Expr *Init = VD->getAnyInitializer())
2381 if (std::optional<SVal> V = svalBuilder.getConstantVal(Init))
2382 return *V;
2383
2384 // Function-scoped static variables are default-initialized to 0; if they
2385 // have an initializer, it would have been processed by now.
2386 // FIXME: This is only true when we're starting analysis from main().
2387 // We're losing a lot of coverage here.
2389 return svalBuilder.makeZeroVal(T);
2390
2391 if (std::optional<SVal> V = getBindingForDerivedDefaultValue(B, MS, R, T)) {
2392 assert(!V->getAs<nonloc::LazyCompoundVal>());
2393 return *V;
2394 }
2395
2396 return svalBuilder.getRegionValueSymbolVal(R);
2397 }
2398
2399 return UndefinedVal();
2400}
2401
2402SVal RegionStoreManager::getBindingForLazySymbol(const TypedValueRegion *R) {
2403 // All other values are symbolic.
2404 return svalBuilder.getRegionValueSymbolVal(R);
2405}
2406
2407const RegionStoreManager::SValListTy &
2408RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
2409 // First, check the cache.
2410 LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.getCVData());
2411 if (I != LazyBindingsMap.end())
2412 return I->second;
2413
2414 // If we don't have a list of values cached, start constructing it.
2415 SValListTy List;
2416
2417 const SubRegion *LazyR = LCV.getRegion();
2418 RegionBindingsRef B = getRegionBindings(LCV.getStore());
2419
2420 // If this region had /no/ bindings at the time, there are no interesting
2421 // values to return.
2422 const ClusterBindings *Cluster = B.lookup(LazyR->getBaseRegion());
2423 if (!Cluster)
2424 return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
2425
2426 SmallVector<BindingPair, 32> Bindings;
2427 collectSubRegionBindings(Bindings, svalBuilder, *Cluster, LazyR,
2428 /*IncludeAllDefaultBindings=*/true);
2429 for (SVal V : llvm::make_second_range(Bindings)) {
2430 if (V.isUnknownOrUndef() || V.isConstant())
2431 continue;
2432
2433 if (auto InnerLCV = V.getAs<nonloc::LazyCompoundVal>()) {
2434 const SValListTy &InnerList = getInterestingValues(*InnerLCV);
2435 llvm::append_range(List, InnerList);
2436 }
2437
2438 List.push_back(V);
2439 }
2440
2441 return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
2442}
2443
2444NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B,
2445 const TypedValueRegion *R) {
2446 if (std::optional<nonloc::LazyCompoundVal> V =
2447 getExistingLazyBinding(svalBuilder, B, R, false))
2448 return *V;
2449
2450 return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R);
2451}
2452
2453SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B,
2454 const TypedValueRegion *R) {
2455 const RecordDecl *RD =
2456 R->getValueType()->castAsCanonical<RecordType>()->getDecl();
2457 if (!RD->getDefinition())
2458 return UnknownVal();
2459
2460 // We also create a LCV for copying empty structs because then the store
2461 // behavior doesn't depend on the struct layout.
2462 // This way even an empty struct can carry taint, no matter if creduce drops
2463 // the last field member or not.
2464 return createLazyBinding(B, R);
2465}
2466
2467SVal RegionStoreManager::getBindingForArray(RegionBindingsConstRef B,
2468 const TypedValueRegion *R) {
2469 assert(Ctx.getAsConstantArrayType(R->getValueType()) &&
2470 "Only constant array types can have compound bindings.");
2471
2472 return createLazyBinding(B, R);
2473}
2474
2475bool RegionStoreManager::includedInBindings(Store store,
2476 const MemRegion *region) const {
2477 RegionBindingsRef B = getRegionBindings(store);
2478 region = region->getBaseRegion();
2479
2480 // Quick path: if the base is the head of a cluster, the region is live.
2481 if (B.lookup(region))
2482 return true;
2483
2484 // Slow path: if the region is the VALUE of any binding, it is live.
2485 for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
2486 const ClusterBindings &Cluster = RI.getData();
2487 for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
2488 CI != CE; ++CI) {
2489 SVal D = CI.getData();
2490 if (const MemRegion *R = D.getAsRegion())
2491 if (R->getBaseRegion() == region)
2492 return true;
2493 }
2494 }
2495
2496 return false;
2497}
2498
2499//===----------------------------------------------------------------------===//
2500// Binding values to regions.
2501//===----------------------------------------------------------------------===//
2502
2503StoreRef RegionStoreManager::killBinding(Store ST, Loc L) {
2504 if (std::optional<loc::MemRegionVal> LV = L.getAs<loc::MemRegionVal>())
2505 if (const MemRegion* R = LV->getRegion())
2506 return StoreRef(getRegionBindings(ST)
2507 .removeBinding(R)
2508 .asImmutableMap()
2509 .getRootWithoutRetain(),
2510 *this);
2511
2512 return StoreRef(ST, *this);
2513}
2514
2515LimitedRegionBindingsRef
2516RegionStoreManager::bind(LimitedRegionBindingsConstRef B, Loc L, SVal V) {
2517 llvm::TimeTraceScope TimeScope("RegionStoreManager::bind",
2518 [&L]() { return locDescr(L); });
2519
2521 return B.withValuesEscaped(V);
2522
2523 // We only care about region locations.
2524 auto MemRegVal = L.getAs<loc::MemRegionVal>();
2525 if (!MemRegVal)
2526 return B;
2527
2528 const MemRegion *R = MemRegVal->getRegion();
2529
2530 // Binding directly to a symbolic region should be treated as binding
2531 // to element 0.
2532 if (const auto *SymReg = dyn_cast<SymbolicRegion>(R)) {
2533 QualType Ty = SymReg->getPointeeStaticType();
2534 if (Ty->isVoidType())
2535 Ty = StateMgr.getContext().CharTy;
2536 R = GetElementZeroRegion(SymReg, Ty);
2537 }
2538
2539 // Check if the region is a struct region.
2540 if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
2541 QualType Ty = TR->getValueType();
2542 if (Ty->isArrayType())
2543 return bindArray(B, TR, V);
2544 if (Ty->isStructureOrClassType())
2545 return bindStruct(B, TR, V);
2546 if (Ty->isVectorType())
2547 return bindVector(B, TR, V);
2548 if (Ty->isUnionType())
2549 return bindAggregate(B, TR, V);
2550 }
2551
2552 assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) &&
2553 "'this' pointer is not an l-value and is not assignable");
2554
2555 // Clear out bindings that may overlap with this binding.
2556 auto NewB = removeSubRegionBindings(B, cast<SubRegion>(R));
2557
2558 // LazyCompoundVals should be always bound as 'default' bindings.
2559 auto KeyKind = isa<nonloc::LazyCompoundVal>(V) ? BindingKey::Default
2560 : BindingKey::Direct;
2561 return NewB.addBinding(BindingKey::Make(R, KeyKind), V);
2562}
2563
2564LimitedRegionBindingsRef
2565RegionStoreManager::setImplicitDefaultValue(LimitedRegionBindingsConstRef B,
2566 const MemRegion *R, QualType T) {
2568 return B;
2569
2570 // Preserve an existing aggregate default binding. This handles partially
2571 // initialized union-containing aggregates where bindAggregate() may already
2572 // have installed a more precise default value at offset 0. Still allow
2573 // implicit defaults for scalars and pointers so regular zero-initialization
2574 // continues to work, e.g. for `new int[10]{}`.
2575 if (T->isAggregateType() && B.getDefaultBinding(R).has_value()) {
2576 return B;
2577 }
2578
2579 SVal V;
2580
2581 if (Loc::isLocType(T))
2582 V = svalBuilder.makeNullWithType(T);
2583 else if (T->isIntegralOrEnumerationType())
2584 V = svalBuilder.makeZeroVal(T);
2585 else if (T->isStructureOrClassType() || T->isArrayType()) {
2586 // Set the default value to a zero constant when it is a structure
2587 // or array. The type doesn't really matter.
2588 V = svalBuilder.makeZeroVal(Ctx.IntTy);
2589 }
2590 else {
2591 // We can't represent values of this type, but we still need to set a value
2592 // to record that the region has been initialized.
2593 // If this assertion ever fires, a new case should be added above -- we
2594 // should know how to default-initialize any value we can symbolicate.
2595 assert(!SymbolManager::canSymbolicate(T) && "This type is representable");
2596 V = UnknownVal();
2597 }
2598
2599 return B.addBinding(R, BindingKey::Default, V);
2600}
2601
2602std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallArray(
2603 LimitedRegionBindingsConstRef B, const TypedValueRegion *R,
2604 const ArrayType *AT, nonloc::LazyCompoundVal LCV) {
2606 return B.withValuesEscaped(LCV);
2607
2608 auto CAT = dyn_cast<ConstantArrayType>(AT);
2609
2610 // If we don't know the size, create a lazyCompoundVal instead.
2611 if (!CAT)
2612 return std::nullopt;
2613
2614 QualType Ty = CAT->getElementType();
2615 if (!(Ty->isScalarType() || Ty->isReferenceType()))
2616 return std::nullopt;
2617
2618 // If the array is too big, create a LCV instead.
2619 uint64_t ArrSize = CAT->getLimitedSize();
2620 if (ArrSize > SmallArrayLimit)
2621 return std::nullopt;
2622
2623 LimitedRegionBindingsRef NewB = B;
2624
2625 for (uint64_t i = 0; i < ArrSize; ++i) {
2626 auto Idx = svalBuilder.makeArrayIndex(i);
2627 const ElementRegion *SrcER =
2628 MRMgr.getElementRegion(Ty, Idx, LCV.getRegion(), Ctx);
2629 SVal V = getBindingForElement(getRegionBindings(LCV.getStore()), SrcER);
2630
2631 const ElementRegion *DstER = MRMgr.getElementRegion(Ty, Idx, R, Ctx);
2632 NewB = bind(NewB, loc::MemRegionVal(DstER), V);
2633 }
2634
2635 return NewB;
2636}
2637
2638LimitedRegionBindingsRef
2639RegionStoreManager::bindArray(LimitedRegionBindingsConstRef B,
2640 const TypedValueRegion *R, SVal Init) {
2641 llvm::TimeTraceScope TimeScope("RegionStoreManager::bindArray",
2642 [R]() { return R->getDescriptiveName(); });
2644 return B.withValuesEscaped(Init);
2645
2646 const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
2647 QualType ElementTy = AT->getElementType();
2648 std::optional<uint64_t> Size;
2649
2650 if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
2651 Size = CAT->getZExtSize();
2652
2653 // Check if the init expr is a literal. If so, bind the rvalue instead.
2654 // FIXME: It's not responsibility of the Store to transform this lvalue
2655 // to rvalue. ExprEngine or maybe even CFG should do this before binding.
2656 if (std::optional<loc::MemRegionVal> MRV = Init.getAs<loc::MemRegionVal>()) {
2657 SVal V = getBinding(B.asStore(), *MRV, R->getValueType());
2658 return bindAggregate(B, R, V);
2659 }
2660
2661 // FIXME Single value constant should have been handled before this call to
2662 // bindArray. This is only a hotfix to not crash.
2663 if (Init.isConstant())
2664 return bindAggregate(B, R, Init);
2665
2666 if (std::optional LCV = Init.getAs<nonloc::LazyCompoundVal>()) {
2667 if (std::optional NewB = tryBindSmallArray(B, R, AT, *LCV))
2668 return *NewB;
2669 return bindAggregate(B, R, Init);
2670 }
2671
2673 return bindAggregate(B, R, Init);
2674
2675 // Remaining case: explicit compound values.
2676 const nonloc::CompoundVal& CV = Init.castAs<nonloc::CompoundVal>();
2677 nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
2678 uint64_t i = 0;
2679
2680 LimitedRegionBindingsRef NewB = B;
2681
2682 for (; Size ? i < *Size : true; ++i, ++VI) {
2683 // The init list might be shorter than the array length.
2684 if (VI == VE)
2685 break;
2686 if (NewB.hasExhaustedBindingLimit())
2687 return NewB.withValuesEscaped(VI, VE);
2688
2689 NonLoc Idx = svalBuilder.makeArrayIndex(i);
2690 const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
2691
2692 if (ElementTy->isStructureOrClassType())
2693 NewB = bindStruct(NewB, ER, *VI);
2694 else if (ElementTy->isArrayType())
2695 NewB = bindArray(NewB, ER, *VI);
2696 else
2697 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
2698 }
2699
2700 // If the init list is shorter than the array length (or the array has
2701 // variable length), set the array default value. Values that are already set
2702 // are not overwritten.
2703 if (!Size || i < *Size)
2704 NewB = setImplicitDefaultValue(NewB, R, ElementTy);
2705
2706 return NewB;
2707}
2708
2709LimitedRegionBindingsRef
2710RegionStoreManager::bindVector(LimitedRegionBindingsConstRef B,
2711 const TypedValueRegion *R, SVal V) {
2712 llvm::TimeTraceScope TimeScope("RegionStoreManager::bindVector",
2713 [R]() { return R->getDescriptiveName(); });
2715 return B.withValuesEscaped(V);
2716
2717 QualType T = R->getValueType();
2718 const VectorType *VT = T->castAs<VectorType>(); // Use castAs for typedefs.
2719
2720 // Handle lazy compound values and symbolic values.
2722 return bindAggregate(B, R, V);
2723
2724 // We may get non-CompoundVal accidentally due to imprecise cast logic or
2725 // that we are binding symbolic struct value. Kill the field values, and if
2726 // the value is symbolic go and bind it as a "default" binding.
2728 return bindAggregate(B, R, UnknownVal());
2729 }
2730
2731 QualType ElemType = VT->getElementType();
2732 nonloc::CompoundVal CV = V.castAs<nonloc::CompoundVal>();
2733 nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
2734 unsigned index = 0, numElements = VT->getNumElements();
2735 LimitedRegionBindingsRef NewB = B;
2736
2737 for ( ; index != numElements ; ++index) {
2738 if (VI == VE)
2739 break;
2740
2741 if (NewB.hasExhaustedBindingLimit())
2742 return NewB.withValuesEscaped(VI, VE);
2743
2744 NonLoc Idx = svalBuilder.makeArrayIndex(index);
2745 const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
2746
2747 if (ElemType->isArrayType())
2748 NewB = bindArray(NewB, ER, *VI);
2749 else if (ElemType->isStructureOrClassType())
2750 NewB = bindStruct(NewB, ER, *VI);
2751 else
2752 NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
2753 }
2754 return NewB;
2755}
2756
2757std::optional<LimitedRegionBindingsRef> RegionStoreManager::tryBindSmallStruct(
2758 LimitedRegionBindingsConstRef B, const TypedValueRegion *R,
2759 const RecordDecl *RD, nonloc::LazyCompoundVal LCV) {
2761 return B.withValuesEscaped(LCV);
2762
2763 FieldVector Fields;
2764
2765 if (const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD))
2766 if (Class->getNumBases() != 0 || Class->getNumVBases() != 0)
2767 return std::nullopt;
2768
2769 for (const auto *FD : RD->fields()) {
2770 if (FD->isUnnamedBitField())
2771 continue;
2772
2773 // If there are too many fields, or if any of the fields are aggregates,
2774 // just use the LCV as a default binding.
2775 if (Fields.size() == SmallStructLimit)
2776 return std::nullopt;
2777
2778 QualType Ty = FD->getType();
2779
2780 // Zero length arrays are basically no-ops, so we also ignore them here.
2781 if (Ty->isConstantArrayType() &&
2783 continue;
2784
2785 if (!(Ty->isScalarType() || Ty->isReferenceType()))
2786 return std::nullopt;
2787
2788 Fields.push_back(FD);
2789 }
2790
2791 LimitedRegionBindingsRef NewB = B;
2792
2793 for (const FieldDecl *Field : Fields) {
2794 const FieldRegion *SourceFR = MRMgr.getFieldRegion(Field, LCV.getRegion());
2795 SVal V = getBindingForField(getRegionBindings(LCV.getStore()), SourceFR);
2796
2797 const FieldRegion *DestFR = MRMgr.getFieldRegion(Field, R);
2798 NewB = bind(NewB, loc::MemRegionVal(DestFR), V);
2799 }
2800
2801 return NewB;
2802}
2803
2804LimitedRegionBindingsRef
2805RegionStoreManager::bindStruct(LimitedRegionBindingsConstRef B,
2806 const TypedValueRegion *R, SVal V) {
2807 llvm::TimeTraceScope TimeScope("RegionStoreManager::bindStruct",
2808 [R]() { return R->getDescriptiveName(); });
2810 return B.withValuesEscaped(V);
2811
2812 QualType T = R->getValueType();
2813 assert(T->isStructureOrClassType());
2814
2815 const auto *RD = T->castAsRecordDecl();
2816 if (!RD->isCompleteDefinition())
2817 return B;
2818
2819 // Handle lazy compound values and symbolic values.
2820 if (std::optional<nonloc::LazyCompoundVal> LCV =
2821 V.getAs<nonloc::LazyCompoundVal>()) {
2822 if (std::optional NewB = tryBindSmallStruct(B, R, RD, *LCV))
2823 return *NewB;
2824 return bindAggregate(B, R, V);
2825 }
2827 return bindAggregate(B, R, V);
2828
2829 // We may get non-CompoundVal accidentally due to imprecise cast logic or
2830 // that we are binding symbolic struct value. Kill the field values, and if
2831 // the value is symbolic go and bind it as a "default" binding.
2832 if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
2833 return bindAggregate(B, R, UnknownVal());
2834
2835 // The raw CompoundVal is essentially a symbolic InitListExpr: an (immutable)
2836 // list of other values. It appears pretty much only when there's an actual
2837 // initializer list expression in the program, and the analyzer tries to
2838 // unwrap it as soon as possible.
2839 // This code is where such unwrap happens: when the compound value is put into
2840 // the object that it was supposed to initialize (it's an *initializer* list,
2841 // after all), instead of binding the whole value to the whole object, we bind
2842 // sub-values to sub-objects. Sub-values may themselves be compound values,
2843 // and in this case the procedure becomes recursive.
2844 // FIXME: The annoying part about compound values is that they don't carry
2845 // any sort of information about which value corresponds to which sub-object.
2846 // It's simply a list of values in the middle of nowhere; we expect to match
2847 // them to sub-objects, essentially, "by index": first value binds to
2848 // the first field, second value binds to the second field, etc.
2849 // It would have been much safer to organize non-lazy compound values as
2850 // a mapping from fields/bases to values.
2851 const nonloc::CompoundVal& CV = V.castAs<nonloc::CompoundVal>();
2852 nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
2853
2854 LimitedRegionBindingsRef NewB = B;
2855
2856 // In C++17 aggregates may have base classes, handle those as well.
2857 // They appear before fields in the initializer list / compound value.
2858 if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
2859 // If the object was constructed with a constructor, its value is a
2860 // LazyCompoundVal. If it's a raw CompoundVal, it means that we're
2861 // performing aggregate initialization. The only exception from this
2862 // rule is sending an Objective-C++ message that returns a C++ object
2863 // to a nil receiver; in this case the semantics is to return a
2864 // zero-initialized object even if it's a C++ object that doesn't have
2865 // this sort of constructor; the CompoundVal is empty in this case.
2866 assert((CRD->isAggregate() || (Ctx.getLangOpts().ObjC && VI == VE)) &&
2867 "Non-aggregates are constructed with a constructor!");
2868
2869 for (const auto &B : CRD->bases()) {
2870 // (Multiple inheritance is fine though.)
2871 assert(!B.isVirtual() && "Aggregates cannot have virtual base classes!");
2872
2873 if (VI == VE)
2874 break;
2875 if (NewB.hasExhaustedBindingLimit())
2876 return NewB.withValuesEscaped(VI, VE);
2877
2878 QualType BTy = B.getType();
2879 assert(BTy->isStructureOrClassType() && "Base classes must be classes!");
2880
2881 const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl();
2882 assert(BRD && "Base classes must be C++ classes!");
2883
2884 const CXXBaseObjectRegion *BR =
2885 MRMgr.getCXXBaseObjectRegion(BRD, R, /*IsVirtual=*/false);
2886
2887 NewB = bindStruct(NewB, BR, *VI);
2888
2889 ++VI;
2890 }
2891 }
2892
2894
2895 for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) {
2896
2897 if (VI == VE)
2898 break;
2899
2900 if (NewB.hasExhaustedBindingLimit())
2901 return NewB.withValuesEscaped(VI, VE);
2902
2903 // Skip any unnamed bitfields to stay in sync with the initializers.
2904 if (FI->isUnnamedBitField())
2905 continue;
2906
2907 QualType FTy = FI->getType();
2908 const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
2909
2910 if (FTy->isArrayType())
2911 NewB = bindArray(NewB, FR, *VI);
2912 else if (FTy->isStructureOrClassType())
2913 NewB = bindStruct(NewB, FR, *VI);
2914 else
2915 NewB = bind(NewB, loc::MemRegionVal(FR), *VI);
2916 ++VI;
2917 }
2918
2919 if (NewB.hasExhaustedBindingLimit())
2920 return NewB.withValuesEscaped(VI, VE);
2921
2922 // There may be fewer values in the initialize list than the fields of struct.
2923 if (FI != FE) {
2924 NewB = NewB.addBinding(R, BindingKey::Default,
2925 svalBuilder.makeIntVal(0, false));
2926 }
2927
2928 return NewB;
2929}
2930
2931LimitedRegionBindingsRef
2932RegionStoreManager::bindAggregate(LimitedRegionBindingsConstRef B,
2933 const TypedRegion *R, SVal Val) {
2934 llvm::TimeTraceScope TimeScope("RegionStoreManager::bindAggregate",
2935 [R]() { return R->getDescriptiveName(); });
2937 return B.withValuesEscaped(Val);
2938
2939 // Remove the old bindings, using 'R' as the root of all regions
2940 // we will invalidate. Then add the new binding.
2941 return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val);
2942}
2943
2944//===----------------------------------------------------------------------===//
2945// State pruning.
2946//===----------------------------------------------------------------------===//
2947
2948namespace {
2949class RemoveDeadBindingsWorker
2950 : public ClusterAnalysis<RemoveDeadBindingsWorker> {
2951 SmallVector<const SymbolicRegion *, 12> Postponed;
2952 SymbolReaper &SymReaper;
2953 const StackFrame *CurrentSF;
2954
2955public:
2956 RemoveDeadBindingsWorker(RegionStoreManager &rm,
2957 ProgramStateManager &stateMgr, RegionBindingsRef b,
2958 SymbolReaper &symReaper, const StackFrame *SF)
2959 : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr, b),
2960 SymReaper(symReaper), CurrentSF(SF) {}
2961
2962 // Called by ClusterAnalysis.
2963 void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C);
2964 void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);
2965 using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
2966
2967 using ClusterAnalysis::AddToWorkList;
2968
2969 bool AddToWorkList(const MemRegion *R);
2970
2971 bool UpdatePostponed();
2972 void VisitBinding(SVal V);
2973};
2974}
2975
2976bool RemoveDeadBindingsWorker::AddToWorkList(const MemRegion *R) {
2977 const MemRegion *BaseR = R->getBaseRegion();
2978 return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
2979}
2980
2981void RemoveDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
2982 const ClusterBindings &C) {
2983
2984 if (const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
2985 if (SymReaper.isLive(VR))
2986 AddToWorkList(baseR, &C);
2987
2988 return;
2989 }
2990
2991 if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
2992 if (SymReaper.isLive(SR->getSymbol()))
2993 AddToWorkList(SR, &C);
2994 else
2995 Postponed.push_back(SR);
2996
2997 return;
2998 }
2999
3001 AddToWorkList(baseR, &C);
3002 return;
3003 }
3004
3005 // CXXThisRegion in the current or parent stack frame is live.
3006 if (const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
3007 const auto *StackReg =
3009 const StackFrame *RegSF = StackReg->getStackFrame();
3010 if (CurrentSF && (RegSF == CurrentSF || RegSF->isParentOf(CurrentSF)))
3011 AddToWorkList(TR, &C);
3012 }
3013}
3014
3015void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
3016 const ClusterBindings *C) {
3017 if (!C)
3018 return;
3019
3020 // Mark the symbol for any SymbolicRegion with live bindings as live itself.
3021 // This means we should continue to track that symbol.
3022 if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
3023 SymReaper.markLive(SymR->getSymbol());
3024
3025 for (const auto &[Key, Val] : *C) {
3026 // Element index of a binding key is live.
3027 SymReaper.markElementIndicesLive(Key.getRegion());
3028
3029 VisitBinding(Val);
3030 }
3031}
3032
3033void RemoveDeadBindingsWorker::VisitBinding(SVal V) {
3034 // Is it a LazyCompoundVal? All referenced regions are live as well.
3035 // The LazyCompoundVal itself is not live but should be readable.
3036 if (auto LCS = V.getAs<nonloc::LazyCompoundVal>()) {
3037 SymReaper.markLazilyCopied(LCS->getRegion());
3038
3039 for (SVal V : RM.getInterestingValues(*LCS)) {
3040 if (auto DepLCS = V.getAs<nonloc::LazyCompoundVal>())
3041 SymReaper.markLazilyCopied(DepLCS->getRegion());
3042 else
3043 VisitBinding(V);
3044 }
3045
3046 return;
3047 }
3048
3049 // If V is a region, then add it to the worklist.
3050 if (const MemRegion *R = V.getAsRegion()) {
3051 AddToWorkList(R);
3052 SymReaper.markLive(R);
3053
3054 // All regions captured by a block are also live.
3055 if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
3056 for (auto Var : BR->referenced_vars())
3057 AddToWorkList(Var.getCapturedRegion());
3058 }
3059 }
3060
3061
3062 // Update the set of live symbols.
3063 for (SymbolRef Sym : V.symbols())
3064 SymReaper.markLive(Sym);
3065}
3066
3067bool RemoveDeadBindingsWorker::UpdatePostponed() {
3068 // See if any postponed SymbolicRegions are actually live now, after
3069 // having done a scan.
3070 bool Changed = false;
3071
3072 for (const SymbolicRegion *SR : Postponed) {
3073 if (SymReaper.isLive(SR->getSymbol())) {
3074 Changed |= AddToWorkList(SR);
3075 SR = nullptr;
3076 }
3077 }
3078
3079 return Changed;
3080}
3081
3082StoreRef RegionStoreManager::removeDeadBindings(Store store,
3083 const StackFrame *SF,
3084 SymbolReaper &SymReaper) {
3085 RegionBindingsRef B = getRegionBindings(store);
3086 RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, SF);
3087 W.GenerateClusters();
3088
3089 // Enqueue the region roots onto the worklist.
3090 for (const MemRegion *Reg : SymReaper.regions()) {
3091 W.AddToWorkList(Reg);
3092 }
3093
3094 do W.RunWorkList(); while (W.UpdatePostponed());
3095
3096 // We have now scanned the store, marking reachable regions and symbols
3097 // as live. We now remove all the regions that are dead from the store
3098 // as well as update DSymbols with the set symbols that are now dead.
3099 for (const MemRegion *Base : llvm::make_first_range(B)) {
3100 // If the cluster has been visited, we know the region has been marked.
3101 // Otherwise, remove the dead entry.
3102 if (!W.isVisited(Base))
3103 B = B.removeCluster(Base);
3104 }
3105
3106 return StoreRef(B.asStore(), *this);
3107}
3108
3109//===----------------------------------------------------------------------===//
3110// Utility methods.
3111//===----------------------------------------------------------------------===//
3112
3113void RegionStoreManager::printJson(raw_ostream &Out, Store S, const char *NL,
3114 unsigned int Space, bool IsDot) const {
3115 RegionBindingsRef Bindings = getRegionBindings(S);
3116
3117 Indent(Out, Space, IsDot) << "\"store\": ";
3118
3119 if (Bindings.isEmpty()) {
3120 Out << "null," << NL;
3121 return;
3122 }
3123
3124 Out << "{ \"pointer\": \"" << Bindings.asStore() << "\", \"items\": [" << NL;
3125 Bindings.printJson(Out, NL, Space + 1, IsDot);
3126 Indent(Out, Space, IsDot) << "]}," << NL;
3127}
#define V(N, I)
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
Result
Implement __builtin_bit_cast and related operations.
#define X(type, name)
Definition Value.h:97
llvm::json::Array Array
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)
const LimitedRegionBindingsRef & LimitedRegionBindingsConstRef
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
__device__ __2f16 b
__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 ...
LimitedRegionBindingsRef removeCluster(const MemRegion *BaseRegion) const
LimitedRegionBindingsRef withValuesEscaped(nonloc::CompoundVal::iterator Begin, nonloc::CompoundVal::iterator End) const
LimitedRegionBindingsRef withValuesEscaped(SVal V) const
LimitedRegionBindingsRef(RegionBindingsRef Base, SmallVectorImpl< SVal > &EscapedValuesDuringBind, std::optional< unsigned > BindingsLeft)
bool hasExhaustedBindingLimit() const
LimitedRegionBindingsRef addBinding(BindingKey K, SVal V) const
LimitedRegionBindingsRef addBinding(const MemRegion *R, BindingKey::Kind k, SVal V) const
LimitedRegionBindingsRef addWithoutDecreasingLimit(const MemRegion *BaseRegion, data_type_ref BindingKeyAndValue) const
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:229
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
Definition ASTContext.h:961
CanQualType IntTy
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
Definition TypeBase.h:3796
Represents the canonical version of C arrays with a specified constant size.
Definition TypeBase.h:3822
uint64_t getLimitedSize() const
Return the size zero-extended to uint64_t or UINT64_MAX if the value is larger than UINT64_MAX.
Definition TypeBase.h:3911
uint64_t getZExtSize() const
Return the size zero-extended as a uint64_t.
Definition TypeBase.h:3898
bool hasAttr() const
Definition DeclBase.h:585
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3267
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3418
bool isUnnamedBitField() const
Determines whether this is an unnamed bitfield.
Definition Decl.h:3288
bool isStringLiteralInit() const
Is this an initializer for an array of characters, initialized by a string literal or an @encode?
Definition Expr.cpp:2455
unsigned getNumInits() const
Definition Expr.h:5335
const Expr * getInit(unsigned Init) const
Definition Expr.h:5357
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8518
field_iterator field_end() const
Definition Decl.h:4553
field_range fields() const
Definition Decl.h:4550
RecordDecl * getDefinition() const
Returns the RecordDecl that actually defines this struct/union/class.
Definition Decl.h:4531
specific_decl_iterator< FieldDecl > field_iterator
Definition Decl.h:4547
field_iterator field_begin() const
Definition Decl.cpp:5269
bool isParentOf(const StackFrame *SF) const
const Decl * getDecl() const
unsigned getLength() const
Definition Expr.h:1912
uint32_t getCodeUnit(size_t i) const
Definition Expr.h:1885
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3840
bool isUnion() const
Definition Decl.h:3950
bool isVoidType() const
Definition TypeBase.h:9048
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isConstantArrayType() const
Definition TypeBase.h:8785
bool isVoidPointerType() const
Definition Type.cpp:749
bool isArrayType() const
Definition TypeBase.h:8781
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9342
bool isReferenceType() const
Definition TypeBase.h:8706
bool isScalarType() const
Definition TypeBase.h:9154
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
Definition TypeBase.h:9170
bool isAggregateType() const
Determines whether the type is a C++ aggregate type or C aggregate or union type.
Definition Type.cpp:2503
RecordDecl * castAsRecordDecl() const
Definition Type.h:48
bool isAnyComplexType() const
Definition TypeBase.h:8817
QualType getCanonicalTypeInternal() const
Definition TypeBase.h:3181
bool isStructureOrClassType() const
Definition Type.cpp:743
bool isVectorType() const
Definition TypeBase.h:8821
bool isRecordType() const
Definition TypeBase.h:8809
bool isUnionType() const
Definition Type.cpp:755
QualType getType() const
Definition Decl.h:723
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1239
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1182
const Expr * getAnyInitializer() const
Get the initializer for this variable, no matter which declaration it is attached to.
Definition Decl.h:1371
unsigned getNumElements() const
Definition TypeBase.h:4252
QualType getElementType() const
Definition TypeBase.h:4251
ElementRegion is used to represent both array elements and casts.
Definition MemRegion.h:1230
LLVM_ATTRIBUTE_RETURNS_NONNULL const FieldDecl * getDecl() const override
Definition MemRegion.h:1156
void dumpToStream(raw_ostream &Out) const
Definition SVals.cpp:379
static bool isLocType(QualType T)
Definition SVals.h:262
DefinedOrUnknownSVal getStaticSize(const MemRegion *MR, SValBuilder &SVB) const
MemRegion - The root abstract class for all memory regions.
Definition MemRegion.h:97
virtual bool isBoundable() const
Definition MemRegion.h:210
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
@ TK_PreserveContents
Tells that a region's contents is not changed.
Definition MemRegion.h:1671
@ TK_EntireMemSpace
When applied to a MemSpaceRegion, indicates the entire memory space should be invalidated.
Definition MemRegion.h:1681
bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const
bool hasSymbolicOffset() const
Definition MemRegion.h:82
const MemRegion * getRegion() const
It might return null.
Definition MemRegion.h:80
int64_t getOffset() const
Definition MemRegion.h:84
const MemRegion * getRegion() const
Definition MemRegion.h:1223
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 getRegionValueSymbolVal(const TypedValueRegion *region)
Make a unique symbol for value of region.
NonLoc makeLazyCompoundVal(const StoreRef &store, const TypedValueRegion *region)
DefinedOrUnknownSVal conjureSymbolVal(const void *symbolTag, ConstCFGElementRef elem, const StackFrame *SF, unsigned count)
Create a new symbol with a unique 'name'.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition SVals.h:56
bool isZeroConstant() const
Definition SVals.cpp:257
bool isUnknownOrUndef() const
Definition SVals.h:109
SymbolRef getAsSymbol(bool IncludeBaseRegions=false) const
If this SVal wraps a symbol return that SymbolRef.
Definition SVals.cpp:103
bool isConstant() const
Definition SVals.cpp:245
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
Definition SVals.h:87
const MemRegion * getAsRegion() const
Definition SVals.cpp:119
T castAs() const
Convert to the specified SVal type, asserting that this SVal is of the desired type.
Definition SVals.h:83
bool scan(nonloc::LazyCompoundVal val)
SmallVector< const MemRegion *, 8 > InvalidatedRegions
Definition Store.h:210
SubRegion - A region that subsets another larger region.
Definition MemRegion.h:473
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
Definition MemRegion.h:486
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
Definition SymExpr.h:107
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.
Definition MemRegion.h:806
TypedValueRegion - An abstract class representing regions having a typed value.
Definition MemRegion.h:562
virtual QualType getValueType() const =0
QualType getLocationType() const override
Definition MemRegion.h:573
QualType getValueType() const override
Definition MemRegion.h:997
const VarDecl * getDecl() const override=0
llvm::ImmutableList< SVal >::iterator iterator
Definition SVals.h:352
Value representing integer constant.
Definition SVals.h:300
While nonloc::CompoundVal covers a few simple use cases, nonloc::LazyCompoundVal is a more performant...
Definition SVals.h:389
LLVM_ATTRIBUTE_RETURNS_NONNULL const LazyCompoundValData * getCVData() const
Definition SVals.h:399
LLVM_ATTRIBUTE_RETURNS_NONNULL const TypedValueRegion * getRegion() const
This function itself is immaterial.
Definition SVals.cpp:193
const void * getStore() const
It might return null.
Definition SVals.cpp:189
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
Definition Store.h:50
const SymExpr * SymbolRef
Definition SymExpr.h:133
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
std::unique_ptr< StoreManager > CreateRegionStoreManager(ProgramStateManager &StMgr)
const void * Store
Store - This opaque type encapsulates an immutable mapping from locations to values.
Definition StoreRef.h:27
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.
Definition Sema.h:830
bool isa(CodeGen::Address addr)
Definition Address.h:330
CFGBlock::ConstCFGElementRef ConstCFGElementRef
Definition CFG.h:1227
@ Bind
'bind' clause, allowed on routine constructs.
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition CallGraph.h:206
bool operator<(DeclarationName LHS, DeclarationName RHS)
Ordering on two declaration names.
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
Definition JsonSupport.h:21
const StreamingDiagnostic & operator<<(const StreamingDiagnostic &DB, const ConceptReference *C)
Insertion operator for diagnostics.
U cast(CodeGen::Address addr)
Definition Address.h:327
@ Class
The "class" keyword introduces the elaborated-type-specifier.
Definition TypeBase.h:5979
unsigned long uint64_t
unsigned int uint32_t
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
__UINTPTR_TYPE__ uintptr_t
An unsigned integer type with the property that any valid pointer to void can be converted to this ty...