forked from OSchip/llvm-project
Further cleanup. Moved definitions for SymbolManager and ValueManager into
their own [.cpp;.h] files. llvm-svn: 47201
This commit is contained in:
parent
f861fbaae8
commit
074965c5cb
|
@ -13,116 +13,13 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/RValues.h"
|
||||
#include "llvm/Support/Streams.h"
|
||||
|
||||
using namespace clang;
|
||||
using llvm::dyn_cast;
|
||||
using llvm::cast;
|
||||
using llvm::APSInt;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SymbolManager.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
SymbolID SymbolManager::getSymbol(ParmVarDecl* D) {
|
||||
SymbolID& X = DataToSymbol[getKey(D)];
|
||||
|
||||
if (!X.isInitialized()) {
|
||||
X = SymbolToData.size();
|
||||
SymbolToData.push_back(SymbolDataParmVar(D));
|
||||
}
|
||||
|
||||
return X;
|
||||
}
|
||||
|
||||
SymbolID SymbolManager::getContentsOfSymbol(SymbolID sym) {
|
||||
SymbolID& X = DataToSymbol[getKey(sym)];
|
||||
|
||||
if (!X.isInitialized()) {
|
||||
X = SymbolToData.size();
|
||||
SymbolToData.push_back(SymbolDataContentsOf(sym));
|
||||
}
|
||||
|
||||
return X;
|
||||
}
|
||||
|
||||
QualType SymbolData::getType() const {
|
||||
switch (getKind()) {
|
||||
default:
|
||||
assert (false && "getType() not implemented for this symbol.");
|
||||
|
||||
case ParmKind:
|
||||
return cast<SymbolDataParmVar>(this)->getDecl()->getType();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
SymbolManager::SymbolManager() {}
|
||||
SymbolManager::~SymbolManager() {}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Values and ValueManager.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
ValueManager::~ValueManager() {
|
||||
// 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();
|
||||
}
|
||||
|
||||
const APSInt& ValueManager::getValue(const APSInt& X) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
void* InsertPos;
|
||||
typedef llvm::FoldingSetNodeWrapper<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 APSInt& ValueManager::getValue(uint64_t X, unsigned BitWidth,
|
||||
bool isUnsigned) {
|
||||
APSInt V(BitWidth, isUnsigned);
|
||||
V = X;
|
||||
return getValue(V);
|
||||
}
|
||||
|
||||
const APSInt& ValueManager::getValue(uint64_t X, QualType T,
|
||||
SourceLocation Loc) {
|
||||
|
||||
unsigned bits = Ctx.getTypeSize(T, Loc);
|
||||
APSInt V(bits, T->isUnsignedIntegerType());
|
||||
V = X;
|
||||
return getValue(V);
|
||||
}
|
||||
|
||||
const SymIntConstraint&
|
||||
ValueManager::getConstraint(SymbolID 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;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Symbol Iteration.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -154,69 +51,12 @@ RValue::symbol_iterator RValue::symbol_end() const {
|
|||
// Transfer function dispatch for Non-LValues.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
static const
|
||||
llvm::APSInt& EvaluateAPSInt(ValueManager& ValMgr, BinaryOperator::Opcode Op,
|
||||
const llvm::APSInt& V1, const llvm::APSInt& V2) {
|
||||
|
||||
switch (Op) {
|
||||
default:
|
||||
assert (false && "Invalid Opcode.");
|
||||
|
||||
case BinaryOperator::Mul:
|
||||
return ValMgr.getValue( V1 * V2 );
|
||||
|
||||
case BinaryOperator::Div:
|
||||
return ValMgr.getValue( V1 / V2 );
|
||||
|
||||
case BinaryOperator::Rem:
|
||||
return ValMgr.getValue( V1 % V2 );
|
||||
|
||||
case BinaryOperator::Add:
|
||||
return ValMgr.getValue( V1 + V2 );
|
||||
|
||||
case BinaryOperator::Sub:
|
||||
return ValMgr.getValue( V1 - V2 );
|
||||
|
||||
case BinaryOperator::Shl:
|
||||
return ValMgr.getValue( V1.operator<<( (unsigned) V2.getZExtValue() ));
|
||||
|
||||
case BinaryOperator::Shr:
|
||||
return ValMgr.getValue( V1.operator>>( (unsigned) V2.getZExtValue() ));
|
||||
|
||||
case BinaryOperator::LT:
|
||||
return ValMgr.getTruthValue( V1 < V2 );
|
||||
|
||||
case BinaryOperator::GT:
|
||||
return ValMgr.getTruthValue( V1 > V2 );
|
||||
|
||||
case BinaryOperator::LE:
|
||||
return ValMgr.getTruthValue( V1 <= V2 );
|
||||
|
||||
case BinaryOperator::GE:
|
||||
return ValMgr.getTruthValue( V1 >= V2 );
|
||||
|
||||
case BinaryOperator::EQ:
|
||||
return ValMgr.getTruthValue( V1 == V2 );
|
||||
|
||||
case BinaryOperator::NE:
|
||||
return ValMgr.getTruthValue( V1 != V2 );
|
||||
|
||||
// Note: LAnd, LOr, Comma are handled specially by higher-level logic.
|
||||
|
||||
case BinaryOperator::And:
|
||||
return ValMgr.getValue( V1 & V2 );
|
||||
|
||||
case BinaryOperator::Or:
|
||||
return ValMgr.getValue( V1 | V2 );
|
||||
}
|
||||
}
|
||||
|
||||
nonlval::ConcreteInt
|
||||
nonlval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr,
|
||||
BinaryOperator::Opcode Op,
|
||||
const nonlval::ConcreteInt& RHS) const {
|
||||
|
||||
return EvaluateAPSInt(ValMgr, Op, getValue(), RHS.getValue());
|
||||
return ValMgr.EvaluateAPSInt(Op, getValue(), RHS.getValue());
|
||||
}
|
||||
|
||||
|
||||
|
@ -249,7 +89,7 @@ lval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr,
|
|||
assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub ||
|
||||
(Op >= BinaryOperator::LT && Op <= BinaryOperator::NE));
|
||||
|
||||
return EvaluateAPSInt(ValMgr, Op, getValue(), RHS.getValue());
|
||||
return ValMgr.EvaluateAPSInt(Op, getValue(), RHS.getValue());
|
||||
}
|
||||
|
||||
NonLValue LValue::EQ(ValueManager& ValMgr, const LValue& RHS) const {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This files defines SymbolManager, a class that manages symbolic values
|
||||
// created for use by GRExprEngine and related classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/SymbolManager.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
SymbolID SymbolManager::getSymbol(ParmVarDecl* D) {
|
||||
SymbolID& X = DataToSymbol[getKey(D)];
|
||||
|
||||
if (!X.isInitialized()) {
|
||||
X = SymbolToData.size();
|
||||
SymbolToData.push_back(SymbolDataParmVar(D));
|
||||
}
|
||||
|
||||
return X;
|
||||
}
|
||||
|
||||
SymbolID SymbolManager::getContentsOfSymbol(SymbolID sym) {
|
||||
SymbolID& X = DataToSymbol[getKey(sym)];
|
||||
|
||||
if (!X.isInitialized()) {
|
||||
X = SymbolToData.size();
|
||||
SymbolToData.push_back(SymbolDataContentsOf(sym));
|
||||
}
|
||||
|
||||
return X;
|
||||
}
|
||||
|
||||
QualType SymbolData::getType() const {
|
||||
switch (getKind()) {
|
||||
default:
|
||||
assert (false && "getType() not implemented for this symbol.");
|
||||
|
||||
case ParmKind:
|
||||
return cast<SymbolDataParmVar>(this)->getDecl()->getType();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
SymbolManager::SymbolManager() {}
|
||||
SymbolManager::~SymbolManager() {}
|
|
@ -0,0 +1,134 @@
|
|||
// ValueManager.h - Low-level value management for Value Tracking -*- C++ -*--==
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This files defines ValueManager, a class that manages the lifetime of APSInt
|
||||
// objects and symbolic constraints used by GRExprEngine and related classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/Analysis/PathSensitive/ValueManager.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
ValueManager::~ValueManager() {
|
||||
// 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();
|
||||
}
|
||||
|
||||
const llvm::APSInt& ValueManager::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& ValueManager::getValue(uint64_t X, unsigned BitWidth,
|
||||
bool isUnsigned) {
|
||||
llvm::APSInt V(BitWidth, isUnsigned);
|
||||
V = X;
|
||||
return getValue(V);
|
||||
}
|
||||
|
||||
const llvm::APSInt& ValueManager::getValue(uint64_t X, QualType T,
|
||||
SourceLocation Loc) {
|
||||
|
||||
unsigned bits = Ctx.getTypeSize(T, Loc);
|
||||
llvm::APSInt V(bits, T->isUnsignedIntegerType());
|
||||
V = X;
|
||||
return getValue(V);
|
||||
}
|
||||
|
||||
const SymIntConstraint&
|
||||
ValueManager::getConstraint(SymbolID 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;
|
||||
}
|
||||
|
||||
const llvm::APSInt&
|
||||
ValueManager::EvaluateAPSInt(BinaryOperator::Opcode Op,
|
||||
const llvm::APSInt& V1, const llvm::APSInt& V2) {
|
||||
|
||||
switch (Op) {
|
||||
default:
|
||||
assert (false && "Invalid Opcode.");
|
||||
|
||||
case BinaryOperator::Mul:
|
||||
return getValue( V1 * V2 );
|
||||
|
||||
case BinaryOperator::Div:
|
||||
return getValue( V1 / V2 );
|
||||
|
||||
case BinaryOperator::Rem:
|
||||
return getValue( V1 % V2 );
|
||||
|
||||
case BinaryOperator::Add:
|
||||
return getValue( V1 + V2 );
|
||||
|
||||
case BinaryOperator::Sub:
|
||||
return getValue( V1 - V2 );
|
||||
|
||||
case BinaryOperator::Shl:
|
||||
return getValue( V1.operator<<( (unsigned) V2.getZExtValue() ));
|
||||
|
||||
case BinaryOperator::Shr:
|
||||
return getValue( V1.operator>>( (unsigned) V2.getZExtValue() ));
|
||||
|
||||
case BinaryOperator::LT:
|
||||
return getTruthValue( V1 < V2 );
|
||||
|
||||
case BinaryOperator::GT:
|
||||
return getTruthValue( V1 > V2 );
|
||||
|
||||
case BinaryOperator::LE:
|
||||
return getTruthValue( V1 <= V2 );
|
||||
|
||||
case BinaryOperator::GE:
|
||||
return getTruthValue( V1 >= V2 );
|
||||
|
||||
case BinaryOperator::EQ:
|
||||
return getTruthValue( V1 == V2 );
|
||||
|
||||
case BinaryOperator::NE:
|
||||
return getTruthValue( V1 != V2 );
|
||||
|
||||
// Note: LAnd, LOr, Comma are handled specially by higher-level logic.
|
||||
|
||||
case BinaryOperator::And:
|
||||
return getValue( V1 & V2 );
|
||||
|
||||
case BinaryOperator::Or:
|
||||
return getValue( V1 | V2 );
|
||||
}
|
||||
}
|
|
@ -15,224 +15,9 @@
|
|||
#ifndef LLVM_CLANG_ANALYSIS_RVALUE_H
|
||||
#define LLVM_CLANG_ANALYSIS_RVALUE_H
|
||||
|
||||
// FIXME: reduce the number of includes.
|
||||
|
||||
#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "clang/Analysis/Analyses/LiveVariables.h"
|
||||
|
||||
#include "clang/Analysis/PathSensitive/ValueManager.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/Streams.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
//==------------------------------------------------------------------------==//
|
||||
// Values and ValueManager.
|
||||
//==------------------------------------------------------------------------==//
|
||||
|
||||
namespace clang {
|
||||
|
||||
class SymbolID {
|
||||
unsigned Data;
|
||||
public:
|
||||
SymbolID() : Data(~0) {}
|
||||
SymbolID(unsigned x) : Data(x) {}
|
||||
|
||||
bool isInitialized() const { return Data != (unsigned) ~0; }
|
||||
operator unsigned() const { assert (isInitialized()); return Data; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const {
|
||||
assert (isInitialized());
|
||||
ID.AddInteger(Data);
|
||||
}
|
||||
|
||||
static inline void Profile(llvm::FoldingSetNodeID& ID, SymbolID X) {
|
||||
X.Profile(ID);
|
||||
}
|
||||
};
|
||||
|
||||
// SymbolData: Used to record meta data about symbols.
|
||||
|
||||
class SymbolData {
|
||||
public:
|
||||
enum Kind { UninitKind, ParmKind, ContentsOfKind };
|
||||
|
||||
private:
|
||||
uintptr_t Data;
|
||||
Kind K;
|
||||
|
||||
protected:
|
||||
SymbolData(uintptr_t D, Kind k) : Data(D), K(k) {}
|
||||
SymbolData(void* D, Kind k) : Data(reinterpret_cast<uintptr_t>(D)), K(k) {}
|
||||
|
||||
void* getPtr() const {
|
||||
assert (K != UninitKind);
|
||||
return reinterpret_cast<void*>(Data);
|
||||
}
|
||||
|
||||
uintptr_t getInt() const {
|
||||
assert (K != UninitKind);
|
||||
return Data;
|
||||
}
|
||||
|
||||
public:
|
||||
SymbolData() : Data(0), K(UninitKind) {}
|
||||
|
||||
Kind getKind() const { return K; }
|
||||
|
||||
inline bool operator==(const SymbolData& R) const {
|
||||
return K == R.K && Data == R.Data;
|
||||
}
|
||||
|
||||
QualType getType() const;
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymbolData*) { return true; }
|
||||
};
|
||||
|
||||
class SymbolDataParmVar : public SymbolData {
|
||||
public:
|
||||
SymbolDataParmVar(ParmVarDecl* VD) : SymbolData(VD, ParmKind) {}
|
||||
|
||||
ParmVarDecl* getDecl() const { return (ParmVarDecl*) getPtr(); }
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymbolData* D) {
|
||||
return D->getKind() == ParmKind;
|
||||
}
|
||||
};
|
||||
|
||||
class SymbolDataContentsOf : public SymbolData {
|
||||
public:
|
||||
SymbolDataContentsOf(SymbolID ID) : SymbolData(ID, ContentsOfKind) {}
|
||||
|
||||
SymbolID getSymbol() const { return (SymbolID) getInt(); }
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymbolData* D) {
|
||||
return D->getKind() == ContentsOfKind;
|
||||
}
|
||||
};
|
||||
|
||||
// Constraints on symbols. Usually wrapped by RValues.
|
||||
|
||||
class SymIntConstraint : public llvm::FoldingSetNode {
|
||||
SymbolID Symbol;
|
||||
BinaryOperator::Opcode Op;
|
||||
const llvm::APSInt& Val;
|
||||
public:
|
||||
SymIntConstraint(SymbolID sym, BinaryOperator::Opcode op,
|
||||
const llvm::APSInt& V)
|
||||
: Symbol(sym),
|
||||
Op(op), Val(V) {}
|
||||
|
||||
BinaryOperator::Opcode getOpcode() const { return Op; }
|
||||
const SymbolID& getSymbol() const { return Symbol; }
|
||||
const llvm::APSInt& getInt() const { return Val; }
|
||||
|
||||
static inline void Profile(llvm::FoldingSetNodeID& ID,
|
||||
const SymbolID& Symbol,
|
||||
BinaryOperator::Opcode Op,
|
||||
const llvm::APSInt& Val) {
|
||||
Symbol.Profile(ID);
|
||||
ID.AddInteger(Op);
|
||||
ID.AddPointer(&Val);
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) {
|
||||
Profile(ID, Symbol, Op, Val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SymbolManager {
|
||||
std::vector<SymbolData> SymbolToData;
|
||||
|
||||
typedef llvm::DenseMap<void*,SymbolID> MapTy;
|
||||
MapTy DataToSymbol;
|
||||
|
||||
void* getKey(void* P) const {
|
||||
return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(P) | 0x1);
|
||||
}
|
||||
|
||||
void* getKey(SymbolID sym) const {
|
||||
return reinterpret_cast<void*>((uintptr_t) (sym << 1));
|
||||
}
|
||||
|
||||
public:
|
||||
SymbolManager();
|
||||
~SymbolManager();
|
||||
|
||||
SymbolID getSymbol(ParmVarDecl* D);
|
||||
SymbolID getContentsOfSymbol(SymbolID sym);
|
||||
|
||||
inline const SymbolData& getSymbolData(SymbolID ID) const {
|
||||
assert (ID < SymbolToData.size());
|
||||
return SymbolToData[ID];
|
||||
}
|
||||
|
||||
inline QualType getType(SymbolID ID) const {
|
||||
return getSymbolData(ID).getType();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class ValueManager {
|
||||
typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
|
||||
APSIntSetTy;
|
||||
|
||||
typedef llvm::FoldingSet<SymIntConstraint>
|
||||
SymIntCSetTy;
|
||||
|
||||
|
||||
ASTContext& Ctx;
|
||||
llvm::BumpPtrAllocator& BPAlloc;
|
||||
|
||||
APSIntSetTy APSIntSet;
|
||||
SymIntCSetTy SymIntCSet;
|
||||
|
||||
public:
|
||||
ValueManager(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
|
||||
: Ctx(ctx), BPAlloc(Alloc) {}
|
||||
|
||||
~ValueManager();
|
||||
|
||||
ASTContext& getContext() const { return Ctx; }
|
||||
|
||||
const llvm::APSInt& getValue(const llvm::APSInt& X);
|
||||
const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
|
||||
const llvm::APSInt& getValue(uint64_t X, QualType T,
|
||||
SourceLocation Loc = SourceLocation());
|
||||
|
||||
inline const llvm::APSInt& getZeroWithPtrWidth() {
|
||||
return getValue( 0,
|
||||
Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()),
|
||||
true );
|
||||
}
|
||||
|
||||
inline const llvm::APSInt& getTruthValue(bool b) {
|
||||
return getValue( b ? 1 : 0,
|
||||
Ctx.getTypeSize(Ctx.IntTy, SourceLocation()),
|
||||
false );
|
||||
|
||||
}
|
||||
|
||||
const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
|
||||
const llvm::APSInt& V);
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
//==------------------------------------------------------------------------==//
|
||||
// Base RValue types.
|
||||
//==------------------------------------------------------------------------==//
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
//==- StateVariant.h - Variant to wrap generated analysis states --*- 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 the template class StateVariant, which serves to wrap
|
||||
// states that are generated by transfer functions.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_PS_STATEVARIANT
|
||||
#define LLVM_CLANG_ANALYSIS_PS_STATEVARIANT
|
||||
|
||||
namespace clang {
|
||||
|
||||
template<typename StateTy>
|
||||
class StateVariant {
|
||||
enum VariantFlag { Infeasible, ImpotentStmt, HasState };
|
||||
StateTy* State;
|
||||
VariantFlag Flag;
|
||||
|
||||
explicit StateVariant(StateTy* state, VariantFlag f) : State(state), Flag(f){}
|
||||
|
||||
public:
|
||||
StateVariant(StateTy* state) : State(state), Flag(HasState) {}
|
||||
|
||||
bool isInfeasible() const { return Flag == Infeasible; }
|
||||
bool isStmtImpotent() const { return Flag == ImpotentStmt; }
|
||||
|
||||
StateTy* getState() const {
|
||||
assert (!isInfeasible());
|
||||
return State;
|
||||
}
|
||||
|
||||
// Factory methods to create states indicating infeasible paths or that
|
||||
// a statement can never modify the program state (from the perspective of
|
||||
// the analysis).
|
||||
static inline StateVariant DenoteInfeasiblePath(StateTy* state = NULL) {
|
||||
return StateVariant(state,Infeasible);
|
||||
}
|
||||
|
||||
static inline StateVariant DenoteImpotentStmt(StateTy* state) {
|
||||
return StateVariant(state,ImpotentStmt);
|
||||
}
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,173 @@
|
|||
//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This files defines SymbolManager, a class that manages symbolic values
|
||||
// created for use by GRExprEngine and related classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_SYMMGR_H
|
||||
#define LLVM_CLANG_ANALYSIS_SYMMGR_H
|
||||
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include <vector>
|
||||
|
||||
namespace clang {
|
||||
|
||||
class SymbolID {
|
||||
unsigned Data;
|
||||
public:
|
||||
SymbolID() : Data(~0) {}
|
||||
SymbolID(unsigned x) : Data(x) {}
|
||||
|
||||
bool isInitialized() const { return Data != (unsigned) ~0; }
|
||||
operator unsigned() const { assert (isInitialized()); return Data; }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const {
|
||||
assert (isInitialized());
|
||||
ID.AddInteger(Data);
|
||||
}
|
||||
|
||||
static inline void Profile(llvm::FoldingSetNodeID& ID, SymbolID X) {
|
||||
X.Profile(ID);
|
||||
}
|
||||
};
|
||||
|
||||
// SymbolData: Used to record meta data about symbols.
|
||||
|
||||
class SymbolData {
|
||||
public:
|
||||
enum Kind { UninitKind, ParmKind, ContentsOfKind };
|
||||
|
||||
private:
|
||||
uintptr_t Data;
|
||||
Kind K;
|
||||
|
||||
protected:
|
||||
SymbolData(uintptr_t D, Kind k) : Data(D), K(k) {}
|
||||
SymbolData(void* D, Kind k) : Data(reinterpret_cast<uintptr_t>(D)), K(k) {}
|
||||
|
||||
void* getPtr() const {
|
||||
assert (K != UninitKind);
|
||||
return reinterpret_cast<void*>(Data);
|
||||
}
|
||||
|
||||
uintptr_t getInt() const {
|
||||
assert (K != UninitKind);
|
||||
return Data;
|
||||
}
|
||||
|
||||
public:
|
||||
SymbolData() : Data(0), K(UninitKind) {}
|
||||
|
||||
Kind getKind() const { return K; }
|
||||
|
||||
inline bool operator==(const SymbolData& R) const {
|
||||
return K == R.K && Data == R.Data;
|
||||
}
|
||||
|
||||
QualType getType() const;
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymbolData*) { return true; }
|
||||
};
|
||||
|
||||
class SymbolDataParmVar : public SymbolData {
|
||||
public:
|
||||
SymbolDataParmVar(ParmVarDecl* VD) : SymbolData(VD, ParmKind) {}
|
||||
|
||||
ParmVarDecl* getDecl() const { return (ParmVarDecl*) getPtr(); }
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymbolData* D) {
|
||||
return D->getKind() == ParmKind;
|
||||
}
|
||||
};
|
||||
|
||||
class SymbolDataContentsOf : public SymbolData {
|
||||
public:
|
||||
SymbolDataContentsOf(SymbolID ID) : SymbolData(ID, ContentsOfKind) {}
|
||||
|
||||
SymbolID getSymbol() const { return (SymbolID) getInt(); }
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const SymbolData* D) {
|
||||
return D->getKind() == ContentsOfKind;
|
||||
}
|
||||
};
|
||||
|
||||
// Constraints on symbols. Usually wrapped by RValues.
|
||||
|
||||
class SymIntConstraint : public llvm::FoldingSetNode {
|
||||
SymbolID Symbol;
|
||||
BinaryOperator::Opcode Op;
|
||||
const llvm::APSInt& Val;
|
||||
public:
|
||||
SymIntConstraint(SymbolID sym, BinaryOperator::Opcode op,
|
||||
const llvm::APSInt& V)
|
||||
: Symbol(sym),
|
||||
Op(op), Val(V) {}
|
||||
|
||||
BinaryOperator::Opcode getOpcode() const { return Op; }
|
||||
const SymbolID& getSymbol() const { return Symbol; }
|
||||
const llvm::APSInt& getInt() const { return Val; }
|
||||
|
||||
static inline void Profile(llvm::FoldingSetNodeID& ID,
|
||||
const SymbolID& Symbol,
|
||||
BinaryOperator::Opcode Op,
|
||||
const llvm::APSInt& Val) {
|
||||
Symbol.Profile(ID);
|
||||
ID.AddInteger(Op);
|
||||
ID.AddPointer(&Val);
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) {
|
||||
Profile(ID, Symbol, Op, Val);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class SymbolManager {
|
||||
std::vector<SymbolData> SymbolToData;
|
||||
|
||||
typedef llvm::DenseMap<void*,SymbolID> MapTy;
|
||||
MapTy DataToSymbol;
|
||||
|
||||
void* getKey(void* P) const {
|
||||
return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(P) | 0x1);
|
||||
}
|
||||
|
||||
void* getKey(SymbolID sym) const {
|
||||
return reinterpret_cast<void*>((uintptr_t) (sym << 1));
|
||||
}
|
||||
|
||||
public:
|
||||
SymbolManager();
|
||||
~SymbolManager();
|
||||
|
||||
SymbolID getSymbol(ParmVarDecl* D);
|
||||
SymbolID getContentsOfSymbol(SymbolID sym);
|
||||
|
||||
inline const SymbolData& getSymbolData(SymbolID ID) const {
|
||||
assert (ID < SymbolToData.size());
|
||||
return SymbolToData[ID];
|
||||
}
|
||||
|
||||
inline QualType getType(SymbolID ID) const {
|
||||
return getSymbolData(ID).getType();
|
||||
}
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
|
@ -0,0 +1,79 @@
|
|||
// ValueManager.h - Low-level value management for Value Tracking -*- C++ -*--==
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This files defines ValueManager, a class that manages the lifetime of APSInt
|
||||
// objects and symbolic constraints used by GRExprEngine and related classes.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_ANALYSIS_VALUEMANAGER_H
|
||||
#define LLVM_CLANG_ANALYSIS_VALUEMANAGER_H
|
||||
|
||||
#include "clang/Analysis/PathSensitive/SymbolManager.h"
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/APSInt.h"
|
||||
|
||||
namespace llvm {
|
||||
class BumpPtrAllocator;
|
||||
}
|
||||
|
||||
namespace clang {
|
||||
class ASTContext;
|
||||
|
||||
|
||||
class ValueManager {
|
||||
typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
|
||||
APSIntSetTy;
|
||||
|
||||
typedef llvm::FoldingSet<SymIntConstraint>
|
||||
SymIntCSetTy;
|
||||
|
||||
ASTContext& Ctx;
|
||||
llvm::BumpPtrAllocator& BPAlloc;
|
||||
|
||||
APSIntSetTy APSIntSet;
|
||||
SymIntCSetTy SymIntCSet;
|
||||
|
||||
public:
|
||||
ValueManager(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
|
||||
: Ctx(ctx), BPAlloc(Alloc) {}
|
||||
|
||||
~ValueManager();
|
||||
|
||||
ASTContext& getContext() const { return Ctx; }
|
||||
|
||||
const llvm::APSInt& getValue(const llvm::APSInt& X);
|
||||
const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
|
||||
const llvm::APSInt& getValue(uint64_t X, QualType T,
|
||||
SourceLocation Loc = SourceLocation());
|
||||
|
||||
inline const llvm::APSInt& getZeroWithPtrWidth() {
|
||||
return getValue( 0,
|
||||
Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()),
|
||||
true );
|
||||
}
|
||||
|
||||
inline const llvm::APSInt& getTruthValue(bool b) {
|
||||
return getValue( b ? 1 : 0,
|
||||
Ctx.getTypeSize(Ctx.IntTy, SourceLocation()),
|
||||
false );
|
||||
}
|
||||
|
||||
const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
|
||||
const llvm::APSInt& V);
|
||||
|
||||
const llvm::APSInt& EvaluateAPSInt(BinaryOperator::Opcode Op,
|
||||
const llvm::APSInt& V1,
|
||||
const llvm::APSInt& V2);
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue