1e029a2ffSEugene Zelenko //===- BasicValueFactory.cpp - Basic values for Path Sens analysis --------===//
2fa0734ecSArgyrios Kyrtzidis //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fa0734ecSArgyrios Kyrtzidis //
7fa0734ecSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
8fa0734ecSArgyrios Kyrtzidis //
9fa0734ecSArgyrios Kyrtzidis // This file defines BasicValueFactory, a class that manages the lifetime
10fa0734ecSArgyrios Kyrtzidis // of APSInt objects and symbolic constraints used by ExprEngine
11fa0734ecSArgyrios Kyrtzidis // and related classes.
12fa0734ecSArgyrios Kyrtzidis //
13fa0734ecSArgyrios Kyrtzidis //===----------------------------------------------------------------------===//
14fa0734ecSArgyrios Kyrtzidis
15f8cbac4bSTed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h"
16e029a2ffSEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
17e029a2ffSEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
182f1f0232STed Kremenek #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
19e029a2ffSEugene Zelenko #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h"
20e029a2ffSEugene Zelenko #include "llvm/ADT/APSInt.h"
21e029a2ffSEugene Zelenko #include "llvm/ADT/FoldingSet.h"
22e029a2ffSEugene Zelenko #include "llvm/ADT/ImmutableList.h"
23e029a2ffSEugene Zelenko #include "llvm/ADT/STLExtras.h"
24*21daada9SDeep Majumder #include "llvm/ADT/SmallPtrSet.h"
25e029a2ffSEugene Zelenko #include <cassert>
26e029a2ffSEugene Zelenko #include <cstdint>
27e029a2ffSEugene Zelenko #include <utility>
28fa0734ecSArgyrios Kyrtzidis
29fa0734ecSArgyrios Kyrtzidis using namespace clang;
30fa0734ecSArgyrios Kyrtzidis using namespace ento;
31fa0734ecSArgyrios Kyrtzidis
Profile(llvm::FoldingSetNodeID & ID,QualType T,llvm::ImmutableList<SVal> L)32fa0734ecSArgyrios Kyrtzidis void CompoundValData::Profile(llvm::FoldingSetNodeID& ID, QualType T,
33fa0734ecSArgyrios Kyrtzidis llvm::ImmutableList<SVal> L) {
34fa0734ecSArgyrios Kyrtzidis T.Profile(ID);
35fa0734ecSArgyrios Kyrtzidis ID.AddPointer(L.getInternalPointer());
36fa0734ecSArgyrios Kyrtzidis }
37fa0734ecSArgyrios Kyrtzidis
Profile(llvm::FoldingSetNodeID & ID,const StoreRef & store,const TypedValueRegion * region)38fa0734ecSArgyrios Kyrtzidis void LazyCompoundValData::Profile(llvm::FoldingSetNodeID& ID,
394bb6c6b3STed Kremenek const StoreRef &store,
408df44b26STed Kremenek const TypedValueRegion *region) {
414bb6c6b3STed Kremenek ID.AddPointer(store.getStore());
42fa0734ecSArgyrios Kyrtzidis ID.AddPointer(region);
43fa0734ecSArgyrios Kyrtzidis }
44fa0734ecSArgyrios Kyrtzidis
Profile(llvm::FoldingSetNodeID & ID,const NamedDecl * D,llvm::ImmutableList<const CXXBaseSpecifier * > L)4564c01f7bSDevin Coughlin void PointerToMemberData::Profile(
469cbfdde2SValeriy Savchenko llvm::FoldingSetNodeID &ID, const NamedDecl *D,
4764c01f7bSDevin Coughlin llvm::ImmutableList<const CXXBaseSpecifier *> L) {
4864c01f7bSDevin Coughlin ID.AddPointer(D);
4964c01f7bSDevin Coughlin ID.AddPointer(L.getInternalPointer());
5064c01f7bSDevin Coughlin }
5164c01f7bSDevin Coughlin
52e029a2ffSEugene Zelenko using SValData = std::pair<SVal, uintptr_t>;
53e029a2ffSEugene Zelenko using SValPair = std::pair<SVal, SVal>;
54fa0734ecSArgyrios Kyrtzidis
55fa0734ecSArgyrios Kyrtzidis namespace llvm {
56e029a2ffSEugene Zelenko
57fa0734ecSArgyrios Kyrtzidis template<> struct FoldingSetTrait<SValData> {
Profilellvm::FoldingSetTrait58fa0734ecSArgyrios Kyrtzidis static inline void Profile(const SValData& X, llvm::FoldingSetNodeID& ID) {
59fa0734ecSArgyrios Kyrtzidis X.first.Profile(ID);
60fa0734ecSArgyrios Kyrtzidis ID.AddPointer( (void*) X.second);
61fa0734ecSArgyrios Kyrtzidis }
62fa0734ecSArgyrios Kyrtzidis };
63fa0734ecSArgyrios Kyrtzidis
64fa0734ecSArgyrios Kyrtzidis template<> struct FoldingSetTrait<SValPair> {
Profilellvm::FoldingSetTrait65fa0734ecSArgyrios Kyrtzidis static inline void Profile(const SValPair& X, llvm::FoldingSetNodeID& ID) {
66fa0734ecSArgyrios Kyrtzidis X.first.Profile(ID);
67fa0734ecSArgyrios Kyrtzidis X.second.Profile(ID);
68fa0734ecSArgyrios Kyrtzidis }
69fa0734ecSArgyrios Kyrtzidis };
70fa0734ecSArgyrios Kyrtzidis
71e029a2ffSEugene Zelenko } // namespace llvm
72fa0734ecSArgyrios Kyrtzidis
73e029a2ffSEugene Zelenko using PersistentSValsTy =
74e029a2ffSEugene Zelenko llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValData>>;
75e029a2ffSEugene Zelenko
76e029a2ffSEugene Zelenko using PersistentSValPairsTy =
77e029a2ffSEugene Zelenko llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValPair>>;
78fa0734ecSArgyrios Kyrtzidis
~BasicValueFactory()79fa0734ecSArgyrios Kyrtzidis BasicValueFactory::~BasicValueFactory() {
80fa0734ecSArgyrios Kyrtzidis // Note that the dstor for the contents of APSIntSet will never be called,
81fa0734ecSArgyrios Kyrtzidis // so we iterate over the set and invoke the dstor for each APSInt. This
82fa0734ecSArgyrios Kyrtzidis // frees an aux. memory allocated to represent very large constants.
83e029a2ffSEugene Zelenko for (const auto &I : APSIntSet)
84e029a2ffSEugene Zelenko I.getValue().~APSInt();
85fa0734ecSArgyrios Kyrtzidis
86fa0734ecSArgyrios Kyrtzidis delete (PersistentSValsTy*) PersistentSVals;
87fa0734ecSArgyrios Kyrtzidis delete (PersistentSValPairsTy*) PersistentSValPairs;
88fa0734ecSArgyrios Kyrtzidis }
89fa0734ecSArgyrios Kyrtzidis
getValue(const llvm::APSInt & X)90fa0734ecSArgyrios Kyrtzidis const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
91fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID ID;
92fa0734ecSArgyrios Kyrtzidis void *InsertPos;
93e029a2ffSEugene Zelenko
94e029a2ffSEugene Zelenko using FoldNodeTy = llvm::FoldingSetNodeWrapper<llvm::APSInt>;
95fa0734ecSArgyrios Kyrtzidis
96fa0734ecSArgyrios Kyrtzidis X.Profile(ID);
97fa0734ecSArgyrios Kyrtzidis FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
98fa0734ecSArgyrios Kyrtzidis
99fa0734ecSArgyrios Kyrtzidis if (!P) {
100fa0734ecSArgyrios Kyrtzidis P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
101fa0734ecSArgyrios Kyrtzidis new (P) FoldNodeTy(X);
102fa0734ecSArgyrios Kyrtzidis APSIntSet.InsertNode(P, InsertPos);
103fa0734ecSArgyrios Kyrtzidis }
104fa0734ecSArgyrios Kyrtzidis
105fa0734ecSArgyrios Kyrtzidis return *P;
106fa0734ecSArgyrios Kyrtzidis }
107fa0734ecSArgyrios Kyrtzidis
getValue(const llvm::APInt & X,bool isUnsigned)108fa0734ecSArgyrios Kyrtzidis const llvm::APSInt& BasicValueFactory::getValue(const llvm::APInt& X,
109fa0734ecSArgyrios Kyrtzidis bool isUnsigned) {
110fa0734ecSArgyrios Kyrtzidis llvm::APSInt V(X, isUnsigned);
111fa0734ecSArgyrios Kyrtzidis return getValue(V);
112fa0734ecSArgyrios Kyrtzidis }
113fa0734ecSArgyrios Kyrtzidis
getValue(uint64_t X,unsigned BitWidth,bool isUnsigned)114fa0734ecSArgyrios Kyrtzidis const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,
115fa0734ecSArgyrios Kyrtzidis bool isUnsigned) {
116fa0734ecSArgyrios Kyrtzidis llvm::APSInt V(BitWidth, isUnsigned);
117fa0734ecSArgyrios Kyrtzidis V = X;
118fa0734ecSArgyrios Kyrtzidis return getValue(V);
119fa0734ecSArgyrios Kyrtzidis }
120fa0734ecSArgyrios Kyrtzidis
getValue(uint64_t X,QualType T)121fa0734ecSArgyrios Kyrtzidis const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
12221580c2fSJordan Rose return getValue(getAPSIntType(T).getValue(X));
123fa0734ecSArgyrios Kyrtzidis }
124fa0734ecSArgyrios Kyrtzidis
125fa0734ecSArgyrios Kyrtzidis const CompoundValData*
getCompoundValData(QualType T,llvm::ImmutableList<SVal> Vals)126fa0734ecSArgyrios Kyrtzidis BasicValueFactory::getCompoundValData(QualType T,
127fa0734ecSArgyrios Kyrtzidis llvm::ImmutableList<SVal> Vals) {
128fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID ID;
129fa0734ecSArgyrios Kyrtzidis CompoundValData::Profile(ID, T, Vals);
130fa0734ecSArgyrios Kyrtzidis void *InsertPos;
131fa0734ecSArgyrios Kyrtzidis
132fa0734ecSArgyrios Kyrtzidis CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
133fa0734ecSArgyrios Kyrtzidis
134fa0734ecSArgyrios Kyrtzidis if (!D) {
135fa0734ecSArgyrios Kyrtzidis D = (CompoundValData*) BPAlloc.Allocate<CompoundValData>();
136fa0734ecSArgyrios Kyrtzidis new (D) CompoundValData(T, Vals);
137fa0734ecSArgyrios Kyrtzidis CompoundValDataSet.InsertNode(D, InsertPos);
138fa0734ecSArgyrios Kyrtzidis }
139fa0734ecSArgyrios Kyrtzidis
140fa0734ecSArgyrios Kyrtzidis return D;
141fa0734ecSArgyrios Kyrtzidis }
142fa0734ecSArgyrios Kyrtzidis
143fa0734ecSArgyrios Kyrtzidis const LazyCompoundValData*
getLazyCompoundValData(const StoreRef & store,const TypedValueRegion * region)1444bb6c6b3STed Kremenek BasicValueFactory::getLazyCompoundValData(const StoreRef &store,
1458df44b26STed Kremenek const TypedValueRegion *region) {
146fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID ID;
147fa0734ecSArgyrios Kyrtzidis LazyCompoundValData::Profile(ID, store, region);
148fa0734ecSArgyrios Kyrtzidis void *InsertPos;
149fa0734ecSArgyrios Kyrtzidis
150fa0734ecSArgyrios Kyrtzidis LazyCompoundValData *D =
151fa0734ecSArgyrios Kyrtzidis LazyCompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
152fa0734ecSArgyrios Kyrtzidis
153fa0734ecSArgyrios Kyrtzidis if (!D) {
154fa0734ecSArgyrios Kyrtzidis D = (LazyCompoundValData*) BPAlloc.Allocate<LazyCompoundValData>();
155fa0734ecSArgyrios Kyrtzidis new (D) LazyCompoundValData(store, region);
156fa0734ecSArgyrios Kyrtzidis LazyCompoundValDataSet.InsertNode(D, InsertPos);
157fa0734ecSArgyrios Kyrtzidis }
158fa0734ecSArgyrios Kyrtzidis
159fa0734ecSArgyrios Kyrtzidis return D;
160fa0734ecSArgyrios Kyrtzidis }
161fa0734ecSArgyrios Kyrtzidis
getPointerToMemberData(const NamedDecl * ND,llvm::ImmutableList<const CXXBaseSpecifier * > L)16264c01f7bSDevin Coughlin const PointerToMemberData *BasicValueFactory::getPointerToMemberData(
1639cbfdde2SValeriy Savchenko const NamedDecl *ND, llvm::ImmutableList<const CXXBaseSpecifier *> L) {
16464c01f7bSDevin Coughlin llvm::FoldingSetNodeID ID;
1659cbfdde2SValeriy Savchenko PointerToMemberData::Profile(ID, ND, L);
16664c01f7bSDevin Coughlin void *InsertPos;
16764c01f7bSDevin Coughlin
16864c01f7bSDevin Coughlin PointerToMemberData *D =
16964c01f7bSDevin Coughlin PointerToMemberDataSet.FindNodeOrInsertPos(ID, InsertPos);
17064c01f7bSDevin Coughlin
17164c01f7bSDevin Coughlin if (!D) {
17264c01f7bSDevin Coughlin D = (PointerToMemberData *)BPAlloc.Allocate<PointerToMemberData>();
1739cbfdde2SValeriy Savchenko new (D) PointerToMemberData(ND, L);
17464c01f7bSDevin Coughlin PointerToMemberDataSet.InsertNode(D, InsertPos);
17564c01f7bSDevin Coughlin }
17664c01f7bSDevin Coughlin
17764c01f7bSDevin Coughlin return D;
17864c01f7bSDevin Coughlin }
17964c01f7bSDevin Coughlin
hasNoRepeatedElements(llvm::ImmutableList<const CXXBaseSpecifier * > BaseSpecList)180*21daada9SDeep Majumder LLVM_ATTRIBUTE_UNUSED bool hasNoRepeatedElements(
181*21daada9SDeep Majumder llvm::ImmutableList<const CXXBaseSpecifier *> BaseSpecList) {
182*21daada9SDeep Majumder llvm::SmallPtrSet<QualType, 16> BaseSpecSeen;
183*21daada9SDeep Majumder for (const CXXBaseSpecifier *BaseSpec : BaseSpecList) {
184*21daada9SDeep Majumder QualType BaseType = BaseSpec->getType();
185*21daada9SDeep Majumder // Check whether inserted
186*21daada9SDeep Majumder if (!BaseSpecSeen.insert(BaseType).second)
187*21daada9SDeep Majumder return false;
188*21daada9SDeep Majumder }
189*21daada9SDeep Majumder return true;
190*21daada9SDeep Majumder }
191*21daada9SDeep Majumder
accumCXXBase(llvm::iterator_range<CastExpr::path_const_iterator> PathRange,const nonloc::PointerToMember & PTM,const CastKind & kind)192e029a2ffSEugene Zelenko const PointerToMemberData *BasicValueFactory::accumCXXBase(
19364c01f7bSDevin Coughlin llvm::iterator_range<CastExpr::path_const_iterator> PathRange,
194*21daada9SDeep Majumder const nonloc::PointerToMember &PTM, const CastKind &kind) {
195*21daada9SDeep Majumder assert((kind == CK_DerivedToBaseMemberPointer ||
196*21daada9SDeep Majumder kind == CK_BaseToDerivedMemberPointer ||
197*21daada9SDeep Majumder kind == CK_ReinterpretMemberPointer) &&
198*21daada9SDeep Majumder "accumCXXBase called with wrong CastKind");
19964c01f7bSDevin Coughlin nonloc::PointerToMember::PTMDataType PTMDT = PTM.getPTMData();
2009cbfdde2SValeriy Savchenko const NamedDecl *ND = nullptr;
201*21daada9SDeep Majumder llvm::ImmutableList<const CXXBaseSpecifier *> BaseSpecList;
20264c01f7bSDevin Coughlin
2039cbfdde2SValeriy Savchenko if (PTMDT.isNull() || PTMDT.is<const NamedDecl *>()) {
2049cbfdde2SValeriy Savchenko if (PTMDT.is<const NamedDecl *>())
2059cbfdde2SValeriy Savchenko ND = PTMDT.get<const NamedDecl *>();
20664c01f7bSDevin Coughlin
207*21daada9SDeep Majumder BaseSpecList = CXXBaseListFactory.getEmptyList();
208*21daada9SDeep Majumder } else {
2099cbfdde2SValeriy Savchenko const PointerToMemberData *PTMD = PTMDT.get<const PointerToMemberData *>();
2109cbfdde2SValeriy Savchenko ND = PTMD->getDeclaratorDecl();
21164c01f7bSDevin Coughlin
212*21daada9SDeep Majumder BaseSpecList = PTMD->getCXXBaseList();
21364c01f7bSDevin Coughlin }
21464c01f7bSDevin Coughlin
215*21daada9SDeep Majumder assert(hasNoRepeatedElements(BaseSpecList) &&
216*21daada9SDeep Majumder "CXXBaseSpecifier list of PointerToMemberData must not have repeated "
217*21daada9SDeep Majumder "elements");
218*21daada9SDeep Majumder
219*21daada9SDeep Majumder if (kind == CK_DerivedToBaseMemberPointer) {
220*21daada9SDeep Majumder // Here we pop off matching CXXBaseSpecifiers from BaseSpecList.
221*21daada9SDeep Majumder // Because, CK_DerivedToBaseMemberPointer comes from a static_cast and
222*21daada9SDeep Majumder // serves to remove a matching implicit cast. Note that static_cast's that
223*21daada9SDeep Majumder // are no-ops do not count since they produce an empty PathRange, a nice
224*21daada9SDeep Majumder // thing about Clang AST.
225*21daada9SDeep Majumder
226*21daada9SDeep Majumder // Now we know that there are no repetitions in BaseSpecList.
227*21daada9SDeep Majumder // So, popping the first element from it corresponding to each element in
228*21daada9SDeep Majumder // PathRange is equivalent to only including elements that are in
229*21daada9SDeep Majumder // BaseSpecList but not it PathRange
230*21daada9SDeep Majumder auto ReducedBaseSpecList = CXXBaseListFactory.getEmptyList();
231*21daada9SDeep Majumder for (const CXXBaseSpecifier *BaseSpec : BaseSpecList) {
232*21daada9SDeep Majumder auto IsSameAsBaseSpec = [&BaseSpec](const CXXBaseSpecifier *I) -> bool {
233*21daada9SDeep Majumder return BaseSpec->getType() == I->getType();
234*21daada9SDeep Majumder };
235*21daada9SDeep Majumder if (llvm::none_of(PathRange, IsSameAsBaseSpec))
236*21daada9SDeep Majumder ReducedBaseSpecList =
237*21daada9SDeep Majumder CXXBaseListFactory.add(BaseSpec, ReducedBaseSpecList);
238*21daada9SDeep Majumder }
239*21daada9SDeep Majumder
240*21daada9SDeep Majumder return getPointerToMemberData(ND, ReducedBaseSpecList);
241*21daada9SDeep Majumder }
242*21daada9SDeep Majumder // FIXME: Reinterpret casts on member-pointers are not handled properly by
243*21daada9SDeep Majumder // this code
244*21daada9SDeep Majumder for (const CXXBaseSpecifier *I : llvm::reverse(PathRange))
245*21daada9SDeep Majumder BaseSpecList = prependCXXBase(I, BaseSpecList);
246*21daada9SDeep Majumder return getPointerToMemberData(ND, BaseSpecList);
24764c01f7bSDevin Coughlin }
24864c01f7bSDevin Coughlin
249fa0734ecSArgyrios Kyrtzidis const llvm::APSInt*
evalAPSInt(BinaryOperator::Opcode Op,const llvm::APSInt & V1,const llvm::APSInt & V2)250fa0734ecSArgyrios Kyrtzidis BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op,
251fa0734ecSArgyrios Kyrtzidis const llvm::APSInt& V1, const llvm::APSInt& V2) {
252fa0734ecSArgyrios Kyrtzidis switch (Op) {
253fa0734ecSArgyrios Kyrtzidis default:
254fbd5039bSFangrui Song llvm_unreachable("Invalid Opcode.");
255fa0734ecSArgyrios Kyrtzidis
256fa0734ecSArgyrios Kyrtzidis case BO_Mul:
257fa0734ecSArgyrios Kyrtzidis return &getValue( V1 * V2 );
258fa0734ecSArgyrios Kyrtzidis
259fa0734ecSArgyrios Kyrtzidis case BO_Div:
2600dadfa8dSDaniel Marjamaki if (V2 == 0) // Avoid division by zero
2610dadfa8dSDaniel Marjamaki return nullptr;
262fa0734ecSArgyrios Kyrtzidis return &getValue( V1 / V2 );
263fa0734ecSArgyrios Kyrtzidis
264fa0734ecSArgyrios Kyrtzidis case BO_Rem:
2650dadfa8dSDaniel Marjamaki if (V2 == 0) // Avoid division by zero
2660dadfa8dSDaniel Marjamaki return nullptr;
267fa0734ecSArgyrios Kyrtzidis return &getValue( V1 % V2 );
268fa0734ecSArgyrios Kyrtzidis
269fa0734ecSArgyrios Kyrtzidis case BO_Add:
270fa0734ecSArgyrios Kyrtzidis return &getValue( V1 + V2 );
271fa0734ecSArgyrios Kyrtzidis
272fa0734ecSArgyrios Kyrtzidis case BO_Sub:
273fa0734ecSArgyrios Kyrtzidis return &getValue( V1 - V2 );
274fa0734ecSArgyrios Kyrtzidis
275fa0734ecSArgyrios Kyrtzidis case BO_Shl: {
276fa0734ecSArgyrios Kyrtzidis // FIXME: This logic should probably go higher up, where we can
277fa0734ecSArgyrios Kyrtzidis // test these conditions symbolically.
278fa0734ecSArgyrios Kyrtzidis
279fa0734ecSArgyrios Kyrtzidis if (V2.isSigned() && V2.isNegative())
2800dbb783cSCraig Topper return nullptr;
281fa0734ecSArgyrios Kyrtzidis
282fa0734ecSArgyrios Kyrtzidis uint64_t Amt = V2.getZExtValue();
283fa0734ecSArgyrios Kyrtzidis
2842be02a78SJordan Rose if (Amt >= V1.getBitWidth())
2850dbb783cSCraig Topper return nullptr;
286fa0734ecSArgyrios Kyrtzidis
2876a308943SAaron Ballman if (!Ctx.getLangOpts().CPlusPlus20) {
2887939ba08SRichard Smith if (V1.isSigned() && V1.isNegative())
2897939ba08SRichard Smith return nullptr;
2907939ba08SRichard Smith
291596fcb1bSGabor Horvath if (V1.isSigned() && Amt > V1.countLeadingZeros())
292596fcb1bSGabor Horvath return nullptr;
2937939ba08SRichard Smith }
294596fcb1bSGabor Horvath
295fa0734ecSArgyrios Kyrtzidis return &getValue( V1.operator<<( (unsigned) Amt ));
296fa0734ecSArgyrios Kyrtzidis }
297fa0734ecSArgyrios Kyrtzidis
298fa0734ecSArgyrios Kyrtzidis case BO_Shr: {
299fa0734ecSArgyrios Kyrtzidis // FIXME: This logic should probably go higher up, where we can
300fa0734ecSArgyrios Kyrtzidis // test these conditions symbolically.
301fa0734ecSArgyrios Kyrtzidis
302fa0734ecSArgyrios Kyrtzidis if (V2.isSigned() && V2.isNegative())
3030dbb783cSCraig Topper return nullptr;
304fa0734ecSArgyrios Kyrtzidis
305fa0734ecSArgyrios Kyrtzidis uint64_t Amt = V2.getZExtValue();
306fa0734ecSArgyrios Kyrtzidis
3072be02a78SJordan Rose if (Amt >= V1.getBitWidth())
3080dbb783cSCraig Topper return nullptr;
309fa0734ecSArgyrios Kyrtzidis
310fa0734ecSArgyrios Kyrtzidis return &getValue( V1.operator>>( (unsigned) Amt ));
311fa0734ecSArgyrios Kyrtzidis }
312fa0734ecSArgyrios Kyrtzidis
313fa0734ecSArgyrios Kyrtzidis case BO_LT:
314fa0734ecSArgyrios Kyrtzidis return &getTruthValue( V1 < V2 );
315fa0734ecSArgyrios Kyrtzidis
316fa0734ecSArgyrios Kyrtzidis case BO_GT:
317fa0734ecSArgyrios Kyrtzidis return &getTruthValue( V1 > V2 );
318fa0734ecSArgyrios Kyrtzidis
319fa0734ecSArgyrios Kyrtzidis case BO_LE:
320fa0734ecSArgyrios Kyrtzidis return &getTruthValue( V1 <= V2 );
321fa0734ecSArgyrios Kyrtzidis
322fa0734ecSArgyrios Kyrtzidis case BO_GE:
323fa0734ecSArgyrios Kyrtzidis return &getTruthValue( V1 >= V2 );
324fa0734ecSArgyrios Kyrtzidis
325fa0734ecSArgyrios Kyrtzidis case BO_EQ:
326fa0734ecSArgyrios Kyrtzidis return &getTruthValue( V1 == V2 );
327fa0734ecSArgyrios Kyrtzidis
328fa0734ecSArgyrios Kyrtzidis case BO_NE:
329fa0734ecSArgyrios Kyrtzidis return &getTruthValue( V1 != V2 );
330fa0734ecSArgyrios Kyrtzidis
331fa0734ecSArgyrios Kyrtzidis // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
332fa0734ecSArgyrios Kyrtzidis
333fa0734ecSArgyrios Kyrtzidis case BO_And:
334fa0734ecSArgyrios Kyrtzidis return &getValue( V1 & V2 );
335fa0734ecSArgyrios Kyrtzidis
336fa0734ecSArgyrios Kyrtzidis case BO_Or:
337fa0734ecSArgyrios Kyrtzidis return &getValue( V1 | V2 );
338fa0734ecSArgyrios Kyrtzidis
339fa0734ecSArgyrios Kyrtzidis case BO_Xor:
340fa0734ecSArgyrios Kyrtzidis return &getValue( V1 ^ V2 );
341fa0734ecSArgyrios Kyrtzidis }
342fa0734ecSArgyrios Kyrtzidis }
343fa0734ecSArgyrios Kyrtzidis
344fa0734ecSArgyrios Kyrtzidis const std::pair<SVal, uintptr_t>&
getPersistentSValWithData(const SVal & V,uintptr_t Data)345fa0734ecSArgyrios Kyrtzidis BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
346fa0734ecSArgyrios Kyrtzidis // Lazily create the folding set.
347fa0734ecSArgyrios Kyrtzidis if (!PersistentSVals) PersistentSVals = new PersistentSValsTy();
348fa0734ecSArgyrios Kyrtzidis
349fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID ID;
350fa0734ecSArgyrios Kyrtzidis void *InsertPos;
351fa0734ecSArgyrios Kyrtzidis V.Profile(ID);
352fa0734ecSArgyrios Kyrtzidis ID.AddPointer((void*) Data);
353fa0734ecSArgyrios Kyrtzidis
354fa0734ecSArgyrios Kyrtzidis PersistentSValsTy& Map = *((PersistentSValsTy*) PersistentSVals);
355fa0734ecSArgyrios Kyrtzidis
356e029a2ffSEugene Zelenko using FoldNodeTy = llvm::FoldingSetNodeWrapper<SValData>;
357e029a2ffSEugene Zelenko
358fa0734ecSArgyrios Kyrtzidis FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
359fa0734ecSArgyrios Kyrtzidis
360fa0734ecSArgyrios Kyrtzidis if (!P) {
361fa0734ecSArgyrios Kyrtzidis P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
362fa0734ecSArgyrios Kyrtzidis new (P) FoldNodeTy(std::make_pair(V, Data));
363fa0734ecSArgyrios Kyrtzidis Map.InsertNode(P, InsertPos);
364fa0734ecSArgyrios Kyrtzidis }
365fa0734ecSArgyrios Kyrtzidis
366fa0734ecSArgyrios Kyrtzidis return P->getValue();
367fa0734ecSArgyrios Kyrtzidis }
368fa0734ecSArgyrios Kyrtzidis
369fa0734ecSArgyrios Kyrtzidis const std::pair<SVal, SVal>&
getPersistentSValPair(const SVal & V1,const SVal & V2)370fa0734ecSArgyrios Kyrtzidis BasicValueFactory::getPersistentSValPair(const SVal& V1, const SVal& V2) {
371fa0734ecSArgyrios Kyrtzidis // Lazily create the folding set.
372fa0734ecSArgyrios Kyrtzidis if (!PersistentSValPairs) PersistentSValPairs = new PersistentSValPairsTy();
373fa0734ecSArgyrios Kyrtzidis
374fa0734ecSArgyrios Kyrtzidis llvm::FoldingSetNodeID ID;
375fa0734ecSArgyrios Kyrtzidis void *InsertPos;
376fa0734ecSArgyrios Kyrtzidis V1.Profile(ID);
377fa0734ecSArgyrios Kyrtzidis V2.Profile(ID);
378fa0734ecSArgyrios Kyrtzidis
379fa0734ecSArgyrios Kyrtzidis PersistentSValPairsTy& Map = *((PersistentSValPairsTy*) PersistentSValPairs);
380fa0734ecSArgyrios Kyrtzidis
381e029a2ffSEugene Zelenko using FoldNodeTy = llvm::FoldingSetNodeWrapper<SValPair>;
382e029a2ffSEugene Zelenko
383fa0734ecSArgyrios Kyrtzidis FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
384fa0734ecSArgyrios Kyrtzidis
385fa0734ecSArgyrios Kyrtzidis if (!P) {
386fa0734ecSArgyrios Kyrtzidis P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
387fa0734ecSArgyrios Kyrtzidis new (P) FoldNodeTy(std::make_pair(V1, V2));
388fa0734ecSArgyrios Kyrtzidis Map.InsertNode(P, InsertPos);
389fa0734ecSArgyrios Kyrtzidis }
390fa0734ecSArgyrios Kyrtzidis
391fa0734ecSArgyrios Kyrtzidis return P->getValue();
392fa0734ecSArgyrios Kyrtzidis }
393fa0734ecSArgyrios Kyrtzidis
getPersistentSVal(SVal X)394fa0734ecSArgyrios Kyrtzidis const SVal* BasicValueFactory::getPersistentSVal(SVal X) {
395fa0734ecSArgyrios Kyrtzidis return &getPersistentSValWithData(X, 0).first;
396fa0734ecSArgyrios Kyrtzidis }
397