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