106f32e7eSjoerg //== RegionStore.cpp - Field-sensitive store model --------------*- C++ -*--==//
206f32e7eSjoerg //
306f32e7eSjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
406f32e7eSjoerg // See https://llvm.org/LICENSE.txt for license information.
506f32e7eSjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
606f32e7eSjoerg //
706f32e7eSjoerg //===----------------------------------------------------------------------===//
806f32e7eSjoerg //
906f32e7eSjoerg // This file defines a basic region store model. In this model, we do have field
1006f32e7eSjoerg // sensitivity. But we assume nothing about the heap shape. So recursive data
1106f32e7eSjoerg // structures are largely ignored. Basically we do 1-limiting analysis.
1206f32e7eSjoerg // Parameter pointers are assumed with no aliasing. Pointee objects of
1306f32e7eSjoerg // parameters are created lazily.
1406f32e7eSjoerg //
1506f32e7eSjoerg //===----------------------------------------------------------------------===//
1606f32e7eSjoerg 
1706f32e7eSjoerg #include "clang/AST/Attr.h"
1806f32e7eSjoerg #include "clang/AST/CharUnits.h"
1906f32e7eSjoerg #include "clang/ASTMatchers/ASTMatchFinder.h"
2006f32e7eSjoerg #include "clang/Analysis/Analyses/LiveVariables.h"
2106f32e7eSjoerg #include "clang/Analysis/AnalysisDeclContext.h"
2206f32e7eSjoerg #include "clang/Basic/JsonSupport.h"
2306f32e7eSjoerg #include "clang/Basic/TargetInfo.h"
2406f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
2506f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
26*13fbcb42Sjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
2706f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
2806f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
2906f32e7eSjoerg #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
3006f32e7eSjoerg #include "llvm/ADT/ImmutableMap.h"
3106f32e7eSjoerg #include "llvm/ADT/Optional.h"
3206f32e7eSjoerg #include "llvm/Support/raw_ostream.h"
3306f32e7eSjoerg #include <utility>
3406f32e7eSjoerg 
3506f32e7eSjoerg using namespace clang;
3606f32e7eSjoerg using namespace ento;
3706f32e7eSjoerg 
3806f32e7eSjoerg //===----------------------------------------------------------------------===//
3906f32e7eSjoerg // Representation of binding keys.
4006f32e7eSjoerg //===----------------------------------------------------------------------===//
4106f32e7eSjoerg 
4206f32e7eSjoerg namespace {
4306f32e7eSjoerg class BindingKey {
4406f32e7eSjoerg public:
4506f32e7eSjoerg   enum Kind { Default = 0x0, Direct = 0x1 };
4606f32e7eSjoerg private:
4706f32e7eSjoerg   enum { Symbolic = 0x2 };
4806f32e7eSjoerg 
4906f32e7eSjoerg   llvm::PointerIntPair<const MemRegion *, 2> P;
5006f32e7eSjoerg   uint64_t Data;
5106f32e7eSjoerg 
5206f32e7eSjoerg   /// Create a key for a binding to region \p r, which has a symbolic offset
5306f32e7eSjoerg   /// from region \p Base.
BindingKey(const SubRegion * r,const SubRegion * Base,Kind k)5406f32e7eSjoerg   explicit BindingKey(const SubRegion *r, const SubRegion *Base, Kind k)
5506f32e7eSjoerg     : P(r, k | Symbolic), Data(reinterpret_cast<uintptr_t>(Base)) {
5606f32e7eSjoerg     assert(r && Base && "Must have known regions.");
5706f32e7eSjoerg     assert(getConcreteOffsetRegion() == Base && "Failed to store base region");
5806f32e7eSjoerg   }
5906f32e7eSjoerg 
6006f32e7eSjoerg   /// Create a key for a binding at \p offset from base region \p r.
BindingKey(const MemRegion * r,uint64_t offset,Kind k)6106f32e7eSjoerg   explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
6206f32e7eSjoerg     : P(r, k), Data(offset) {
6306f32e7eSjoerg     assert(r && "Must have known regions.");
6406f32e7eSjoerg     assert(getOffset() == offset && "Failed to store offset");
6506f32e7eSjoerg     assert((r == r->getBaseRegion() || isa<ObjCIvarRegion>(r) ||
6606f32e7eSjoerg             isa <CXXDerivedObjectRegion>(r)) &&
6706f32e7eSjoerg            "Not a base");
6806f32e7eSjoerg   }
6906f32e7eSjoerg public:
7006f32e7eSjoerg 
isDirect() const7106f32e7eSjoerg   bool isDirect() const { return P.getInt() & Direct; }
hasSymbolicOffset() const7206f32e7eSjoerg   bool hasSymbolicOffset() const { return P.getInt() & Symbolic; }
7306f32e7eSjoerg 
getRegion() const7406f32e7eSjoerg   const MemRegion *getRegion() const { return P.getPointer(); }
getOffset() const7506f32e7eSjoerg   uint64_t getOffset() const {
7606f32e7eSjoerg     assert(!hasSymbolicOffset());
7706f32e7eSjoerg     return Data;
7806f32e7eSjoerg   }
7906f32e7eSjoerg 
getConcreteOffsetRegion() const8006f32e7eSjoerg   const SubRegion *getConcreteOffsetRegion() const {
8106f32e7eSjoerg     assert(hasSymbolicOffset());
8206f32e7eSjoerg     return reinterpret_cast<const SubRegion *>(static_cast<uintptr_t>(Data));
8306f32e7eSjoerg   }
8406f32e7eSjoerg 
getBaseRegion() const8506f32e7eSjoerg   const MemRegion *getBaseRegion() const {
8606f32e7eSjoerg     if (hasSymbolicOffset())
8706f32e7eSjoerg       return getConcreteOffsetRegion()->getBaseRegion();
8806f32e7eSjoerg     return getRegion()->getBaseRegion();
8906f32e7eSjoerg   }
9006f32e7eSjoerg 
Profile(llvm::FoldingSetNodeID & ID) const9106f32e7eSjoerg   void Profile(llvm::FoldingSetNodeID& ID) const {
9206f32e7eSjoerg     ID.AddPointer(P.getOpaqueValue());
9306f32e7eSjoerg     ID.AddInteger(Data);
9406f32e7eSjoerg   }
9506f32e7eSjoerg 
9606f32e7eSjoerg   static BindingKey Make(const MemRegion *R, Kind k);
9706f32e7eSjoerg 
operator <(const BindingKey & X) const9806f32e7eSjoerg   bool operator<(const BindingKey &X) const {
9906f32e7eSjoerg     if (P.getOpaqueValue() < X.P.getOpaqueValue())
10006f32e7eSjoerg       return true;
10106f32e7eSjoerg     if (P.getOpaqueValue() > X.P.getOpaqueValue())
10206f32e7eSjoerg       return false;
10306f32e7eSjoerg     return Data < X.Data;
10406f32e7eSjoerg   }
10506f32e7eSjoerg 
operator ==(const BindingKey & X) const10606f32e7eSjoerg   bool operator==(const BindingKey &X) const {
10706f32e7eSjoerg     return P.getOpaqueValue() == X.P.getOpaqueValue() &&
10806f32e7eSjoerg            Data == X.Data;
10906f32e7eSjoerg   }
11006f32e7eSjoerg 
11106f32e7eSjoerg   LLVM_DUMP_METHOD void dump() const;
11206f32e7eSjoerg };
11306f32e7eSjoerg } // end anonymous namespace
11406f32e7eSjoerg 
Make(const MemRegion * R,Kind k)11506f32e7eSjoerg BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
11606f32e7eSjoerg   const RegionOffset &RO = R->getAsOffset();
11706f32e7eSjoerg   if (RO.hasSymbolicOffset())
11806f32e7eSjoerg     return BindingKey(cast<SubRegion>(R), cast<SubRegion>(RO.getRegion()), k);
11906f32e7eSjoerg 
12006f32e7eSjoerg   return BindingKey(RO.getRegion(), RO.getOffset(), k);
12106f32e7eSjoerg }
12206f32e7eSjoerg 
12306f32e7eSjoerg namespace llvm {
operator <<(raw_ostream & Out,BindingKey K)12406f32e7eSjoerg static inline raw_ostream &operator<<(raw_ostream &Out, BindingKey K) {
12506f32e7eSjoerg   Out << "\"kind\": \"" << (K.isDirect() ? "Direct" : "Default")
12606f32e7eSjoerg       << "\", \"offset\": ";
12706f32e7eSjoerg 
12806f32e7eSjoerg   if (!K.hasSymbolicOffset())
12906f32e7eSjoerg     Out << K.getOffset();
13006f32e7eSjoerg   else
13106f32e7eSjoerg     Out << "null";
13206f32e7eSjoerg 
13306f32e7eSjoerg   return Out;
13406f32e7eSjoerg }
13506f32e7eSjoerg 
13606f32e7eSjoerg } // namespace llvm
13706f32e7eSjoerg 
13806f32e7eSjoerg #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump() const13906f32e7eSjoerg void BindingKey::dump() const { llvm::errs() << *this; }
14006f32e7eSjoerg #endif
14106f32e7eSjoerg 
14206f32e7eSjoerg //===----------------------------------------------------------------------===//
14306f32e7eSjoerg // Actual Store type.
14406f32e7eSjoerg //===----------------------------------------------------------------------===//
14506f32e7eSjoerg 
14606f32e7eSjoerg typedef llvm::ImmutableMap<BindingKey, SVal>    ClusterBindings;
14706f32e7eSjoerg typedef llvm::ImmutableMapRef<BindingKey, SVal> ClusterBindingsRef;
14806f32e7eSjoerg typedef std::pair<BindingKey, SVal> BindingPair;
14906f32e7eSjoerg 
15006f32e7eSjoerg typedef llvm::ImmutableMap<const MemRegion *, ClusterBindings>
15106f32e7eSjoerg         RegionBindings;
15206f32e7eSjoerg 
15306f32e7eSjoerg namespace {
15406f32e7eSjoerg class RegionBindingsRef : public llvm::ImmutableMapRef<const MemRegion *,
15506f32e7eSjoerg                                  ClusterBindings> {
15606f32e7eSjoerg   ClusterBindings::Factory *CBFactory;
15706f32e7eSjoerg 
15806f32e7eSjoerg   // This flag indicates whether the current bindings are within the analysis
15906f32e7eSjoerg   // that has started from main(). It affects how we perform loads from
16006f32e7eSjoerg   // global variables that have initializers: if we have observed the
16106f32e7eSjoerg   // program execution from the start and we know that these variables
16206f32e7eSjoerg   // have not been overwritten yet, we can be sure that their initializers
16306f32e7eSjoerg   // are still relevant. This flag never gets changed when the bindings are
16406f32e7eSjoerg   // updated, so it could potentially be moved into RegionStoreManager
16506f32e7eSjoerg   // (as if it's the same bindings but a different loading procedure)
16606f32e7eSjoerg   // however that would have made the manager needlessly stateful.
16706f32e7eSjoerg   bool IsMainAnalysis;
16806f32e7eSjoerg 
16906f32e7eSjoerg public:
17006f32e7eSjoerg   typedef llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>
17106f32e7eSjoerg           ParentTy;
17206f32e7eSjoerg 
RegionBindingsRef(ClusterBindings::Factory & CBFactory,const RegionBindings::TreeTy * T,RegionBindings::TreeTy::Factory * F,bool IsMainAnalysis)17306f32e7eSjoerg   RegionBindingsRef(ClusterBindings::Factory &CBFactory,
17406f32e7eSjoerg                     const RegionBindings::TreeTy *T,
17506f32e7eSjoerg                     RegionBindings::TreeTy::Factory *F,
17606f32e7eSjoerg                     bool IsMainAnalysis)
17706f32e7eSjoerg       : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(T, F),
17806f32e7eSjoerg         CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
17906f32e7eSjoerg 
RegionBindingsRef(const ParentTy & P,ClusterBindings::Factory & CBFactory,bool IsMainAnalysis)18006f32e7eSjoerg   RegionBindingsRef(const ParentTy &P,
18106f32e7eSjoerg                     ClusterBindings::Factory &CBFactory,
18206f32e7eSjoerg                     bool IsMainAnalysis)
18306f32e7eSjoerg       : llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>(P),
18406f32e7eSjoerg         CBFactory(&CBFactory), IsMainAnalysis(IsMainAnalysis) {}
18506f32e7eSjoerg 
add(key_type_ref K,data_type_ref D) const18606f32e7eSjoerg   RegionBindingsRef add(key_type_ref K, data_type_ref D) const {
18706f32e7eSjoerg     return RegionBindingsRef(static_cast<const ParentTy *>(this)->add(K, D),
18806f32e7eSjoerg                              *CBFactory, IsMainAnalysis);
18906f32e7eSjoerg   }
19006f32e7eSjoerg 
remove(key_type_ref K) const19106f32e7eSjoerg   RegionBindingsRef remove(key_type_ref K) const {
19206f32e7eSjoerg     return RegionBindingsRef(static_cast<const ParentTy *>(this)->remove(K),
19306f32e7eSjoerg                              *CBFactory, IsMainAnalysis);
19406f32e7eSjoerg   }
19506f32e7eSjoerg 
19606f32e7eSjoerg   RegionBindingsRef addBinding(BindingKey K, SVal V) const;
19706f32e7eSjoerg 
19806f32e7eSjoerg   RegionBindingsRef addBinding(const MemRegion *R,
19906f32e7eSjoerg                                BindingKey::Kind k, SVal V) const;
20006f32e7eSjoerg 
20106f32e7eSjoerg   const SVal *lookup(BindingKey K) const;
20206f32e7eSjoerg   const SVal *lookup(const MemRegion *R, BindingKey::Kind k) const;
20306f32e7eSjoerg   using llvm::ImmutableMapRef<const MemRegion *, ClusterBindings>::lookup;
20406f32e7eSjoerg 
20506f32e7eSjoerg   RegionBindingsRef removeBinding(BindingKey K);
20606f32e7eSjoerg 
20706f32e7eSjoerg   RegionBindingsRef removeBinding(const MemRegion *R,
20806f32e7eSjoerg                                   BindingKey::Kind k);
20906f32e7eSjoerg 
removeBinding(const MemRegion * R)21006f32e7eSjoerg   RegionBindingsRef removeBinding(const MemRegion *R) {
21106f32e7eSjoerg     return removeBinding(R, BindingKey::Direct).
21206f32e7eSjoerg            removeBinding(R, BindingKey::Default);
21306f32e7eSjoerg   }
21406f32e7eSjoerg 
21506f32e7eSjoerg   Optional<SVal> getDirectBinding(const MemRegion *R) const;
21606f32e7eSjoerg 
21706f32e7eSjoerg   /// getDefaultBinding - Returns an SVal* representing an optional default
21806f32e7eSjoerg   ///  binding associated with a region and its subregions.
21906f32e7eSjoerg   Optional<SVal> getDefaultBinding(const MemRegion *R) const;
22006f32e7eSjoerg 
22106f32e7eSjoerg   /// Return the internal tree as a Store.
asStore() const22206f32e7eSjoerg   Store asStore() const {
22306f32e7eSjoerg     llvm::PointerIntPair<Store, 1, bool> Ptr = {
22406f32e7eSjoerg         asImmutableMap().getRootWithoutRetain(), IsMainAnalysis};
22506f32e7eSjoerg     return reinterpret_cast<Store>(Ptr.getOpaqueValue());
22606f32e7eSjoerg   }
22706f32e7eSjoerg 
isMainAnalysis() const22806f32e7eSjoerg   bool isMainAnalysis() const {
22906f32e7eSjoerg     return IsMainAnalysis;
23006f32e7eSjoerg   }
23106f32e7eSjoerg 
printJson(raw_ostream & Out,const char * NL="\\n",unsigned int Space=0,bool IsDot=false) const23206f32e7eSjoerg   void printJson(raw_ostream &Out, const char *NL = "\n",
23306f32e7eSjoerg                  unsigned int Space = 0, bool IsDot = false) const {
23406f32e7eSjoerg     for (iterator I = begin(); I != end(); ++I) {
23506f32e7eSjoerg       // TODO: We might need a .printJson for I.getKey() as well.
23606f32e7eSjoerg       Indent(Out, Space, IsDot)
23706f32e7eSjoerg           << "{ \"cluster\": \"" << I.getKey() << "\", \"pointer\": \""
23806f32e7eSjoerg           << (const void *)I.getKey() << "\", \"items\": [" << NL;
23906f32e7eSjoerg 
24006f32e7eSjoerg       ++Space;
24106f32e7eSjoerg       const ClusterBindings &CB = I.getData();
24206f32e7eSjoerg       for (ClusterBindings::iterator CI = CB.begin(); CI != CB.end(); ++CI) {
24306f32e7eSjoerg         Indent(Out, Space, IsDot) << "{ " << CI.getKey() << ", \"value\": ";
24406f32e7eSjoerg         CI.getData().printJson(Out, /*AddQuotes=*/true);
24506f32e7eSjoerg         Out << " }";
24606f32e7eSjoerg         if (std::next(CI) != CB.end())
24706f32e7eSjoerg           Out << ',';
24806f32e7eSjoerg         Out << NL;
24906f32e7eSjoerg       }
25006f32e7eSjoerg 
25106f32e7eSjoerg       --Space;
25206f32e7eSjoerg       Indent(Out, Space, IsDot) << "]}";
25306f32e7eSjoerg       if (std::next(I) != end())
25406f32e7eSjoerg         Out << ',';
25506f32e7eSjoerg       Out << NL;
25606f32e7eSjoerg     }
25706f32e7eSjoerg   }
25806f32e7eSjoerg 
dump() const25906f32e7eSjoerg   LLVM_DUMP_METHOD void dump() const { printJson(llvm::errs()); }
26006f32e7eSjoerg };
26106f32e7eSjoerg } // end anonymous namespace
26206f32e7eSjoerg 
26306f32e7eSjoerg typedef const RegionBindingsRef& RegionBindingsConstRef;
26406f32e7eSjoerg 
getDirectBinding(const MemRegion * R) const26506f32e7eSjoerg Optional<SVal> RegionBindingsRef::getDirectBinding(const MemRegion *R) const {
26606f32e7eSjoerg   return Optional<SVal>::create(lookup(R, BindingKey::Direct));
26706f32e7eSjoerg }
26806f32e7eSjoerg 
getDefaultBinding(const MemRegion * R) const26906f32e7eSjoerg Optional<SVal> RegionBindingsRef::getDefaultBinding(const MemRegion *R) const {
27006f32e7eSjoerg   return Optional<SVal>::create(lookup(R, BindingKey::Default));
27106f32e7eSjoerg }
27206f32e7eSjoerg 
addBinding(BindingKey K,SVal V) const27306f32e7eSjoerg RegionBindingsRef RegionBindingsRef::addBinding(BindingKey K, SVal V) const {
27406f32e7eSjoerg   const MemRegion *Base = K.getBaseRegion();
27506f32e7eSjoerg 
27606f32e7eSjoerg   const ClusterBindings *ExistingCluster = lookup(Base);
27706f32e7eSjoerg   ClusterBindings Cluster =
27806f32e7eSjoerg       (ExistingCluster ? *ExistingCluster : CBFactory->getEmptyMap());
27906f32e7eSjoerg 
28006f32e7eSjoerg   ClusterBindings NewCluster = CBFactory->add(Cluster, K, V);
28106f32e7eSjoerg   return add(Base, NewCluster);
28206f32e7eSjoerg }
28306f32e7eSjoerg 
28406f32e7eSjoerg 
addBinding(const MemRegion * R,BindingKey::Kind k,SVal V) const28506f32e7eSjoerg RegionBindingsRef RegionBindingsRef::addBinding(const MemRegion *R,
28606f32e7eSjoerg                                                 BindingKey::Kind k,
28706f32e7eSjoerg                                                 SVal V) const {
28806f32e7eSjoerg   return addBinding(BindingKey::Make(R, k), V);
28906f32e7eSjoerg }
29006f32e7eSjoerg 
lookup(BindingKey K) const29106f32e7eSjoerg const SVal *RegionBindingsRef::lookup(BindingKey K) const {
29206f32e7eSjoerg   const ClusterBindings *Cluster = lookup(K.getBaseRegion());
29306f32e7eSjoerg   if (!Cluster)
29406f32e7eSjoerg     return nullptr;
29506f32e7eSjoerg   return Cluster->lookup(K);
29606f32e7eSjoerg }
29706f32e7eSjoerg 
lookup(const MemRegion * R,BindingKey::Kind k) const29806f32e7eSjoerg const SVal *RegionBindingsRef::lookup(const MemRegion *R,
29906f32e7eSjoerg                                       BindingKey::Kind k) const {
30006f32e7eSjoerg   return lookup(BindingKey::Make(R, k));
30106f32e7eSjoerg }
30206f32e7eSjoerg 
removeBinding(BindingKey K)30306f32e7eSjoerg RegionBindingsRef RegionBindingsRef::removeBinding(BindingKey K) {
30406f32e7eSjoerg   const MemRegion *Base = K.getBaseRegion();
30506f32e7eSjoerg   const ClusterBindings *Cluster = lookup(Base);
30606f32e7eSjoerg   if (!Cluster)
30706f32e7eSjoerg     return *this;
30806f32e7eSjoerg 
30906f32e7eSjoerg   ClusterBindings NewCluster = CBFactory->remove(*Cluster, K);
31006f32e7eSjoerg   if (NewCluster.isEmpty())
31106f32e7eSjoerg     return remove(Base);
31206f32e7eSjoerg   return add(Base, NewCluster);
31306f32e7eSjoerg }
31406f32e7eSjoerg 
removeBinding(const MemRegion * R,BindingKey::Kind k)31506f32e7eSjoerg RegionBindingsRef RegionBindingsRef::removeBinding(const MemRegion *R,
31606f32e7eSjoerg                                                 BindingKey::Kind k){
31706f32e7eSjoerg   return removeBinding(BindingKey::Make(R, k));
31806f32e7eSjoerg }
31906f32e7eSjoerg 
32006f32e7eSjoerg //===----------------------------------------------------------------------===//
32106f32e7eSjoerg // Fine-grained control of RegionStoreManager.
32206f32e7eSjoerg //===----------------------------------------------------------------------===//
32306f32e7eSjoerg 
32406f32e7eSjoerg namespace {
32506f32e7eSjoerg struct minimal_features_tag {};
32606f32e7eSjoerg struct maximal_features_tag {};
32706f32e7eSjoerg 
32806f32e7eSjoerg class RegionStoreFeatures {
32906f32e7eSjoerg   bool SupportsFields;
33006f32e7eSjoerg public:
RegionStoreFeatures(minimal_features_tag)33106f32e7eSjoerg   RegionStoreFeatures(minimal_features_tag) :
33206f32e7eSjoerg     SupportsFields(false) {}
33306f32e7eSjoerg 
RegionStoreFeatures(maximal_features_tag)33406f32e7eSjoerg   RegionStoreFeatures(maximal_features_tag) :
33506f32e7eSjoerg     SupportsFields(true) {}
33606f32e7eSjoerg 
enableFields(bool t)33706f32e7eSjoerg   void enableFields(bool t) { SupportsFields = t; }
33806f32e7eSjoerg 
supportsFields() const33906f32e7eSjoerg   bool supportsFields() const { return SupportsFields; }
34006f32e7eSjoerg };
34106f32e7eSjoerg }
34206f32e7eSjoerg 
34306f32e7eSjoerg //===----------------------------------------------------------------------===//
34406f32e7eSjoerg // Main RegionStore logic.
34506f32e7eSjoerg //===----------------------------------------------------------------------===//
34606f32e7eSjoerg 
34706f32e7eSjoerg namespace {
34806f32e7eSjoerg class InvalidateRegionsWorker;
34906f32e7eSjoerg 
35006f32e7eSjoerg class RegionStoreManager : public StoreManager {
35106f32e7eSjoerg public:
35206f32e7eSjoerg   const RegionStoreFeatures Features;
35306f32e7eSjoerg 
35406f32e7eSjoerg   RegionBindings::Factory RBFactory;
35506f32e7eSjoerg   mutable ClusterBindings::Factory CBFactory;
35606f32e7eSjoerg 
35706f32e7eSjoerg   typedef std::vector<SVal> SValListTy;
35806f32e7eSjoerg private:
35906f32e7eSjoerg   typedef llvm::DenseMap<const LazyCompoundValData *,
36006f32e7eSjoerg                          SValListTy> LazyBindingsMapTy;
36106f32e7eSjoerg   LazyBindingsMapTy LazyBindingsMap;
36206f32e7eSjoerg 
36306f32e7eSjoerg   /// The largest number of fields a struct can have and still be
36406f32e7eSjoerg   /// considered "small".
36506f32e7eSjoerg   ///
36606f32e7eSjoerg   /// This is currently used to decide whether or not it is worth "forcing" a
36706f32e7eSjoerg   /// LazyCompoundVal on bind.
36806f32e7eSjoerg   ///
36906f32e7eSjoerg   /// This is controlled by 'region-store-small-struct-limit' option.
37006f32e7eSjoerg   /// To disable all small-struct-dependent behavior, set the option to "0".
37106f32e7eSjoerg   unsigned SmallStructLimit;
37206f32e7eSjoerg 
37306f32e7eSjoerg   /// A helper used to populate the work list with the given set of
37406f32e7eSjoerg   /// regions.
37506f32e7eSjoerg   void populateWorkList(InvalidateRegionsWorker &W,
37606f32e7eSjoerg                         ArrayRef<SVal> Values,
37706f32e7eSjoerg                         InvalidatedRegions *TopLevelRegions);
37806f32e7eSjoerg 
37906f32e7eSjoerg public:
RegionStoreManager(ProgramStateManager & mgr,const RegionStoreFeatures & f)38006f32e7eSjoerg   RegionStoreManager(ProgramStateManager& mgr, const RegionStoreFeatures &f)
38106f32e7eSjoerg     : StoreManager(mgr), Features(f),
38206f32e7eSjoerg       RBFactory(mgr.getAllocator()), CBFactory(mgr.getAllocator()),
38306f32e7eSjoerg       SmallStructLimit(0) {
384*13fbcb42Sjoerg     ExprEngine &Eng = StateMgr.getOwningEngine();
38506f32e7eSjoerg     AnalyzerOptions &Options = Eng.getAnalysisManager().options;
38606f32e7eSjoerg     SmallStructLimit = Options.RegionStoreSmallStructLimit;
38706f32e7eSjoerg   }
38806f32e7eSjoerg 
38906f32e7eSjoerg 
39006f32e7eSjoerg   /// setImplicitDefaultValue - Set the default binding for the provided
39106f32e7eSjoerg   ///  MemRegion to the value implicitly defined for compound literals when
39206f32e7eSjoerg   ///  the value is not specified.
39306f32e7eSjoerg   RegionBindingsRef setImplicitDefaultValue(RegionBindingsConstRef B,
39406f32e7eSjoerg                                             const MemRegion *R, QualType T);
39506f32e7eSjoerg 
39606f32e7eSjoerg   /// ArrayToPointer - Emulates the "decay" of an array to a pointer
39706f32e7eSjoerg   ///  type.  'Array' represents the lvalue of the array being decayed
39806f32e7eSjoerg   ///  to a pointer, and the returned SVal represents the decayed
39906f32e7eSjoerg   ///  version of that lvalue (i.e., a pointer to the first element of
40006f32e7eSjoerg   ///  the array).  This is called by ExprEngine when evaluating
40106f32e7eSjoerg   ///  casts from arrays to pointers.
40206f32e7eSjoerg   SVal ArrayToPointer(Loc Array, QualType ElementTy) override;
40306f32e7eSjoerg 
40406f32e7eSjoerg   /// Creates the Store that correctly represents memory contents before
40506f32e7eSjoerg   /// the beginning of the analysis of the given top-level stack frame.
getInitialStore(const LocationContext * InitLoc)40606f32e7eSjoerg   StoreRef getInitialStore(const LocationContext *InitLoc) override {
40706f32e7eSjoerg     bool IsMainAnalysis = false;
40806f32e7eSjoerg     if (const auto *FD = dyn_cast<FunctionDecl>(InitLoc->getDecl()))
40906f32e7eSjoerg       IsMainAnalysis = FD->isMain() && !Ctx.getLangOpts().CPlusPlus;
41006f32e7eSjoerg     return StoreRef(RegionBindingsRef(
41106f32e7eSjoerg         RegionBindingsRef::ParentTy(RBFactory.getEmptyMap(), RBFactory),
41206f32e7eSjoerg         CBFactory, IsMainAnalysis).asStore(), *this);
41306f32e7eSjoerg   }
41406f32e7eSjoerg 
41506f32e7eSjoerg   //===-------------------------------------------------------------------===//
41606f32e7eSjoerg   // Binding values to regions.
41706f32e7eSjoerg   //===-------------------------------------------------------------------===//
41806f32e7eSjoerg   RegionBindingsRef invalidateGlobalRegion(MemRegion::Kind K,
41906f32e7eSjoerg                                            const Expr *Ex,
42006f32e7eSjoerg                                            unsigned Count,
42106f32e7eSjoerg                                            const LocationContext *LCtx,
42206f32e7eSjoerg                                            RegionBindingsRef B,
42306f32e7eSjoerg                                            InvalidatedRegions *Invalidated);
42406f32e7eSjoerg 
42506f32e7eSjoerg   StoreRef invalidateRegions(Store store,
42606f32e7eSjoerg                              ArrayRef<SVal> Values,
42706f32e7eSjoerg                              const Expr *E, unsigned Count,
42806f32e7eSjoerg                              const LocationContext *LCtx,
42906f32e7eSjoerg                              const CallEvent *Call,
43006f32e7eSjoerg                              InvalidatedSymbols &IS,
43106f32e7eSjoerg                              RegionAndSymbolInvalidationTraits &ITraits,
43206f32e7eSjoerg                              InvalidatedRegions *Invalidated,
43306f32e7eSjoerg                              InvalidatedRegions *InvalidatedTopLevel) override;
43406f32e7eSjoerg 
43506f32e7eSjoerg   bool scanReachableSymbols(Store S, const MemRegion *R,
43606f32e7eSjoerg                             ScanReachableSymbols &Callbacks) override;
43706f32e7eSjoerg 
43806f32e7eSjoerg   RegionBindingsRef removeSubRegionBindings(RegionBindingsConstRef B,
43906f32e7eSjoerg                                             const SubRegion *R);
44006f32e7eSjoerg 
44106f32e7eSjoerg public: // Part of public interface to class.
44206f32e7eSjoerg 
Bind(Store store,Loc LV,SVal V)44306f32e7eSjoerg   StoreRef Bind(Store store, Loc LV, SVal V) override {
44406f32e7eSjoerg     return StoreRef(bind(getRegionBindings(store), LV, V).asStore(), *this);
44506f32e7eSjoerg   }
44606f32e7eSjoerg 
44706f32e7eSjoerg   RegionBindingsRef bind(RegionBindingsConstRef B, Loc LV, SVal V);
44806f32e7eSjoerg 
44906f32e7eSjoerg   // BindDefaultInitial is only used to initialize a region with
45006f32e7eSjoerg   // a default value.
BindDefaultInitial(Store store,const MemRegion * R,SVal V)45106f32e7eSjoerg   StoreRef BindDefaultInitial(Store store, const MemRegion *R,
45206f32e7eSjoerg                               SVal V) override {
45306f32e7eSjoerg     RegionBindingsRef B = getRegionBindings(store);
45406f32e7eSjoerg     // Use other APIs when you have to wipe the region that was initialized
45506f32e7eSjoerg     // earlier.
45606f32e7eSjoerg     assert(!(B.getDefaultBinding(R) || B.getDirectBinding(R)) &&
45706f32e7eSjoerg            "Double initialization!");
45806f32e7eSjoerg     B = B.addBinding(BindingKey::Make(R, BindingKey::Default), V);
45906f32e7eSjoerg     return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);
46006f32e7eSjoerg   }
46106f32e7eSjoerg 
46206f32e7eSjoerg   // BindDefaultZero is used for zeroing constructors that may accidentally
46306f32e7eSjoerg   // overwrite existing bindings.
BindDefaultZero(Store store,const MemRegion * R)46406f32e7eSjoerg   StoreRef BindDefaultZero(Store store, const MemRegion *R) override {
46506f32e7eSjoerg     // FIXME: The offsets of empty bases can be tricky because of
46606f32e7eSjoerg     // of the so called "empty base class optimization".
46706f32e7eSjoerg     // If a base class has been optimized out
46806f32e7eSjoerg     // we should not try to create a binding, otherwise we should.
46906f32e7eSjoerg     // Unfortunately, at the moment ASTRecordLayout doesn't expose
47006f32e7eSjoerg     // the actual sizes of the empty bases
47106f32e7eSjoerg     // and trying to infer them from offsets/alignments
47206f32e7eSjoerg     // seems to be error-prone and non-trivial because of the trailing padding.
47306f32e7eSjoerg     // As a temporary mitigation we don't create bindings for empty bases.
47406f32e7eSjoerg     if (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
47506f32e7eSjoerg       if (BR->getDecl()->isEmpty())
47606f32e7eSjoerg         return StoreRef(store, *this);
47706f32e7eSjoerg 
47806f32e7eSjoerg     RegionBindingsRef B = getRegionBindings(store);
47906f32e7eSjoerg     SVal V = svalBuilder.makeZeroVal(Ctx.CharTy);
48006f32e7eSjoerg     B = removeSubRegionBindings(B, cast<SubRegion>(R));
48106f32e7eSjoerg     B = B.addBinding(BindingKey::Make(R, BindingKey::Default), V);
48206f32e7eSjoerg     return StoreRef(B.asImmutableMap().getRootWithoutRetain(), *this);
48306f32e7eSjoerg   }
48406f32e7eSjoerg 
48506f32e7eSjoerg   /// Attempt to extract the fields of \p LCV and bind them to the struct region
48606f32e7eSjoerg   /// \p R.
48706f32e7eSjoerg   ///
48806f32e7eSjoerg   /// This path is used when it seems advantageous to "force" loading the values
48906f32e7eSjoerg   /// within a LazyCompoundVal to bind memberwise to the struct region, rather
49006f32e7eSjoerg   /// than using a Default binding at the base of the entire region. This is a
49106f32e7eSjoerg   /// heuristic attempting to avoid building long chains of LazyCompoundVals.
49206f32e7eSjoerg   ///
49306f32e7eSjoerg   /// \returns The updated store bindings, or \c None if binding non-lazily
49406f32e7eSjoerg   ///          would be too expensive.
49506f32e7eSjoerg   Optional<RegionBindingsRef> tryBindSmallStruct(RegionBindingsConstRef B,
49606f32e7eSjoerg                                                  const TypedValueRegion *R,
49706f32e7eSjoerg                                                  const RecordDecl *RD,
49806f32e7eSjoerg                                                  nonloc::LazyCompoundVal LCV);
49906f32e7eSjoerg 
50006f32e7eSjoerg   /// BindStruct - Bind a compound value to a structure.
50106f32e7eSjoerg   RegionBindingsRef bindStruct(RegionBindingsConstRef B,
50206f32e7eSjoerg                                const TypedValueRegion* R, SVal V);
50306f32e7eSjoerg 
50406f32e7eSjoerg   /// BindVector - Bind a compound value to a vector.
50506f32e7eSjoerg   RegionBindingsRef bindVector(RegionBindingsConstRef B,
50606f32e7eSjoerg                                const TypedValueRegion* R, SVal V);
50706f32e7eSjoerg 
50806f32e7eSjoerg   RegionBindingsRef bindArray(RegionBindingsConstRef B,
50906f32e7eSjoerg                               const TypedValueRegion* R,
51006f32e7eSjoerg                               SVal V);
51106f32e7eSjoerg 
51206f32e7eSjoerg   /// Clears out all bindings in the given region and assigns a new value
51306f32e7eSjoerg   /// as a Default binding.
51406f32e7eSjoerg   RegionBindingsRef bindAggregate(RegionBindingsConstRef B,
51506f32e7eSjoerg                                   const TypedRegion *R,
51606f32e7eSjoerg                                   SVal DefaultVal);
51706f32e7eSjoerg 
51806f32e7eSjoerg   /// Create a new store with the specified binding removed.
51906f32e7eSjoerg   /// \param ST the original store, that is the basis for the new store.
52006f32e7eSjoerg   /// \param L the location whose binding should be removed.
52106f32e7eSjoerg   StoreRef killBinding(Store ST, Loc L) override;
52206f32e7eSjoerg 
incrementReferenceCount(Store store)52306f32e7eSjoerg   void incrementReferenceCount(Store store) override {
52406f32e7eSjoerg     getRegionBindings(store).manualRetain();
52506f32e7eSjoerg   }
52606f32e7eSjoerg 
52706f32e7eSjoerg   /// If the StoreManager supports it, decrement the reference count of
52806f32e7eSjoerg   /// the specified Store object.  If the reference count hits 0, the memory
52906f32e7eSjoerg   /// associated with the object is recycled.
decrementReferenceCount(Store store)53006f32e7eSjoerg   void decrementReferenceCount(Store store) override {
53106f32e7eSjoerg     getRegionBindings(store).manualRelease();
53206f32e7eSjoerg   }
53306f32e7eSjoerg 
53406f32e7eSjoerg   bool includedInBindings(Store store, const MemRegion *region) const override;
53506f32e7eSjoerg 
53606f32e7eSjoerg   /// Return the value bound to specified location in a given state.
53706f32e7eSjoerg   ///
53806f32e7eSjoerg   /// The high level logic for this method is this:
53906f32e7eSjoerg   /// getBinding (L)
54006f32e7eSjoerg   ///   if L has binding
54106f32e7eSjoerg   ///     return L's binding
54206f32e7eSjoerg   ///   else if L is in killset
54306f32e7eSjoerg   ///     return unknown
54406f32e7eSjoerg   ///   else
54506f32e7eSjoerg   ///     if L is on stack or heap
54606f32e7eSjoerg   ///       return undefined
54706f32e7eSjoerg   ///     else
54806f32e7eSjoerg   ///       return symbolic
getBinding(Store S,Loc L,QualType T)54906f32e7eSjoerg   SVal getBinding(Store S, Loc L, QualType T) override {
55006f32e7eSjoerg     return getBinding(getRegionBindings(S), L, T);
55106f32e7eSjoerg   }
55206f32e7eSjoerg 
getDefaultBinding(Store S,const MemRegion * R)55306f32e7eSjoerg   Optional<SVal> getDefaultBinding(Store S, const MemRegion *R) override {
55406f32e7eSjoerg     RegionBindingsRef B = getRegionBindings(S);
55506f32e7eSjoerg     // Default bindings are always applied over a base region so look up the
55606f32e7eSjoerg     // base region's default binding, otherwise the lookup will fail when R
55706f32e7eSjoerg     // is at an offset from R->getBaseRegion().
55806f32e7eSjoerg     return B.getDefaultBinding(R->getBaseRegion());
55906f32e7eSjoerg   }
56006f32e7eSjoerg 
56106f32e7eSjoerg   SVal getBinding(RegionBindingsConstRef B, Loc L, QualType T = QualType());
56206f32e7eSjoerg 
56306f32e7eSjoerg   SVal getBindingForElement(RegionBindingsConstRef B, const ElementRegion *R);
56406f32e7eSjoerg 
56506f32e7eSjoerg   SVal getBindingForField(RegionBindingsConstRef B, const FieldRegion *R);
56606f32e7eSjoerg 
56706f32e7eSjoerg   SVal getBindingForObjCIvar(RegionBindingsConstRef B, const ObjCIvarRegion *R);
56806f32e7eSjoerg 
56906f32e7eSjoerg   SVal getBindingForVar(RegionBindingsConstRef B, const VarRegion *R);
57006f32e7eSjoerg 
57106f32e7eSjoerg   SVal getBindingForLazySymbol(const TypedValueRegion *R);
57206f32e7eSjoerg 
57306f32e7eSjoerg   SVal getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
57406f32e7eSjoerg                                          const TypedValueRegion *R,
57506f32e7eSjoerg                                          QualType Ty);
57606f32e7eSjoerg 
57706f32e7eSjoerg   SVal getLazyBinding(const SubRegion *LazyBindingRegion,
57806f32e7eSjoerg                       RegionBindingsRef LazyBinding);
57906f32e7eSjoerg 
58006f32e7eSjoerg   /// Get bindings for the values in a struct and return a CompoundVal, used
58106f32e7eSjoerg   /// when doing struct copy:
58206f32e7eSjoerg   /// struct s x, y;
58306f32e7eSjoerg   /// x = y;
58406f32e7eSjoerg   /// y's value is retrieved by this method.
58506f32e7eSjoerg   SVal getBindingForStruct(RegionBindingsConstRef B, const TypedValueRegion *R);
58606f32e7eSjoerg   SVal getBindingForArray(RegionBindingsConstRef B, const TypedValueRegion *R);
58706f32e7eSjoerg   NonLoc createLazyBinding(RegionBindingsConstRef B, const TypedValueRegion *R);
58806f32e7eSjoerg 
58906f32e7eSjoerg   /// Used to lazily generate derived symbols for bindings that are defined
59006f32e7eSjoerg   /// implicitly by default bindings in a super region.
59106f32e7eSjoerg   ///
59206f32e7eSjoerg   /// Note that callers may need to specially handle LazyCompoundVals, which
59306f32e7eSjoerg   /// are returned as is in case the caller needs to treat them differently.
59406f32e7eSjoerg   Optional<SVal> getBindingForDerivedDefaultValue(RegionBindingsConstRef B,
59506f32e7eSjoerg                                                   const MemRegion *superR,
59606f32e7eSjoerg                                                   const TypedValueRegion *R,
59706f32e7eSjoerg                                                   QualType Ty);
59806f32e7eSjoerg 
59906f32e7eSjoerg   /// Get the state and region whose binding this region \p R corresponds to.
60006f32e7eSjoerg   ///
60106f32e7eSjoerg   /// If there is no lazy binding for \p R, the returned value will have a null
60206f32e7eSjoerg   /// \c second. Note that a null pointer can represents a valid Store.
60306f32e7eSjoerg   std::pair<Store, const SubRegion *>
60406f32e7eSjoerg   findLazyBinding(RegionBindingsConstRef B, const SubRegion *R,
60506f32e7eSjoerg                   const SubRegion *originalRegion);
60606f32e7eSjoerg 
60706f32e7eSjoerg   /// Returns the cached set of interesting SVals contained within a lazy
60806f32e7eSjoerg   /// binding.
60906f32e7eSjoerg   ///
61006f32e7eSjoerg   /// The precise value of "interesting" is determined for the purposes of
61106f32e7eSjoerg   /// RegionStore's internal analysis. It must always contain all regions and
61206f32e7eSjoerg   /// symbols, but may omit constants and other kinds of SVal.
61306f32e7eSjoerg   const SValListTy &getInterestingValues(nonloc::LazyCompoundVal LCV);
61406f32e7eSjoerg 
61506f32e7eSjoerg   //===------------------------------------------------------------------===//
61606f32e7eSjoerg   // State pruning.
61706f32e7eSjoerg   //===------------------------------------------------------------------===//
61806f32e7eSjoerg 
61906f32e7eSjoerg   /// removeDeadBindings - Scans the RegionStore of 'state' for dead values.
62006f32e7eSjoerg   ///  It returns a new Store with these values removed.
62106f32e7eSjoerg   StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx,
62206f32e7eSjoerg                               SymbolReaper& SymReaper) override;
62306f32e7eSjoerg 
62406f32e7eSjoerg   //===------------------------------------------------------------------===//
62506f32e7eSjoerg   // Utility methods.
62606f32e7eSjoerg   //===------------------------------------------------------------------===//
62706f32e7eSjoerg 
getRegionBindings(Store store) const62806f32e7eSjoerg   RegionBindingsRef getRegionBindings(Store store) const {
62906f32e7eSjoerg     llvm::PointerIntPair<Store, 1, bool> Ptr;
63006f32e7eSjoerg     Ptr.setFromOpaqueValue(const_cast<void *>(store));
63106f32e7eSjoerg     return RegionBindingsRef(
63206f32e7eSjoerg         CBFactory,
63306f32e7eSjoerg         static_cast<const RegionBindings::TreeTy *>(Ptr.getPointer()),
63406f32e7eSjoerg         RBFactory.getTreeFactory(),
63506f32e7eSjoerg         Ptr.getInt());
63606f32e7eSjoerg   }
63706f32e7eSjoerg 
63806f32e7eSjoerg   void printJson(raw_ostream &Out, Store S, const char *NL = "\n",
63906f32e7eSjoerg                  unsigned int Space = 0, bool IsDot = false) const override;
64006f32e7eSjoerg 
iterBindings(Store store,BindingsHandler & f)64106f32e7eSjoerg   void iterBindings(Store store, BindingsHandler& f) override {
64206f32e7eSjoerg     RegionBindingsRef B = getRegionBindings(store);
64306f32e7eSjoerg     for (RegionBindingsRef::iterator I = B.begin(), E = B.end(); I != E; ++I) {
64406f32e7eSjoerg       const ClusterBindings &Cluster = I.getData();
64506f32e7eSjoerg       for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
64606f32e7eSjoerg            CI != CE; ++CI) {
64706f32e7eSjoerg         const BindingKey &K = CI.getKey();
64806f32e7eSjoerg         if (!K.isDirect())
64906f32e7eSjoerg           continue;
65006f32e7eSjoerg         if (const SubRegion *R = dyn_cast<SubRegion>(K.getRegion())) {
65106f32e7eSjoerg           // FIXME: Possibly incorporate the offset?
65206f32e7eSjoerg           if (!f.HandleBinding(*this, store, R, CI.getData()))
65306f32e7eSjoerg             return;
65406f32e7eSjoerg         }
65506f32e7eSjoerg       }
65606f32e7eSjoerg     }
65706f32e7eSjoerg   }
65806f32e7eSjoerg };
65906f32e7eSjoerg 
66006f32e7eSjoerg } // end anonymous namespace
66106f32e7eSjoerg 
66206f32e7eSjoerg //===----------------------------------------------------------------------===//
66306f32e7eSjoerg // RegionStore creation.
66406f32e7eSjoerg //===----------------------------------------------------------------------===//
66506f32e7eSjoerg 
66606f32e7eSjoerg std::unique_ptr<StoreManager>
CreateRegionStoreManager(ProgramStateManager & StMgr)66706f32e7eSjoerg ento::CreateRegionStoreManager(ProgramStateManager &StMgr) {
66806f32e7eSjoerg   RegionStoreFeatures F = maximal_features_tag();
66906f32e7eSjoerg   return std::make_unique<RegionStoreManager>(StMgr, F);
67006f32e7eSjoerg }
67106f32e7eSjoerg 
67206f32e7eSjoerg std::unique_ptr<StoreManager>
CreateFieldsOnlyRegionStoreManager(ProgramStateManager & StMgr)67306f32e7eSjoerg ento::CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr) {
67406f32e7eSjoerg   RegionStoreFeatures F = minimal_features_tag();
67506f32e7eSjoerg   F.enableFields(true);
67606f32e7eSjoerg   return std::make_unique<RegionStoreManager>(StMgr, F);
67706f32e7eSjoerg }
67806f32e7eSjoerg 
67906f32e7eSjoerg 
68006f32e7eSjoerg //===----------------------------------------------------------------------===//
68106f32e7eSjoerg // Region Cluster analysis.
68206f32e7eSjoerg //===----------------------------------------------------------------------===//
68306f32e7eSjoerg 
68406f32e7eSjoerg namespace {
68506f32e7eSjoerg /// Used to determine which global regions are automatically included in the
68606f32e7eSjoerg /// initial worklist of a ClusterAnalysis.
68706f32e7eSjoerg enum GlobalsFilterKind {
68806f32e7eSjoerg   /// Don't include any global regions.
68906f32e7eSjoerg   GFK_None,
69006f32e7eSjoerg   /// Only include system globals.
69106f32e7eSjoerg   GFK_SystemOnly,
69206f32e7eSjoerg   /// Include all global regions.
69306f32e7eSjoerg   GFK_All
69406f32e7eSjoerg };
69506f32e7eSjoerg 
69606f32e7eSjoerg template <typename DERIVED>
69706f32e7eSjoerg class ClusterAnalysis  {
69806f32e7eSjoerg protected:
69906f32e7eSjoerg   typedef llvm::DenseMap<const MemRegion *, const ClusterBindings *> ClusterMap;
70006f32e7eSjoerg   typedef const MemRegion * WorkListElement;
70106f32e7eSjoerg   typedef SmallVector<WorkListElement, 10> WorkList;
70206f32e7eSjoerg 
70306f32e7eSjoerg   llvm::SmallPtrSet<const ClusterBindings *, 16> Visited;
70406f32e7eSjoerg 
70506f32e7eSjoerg   WorkList WL;
70606f32e7eSjoerg 
70706f32e7eSjoerg   RegionStoreManager &RM;
70806f32e7eSjoerg   ASTContext &Ctx;
70906f32e7eSjoerg   SValBuilder &svalBuilder;
71006f32e7eSjoerg 
71106f32e7eSjoerg   RegionBindingsRef B;
71206f32e7eSjoerg 
71306f32e7eSjoerg 
71406f32e7eSjoerg protected:
getCluster(const MemRegion * R)71506f32e7eSjoerg   const ClusterBindings *getCluster(const MemRegion *R) {
71606f32e7eSjoerg     return B.lookup(R);
71706f32e7eSjoerg   }
71806f32e7eSjoerg 
71906f32e7eSjoerg   /// Returns true if all clusters in the given memspace should be initially
72006f32e7eSjoerg   /// included in the cluster analysis. Subclasses may provide their
72106f32e7eSjoerg   /// own implementation.
includeEntireMemorySpace(const MemRegion * Base)72206f32e7eSjoerg   bool includeEntireMemorySpace(const MemRegion *Base) {
72306f32e7eSjoerg     return false;
72406f32e7eSjoerg   }
72506f32e7eSjoerg 
72606f32e7eSjoerg public:
ClusterAnalysis(RegionStoreManager & rm,ProgramStateManager & StateMgr,RegionBindingsRef b)72706f32e7eSjoerg   ClusterAnalysis(RegionStoreManager &rm, ProgramStateManager &StateMgr,
72806f32e7eSjoerg                   RegionBindingsRef b)
72906f32e7eSjoerg       : RM(rm), Ctx(StateMgr.getContext()),
73006f32e7eSjoerg         svalBuilder(StateMgr.getSValBuilder()), B(std::move(b)) {}
73106f32e7eSjoerg 
getRegionBindings() const73206f32e7eSjoerg   RegionBindingsRef getRegionBindings() const { return B; }
73306f32e7eSjoerg 
isVisited(const MemRegion * R)73406f32e7eSjoerg   bool isVisited(const MemRegion *R) {
73506f32e7eSjoerg     return Visited.count(getCluster(R));
73606f32e7eSjoerg   }
73706f32e7eSjoerg 
GenerateClusters()73806f32e7eSjoerg   void GenerateClusters() {
73906f32e7eSjoerg     // Scan the entire set of bindings and record the region clusters.
74006f32e7eSjoerg     for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end();
74106f32e7eSjoerg          RI != RE; ++RI){
74206f32e7eSjoerg       const MemRegion *Base = RI.getKey();
74306f32e7eSjoerg 
74406f32e7eSjoerg       const ClusterBindings &Cluster = RI.getData();
74506f32e7eSjoerg       assert(!Cluster.isEmpty() && "Empty clusters should be removed");
74606f32e7eSjoerg       static_cast<DERIVED*>(this)->VisitAddedToCluster(Base, Cluster);
74706f32e7eSjoerg 
74806f32e7eSjoerg       // If the base's memspace should be entirely invalidated, add the cluster
74906f32e7eSjoerg       // to the workspace up front.
75006f32e7eSjoerg       if (static_cast<DERIVED*>(this)->includeEntireMemorySpace(Base))
75106f32e7eSjoerg         AddToWorkList(WorkListElement(Base), &Cluster);
75206f32e7eSjoerg     }
75306f32e7eSjoerg   }
75406f32e7eSjoerg 
AddToWorkList(WorkListElement E,const ClusterBindings * C)75506f32e7eSjoerg   bool AddToWorkList(WorkListElement E, const ClusterBindings *C) {
75606f32e7eSjoerg     if (C && !Visited.insert(C).second)
75706f32e7eSjoerg       return false;
75806f32e7eSjoerg     WL.push_back(E);
75906f32e7eSjoerg     return true;
76006f32e7eSjoerg   }
76106f32e7eSjoerg 
AddToWorkList(const MemRegion * R)76206f32e7eSjoerg   bool AddToWorkList(const MemRegion *R) {
76306f32e7eSjoerg     return static_cast<DERIVED*>(this)->AddToWorkList(R);
76406f32e7eSjoerg   }
76506f32e7eSjoerg 
RunWorkList()76606f32e7eSjoerg   void RunWorkList() {
76706f32e7eSjoerg     while (!WL.empty()) {
76806f32e7eSjoerg       WorkListElement E = WL.pop_back_val();
76906f32e7eSjoerg       const MemRegion *BaseR = E;
77006f32e7eSjoerg 
77106f32e7eSjoerg       static_cast<DERIVED*>(this)->VisitCluster(BaseR, getCluster(BaseR));
77206f32e7eSjoerg     }
77306f32e7eSjoerg   }
77406f32e7eSjoerg 
VisitAddedToCluster(const MemRegion * baseR,const ClusterBindings & C)77506f32e7eSjoerg   void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C) {}
VisitCluster(const MemRegion * baseR,const ClusterBindings * C)77606f32e7eSjoerg   void VisitCluster(const MemRegion *baseR, const ClusterBindings *C) {}
77706f32e7eSjoerg 
VisitCluster(const MemRegion * BaseR,const ClusterBindings * C,bool Flag)77806f32e7eSjoerg   void VisitCluster(const MemRegion *BaseR, const ClusterBindings *C,
77906f32e7eSjoerg                     bool Flag) {
78006f32e7eSjoerg     static_cast<DERIVED*>(this)->VisitCluster(BaseR, C);
78106f32e7eSjoerg   }
78206f32e7eSjoerg };
78306f32e7eSjoerg }
78406f32e7eSjoerg 
78506f32e7eSjoerg //===----------------------------------------------------------------------===//
78606f32e7eSjoerg // Binding invalidation.
78706f32e7eSjoerg //===----------------------------------------------------------------------===//
78806f32e7eSjoerg 
scanReachableSymbols(Store S,const MemRegion * R,ScanReachableSymbols & Callbacks)78906f32e7eSjoerg bool RegionStoreManager::scanReachableSymbols(Store S, const MemRegion *R,
79006f32e7eSjoerg                                               ScanReachableSymbols &Callbacks) {
79106f32e7eSjoerg   assert(R == R->getBaseRegion() && "Should only be called for base regions");
79206f32e7eSjoerg   RegionBindingsRef B = getRegionBindings(S);
79306f32e7eSjoerg   const ClusterBindings *Cluster = B.lookup(R);
79406f32e7eSjoerg 
79506f32e7eSjoerg   if (!Cluster)
79606f32e7eSjoerg     return true;
79706f32e7eSjoerg 
79806f32e7eSjoerg   for (ClusterBindings::iterator RI = Cluster->begin(), RE = Cluster->end();
79906f32e7eSjoerg        RI != RE; ++RI) {
80006f32e7eSjoerg     if (!Callbacks.scan(RI.getData()))
80106f32e7eSjoerg       return false;
80206f32e7eSjoerg   }
80306f32e7eSjoerg 
80406f32e7eSjoerg   return true;
80506f32e7eSjoerg }
80606f32e7eSjoerg 
isUnionField(const FieldRegion * FR)80706f32e7eSjoerg static inline bool isUnionField(const FieldRegion *FR) {
80806f32e7eSjoerg   return FR->getDecl()->getParent()->isUnion();
80906f32e7eSjoerg }
81006f32e7eSjoerg 
81106f32e7eSjoerg typedef SmallVector<const FieldDecl *, 8> FieldVector;
81206f32e7eSjoerg 
getSymbolicOffsetFields(BindingKey K,FieldVector & Fields)81306f32e7eSjoerg static void getSymbolicOffsetFields(BindingKey K, FieldVector &Fields) {
81406f32e7eSjoerg   assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
81506f32e7eSjoerg 
81606f32e7eSjoerg   const MemRegion *Base = K.getConcreteOffsetRegion();
81706f32e7eSjoerg   const MemRegion *R = K.getRegion();
81806f32e7eSjoerg 
81906f32e7eSjoerg   while (R != Base) {
82006f32e7eSjoerg     if (const FieldRegion *FR = dyn_cast<FieldRegion>(R))
82106f32e7eSjoerg       if (!isUnionField(FR))
82206f32e7eSjoerg         Fields.push_back(FR->getDecl());
82306f32e7eSjoerg 
82406f32e7eSjoerg     R = cast<SubRegion>(R)->getSuperRegion();
82506f32e7eSjoerg   }
82606f32e7eSjoerg }
82706f32e7eSjoerg 
isCompatibleWithFields(BindingKey K,const FieldVector & Fields)82806f32e7eSjoerg static bool isCompatibleWithFields(BindingKey K, const FieldVector &Fields) {
82906f32e7eSjoerg   assert(K.hasSymbolicOffset() && "Not implemented for concrete offset keys");
83006f32e7eSjoerg 
83106f32e7eSjoerg   if (Fields.empty())
83206f32e7eSjoerg     return true;
83306f32e7eSjoerg 
83406f32e7eSjoerg   FieldVector FieldsInBindingKey;
83506f32e7eSjoerg   getSymbolicOffsetFields(K, FieldsInBindingKey);
83606f32e7eSjoerg 
83706f32e7eSjoerg   ptrdiff_t Delta = FieldsInBindingKey.size() - Fields.size();
83806f32e7eSjoerg   if (Delta >= 0)
83906f32e7eSjoerg     return std::equal(FieldsInBindingKey.begin() + Delta,
84006f32e7eSjoerg                       FieldsInBindingKey.end(),
84106f32e7eSjoerg                       Fields.begin());
84206f32e7eSjoerg   else
84306f32e7eSjoerg     return std::equal(FieldsInBindingKey.begin(), FieldsInBindingKey.end(),
84406f32e7eSjoerg                       Fields.begin() - Delta);
84506f32e7eSjoerg }
84606f32e7eSjoerg 
84706f32e7eSjoerg /// Collects all bindings in \p Cluster that may refer to bindings within
84806f32e7eSjoerg /// \p Top.
84906f32e7eSjoerg ///
85006f32e7eSjoerg /// Each binding is a pair whose \c first is the key (a BindingKey) and whose
85106f32e7eSjoerg /// \c second is the value (an SVal).
85206f32e7eSjoerg ///
85306f32e7eSjoerg /// The \p IncludeAllDefaultBindings parameter specifies whether to include
85406f32e7eSjoerg /// default bindings that may extend beyond \p Top itself, e.g. if \p Top is
85506f32e7eSjoerg /// an aggregate within a larger aggregate with a default binding.
85606f32e7eSjoerg static void
collectSubRegionBindings(SmallVectorImpl<BindingPair> & Bindings,SValBuilder & SVB,const ClusterBindings & Cluster,const SubRegion * Top,BindingKey TopKey,bool IncludeAllDefaultBindings)85706f32e7eSjoerg collectSubRegionBindings(SmallVectorImpl<BindingPair> &Bindings,
85806f32e7eSjoerg                          SValBuilder &SVB, const ClusterBindings &Cluster,
85906f32e7eSjoerg                          const SubRegion *Top, BindingKey TopKey,
86006f32e7eSjoerg                          bool IncludeAllDefaultBindings) {
86106f32e7eSjoerg   FieldVector FieldsInSymbolicSubregions;
86206f32e7eSjoerg   if (TopKey.hasSymbolicOffset()) {
86306f32e7eSjoerg     getSymbolicOffsetFields(TopKey, FieldsInSymbolicSubregions);
86406f32e7eSjoerg     Top = TopKey.getConcreteOffsetRegion();
86506f32e7eSjoerg     TopKey = BindingKey::Make(Top, BindingKey::Default);
86606f32e7eSjoerg   }
86706f32e7eSjoerg 
86806f32e7eSjoerg   // Find the length (in bits) of the region being invalidated.
86906f32e7eSjoerg   uint64_t Length = UINT64_MAX;
870*13fbcb42Sjoerg   SVal Extent = Top->getMemRegionManager().getStaticSize(Top, SVB);
87106f32e7eSjoerg   if (Optional<nonloc::ConcreteInt> ExtentCI =
87206f32e7eSjoerg           Extent.getAs<nonloc::ConcreteInt>()) {
87306f32e7eSjoerg     const llvm::APSInt &ExtentInt = ExtentCI->getValue();
87406f32e7eSjoerg     assert(ExtentInt.isNonNegative() || ExtentInt.isUnsigned());
87506f32e7eSjoerg     // Extents are in bytes but region offsets are in bits. Be careful!
87606f32e7eSjoerg     Length = ExtentInt.getLimitedValue() * SVB.getContext().getCharWidth();
87706f32e7eSjoerg   } else if (const FieldRegion *FR = dyn_cast<FieldRegion>(Top)) {
87806f32e7eSjoerg     if (FR->getDecl()->isBitField())
87906f32e7eSjoerg       Length = FR->getDecl()->getBitWidthValue(SVB.getContext());
88006f32e7eSjoerg   }
88106f32e7eSjoerg 
88206f32e7eSjoerg   for (ClusterBindings::iterator I = Cluster.begin(), E = Cluster.end();
88306f32e7eSjoerg        I != E; ++I) {
88406f32e7eSjoerg     BindingKey NextKey = I.getKey();
88506f32e7eSjoerg     if (NextKey.getRegion() == TopKey.getRegion()) {
88606f32e7eSjoerg       // FIXME: This doesn't catch the case where we're really invalidating a
88706f32e7eSjoerg       // region with a symbolic offset. Example:
88806f32e7eSjoerg       //      R: points[i].y
88906f32e7eSjoerg       //   Next: points[0].x
89006f32e7eSjoerg 
89106f32e7eSjoerg       if (NextKey.getOffset() > TopKey.getOffset() &&
89206f32e7eSjoerg           NextKey.getOffset() - TopKey.getOffset() < Length) {
89306f32e7eSjoerg         // Case 1: The next binding is inside the region we're invalidating.
89406f32e7eSjoerg         // Include it.
89506f32e7eSjoerg         Bindings.push_back(*I);
89606f32e7eSjoerg 
89706f32e7eSjoerg       } else if (NextKey.getOffset() == TopKey.getOffset()) {
89806f32e7eSjoerg         // Case 2: The next binding is at the same offset as the region we're
89906f32e7eSjoerg         // invalidating. In this case, we need to leave default bindings alone,
90006f32e7eSjoerg         // since they may be providing a default value for a regions beyond what
90106f32e7eSjoerg         // we're invalidating.
90206f32e7eSjoerg         // FIXME: This is probably incorrect; consider invalidating an outer
90306f32e7eSjoerg         // struct whose first field is bound to a LazyCompoundVal.
90406f32e7eSjoerg         if (IncludeAllDefaultBindings || NextKey.isDirect())
90506f32e7eSjoerg           Bindings.push_back(*I);
90606f32e7eSjoerg       }
90706f32e7eSjoerg 
90806f32e7eSjoerg     } else if (NextKey.hasSymbolicOffset()) {
90906f32e7eSjoerg       const MemRegion *Base = NextKey.getConcreteOffsetRegion();
91006f32e7eSjoerg       if (Top->isSubRegionOf(Base) && Top != Base) {
91106f32e7eSjoerg         // Case 3: The next key is symbolic and we just changed something within
91206f32e7eSjoerg         // its concrete region. We don't know if the binding is still valid, so
91306f32e7eSjoerg         // we'll be conservative and include it.
91406f32e7eSjoerg         if (IncludeAllDefaultBindings || NextKey.isDirect())
91506f32e7eSjoerg           if (isCompatibleWithFields(NextKey, FieldsInSymbolicSubregions))
91606f32e7eSjoerg             Bindings.push_back(*I);
91706f32e7eSjoerg       } else if (const SubRegion *BaseSR = dyn_cast<SubRegion>(Base)) {
91806f32e7eSjoerg         // Case 4: The next key is symbolic, but we changed a known
91906f32e7eSjoerg         // super-region. In this case the binding is certainly included.
92006f32e7eSjoerg         if (BaseSR->isSubRegionOf(Top))
92106f32e7eSjoerg           if (isCompatibleWithFields(NextKey, FieldsInSymbolicSubregions))
92206f32e7eSjoerg             Bindings.push_back(*I);
92306f32e7eSjoerg       }
92406f32e7eSjoerg     }
92506f32e7eSjoerg   }
92606f32e7eSjoerg }
92706f32e7eSjoerg 
92806f32e7eSjoerg static void
collectSubRegionBindings(SmallVectorImpl<BindingPair> & Bindings,SValBuilder & SVB,const ClusterBindings & Cluster,const SubRegion * Top,bool IncludeAllDefaultBindings)92906f32e7eSjoerg collectSubRegionBindings(SmallVectorImpl<BindingPair> &Bindings,
93006f32e7eSjoerg                          SValBuilder &SVB, const ClusterBindings &Cluster,
93106f32e7eSjoerg                          const SubRegion *Top, bool IncludeAllDefaultBindings) {
93206f32e7eSjoerg   collectSubRegionBindings(Bindings, SVB, Cluster, Top,
93306f32e7eSjoerg                            BindingKey::Make(Top, BindingKey::Default),
93406f32e7eSjoerg                            IncludeAllDefaultBindings);
93506f32e7eSjoerg }
93606f32e7eSjoerg 
93706f32e7eSjoerg RegionBindingsRef
removeSubRegionBindings(RegionBindingsConstRef B,const SubRegion * Top)93806f32e7eSjoerg RegionStoreManager::removeSubRegionBindings(RegionBindingsConstRef B,
93906f32e7eSjoerg                                             const SubRegion *Top) {
94006f32e7eSjoerg   BindingKey TopKey = BindingKey::Make(Top, BindingKey::Default);
94106f32e7eSjoerg   const MemRegion *ClusterHead = TopKey.getBaseRegion();
94206f32e7eSjoerg 
94306f32e7eSjoerg   if (Top == ClusterHead) {
94406f32e7eSjoerg     // We can remove an entire cluster's bindings all in one go.
94506f32e7eSjoerg     return B.remove(Top);
94606f32e7eSjoerg   }
94706f32e7eSjoerg 
94806f32e7eSjoerg   const ClusterBindings *Cluster = B.lookup(ClusterHead);
94906f32e7eSjoerg   if (!Cluster) {
95006f32e7eSjoerg     // If we're invalidating a region with a symbolic offset, we need to make
95106f32e7eSjoerg     // sure we don't treat the base region as uninitialized anymore.
95206f32e7eSjoerg     if (TopKey.hasSymbolicOffset()) {
95306f32e7eSjoerg       const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
95406f32e7eSjoerg       return B.addBinding(Concrete, BindingKey::Default, UnknownVal());
95506f32e7eSjoerg     }
95606f32e7eSjoerg     return B;
95706f32e7eSjoerg   }
95806f32e7eSjoerg 
95906f32e7eSjoerg   SmallVector<BindingPair, 32> Bindings;
96006f32e7eSjoerg   collectSubRegionBindings(Bindings, svalBuilder, *Cluster, Top, TopKey,
96106f32e7eSjoerg                            /*IncludeAllDefaultBindings=*/false);
96206f32e7eSjoerg 
96306f32e7eSjoerg   ClusterBindingsRef Result(*Cluster, CBFactory);
96406f32e7eSjoerg   for (SmallVectorImpl<BindingPair>::const_iterator I = Bindings.begin(),
96506f32e7eSjoerg                                                     E = Bindings.end();
96606f32e7eSjoerg        I != E; ++I)
96706f32e7eSjoerg     Result = Result.remove(I->first);
96806f32e7eSjoerg 
96906f32e7eSjoerg   // If we're invalidating a region with a symbolic offset, we need to make sure
97006f32e7eSjoerg   // we don't treat the base region as uninitialized anymore.
97106f32e7eSjoerg   // FIXME: This isn't very precise; see the example in
97206f32e7eSjoerg   // collectSubRegionBindings.
97306f32e7eSjoerg   if (TopKey.hasSymbolicOffset()) {
97406f32e7eSjoerg     const SubRegion *Concrete = TopKey.getConcreteOffsetRegion();
97506f32e7eSjoerg     Result = Result.add(BindingKey::Make(Concrete, BindingKey::Default),
97606f32e7eSjoerg                         UnknownVal());
97706f32e7eSjoerg   }
97806f32e7eSjoerg 
97906f32e7eSjoerg   if (Result.isEmpty())
98006f32e7eSjoerg     return B.remove(ClusterHead);
98106f32e7eSjoerg   return B.add(ClusterHead, Result.asImmutableMap());
98206f32e7eSjoerg }
98306f32e7eSjoerg 
98406f32e7eSjoerg namespace {
98506f32e7eSjoerg class InvalidateRegionsWorker : public ClusterAnalysis<InvalidateRegionsWorker>
98606f32e7eSjoerg {
98706f32e7eSjoerg   const Expr *Ex;
98806f32e7eSjoerg   unsigned Count;
98906f32e7eSjoerg   const LocationContext *LCtx;
99006f32e7eSjoerg   InvalidatedSymbols &IS;
99106f32e7eSjoerg   RegionAndSymbolInvalidationTraits &ITraits;
99206f32e7eSjoerg   StoreManager::InvalidatedRegions *Regions;
99306f32e7eSjoerg   GlobalsFilterKind GlobalsFilter;
99406f32e7eSjoerg public:
InvalidateRegionsWorker(RegionStoreManager & rm,ProgramStateManager & stateMgr,RegionBindingsRef b,const Expr * ex,unsigned count,const LocationContext * lctx,InvalidatedSymbols & is,RegionAndSymbolInvalidationTraits & ITraitsIn,StoreManager::InvalidatedRegions * r,GlobalsFilterKind GFK)99506f32e7eSjoerg   InvalidateRegionsWorker(RegionStoreManager &rm,
99606f32e7eSjoerg                           ProgramStateManager &stateMgr,
99706f32e7eSjoerg                           RegionBindingsRef b,
99806f32e7eSjoerg                           const Expr *ex, unsigned count,
99906f32e7eSjoerg                           const LocationContext *lctx,
100006f32e7eSjoerg                           InvalidatedSymbols &is,
100106f32e7eSjoerg                           RegionAndSymbolInvalidationTraits &ITraitsIn,
100206f32e7eSjoerg                           StoreManager::InvalidatedRegions *r,
100306f32e7eSjoerg                           GlobalsFilterKind GFK)
100406f32e7eSjoerg      : ClusterAnalysis<InvalidateRegionsWorker>(rm, stateMgr, b),
100506f32e7eSjoerg        Ex(ex), Count(count), LCtx(lctx), IS(is), ITraits(ITraitsIn), Regions(r),
100606f32e7eSjoerg        GlobalsFilter(GFK) {}
100706f32e7eSjoerg 
100806f32e7eSjoerg   void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);
100906f32e7eSjoerg   void VisitBinding(SVal V);
101006f32e7eSjoerg 
101106f32e7eSjoerg   using ClusterAnalysis::AddToWorkList;
101206f32e7eSjoerg 
101306f32e7eSjoerg   bool AddToWorkList(const MemRegion *R);
101406f32e7eSjoerg 
101506f32e7eSjoerg   /// Returns true if all clusters in the memory space for \p Base should be
101606f32e7eSjoerg   /// be invalidated.
101706f32e7eSjoerg   bool includeEntireMemorySpace(const MemRegion *Base);
101806f32e7eSjoerg 
101906f32e7eSjoerg   /// Returns true if the memory space of the given region is one of the global
102006f32e7eSjoerg   /// regions specially included at the start of invalidation.
102106f32e7eSjoerg   bool isInitiallyIncludedGlobalRegion(const MemRegion *R);
102206f32e7eSjoerg };
102306f32e7eSjoerg }
102406f32e7eSjoerg 
AddToWorkList(const MemRegion * R)102506f32e7eSjoerg bool InvalidateRegionsWorker::AddToWorkList(const MemRegion *R) {
102606f32e7eSjoerg   bool doNotInvalidateSuperRegion = ITraits.hasTrait(
102706f32e7eSjoerg       R, RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
102806f32e7eSjoerg   const MemRegion *BaseR = doNotInvalidateSuperRegion ? R : R->getBaseRegion();
102906f32e7eSjoerg   return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
103006f32e7eSjoerg }
103106f32e7eSjoerg 
VisitBinding(SVal V)103206f32e7eSjoerg void InvalidateRegionsWorker::VisitBinding(SVal V) {
103306f32e7eSjoerg   // A symbol?  Mark it touched by the invalidation.
103406f32e7eSjoerg   if (SymbolRef Sym = V.getAsSymbol())
103506f32e7eSjoerg     IS.insert(Sym);
103606f32e7eSjoerg 
103706f32e7eSjoerg   if (const MemRegion *R = V.getAsRegion()) {
103806f32e7eSjoerg     AddToWorkList(R);
103906f32e7eSjoerg     return;
104006f32e7eSjoerg   }
104106f32e7eSjoerg 
104206f32e7eSjoerg   // Is it a LazyCompoundVal?  All references get invalidated as well.
104306f32e7eSjoerg   if (Optional<nonloc::LazyCompoundVal> LCS =
104406f32e7eSjoerg           V.getAs<nonloc::LazyCompoundVal>()) {
104506f32e7eSjoerg 
104606f32e7eSjoerg     const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
104706f32e7eSjoerg 
104806f32e7eSjoerg     for (RegionStoreManager::SValListTy::const_iterator I = Vals.begin(),
104906f32e7eSjoerg                                                         E = Vals.end();
105006f32e7eSjoerg          I != E; ++I)
105106f32e7eSjoerg       VisitBinding(*I);
105206f32e7eSjoerg 
105306f32e7eSjoerg     return;
105406f32e7eSjoerg   }
105506f32e7eSjoerg }
105606f32e7eSjoerg 
VisitCluster(const MemRegion * baseR,const ClusterBindings * C)105706f32e7eSjoerg void InvalidateRegionsWorker::VisitCluster(const MemRegion *baseR,
105806f32e7eSjoerg                                            const ClusterBindings *C) {
105906f32e7eSjoerg 
106006f32e7eSjoerg   bool PreserveRegionsContents =
106106f32e7eSjoerg       ITraits.hasTrait(baseR,
106206f32e7eSjoerg                        RegionAndSymbolInvalidationTraits::TK_PreserveContents);
106306f32e7eSjoerg 
106406f32e7eSjoerg   if (C) {
106506f32e7eSjoerg     for (ClusterBindings::iterator I = C->begin(), E = C->end(); I != E; ++I)
106606f32e7eSjoerg       VisitBinding(I.getData());
106706f32e7eSjoerg 
106806f32e7eSjoerg     // Invalidate regions contents.
106906f32e7eSjoerg     if (!PreserveRegionsContents)
107006f32e7eSjoerg       B = B.remove(baseR);
107106f32e7eSjoerg   }
107206f32e7eSjoerg 
107306f32e7eSjoerg   if (const auto *TO = dyn_cast<TypedValueRegion>(baseR)) {
107406f32e7eSjoerg     if (const auto *RD = TO->getValueType()->getAsCXXRecordDecl()) {
107506f32e7eSjoerg 
107606f32e7eSjoerg       // Lambdas can affect all static local variables without explicitly
107706f32e7eSjoerg       // capturing those.
107806f32e7eSjoerg       // We invalidate all static locals referenced inside the lambda body.
107906f32e7eSjoerg       if (RD->isLambda() && RD->getLambdaCallOperator()->getBody()) {
108006f32e7eSjoerg         using namespace ast_matchers;
108106f32e7eSjoerg 
108206f32e7eSjoerg         const char *DeclBind = "DeclBind";
108306f32e7eSjoerg         StatementMatcher RefToStatic = stmt(hasDescendant(declRefExpr(
108406f32e7eSjoerg               to(varDecl(hasStaticStorageDuration()).bind(DeclBind)))));
108506f32e7eSjoerg         auto Matches =
108606f32e7eSjoerg             match(RefToStatic, *RD->getLambdaCallOperator()->getBody(),
108706f32e7eSjoerg                   RD->getASTContext());
108806f32e7eSjoerg 
108906f32e7eSjoerg         for (BoundNodes &Match : Matches) {
109006f32e7eSjoerg           auto *VD = Match.getNodeAs<VarDecl>(DeclBind);
109106f32e7eSjoerg           const VarRegion *ToInvalidate =
109206f32e7eSjoerg               RM.getRegionManager().getVarRegion(VD, LCtx);
109306f32e7eSjoerg           AddToWorkList(ToInvalidate);
109406f32e7eSjoerg         }
109506f32e7eSjoerg       }
109606f32e7eSjoerg     }
109706f32e7eSjoerg   }
109806f32e7eSjoerg 
109906f32e7eSjoerg   // BlockDataRegion?  If so, invalidate captured variables that are passed
110006f32e7eSjoerg   // by reference.
110106f32e7eSjoerg   if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(baseR)) {
110206f32e7eSjoerg     for (BlockDataRegion::referenced_vars_iterator
110306f32e7eSjoerg          BI = BR->referenced_vars_begin(), BE = BR->referenced_vars_end() ;
110406f32e7eSjoerg          BI != BE; ++BI) {
110506f32e7eSjoerg       const VarRegion *VR = BI.getCapturedRegion();
110606f32e7eSjoerg       const VarDecl *VD = VR->getDecl();
110706f32e7eSjoerg       if (VD->hasAttr<BlocksAttr>() || !VD->hasLocalStorage()) {
110806f32e7eSjoerg         AddToWorkList(VR);
110906f32e7eSjoerg       }
111006f32e7eSjoerg       else if (Loc::isLocType(VR->getValueType())) {
111106f32e7eSjoerg         // Map the current bindings to a Store to retrieve the value
111206f32e7eSjoerg         // of the binding.  If that binding itself is a region, we should
111306f32e7eSjoerg         // invalidate that region.  This is because a block may capture
111406f32e7eSjoerg         // a pointer value, but the thing pointed by that pointer may
111506f32e7eSjoerg         // get invalidated.
111606f32e7eSjoerg         SVal V = RM.getBinding(B, loc::MemRegionVal(VR));
111706f32e7eSjoerg         if (Optional<Loc> L = V.getAs<Loc>()) {
111806f32e7eSjoerg           if (const MemRegion *LR = L->getAsRegion())
111906f32e7eSjoerg             AddToWorkList(LR);
112006f32e7eSjoerg         }
112106f32e7eSjoerg       }
112206f32e7eSjoerg     }
112306f32e7eSjoerg     return;
112406f32e7eSjoerg   }
112506f32e7eSjoerg 
112606f32e7eSjoerg   // Symbolic region?
112706f32e7eSjoerg   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR))
112806f32e7eSjoerg     IS.insert(SR->getSymbol());
112906f32e7eSjoerg 
113006f32e7eSjoerg   // Nothing else should be done in the case when we preserve regions context.
113106f32e7eSjoerg   if (PreserveRegionsContents)
113206f32e7eSjoerg     return;
113306f32e7eSjoerg 
113406f32e7eSjoerg   // Otherwise, we have a normal data region. Record that we touched the region.
113506f32e7eSjoerg   if (Regions)
113606f32e7eSjoerg     Regions->push_back(baseR);
113706f32e7eSjoerg 
113806f32e7eSjoerg   if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
113906f32e7eSjoerg     // Invalidate the region by setting its default value to
114006f32e7eSjoerg     // conjured symbol. The type of the symbol is irrelevant.
114106f32e7eSjoerg     DefinedOrUnknownSVal V =
114206f32e7eSjoerg       svalBuilder.conjureSymbolVal(baseR, Ex, LCtx, Ctx.IntTy, Count);
114306f32e7eSjoerg     B = B.addBinding(baseR, BindingKey::Default, V);
114406f32e7eSjoerg     return;
114506f32e7eSjoerg   }
114606f32e7eSjoerg 
114706f32e7eSjoerg   if (!baseR->isBoundable())
114806f32e7eSjoerg     return;
114906f32e7eSjoerg 
115006f32e7eSjoerg   const TypedValueRegion *TR = cast<TypedValueRegion>(baseR);
115106f32e7eSjoerg   QualType T = TR->getValueType();
115206f32e7eSjoerg 
115306f32e7eSjoerg   if (isInitiallyIncludedGlobalRegion(baseR)) {
115406f32e7eSjoerg     // If the region is a global and we are invalidating all globals,
115506f32e7eSjoerg     // erasing the entry is good enough.  This causes all globals to be lazily
115606f32e7eSjoerg     // symbolicated from the same base symbol.
115706f32e7eSjoerg     return;
115806f32e7eSjoerg   }
115906f32e7eSjoerg 
116006f32e7eSjoerg   if (T->isRecordType()) {
116106f32e7eSjoerg     // Invalidate the region by setting its default value to
116206f32e7eSjoerg     // conjured symbol. The type of the symbol is irrelevant.
116306f32e7eSjoerg     DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(baseR, Ex, LCtx,
116406f32e7eSjoerg                                                           Ctx.IntTy, Count);
116506f32e7eSjoerg     B = B.addBinding(baseR, BindingKey::Default, V);
116606f32e7eSjoerg     return;
116706f32e7eSjoerg   }
116806f32e7eSjoerg 
116906f32e7eSjoerg   if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
117006f32e7eSjoerg     bool doNotInvalidateSuperRegion = ITraits.hasTrait(
117106f32e7eSjoerg         baseR,
117206f32e7eSjoerg         RegionAndSymbolInvalidationTraits::TK_DoNotInvalidateSuperRegion);
117306f32e7eSjoerg 
117406f32e7eSjoerg     if (doNotInvalidateSuperRegion) {
117506f32e7eSjoerg       // We are not doing blank invalidation of the whole array region so we
117606f32e7eSjoerg       // have to manually invalidate each elements.
117706f32e7eSjoerg       Optional<uint64_t> NumElements;
117806f32e7eSjoerg 
117906f32e7eSjoerg       // Compute lower and upper offsets for region within array.
118006f32e7eSjoerg       if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT))
118106f32e7eSjoerg         NumElements = CAT->getSize().getZExtValue();
118206f32e7eSjoerg       if (!NumElements) // We are not dealing with a constant size array
118306f32e7eSjoerg         goto conjure_default;
118406f32e7eSjoerg       QualType ElementTy = AT->getElementType();
118506f32e7eSjoerg       uint64_t ElemSize = Ctx.getTypeSize(ElementTy);
118606f32e7eSjoerg       const RegionOffset &RO = baseR->getAsOffset();
118706f32e7eSjoerg       const MemRegion *SuperR = baseR->getBaseRegion();
118806f32e7eSjoerg       if (RO.hasSymbolicOffset()) {
118906f32e7eSjoerg         // If base region has a symbolic offset,
119006f32e7eSjoerg         // we revert to invalidating the super region.
119106f32e7eSjoerg         if (SuperR)
119206f32e7eSjoerg           AddToWorkList(SuperR);
119306f32e7eSjoerg         goto conjure_default;
119406f32e7eSjoerg       }
119506f32e7eSjoerg 
119606f32e7eSjoerg       uint64_t LowerOffset = RO.getOffset();
119706f32e7eSjoerg       uint64_t UpperOffset = LowerOffset + *NumElements * ElemSize;
119806f32e7eSjoerg       bool UpperOverflow = UpperOffset < LowerOffset;
119906f32e7eSjoerg 
120006f32e7eSjoerg       // Invalidate regions which are within array boundaries,
120106f32e7eSjoerg       // or have a symbolic offset.
120206f32e7eSjoerg       if (!SuperR)
120306f32e7eSjoerg         goto conjure_default;
120406f32e7eSjoerg 
120506f32e7eSjoerg       const ClusterBindings *C = B.lookup(SuperR);
120606f32e7eSjoerg       if (!C)
120706f32e7eSjoerg         goto conjure_default;
120806f32e7eSjoerg 
120906f32e7eSjoerg       for (ClusterBindings::iterator I = C->begin(), E = C->end(); I != E;
121006f32e7eSjoerg            ++I) {
121106f32e7eSjoerg         const BindingKey &BK = I.getKey();
121206f32e7eSjoerg         Optional<uint64_t> ROffset =
121306f32e7eSjoerg             BK.hasSymbolicOffset() ? Optional<uint64_t>() : BK.getOffset();
121406f32e7eSjoerg 
121506f32e7eSjoerg         // Check offset is not symbolic and within array's boundaries.
121606f32e7eSjoerg         // Handles arrays of 0 elements and of 0-sized elements as well.
121706f32e7eSjoerg         if (!ROffset ||
121806f32e7eSjoerg             ((*ROffset >= LowerOffset && *ROffset < UpperOffset) ||
121906f32e7eSjoerg              (UpperOverflow &&
122006f32e7eSjoerg               (*ROffset >= LowerOffset || *ROffset < UpperOffset)) ||
122106f32e7eSjoerg              (LowerOffset == UpperOffset && *ROffset == LowerOffset))) {
122206f32e7eSjoerg           B = B.removeBinding(I.getKey());
122306f32e7eSjoerg           // Bound symbolic regions need to be invalidated for dead symbol
122406f32e7eSjoerg           // detection.
122506f32e7eSjoerg           SVal V = I.getData();
122606f32e7eSjoerg           const MemRegion *R = V.getAsRegion();
122706f32e7eSjoerg           if (R && isa<SymbolicRegion>(R))
122806f32e7eSjoerg             VisitBinding(V);
122906f32e7eSjoerg         }
123006f32e7eSjoerg       }
123106f32e7eSjoerg     }
123206f32e7eSjoerg   conjure_default:
123306f32e7eSjoerg       // Set the default value of the array to conjured symbol.
123406f32e7eSjoerg     DefinedOrUnknownSVal V =
123506f32e7eSjoerg     svalBuilder.conjureSymbolVal(baseR, Ex, LCtx,
123606f32e7eSjoerg                                      AT->getElementType(), Count);
123706f32e7eSjoerg     B = B.addBinding(baseR, BindingKey::Default, V);
123806f32e7eSjoerg     return;
123906f32e7eSjoerg   }
124006f32e7eSjoerg 
124106f32e7eSjoerg   DefinedOrUnknownSVal V = svalBuilder.conjureSymbolVal(baseR, Ex, LCtx,
124206f32e7eSjoerg                                                         T,Count);
124306f32e7eSjoerg   assert(SymbolManager::canSymbolicate(T) || V.isUnknown());
124406f32e7eSjoerg   B = B.addBinding(baseR, BindingKey::Direct, V);
124506f32e7eSjoerg }
124606f32e7eSjoerg 
isInitiallyIncludedGlobalRegion(const MemRegion * R)124706f32e7eSjoerg bool InvalidateRegionsWorker::isInitiallyIncludedGlobalRegion(
124806f32e7eSjoerg     const MemRegion *R) {
124906f32e7eSjoerg   switch (GlobalsFilter) {
125006f32e7eSjoerg   case GFK_None:
125106f32e7eSjoerg     return false;
125206f32e7eSjoerg   case GFK_SystemOnly:
125306f32e7eSjoerg     return isa<GlobalSystemSpaceRegion>(R->getMemorySpace());
125406f32e7eSjoerg   case GFK_All:
125506f32e7eSjoerg     return isa<NonStaticGlobalSpaceRegion>(R->getMemorySpace());
125606f32e7eSjoerg   }
125706f32e7eSjoerg 
125806f32e7eSjoerg   llvm_unreachable("unknown globals filter");
125906f32e7eSjoerg }
126006f32e7eSjoerg 
includeEntireMemorySpace(const MemRegion * Base)126106f32e7eSjoerg bool InvalidateRegionsWorker::includeEntireMemorySpace(const MemRegion *Base) {
126206f32e7eSjoerg   if (isInitiallyIncludedGlobalRegion(Base))
126306f32e7eSjoerg     return true;
126406f32e7eSjoerg 
126506f32e7eSjoerg   const MemSpaceRegion *MemSpace = Base->getMemorySpace();
126606f32e7eSjoerg   return ITraits.hasTrait(MemSpace,
126706f32e7eSjoerg                           RegionAndSymbolInvalidationTraits::TK_EntireMemSpace);
126806f32e7eSjoerg }
126906f32e7eSjoerg 
127006f32e7eSjoerg RegionBindingsRef
invalidateGlobalRegion(MemRegion::Kind K,const Expr * Ex,unsigned Count,const LocationContext * LCtx,RegionBindingsRef B,InvalidatedRegions * Invalidated)127106f32e7eSjoerg RegionStoreManager::invalidateGlobalRegion(MemRegion::Kind K,
127206f32e7eSjoerg                                            const Expr *Ex,
127306f32e7eSjoerg                                            unsigned Count,
127406f32e7eSjoerg                                            const LocationContext *LCtx,
127506f32e7eSjoerg                                            RegionBindingsRef B,
127606f32e7eSjoerg                                            InvalidatedRegions *Invalidated) {
127706f32e7eSjoerg   // Bind the globals memory space to a new symbol that we will use to derive
127806f32e7eSjoerg   // the bindings for all globals.
127906f32e7eSjoerg   const GlobalsSpaceRegion *GS = MRMgr.getGlobalsRegion(K);
128006f32e7eSjoerg   SVal V = svalBuilder.conjureSymbolVal(/* symbolTag = */ (const void*) GS, Ex, LCtx,
128106f32e7eSjoerg                                         /* type does not matter */ Ctx.IntTy,
128206f32e7eSjoerg                                         Count);
128306f32e7eSjoerg 
128406f32e7eSjoerg   B = B.removeBinding(GS)
128506f32e7eSjoerg        .addBinding(BindingKey::Make(GS, BindingKey::Default), V);
128606f32e7eSjoerg 
128706f32e7eSjoerg   // Even if there are no bindings in the global scope, we still need to
128806f32e7eSjoerg   // record that we touched it.
128906f32e7eSjoerg   if (Invalidated)
129006f32e7eSjoerg     Invalidated->push_back(GS);
129106f32e7eSjoerg 
129206f32e7eSjoerg   return B;
129306f32e7eSjoerg }
129406f32e7eSjoerg 
populateWorkList(InvalidateRegionsWorker & W,ArrayRef<SVal> Values,InvalidatedRegions * TopLevelRegions)129506f32e7eSjoerg void RegionStoreManager::populateWorkList(InvalidateRegionsWorker &W,
129606f32e7eSjoerg                                           ArrayRef<SVal> Values,
129706f32e7eSjoerg                                           InvalidatedRegions *TopLevelRegions) {
129806f32e7eSjoerg   for (ArrayRef<SVal>::iterator I = Values.begin(),
129906f32e7eSjoerg                                 E = Values.end(); I != E; ++I) {
130006f32e7eSjoerg     SVal V = *I;
130106f32e7eSjoerg     if (Optional<nonloc::LazyCompoundVal> LCS =
130206f32e7eSjoerg         V.getAs<nonloc::LazyCompoundVal>()) {
130306f32e7eSjoerg 
130406f32e7eSjoerg       const SValListTy &Vals = getInterestingValues(*LCS);
130506f32e7eSjoerg 
130606f32e7eSjoerg       for (SValListTy::const_iterator I = Vals.begin(),
130706f32e7eSjoerg                                       E = Vals.end(); I != E; ++I) {
130806f32e7eSjoerg         // Note: the last argument is false here because these are
130906f32e7eSjoerg         // non-top-level regions.
131006f32e7eSjoerg         if (const MemRegion *R = (*I).getAsRegion())
131106f32e7eSjoerg           W.AddToWorkList(R);
131206f32e7eSjoerg       }
131306f32e7eSjoerg       continue;
131406f32e7eSjoerg     }
131506f32e7eSjoerg 
131606f32e7eSjoerg     if (const MemRegion *R = V.getAsRegion()) {
131706f32e7eSjoerg       if (TopLevelRegions)
131806f32e7eSjoerg         TopLevelRegions->push_back(R);
131906f32e7eSjoerg       W.AddToWorkList(R);
132006f32e7eSjoerg       continue;
132106f32e7eSjoerg     }
132206f32e7eSjoerg   }
132306f32e7eSjoerg }
132406f32e7eSjoerg 
132506f32e7eSjoerg StoreRef
invalidateRegions(Store store,ArrayRef<SVal> Values,const Expr * Ex,unsigned Count,const LocationContext * LCtx,const CallEvent * Call,InvalidatedSymbols & IS,RegionAndSymbolInvalidationTraits & ITraits,InvalidatedRegions * TopLevelRegions,InvalidatedRegions * Invalidated)132606f32e7eSjoerg RegionStoreManager::invalidateRegions(Store store,
132706f32e7eSjoerg                                      ArrayRef<SVal> Values,
132806f32e7eSjoerg                                      const Expr *Ex, unsigned Count,
132906f32e7eSjoerg                                      const LocationContext *LCtx,
133006f32e7eSjoerg                                      const CallEvent *Call,
133106f32e7eSjoerg                                      InvalidatedSymbols &IS,
133206f32e7eSjoerg                                      RegionAndSymbolInvalidationTraits &ITraits,
133306f32e7eSjoerg                                      InvalidatedRegions *TopLevelRegions,
133406f32e7eSjoerg                                      InvalidatedRegions *Invalidated) {
133506f32e7eSjoerg   GlobalsFilterKind GlobalsFilter;
133606f32e7eSjoerg   if (Call) {
133706f32e7eSjoerg     if (Call->isInSystemHeader())
133806f32e7eSjoerg       GlobalsFilter = GFK_SystemOnly;
133906f32e7eSjoerg     else
134006f32e7eSjoerg       GlobalsFilter = GFK_All;
134106f32e7eSjoerg   } else {
134206f32e7eSjoerg     GlobalsFilter = GFK_None;
134306f32e7eSjoerg   }
134406f32e7eSjoerg 
134506f32e7eSjoerg   RegionBindingsRef B = getRegionBindings(store);
134606f32e7eSjoerg   InvalidateRegionsWorker W(*this, StateMgr, B, Ex, Count, LCtx, IS, ITraits,
134706f32e7eSjoerg                             Invalidated, GlobalsFilter);
134806f32e7eSjoerg 
134906f32e7eSjoerg   // Scan the bindings and generate the clusters.
135006f32e7eSjoerg   W.GenerateClusters();
135106f32e7eSjoerg 
135206f32e7eSjoerg   // Add the regions to the worklist.
135306f32e7eSjoerg   populateWorkList(W, Values, TopLevelRegions);
135406f32e7eSjoerg 
135506f32e7eSjoerg   W.RunWorkList();
135606f32e7eSjoerg 
135706f32e7eSjoerg   // Return the new bindings.
135806f32e7eSjoerg   B = W.getRegionBindings();
135906f32e7eSjoerg 
136006f32e7eSjoerg   // For calls, determine which global regions should be invalidated and
136106f32e7eSjoerg   // invalidate them. (Note that function-static and immutable globals are never
136206f32e7eSjoerg   // invalidated by this.)
136306f32e7eSjoerg   // TODO: This could possibly be more precise with modules.
136406f32e7eSjoerg   switch (GlobalsFilter) {
136506f32e7eSjoerg   case GFK_All:
136606f32e7eSjoerg     B = invalidateGlobalRegion(MemRegion::GlobalInternalSpaceRegionKind,
136706f32e7eSjoerg                                Ex, Count, LCtx, B, Invalidated);
136806f32e7eSjoerg     LLVM_FALLTHROUGH;
136906f32e7eSjoerg   case GFK_SystemOnly:
137006f32e7eSjoerg     B = invalidateGlobalRegion(MemRegion::GlobalSystemSpaceRegionKind,
137106f32e7eSjoerg                                Ex, Count, LCtx, B, Invalidated);
137206f32e7eSjoerg     LLVM_FALLTHROUGH;
137306f32e7eSjoerg   case GFK_None:
137406f32e7eSjoerg     break;
137506f32e7eSjoerg   }
137606f32e7eSjoerg 
137706f32e7eSjoerg   return StoreRef(B.asStore(), *this);
137806f32e7eSjoerg }
137906f32e7eSjoerg 
138006f32e7eSjoerg //===----------------------------------------------------------------------===//
138106f32e7eSjoerg // Location and region casting.
138206f32e7eSjoerg //===----------------------------------------------------------------------===//
138306f32e7eSjoerg 
138406f32e7eSjoerg /// ArrayToPointer - Emulates the "decay" of an array to a pointer
138506f32e7eSjoerg ///  type.  'Array' represents the lvalue of the array being decayed
138606f32e7eSjoerg ///  to a pointer, and the returned SVal represents the decayed
138706f32e7eSjoerg ///  version of that lvalue (i.e., a pointer to the first element of
138806f32e7eSjoerg ///  the array).  This is called by ExprEngine when evaluating casts
138906f32e7eSjoerg ///  from arrays to pointers.
ArrayToPointer(Loc Array,QualType T)139006f32e7eSjoerg SVal RegionStoreManager::ArrayToPointer(Loc Array, QualType T) {
139106f32e7eSjoerg   if (Array.getAs<loc::ConcreteInt>())
139206f32e7eSjoerg     return Array;
139306f32e7eSjoerg 
139406f32e7eSjoerg   if (!Array.getAs<loc::MemRegionVal>())
139506f32e7eSjoerg     return UnknownVal();
139606f32e7eSjoerg 
139706f32e7eSjoerg   const SubRegion *R =
139806f32e7eSjoerg       cast<SubRegion>(Array.castAs<loc::MemRegionVal>().getRegion());
139906f32e7eSjoerg   NonLoc ZeroIdx = svalBuilder.makeZeroArrayIndex();
140006f32e7eSjoerg   return loc::MemRegionVal(MRMgr.getElementRegion(T, ZeroIdx, R, Ctx));
140106f32e7eSjoerg }
140206f32e7eSjoerg 
140306f32e7eSjoerg //===----------------------------------------------------------------------===//
140406f32e7eSjoerg // Loading values from regions.
140506f32e7eSjoerg //===----------------------------------------------------------------------===//
140606f32e7eSjoerg 
getBinding(RegionBindingsConstRef B,Loc L,QualType T)140706f32e7eSjoerg SVal RegionStoreManager::getBinding(RegionBindingsConstRef B, Loc L, QualType T) {
140806f32e7eSjoerg   assert(!L.getAs<UnknownVal>() && "location unknown");
140906f32e7eSjoerg   assert(!L.getAs<UndefinedVal>() && "location undefined");
141006f32e7eSjoerg 
141106f32e7eSjoerg   // For access to concrete addresses, return UnknownVal.  Checks
141206f32e7eSjoerg   // for null dereferences (and similar errors) are done by checkers, not
141306f32e7eSjoerg   // the Store.
141406f32e7eSjoerg   // FIXME: We can consider lazily symbolicating such memory, but we really
141506f32e7eSjoerg   // should defer this when we can reason easily about symbolicating arrays
141606f32e7eSjoerg   // of bytes.
141706f32e7eSjoerg   if (L.getAs<loc::ConcreteInt>()) {
141806f32e7eSjoerg     return UnknownVal();
141906f32e7eSjoerg   }
142006f32e7eSjoerg   if (!L.getAs<loc::MemRegionVal>()) {
142106f32e7eSjoerg     return UnknownVal();
142206f32e7eSjoerg   }
142306f32e7eSjoerg 
142406f32e7eSjoerg   const MemRegion *MR = L.castAs<loc::MemRegionVal>().getRegion();
142506f32e7eSjoerg 
142606f32e7eSjoerg   if (isa<BlockDataRegion>(MR)) {
142706f32e7eSjoerg     return UnknownVal();
142806f32e7eSjoerg   }
142906f32e7eSjoerg 
143006f32e7eSjoerg   if (!isa<TypedValueRegion>(MR)) {
143106f32e7eSjoerg     if (T.isNull()) {
143206f32e7eSjoerg       if (const TypedRegion *TR = dyn_cast<TypedRegion>(MR))
143306f32e7eSjoerg         T = TR->getLocationType()->getPointeeType();
143406f32e7eSjoerg       else if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
143506f32e7eSjoerg         T = SR->getSymbol()->getType()->getPointeeType();
143606f32e7eSjoerg     }
143706f32e7eSjoerg     assert(!T.isNull() && "Unable to auto-detect binding type!");
143806f32e7eSjoerg     assert(!T->isVoidType() && "Attempting to dereference a void pointer!");
143906f32e7eSjoerg     MR = GetElementZeroRegion(cast<SubRegion>(MR), T);
144006f32e7eSjoerg   } else {
144106f32e7eSjoerg     T = cast<TypedValueRegion>(MR)->getValueType();
144206f32e7eSjoerg   }
144306f32e7eSjoerg 
144406f32e7eSjoerg   // FIXME: Perhaps this method should just take a 'const MemRegion*' argument
144506f32e7eSjoerg   //  instead of 'Loc', and have the other Loc cases handled at a higher level.
144606f32e7eSjoerg   const TypedValueRegion *R = cast<TypedValueRegion>(MR);
144706f32e7eSjoerg   QualType RTy = R->getValueType();
144806f32e7eSjoerg 
144906f32e7eSjoerg   // FIXME: we do not yet model the parts of a complex type, so treat the
145006f32e7eSjoerg   // whole thing as "unknown".
145106f32e7eSjoerg   if (RTy->isAnyComplexType())
145206f32e7eSjoerg     return UnknownVal();
145306f32e7eSjoerg 
145406f32e7eSjoerg   // FIXME: We should eventually handle funny addressing.  e.g.:
145506f32e7eSjoerg   //
145606f32e7eSjoerg   //   int x = ...;
145706f32e7eSjoerg   //   int *p = &x;
145806f32e7eSjoerg   //   char *q = (char*) p;
145906f32e7eSjoerg   //   char c = *q;  // returns the first byte of 'x'.
146006f32e7eSjoerg   //
146106f32e7eSjoerg   // Such funny addressing will occur due to layering of regions.
146206f32e7eSjoerg   if (RTy->isStructureOrClassType())
146306f32e7eSjoerg     return getBindingForStruct(B, R);
146406f32e7eSjoerg 
146506f32e7eSjoerg   // FIXME: Handle unions.
146606f32e7eSjoerg   if (RTy->isUnionType())
146706f32e7eSjoerg     return createLazyBinding(B, R);
146806f32e7eSjoerg 
146906f32e7eSjoerg   if (RTy->isArrayType()) {
147006f32e7eSjoerg     if (RTy->isConstantArrayType())
147106f32e7eSjoerg       return getBindingForArray(B, R);
147206f32e7eSjoerg     else
147306f32e7eSjoerg       return UnknownVal();
147406f32e7eSjoerg   }
147506f32e7eSjoerg 
147606f32e7eSjoerg   // FIXME: handle Vector types.
147706f32e7eSjoerg   if (RTy->isVectorType())
147806f32e7eSjoerg     return UnknownVal();
147906f32e7eSjoerg 
148006f32e7eSjoerg   if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
1481*13fbcb42Sjoerg     return svalBuilder.evalCast(getBindingForField(B, FR), T, QualType{});
148206f32e7eSjoerg 
148306f32e7eSjoerg   if (const ElementRegion* ER = dyn_cast<ElementRegion>(R)) {
148406f32e7eSjoerg     // FIXME: Here we actually perform an implicit conversion from the loaded
148506f32e7eSjoerg     // value to the element type.  Eventually we want to compose these values
148606f32e7eSjoerg     // more intelligently.  For example, an 'element' can encompass multiple
148706f32e7eSjoerg     // bound regions (e.g., several bound bytes), or could be a subset of
148806f32e7eSjoerg     // a larger value.
1489*13fbcb42Sjoerg     return svalBuilder.evalCast(getBindingForElement(B, ER), T, QualType{});
149006f32e7eSjoerg   }
149106f32e7eSjoerg 
149206f32e7eSjoerg   if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
149306f32e7eSjoerg     // FIXME: Here we actually perform an implicit conversion from the loaded
149406f32e7eSjoerg     // value to the ivar type.  What we should model is stores to ivars
149506f32e7eSjoerg     // that blow past the extent of the ivar.  If the address of the ivar is
149606f32e7eSjoerg     // reinterpretted, it is possible we stored a different value that could
149706f32e7eSjoerg     // fit within the ivar.  Either we need to cast these when storing them
149806f32e7eSjoerg     // or reinterpret them lazily (as we do here).
1499*13fbcb42Sjoerg     return svalBuilder.evalCast(getBindingForObjCIvar(B, IVR), T, QualType{});
150006f32e7eSjoerg   }
150106f32e7eSjoerg 
150206f32e7eSjoerg   if (const VarRegion *VR = dyn_cast<VarRegion>(R)) {
150306f32e7eSjoerg     // FIXME: Here we actually perform an implicit conversion from the loaded
150406f32e7eSjoerg     // value to the variable type.  What we should model is stores to variables
150506f32e7eSjoerg     // that blow past the extent of the variable.  If the address of the
150606f32e7eSjoerg     // variable is reinterpretted, it is possible we stored a different value
150706f32e7eSjoerg     // that could fit within the variable.  Either we need to cast these when
150806f32e7eSjoerg     // storing them or reinterpret them lazily (as we do here).
1509*13fbcb42Sjoerg     return svalBuilder.evalCast(getBindingForVar(B, VR), T, QualType{});
151006f32e7eSjoerg   }
151106f32e7eSjoerg 
151206f32e7eSjoerg   const SVal *V = B.lookup(R, BindingKey::Direct);
151306f32e7eSjoerg 
151406f32e7eSjoerg   // Check if the region has a binding.
151506f32e7eSjoerg   if (V)
151606f32e7eSjoerg     return *V;
151706f32e7eSjoerg 
151806f32e7eSjoerg   // The location does not have a bound value.  This means that it has
151906f32e7eSjoerg   // the value it had upon its creation and/or entry to the analyzed
152006f32e7eSjoerg   // function/method.  These are either symbolic values or 'undefined'.
152106f32e7eSjoerg   if (R->hasStackNonParametersStorage()) {
152206f32e7eSjoerg     // All stack variables are considered to have undefined values
152306f32e7eSjoerg     // upon creation.  All heap allocated blocks are considered to
152406f32e7eSjoerg     // have undefined values as well unless they are explicitly bound
152506f32e7eSjoerg     // to specific values.
152606f32e7eSjoerg     return UndefinedVal();
152706f32e7eSjoerg   }
152806f32e7eSjoerg 
152906f32e7eSjoerg   // All other values are symbolic.
153006f32e7eSjoerg   return svalBuilder.getRegionValueSymbolVal(R);
153106f32e7eSjoerg }
153206f32e7eSjoerg 
getUnderlyingType(const SubRegion * R)153306f32e7eSjoerg static QualType getUnderlyingType(const SubRegion *R) {
153406f32e7eSjoerg   QualType RegionTy;
153506f32e7eSjoerg   if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(R))
153606f32e7eSjoerg     RegionTy = TVR->getValueType();
153706f32e7eSjoerg 
153806f32e7eSjoerg   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R))
153906f32e7eSjoerg     RegionTy = SR->getSymbol()->getType();
154006f32e7eSjoerg 
154106f32e7eSjoerg   return RegionTy;
154206f32e7eSjoerg }
154306f32e7eSjoerg 
154406f32e7eSjoerg /// Checks to see if store \p B has a lazy binding for region \p R.
154506f32e7eSjoerg ///
154606f32e7eSjoerg /// If \p AllowSubregionBindings is \c false, a lazy binding will be rejected
154706f32e7eSjoerg /// if there are additional bindings within \p R.
154806f32e7eSjoerg ///
154906f32e7eSjoerg /// Note that unlike RegionStoreManager::findLazyBinding, this will not search
155006f32e7eSjoerg /// for lazy bindings for super-regions of \p R.
155106f32e7eSjoerg static Optional<nonloc::LazyCompoundVal>
getExistingLazyBinding(SValBuilder & SVB,RegionBindingsConstRef B,const SubRegion * R,bool AllowSubregionBindings)155206f32e7eSjoerg getExistingLazyBinding(SValBuilder &SVB, RegionBindingsConstRef B,
155306f32e7eSjoerg                        const SubRegion *R, bool AllowSubregionBindings) {
155406f32e7eSjoerg   Optional<SVal> V = B.getDefaultBinding(R);
155506f32e7eSjoerg   if (!V)
155606f32e7eSjoerg     return None;
155706f32e7eSjoerg 
155806f32e7eSjoerg   Optional<nonloc::LazyCompoundVal> LCV = V->getAs<nonloc::LazyCompoundVal>();
155906f32e7eSjoerg   if (!LCV)
156006f32e7eSjoerg     return None;
156106f32e7eSjoerg 
156206f32e7eSjoerg   // If the LCV is for a subregion, the types might not match, and we shouldn't
156306f32e7eSjoerg   // reuse the binding.
156406f32e7eSjoerg   QualType RegionTy = getUnderlyingType(R);
156506f32e7eSjoerg   if (!RegionTy.isNull() &&
156606f32e7eSjoerg       !RegionTy->isVoidPointerType()) {
156706f32e7eSjoerg     QualType SourceRegionTy = LCV->getRegion()->getValueType();
156806f32e7eSjoerg     if (!SVB.getContext().hasSameUnqualifiedType(RegionTy, SourceRegionTy))
156906f32e7eSjoerg       return None;
157006f32e7eSjoerg   }
157106f32e7eSjoerg 
157206f32e7eSjoerg   if (!AllowSubregionBindings) {
157306f32e7eSjoerg     // If there are any other bindings within this region, we shouldn't reuse
157406f32e7eSjoerg     // the top-level binding.
157506f32e7eSjoerg     SmallVector<BindingPair, 16> Bindings;
157606f32e7eSjoerg     collectSubRegionBindings(Bindings, SVB, *B.lookup(R->getBaseRegion()), R,
157706f32e7eSjoerg                              /*IncludeAllDefaultBindings=*/true);
157806f32e7eSjoerg     if (Bindings.size() > 1)
157906f32e7eSjoerg       return None;
158006f32e7eSjoerg   }
158106f32e7eSjoerg 
158206f32e7eSjoerg   return *LCV;
158306f32e7eSjoerg }
158406f32e7eSjoerg 
158506f32e7eSjoerg 
158606f32e7eSjoerg std::pair<Store, const SubRegion *>
findLazyBinding(RegionBindingsConstRef B,const SubRegion * R,const SubRegion * originalRegion)158706f32e7eSjoerg RegionStoreManager::findLazyBinding(RegionBindingsConstRef B,
158806f32e7eSjoerg                                    const SubRegion *R,
158906f32e7eSjoerg                                    const SubRegion *originalRegion) {
159006f32e7eSjoerg   if (originalRegion != R) {
159106f32e7eSjoerg     if (Optional<nonloc::LazyCompoundVal> V =
159206f32e7eSjoerg           getExistingLazyBinding(svalBuilder, B, R, true))
159306f32e7eSjoerg       return std::make_pair(V->getStore(), V->getRegion());
159406f32e7eSjoerg   }
159506f32e7eSjoerg 
159606f32e7eSjoerg   typedef std::pair<Store, const SubRegion *> StoreRegionPair;
159706f32e7eSjoerg   StoreRegionPair Result = StoreRegionPair();
159806f32e7eSjoerg 
159906f32e7eSjoerg   if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
160006f32e7eSjoerg     Result = findLazyBinding(B, cast<SubRegion>(ER->getSuperRegion()),
160106f32e7eSjoerg                              originalRegion);
160206f32e7eSjoerg 
160306f32e7eSjoerg     if (Result.second)
160406f32e7eSjoerg       Result.second = MRMgr.getElementRegionWithSuper(ER, Result.second);
160506f32e7eSjoerg 
160606f32e7eSjoerg   } else if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
160706f32e7eSjoerg     Result = findLazyBinding(B, cast<SubRegion>(FR->getSuperRegion()),
160806f32e7eSjoerg                                        originalRegion);
160906f32e7eSjoerg 
161006f32e7eSjoerg     if (Result.second)
161106f32e7eSjoerg       Result.second = MRMgr.getFieldRegionWithSuper(FR, Result.second);
161206f32e7eSjoerg 
161306f32e7eSjoerg   } else if (const CXXBaseObjectRegion *BaseReg =
161406f32e7eSjoerg                dyn_cast<CXXBaseObjectRegion>(R)) {
161506f32e7eSjoerg     // C++ base object region is another kind of region that we should blast
161606f32e7eSjoerg     // through to look for lazy compound value. It is like a field region.
161706f32e7eSjoerg     Result = findLazyBinding(B, cast<SubRegion>(BaseReg->getSuperRegion()),
161806f32e7eSjoerg                              originalRegion);
161906f32e7eSjoerg 
162006f32e7eSjoerg     if (Result.second)
162106f32e7eSjoerg       Result.second = MRMgr.getCXXBaseObjectRegionWithSuper(BaseReg,
162206f32e7eSjoerg                                                             Result.second);
162306f32e7eSjoerg   }
162406f32e7eSjoerg 
162506f32e7eSjoerg   return Result;
162606f32e7eSjoerg }
162706f32e7eSjoerg 
getBindingForElement(RegionBindingsConstRef B,const ElementRegion * R)162806f32e7eSjoerg SVal RegionStoreManager::getBindingForElement(RegionBindingsConstRef B,
162906f32e7eSjoerg                                               const ElementRegion* R) {
163006f32e7eSjoerg   // Check if the region has a binding.
163106f32e7eSjoerg   if (const Optional<SVal> &V = B.getDirectBinding(R))
163206f32e7eSjoerg     return *V;
163306f32e7eSjoerg 
163406f32e7eSjoerg   const MemRegion* superR = R->getSuperRegion();
163506f32e7eSjoerg 
163606f32e7eSjoerg   // Check if the region is an element region of a string literal.
163706f32e7eSjoerg   if (const StringRegion *StrR = dyn_cast<StringRegion>(superR)) {
163806f32e7eSjoerg     // FIXME: Handle loads from strings where the literal is treated as
163906f32e7eSjoerg     // an integer, e.g., *((unsigned int*)"hello")
164006f32e7eSjoerg     QualType T = Ctx.getAsArrayType(StrR->getValueType())->getElementType();
164106f32e7eSjoerg     if (!Ctx.hasSameUnqualifiedType(T, R->getElementType()))
164206f32e7eSjoerg       return UnknownVal();
164306f32e7eSjoerg 
164406f32e7eSjoerg     const StringLiteral *Str = StrR->getStringLiteral();
164506f32e7eSjoerg     SVal Idx = R->getIndex();
164606f32e7eSjoerg     if (Optional<nonloc::ConcreteInt> CI = Idx.getAs<nonloc::ConcreteInt>()) {
164706f32e7eSjoerg       int64_t i = CI->getValue().getSExtValue();
164806f32e7eSjoerg       // Abort on string underrun.  This can be possible by arbitrary
164906f32e7eSjoerg       // clients of getBindingForElement().
165006f32e7eSjoerg       if (i < 0)
165106f32e7eSjoerg         return UndefinedVal();
165206f32e7eSjoerg       int64_t length = Str->getLength();
165306f32e7eSjoerg       // Technically, only i == length is guaranteed to be null.
165406f32e7eSjoerg       // However, such overflows should be caught before reaching this point;
165506f32e7eSjoerg       // the only time such an access would be made is if a string literal was
165606f32e7eSjoerg       // used to initialize a larger array.
165706f32e7eSjoerg       char c = (i >= length) ? '\0' : Str->getCodeUnit(i);
165806f32e7eSjoerg       return svalBuilder.makeIntVal(c, T);
165906f32e7eSjoerg     }
166006f32e7eSjoerg   } else if (const VarRegion *VR = dyn_cast<VarRegion>(superR)) {
166106f32e7eSjoerg     // Check if the containing array has an initialized value that we can trust.
166206f32e7eSjoerg     // We can trust a const value or a value of a global initializer in main().
166306f32e7eSjoerg     const VarDecl *VD = VR->getDecl();
166406f32e7eSjoerg     if (VD->getType().isConstQualified() ||
166506f32e7eSjoerg         R->getElementType().isConstQualified() ||
166606f32e7eSjoerg         (B.isMainAnalysis() && VD->hasGlobalStorage())) {
166706f32e7eSjoerg       if (const Expr *Init = VD->getAnyInitializer()) {
166806f32e7eSjoerg         if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
166906f32e7eSjoerg           // The array index has to be known.
167006f32e7eSjoerg           if (auto CI = R->getIndex().getAs<nonloc::ConcreteInt>()) {
167106f32e7eSjoerg             int64_t i = CI->getValue().getSExtValue();
167206f32e7eSjoerg             // If it is known that the index is out of bounds, we can return
167306f32e7eSjoerg             // an undefined value.
167406f32e7eSjoerg             if (i < 0)
167506f32e7eSjoerg               return UndefinedVal();
167606f32e7eSjoerg 
167706f32e7eSjoerg             if (auto CAT = Ctx.getAsConstantArrayType(VD->getType()))
167806f32e7eSjoerg               if (CAT->getSize().sle(i))
167906f32e7eSjoerg                 return UndefinedVal();
168006f32e7eSjoerg 
168106f32e7eSjoerg             // If there is a list, but no init, it must be zero.
168206f32e7eSjoerg             if (i >= InitList->getNumInits())
168306f32e7eSjoerg               return svalBuilder.makeZeroVal(R->getElementType());
168406f32e7eSjoerg 
168506f32e7eSjoerg             if (const Expr *ElemInit = InitList->getInit(i))
168606f32e7eSjoerg               if (Optional<SVal> V = svalBuilder.getConstantVal(ElemInit))
168706f32e7eSjoerg                 return *V;
168806f32e7eSjoerg           }
168906f32e7eSjoerg         }
169006f32e7eSjoerg       }
169106f32e7eSjoerg     }
169206f32e7eSjoerg   }
169306f32e7eSjoerg 
169406f32e7eSjoerg   // Check for loads from a code text region.  For such loads, just give up.
169506f32e7eSjoerg   if (isa<CodeTextRegion>(superR))
169606f32e7eSjoerg     return UnknownVal();
169706f32e7eSjoerg 
169806f32e7eSjoerg   // Handle the case where we are indexing into a larger scalar object.
169906f32e7eSjoerg   // For example, this handles:
170006f32e7eSjoerg   //   int x = ...
170106f32e7eSjoerg   //   char *y = &x;
170206f32e7eSjoerg   //   return *y;
170306f32e7eSjoerg   // FIXME: This is a hack, and doesn't do anything really intelligent yet.
170406f32e7eSjoerg   const RegionRawOffset &O = R->getAsArrayOffset();
170506f32e7eSjoerg 
170606f32e7eSjoerg   // If we cannot reason about the offset, return an unknown value.
170706f32e7eSjoerg   if (!O.getRegion())
170806f32e7eSjoerg     return UnknownVal();
170906f32e7eSjoerg 
171006f32e7eSjoerg   if (const TypedValueRegion *baseR =
171106f32e7eSjoerg         dyn_cast_or_null<TypedValueRegion>(O.getRegion())) {
171206f32e7eSjoerg     QualType baseT = baseR->getValueType();
171306f32e7eSjoerg     if (baseT->isScalarType()) {
171406f32e7eSjoerg       QualType elemT = R->getElementType();
171506f32e7eSjoerg       if (elemT->isScalarType()) {
171606f32e7eSjoerg         if (Ctx.getTypeSizeInChars(baseT) >= Ctx.getTypeSizeInChars(elemT)) {
171706f32e7eSjoerg           if (const Optional<SVal> &V = B.getDirectBinding(superR)) {
171806f32e7eSjoerg             if (SymbolRef parentSym = V->getAsSymbol())
171906f32e7eSjoerg               return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
172006f32e7eSjoerg 
172106f32e7eSjoerg             if (V->isUnknownOrUndef())
172206f32e7eSjoerg               return *V;
172306f32e7eSjoerg             // Other cases: give up.  We are indexing into a larger object
172406f32e7eSjoerg             // that has some value, but we don't know how to handle that yet.
172506f32e7eSjoerg             return UnknownVal();
172606f32e7eSjoerg           }
172706f32e7eSjoerg         }
172806f32e7eSjoerg       }
172906f32e7eSjoerg     }
173006f32e7eSjoerg   }
173106f32e7eSjoerg   return getBindingForFieldOrElementCommon(B, R, R->getElementType());
173206f32e7eSjoerg }
173306f32e7eSjoerg 
getBindingForField(RegionBindingsConstRef B,const FieldRegion * R)173406f32e7eSjoerg SVal RegionStoreManager::getBindingForField(RegionBindingsConstRef B,
173506f32e7eSjoerg                                             const FieldRegion* R) {
173606f32e7eSjoerg 
173706f32e7eSjoerg   // Check if the region has a binding.
173806f32e7eSjoerg   if (const Optional<SVal> &V = B.getDirectBinding(R))
173906f32e7eSjoerg     return *V;
174006f32e7eSjoerg 
174106f32e7eSjoerg   // Is the field declared constant and has an in-class initializer?
174206f32e7eSjoerg   const FieldDecl *FD = R->getDecl();
174306f32e7eSjoerg   QualType Ty = FD->getType();
174406f32e7eSjoerg   if (Ty.isConstQualified())
174506f32e7eSjoerg     if (const Expr *Init = FD->getInClassInitializer())
174606f32e7eSjoerg       if (Optional<SVal> V = svalBuilder.getConstantVal(Init))
174706f32e7eSjoerg         return *V;
174806f32e7eSjoerg 
174906f32e7eSjoerg   // If the containing record was initialized, try to get its constant value.
175006f32e7eSjoerg   const MemRegion* superR = R->getSuperRegion();
175106f32e7eSjoerg   if (const auto *VR = dyn_cast<VarRegion>(superR)) {
175206f32e7eSjoerg     const VarDecl *VD = VR->getDecl();
175306f32e7eSjoerg     QualType RecordVarTy = VD->getType();
175406f32e7eSjoerg     unsigned Index = FD->getFieldIndex();
175506f32e7eSjoerg     // Either the record variable or the field has an initializer that we can
175606f32e7eSjoerg     // trust. We trust initializers of constants and, additionally, respect
175706f32e7eSjoerg     // initializers of globals when analyzing main().
175806f32e7eSjoerg     if (RecordVarTy.isConstQualified() || Ty.isConstQualified() ||
175906f32e7eSjoerg         (B.isMainAnalysis() && VD->hasGlobalStorage()))
176006f32e7eSjoerg       if (const Expr *Init = VD->getAnyInitializer())
176106f32e7eSjoerg         if (const auto *InitList = dyn_cast<InitListExpr>(Init)) {
176206f32e7eSjoerg           if (Index < InitList->getNumInits()) {
176306f32e7eSjoerg             if (const Expr *FieldInit = InitList->getInit(Index))
176406f32e7eSjoerg               if (Optional<SVal> V = svalBuilder.getConstantVal(FieldInit))
176506f32e7eSjoerg                 return *V;
176606f32e7eSjoerg           } else {
176706f32e7eSjoerg             return svalBuilder.makeZeroVal(Ty);
176806f32e7eSjoerg           }
176906f32e7eSjoerg         }
177006f32e7eSjoerg   }
177106f32e7eSjoerg 
177206f32e7eSjoerg   return getBindingForFieldOrElementCommon(B, R, Ty);
177306f32e7eSjoerg }
177406f32e7eSjoerg 
177506f32e7eSjoerg Optional<SVal>
getBindingForDerivedDefaultValue(RegionBindingsConstRef B,const MemRegion * superR,const TypedValueRegion * R,QualType Ty)177606f32e7eSjoerg RegionStoreManager::getBindingForDerivedDefaultValue(RegionBindingsConstRef B,
177706f32e7eSjoerg                                                      const MemRegion *superR,
177806f32e7eSjoerg                                                      const TypedValueRegion *R,
177906f32e7eSjoerg                                                      QualType Ty) {
178006f32e7eSjoerg 
178106f32e7eSjoerg   if (const Optional<SVal> &D = B.getDefaultBinding(superR)) {
178206f32e7eSjoerg     const SVal &val = D.getValue();
178306f32e7eSjoerg     if (SymbolRef parentSym = val.getAsSymbol())
178406f32e7eSjoerg       return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
178506f32e7eSjoerg 
178606f32e7eSjoerg     if (val.isZeroConstant())
178706f32e7eSjoerg       return svalBuilder.makeZeroVal(Ty);
178806f32e7eSjoerg 
178906f32e7eSjoerg     if (val.isUnknownOrUndef())
179006f32e7eSjoerg       return val;
179106f32e7eSjoerg 
179206f32e7eSjoerg     // Lazy bindings are usually handled through getExistingLazyBinding().
179306f32e7eSjoerg     // We should unify these two code paths at some point.
179406f32e7eSjoerg     if (val.getAs<nonloc::LazyCompoundVal>() ||
179506f32e7eSjoerg         val.getAs<nonloc::CompoundVal>())
179606f32e7eSjoerg       return val;
179706f32e7eSjoerg 
179806f32e7eSjoerg     llvm_unreachable("Unknown default value");
179906f32e7eSjoerg   }
180006f32e7eSjoerg 
180106f32e7eSjoerg   return None;
180206f32e7eSjoerg }
180306f32e7eSjoerg 
getLazyBinding(const SubRegion * LazyBindingRegion,RegionBindingsRef LazyBinding)180406f32e7eSjoerg SVal RegionStoreManager::getLazyBinding(const SubRegion *LazyBindingRegion,
180506f32e7eSjoerg                                         RegionBindingsRef LazyBinding) {
180606f32e7eSjoerg   SVal Result;
180706f32e7eSjoerg   if (const ElementRegion *ER = dyn_cast<ElementRegion>(LazyBindingRegion))
180806f32e7eSjoerg     Result = getBindingForElement(LazyBinding, ER);
180906f32e7eSjoerg   else
181006f32e7eSjoerg     Result = getBindingForField(LazyBinding,
181106f32e7eSjoerg                                 cast<FieldRegion>(LazyBindingRegion));
181206f32e7eSjoerg 
181306f32e7eSjoerg   // FIXME: This is a hack to deal with RegionStore's inability to distinguish a
181406f32e7eSjoerg   // default value for /part/ of an aggregate from a default value for the
181506f32e7eSjoerg   // /entire/ aggregate. The most common case of this is when struct Outer
181606f32e7eSjoerg   // has as its first member a struct Inner, which is copied in from a stack
181706f32e7eSjoerg   // variable. In this case, even if the Outer's default value is symbolic, 0,
181806f32e7eSjoerg   // or unknown, it gets overridden by the Inner's default value of undefined.
181906f32e7eSjoerg   //
182006f32e7eSjoerg   // This is a general problem -- if the Inner is zero-initialized, the Outer
182106f32e7eSjoerg   // will now look zero-initialized. The proper way to solve this is with a
182206f32e7eSjoerg   // new version of RegionStore that tracks the extent of a binding as well
182306f32e7eSjoerg   // as the offset.
182406f32e7eSjoerg   //
182506f32e7eSjoerg   // This hack only takes care of the undefined case because that can very
182606f32e7eSjoerg   // quickly result in a warning.
182706f32e7eSjoerg   if (Result.isUndef())
182806f32e7eSjoerg     Result = UnknownVal();
182906f32e7eSjoerg 
183006f32e7eSjoerg   return Result;
183106f32e7eSjoerg }
183206f32e7eSjoerg 
183306f32e7eSjoerg SVal
getBindingForFieldOrElementCommon(RegionBindingsConstRef B,const TypedValueRegion * R,QualType Ty)183406f32e7eSjoerg RegionStoreManager::getBindingForFieldOrElementCommon(RegionBindingsConstRef B,
183506f32e7eSjoerg                                                       const TypedValueRegion *R,
183606f32e7eSjoerg                                                       QualType Ty) {
183706f32e7eSjoerg 
183806f32e7eSjoerg   // At this point we have already checked in either getBindingForElement or
183906f32e7eSjoerg   // getBindingForField if 'R' has a direct binding.
184006f32e7eSjoerg 
184106f32e7eSjoerg   // Lazy binding?
184206f32e7eSjoerg   Store lazyBindingStore = nullptr;
184306f32e7eSjoerg   const SubRegion *lazyBindingRegion = nullptr;
184406f32e7eSjoerg   std::tie(lazyBindingStore, lazyBindingRegion) = findLazyBinding(B, R, R);
184506f32e7eSjoerg   if (lazyBindingRegion)
184606f32e7eSjoerg     return getLazyBinding(lazyBindingRegion,
184706f32e7eSjoerg                           getRegionBindings(lazyBindingStore));
184806f32e7eSjoerg 
184906f32e7eSjoerg   // Record whether or not we see a symbolic index.  That can completely
185006f32e7eSjoerg   // be out of scope of our lookup.
185106f32e7eSjoerg   bool hasSymbolicIndex = false;
185206f32e7eSjoerg 
185306f32e7eSjoerg   // FIXME: This is a hack to deal with RegionStore's inability to distinguish a
185406f32e7eSjoerg   // default value for /part/ of an aggregate from a default value for the
185506f32e7eSjoerg   // /entire/ aggregate. The most common case of this is when struct Outer
185606f32e7eSjoerg   // has as its first member a struct Inner, which is copied in from a stack
185706f32e7eSjoerg   // variable. In this case, even if the Outer's default value is symbolic, 0,
185806f32e7eSjoerg   // or unknown, it gets overridden by the Inner's default value of undefined.
185906f32e7eSjoerg   //
186006f32e7eSjoerg   // This is a general problem -- if the Inner is zero-initialized, the Outer
186106f32e7eSjoerg   // will now look zero-initialized. The proper way to solve this is with a
186206f32e7eSjoerg   // new version of RegionStore that tracks the extent of a binding as well
186306f32e7eSjoerg   // as the offset.
186406f32e7eSjoerg   //
186506f32e7eSjoerg   // This hack only takes care of the undefined case because that can very
186606f32e7eSjoerg   // quickly result in a warning.
186706f32e7eSjoerg   bool hasPartialLazyBinding = false;
186806f32e7eSjoerg 
186906f32e7eSjoerg   const SubRegion *SR = R;
187006f32e7eSjoerg   while (SR) {
187106f32e7eSjoerg     const MemRegion *Base = SR->getSuperRegion();
187206f32e7eSjoerg     if (Optional<SVal> D = getBindingForDerivedDefaultValue(B, Base, R, Ty)) {
187306f32e7eSjoerg       if (D->getAs<nonloc::LazyCompoundVal>()) {
187406f32e7eSjoerg         hasPartialLazyBinding = true;
187506f32e7eSjoerg         break;
187606f32e7eSjoerg       }
187706f32e7eSjoerg 
187806f32e7eSjoerg       return *D;
187906f32e7eSjoerg     }
188006f32e7eSjoerg 
188106f32e7eSjoerg     if (const ElementRegion *ER = dyn_cast<ElementRegion>(Base)) {
188206f32e7eSjoerg       NonLoc index = ER->getIndex();
188306f32e7eSjoerg       if (!index.isConstant())
188406f32e7eSjoerg         hasSymbolicIndex = true;
188506f32e7eSjoerg     }
188606f32e7eSjoerg 
188706f32e7eSjoerg     // If our super region is a field or element itself, walk up the region
188806f32e7eSjoerg     // hierarchy to see if there is a default value installed in an ancestor.
188906f32e7eSjoerg     SR = dyn_cast<SubRegion>(Base);
189006f32e7eSjoerg   }
189106f32e7eSjoerg 
189206f32e7eSjoerg   if (R->hasStackNonParametersStorage()) {
189306f32e7eSjoerg     if (isa<ElementRegion>(R)) {
189406f32e7eSjoerg       // Currently we don't reason specially about Clang-style vectors.  Check
189506f32e7eSjoerg       // if superR is a vector and if so return Unknown.
189606f32e7eSjoerg       if (const TypedValueRegion *typedSuperR =
189706f32e7eSjoerg             dyn_cast<TypedValueRegion>(R->getSuperRegion())) {
189806f32e7eSjoerg         if (typedSuperR->getValueType()->isVectorType())
189906f32e7eSjoerg           return UnknownVal();
190006f32e7eSjoerg       }
190106f32e7eSjoerg     }
190206f32e7eSjoerg 
190306f32e7eSjoerg     // FIXME: We also need to take ElementRegions with symbolic indexes into
190406f32e7eSjoerg     // account.  This case handles both directly accessing an ElementRegion
190506f32e7eSjoerg     // with a symbolic offset, but also fields within an element with
190606f32e7eSjoerg     // a symbolic offset.
190706f32e7eSjoerg     if (hasSymbolicIndex)
190806f32e7eSjoerg       return UnknownVal();
190906f32e7eSjoerg 
1910*13fbcb42Sjoerg     // Additionally allow introspection of a block's internal layout.
1911*13fbcb42Sjoerg     if (!hasPartialLazyBinding && !isa<BlockDataRegion>(R->getBaseRegion()))
191206f32e7eSjoerg       return UndefinedVal();
191306f32e7eSjoerg   }
191406f32e7eSjoerg 
191506f32e7eSjoerg   // All other values are symbolic.
191606f32e7eSjoerg   return svalBuilder.getRegionValueSymbolVal(R);
191706f32e7eSjoerg }
191806f32e7eSjoerg 
getBindingForObjCIvar(RegionBindingsConstRef B,const ObjCIvarRegion * R)191906f32e7eSjoerg SVal RegionStoreManager::getBindingForObjCIvar(RegionBindingsConstRef B,
192006f32e7eSjoerg                                                const ObjCIvarRegion* R) {
192106f32e7eSjoerg   // Check if the region has a binding.
192206f32e7eSjoerg   if (const Optional<SVal> &V = B.getDirectBinding(R))
192306f32e7eSjoerg     return *V;
192406f32e7eSjoerg 
192506f32e7eSjoerg   const MemRegion *superR = R->getSuperRegion();
192606f32e7eSjoerg 
192706f32e7eSjoerg   // Check if the super region has a default binding.
192806f32e7eSjoerg   if (const Optional<SVal> &V = B.getDefaultBinding(superR)) {
192906f32e7eSjoerg     if (SymbolRef parentSym = V->getAsSymbol())
193006f32e7eSjoerg       return svalBuilder.getDerivedRegionValueSymbolVal(parentSym, R);
193106f32e7eSjoerg 
193206f32e7eSjoerg     // Other cases: give up.
193306f32e7eSjoerg     return UnknownVal();
193406f32e7eSjoerg   }
193506f32e7eSjoerg 
193606f32e7eSjoerg   return getBindingForLazySymbol(R);
193706f32e7eSjoerg }
193806f32e7eSjoerg 
getBindingForVar(RegionBindingsConstRef B,const VarRegion * R)193906f32e7eSjoerg SVal RegionStoreManager::getBindingForVar(RegionBindingsConstRef B,
194006f32e7eSjoerg                                           const VarRegion *R) {
194106f32e7eSjoerg 
194206f32e7eSjoerg   // Check if the region has a binding.
194306f32e7eSjoerg   if (Optional<SVal> V = B.getDirectBinding(R))
194406f32e7eSjoerg     return *V;
194506f32e7eSjoerg 
194606f32e7eSjoerg   if (Optional<SVal> V = B.getDefaultBinding(R))
194706f32e7eSjoerg     return *V;
194806f32e7eSjoerg 
194906f32e7eSjoerg   // Lazily derive a value for the VarRegion.
195006f32e7eSjoerg   const VarDecl *VD = R->getDecl();
195106f32e7eSjoerg   const MemSpaceRegion *MS = R->getMemorySpace();
195206f32e7eSjoerg 
195306f32e7eSjoerg   // Arguments are always symbolic.
195406f32e7eSjoerg   if (isa<StackArgumentsSpaceRegion>(MS))
195506f32e7eSjoerg     return svalBuilder.getRegionValueSymbolVal(R);
195606f32e7eSjoerg 
195706f32e7eSjoerg   // Is 'VD' declared constant?  If so, retrieve the constant value.
195806f32e7eSjoerg   if (VD->getType().isConstQualified()) {
195906f32e7eSjoerg     if (const Expr *Init = VD->getAnyInitializer()) {
196006f32e7eSjoerg       if (Optional<SVal> V = svalBuilder.getConstantVal(Init))
196106f32e7eSjoerg         return *V;
196206f32e7eSjoerg 
196306f32e7eSjoerg       // If the variable is const qualified and has an initializer but
196406f32e7eSjoerg       // we couldn't evaluate initializer to a value, treat the value as
196506f32e7eSjoerg       // unknown.
196606f32e7eSjoerg       return UnknownVal();
196706f32e7eSjoerg     }
196806f32e7eSjoerg   }
196906f32e7eSjoerg 
197006f32e7eSjoerg   // This must come after the check for constants because closure-captured
197106f32e7eSjoerg   // constant variables may appear in UnknownSpaceRegion.
197206f32e7eSjoerg   if (isa<UnknownSpaceRegion>(MS))
197306f32e7eSjoerg     return svalBuilder.getRegionValueSymbolVal(R);
197406f32e7eSjoerg 
197506f32e7eSjoerg   if (isa<GlobalsSpaceRegion>(MS)) {
197606f32e7eSjoerg     QualType T = VD->getType();
197706f32e7eSjoerg 
197806f32e7eSjoerg     // If we're in main(), then global initializers have not become stale yet.
197906f32e7eSjoerg     if (B.isMainAnalysis())
198006f32e7eSjoerg       if (const Expr *Init = VD->getAnyInitializer())
198106f32e7eSjoerg         if (Optional<SVal> V = svalBuilder.getConstantVal(Init))
198206f32e7eSjoerg           return *V;
198306f32e7eSjoerg 
198406f32e7eSjoerg     // Function-scoped static variables are default-initialized to 0; if they
198506f32e7eSjoerg     // have an initializer, it would have been processed by now.
198606f32e7eSjoerg     // FIXME: This is only true when we're starting analysis from main().
198706f32e7eSjoerg     // We're losing a lot of coverage here.
198806f32e7eSjoerg     if (isa<StaticGlobalSpaceRegion>(MS))
198906f32e7eSjoerg       return svalBuilder.makeZeroVal(T);
199006f32e7eSjoerg 
199106f32e7eSjoerg     if (Optional<SVal> V = getBindingForDerivedDefaultValue(B, MS, R, T)) {
199206f32e7eSjoerg       assert(!V->getAs<nonloc::LazyCompoundVal>());
199306f32e7eSjoerg       return V.getValue();
199406f32e7eSjoerg     }
199506f32e7eSjoerg 
199606f32e7eSjoerg     return svalBuilder.getRegionValueSymbolVal(R);
199706f32e7eSjoerg   }
199806f32e7eSjoerg 
199906f32e7eSjoerg   return UndefinedVal();
200006f32e7eSjoerg }
200106f32e7eSjoerg 
getBindingForLazySymbol(const TypedValueRegion * R)200206f32e7eSjoerg SVal RegionStoreManager::getBindingForLazySymbol(const TypedValueRegion *R) {
200306f32e7eSjoerg   // All other values are symbolic.
200406f32e7eSjoerg   return svalBuilder.getRegionValueSymbolVal(R);
200506f32e7eSjoerg }
200606f32e7eSjoerg 
200706f32e7eSjoerg const RegionStoreManager::SValListTy &
getInterestingValues(nonloc::LazyCompoundVal LCV)200806f32e7eSjoerg RegionStoreManager::getInterestingValues(nonloc::LazyCompoundVal LCV) {
200906f32e7eSjoerg   // First, check the cache.
201006f32e7eSjoerg   LazyBindingsMapTy::iterator I = LazyBindingsMap.find(LCV.getCVData());
201106f32e7eSjoerg   if (I != LazyBindingsMap.end())
201206f32e7eSjoerg     return I->second;
201306f32e7eSjoerg 
201406f32e7eSjoerg   // If we don't have a list of values cached, start constructing it.
201506f32e7eSjoerg   SValListTy List;
201606f32e7eSjoerg 
201706f32e7eSjoerg   const SubRegion *LazyR = LCV.getRegion();
201806f32e7eSjoerg   RegionBindingsRef B = getRegionBindings(LCV.getStore());
201906f32e7eSjoerg 
202006f32e7eSjoerg   // If this region had /no/ bindings at the time, there are no interesting
202106f32e7eSjoerg   // values to return.
202206f32e7eSjoerg   const ClusterBindings *Cluster = B.lookup(LazyR->getBaseRegion());
202306f32e7eSjoerg   if (!Cluster)
202406f32e7eSjoerg     return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
202506f32e7eSjoerg 
202606f32e7eSjoerg   SmallVector<BindingPair, 32> Bindings;
202706f32e7eSjoerg   collectSubRegionBindings(Bindings, svalBuilder, *Cluster, LazyR,
202806f32e7eSjoerg                            /*IncludeAllDefaultBindings=*/true);
202906f32e7eSjoerg   for (SmallVectorImpl<BindingPair>::const_iterator I = Bindings.begin(),
203006f32e7eSjoerg                                                     E = Bindings.end();
203106f32e7eSjoerg        I != E; ++I) {
203206f32e7eSjoerg     SVal V = I->second;
203306f32e7eSjoerg     if (V.isUnknownOrUndef() || V.isConstant())
203406f32e7eSjoerg       continue;
203506f32e7eSjoerg 
203606f32e7eSjoerg     if (Optional<nonloc::LazyCompoundVal> InnerLCV =
203706f32e7eSjoerg             V.getAs<nonloc::LazyCompoundVal>()) {
203806f32e7eSjoerg       const SValListTy &InnerList = getInterestingValues(*InnerLCV);
203906f32e7eSjoerg       List.insert(List.end(), InnerList.begin(), InnerList.end());
204006f32e7eSjoerg       continue;
204106f32e7eSjoerg     }
204206f32e7eSjoerg 
204306f32e7eSjoerg     List.push_back(V);
204406f32e7eSjoerg   }
204506f32e7eSjoerg 
204606f32e7eSjoerg   return (LazyBindingsMap[LCV.getCVData()] = std::move(List));
204706f32e7eSjoerg }
204806f32e7eSjoerg 
createLazyBinding(RegionBindingsConstRef B,const TypedValueRegion * R)204906f32e7eSjoerg NonLoc RegionStoreManager::createLazyBinding(RegionBindingsConstRef B,
205006f32e7eSjoerg                                              const TypedValueRegion *R) {
205106f32e7eSjoerg   if (Optional<nonloc::LazyCompoundVal> V =
205206f32e7eSjoerg         getExistingLazyBinding(svalBuilder, B, R, false))
205306f32e7eSjoerg     return *V;
205406f32e7eSjoerg 
205506f32e7eSjoerg   return svalBuilder.makeLazyCompoundVal(StoreRef(B.asStore(), *this), R);
205606f32e7eSjoerg }
205706f32e7eSjoerg 
isRecordEmpty(const RecordDecl * RD)205806f32e7eSjoerg static bool isRecordEmpty(const RecordDecl *RD) {
205906f32e7eSjoerg   if (!RD->field_empty())
206006f32e7eSjoerg     return false;
206106f32e7eSjoerg   if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(RD))
206206f32e7eSjoerg     return CRD->getNumBases() == 0;
206306f32e7eSjoerg   return true;
206406f32e7eSjoerg }
206506f32e7eSjoerg 
getBindingForStruct(RegionBindingsConstRef B,const TypedValueRegion * R)206606f32e7eSjoerg SVal RegionStoreManager::getBindingForStruct(RegionBindingsConstRef B,
206706f32e7eSjoerg                                              const TypedValueRegion *R) {
206806f32e7eSjoerg   const RecordDecl *RD = R->getValueType()->castAs<RecordType>()->getDecl();
206906f32e7eSjoerg   if (!RD->getDefinition() || isRecordEmpty(RD))
207006f32e7eSjoerg     return UnknownVal();
207106f32e7eSjoerg 
207206f32e7eSjoerg   return createLazyBinding(B, R);
207306f32e7eSjoerg }
207406f32e7eSjoerg 
getBindingForArray(RegionBindingsConstRef B,const TypedValueRegion * R)207506f32e7eSjoerg SVal RegionStoreManager::getBindingForArray(RegionBindingsConstRef B,
207606f32e7eSjoerg                                             const TypedValueRegion *R) {
207706f32e7eSjoerg   assert(Ctx.getAsConstantArrayType(R->getValueType()) &&
207806f32e7eSjoerg          "Only constant array types can have compound bindings.");
207906f32e7eSjoerg 
208006f32e7eSjoerg   return createLazyBinding(B, R);
208106f32e7eSjoerg }
208206f32e7eSjoerg 
includedInBindings(Store store,const MemRegion * region) const208306f32e7eSjoerg bool RegionStoreManager::includedInBindings(Store store,
208406f32e7eSjoerg                                             const MemRegion *region) const {
208506f32e7eSjoerg   RegionBindingsRef B = getRegionBindings(store);
208606f32e7eSjoerg   region = region->getBaseRegion();
208706f32e7eSjoerg 
208806f32e7eSjoerg   // Quick path: if the base is the head of a cluster, the region is live.
208906f32e7eSjoerg   if (B.lookup(region))
209006f32e7eSjoerg     return true;
209106f32e7eSjoerg 
209206f32e7eSjoerg   // Slow path: if the region is the VALUE of any binding, it is live.
209306f32e7eSjoerg   for (RegionBindingsRef::iterator RI = B.begin(), RE = B.end(); RI != RE; ++RI) {
209406f32e7eSjoerg     const ClusterBindings &Cluster = RI.getData();
209506f32e7eSjoerg     for (ClusterBindings::iterator CI = Cluster.begin(), CE = Cluster.end();
209606f32e7eSjoerg          CI != CE; ++CI) {
209706f32e7eSjoerg       const SVal &D = CI.getData();
209806f32e7eSjoerg       if (const MemRegion *R = D.getAsRegion())
209906f32e7eSjoerg         if (R->getBaseRegion() == region)
210006f32e7eSjoerg           return true;
210106f32e7eSjoerg     }
210206f32e7eSjoerg   }
210306f32e7eSjoerg 
210406f32e7eSjoerg   return false;
210506f32e7eSjoerg }
210606f32e7eSjoerg 
210706f32e7eSjoerg //===----------------------------------------------------------------------===//
210806f32e7eSjoerg // Binding values to regions.
210906f32e7eSjoerg //===----------------------------------------------------------------------===//
211006f32e7eSjoerg 
killBinding(Store ST,Loc L)211106f32e7eSjoerg StoreRef RegionStoreManager::killBinding(Store ST, Loc L) {
211206f32e7eSjoerg   if (Optional<loc::MemRegionVal> LV = L.getAs<loc::MemRegionVal>())
211306f32e7eSjoerg     if (const MemRegion* R = LV->getRegion())
211406f32e7eSjoerg       return StoreRef(getRegionBindings(ST).removeBinding(R)
211506f32e7eSjoerg                                            .asImmutableMap()
211606f32e7eSjoerg                                            .getRootWithoutRetain(),
211706f32e7eSjoerg                       *this);
211806f32e7eSjoerg 
211906f32e7eSjoerg   return StoreRef(ST, *this);
212006f32e7eSjoerg }
212106f32e7eSjoerg 
212206f32e7eSjoerg RegionBindingsRef
bind(RegionBindingsConstRef B,Loc L,SVal V)212306f32e7eSjoerg RegionStoreManager::bind(RegionBindingsConstRef B, Loc L, SVal V) {
212406f32e7eSjoerg   if (L.getAs<loc::ConcreteInt>())
212506f32e7eSjoerg     return B;
212606f32e7eSjoerg 
212706f32e7eSjoerg   // If we get here, the location should be a region.
212806f32e7eSjoerg   const MemRegion *R = L.castAs<loc::MemRegionVal>().getRegion();
212906f32e7eSjoerg 
213006f32e7eSjoerg   // Check if the region is a struct region.
213106f32e7eSjoerg   if (const TypedValueRegion* TR = dyn_cast<TypedValueRegion>(R)) {
213206f32e7eSjoerg     QualType Ty = TR->getValueType();
213306f32e7eSjoerg     if (Ty->isArrayType())
213406f32e7eSjoerg       return bindArray(B, TR, V);
213506f32e7eSjoerg     if (Ty->isStructureOrClassType())
213606f32e7eSjoerg       return bindStruct(B, TR, V);
213706f32e7eSjoerg     if (Ty->isVectorType())
213806f32e7eSjoerg       return bindVector(B, TR, V);
213906f32e7eSjoerg     if (Ty->isUnionType())
214006f32e7eSjoerg       return bindAggregate(B, TR, V);
214106f32e7eSjoerg   }
214206f32e7eSjoerg 
214306f32e7eSjoerg   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(R)) {
214406f32e7eSjoerg     // Binding directly to a symbolic region should be treated as binding
214506f32e7eSjoerg     // to element 0.
214606f32e7eSjoerg     QualType T = SR->getSymbol()->getType();
214706f32e7eSjoerg     if (T->isAnyPointerType() || T->isReferenceType())
214806f32e7eSjoerg       T = T->getPointeeType();
214906f32e7eSjoerg 
215006f32e7eSjoerg     R = GetElementZeroRegion(SR, T);
215106f32e7eSjoerg   }
215206f32e7eSjoerg 
215306f32e7eSjoerg   assert((!isa<CXXThisRegion>(R) || !B.lookup(R)) &&
215406f32e7eSjoerg          "'this' pointer is not an l-value and is not assignable");
215506f32e7eSjoerg 
215606f32e7eSjoerg   // Clear out bindings that may overlap with this binding.
215706f32e7eSjoerg   RegionBindingsRef NewB = removeSubRegionBindings(B, cast<SubRegion>(R));
215806f32e7eSjoerg   return NewB.addBinding(BindingKey::Make(R, BindingKey::Direct), V);
215906f32e7eSjoerg }
216006f32e7eSjoerg 
216106f32e7eSjoerg RegionBindingsRef
setImplicitDefaultValue(RegionBindingsConstRef B,const MemRegion * R,QualType T)216206f32e7eSjoerg RegionStoreManager::setImplicitDefaultValue(RegionBindingsConstRef B,
216306f32e7eSjoerg                                             const MemRegion *R,
216406f32e7eSjoerg                                             QualType T) {
216506f32e7eSjoerg   SVal V;
216606f32e7eSjoerg 
216706f32e7eSjoerg   if (Loc::isLocType(T))
216806f32e7eSjoerg     V = svalBuilder.makeNull();
216906f32e7eSjoerg   else if (T->isIntegralOrEnumerationType())
217006f32e7eSjoerg     V = svalBuilder.makeZeroVal(T);
217106f32e7eSjoerg   else if (T->isStructureOrClassType() || T->isArrayType()) {
217206f32e7eSjoerg     // Set the default value to a zero constant when it is a structure
217306f32e7eSjoerg     // or array.  The type doesn't really matter.
217406f32e7eSjoerg     V = svalBuilder.makeZeroVal(Ctx.IntTy);
217506f32e7eSjoerg   }
217606f32e7eSjoerg   else {
217706f32e7eSjoerg     // We can't represent values of this type, but we still need to set a value
217806f32e7eSjoerg     // to record that the region has been initialized.
217906f32e7eSjoerg     // If this assertion ever fires, a new case should be added above -- we
218006f32e7eSjoerg     // should know how to default-initialize any value we can symbolicate.
218106f32e7eSjoerg     assert(!SymbolManager::canSymbolicate(T) && "This type is representable");
218206f32e7eSjoerg     V = UnknownVal();
218306f32e7eSjoerg   }
218406f32e7eSjoerg 
218506f32e7eSjoerg   return B.addBinding(R, BindingKey::Default, V);
218606f32e7eSjoerg }
218706f32e7eSjoerg 
218806f32e7eSjoerg RegionBindingsRef
bindArray(RegionBindingsConstRef B,const TypedValueRegion * R,SVal Init)218906f32e7eSjoerg RegionStoreManager::bindArray(RegionBindingsConstRef B,
219006f32e7eSjoerg                               const TypedValueRegion* R,
219106f32e7eSjoerg                               SVal Init) {
219206f32e7eSjoerg 
219306f32e7eSjoerg   const ArrayType *AT =cast<ArrayType>(Ctx.getCanonicalType(R->getValueType()));
219406f32e7eSjoerg   QualType ElementTy = AT->getElementType();
219506f32e7eSjoerg   Optional<uint64_t> Size;
219606f32e7eSjoerg 
219706f32e7eSjoerg   if (const ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(AT))
219806f32e7eSjoerg     Size = CAT->getSize().getZExtValue();
219906f32e7eSjoerg 
220006f32e7eSjoerg   // Check if the init expr is a literal. If so, bind the rvalue instead.
220106f32e7eSjoerg   // FIXME: It's not responsibility of the Store to transform this lvalue
220206f32e7eSjoerg   // to rvalue. ExprEngine or maybe even CFG should do this before binding.
220306f32e7eSjoerg   if (Optional<loc::MemRegionVal> MRV = Init.getAs<loc::MemRegionVal>()) {
220406f32e7eSjoerg     SVal V = getBinding(B.asStore(), *MRV, R->getValueType());
220506f32e7eSjoerg     return bindAggregate(B, R, V);
220606f32e7eSjoerg   }
220706f32e7eSjoerg 
220806f32e7eSjoerg   // Handle lazy compound values.
220906f32e7eSjoerg   if (Init.getAs<nonloc::LazyCompoundVal>())
221006f32e7eSjoerg     return bindAggregate(B, R, Init);
221106f32e7eSjoerg 
221206f32e7eSjoerg   if (Init.isUnknown())
221306f32e7eSjoerg     return bindAggregate(B, R, UnknownVal());
221406f32e7eSjoerg 
221506f32e7eSjoerg   // Remaining case: explicit compound values.
221606f32e7eSjoerg   const nonloc::CompoundVal& CV = Init.castAs<nonloc::CompoundVal>();
221706f32e7eSjoerg   nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
221806f32e7eSjoerg   uint64_t i = 0;
221906f32e7eSjoerg 
222006f32e7eSjoerg   RegionBindingsRef NewB(B);
222106f32e7eSjoerg 
222206f32e7eSjoerg   for (; Size.hasValue() ? i < Size.getValue() : true ; ++i, ++VI) {
222306f32e7eSjoerg     // The init list might be shorter than the array length.
222406f32e7eSjoerg     if (VI == VE)
222506f32e7eSjoerg       break;
222606f32e7eSjoerg 
222706f32e7eSjoerg     const NonLoc &Idx = svalBuilder.makeArrayIndex(i);
222806f32e7eSjoerg     const ElementRegion *ER = MRMgr.getElementRegion(ElementTy, Idx, R, Ctx);
222906f32e7eSjoerg 
223006f32e7eSjoerg     if (ElementTy->isStructureOrClassType())
223106f32e7eSjoerg       NewB = bindStruct(NewB, ER, *VI);
223206f32e7eSjoerg     else if (ElementTy->isArrayType())
223306f32e7eSjoerg       NewB = bindArray(NewB, ER, *VI);
223406f32e7eSjoerg     else
223506f32e7eSjoerg       NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
223606f32e7eSjoerg   }
223706f32e7eSjoerg 
223806f32e7eSjoerg   // If the init list is shorter than the array length (or the array has
223906f32e7eSjoerg   // variable length), set the array default value. Values that are already set
224006f32e7eSjoerg   // are not overwritten.
224106f32e7eSjoerg   if (!Size.hasValue() || i < Size.getValue())
224206f32e7eSjoerg     NewB = setImplicitDefaultValue(NewB, R, ElementTy);
224306f32e7eSjoerg 
224406f32e7eSjoerg   return NewB;
224506f32e7eSjoerg }
224606f32e7eSjoerg 
bindVector(RegionBindingsConstRef B,const TypedValueRegion * R,SVal V)224706f32e7eSjoerg RegionBindingsRef RegionStoreManager::bindVector(RegionBindingsConstRef B,
224806f32e7eSjoerg                                                  const TypedValueRegion* R,
224906f32e7eSjoerg                                                  SVal V) {
225006f32e7eSjoerg   QualType T = R->getValueType();
225106f32e7eSjoerg   const VectorType *VT = T->castAs<VectorType>(); // Use castAs for typedefs.
225206f32e7eSjoerg 
225306f32e7eSjoerg   // Handle lazy compound values and symbolic values.
225406f32e7eSjoerg   if (V.getAs<nonloc::LazyCompoundVal>() || V.getAs<nonloc::SymbolVal>())
225506f32e7eSjoerg     return bindAggregate(B, R, V);
225606f32e7eSjoerg 
225706f32e7eSjoerg   // We may get non-CompoundVal accidentally due to imprecise cast logic or
225806f32e7eSjoerg   // that we are binding symbolic struct value. Kill the field values, and if
225906f32e7eSjoerg   // the value is symbolic go and bind it as a "default" binding.
226006f32e7eSjoerg   if (!V.getAs<nonloc::CompoundVal>()) {
226106f32e7eSjoerg     return bindAggregate(B, R, UnknownVal());
226206f32e7eSjoerg   }
226306f32e7eSjoerg 
226406f32e7eSjoerg   QualType ElemType = VT->getElementType();
226506f32e7eSjoerg   nonloc::CompoundVal CV = V.castAs<nonloc::CompoundVal>();
226606f32e7eSjoerg   nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
226706f32e7eSjoerg   unsigned index = 0, numElements = VT->getNumElements();
226806f32e7eSjoerg   RegionBindingsRef NewB(B);
226906f32e7eSjoerg 
227006f32e7eSjoerg   for ( ; index != numElements ; ++index) {
227106f32e7eSjoerg     if (VI == VE)
227206f32e7eSjoerg       break;
227306f32e7eSjoerg 
227406f32e7eSjoerg     NonLoc Idx = svalBuilder.makeArrayIndex(index);
227506f32e7eSjoerg     const ElementRegion *ER = MRMgr.getElementRegion(ElemType, Idx, R, Ctx);
227606f32e7eSjoerg 
227706f32e7eSjoerg     if (ElemType->isArrayType())
227806f32e7eSjoerg       NewB = bindArray(NewB, ER, *VI);
227906f32e7eSjoerg     else if (ElemType->isStructureOrClassType())
228006f32e7eSjoerg       NewB = bindStruct(NewB, ER, *VI);
228106f32e7eSjoerg     else
228206f32e7eSjoerg       NewB = bind(NewB, loc::MemRegionVal(ER), *VI);
228306f32e7eSjoerg   }
228406f32e7eSjoerg   return NewB;
228506f32e7eSjoerg }
228606f32e7eSjoerg 
228706f32e7eSjoerg Optional<RegionBindingsRef>
tryBindSmallStruct(RegionBindingsConstRef B,const TypedValueRegion * R,const RecordDecl * RD,nonloc::LazyCompoundVal LCV)228806f32e7eSjoerg RegionStoreManager::tryBindSmallStruct(RegionBindingsConstRef B,
228906f32e7eSjoerg                                        const TypedValueRegion *R,
229006f32e7eSjoerg                                        const RecordDecl *RD,
229106f32e7eSjoerg                                        nonloc::LazyCompoundVal LCV) {
229206f32e7eSjoerg   FieldVector Fields;
229306f32e7eSjoerg 
229406f32e7eSjoerg   if (const CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(RD))
229506f32e7eSjoerg     if (Class->getNumBases() != 0 || Class->getNumVBases() != 0)
229606f32e7eSjoerg       return None;
229706f32e7eSjoerg 
229806f32e7eSjoerg   for (const auto *FD : RD->fields()) {
229906f32e7eSjoerg     if (FD->isUnnamedBitfield())
230006f32e7eSjoerg       continue;
230106f32e7eSjoerg 
230206f32e7eSjoerg     // If there are too many fields, or if any of the fields are aggregates,
230306f32e7eSjoerg     // just use the LCV as a default binding.
230406f32e7eSjoerg     if (Fields.size() == SmallStructLimit)
230506f32e7eSjoerg       return None;
230606f32e7eSjoerg 
230706f32e7eSjoerg     QualType Ty = FD->getType();
230806f32e7eSjoerg     if (!(Ty->isScalarType() || Ty->isReferenceType()))
230906f32e7eSjoerg       return None;
231006f32e7eSjoerg 
231106f32e7eSjoerg     Fields.push_back(FD);
231206f32e7eSjoerg   }
231306f32e7eSjoerg 
231406f32e7eSjoerg   RegionBindingsRef NewB = B;
231506f32e7eSjoerg 
231606f32e7eSjoerg   for (FieldVector::iterator I = Fields.begin(), E = Fields.end(); I != E; ++I){
231706f32e7eSjoerg     const FieldRegion *SourceFR = MRMgr.getFieldRegion(*I, LCV.getRegion());
231806f32e7eSjoerg     SVal V = getBindingForField(getRegionBindings(LCV.getStore()), SourceFR);
231906f32e7eSjoerg 
232006f32e7eSjoerg     const FieldRegion *DestFR = MRMgr.getFieldRegion(*I, R);
232106f32e7eSjoerg     NewB = bind(NewB, loc::MemRegionVal(DestFR), V);
232206f32e7eSjoerg   }
232306f32e7eSjoerg 
232406f32e7eSjoerg   return NewB;
232506f32e7eSjoerg }
232606f32e7eSjoerg 
bindStruct(RegionBindingsConstRef B,const TypedValueRegion * R,SVal V)232706f32e7eSjoerg RegionBindingsRef RegionStoreManager::bindStruct(RegionBindingsConstRef B,
232806f32e7eSjoerg                                                  const TypedValueRegion* R,
232906f32e7eSjoerg                                                  SVal V) {
233006f32e7eSjoerg   if (!Features.supportsFields())
233106f32e7eSjoerg     return B;
233206f32e7eSjoerg 
233306f32e7eSjoerg   QualType T = R->getValueType();
233406f32e7eSjoerg   assert(T->isStructureOrClassType());
233506f32e7eSjoerg 
233606f32e7eSjoerg   const RecordType* RT = T->castAs<RecordType>();
233706f32e7eSjoerg   const RecordDecl *RD = RT->getDecl();
233806f32e7eSjoerg 
233906f32e7eSjoerg   if (!RD->isCompleteDefinition())
234006f32e7eSjoerg     return B;
234106f32e7eSjoerg 
234206f32e7eSjoerg   // Handle lazy compound values and symbolic values.
234306f32e7eSjoerg   if (Optional<nonloc::LazyCompoundVal> LCV =
234406f32e7eSjoerg         V.getAs<nonloc::LazyCompoundVal>()) {
234506f32e7eSjoerg     if (Optional<RegionBindingsRef> NewB = tryBindSmallStruct(B, R, RD, *LCV))
234606f32e7eSjoerg       return *NewB;
234706f32e7eSjoerg     return bindAggregate(B, R, V);
234806f32e7eSjoerg   }
234906f32e7eSjoerg   if (V.getAs<nonloc::SymbolVal>())
235006f32e7eSjoerg     return bindAggregate(B, R, V);
235106f32e7eSjoerg 
235206f32e7eSjoerg   // We may get non-CompoundVal accidentally due to imprecise cast logic or
235306f32e7eSjoerg   // that we are binding symbolic struct value. Kill the field values, and if
235406f32e7eSjoerg   // the value is symbolic go and bind it as a "default" binding.
235506f32e7eSjoerg   if (V.isUnknown() || !V.getAs<nonloc::CompoundVal>())
235606f32e7eSjoerg     return bindAggregate(B, R, UnknownVal());
235706f32e7eSjoerg 
235806f32e7eSjoerg   // The raw CompoundVal is essentially a symbolic InitListExpr: an (immutable)
235906f32e7eSjoerg   // list of other values. It appears pretty much only when there's an actual
236006f32e7eSjoerg   // initializer list expression in the program, and the analyzer tries to
236106f32e7eSjoerg   // unwrap it as soon as possible.
236206f32e7eSjoerg   // This code is where such unwrap happens: when the compound value is put into
236306f32e7eSjoerg   // the object that it was supposed to initialize (it's an *initializer* list,
236406f32e7eSjoerg   // after all), instead of binding the whole value to the whole object, we bind
236506f32e7eSjoerg   // sub-values to sub-objects. Sub-values may themselves be compound values,
236606f32e7eSjoerg   // and in this case the procedure becomes recursive.
236706f32e7eSjoerg   // FIXME: The annoying part about compound values is that they don't carry
236806f32e7eSjoerg   // any sort of information about which value corresponds to which sub-object.
236906f32e7eSjoerg   // It's simply a list of values in the middle of nowhere; we expect to match
237006f32e7eSjoerg   // them to sub-objects, essentially, "by index": first value binds to
237106f32e7eSjoerg   // the first field, second value binds to the second field, etc.
237206f32e7eSjoerg   // It would have been much safer to organize non-lazy compound values as
237306f32e7eSjoerg   // a mapping from fields/bases to values.
237406f32e7eSjoerg   const nonloc::CompoundVal& CV = V.castAs<nonloc::CompoundVal>();
237506f32e7eSjoerg   nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
237606f32e7eSjoerg 
237706f32e7eSjoerg   RegionBindingsRef NewB(B);
237806f32e7eSjoerg 
237906f32e7eSjoerg   // In C++17 aggregates may have base classes, handle those as well.
238006f32e7eSjoerg   // They appear before fields in the initializer list / compound value.
238106f32e7eSjoerg   if (const auto *CRD = dyn_cast<CXXRecordDecl>(RD)) {
238206f32e7eSjoerg     // If the object was constructed with a constructor, its value is a
238306f32e7eSjoerg     // LazyCompoundVal. If it's a raw CompoundVal, it means that we're
238406f32e7eSjoerg     // performing aggregate initialization. The only exception from this
238506f32e7eSjoerg     // rule is sending an Objective-C++ message that returns a C++ object
238606f32e7eSjoerg     // to a nil receiver; in this case the semantics is to return a
238706f32e7eSjoerg     // zero-initialized object even if it's a C++ object that doesn't have
238806f32e7eSjoerg     // this sort of constructor; the CompoundVal is empty in this case.
238906f32e7eSjoerg     assert((CRD->isAggregate() || (Ctx.getLangOpts().ObjC && VI == VE)) &&
239006f32e7eSjoerg            "Non-aggregates are constructed with a constructor!");
239106f32e7eSjoerg 
239206f32e7eSjoerg     for (const auto &B : CRD->bases()) {
239306f32e7eSjoerg       // (Multiple inheritance is fine though.)
239406f32e7eSjoerg       assert(!B.isVirtual() && "Aggregates cannot have virtual base classes!");
239506f32e7eSjoerg 
239606f32e7eSjoerg       if (VI == VE)
239706f32e7eSjoerg         break;
239806f32e7eSjoerg 
239906f32e7eSjoerg       QualType BTy = B.getType();
240006f32e7eSjoerg       assert(BTy->isStructureOrClassType() && "Base classes must be classes!");
240106f32e7eSjoerg 
240206f32e7eSjoerg       const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl();
240306f32e7eSjoerg       assert(BRD && "Base classes must be C++ classes!");
240406f32e7eSjoerg 
240506f32e7eSjoerg       const CXXBaseObjectRegion *BR =
240606f32e7eSjoerg           MRMgr.getCXXBaseObjectRegion(BRD, R, /*IsVirtual=*/false);
240706f32e7eSjoerg 
240806f32e7eSjoerg       NewB = bindStruct(NewB, BR, *VI);
240906f32e7eSjoerg 
241006f32e7eSjoerg       ++VI;
241106f32e7eSjoerg     }
241206f32e7eSjoerg   }
241306f32e7eSjoerg 
241406f32e7eSjoerg   RecordDecl::field_iterator FI, FE;
241506f32e7eSjoerg 
241606f32e7eSjoerg   for (FI = RD->field_begin(), FE = RD->field_end(); FI != FE; ++FI) {
241706f32e7eSjoerg 
241806f32e7eSjoerg     if (VI == VE)
241906f32e7eSjoerg       break;
242006f32e7eSjoerg 
242106f32e7eSjoerg     // Skip any unnamed bitfields to stay in sync with the initializers.
242206f32e7eSjoerg     if (FI->isUnnamedBitfield())
242306f32e7eSjoerg       continue;
242406f32e7eSjoerg 
242506f32e7eSjoerg     QualType FTy = FI->getType();
242606f32e7eSjoerg     const FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
242706f32e7eSjoerg 
242806f32e7eSjoerg     if (FTy->isArrayType())
242906f32e7eSjoerg       NewB = bindArray(NewB, FR, *VI);
243006f32e7eSjoerg     else if (FTy->isStructureOrClassType())
243106f32e7eSjoerg       NewB = bindStruct(NewB, FR, *VI);
243206f32e7eSjoerg     else
243306f32e7eSjoerg       NewB = bind(NewB, loc::MemRegionVal(FR), *VI);
243406f32e7eSjoerg     ++VI;
243506f32e7eSjoerg   }
243606f32e7eSjoerg 
243706f32e7eSjoerg   // There may be fewer values in the initialize list than the fields of struct.
243806f32e7eSjoerg   if (FI != FE) {
243906f32e7eSjoerg     NewB = NewB.addBinding(R, BindingKey::Default,
244006f32e7eSjoerg                            svalBuilder.makeIntVal(0, false));
244106f32e7eSjoerg   }
244206f32e7eSjoerg 
244306f32e7eSjoerg   return NewB;
244406f32e7eSjoerg }
244506f32e7eSjoerg 
244606f32e7eSjoerg RegionBindingsRef
bindAggregate(RegionBindingsConstRef B,const TypedRegion * R,SVal Val)244706f32e7eSjoerg RegionStoreManager::bindAggregate(RegionBindingsConstRef B,
244806f32e7eSjoerg                                   const TypedRegion *R,
244906f32e7eSjoerg                                   SVal Val) {
245006f32e7eSjoerg   // Remove the old bindings, using 'R' as the root of all regions
245106f32e7eSjoerg   // we will invalidate. Then add the new binding.
245206f32e7eSjoerg   return removeSubRegionBindings(B, R).addBinding(R, BindingKey::Default, Val);
245306f32e7eSjoerg }
245406f32e7eSjoerg 
245506f32e7eSjoerg //===----------------------------------------------------------------------===//
245606f32e7eSjoerg // State pruning.
245706f32e7eSjoerg //===----------------------------------------------------------------------===//
245806f32e7eSjoerg 
245906f32e7eSjoerg namespace {
246006f32e7eSjoerg class RemoveDeadBindingsWorker
246106f32e7eSjoerg     : public ClusterAnalysis<RemoveDeadBindingsWorker> {
246206f32e7eSjoerg   SmallVector<const SymbolicRegion *, 12> Postponed;
246306f32e7eSjoerg   SymbolReaper &SymReaper;
246406f32e7eSjoerg   const StackFrameContext *CurrentLCtx;
246506f32e7eSjoerg 
246606f32e7eSjoerg public:
RemoveDeadBindingsWorker(RegionStoreManager & rm,ProgramStateManager & stateMgr,RegionBindingsRef b,SymbolReaper & symReaper,const StackFrameContext * LCtx)246706f32e7eSjoerg   RemoveDeadBindingsWorker(RegionStoreManager &rm,
246806f32e7eSjoerg                            ProgramStateManager &stateMgr,
246906f32e7eSjoerg                            RegionBindingsRef b, SymbolReaper &symReaper,
247006f32e7eSjoerg                            const StackFrameContext *LCtx)
247106f32e7eSjoerg     : ClusterAnalysis<RemoveDeadBindingsWorker>(rm, stateMgr, b),
247206f32e7eSjoerg       SymReaper(symReaper), CurrentLCtx(LCtx) {}
247306f32e7eSjoerg 
247406f32e7eSjoerg   // Called by ClusterAnalysis.
247506f32e7eSjoerg   void VisitAddedToCluster(const MemRegion *baseR, const ClusterBindings &C);
247606f32e7eSjoerg   void VisitCluster(const MemRegion *baseR, const ClusterBindings *C);
247706f32e7eSjoerg   using ClusterAnalysis<RemoveDeadBindingsWorker>::VisitCluster;
247806f32e7eSjoerg 
247906f32e7eSjoerg   using ClusterAnalysis::AddToWorkList;
248006f32e7eSjoerg 
248106f32e7eSjoerg   bool AddToWorkList(const MemRegion *R);
248206f32e7eSjoerg 
248306f32e7eSjoerg   bool UpdatePostponed();
248406f32e7eSjoerg   void VisitBinding(SVal V);
248506f32e7eSjoerg };
248606f32e7eSjoerg }
248706f32e7eSjoerg 
AddToWorkList(const MemRegion * R)248806f32e7eSjoerg bool RemoveDeadBindingsWorker::AddToWorkList(const MemRegion *R) {
248906f32e7eSjoerg   const MemRegion *BaseR = R->getBaseRegion();
249006f32e7eSjoerg   return AddToWorkList(WorkListElement(BaseR), getCluster(BaseR));
249106f32e7eSjoerg }
249206f32e7eSjoerg 
VisitAddedToCluster(const MemRegion * baseR,const ClusterBindings & C)249306f32e7eSjoerg void RemoveDeadBindingsWorker::VisitAddedToCluster(const MemRegion *baseR,
249406f32e7eSjoerg                                                    const ClusterBindings &C) {
249506f32e7eSjoerg 
249606f32e7eSjoerg   if (const VarRegion *VR = dyn_cast<VarRegion>(baseR)) {
249706f32e7eSjoerg     if (SymReaper.isLive(VR))
249806f32e7eSjoerg       AddToWorkList(baseR, &C);
249906f32e7eSjoerg 
250006f32e7eSjoerg     return;
250106f32e7eSjoerg   }
250206f32e7eSjoerg 
250306f32e7eSjoerg   if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(baseR)) {
250406f32e7eSjoerg     if (SymReaper.isLive(SR->getSymbol()))
250506f32e7eSjoerg       AddToWorkList(SR, &C);
250606f32e7eSjoerg     else
250706f32e7eSjoerg       Postponed.push_back(SR);
250806f32e7eSjoerg 
250906f32e7eSjoerg     return;
251006f32e7eSjoerg   }
251106f32e7eSjoerg 
251206f32e7eSjoerg   if (isa<NonStaticGlobalSpaceRegion>(baseR)) {
251306f32e7eSjoerg     AddToWorkList(baseR, &C);
251406f32e7eSjoerg     return;
251506f32e7eSjoerg   }
251606f32e7eSjoerg 
251706f32e7eSjoerg   // CXXThisRegion in the current or parent location context is live.
251806f32e7eSjoerg   if (const CXXThisRegion *TR = dyn_cast<CXXThisRegion>(baseR)) {
251906f32e7eSjoerg     const auto *StackReg =
252006f32e7eSjoerg         cast<StackArgumentsSpaceRegion>(TR->getSuperRegion());
252106f32e7eSjoerg     const StackFrameContext *RegCtx = StackReg->getStackFrame();
252206f32e7eSjoerg     if (CurrentLCtx &&
252306f32e7eSjoerg         (RegCtx == CurrentLCtx || RegCtx->isParentOf(CurrentLCtx)))
252406f32e7eSjoerg       AddToWorkList(TR, &C);
252506f32e7eSjoerg   }
252606f32e7eSjoerg }
252706f32e7eSjoerg 
VisitCluster(const MemRegion * baseR,const ClusterBindings * C)252806f32e7eSjoerg void RemoveDeadBindingsWorker::VisitCluster(const MemRegion *baseR,
252906f32e7eSjoerg                                             const ClusterBindings *C) {
253006f32e7eSjoerg   if (!C)
253106f32e7eSjoerg     return;
253206f32e7eSjoerg 
253306f32e7eSjoerg   // Mark the symbol for any SymbolicRegion with live bindings as live itself.
253406f32e7eSjoerg   // This means we should continue to track that symbol.
253506f32e7eSjoerg   if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(baseR))
253606f32e7eSjoerg     SymReaper.markLive(SymR->getSymbol());
253706f32e7eSjoerg 
253806f32e7eSjoerg   for (ClusterBindings::iterator I = C->begin(), E = C->end(); I != E; ++I) {
253906f32e7eSjoerg     // Element index of a binding key is live.
254006f32e7eSjoerg     SymReaper.markElementIndicesLive(I.getKey().getRegion());
254106f32e7eSjoerg 
254206f32e7eSjoerg     VisitBinding(I.getData());
254306f32e7eSjoerg   }
254406f32e7eSjoerg }
254506f32e7eSjoerg 
VisitBinding(SVal V)254606f32e7eSjoerg void RemoveDeadBindingsWorker::VisitBinding(SVal V) {
254706f32e7eSjoerg   // Is it a LazyCompoundVal?  All referenced regions are live as well.
254806f32e7eSjoerg   if (Optional<nonloc::LazyCompoundVal> LCS =
254906f32e7eSjoerg           V.getAs<nonloc::LazyCompoundVal>()) {
255006f32e7eSjoerg 
255106f32e7eSjoerg     const RegionStoreManager::SValListTy &Vals = RM.getInterestingValues(*LCS);
255206f32e7eSjoerg 
255306f32e7eSjoerg     for (RegionStoreManager::SValListTy::const_iterator I = Vals.begin(),
255406f32e7eSjoerg                                                         E = Vals.end();
255506f32e7eSjoerg          I != E; ++I)
255606f32e7eSjoerg       VisitBinding(*I);
255706f32e7eSjoerg 
255806f32e7eSjoerg     return;
255906f32e7eSjoerg   }
256006f32e7eSjoerg 
256106f32e7eSjoerg   // If V is a region, then add it to the worklist.
256206f32e7eSjoerg   if (const MemRegion *R = V.getAsRegion()) {
256306f32e7eSjoerg     AddToWorkList(R);
256406f32e7eSjoerg     SymReaper.markLive(R);
256506f32e7eSjoerg 
256606f32e7eSjoerg     // All regions captured by a block are also live.
256706f32e7eSjoerg     if (const BlockDataRegion *BR = dyn_cast<BlockDataRegion>(R)) {
256806f32e7eSjoerg       BlockDataRegion::referenced_vars_iterator I = BR->referenced_vars_begin(),
256906f32e7eSjoerg                                                 E = BR->referenced_vars_end();
257006f32e7eSjoerg       for ( ; I != E; ++I)
257106f32e7eSjoerg         AddToWorkList(I.getCapturedRegion());
257206f32e7eSjoerg     }
257306f32e7eSjoerg   }
257406f32e7eSjoerg 
257506f32e7eSjoerg 
257606f32e7eSjoerg   // Update the set of live symbols.
257706f32e7eSjoerg   for (auto SI = V.symbol_begin(), SE = V.symbol_end(); SI!=SE; ++SI)
257806f32e7eSjoerg     SymReaper.markLive(*SI);
257906f32e7eSjoerg }
258006f32e7eSjoerg 
UpdatePostponed()258106f32e7eSjoerg bool RemoveDeadBindingsWorker::UpdatePostponed() {
258206f32e7eSjoerg   // See if any postponed SymbolicRegions are actually live now, after
258306f32e7eSjoerg   // having done a scan.
258406f32e7eSjoerg   bool Changed = false;
258506f32e7eSjoerg 
258606f32e7eSjoerg   for (auto I = Postponed.begin(), E = Postponed.end(); I != E; ++I) {
258706f32e7eSjoerg     if (const SymbolicRegion *SR = *I) {
258806f32e7eSjoerg       if (SymReaper.isLive(SR->getSymbol())) {
258906f32e7eSjoerg         Changed |= AddToWorkList(SR);
259006f32e7eSjoerg         *I = nullptr;
259106f32e7eSjoerg       }
259206f32e7eSjoerg     }
259306f32e7eSjoerg   }
259406f32e7eSjoerg 
259506f32e7eSjoerg   return Changed;
259606f32e7eSjoerg }
259706f32e7eSjoerg 
removeDeadBindings(Store store,const StackFrameContext * LCtx,SymbolReaper & SymReaper)259806f32e7eSjoerg StoreRef RegionStoreManager::removeDeadBindings(Store store,
259906f32e7eSjoerg                                                 const StackFrameContext *LCtx,
260006f32e7eSjoerg                                                 SymbolReaper& SymReaper) {
260106f32e7eSjoerg   RegionBindingsRef B = getRegionBindings(store);
260206f32e7eSjoerg   RemoveDeadBindingsWorker W(*this, StateMgr, B, SymReaper, LCtx);
260306f32e7eSjoerg   W.GenerateClusters();
260406f32e7eSjoerg 
260506f32e7eSjoerg   // Enqueue the region roots onto the worklist.
260606f32e7eSjoerg   for (SymbolReaper::region_iterator I = SymReaper.region_begin(),
260706f32e7eSjoerg        E = SymReaper.region_end(); I != E; ++I) {
260806f32e7eSjoerg     W.AddToWorkList(*I);
260906f32e7eSjoerg   }
261006f32e7eSjoerg 
261106f32e7eSjoerg   do W.RunWorkList(); while (W.UpdatePostponed());
261206f32e7eSjoerg 
261306f32e7eSjoerg   // We have now scanned the store, marking reachable regions and symbols
261406f32e7eSjoerg   // as live.  We now remove all the regions that are dead from the store
261506f32e7eSjoerg   // as well as update DSymbols with the set symbols that are now dead.
261606f32e7eSjoerg   for (RegionBindingsRef::iterator I = B.begin(), E = B.end(); I != E; ++I) {
261706f32e7eSjoerg     const MemRegion *Base = I.getKey();
261806f32e7eSjoerg 
261906f32e7eSjoerg     // If the cluster has been visited, we know the region has been marked.
262006f32e7eSjoerg     // Otherwise, remove the dead entry.
262106f32e7eSjoerg     if (!W.isVisited(Base))
262206f32e7eSjoerg       B = B.remove(Base);
262306f32e7eSjoerg   }
262406f32e7eSjoerg 
262506f32e7eSjoerg   return StoreRef(B.asStore(), *this);
262606f32e7eSjoerg }
262706f32e7eSjoerg 
262806f32e7eSjoerg //===----------------------------------------------------------------------===//
262906f32e7eSjoerg // Utility methods.
263006f32e7eSjoerg //===----------------------------------------------------------------------===//
263106f32e7eSjoerg 
printJson(raw_ostream & Out,Store S,const char * NL,unsigned int Space,bool IsDot) const263206f32e7eSjoerg void RegionStoreManager::printJson(raw_ostream &Out, Store S, const char *NL,
263306f32e7eSjoerg                                    unsigned int Space, bool IsDot) const {
263406f32e7eSjoerg   RegionBindingsRef Bindings = getRegionBindings(S);
263506f32e7eSjoerg 
263606f32e7eSjoerg   Indent(Out, Space, IsDot) << "\"store\": ";
263706f32e7eSjoerg 
263806f32e7eSjoerg   if (Bindings.isEmpty()) {
263906f32e7eSjoerg     Out << "null," << NL;
264006f32e7eSjoerg     return;
264106f32e7eSjoerg   }
264206f32e7eSjoerg 
264306f32e7eSjoerg   Out << "{ \"pointer\": \"" << Bindings.asStore() << "\", \"items\": [" << NL;
264406f32e7eSjoerg   Bindings.printJson(Out, NL, Space + 1, IsDot);
264506f32e7eSjoerg   Indent(Out, Space, IsDot) << "]}," << NL;
264606f32e7eSjoerg }
2647