1 //=== BasicValueFactory.cpp - Basic values for Path Sens analysis --*- C++ -*-//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines BasicValueFactory, a class that manages the lifetime
11 // of APSInt objects and symbolic constraints used by ExprEngine
12 // and related classes.
14 //===----------------------------------------------------------------------===//
16 #include "clang/StaticAnalyzer/PathSensitive/BasicValueFactory.h"
18 using namespace clang
;
21 void CompoundValData::Profile(llvm::FoldingSetNodeID
& ID
, QualType T
,
22 llvm::ImmutableList
<SVal
> L
) {
24 ID
.AddPointer(L
.getInternalPointer());
27 void LazyCompoundValData::Profile(llvm::FoldingSetNodeID
& ID
,
28 const void *store
,const TypedRegion
*region
) {
30 ID
.AddPointer(region
);
33 typedef std::pair
<SVal
, uintptr_t> SValData
;
34 typedef std::pair
<SVal
, SVal
> SValPair
;
37 template<> struct FoldingSetTrait
<SValData
> {
38 static inline void Profile(const SValData
& X
, llvm::FoldingSetNodeID
& ID
) {
40 ID
.AddPointer( (void*) X
.second
);
44 template<> struct FoldingSetTrait
<SValPair
> {
45 static inline void Profile(const SValPair
& X
, llvm::FoldingSetNodeID
& ID
) {
52 typedef llvm::FoldingSet
<llvm::FoldingSetNodeWrapper
<SValData
> >
55 typedef llvm::FoldingSet
<llvm::FoldingSetNodeWrapper
<SValPair
> >
56 PersistentSValPairsTy
;
58 BasicValueFactory::~BasicValueFactory() {
59 // Note that the dstor for the contents of APSIntSet will never be called,
60 // so we iterate over the set and invoke the dstor for each APSInt. This
61 // frees an aux. memory allocated to represent very large constants.
62 for (APSIntSetTy::iterator I
=APSIntSet
.begin(), E
=APSIntSet
.end(); I
!=E
; ++I
)
63 I
->getValue().~APSInt();
65 delete (PersistentSValsTy
*) PersistentSVals
;
66 delete (PersistentSValPairsTy
*) PersistentSValPairs
;
69 const llvm::APSInt
& BasicValueFactory::getValue(const llvm::APSInt
& X
) {
70 llvm::FoldingSetNodeID ID
;
72 typedef llvm::FoldingSetNodeWrapper
<llvm::APSInt
> FoldNodeTy
;
75 FoldNodeTy
* P
= APSIntSet
.FindNodeOrInsertPos(ID
, InsertPos
);
78 P
= (FoldNodeTy
*) BPAlloc
.Allocate
<FoldNodeTy
>();
79 new (P
) FoldNodeTy(X
);
80 APSIntSet
.InsertNode(P
, InsertPos
);
86 const llvm::APSInt
& BasicValueFactory::getValue(const llvm::APInt
& X
,
88 llvm::APSInt
V(X
, isUnsigned
);
92 const llvm::APSInt
& BasicValueFactory::getValue(uint64_t X
, unsigned BitWidth
,
94 llvm::APSInt
V(BitWidth
, isUnsigned
);
99 const llvm::APSInt
& BasicValueFactory::getValue(uint64_t X
, QualType T
) {
101 unsigned bits
= Ctx
.getTypeSize(T
);
102 llvm::APSInt
V(bits
, T
->isUnsignedIntegerType() || Loc::IsLocType(T
));
107 const CompoundValData
*
108 BasicValueFactory::getCompoundValData(QualType T
,
109 llvm::ImmutableList
<SVal
> Vals
) {
111 llvm::FoldingSetNodeID ID
;
112 CompoundValData::Profile(ID
, T
, Vals
);
115 CompoundValData
* D
= CompoundValDataSet
.FindNodeOrInsertPos(ID
, InsertPos
);
118 D
= (CompoundValData
*) BPAlloc
.Allocate
<CompoundValData
>();
119 new (D
) CompoundValData(T
, Vals
);
120 CompoundValDataSet
.InsertNode(D
, InsertPos
);
126 const LazyCompoundValData
*
127 BasicValueFactory::getLazyCompoundValData(const void *store
,
128 const TypedRegion
*region
) {
129 llvm::FoldingSetNodeID ID
;
130 LazyCompoundValData::Profile(ID
, store
, region
);
133 LazyCompoundValData
*D
=
134 LazyCompoundValDataSet
.FindNodeOrInsertPos(ID
, InsertPos
);
137 D
= (LazyCompoundValData
*) BPAlloc
.Allocate
<LazyCompoundValData
>();
138 new (D
) LazyCompoundValData(store
, region
);
139 LazyCompoundValDataSet
.InsertNode(D
, InsertPos
);
146 BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op
,
147 const llvm::APSInt
& V1
, const llvm::APSInt
& V2
) {
151 assert (false && "Invalid Opcode.");
154 return &getValue( V1
* V2
);
157 return &getValue( V1
/ V2
);
160 return &getValue( V1
% V2
);
163 return &getValue( V1
+ V2
);
166 return &getValue( V1
- V2
);
170 // FIXME: This logic should probably go higher up, where we can
171 // test these conditions symbolically.
173 // FIXME: Expand these checks to include all undefined behavior.
175 if (V2
.isSigned() && V2
.isNegative())
178 uint64_t Amt
= V2
.getZExtValue();
180 if (Amt
> V1
.getBitWidth())
183 return &getValue( V1
.operator<<( (unsigned) Amt
));
188 // FIXME: This logic should probably go higher up, where we can
189 // test these conditions symbolically.
191 // FIXME: Expand these checks to include all undefined behavior.
193 if (V2
.isSigned() && V2
.isNegative())
196 uint64_t Amt
= V2
.getZExtValue();
198 if (Amt
> V1
.getBitWidth())
201 return &getValue( V1
.operator>>( (unsigned) Amt
));
205 return &getTruthValue( V1
< V2
);
208 return &getTruthValue( V1
> V2
);
211 return &getTruthValue( V1
<= V2
);
214 return &getTruthValue( V1
>= V2
);
217 return &getTruthValue( V1
== V2
);
220 return &getTruthValue( V1
!= V2
);
222 // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
225 return &getValue( V1
& V2
);
228 return &getValue( V1
| V2
);
231 return &getValue( V1
^ V2
);
236 const std::pair
<SVal
, uintptr_t>&
237 BasicValueFactory::getPersistentSValWithData(const SVal
& V
, uintptr_t Data
) {
239 // Lazily create the folding set.
240 if (!PersistentSVals
) PersistentSVals
= new PersistentSValsTy();
242 llvm::FoldingSetNodeID ID
;
245 ID
.AddPointer((void*) Data
);
247 PersistentSValsTy
& Map
= *((PersistentSValsTy
*) PersistentSVals
);
249 typedef llvm::FoldingSetNodeWrapper
<SValData
> FoldNodeTy
;
250 FoldNodeTy
* P
= Map
.FindNodeOrInsertPos(ID
, InsertPos
);
253 P
= (FoldNodeTy
*) BPAlloc
.Allocate
<FoldNodeTy
>();
254 new (P
) FoldNodeTy(std::make_pair(V
, Data
));
255 Map
.InsertNode(P
, InsertPos
);
258 return P
->getValue();
261 const std::pair
<SVal
, SVal
>&
262 BasicValueFactory::getPersistentSValPair(const SVal
& V1
, const SVal
& V2
) {
264 // Lazily create the folding set.
265 if (!PersistentSValPairs
) PersistentSValPairs
= new PersistentSValPairsTy();
267 llvm::FoldingSetNodeID ID
;
272 PersistentSValPairsTy
& Map
= *((PersistentSValPairsTy
*) PersistentSValPairs
);
274 typedef llvm::FoldingSetNodeWrapper
<SValPair
> FoldNodeTy
;
275 FoldNodeTy
* P
= Map
.FindNodeOrInsertPos(ID
, InsertPos
);
278 P
= (FoldNodeTy
*) BPAlloc
.Allocate
<FoldNodeTy
>();
279 new (P
) FoldNodeTy(std::make_pair(V1
, V2
));
280 Map
.InsertNode(P
, InsertPos
);
283 return P
->getValue();
286 const SVal
* BasicValueFactory::getPersistentSVal(SVal X
) {
287 return &getPersistentSValWithData(X
, 0).first
;