forked from OSchip/llvm-project
Add "KnownSVal" to represent SVals that cannot be UnknownSVal.
This provides a few sundry cleanups, and allows us to provide a compile-time check for a case that was a runtime assertion. llvm-svn: 175987
This commit is contained in:
parent
c4a90244bb
commit
e3cf171730
|
@ -99,7 +99,7 @@ class FindLastStoreBRVisitor
|
|||
{
|
||||
const MemRegion *R;
|
||||
SVal V;
|
||||
bool satisfied;
|
||||
bool Satisfied;
|
||||
|
||||
public:
|
||||
/// \brief Convenience method to create a visitor given only the MemRegion.
|
||||
|
@ -112,13 +112,10 @@ public:
|
|||
/// the BugReport.
|
||||
static void registerStatementVarDecls(BugReport &BR, const Stmt *S);
|
||||
|
||||
FindLastStoreBRVisitor(SVal v, const MemRegion *r)
|
||||
: R(r), V(v), satisfied(false) {
|
||||
assert (!V.isUnknown() && "Cannot track unknown value.");
|
||||
|
||||
// TODO: Does it make sense to allow undef values here?
|
||||
// (If not, also see UndefCapturedBlockVarChecker)?
|
||||
}
|
||||
FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R)
|
||||
: R(R),
|
||||
V(V),
|
||||
Satisfied(false) {}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) const;
|
||||
|
||||
|
|
|
@ -219,7 +219,7 @@ public:
|
|||
|
||||
private:
|
||||
friend class SVal;
|
||||
static bool isKind(const SVal& V) {
|
||||
static bool isKind(const SVal &V) {
|
||||
return V.getBaseKind() == UnknownKind;
|
||||
}
|
||||
};
|
||||
|
@ -242,6 +242,19 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/// \brief Represents an SVal that is guaranteed to not be UnknownVal.
|
||||
class KnownSVal : public SVal {
|
||||
KnownSVal() {}
|
||||
friend class SVal;
|
||||
static bool isKind(const SVal &V) {
|
||||
return !V.isUnknown();
|
||||
}
|
||||
public:
|
||||
KnownSVal(const DefinedSVal &V) : SVal(V) {}
|
||||
KnownSVal(const UndefinedVal &V) : SVal(V) {}
|
||||
};
|
||||
|
||||
class NonLoc : public DefinedSVal {
|
||||
protected:
|
||||
NonLoc() {}
|
||||
|
|
|
@ -75,9 +75,8 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
|
|||
continue;
|
||||
|
||||
// Get the VarRegion associated with VD in the local stack frame.
|
||||
SVal VRVal = state->getSVal(I.getOriginalRegion());
|
||||
|
||||
if (VRVal.isUndef())
|
||||
if (Optional<UndefinedVal> V =
|
||||
state->getSVal(I.getOriginalRegion()).getAs<UndefinedVal>()) {
|
||||
if (ExplodedNode *N = C.generateSink()) {
|
||||
if (!BT)
|
||||
BT.reset(new BuiltinBug("uninitialized variable captured by block"));
|
||||
|
@ -92,11 +91,12 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE,
|
|||
BugReport *R = new BugReport(*BT, os.str(), N);
|
||||
if (const Expr *Ex = FindBlockDeclRefExpr(BE->getBody(), VD))
|
||||
R->addRange(Ex->getSourceRange());
|
||||
R->addVisitor(new FindLastStoreBRVisitor(VRVal, VR));
|
||||
R->addVisitor(new FindLastStoreBRVisitor(*V, VR));
|
||||
R->disablePathPruning();
|
||||
// need location of block
|
||||
C.emitReport(R);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -354,7 +354,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
|
|||
BugReporterContext &BRC,
|
||||
BugReport &BR) {
|
||||
|
||||
if (satisfied)
|
||||
if (Satisfied)
|
||||
return NULL;
|
||||
|
||||
const ExplodedNode *StoreSite = 0;
|
||||
|
@ -410,7 +410,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
|
|||
|
||||
if (!StoreSite)
|
||||
return NULL;
|
||||
satisfied = true;
|
||||
Satisfied = true;
|
||||
|
||||
// If we have an expression that provided the value, try to track where it
|
||||
// came from.
|
||||
|
@ -449,8 +449,9 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
|
|||
if (const BlockDataRegion *BDR =
|
||||
dyn_cast_or_null<BlockDataRegion>(V.getAsRegion())) {
|
||||
if (const VarRegion *OriginalR = BDR->getOriginalRegion(VR)) {
|
||||
V = State->getSVal(OriginalR);
|
||||
BR.addVisitor(new FindLastStoreBRVisitor(V, OriginalR));
|
||||
if (Optional<KnownSVal> KV =
|
||||
State->getSVal(OriginalR).getAs<KnownSVal>())
|
||||
BR.addVisitor(new FindLastStoreBRVisitor(*KV, OriginalR));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -698,7 +699,8 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S,
|
|||
report.addVisitor(ConstraintTracker);
|
||||
}
|
||||
|
||||
report.addVisitor(new FindLastStoreBRVisitor(V, R));
|
||||
if (Optional<KnownSVal> KV = V.getAs<KnownSVal>())
|
||||
report.addVisitor(new FindLastStoreBRVisitor(*KV, R));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -711,7 +713,6 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S,
|
|||
// Uncomment this to find cases where we aren't properly getting the
|
||||
// base value that was dereferenced.
|
||||
// assert(!V.isUnknownOrUndef());
|
||||
|
||||
// Is it a symbolic value?
|
||||
if (Optional<loc::MemRegionVal> L = V.getAs<loc::MemRegionVal>()) {
|
||||
// At this point we are dealing with the region's LValue.
|
||||
|
@ -743,14 +744,11 @@ FindLastStoreBRVisitor::createVisitorObject(const ExplodedNode *N,
|
|||
assert(R && "The memory region is null.");
|
||||
|
||||
ProgramStateRef state = N->getState();
|
||||
SVal V = state->getSVal(R);
|
||||
if (V.isUnknown())
|
||||
return 0;
|
||||
|
||||
return new FindLastStoreBRVisitor(V, R);
|
||||
if (Optional<KnownSVal> KV = state->getSVal(R).getAs<KnownSVal>())
|
||||
return new FindLastStoreBRVisitor(*KV, R);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N,
|
||||
const ExplodedNode *PrevN,
|
||||
BugReporterContext &BRC,
|
||||
|
@ -808,7 +806,7 @@ void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR,
|
|||
|
||||
if (V.getAs<loc::ConcreteInt>() || V.getAs<nonloc::ConcreteInt>()) {
|
||||
// Register a new visitor with the BugReport.
|
||||
BR.addVisitor(new FindLastStoreBRVisitor(V, R));
|
||||
BR.addVisitor(new FindLastStoreBRVisitor(V.castAs<KnownSVal>(), R));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue