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