Newer
Older
//=== BasicValueFactory.cpp - Basic values for Path Sens analysis --*- C++ -*-//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines BasicValueFactory, a class that manages the lifetime
// of APSInt objects and symbolic constraints used by GRExprEngine
// and related classes.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/BasicValueFactory.h"
using namespace clang;
Zhongxing Xu
committed
void CompoundValData::Profile(llvm::FoldingSetNodeID& ID, QualType T,
Ted Kremenek
committed
llvm::ImmutableList<SVal> L) {
Zhongxing Xu
committed
T.Profile(ID);
Ted Kremenek
committed
ID.AddPointer(L.getInternalPointer());
Zhongxing Xu
committed
}
Zhongxing Xu
committed
typedef std::pair<SVal, uintptr_t> SValData;
typedef std::pair<SVal, SVal> SValPair;
Ted Kremenek
committed
namespace llvm {
Zhongxing Xu
committed
template<> struct FoldingSetTrait<SValData> {
static inline void Profile(const SValData& X, llvm::FoldingSetNodeID& ID) {
Ted Kremenek
committed
X.first.Profile(ID);
Ted Kremenek
committed
ID.AddPointer( (void*) X.second);
Ted Kremenek
committed
}
};
Zhongxing Xu
committed
template<> struct FoldingSetTrait<SValPair> {
static inline void Profile(const SValPair& X, llvm::FoldingSetNodeID& ID) {
X.first.Profile(ID);
X.second.Profile(ID);
}
};
Ted Kremenek
committed
}
Zhongxing Xu
committed
typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValData> >
PersistentSValsTy;
Ted Kremenek
committed
Zhongxing Xu
committed
typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SValPair> >
PersistentSValPairsTy;
BasicValueFactory::~BasicValueFactory() {
// Note that the dstor for the contents of APSIntSet will never be called,
// so we iterate over the set and invoke the dstor for each APSInt. This
// frees an aux. memory allocated to represent very large constants.
for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I)
I->getValue().~APSInt();
Ted Kremenek
committed
Zhongxing Xu
committed
delete (PersistentSValsTy*) PersistentSVals;
delete (PersistentSValPairsTy*) PersistentSValPairs;
}
const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
llvm::FoldingSetNodeID ID;
void* InsertPos;
typedef llvm::FoldingSetNodeWrapper<llvm::APSInt> FoldNodeTy;
X.Profile(ID);
FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
if (!P) {
P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
new (P) FoldNodeTy(X);
APSIntSet.InsertNode(P, InsertPos);
}
return *P;
}
const llvm::APSInt& BasicValueFactory::getValue(const llvm::APInt& X,
bool isUnsigned) {
llvm::APSInt V(X, isUnsigned);
return getValue(V);
}
const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, unsigned BitWidth,
bool isUnsigned) {
llvm::APSInt V(BitWidth, isUnsigned);
V = X;
return getValue(V);
}
const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) {
unsigned bits = Ctx.getTypeSize(T);
llvm::APSInt V(bits, T->isUnsignedIntegerType());
V = X;
return getValue(V);
}
const SymIntConstraint&
Ted Kremenek
committed
BasicValueFactory::getConstraint(SymbolRef sym, BinaryOperator::Opcode Op,
const llvm::APSInt& V) {
llvm::FoldingSetNodeID ID;
SymIntConstraint::Profile(ID, sym, Op, V);
void* InsertPos;
SymIntConstraint* C = SymIntCSet.FindNodeOrInsertPos(ID, InsertPos);
if (!C) {
C = (SymIntConstraint*) BPAlloc.Allocate<SymIntConstraint>();
new (C) SymIntConstraint(sym, Op, V);
SymIntCSet.InsertNode(C, InsertPos);
}
return *C;
}
Zhongxing Xu
committed
const CompoundValData*
Ted Kremenek
committed
BasicValueFactory::getCompoundValData(QualType T,
llvm::ImmutableList<SVal> Vals) {
Zhongxing Xu
committed
llvm::FoldingSetNodeID ID;
Ted Kremenek
committed
CompoundValData::Profile(ID, T, Vals);
Zhongxing Xu
committed
void* InsertPos;
CompoundValData* D = CompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
if (!D) {
D = (CompoundValData*) BPAlloc.Allocate<CompoundValData>();
Ted Kremenek
committed
new (D) CompoundValData(T, Vals);
Zhongxing Xu
committed
CompoundValDataSet.InsertNode(D, InsertPos);
}
return D;
}
Ted Kremenek
committed
const llvm::APSInt*
BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
const llvm::APSInt& V1, const llvm::APSInt& V2) {
switch (Op) {
default:
assert (false && "Invalid Opcode.");
case BinaryOperator::Mul:
Ted Kremenek
committed
return &getValue( V1 * V2 );
case BinaryOperator::Div:
Ted Kremenek
committed
return &getValue( V1 / V2 );
case BinaryOperator::Rem:
Ted Kremenek
committed
return &getValue( V1 % V2 );
case BinaryOperator::Add:
Ted Kremenek
committed
return &getValue( V1 + V2 );
case BinaryOperator::Sub:
Ted Kremenek
committed
return &getValue( V1 - V2 );
Ted Kremenek
committed
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
case BinaryOperator::Shl: {
// FIXME: This logic should probably go higher up, where we can
// test these conditions symbolically.
// FIXME: Expand these checks to include all undefined behavior.
if (V2.isSigned() && V2.isNegative())
return NULL;
uint64_t Amt = V2.getZExtValue();
if (Amt > V1.getBitWidth())
return NULL;
return &getValue( V1.operator<<( (unsigned) Amt ));
}
case BinaryOperator::Shr: {
// FIXME: This logic should probably go higher up, where we can
// test these conditions symbolically.
// FIXME: Expand these checks to include all undefined behavior.
if (V2.isSigned() && V2.isNegative())
return NULL;
uint64_t Amt = V2.getZExtValue();
if (Amt > V1.getBitWidth())
return NULL;
Ted Kremenek
committed
return &getValue( V1.operator>>( (unsigned) Amt ));
}
case BinaryOperator::LT:
Ted Kremenek
committed
return &getTruthValue( V1 < V2 );
case BinaryOperator::GT:
Ted Kremenek
committed
return &getTruthValue( V1 > V2 );
case BinaryOperator::LE:
Ted Kremenek
committed
return &getTruthValue( V1 <= V2 );
case BinaryOperator::GE:
Ted Kremenek
committed
return &getTruthValue( V1 >= V2 );
case BinaryOperator::EQ:
Ted Kremenek
committed
return &getTruthValue( V1 == V2 );
case BinaryOperator::NE:
Ted Kremenek
committed
return &getTruthValue( V1 != V2 );
// Note: LAnd, LOr, Comma are handled specially by higher-level logic.
case BinaryOperator::And:
Ted Kremenek
committed
return &getValue( V1 & V2 );
case BinaryOperator::Or:
Ted Kremenek
committed
return &getValue( V1 | V2 );
case BinaryOperator::Xor:
Ted Kremenek
committed
return &getValue( V1 ^ V2 );
}
}
Ted Kremenek
committed
Zhongxing Xu
committed
const std::pair<SVal, uintptr_t>&
BasicValueFactory::getPersistentSValWithData(const SVal& V, uintptr_t Data) {
Ted Kremenek
committed
// Lazily create the folding set.
Zhongxing Xu
committed
if (!PersistentSVals) PersistentSVals = new PersistentSValsTy();
Ted Kremenek
committed
llvm::FoldingSetNodeID ID;
void* InsertPos;
V.Profile(ID);
Ted Kremenek
committed
ID.AddPointer((void*) Data);
Ted Kremenek
committed
Zhongxing Xu
committed
PersistentSValsTy& Map = *((PersistentSValsTy*) PersistentSVals);
Ted Kremenek
committed
Zhongxing Xu
committed
typedef llvm::FoldingSetNodeWrapper<SValData> FoldNodeTy;
Ted Kremenek
committed
FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
if (!P) {
P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
Ted Kremenek
committed
new (P) FoldNodeTy(std::make_pair(V, Data));
Ted Kremenek
committed
Map.InsertNode(P, InsertPos);
}
Ted Kremenek
committed
return P->getValue();
Ted Kremenek
committed
}
Zhongxing Xu
committed
const std::pair<SVal, SVal>&
BasicValueFactory::getPersistentSValPair(const SVal& V1, const SVal& V2) {
// Lazily create the folding set.
Zhongxing Xu
committed
if (!PersistentSValPairs) PersistentSValPairs = new PersistentSValPairsTy();
llvm::FoldingSetNodeID ID;
void* InsertPos;
V1.Profile(ID);
V2.Profile(ID);
Zhongxing Xu
committed
PersistentSValPairsTy& Map = *((PersistentSValPairsTy*) PersistentSValPairs);
Zhongxing Xu
committed
typedef llvm::FoldingSetNodeWrapper<SValPair> FoldNodeTy;
FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
if (!P) {
P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
new (P) FoldNodeTy(std::make_pair(V1, V2));
Map.InsertNode(P, InsertPos);
}
return P->getValue();
}
Zhongxing Xu
committed
const SVal* BasicValueFactory::getPersistentSVal(SVal X) {
return &getPersistentSValWithData(X, 0).first;