blob: 246beead1208ce98ed36d54e58ca8270ac64dcbf [file] [log] [blame]
Ted Kremenek240f1f02008-03-07 20:13:31 +00001//=== BasicValueFactory.cpp - Basic values for Path Sens analysis --*- C++ -*-//
Ted Kremenekd70d0b02008-02-16 01:12:31 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Ted Kremenek240f1f02008-03-07 20:13:31 +000010// This file defines BasicValueFactory, a class that manages the lifetime
Mike Stump1eb44332009-09-09 15:08:12 +000011// of APSInt objects and symbolic constraints used by GRExprEngine
Ted Kremenek240f1f02008-03-07 20:13:31 +000012// and related classes.
Ted Kremenekd70d0b02008-02-16 01:12:31 +000013//
14//===----------------------------------------------------------------------===//
15
Ted Kremenek1309f9a2010-01-25 04:41:41 +000016#include "clang/Checker/PathSensitive/BasicValueFactory.h"
Ted Kremenekd70d0b02008-02-16 01:12:31 +000017
18using namespace clang;
19
Mike Stump1eb44332009-09-09 15:08:12 +000020void CompoundValData::Profile(llvm::FoldingSetNodeID& ID, QualType T,
Ted Kremenek632e8b82008-10-30 17:44:46 +000021 llvm::ImmutableList<SVal> L) {
Zhongxing Xu6764b722008-10-30 04:58:00 +000022 T.Profile(ID);
Ted Kremenek632e8b82008-10-30 17:44:46 +000023 ID.AddPointer(L.getInternalPointer());
Zhongxing Xu6764b722008-10-30 04:58:00 +000024}
25
Ted Kremeneka5e81f12009-08-06 01:20:57 +000026void LazyCompoundValData::Profile(llvm::FoldingSetNodeID& ID,
Zhongxing Xubfcaf802010-02-05 02:26:30 +000027 const void *store,const TypedRegion *region) {
28 ID.AddPointer(store);
Ted Kremeneka5e81f12009-08-06 01:20:57 +000029 ID.AddPointer(region);
30}
31
Zhongxing Xu1c96b242008-10-17 05:57:07 +000032typedef std::pair<SVal, uintptr_t> SValData;
33typedef std::pair<SVal, SVal> SValPair;
Ted Kremenek4d0348b2008-04-29 23:24:44 +000034
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000035namespace llvm {
Zhongxing Xu1c96b242008-10-17 05:57:07 +000036template<> struct FoldingSetTrait<SValData> {
37 static inline void Profile(const SValData& X, llvm::FoldingSetNodeID& ID) {
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000038 X.first.Profile(ID);
Ted Kremenek718c4f72008-04-29 22:17:41 +000039 ID.AddPointer( (void*) X.second);
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000040 }
41};
Mike Stump1eb44332009-09-09 15:08:12 +000042
Zhongxing Xu1c96b242008-10-17 05:57:07 +000043template<> struct FoldingSetTrait<SValPair> {
44 static inline void Profile(const SValPair& X, llvm::FoldingSetNodeID& ID) {
Ted Kremenek4d0348b2008-04-29 23:24:44 +000045 X.first.Profile(ID);
46 X.second.Profile(ID);
47 }
48};
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000049}
50
Zhongxing Xu1c96b242008-10-17 05:57:07 +000051typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValData> >
52 PersistentSValsTy;
Ted Kremenek0fe33bc2008-04-22 21:10:18 +000053
Zhongxing Xu1c96b242008-10-17 05:57:07 +000054typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValPair> >
55 PersistentSValPairsTy;
Ted Kremenek4d0348b2008-04-29 23:24:44 +000056
Ted Kremenek240f1f02008-03-07 20:13:31 +000057BasicValueFactory::~BasicValueFactory() {
Ted Kremenekd70d0b02008-02-16 01:12:31 +000058 // Note that the dstor for the contents of APSIntSet will never be called,
59 // so we iterate over the set and invoke the dstor for each APSInt. This
60 // frees an aux. memory allocated to represent very large constants.
61 for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
62 I->getValue().~APSInt();
Mike Stump1eb44332009-09-09 15:08:12 +000063
64 delete (PersistentSValsTy*) PersistentSVals;
Zhongxing Xu1c96b242008-10-17 05:57:07 +000065 delete (PersistentSValPairsTy*) PersistentSValPairs;
Ted Kremenekd70d0b02008-02-16 01:12:31 +000066}
67
Ted Kremenek240f1f02008-03-07 20:13:31 +000068const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
Ted Kremenekd70d0b02008-02-16 01:12:31 +000069 llvm::FoldingSetNodeID ID;
70 void* InsertPos;
71 typedef llvm::FoldingSetNodeWrapper<llvm::APSInt> FoldNodeTy;
Mike Stump1eb44332009-09-09 15:08:12 +000072
Ted Kremenekd70d0b02008-02-16 01:12:31 +000073 X.Profile(ID);
74 FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
Mike Stump1eb44332009-09-09 15:08:12 +000075
76 if (!P) {
Ted Kremenekd70d0b02008-02-16 01:12:31 +000077 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
78 new (P) FoldNodeTy(X);
79 APSIntSet.InsertNode(P, InsertPos);
80 }
Mike Stump1eb44332009-09-09 15:08:12 +000081
Ted Kremenekd70d0b02008-02-16 01:12:31 +000082 return *P;
83}
84
Zhongxing Xue8a964b2008-11-22 13:21:46 +000085const llvm::APSInt& BasicValueFactory::getValue(const llvm::APInt& X,
86 bool isUnsigned) {
87 llvm::APSInt V(X, isUnsigned);
88 return getValue(V);
89}
90
Ted Kremenek240f1f02008-03-07 20:13:31 +000091const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,
Ted Kremenekd70d0b02008-02-16 01:12:31 +000092 bool isUnsigned) {
93 llvm::APSInt V(BitWidth, isUnsigned);
Mike Stump1eb44332009-09-09 15:08:12 +000094 V = X;
Ted Kremenekd70d0b02008-02-16 01:12:31 +000095 return getValue(V);
96}
97
Ted Kremenek240f1f02008-03-07 20:13:31 +000098const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
Mike Stump1eb44332009-09-09 15:08:12 +000099
Chris Lattner98be4942008-03-05 18:54:05 +0000100 unsigned bits = Ctx.getTypeSize(T);
Ted Kremenekfa6228d2009-03-11 02:52:39 +0000101 llvm::APSInt V(bits, T->isUnsignedIntegerType() || Loc::IsLocType(T));
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000102 V = X;
103 return getValue(V);
104}
105
Mike Stump1eb44332009-09-09 15:08:12 +0000106const CompoundValData*
Ted Kremenek632e8b82008-10-30 17:44:46 +0000107BasicValueFactory::getCompoundValData(QualType T,
108 llvm::ImmutableList<SVal> Vals) {
Mike Stump1eb44332009-09-09 15:08:12 +0000109
Zhongxing Xu6764b722008-10-30 04:58:00 +0000110 llvm::FoldingSetNodeID ID;
Ted Kremenek632e8b82008-10-30 17:44:46 +0000111 CompoundValData::Profile(ID, T, Vals);
Zhongxing Xu6764b722008-10-30 04:58:00 +0000112 void* InsertPos;
113
114 CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
115
116 if (!D) {
117 D = (CompoundValData*) BPAlloc.Allocate<CompoundValData>();
Ted Kremenek632e8b82008-10-30 17:44:46 +0000118 new (D) CompoundValData(T, Vals);
Zhongxing Xu6764b722008-10-30 04:58:00 +0000119 CompoundValDataSet.InsertNode(D, InsertPos);
120 }
121
122 return D;
123}
124
Ted Kremeneka5e81f12009-08-06 01:20:57 +0000125const LazyCompoundValData*
Zhongxing Xubfcaf802010-02-05 02:26:30 +0000126BasicValueFactory::getLazyCompoundValData(const void *store,
Ted Kremeneka5e81f12009-08-06 01:20:57 +0000127 const TypedRegion *region) {
128 llvm::FoldingSetNodeID ID;
Zhongxing Xubfcaf802010-02-05 02:26:30 +0000129 LazyCompoundValData::Profile(ID, store, region);
Ted Kremeneka5e81f12009-08-06 01:20:57 +0000130 void* InsertPos;
Mike Stump1eb44332009-09-09 15:08:12 +0000131
Ted Kremeneka5e81f12009-08-06 01:20:57 +0000132 LazyCompoundValData *D =
133 LazyCompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
Mike Stump1eb44332009-09-09 15:08:12 +0000134
Ted Kremeneka5e81f12009-08-06 01:20:57 +0000135 if (!D) {
136 D = (LazyCompoundValData*) BPAlloc.Allocate<LazyCompoundValData>();
Zhongxing Xubfcaf802010-02-05 02:26:30 +0000137 new (D) LazyCompoundValData(store, region);
Ted Kremeneka5e81f12009-08-06 01:20:57 +0000138 LazyCompoundValDataSet.InsertNode(D, InsertPos);
139 }
Mike Stump1eb44332009-09-09 15:08:12 +0000140
Ted Kremeneka5e81f12009-08-06 01:20:57 +0000141 return D;
142}
143
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000144const llvm::APSInt*
Ted Kremenek240f1f02008-03-07 20:13:31 +0000145BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000146 const llvm::APSInt& V1, const llvm::APSInt& V2) {
Mike Stump1eb44332009-09-09 15:08:12 +0000147
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000148 switch (Op) {
149 default:
150 assert (false && "Invalid Opcode.");
Mike Stump1eb44332009-09-09 15:08:12 +0000151
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000152 case BinaryOperator::Mul:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000153 return &getValue( V1 * V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000154
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000155 case BinaryOperator::Div:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000156 return &getValue( V1 / V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000157
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000158 case BinaryOperator::Rem:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000159 return &getValue( V1 % V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000160
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000161 case BinaryOperator::Add:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000162 return &getValue( V1 + V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000163
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000164 case BinaryOperator::Sub:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000165 return &getValue( V1 - V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000166
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000167 case BinaryOperator::Shl: {
168
169 // FIXME: This logic should probably go higher up, where we can
170 // test these conditions symbolically.
Mike Stump1eb44332009-09-09 15:08:12 +0000171
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000172 // FIXME: Expand these checks to include all undefined behavior.
Mike Stump1eb44332009-09-09 15:08:12 +0000173
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000174 if (V2.isSigned() && V2.isNegative())
175 return NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000176
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000177 uint64_t Amt = V2.getZExtValue();
Mike Stump1eb44332009-09-09 15:08:12 +0000178
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000179 if (Amt > V1.getBitWidth())
180 return NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000181
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000182 return &getValue( V1.operator<<( (unsigned) Amt ));
183 }
Mike Stump1eb44332009-09-09 15:08:12 +0000184
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000185 case BinaryOperator::Shr: {
Mike Stump1eb44332009-09-09 15:08:12 +0000186
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000187 // FIXME: This logic should probably go higher up, where we can
188 // test these conditions symbolically.
Mike Stump1eb44332009-09-09 15:08:12 +0000189
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000190 // FIXME: Expand these checks to include all undefined behavior.
Mike Stump1eb44332009-09-09 15:08:12 +0000191
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000192 if (V2.isSigned() && V2.isNegative())
193 return NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000194
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000195 uint64_t Amt = V2.getZExtValue();
Mike Stump1eb44332009-09-09 15:08:12 +0000196
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000197 if (Amt > V1.getBitWidth())
198 return NULL;
Mike Stump1eb44332009-09-09 15:08:12 +0000199
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000200 return &getValue( V1.operator>>( (unsigned) Amt ));
201 }
Mike Stump1eb44332009-09-09 15:08:12 +0000202
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000203 case BinaryOperator::LT:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000204 return &getTruthValue( V1 < V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000205
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000206 case BinaryOperator::GT:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000207 return &getTruthValue( V1 > V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000208
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000209 case BinaryOperator::LE:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000210 return &getTruthValue( V1 <= V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000211
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000212 case BinaryOperator::GE:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000213 return &getTruthValue( V1 >= V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000214
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000215 case BinaryOperator::EQ:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000216 return &getTruthValue( V1 == V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000217
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000218 case BinaryOperator::NE:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000219 return &getTruthValue( V1 != V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000220
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000221 // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
Mike Stump1eb44332009-09-09 15:08:12 +0000222
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000223 case BinaryOperator::And:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000224 return &getValue( V1 & V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000225
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000226 case BinaryOperator::Or:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000227 return &getValue( V1 | V2 );
Mike Stump1eb44332009-09-09 15:08:12 +0000228
Ted Kremenek1caf26a2008-02-19 20:53:37 +0000229 case BinaryOperator::Xor:
Ted Kremenek8cc13ea2008-02-28 20:32:03 +0000230 return &getValue( V1 ^ V2 );
Ted Kremenekd70d0b02008-02-16 01:12:31 +0000231 }
232}
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000233
234
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000235const std::pair<SVal, uintptr_t>&
236BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
Mike Stump1eb44332009-09-09 15:08:12 +0000237
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000238 // Lazily create the folding set.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000239 if (!PersistentSVals) PersistentSVals = new PersistentSValsTy();
Mike Stump1eb44332009-09-09 15:08:12 +0000240
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000241 llvm::FoldingSetNodeID ID;
242 void* InsertPos;
243 V.Profile(ID);
Ted Kremenek718c4f72008-04-29 22:17:41 +0000244 ID.AddPointer((void*) Data);
Mike Stump1eb44332009-09-09 15:08:12 +0000245
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000246 PersistentSValsTy& Map = *((PersistentSValsTy*) PersistentSVals);
Mike Stump1eb44332009-09-09 15:08:12 +0000247
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000248 typedef llvm::FoldingSetNodeWrapper<SValData> FoldNodeTy;
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000249 FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
Mike Stump1eb44332009-09-09 15:08:12 +0000250
251 if (!P) {
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000252 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
Ted Kremenek718c4f72008-04-29 22:17:41 +0000253 new (P) FoldNodeTy(std::make_pair(V, Data));
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000254 Map.InsertNode(P, InsertPos);
255 }
256
Ted Kremenek718c4f72008-04-29 22:17:41 +0000257 return P->getValue();
Ted Kremenek0fe33bc2008-04-22 21:10:18 +0000258}
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000259
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000260const std::pair<SVal, SVal>&
261BasicValueFactory::getPersistentSValPair(const SVal& V1, const SVal& V2) {
Mike Stump1eb44332009-09-09 15:08:12 +0000262
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000263 // Lazily create the folding set.
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000264 if (!PersistentSValPairs) PersistentSValPairs = new PersistentSValPairsTy();
Mike Stump1eb44332009-09-09 15:08:12 +0000265
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000266 llvm::FoldingSetNodeID ID;
267 void* InsertPos;
268 V1.Profile(ID);
269 V2.Profile(ID);
Mike Stump1eb44332009-09-09 15:08:12 +0000270
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000271 PersistentSValPairsTy& Map = *((PersistentSValPairsTy*) PersistentSValPairs);
Mike Stump1eb44332009-09-09 15:08:12 +0000272
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000273 typedef llvm::FoldingSetNodeWrapper<SValPair> FoldNodeTy;
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000274 FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
Mike Stump1eb44332009-09-09 15:08:12 +0000275
276 if (!P) {
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000277 P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
278 new (P) FoldNodeTy(std::make_pair(V1, V2));
279 Map.InsertNode(P, InsertPos);
280 }
Mike Stump1eb44332009-09-09 15:08:12 +0000281
Ted Kremenek4d0348b2008-04-29 23:24:44 +0000282 return P->getValue();
283}
284
Zhongxing Xu1c96b242008-10-17 05:57:07 +0000285const SVal* BasicValueFactory::getPersistentSVal(SVal X) {
286 return &getPersistentSValWithData(X, 0).first;
Mike Stump1eb44332009-09-09 15:08:12 +0000287}
Ted Kremenek7360fda2008-09-18 23:09:54 +0000288
289