зеркало из https://github.com/microsoft/clang-1.git
Added lval::FieldOffset, which represents symbolic lvalues for field offsets from other Lvalues.
This removes the failure in null-deref-ps.c (test suite). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50449 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
1b8bd4d71c
Коммит
718c4f7b3f
|
@ -71,8 +71,8 @@ public:
|
|||
const llvm::APSInt& V1,
|
||||
const llvm::APSInt& V2);
|
||||
|
||||
const std::pair<RVal, unsigned>&
|
||||
getPersistentSizedRVal(const RVal& V, unsigned Bits);
|
||||
const std::pair<RVal, uintptr_t>&
|
||||
getPersistentRValWithData(const RVal& V, uintptr_t Data);
|
||||
};
|
||||
|
||||
} // end clang namespace
|
||||
|
|
|
@ -234,17 +234,20 @@ public:
|
|||
};
|
||||
|
||||
class LValAsInteger : public NonLVal {
|
||||
LValAsInteger(const std::pair<RVal, unsigned>& data) :
|
||||
NonLVal(LValAsIntegerKind, &data) {}
|
||||
LValAsInteger(const std::pair<RVal, uintptr_t>& data) :
|
||||
NonLVal(LValAsIntegerKind, &data) {
|
||||
assert (isa<LVal>(data.first));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
LVal getLVal() const {
|
||||
return cast<LVal>(((std::pair<RVal, unsigned>*) Data)->first);
|
||||
return cast<LVal>(((std::pair<RVal, uintptr_t>*) Data)->first);
|
||||
}
|
||||
|
||||
const LVal& getPersistentLVal() const {
|
||||
return cast<LVal>(((std::pair<RVal, unsigned>*) Data)->first);
|
||||
const RVal& V = ((std::pair<RVal, uintptr_t>*) Data)->first;
|
||||
return cast<LVal>(V);
|
||||
}
|
||||
|
||||
unsigned getNumBits() const {
|
||||
|
@ -263,7 +266,7 @@ public:
|
|||
|
||||
static inline LValAsInteger Make(BasicValueFactory& Vals, LVal V,
|
||||
unsigned Bits) {
|
||||
return LValAsInteger(Vals.getPersistentSizedRVal(V, Bits));
|
||||
return LValAsInteger(Vals.getPersistentRValWithData(V, Bits));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -276,7 +279,7 @@ public:
|
|||
namespace lval {
|
||||
|
||||
enum Kind { SymbolValKind, GotoLabelKind, DeclValKind, FuncValKind,
|
||||
ConcreteIntKind, StringLiteralValKind };
|
||||
ConcreteIntKind, StringLiteralValKind, FieldOffsetKind };
|
||||
|
||||
class SymbolVal : public LVal {
|
||||
public:
|
||||
|
@ -409,7 +412,48 @@ public:
|
|||
return V->getSubKind() == StringLiteralValKind;
|
||||
}
|
||||
};
|
||||
|
||||
class FieldOffset : public LVal {
|
||||
FieldOffset(const std::pair<RVal, uintptr_t>& data)
|
||||
: LVal(FieldOffsetKind, &data) {
|
||||
assert (isa<LVal>(data.first));
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
LVal getBase() const {
|
||||
return reinterpret_cast<const std::pair<LVal,uintptr_t>*> (Data)->first;
|
||||
}
|
||||
|
||||
const LVal& getPersistentBase() const {
|
||||
return reinterpret_cast<const std::pair<LVal,uintptr_t>*> (Data)->first;
|
||||
}
|
||||
|
||||
|
||||
FieldDecl* getFieldDecl() const {
|
||||
return (FieldDecl*)
|
||||
reinterpret_cast<const std::pair<LVal,uintptr_t>*> (Data)->second;
|
||||
}
|
||||
|
||||
// Implement isa<T> support.
|
||||
static inline bool classof(const RVal* V) {
|
||||
return V->getBaseKind() == LValKind &&
|
||||
V->getSubKind() == FieldOffsetKind;
|
||||
}
|
||||
|
||||
static inline bool classof(const LVal* V) {
|
||||
return V->getSubKind() == FieldOffsetKind;
|
||||
}
|
||||
|
||||
static inline RVal Make(BasicValueFactory& Vals, RVal Base, FieldDecl* D) {
|
||||
|
||||
if (Base.isUnknownOrUndef())
|
||||
return Base;
|
||||
|
||||
return FieldOffset(Vals.getPersistentRValWithData(cast<LVal>(Base),
|
||||
(uintptr_t) D));
|
||||
}
|
||||
};
|
||||
|
||||
} // end clang::lval namespace
|
||||
} // end clang namespace
|
||||
|
|
|
@ -18,18 +18,18 @@
|
|||
|
||||
using namespace clang;
|
||||
|
||||
typedef std::pair<RVal, unsigned> SizedRVal;
|
||||
typedef std::pair<RVal, uintptr_t> RValData;
|
||||
|
||||
namespace llvm {
|
||||
template<> struct FoldingSetTrait<SizedRVal> {
|
||||
static inline void Profile(const SizedRVal& X, llvm::FoldingSetNodeID& ID) {
|
||||
template<> struct FoldingSetTrait<RValData> {
|
||||
static inline void Profile(const RValData& X, llvm::FoldingSetNodeID& ID) {
|
||||
X.first.Profile(ID);
|
||||
ID.AddInteger(X.second);
|
||||
ID.AddPointer( (void*) X.second);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<SizedRVal> >
|
||||
typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<RValData> >
|
||||
PersistentRValsTy;
|
||||
|
||||
BasicValueFactory::~BasicValueFactory() {
|
||||
|
@ -184,8 +184,8 @@ BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
|
|||
}
|
||||
|
||||
|
||||
const std::pair<RVal, unsigned>&
|
||||
BasicValueFactory::getPersistentSizedRVal(const RVal& V, unsigned Bits) {
|
||||
const std::pair<RVal, uintptr_t>&
|
||||
BasicValueFactory::getPersistentRValWithData(const RVal& V, uintptr_t Data) {
|
||||
|
||||
// Lazily create the folding set.
|
||||
if (!PersistentRVals) PersistentRVals = new PersistentRValsTy();
|
||||
|
@ -193,18 +193,18 @@ BasicValueFactory::getPersistentSizedRVal(const RVal& V, unsigned Bits) {
|
|||
llvm::FoldingSetNodeID ID;
|
||||
void* InsertPos;
|
||||
V.Profile(ID);
|
||||
ID.AddInteger(Bits);
|
||||
ID.AddPointer((void*) Data);
|
||||
|
||||
PersistentRValsTy& Map = *((PersistentRValsTy*) PersistentRVals);
|
||||
|
||||
typedef llvm::FoldingSetNodeWrapper<SizedRVal> FoldNodeTy;
|
||||
typedef llvm::FoldingSetNodeWrapper<RValData> FoldNodeTy;
|
||||
FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos);
|
||||
|
||||
if (!P) {
|
||||
P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
|
||||
new (P) FoldNodeTy(std::make_pair(V, Bits));
|
||||
new (P) FoldNodeTy(std::make_pair(V, Data));
|
||||
Map.InsertNode(P, InsertPos);
|
||||
}
|
||||
|
||||
return *P;
|
||||
return P->getValue();
|
||||
}
|
||||
|
|
|
@ -856,16 +856,12 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred,
|
|||
// This is a redunant copy; we do this as a placeholder for future logic.
|
||||
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
|
||||
ValueState* St = GetState(*I);
|
||||
RVal V = GetRVal(St, Base);
|
||||
RVal BaseV = GetRVal(St, Base);
|
||||
|
||||
// TODO: Compute the LVal for the field. This will enable field
|
||||
// sensitivity for the analysis.
|
||||
|
||||
if (!(V.isUndef() || V.isUnknown() || isa<lval::ConcreteInt>(V)))
|
||||
V = UnknownVal();
|
||||
|
||||
MakeNode(Dst, M, *I, SetRVal(St, M, V));
|
||||
RVal V = lval::FieldOffset::Make(BasicVals, GetRVal(St, Base),
|
||||
M->getMemberDecl());
|
||||
|
||||
MakeNode(Dst, M, *I, SetRVal(St, M, V));
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -879,13 +875,8 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred,
|
|||
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
|
||||
ValueState* St = GetState(*I);
|
||||
|
||||
RVal V = GetRVal(St, Base);
|
||||
|
||||
// TODO: Compute the LVal for the field. This will enable field
|
||||
// sensitivity for the analysis.
|
||||
|
||||
if (!(V.isUndef() || V.isUnknown() || isa<lval::ConcreteInt>(V)))
|
||||
V = UnknownVal();
|
||||
RVal V = lval::FieldOffset::Make(BasicVals, GetRVal(St, Base),
|
||||
M->getMemberDecl());
|
||||
|
||||
EvalLoad(Dst, M, *I, St, V, true);
|
||||
}
|
||||
|
@ -2034,7 +2025,11 @@ ValueState* GRExprEngine::AssumeAux(ValueState* St, LVal Cond,
|
|||
case lval::StringLiteralValKind:
|
||||
isFeasible = Assumption;
|
||||
return St;
|
||||
|
||||
|
||||
case lval::FieldOffsetKind:
|
||||
return AssumeAux(St, cast<lval::FieldOffset>(Cond).getBase(),
|
||||
Assumption, isFeasible);
|
||||
|
||||
case lval::ConcreteIntKind: {
|
||||
bool b = cast<lval::ConcreteInt>(Cond).getValue() != 0;
|
||||
isFeasible = b ? Assumption : !Assumption;
|
||||
|
|
|
@ -25,6 +25,9 @@ using llvm::APSInt;
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
RVal::symbol_iterator RVal::symbol_begin() const {
|
||||
|
||||
// FIXME: This is a rat's nest. Cleanup.
|
||||
|
||||
if (isa<lval::SymbolVal>(this))
|
||||
return (symbol_iterator) (&Data);
|
||||
else if (isa<nonlval::SymbolVal>(this))
|
||||
|
@ -39,7 +42,10 @@ RVal::symbol_iterator RVal::symbol_begin() const {
|
|||
const nonlval::LValAsInteger& V = cast<nonlval::LValAsInteger>(*this);
|
||||
return V.getPersistentLVal().symbol_begin();
|
||||
}
|
||||
|
||||
else if (isa<lval::FieldOffset>(this)) {
|
||||
const lval::FieldOffset& V = cast<lval::FieldOffset>(*this);
|
||||
return V.getPersistentBase().symbol_begin();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -402,6 +408,13 @@ void LVal::print(std::ostream& Out) const {
|
|||
<< "\"";
|
||||
break;
|
||||
|
||||
case lval::FieldOffsetKind: {
|
||||
const lval::FieldOffset& C = *cast<lval::FieldOffset>(this);
|
||||
C.getBase().print(Out);
|
||||
Out << "." << C.getFieldDecl()->getName() << " (field LVal)";
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert (false && "Pretty-printing not implemented for this LVal.");
|
||||
break;
|
||||
|
|
|
@ -212,6 +212,9 @@ RVal ValueStateManager::GetRVal(ValueState* St, LVal LV, QualType T) {
|
|||
return UnknownVal();
|
||||
}
|
||||
|
||||
case lval::FieldOffsetKind:
|
||||
return UnknownVal();
|
||||
|
||||
case lval::FuncValKind:
|
||||
return LV;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче