[cfe-commits] r50453 - in /cfe/trunk: include/clang/Analysis/PathSensitive/BasicValueFactory.h include/clang/Analysis/PathSensitive/RValues.h lib/Analysis/BasicValueFactory.cpp lib/Analysis/GRExprEngine.cpp lib/Analysis/RValues.cpp lib/Analysis/ValueState.cpp
Ted Kremenek
kremenek at apple.com
Tue Apr 29 16:24:45 PDT 2008
Author: kremenek
Date: Tue Apr 29 18:24:44 2008
New Revision: 50453
URL: http://llvm.org/viewvc/llvm-project?rev=50453&view=rev
Log:
Add lval::ArrayOffset, which represent the locations of entries in an array.
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h
cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
cfe/trunk/lib/Analysis/BasicValueFactory.cpp
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/RValues.cpp
cfe/trunk/lib/Analysis/ValueState.cpp
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h?rev=50453&r1=50452&r2=50453&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h Tue Apr 29 18:24:44 2008
@@ -43,10 +43,11 @@
APSIntSetTy APSIntSet;
SymIntCSetTy SymIntCSet;
void* PersistentRVals;
+ void* PersistentRValPairs;
public:
BasicValueFactory(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
- : Ctx(ctx), BPAlloc(Alloc), PersistentRVals(0) {}
+ : Ctx(ctx), BPAlloc(Alloc), PersistentRVals(0), PersistentRValPairs(0) {}
~BasicValueFactory();
@@ -73,6 +74,9 @@
const std::pair<RVal, uintptr_t>&
getPersistentRValWithData(const RVal& V, uintptr_t Data);
+
+ const std::pair<RVal, RVal>&
+ getPersistentRValPair(const RVal& V1, const RVal& V2);
};
} // end clang namespace
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h?rev=50453&r1=50452&r2=50453&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h Tue Apr 29 18:24:44 2008
@@ -279,7 +279,8 @@
namespace lval {
enum Kind { SymbolValKind, GotoLabelKind, DeclValKind, FuncValKind,
- ConcreteIntKind, StringLiteralValKind, FieldOffsetKind };
+ ConcreteIntKind, StringLiteralValKind, FieldOffsetKind,
+ ArrayOffsetKind };
class SymbolVal : public LVal {
public:
@@ -415,9 +416,7 @@
class FieldOffset : public LVal {
FieldOffset(const std::pair<RVal, uintptr_t>& data)
- : LVal(FieldOffsetKind, &data) {
- assert (isa<LVal>(data.first));
- }
+ : LVal(FieldOffsetKind, &data) {}
public:
@@ -455,6 +454,49 @@
}
};
+class ArrayOffset : public LVal {
+ ArrayOffset(const std::pair<RVal,RVal>& data) : LVal(ArrayOffsetKind,&data) {}
+public:
+
+ LVal getBase() const {
+ return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->first;
+ }
+
+ const LVal& getPersistentBase() const {
+ return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->first;
+ }
+
+ RVal getOffset() const {
+ return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->second;
+ }
+
+ const RVal& getPersistentOffset() const {
+ return reinterpret_cast<const std::pair<LVal,RVal>*> (Data)->second;
+ }
+
+
+ // Implement isa<T> support.
+ static inline bool classof(const RVal* V) {
+ return V->getBaseKind() == LValKind &&
+ V->getSubKind() == ArrayOffsetKind;
+ }
+
+ static inline bool classof(const LVal* V) {
+ return V->getSubKind() == ArrayOffsetKind;
+ }
+
+ static inline RVal Make(BasicValueFactory& Vals, RVal Base, RVal Offset) {
+
+ if (Base.isUnknownOrUndef())
+ return Base;
+
+ if (Offset.isUndef())
+ return Offset;
+
+ return ArrayOffset(Vals.getPersistentRValPair(cast<LVal>(Base), Offset));
+ }
+};
+
} // end clang::lval namespace
} // end clang namespace
Modified: cfe/trunk/lib/Analysis/BasicValueFactory.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicValueFactory.cpp?rev=50453&r1=50452&r2=50453&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BasicValueFactory.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicValueFactory.cpp Tue Apr 29 18:24:44 2008
@@ -19,6 +19,8 @@
using namespace clang;
typedef std::pair<RVal, uintptr_t> RValData;
+typedef std::pair<RVal, RVal> RValPair;
+
namespace llvm {
template<> struct FoldingSetTrait<RValData> {
@@ -27,11 +29,21 @@
ID.AddPointer( (void*) X.second);
}
};
+
+template<> struct FoldingSetTrait<RValPair> {
+ static inline void Profile(const RValPair& X, llvm::FoldingSetNodeID& ID) {
+ X.first.Profile(ID);
+ X.second.Profile(ID);
+ }
+};
}
typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<RValData> >
PersistentRValsTy;
+typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<RValPair> >
+ PersistentRValPairsTy;
+
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
@@ -40,6 +52,7 @@
I->getValue().~APSInt();
delete (PersistentRValsTy*) PersistentRVals;
+ delete (PersistentRValPairsTy*) PersistentRValPairs;
}
const llvm::APSInt& BasicValueFactory::getValue(const llvm::APSInt& X) {
@@ -208,3 +221,29 @@
return P->getValue();
}
+
+const std::pair<RVal, RVal>&
+BasicValueFactory::getPersistentRValPair(const RVal& V1, const RVal& V2) {
+
+ // Lazily create the folding set.
+ if (!PersistentRValPairs) PersistentRValPairs = new PersistentRValPairsTy();
+
+ llvm::FoldingSetNodeID ID;
+ void* InsertPos;
+ V1.Profile(ID);
+ V2.Profile(ID);
+
+ PersistentRValPairsTy& Map = *((PersistentRValPairsTy*) PersistentRValPairs);
+
+ typedef llvm::FoldingSetNodeWrapper<RValPair> 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();
+}
+
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=50453&r1=50452&r2=50453&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Tue Apr 29 18:24:44 2008
@@ -780,6 +780,7 @@
NodeSet& Dst, bool asLVal) {
Expr* Base = A->getBase()->IgnoreParens();
+ Expr* Idx = A->getIdx()->IgnoreParens();
// Always visit the base as an LVal expression. This computes the
// abstract address of the base object.
@@ -790,47 +791,25 @@
else
VisitLVal(Base, Pred, Tmp);
- // TODO: Compute the LVal for the entry. This will enable array sensitivity
- // for the analysis.
-
- // Return the LVal of the array entry.
- if (asLVal) {
+ for (NodeSet::iterator I1=Tmp.begin(), E1=Tmp.end(); I1!=E1; ++I1) {
- // 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);
-
- // TODO: Compute the LVal for the entry. This will enable array sensitivity
- // for the analysis.
-
- if (!(V.isUndef() || V.isUnknown() || isa<lval::ConcreteInt>(V)))
- V = UnknownVal();
+ // Evaluate the index.
+
+ NodeSet Tmp2;
+ Visit(Idx, *I1, Tmp2);
- MakeNode(Dst, A, *I, SetRVal(St, A, V));
- }
-
- return;
- }
-
- // We are doing a load. Check for a bad dereference. In the future we
- // will check the actual entry lval; for now, check the Base LVal. For now
- // the load will just return "UnknownVal" (since we don't have array
- // sensitivity), but it will perform a null check.
-
- for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
+ for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2!=E2; ++I2) {
- ValueState* St = GetState(*I);
- RVal V = GetRVal(St, Base);
-
- // TODO: Compute the LVal for the entry. This will enable array sensitivity
- // for the analysis.
-
- if (!(V.isUndef() || V.isUnknown() || isa<lval::ConcreteInt>(V)))
- V = UnknownVal();
-
- EvalLoad(Dst, A, *I, St, GetRVal(St, Base), true);
+ ValueState* St = GetState(*I2);
+ RVal BaseV = GetRVal(St, Base);
+ RVal IdxV = GetRVal(St, Idx);
+ RVal V = lval::ArrayOffset::Make(BasicVals, BaseV, IdxV);
+
+ if (asLVal)
+ MakeNode(Dst, A, *I2, SetRVal(St, A, V));
+ else
+ EvalLoad(Dst, A, *I2, St, V);
+ }
}
}
@@ -849,36 +828,17 @@
else
VisitLVal(Base, Pred, Tmp);
-
- // Return the LVal of the field access.
- if (asLVal) {
-
- // 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 BaseV = GetRVal(St, Base);
-
- RVal V = lval::FieldOffset::Make(BasicVals, GetRVal(St, Base),
- M->getMemberDecl());
-
- MakeNode(Dst, M, *I, SetRVal(St, M, V));
- }
-
- return;
- }
-
- // We are doing a load. Check for a bad dereference. In the future we
- // will check the actual field lval; for now, check the Base LVal. For now
- // the load will just return "UnknownVal" (since we don't have field
- // sensitivity), but it will perform a null check.
-
for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
ValueState* St = GetState(*I);
+ RVal BaseV = GetRVal(St, Base);
RVal V = lval::FieldOffset::Make(BasicVals, GetRVal(St, Base),
M->getMemberDecl());
- EvalLoad(Dst, M, *I, St, V, true);
+ if (asLVal)
+ MakeNode(Dst, M, *I, SetRVal(St, M, V));
+ else
+ EvalLoad(Dst, M, *I, St, V);
}
}
@@ -2030,6 +1990,10 @@
return AssumeAux(St, cast<lval::FieldOffset>(Cond).getBase(),
Assumption, isFeasible);
+ case lval::ArrayOffsetKind:
+ return AssumeAux(St, cast<lval::ArrayOffset>(Cond).getBase(),
+ Assumption, isFeasible);
+
case lval::ConcreteIntKind: {
bool b = cast<lval::ConcreteInt>(Cond).getValue() != 0;
isFeasible = b ? Assumption : !Assumption;
Modified: cfe/trunk/lib/Analysis/RValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RValues.cpp?rev=50453&r1=50452&r2=50453&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/RValues.cpp (original)
+++ cfe/trunk/lib/Analysis/RValues.cpp Tue Apr 29 18:24:44 2008
@@ -415,6 +415,15 @@
break;
}
+ case lval::ArrayOffsetKind: {
+ const lval::ArrayOffset& C = *cast<lval::ArrayOffset>(this);
+ C.getBase().print(Out);
+ Out << "[";
+ C.getOffset().print(Out);
+ Out << "] (lval array entry)";
+ break;
+ }
+
default:
assert (false && "Pretty-printing not implemented for this LVal.");
break;
Modified: cfe/trunk/lib/Analysis/ValueState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ValueState.cpp?rev=50453&r1=50452&r2=50453&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ValueState.cpp (original)
+++ cfe/trunk/lib/Analysis/ValueState.cpp Tue Apr 29 18:24:44 2008
@@ -212,6 +212,7 @@
return UnknownVal();
}
+ case lval::ArrayOffsetKind:
case lval::FieldOffsetKind:
return UnknownVal();
More information about the cfe-commits
mailing list