"llvm/lib/git@repo.hca.bsc.es:rferrer/llvm-epi-0.8.git" did not exist on "459e079912614f47904e14c76dd879e61beeeec1"
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
//===----------------------------------------------------------------------===//
// Symbol Iteration.
//===----------------------------------------------------------------------===//
Zhongxing Xu
committed
SVal::symbol_iterator SVal::symbol_begin() const {
Ted Kremenek
committed
// FIXME: This is a rat's nest. Cleanup.
Zhongxing Xu
committed
if (isa<loc::SymbolVal>(this))
Ted Kremenek
committed
return symbol_iterator(SymbolRef((uintptr_t)Data));
Zhongxing Xu
committed
else if (isa<nonloc::SymbolVal>(this))
Ted Kremenek
committed
return symbol_iterator(SymbolRef((uintptr_t)Data));
Zhongxing Xu
committed
else if (isa<nonloc::SymIntConstraintVal>(this)) {
const SymIntConstraint& C =
Ted Kremenek
committed
cast<nonloc::SymIntConstraintVal>(this)->getConstraint();
return symbol_iterator(C.getSymbol());
Ted Kremenek
committed
}
Zhongxing Xu
committed
else if (isa<nonloc::LocAsInteger>(this)) {
const nonloc::LocAsInteger& V = cast<nonloc::LocAsInteger>(*this);
return V.getPersistentLoc().symbol_begin();
Ted Kremenek
committed
}
Ted Kremenek
committed
else if (isa<loc::MemRegionVal>(this)) {
const MemRegion* R = cast<loc::MemRegionVal>(this)->getRegion();
if (const SymbolicRegion* S = dyn_cast<SymbolicRegion>(R))
return symbol_iterator(S->getSymbol());
}
Ted Kremenek
committed
Ted Kremenek
committed
return symbol_iterator();
Ted Kremenek
committed
}
Zhongxing Xu
committed
SVal::symbol_iterator SVal::symbol_end() const {
Ted Kremenek
committed
return symbol_iterator();
Ted Kremenek
committed
}
//===----------------------------------------------------------------------===//
// 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();
Zhongxing Xu
committed
NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const {
switch (getSubKind()) {
default:
Zhongxing Xu
committed
assert(false && "EQ not implemented for this Loc.");
break;
Zhongxing Xu
committed
case loc::ConcreteIntKind:
if (isa<loc::ConcreteInt>(R)) {
bool b = cast<loc::ConcreteInt>(this)->getValue() ==
cast<loc::ConcreteInt>(R).getValue();
Zhongxing Xu
committed
return NonLoc::MakeIntTruthVal(BasicVals, b);
Zhongxing Xu
committed
else if (isa<loc::SymbolVal>(R)) {
const SymIntConstraint& C =
Zhongxing Xu
committed
BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
BinaryOperator::EQ,
Zhongxing Xu
committed
cast<loc::ConcreteInt>(this)->getValue());
Zhongxing Xu
committed
return nonloc::SymIntConstraintVal(C);
}
break;
Zhongxing Xu
committed
case loc::SymbolValKind: {
if (isa<loc::ConcreteInt>(R)) {
const SymIntConstraint& C =
Zhongxing Xu
committed
BasicVals.getConstraint(cast<loc::SymbolVal>(this)->getSymbol(),
BinaryOperator::EQ,
Zhongxing Xu
committed
cast<loc::ConcreteInt>(R).getValue());
Zhongxing Xu
committed
return nonloc::SymIntConstraintVal(C);
}
Zhongxing Xu
committed
assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement unification.");
break;
Zhongxing Xu
committed
case loc::MemRegionKind:
if (isa<loc::MemRegionVal>(R)) {
bool b = cast<loc::MemRegionVal>(*this) == cast<loc::MemRegionVal>(R);
return NonLoc::MakeIntTruthVal(BasicVals, b);
}
break;
Zhongxing Xu
committed
return NonLoc::MakeIntTruthVal(BasicVals, false);
Zhongxing Xu
committed
NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const {
switch (getSubKind()) {
default:
Zhongxing Xu
committed
assert(false && "NE not implemented for this Loc.");
break;
Zhongxing Xu
committed
case loc::ConcreteIntKind:
if (isa<loc::ConcreteInt>(R)) {
bool b = cast<loc::ConcreteInt>(this)->getValue() !=
cast<loc::ConcreteInt>(R).getValue();
Zhongxing Xu
committed
return NonLoc::MakeIntTruthVal(BasicVals, b);
Zhongxing Xu
committed
else if (isa<loc::SymbolVal>(R)) {
const SymIntConstraint& C =
Zhongxing Xu
committed
BasicVals.getConstraint(cast<loc::SymbolVal>(R).getSymbol(),
BinaryOperator::NE,
Zhongxing Xu
committed
cast<loc::ConcreteInt>(this)->getValue());
Zhongxing Xu
committed
return nonloc::SymIntConstraintVal(C);
Zhongxing Xu
committed
case loc::SymbolValKind: {
if (isa<loc::ConcreteInt>(R)) {
const SymIntConstraint& C =
Zhongxing Xu
committed
BasicVals.getConstraint(cast<loc::SymbolVal>(this)->getSymbol(),
BinaryOperator::NE,
Zhongxing Xu
committed
cast<loc::ConcreteInt>(R).getValue());
Zhongxing Xu
committed
return nonloc::SymIntConstraintVal(C);
Zhongxing Xu
committed
assert (!isa<loc::SymbolVal>(R) && "FIXME: Implement sym !=.");
break;
}
Zhongxing Xu
committed
case loc::MemRegionKind:
if (isa<loc::MemRegionVal>(R)) {
bool b = cast<loc::MemRegionVal>(*this)==cast<loc::MemRegionVal>(R);
return NonLoc::MakeIntTruthVal(BasicVals, b);
}
break;
Zhongxing Xu
committed
return NonLoc::MakeIntTruthVal(BasicVals, true);
}
//===----------------------------------------------------------------------===//
Zhongxing Xu
committed
// Utility methods for constructing Non-Locs.
//===----------------------------------------------------------------------===//
NonLoc NonLoc::MakeVal(SymbolRef sym) {
return nonloc::SymbolVal(sym);
}
NonLoc NonLoc::MakeVal(BasicValueFactory& BasicVals, unsigned X,
bool isUnsigned) {
return nonloc::ConcreteInt(BasicVals.getValue(X, sizeof(unsigned)*8,
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 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 SVal::GetRValueSymbolVal(SymbolManager& SymMgr, const MemRegion* R) {
SymbolRef sym = SymMgr.getRegionRValueSymbol(R);
if (const TypedRegion* TR = cast<TypedRegion>(R))
if (Loc::IsLocType(TR->getRValueType(SymMgr.getContext())))
return Loc::MakeVal(sym);
return NonLoc::MakeVal(sym);
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::MakeVal(SymbolRef sym) { return loc::SymbolVal(sym); }
//===----------------------------------------------------------------------===//
// Pretty-Printing.
//===----------------------------------------------------------------------===//
void SVal::printStdErr() const { print(llvm::errs()); llvm::errs().flush(); }
Zhongxing Xu
committed
void SVal::print(std::ostream& Out) const {
llvm::raw_os_ostream out(Out);
print(out);
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
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
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.");
}
}
static void printOpcode(llvm::raw_ostream& Out, BinaryOperator::Opcode Op) {
switch (Op) {
case BinaryOperator::Mul: Out << '*' ; break;
case BinaryOperator::Div: Out << '/' ; break;
case BinaryOperator::Rem: Out << '%' ; break;
case BinaryOperator::Add: Out << '+' ; break;
case BinaryOperator::Sub: Out << '-' ; break;
case BinaryOperator::Shl: Out << "<<" ; break;
case BinaryOperator::Shr: Out << ">>" ; break;
case BinaryOperator::LT: Out << "<" ; break;
case BinaryOperator::GT: Out << '>' ; break;
case BinaryOperator::LE: Out << "<=" ; break;
case BinaryOperator::GE: Out << ">=" ; break;
case BinaryOperator::EQ: Out << "==" ; break;
case BinaryOperator::NE: Out << "!=" ; break;
case BinaryOperator::And: Out << '&' ; break;
case BinaryOperator::Xor: Out << '^' ; break;
case BinaryOperator::Or: Out << '|' ; break;
default: assert(false && "Not yet implemented.");
}
}
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;
case nonloc::SymIntConstraintValKind: {
const nonloc::SymIntConstraintVal& C =
*cast<nonloc::SymIntConstraintVal>(this);
Out << '$' << C.getConstraint().getSymbol() << ' ';
printOpcode(Out, C.getConstraint().getOpcode());
Out << ' ' << C.getConstraint().getInt().getZExtValue();
if (C.getConstraint().getInt().isUnsigned())
Out << 'U';
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;
}
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
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::SymbolValKind:
Out << '$' << cast<loc::SymbolVal>(this)->getSymbol();
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;
}
}