10b57cec5SDimitry Andric //===- BasicValueFactory.cpp - Basic values for Path Sens analysis --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric //  This file defines BasicValueFactory, a class that manages the lifetime
100b57cec5SDimitry Andric //  of APSInt objects and symbolic constraints used by ExprEngine
110b57cec5SDimitry Andric //  and related classes.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
160b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
170b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
180b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
190b57cec5SDimitry Andric #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
200b57cec5SDimitry Andric #include "llvm/ADT/APSInt.h"
210b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h"
220b57cec5SDimitry Andric #include "llvm/ADT/ImmutableList.h"
230b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
24fe6060f1SDimitry Andric #include "llvm/ADT/SmallPtrSet.h"
250b57cec5SDimitry Andric #include <cassert>
260b57cec5SDimitry Andric #include <cstdint>
270b57cec5SDimitry Andric #include <utility>
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric using namespace clang;
300b57cec5SDimitry Andric using namespace ento;
310b57cec5SDimitry Andric 
Profile(llvm::FoldingSetNodeID & ID,QualType T,llvm::ImmutableList<SVal> L)320b57cec5SDimitry Andric void CompoundValData::Profile(llvm::FoldingSetNodeID& ID, QualType T,
330b57cec5SDimitry Andric                               llvm::ImmutableList<SVal> L) {
340b57cec5SDimitry Andric   T.Profile(ID);
350b57cec5SDimitry Andric   ID.AddPointer(L.getInternalPointer());
360b57cec5SDimitry Andric }
370b57cec5SDimitry Andric 
Profile(llvm::FoldingSetNodeID & ID,const StoreRef & store,const TypedValueRegion * region)380b57cec5SDimitry Andric void LazyCompoundValData::Profile(llvm::FoldingSetNodeID& ID,
390b57cec5SDimitry Andric                                   const StoreRef &store,
400b57cec5SDimitry Andric                                   const TypedValueRegion *region) {
410b57cec5SDimitry Andric   ID.AddPointer(store.getStore());
420b57cec5SDimitry Andric   ID.AddPointer(region);
430b57cec5SDimitry Andric }
440b57cec5SDimitry Andric 
Profile(llvm::FoldingSetNodeID & ID,const NamedDecl * D,llvm::ImmutableList<const CXXBaseSpecifier * > L)450b57cec5SDimitry Andric void PointerToMemberData::Profile(
46e8d8bef9SDimitry Andric     llvm::FoldingSetNodeID &ID, const NamedDecl *D,
470b57cec5SDimitry Andric     llvm::ImmutableList<const CXXBaseSpecifier *> L) {
480b57cec5SDimitry Andric   ID.AddPointer(D);
490b57cec5SDimitry Andric   ID.AddPointer(L.getInternalPointer());
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric using SValData = std::pair<SVal, uintptr_t>;
530b57cec5SDimitry Andric using SValPair = std::pair<SVal, SVal>;
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric namespace llvm {
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric template<> struct FoldingSetTrait<SValData> {
Profilellvm::FoldingSetTrait580b57cec5SDimitry Andric   static inline void Profile(const SValData& X, llvm::FoldingSetNodeID& ID) {
590b57cec5SDimitry Andric     X.first.Profile(ID);
600b57cec5SDimitry Andric     ID.AddPointer( (void*) X.second);
610b57cec5SDimitry Andric   }
620b57cec5SDimitry Andric };
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric template<> struct FoldingSetTrait<SValPair> {
Profilellvm::FoldingSetTrait650b57cec5SDimitry Andric   static inline void Profile(const SValPair& X, llvm::FoldingSetNodeID& ID) {
660b57cec5SDimitry Andric     X.first.Profile(ID);
670b57cec5SDimitry Andric     X.second.Profile(ID);
680b57cec5SDimitry Andric   }
690b57cec5SDimitry Andric };
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric } // namespace llvm
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric using PersistentSValsTy =
740b57cec5SDimitry Andric     llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValData>>;
750b57cec5SDimitry Andric 
760b57cec5SDimitry Andric using PersistentSValPairsTy =
770b57cec5SDimitry Andric     llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValPair>>;
780b57cec5SDimitry Andric 
~BasicValueFactory()790b57cec5SDimitry Andric BasicValueFactory::~BasicValueFactory() {
800b57cec5SDimitry Andric   // Note that the dstor for the contents of APSIntSet will never be called,
810b57cec5SDimitry Andric   // so we iterate over the set and invoke the dstor for each APSInt.  This
820b57cec5SDimitry Andric   // frees an aux. memory allocated to represent very large constants.
830b57cec5SDimitry Andric   for (const auto &I : APSIntSet)
840b57cec5SDimitry Andric     I.getValue().~APSInt();
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   delete (PersistentSValsTy*) PersistentSVals;
870b57cec5SDimitry Andric   delete (PersistentSValPairsTy*) PersistentSValPairs;
880b57cec5SDimitry Andric }
890b57cec5SDimitry Andric 
getValue(const llvm::APSInt & X)900b57cec5SDimitry Andric const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
910b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
920b57cec5SDimitry Andric   void *InsertPos;
930b57cec5SDimitry Andric 
940b57cec5SDimitry Andric   using FoldNodeTy = llvm::FoldingSetNodeWrapper<llvm::APSInt>;
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   X.Profile(ID);
970b57cec5SDimitry Andric   FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   if (!P) {
10006c3fb27SDimitry Andric     P = new (BPAlloc) FoldNodeTy(X);
1010b57cec5SDimitry Andric     APSIntSet.InsertNode(P, InsertPos);
1020b57cec5SDimitry Andric   }
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   return *P;
1050b57cec5SDimitry Andric }
1060b57cec5SDimitry Andric 
getValue(const llvm::APInt & X,bool isUnsigned)1070b57cec5SDimitry Andric const llvm::APSInt& BasicValueFactory::getValue(const llvm::APInt& X,
1080b57cec5SDimitry Andric                                                 bool isUnsigned) {
1090b57cec5SDimitry Andric   llvm::APSInt V(X, isUnsigned);
1100b57cec5SDimitry Andric   return getValue(V);
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric 
getValue(uint64_t X,unsigned BitWidth,bool isUnsigned)1130b57cec5SDimitry Andric const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,
1140b57cec5SDimitry Andric                                            bool isUnsigned) {
1150b57cec5SDimitry Andric   llvm::APSInt V(BitWidth, isUnsigned);
1160b57cec5SDimitry Andric   V = X;
1170b57cec5SDimitry Andric   return getValue(V);
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
getValue(uint64_t X,QualType T)1200b57cec5SDimitry Andric const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
1210b57cec5SDimitry Andric   return getValue(getAPSIntType(T).getValue(X));
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric 
1240b57cec5SDimitry Andric const CompoundValData*
getCompoundValData(QualType T,llvm::ImmutableList<SVal> Vals)1250b57cec5SDimitry Andric BasicValueFactory::getCompoundValData(QualType T,
1260b57cec5SDimitry Andric                                       llvm::ImmutableList<SVal> Vals) {
1270b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
1280b57cec5SDimitry Andric   CompoundValData::Profile(ID, T, Vals);
1290b57cec5SDimitry Andric   void *InsertPos;
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   if (!D) {
13406c3fb27SDimitry Andric     D = new (BPAlloc) CompoundValData(T, Vals);
1350b57cec5SDimitry Andric     CompoundValDataSet.InsertNode(D, InsertPos);
1360b57cec5SDimitry Andric   }
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   return D;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric const LazyCompoundValData*
getLazyCompoundValData(const StoreRef & store,const TypedValueRegion * region)1420b57cec5SDimitry Andric BasicValueFactory::getLazyCompoundValData(const StoreRef &store,
1430b57cec5SDimitry Andric                                           const TypedValueRegion *region) {
1440b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
1450b57cec5SDimitry Andric   LazyCompoundValData::Profile(ID, store, region);
1460b57cec5SDimitry Andric   void *InsertPos;
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   LazyCompoundValData *D =
1490b57cec5SDimitry Andric     LazyCompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   if (!D) {
15206c3fb27SDimitry Andric     D = new (BPAlloc) LazyCompoundValData(store, region);
1530b57cec5SDimitry Andric     LazyCompoundValDataSet.InsertNode(D, InsertPos);
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric 
1560b57cec5SDimitry Andric   return D;
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
getPointerToMemberData(const NamedDecl * ND,llvm::ImmutableList<const CXXBaseSpecifier * > L)1590b57cec5SDimitry Andric const PointerToMemberData *BasicValueFactory::getPointerToMemberData(
160e8d8bef9SDimitry Andric     const NamedDecl *ND, llvm::ImmutableList<const CXXBaseSpecifier *> L) {
1610b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
162e8d8bef9SDimitry Andric   PointerToMemberData::Profile(ID, ND, L);
1630b57cec5SDimitry Andric   void *InsertPos;
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric   PointerToMemberData *D =
1660b57cec5SDimitry Andric       PointerToMemberDataSet.FindNodeOrInsertPos(ID, InsertPos);
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   if (!D) {
16906c3fb27SDimitry Andric     D = new (BPAlloc) PointerToMemberData(ND, L);
1700b57cec5SDimitry Andric     PointerToMemberDataSet.InsertNode(D, InsertPos);
1710b57cec5SDimitry Andric   }
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   return D;
1740b57cec5SDimitry Andric }
1750b57cec5SDimitry Andric 
hasNoRepeatedElements(llvm::ImmutableList<const CXXBaseSpecifier * > BaseSpecList)176fe6060f1SDimitry Andric LLVM_ATTRIBUTE_UNUSED bool hasNoRepeatedElements(
177fe6060f1SDimitry Andric     llvm::ImmutableList<const CXXBaseSpecifier *> BaseSpecList) {
178fe6060f1SDimitry Andric   llvm::SmallPtrSet<QualType, 16> BaseSpecSeen;
179fe6060f1SDimitry Andric   for (const CXXBaseSpecifier *BaseSpec : BaseSpecList) {
180fe6060f1SDimitry Andric     QualType BaseType = BaseSpec->getType();
181fe6060f1SDimitry Andric     // Check whether inserted
182fe6060f1SDimitry Andric     if (!BaseSpecSeen.insert(BaseType).second)
183fe6060f1SDimitry Andric       return false;
184fe6060f1SDimitry Andric   }
185fe6060f1SDimitry Andric   return true;
186fe6060f1SDimitry Andric }
187fe6060f1SDimitry Andric 
accumCXXBase(llvm::iterator_range<CastExpr::path_const_iterator> PathRange,const nonloc::PointerToMember & PTM,const CastKind & kind)1880b57cec5SDimitry Andric const PointerToMemberData *BasicValueFactory::accumCXXBase(
1890b57cec5SDimitry Andric     llvm::iterator_range<CastExpr::path_const_iterator> PathRange,
190fe6060f1SDimitry Andric     const nonloc::PointerToMember &PTM, const CastKind &kind) {
191fe6060f1SDimitry Andric   assert((kind == CK_DerivedToBaseMemberPointer ||
192fe6060f1SDimitry Andric           kind == CK_BaseToDerivedMemberPointer ||
193fe6060f1SDimitry Andric           kind == CK_ReinterpretMemberPointer) &&
194fe6060f1SDimitry Andric          "accumCXXBase called with wrong CastKind");
1950b57cec5SDimitry Andric   nonloc::PointerToMember::PTMDataType PTMDT = PTM.getPTMData();
196e8d8bef9SDimitry Andric   const NamedDecl *ND = nullptr;
197fe6060f1SDimitry Andric   llvm::ImmutableList<const CXXBaseSpecifier *> BaseSpecList;
1980b57cec5SDimitry Andric 
199e8d8bef9SDimitry Andric   if (PTMDT.isNull() || PTMDT.is<const NamedDecl *>()) {
200e8d8bef9SDimitry Andric     if (PTMDT.is<const NamedDecl *>())
201e8d8bef9SDimitry Andric       ND = PTMDT.get<const NamedDecl *>();
2020b57cec5SDimitry Andric 
203fe6060f1SDimitry Andric     BaseSpecList = CXXBaseListFactory.getEmptyList();
204fe6060f1SDimitry Andric   } else {
205e8d8bef9SDimitry Andric     const PointerToMemberData *PTMD = PTMDT.get<const PointerToMemberData *>();
206e8d8bef9SDimitry Andric     ND = PTMD->getDeclaratorDecl();
2070b57cec5SDimitry Andric 
208fe6060f1SDimitry Andric     BaseSpecList = PTMD->getCXXBaseList();
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric 
211fe6060f1SDimitry Andric   assert(hasNoRepeatedElements(BaseSpecList) &&
212fe6060f1SDimitry Andric          "CXXBaseSpecifier list of PointerToMemberData must not have repeated "
213fe6060f1SDimitry Andric          "elements");
214fe6060f1SDimitry Andric 
215fe6060f1SDimitry Andric   if (kind == CK_DerivedToBaseMemberPointer) {
216fe6060f1SDimitry Andric     // Here we pop off matching CXXBaseSpecifiers from BaseSpecList.
217fe6060f1SDimitry Andric     // Because, CK_DerivedToBaseMemberPointer comes from a static_cast and
218fe6060f1SDimitry Andric     // serves to remove a matching implicit cast. Note that static_cast's that
219fe6060f1SDimitry Andric     // are no-ops do not count since they produce an empty PathRange, a nice
220fe6060f1SDimitry Andric     // thing about Clang AST.
221fe6060f1SDimitry Andric 
222fe6060f1SDimitry Andric     // Now we know that there are no repetitions in BaseSpecList.
223fe6060f1SDimitry Andric     // So, popping the first element from it corresponding to each element in
224fe6060f1SDimitry Andric     // PathRange is equivalent to only including elements that are in
225fe6060f1SDimitry Andric     // BaseSpecList but not it PathRange
226fe6060f1SDimitry Andric     auto ReducedBaseSpecList = CXXBaseListFactory.getEmptyList();
227fe6060f1SDimitry Andric     for (const CXXBaseSpecifier *BaseSpec : BaseSpecList) {
228fe6060f1SDimitry Andric       auto IsSameAsBaseSpec = [&BaseSpec](const CXXBaseSpecifier *I) -> bool {
229fe6060f1SDimitry Andric         return BaseSpec->getType() == I->getType();
230fe6060f1SDimitry Andric       };
231fe6060f1SDimitry Andric       if (llvm::none_of(PathRange, IsSameAsBaseSpec))
232fe6060f1SDimitry Andric         ReducedBaseSpecList =
233fe6060f1SDimitry Andric             CXXBaseListFactory.add(BaseSpec, ReducedBaseSpecList);
234fe6060f1SDimitry Andric     }
235fe6060f1SDimitry Andric 
236fe6060f1SDimitry Andric     return getPointerToMemberData(ND, ReducedBaseSpecList);
237fe6060f1SDimitry Andric   }
238fe6060f1SDimitry Andric   // FIXME: Reinterpret casts on member-pointers are not handled properly by
239fe6060f1SDimitry Andric   // this code
240fe6060f1SDimitry Andric   for (const CXXBaseSpecifier *I : llvm::reverse(PathRange))
241fe6060f1SDimitry Andric     BaseSpecList = prependCXXBase(I, BaseSpecList);
242fe6060f1SDimitry Andric   return getPointerToMemberData(ND, BaseSpecList);
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric const llvm::APSInt*
evalAPSInt(BinaryOperator::Opcode Op,const llvm::APSInt & V1,const llvm::APSInt & V2)2460b57cec5SDimitry Andric BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
2470b57cec5SDimitry Andric                              const llvm::APSInt& V1, const llvm::APSInt& V2) {
2480b57cec5SDimitry Andric   switch (Op) {
2490b57cec5SDimitry Andric     default:
2500b57cec5SDimitry Andric       llvm_unreachable("Invalid Opcode.");
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric     case BO_Mul:
2530b57cec5SDimitry Andric       return &getValue( V1 * V2 );
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric     case BO_Div:
2560b57cec5SDimitry Andric       if (V2 == 0) // Avoid division by zero
2570b57cec5SDimitry Andric         return nullptr;
2580b57cec5SDimitry Andric       return &getValue( V1 / V2 );
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric     case BO_Rem:
2610b57cec5SDimitry Andric       if (V2 == 0) // Avoid division by zero
2620b57cec5SDimitry Andric         return nullptr;
2630b57cec5SDimitry Andric       return &getValue( V1 % V2 );
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric     case BO_Add:
2660b57cec5SDimitry Andric       return &getValue( V1 + V2 );
2670b57cec5SDimitry Andric 
2680b57cec5SDimitry Andric     case BO_Sub:
2690b57cec5SDimitry Andric       return &getValue( V1 - V2 );
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric     case BO_Shl: {
2720b57cec5SDimitry Andric       // FIXME: This logic should probably go higher up, where we can
2730b57cec5SDimitry Andric       // test these conditions symbolically.
2740b57cec5SDimitry Andric 
2755f757f3fSDimitry Andric       if (V2.isNegative() || V2.getBitWidth() > 64)
2760b57cec5SDimitry Andric         return nullptr;
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric       uint64_t Amt = V2.getZExtValue();
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric       if (Amt >= V1.getBitWidth())
2810b57cec5SDimitry Andric         return nullptr;
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric       return &getValue( V1.operator<<( (unsigned) Amt ));
2840b57cec5SDimitry Andric     }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric     case BO_Shr: {
2870b57cec5SDimitry Andric       // FIXME: This logic should probably go higher up, where we can
2880b57cec5SDimitry Andric       // test these conditions symbolically.
2890b57cec5SDimitry Andric 
2905f757f3fSDimitry Andric       if (V2.isNegative() || V2.getBitWidth() > 64)
2910b57cec5SDimitry Andric         return nullptr;
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric       uint64_t Amt = V2.getZExtValue();
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric       if (Amt >= V1.getBitWidth())
2960b57cec5SDimitry Andric         return nullptr;
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric       return &getValue( V1.operator>>( (unsigned) Amt ));
2990b57cec5SDimitry Andric     }
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric     case BO_LT:
3020b57cec5SDimitry Andric       return &getTruthValue( V1 < V2 );
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric     case BO_GT:
3050b57cec5SDimitry Andric       return &getTruthValue( V1 > V2 );
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric     case BO_LE:
3080b57cec5SDimitry Andric       return &getTruthValue( V1 <= V2 );
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric     case BO_GE:
3110b57cec5SDimitry Andric       return &getTruthValue( V1 >= V2 );
3120b57cec5SDimitry Andric 
3130b57cec5SDimitry Andric     case BO_EQ:
3140b57cec5SDimitry Andric       return &getTruthValue( V1 == V2 );
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric     case BO_NE:
3170b57cec5SDimitry Andric       return &getTruthValue( V1 != V2 );
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric       // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric     case BO_And:
3220b57cec5SDimitry Andric       return &getValue( V1 & V2 );
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric     case BO_Or:
3250b57cec5SDimitry Andric       return &getValue( V1 | V2 );
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric     case BO_Xor:
3280b57cec5SDimitry Andric       return &getValue( V1 ^ V2 );
3290b57cec5SDimitry Andric   }
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric const std::pair<SVal, uintptr_t>&
getPersistentSValWithData(const SVal & V,uintptr_t Data)3330b57cec5SDimitry Andric BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
3340b57cec5SDimitry Andric   // Lazily create the folding set.
3350b57cec5SDimitry Andric   if (!PersistentSVals) PersistentSVals = new PersistentSValsTy();
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
3380b57cec5SDimitry Andric   void *InsertPos;
3390b57cec5SDimitry Andric   V.Profile(ID);
3400b57cec5SDimitry Andric   ID.AddPointer((void*) Data);
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric   PersistentSValsTy& Map = *((PersistentSValsTy*) PersistentSVals);
3430b57cec5SDimitry Andric 
3440b57cec5SDimitry Andric   using FoldNodeTy = llvm::FoldingSetNodeWrapper<SValData>;
3450b57cec5SDimitry Andric 
3460b57cec5SDimitry Andric   FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   if (!P) {
34906c3fb27SDimitry Andric     P = new (BPAlloc) FoldNodeTy(std::make_pair(V, Data));
3500b57cec5SDimitry Andric     Map.InsertNode(P, InsertPos);
3510b57cec5SDimitry Andric   }
3520b57cec5SDimitry Andric 
3530b57cec5SDimitry Andric   return P->getValue();
3540b57cec5SDimitry Andric }
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric const std::pair<SVal, SVal>&
getPersistentSValPair(const SVal & V1,const SVal & V2)3570b57cec5SDimitry Andric BasicValueFactory::getPersistentSValPair(const SVal& V1, const SVal& V2) {
3580b57cec5SDimitry Andric   // Lazily create the folding set.
3590b57cec5SDimitry Andric   if (!PersistentSValPairs) PersistentSValPairs = new PersistentSValPairsTy();
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   llvm::FoldingSetNodeID ID;
3620b57cec5SDimitry Andric   void *InsertPos;
3630b57cec5SDimitry Andric   V1.Profile(ID);
3640b57cec5SDimitry Andric   V2.Profile(ID);
3650b57cec5SDimitry Andric 
3660b57cec5SDimitry Andric   PersistentSValPairsTy& Map = *((PersistentSValPairsTy*) PersistentSValPairs);
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   using FoldNodeTy = llvm::FoldingSetNodeWrapper<SValPair>;
3690b57cec5SDimitry Andric 
3700b57cec5SDimitry Andric   FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric   if (!P) {
37306c3fb27SDimitry Andric     P = new (BPAlloc) FoldNodeTy(std::make_pair(V1, V2));
3740b57cec5SDimitry Andric     Map.InsertNode(P, InsertPos);
3750b57cec5SDimitry Andric   }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   return P->getValue();
3780b57cec5SDimitry Andric }
3790b57cec5SDimitry Andric 
getPersistentSVal(SVal X)3800b57cec5SDimitry Andric const SVal* BasicValueFactory::getPersistentSVal(SVal X) {
3810b57cec5SDimitry Andric   return &getPersistentSValWithData(X, 0).first;
3820b57cec5SDimitry Andric }
383