"git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "111caaac58e21550c71c96f68394ad4d5f4f0198"
Newer
Older
//= RValues.cpp - Abstract RValues for Path-Sens. Value Tracking -*- C++ -*-==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
Zhongxing Xu
committed
// This file defines SVal, Loc, and NonLoc, classes that represent
// abstract r-values for use with path-sensitive value tracking.
//
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
#include "clang/Analysis/PathSensitive/GRState.h"
#include "llvm/Support/Streams.h"
using namespace clang;
using llvm::dyn_cast;
using llvm::cast;
using llvm::APSInt;
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
// Symbol iteration within an SVal.
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Utility methods.
//===----------------------------------------------------------------------===//
Ted Kremenek
committed
/// getAsLocSymbol - If this SVal is a location (subclasses Loc) and
/// wraps a symbol, return that SymbolRef. Otherwise return a SymbolRef
/// where 'isValid()' returns false.
SymbolRef SVal::getAsLocSymbol() const {
if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(this)) {
const MemRegion *R = X->getRegion();
while (R) {
// Blast through region views.
if (const TypedViewRegion *View = dyn_cast<TypedViewRegion>(R)) {
R = View->getSuperRegion();
continue;
}
if (const SymbolicRegion *SymR = dyn_cast<SymbolicRegion>(R))
return SymR->getSymbol();
break;
}
}
Ted Kremenek
committed
return 0;
Ted Kremenek
committed
}
/// getAsSymbol - If this Sval wraps a symbol return that SymbolRef.
/// Otherwise return a SymbolRef where 'isValid()' returns false.
SymbolRef SVal::getAsSymbol() const {
if (const nonloc::SymbolVal *X = dyn_cast<nonloc::SymbolVal>(this))
return X->getSymbol();
Ted Kremenek
committed
if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
if (SymbolRef Y = dyn_cast<SymbolData>(X->getSymbolicExpression()))
return Y;
Ted Kremenek
committed
return getAsLocSymbol();
}
Ted Kremenek
committed
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then
/// return that expression. Otherwise return NULL.
const SymExpr *SVal::getAsSymbolicExpression() const {
if (const nonloc::SymExprVal *X = dyn_cast<nonloc::SymExprVal>(this))
return X->getSymbolicExpression();
return getAsSymbol();
}
bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const {
return itr == X.itr;
}
bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const {
return itr != X.itr;
}
SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) {
itr.push_back(SE);
while (!isa<SymbolData>(itr.back())) expand();
}
SVal::symbol_iterator& SVal::symbol_iterator::operator++() {
assert(!itr.empty() && "attempting to iterate on an 'end' iterator");
assert(isa<SymbolData>(itr.back()));
itr.pop_back();
if (!itr.empty())
while (!isa<SymbolData>(itr.back())) expand();
return *this;
}
SymbolRef SVal::symbol_iterator::operator*() {
assert(!itr.empty() && "attempting to dereference an 'end' iterator");
return cast<SymbolData>(itr.back());
}
void SVal::symbol_iterator::expand() {
const SymExpr *SE = itr.back();
itr.pop_back();
if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
itr.push_back(SIE->getLHS());
return;
}
else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
itr.push_back(SSE->getLHS());
itr.push_back(SSE->getRHS());
return;
}
assert(false && "unhandled expansion case");
}
//===----------------------------------------------------------------------===//
// Other Iterators.
//===----------------------------------------------------------------------===//
nonloc::CompoundVal::iterator nonloc::CompoundVal::begin() const {
return getValue()->begin();
}
nonloc::CompoundVal::iterator nonloc::CompoundVal::end() const {
return getValue()->end();
}
Ted Kremenek
committed
//===----------------------------------------------------------------------===//
// Useful predicates.
//===----------------------------------------------------------------------===//
Zhongxing Xu
committed
bool SVal::isZeroConstant() const {
if (isa<loc::ConcreteInt>(*this))
return cast<loc::ConcreteInt>(*this).getValue() == 0;
else if (isa<nonloc::ConcreteInt>(*this))
return cast<nonloc::ConcreteInt>(*this).getValue() == 0;
Ted Kremenek
committed
else
return false;
}
//===----------------------------------------------------------------------===//
Zhongxing Xu
committed
// Transfer function dispatch for Non-Locs.
//===----------------------------------------------------------------------===//
Zhongxing Xu
committed
SVal nonloc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
Zhongxing Xu
committed
const nonloc::ConcreteInt& R) const {
const llvm::APSInt* X =
BasicVals.EvaluateAPSInt(Op, getValue(), R.getValue());
Ted Kremenek
committed
if (X)
Zhongxing Xu
committed
return nonloc::ConcreteInt(*X);
Ted Kremenek
committed
else
return UndefinedVal();
}
// Bitwise-Complement.
Zhongxing Xu
committed
nonloc::ConcreteInt
nonloc::ConcreteInt::EvalComplement(BasicValueFactory& BasicVals) const {
return BasicVals.getValue(~getValue());
}
// Unary Minus.
Zhongxing Xu
committed
nonloc::ConcreteInt
nonloc::ConcreteInt::EvalMinus(BasicValueFactory& BasicVals, UnaryOperator* U) const {
assert (U->getType() == U->getSubExpr()->getType());
assert (U->getType()->isIntegerType());
return BasicVals.getValue(-getValue());
//===----------------------------------------------------------------------===//
Zhongxing Xu
committed
// Transfer function dispatch for Locs.
//===----------------------------------------------------------------------===//
SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals,
BinaryOperator::Opcode Op,
const loc::ConcreteInt& R) const {
assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub ||
(Op >= BinaryOperator::LT && Op <= BinaryOperator::NE));
const llvm::APSInt* X = BasicVals.EvaluateAPSInt(Op, getValue(), R.getValue());
Ted Kremenek
committed
if (X)
Zhongxing Xu
committed
return loc::ConcreteInt(*X);
Ted Kremenek
committed
else
return UndefinedVal();
//===----------------------------------------------------------------------===//
// Utility methods for constructing SVals.
//===----------------------------------------------------------------------===//
SVal ValueManager::makeZeroVal(QualType T) {
if (Loc::IsLocType(T))
return Loc::MakeNull(BasicVals);
if (T->isIntegerType())
return NonLoc::MakeVal(BasicVals, 0, T);
// FIXME: Handle floats.
// FIXME: Handle structs.
return UnknownVal();
}
//===----------------------------------------------------------------------===//
Zhongxing Xu
committed
// Utility methods for constructing Non-Locs.
//===----------------------------------------------------------------------===//
NonLoc ValueManager::makeNonLoc(SymbolRef sym) {
Zhongxing Xu
committed
}
NonLoc ValueManager::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const APSInt& v, QualType T) {
Zhongxing Xu
committed
// The Environment ensures we always get a persistent APSInt in
// BasicValueFactory, so we don't need to get the APSInt from
// BasicValueFactory again.
Ted Kremenek
committed
assert(!Loc::IsLocType(T));
return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T));
Zhongxing Xu
committed
}
NonLoc ValueManager::makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op,
const SymExpr *rhs, QualType T) {
Zhongxing Xu
committed
assert(SymMgr.getType(lhs) == SymMgr.getType(rhs));
Ted Kremenek
committed
assert(!Loc::IsLocType(T));
return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T));
NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X,
bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getIntValue(X, isUnsigned));
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, uint64_t X,
unsigned BitWidth, bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getValue(X, BitWidth, isUnsigned));
}
Zhongxing Xu
committed
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, uint64_t X, QualType T) {
return nonloc::ConcreteInt(BasicVals.getValue(X, T));
Zhongxing Xu
committed
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, IntegerLiteral* I) {
Zhongxing Xu
committed
return nonloc::ConcreteInt(BasicVals.getValue(APSInt(I->getValue(),
I->getType()->isUnsignedIntegerType())));
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const llvm::APInt& I,
bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getValue(I, isUnsigned));
}
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, const llvm::APSInt& I) {
return nonloc::ConcreteInt(BasicVals.getValue(I));
}
Zhongxing Xu
committed
NonLoc NonLoc::MakeIntTruthVal(BasicValueFactory& BasicVals, bool b) {
return nonloc::ConcreteInt(BasicVals.getTruthValue(b));
}
Ted Kremenek
committed
NonLoc ValueManager::makeTruthVal(bool b, QualType T) {
return nonloc::ConcreteInt(BasicVals.getTruthValue(b, T));
}
Ted Kremenek
committed
NonLoc NonLoc::MakeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals,
Zhongxing Xu
committed
BasicValueFactory& BasicVals) {
Ted Kremenek
committed
return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
Zhongxing Xu
committed
}
SVal ValueManager::getRValueSymbolVal(const MemRegion* R) {
SymbolRef sym = SymMgr.getRegionRValueSymbol(R);
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
QualType T = TR->getRValueType(SymMgr.getContext());
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
}
if (Loc::IsLocType(T))
return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
// Only handle integers for now.
Zhongxing Xu
committed
if (T->isIntegerType() && T->isScalarType())
return makeNonLoc(sym);
}
return UnknownVal();
SVal ValueManager::getConjuredSymbolVal(const Expr* E, unsigned Count) {
Zhongxing Xu
committed
SymbolRef sym = SymMgr.getConjuredSymbol(E, Count);
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
}
Zhongxing Xu
committed
if (Loc::IsLocType(T))
return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
Zhongxing Xu
committed
if (T->isIntegerType() && T->isScalarType())
return makeNonLoc(sym);
SVal ValueManager::getConjuredSymbolVal(const Expr* E, QualType T,
unsigned Count) {
Zhongxing Xu
committed
SymbolRef sym = SymMgr.getConjuredSymbol(E, T, Count);
// If T is of function pointer type, create a CodeTextRegion wrapping a
// symbol.
if (T->isFunctionPointerType()) {
return Loc::MakeVal(MemMgr.getCodeTextRegion(sym, T));
}
Zhongxing Xu
committed
if (Loc::IsLocType(T))
return Loc::MakeVal(MemMgr.getSymbolicRegion(sym));
Zhongxing Xu
committed
if (T->isIntegerType() && T->isScalarType())
return makeNonLoc(sym);
Zhongxing Xu
committed
return UnknownVal();
}
SVal ValueManager::getFunctionPointer(const FunctionDecl* FD) {
CodeTextRegion* R
= MemMgr.getCodeTextRegion(FD, Context.getPointerType(FD->getType()));
return loc::MemRegionVal(R);
Ted Kremenek
committed
nonloc::LocAsInteger nonloc::LocAsInteger::Make(BasicValueFactory& Vals, Loc V,
unsigned Bits) {
return LocAsInteger(Vals.getPersistentSValWithData(V, Bits));
}
//===----------------------------------------------------------------------===//
Zhongxing Xu
committed
// Utility methods for constructing Locs.
//===----------------------------------------------------------------------===//
Loc Loc::MakeVal(const MemRegion* R) { return loc::MemRegionVal(R); }
Zhongxing Xu
committed
Loc Loc::MakeVal(AddrLabelExpr* E) { return loc::GotoLabel(E->getLabel()); }
Loc Loc::MakeNull(BasicValueFactory &BasicVals) {
return loc::ConcreteInt(BasicVals.getZeroWithPtrWidth());
}
//===----------------------------------------------------------------------===//
// Pretty-Printing.
//===----------------------------------------------------------------------===//
void SVal::printStdErr() const { print(llvm::errs()); }
Zhongxing Xu
committed
void SVal::print(std::ostream& Out) const {
llvm::raw_os_ostream out(Out);
print(out);
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
void SVal::print(llvm::raw_ostream& Out) const {
switch (getBaseKind()) {
case UnknownKind:
Out << "Invalid"; break;
case NonLocKind:
cast<NonLoc>(this)->print(Out); break;
case LocKind:
cast<Loc>(this)->print(Out); break;
case UndefinedKind:
Out << "Undefined"; break;
default:
assert (false && "Invalid SVal.");
}
}
void NonLoc::print(llvm::raw_ostream& Out) const {
switch (getSubKind()) {
case nonloc::ConcreteIntKind:
Out << cast<nonloc::ConcreteInt>(this)->getValue().getZExtValue();
if (cast<nonloc::ConcreteInt>(this)->getValue().isUnsigned())
Out << 'U';
break;
case nonloc::SymbolValKind:
Out << '$' << cast<nonloc::SymbolVal>(this)->getSymbol();
break;
Ted Kremenek
committed
case nonloc::SymExprValKind: {
const nonloc::SymExprVal& C = *cast<nonloc::SymExprVal>(this);
const SymExpr *SE = C.getSymbolicExpression();
Out << SE;
break;
}
case nonloc::LocAsIntegerKind: {
const nonloc::LocAsInteger& C = *cast<nonloc::LocAsInteger>(this);
C.getLoc().print(Out);
Out << " [as " << C.getNumBits() << " bit integer]";
break;
}
case nonloc::CompoundValKind: {
const nonloc::CompoundVal& C = *cast<nonloc::CompoundVal>(this);
Out << " {";
bool first = true;
for (nonloc::CompoundVal::iterator I=C.begin(), E=C.end(); I!=E; ++I) {
if (first) { Out << ' '; first = false; }
else Out << ", ";
}
Out << " }";
break;
}
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
default:
assert (false && "Pretty-printed not implemented for this NonLoc.");
break;
}
}
void Loc::print(llvm::raw_ostream& Out) const {
switch (getSubKind()) {
case loc::ConcreteIntKind:
Out << cast<loc::ConcreteInt>(this)->getValue().getZExtValue()
<< " (Loc)";
break;
case loc::GotoLabelKind:
Out << "&&"
<< cast<loc::GotoLabel>(this)->getLabel()->getID()->getName();
break;
case loc::MemRegionKind:
Out << '&' << cast<loc::MemRegionVal>(this)->getRegion()->getString();
break;
case loc::FuncValKind:
Out << "function "
<< cast<loc::FuncVal>(this)->getDecl()->getIdentifier()->getName();
break;
default:
assert (false && "Pretty-printing not implemented for this Loc.");
break;
}
}