Add lval::ArrayOffset, which represent the locations of entries in an array.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50453 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/BasicValueFactory.cpp b/lib/Analysis/BasicValueFactory.cpp
index b0aa79e..8d737a9 100644
--- a/lib/Analysis/BasicValueFactory.cpp
+++ b/lib/Analysis/BasicValueFactory.cpp
@@ -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();
+}
+
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index a4f1a05..a7b31d5 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -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();
-
- 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) {
+ // Evaluate the index.
- 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);
+ NodeSet Tmp2;
+ Visit(Idx, *I1, Tmp2);
+
+ for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2!=E2; ++I2) {
+
+ 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;
diff --git a/lib/Analysis/RValues.cpp b/lib/Analysis/RValues.cpp
index ab1cf6a..85c3b23 100644
--- a/lib/Analysis/RValues.cpp
+++ b/lib/Analysis/RValues.cpp
@@ -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;
diff --git a/lib/Analysis/ValueState.cpp b/lib/Analysis/ValueState.cpp
index e51366d..edc5b6d 100644
--- a/lib/Analysis/ValueState.cpp
+++ b/lib/Analysis/ValueState.cpp
@@ -212,6 +212,7 @@
return UnknownVal();
}
+ case lval::ArrayOffsetKind:
case lval::FieldOffsetKind:
return UnknownVal();