Skip to content

Commit

Permalink
[analyzer] Add LocationContext as a parameter to checkRegionChanges
Browse files Browse the repository at this point in the history
This patch adds LocationContext to checkRegionChanges and removes
wantsRegionChangeUpdate as it was unused.

A patch by Krzysztof Wiśniewski!

Differential Revision: https://reviews.llvm.org/D27090

llvm-svn: 291869
  • Loading branch information
AnnaZaks committed Jan 13, 2017
1 parent e43b4fc commit b570195
Show file tree
Hide file tree
Showing 16 changed files with 84 additions and 62 deletions.
6 changes: 4 additions & 2 deletions clang/include/clang/StaticAnalyzer/Core/Checker.h
Expand Up @@ -321,9 +321,11 @@ class RegionChanges {
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> Explicits,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) {
return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
Explicits, Regions, Call);
return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
Explicits, Regions,
LCtx, Call);
}

public:
Expand Down
10 changes: 6 additions & 4 deletions clang/include/clang/StaticAnalyzer/Core/CheckerManager.h
Expand Up @@ -338,6 +338,7 @@ class CheckerManager {
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call);

/// \brief Run checkers when pointers escape.
Expand Down Expand Up @@ -443,10 +444,11 @@ class CheckerManager {
typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;

typedef CheckerFn<ProgramStateRef (ProgramStateRef,
const InvalidatedSymbols *symbols,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call)>
const InvalidatedSymbols *symbols,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call)>
CheckRegionChangesFunc;

typedef CheckerFn<ProgramStateRef (ProgramStateRef,
Expand Down
Expand Up @@ -293,6 +293,7 @@ class ExprEngine : public SubEngine {
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) override;

/// printState - Called by ProgramStateManager to print checker-specific data.
Expand Down Expand Up @@ -522,7 +523,9 @@ class ExprEngine : public SubEngine {

/// Call PointerEscape callback when a value escapes as a result of bind.
ProgramStateRef processPointerEscapedOnBind(ProgramStateRef State,
SVal Loc, SVal Val) override;
SVal Loc,
SVal Val,
const LocationContext *LCtx) override;
/// Call PointerEscape callback when a value escapes as a result of
/// region invalidation.
/// \param[in] ITraits Specifies invalidation traits for regions/symbols.
Expand Down
Expand Up @@ -229,11 +229,12 @@ class ProgramState : public llvm::FoldingSetNode {

ProgramStateRef bindLoc(Loc location,
SVal V,
const LocationContext *LCtx,
bool notifyChanges = true) const;

ProgramStateRef bindLoc(SVal location, SVal V) const;
ProgramStateRef bindLoc(SVal location, SVal V, const LocationContext *LCtx) const;

ProgramStateRef bindDefault(SVal loc, SVal V) const;
ProgramStateRef bindDefault(SVal loc, SVal V, const LocationContext *LCtx) const;

ProgramStateRef killBinding(Loc LV) const;

Expand Down Expand Up @@ -681,9 +682,9 @@ ProgramState::assumeInclusiveRange(DefinedOrUnknownSVal Val,
this, Val.castAs<NonLoc>(), From, To);
}

inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V) const {
inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationContext *LCtx) const {
if (Optional<Loc> L = LV.getAs<Loc>())
return bindLoc(*L, V);
return bindLoc(*L, V, LCtx);
return this;
}

Expand Down
Expand Up @@ -131,17 +131,19 @@ class SubEngine {
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) = 0;


inline ProgramStateRef
processRegionChange(ProgramStateRef state,
const MemRegion* MR) {
return processRegionChanges(state, nullptr, MR, MR, nullptr);
const MemRegion* MR,
const LocationContext *LCtx) {
return processRegionChanges(state, nullptr, MR, MR, LCtx, nullptr);
}

virtual ProgramStateRef
processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val) = 0;
processPointerEscapedOnBind(ProgramStateRef State, SVal Loc, SVal Val, const LocationContext *LCtx) = 0;

virtual ProgramStateRef
notifyCheckersOfPointerEscape(ProgramStateRef State,
Expand Down
10 changes: 8 additions & 2 deletions clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
Expand Up @@ -68,6 +68,7 @@ class CStringChecker : public Checker< eval::Call,
const InvalidatedSymbols *,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) const;

typedef void (CStringChecker::*FnCheck)(CheckerContext &,
Expand Down Expand Up @@ -1943,8 +1944,12 @@ void CStringChecker::evalStrsep(CheckerContext &C, const CallExpr *CE) const {
// Overwrite the search string pointer. The new value is either an address
// further along in the same string, or NULL if there are no more tokens.
State = State->bindLoc(*SearchStrLoc,
SVB.conjureSymbolVal(getTag(), CE, LCtx, CharPtrTy,
C.blockCount()));
SVB.conjureSymbolVal(getTag(),
CE,
LCtx,
CharPtrTy,
C.blockCount()),
LCtx);
} else {
assert(SearchStrVal.isUnknown());
// Conjure a symbolic value. It's the best we can do.
Expand Down Expand Up @@ -2116,6 +2121,7 @@ CStringChecker::checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) const {
CStringLengthTy Entries = state->get<CStringLength>();
if (Entries.isEmpty())
Expand Down
Expand Up @@ -51,9 +51,9 @@ void CXXSelfAssignmentChecker::checkBeginFunction(CheckerContext &C) const {
State->getSVal(SVB.getCXXThis(MD, LCtx->getCurrentStackFrame()));
auto Param = SVB.makeLoc(State->getRegion(MD->getParamDecl(0), LCtx));
auto ParamVal = State->getSVal(Param);
ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal);
ProgramStateRef SelfAssignState = State->bindLoc(Param, ThisVal, LCtx);
C.addTransition(SelfAssignState);
ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal);
ProgramStateRef NonSelfAssignState = State->bindLoc(Param, ParamVal, LCtx);
C.addTransition(NonSelfAssignState);
}

Expand Down
14 changes: 3 additions & 11 deletions clang/lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
Expand Up @@ -231,14 +231,6 @@ class CheckerDocumentation : public Checker< check::PreStmt<ReturnStmt>,
/// check::LiveSymbols
void checkLiveSymbols(ProgramStateRef State, SymbolReaper &SR) const {}

/// \brief Called to determine if the checker currently needs to know if when
/// contents of any regions change.
///
/// Since it is not necessarily cheap to compute which regions are being
/// changed, this allows the analyzer core to skip the more expensive
/// #checkRegionChanges when no checkers are tracking any state.
bool wantsRegionChangeUpdate(ProgramStateRef St) const { return true; }

/// \brief Called when the contents of one or more regions change.
///
/// This can occur in many different ways: an explicit bind, a blanket
Expand All @@ -255,18 +247,18 @@ class CheckerDocumentation : public Checker< check::PreStmt<ReturnStmt>,
/// by this change. For a simple bind, this list will be the same as
/// \p ExplicitRegions, since a bind does not affect the contents of
/// anything accessible through the base region.
/// \param LCtx LocationContext that is useful for getting various contextual
/// info, like callstack, CFG etc.
/// \param Call The opaque call triggering this invalidation. Will be 0 if the
/// change was not triggered by a call.
///
/// Note that this callback will not be invoked unless
/// #wantsRegionChangeUpdate returns \c true.
///
/// check::RegionChanges
ProgramStateRef
checkRegionChanges(ProgramStateRef State,
const InvalidatedSymbols *Invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) const {
return State;
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
Expand Up @@ -1154,7 +1154,7 @@ ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
State = State->BindExpr(CE, C.getLocationContext(), RetVal);

// Fill the region with the initialization value.
State = State->bindDefault(RetVal, Init);
State = State->bindDefault(RetVal, Init, LCtx);

// Set the region's extent equal to the Size parameter.
const SymbolicRegion *R =
Expand Down
12 changes: 7 additions & 5 deletions clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
Expand Up @@ -2661,6 +2661,7 @@ class RetainCountChecker
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext* LCtx,
const CallEvent *Call) const;

void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const;
Expand Down Expand Up @@ -3647,7 +3648,7 @@ void RetainCountChecker::checkBind(SVal loc, SVal val, const Stmt *S,
// same state.
SVal StoredVal = state->getSVal(regionLoc->getRegion());
if (StoredVal != val)
escapes = (state == (state->bindLoc(*regionLoc, val)));
escapes = (state == (state->bindLoc(*regionLoc, val, C.getLocationContext())));
}
if (!escapes) {
// Case 4: We do not currently model what happens when a symbol is
Expand Down Expand Up @@ -3714,10 +3715,11 @@ ProgramStateRef RetainCountChecker::evalAssume(ProgramStateRef state,

ProgramStateRef
RetainCountChecker::checkRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call) const {
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) const {
if (!invalidated)
return state;

Expand Down
12 changes: 7 additions & 5 deletions clang/lib/StaticAnalyzer/Core/CheckerManager.cpp
Expand Up @@ -521,17 +521,19 @@ void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
/// \brief Run checkers for region changes.
ProgramStateRef
CheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const CallEvent *Call) {
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> ExplicitRegions,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) {
for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
// If any checker declares the state infeasible (or if it starts that way),
// bail out.
if (!state)
return nullptr;
state = RegionChangesCheckers[i](state, invalidated,
ExplicitRegions, Regions, Call);
ExplicitRegions, Regions,
LCtx, Call);
}
return state;
}
Expand Down
22 changes: 13 additions & 9 deletions clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
Expand Up @@ -254,7 +254,7 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
break;
case SubobjectAdjustment::MemberPointerAdjustment:
// FIXME: Unimplemented.
State->bindDefault(Reg, UnknownVal());
State->bindDefault(Reg, UnknownVal(), LC);
return State;
}
}
Expand All @@ -265,7 +265,7 @@ ExprEngine::createTemporaryRegionIfNeeded(ProgramStateRef State,
currBldrCtx->blockCount());
// Bind the value of the expression to the sub-object region, and then bind
// the sub-object region to our expression.
State = State->bindLoc(Reg, V);
State = State->bindLoc(Reg, V, LC);
State = State->BindExpr(Result, LC, Reg);
return State;
}
Expand All @@ -286,9 +286,11 @@ ExprEngine::processRegionChanges(ProgramStateRef state,
const InvalidatedSymbols *invalidated,
ArrayRef<const MemRegion *> Explicits,
ArrayRef<const MemRegion *> Regions,
const LocationContext *LCtx,
const CallEvent *Call) {
return getCheckerManager().runCheckersForRegionChanges(state, invalidated,
Explicits, Regions, Call);
Explicits, Regions,
LCtx, Call);
}

void ExprEngine::printState(raw_ostream &Out, ProgramStateRef State,
Expand Down Expand Up @@ -2165,7 +2167,9 @@ class CollectReachableSymbolsCallback final : public SymbolVisitor {
// (3) We are binding to a MemRegion with stack storage that the store
// does not understand.
ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State,
SVal Loc, SVal Val) {
SVal Loc,
SVal Val,
const LocationContext *LCtx) {
// Are we storing to something that causes the value to "escape"?
bool escapes = true;

Expand All @@ -2181,7 +2185,7 @@ ProgramStateRef ExprEngine::processPointerEscapedOnBind(ProgramStateRef State,
// same state.
SVal StoredVal = State->getSVal(regionLoc->getRegion());
if (StoredVal != Val)
escapes = (State == (State->bindLoc(*regionLoc, Val)));
escapes = (State == (State->bindLoc(*regionLoc, Val, LCtx)));
}
}

Expand Down Expand Up @@ -2278,7 +2282,7 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
const ProgramPoint L = PostStore(StoreE, LC, /*Loc*/nullptr,
/*tag*/nullptr);
ProgramStateRef state = Pred->getState();
state = processPointerEscapedOnBind(state, location, Val);
state = processPointerEscapedOnBind(state, location, Val, LC);
Bldr.generateNode(L, state, Pred);
return;
}
Expand All @@ -2288,13 +2292,13 @@ void ExprEngine::evalBind(ExplodedNodeSet &Dst, const Stmt *StoreE,
ExplodedNode *PredI = *I;
ProgramStateRef state = PredI->getState();

state = processPointerEscapedOnBind(state, location, Val);
state = processPointerEscapedOnBind(state, location, Val, LC);

// When binding the value, pass on the hint that this is a initialization.
// For initializations, we do not need to inform clients of region
// changes.
state = state->bindLoc(location.castAs<Loc>(),
Val, /* notifyChanges = */ !atDeclInit);
Val, LC, /* notifyChanges = */ !atDeclInit);

const MemRegion *LocReg = nullptr;
if (Optional<loc::MemRegionVal> LocRegVal =
Expand Down Expand Up @@ -2520,7 +2524,7 @@ void ExprEngine::VisitGCCAsmStmt(const GCCAsmStmt *A, ExplodedNode *Pred,
assert (!X.getAs<NonLoc>()); // Should be an Lval, or unknown, undef.

if (Optional<Loc> LV = X.getAs<Loc>())
state = state->bindLoc(*LV, UnknownVal());
state = state->bindLoc(*LV, UnknownVal(), Pred->getLocationContext());
}

Bldr.generateNode(A, Pred, state);
Expand Down
7 changes: 4 additions & 3 deletions clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
Expand Up @@ -227,12 +227,13 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,

if (capturedR != originalR) {
SVal originalV;
const LocationContext *LCtx = Pred->getLocationContext();
if (copyExpr) {
originalV = State->getSVal(copyExpr, Pred->getLocationContext());
originalV = State->getSVal(copyExpr, LCtx);
} else {
originalV = State->getSVal(loc::MemRegionVal(originalR));
}
State = State->bindLoc(loc::MemRegionVal(capturedR), originalV);
State = State->bindLoc(loc::MemRegionVal(capturedR), originalV, LCtx);
}
}
}
Expand Down Expand Up @@ -534,7 +535,7 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL,
} else {
assert(isa<InitListExpr>(Init));
Loc CLLoc = State->getLValue(CL, LCtx);
State = State->bindLoc(CLLoc, V);
State = State->bindLoc(CLLoc, V, LCtx);

if (CL->isGLValue())
V = CLLoc;
Expand Down
6 changes: 3 additions & 3 deletions clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
Expand Up @@ -317,7 +317,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
// actually make things worse. Placement new makes this tricky as well,
// since it's then possible to be initializing one part of a multi-
// dimensional array.
State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal);
State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal, LCtx);
Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
ProgramPoint::PreStmtKind);
}
Expand Down Expand Up @@ -572,7 +572,7 @@ void ExprEngine::VisitCXXCatchStmt(const CXXCatchStmt *CS,
SVal V = svalBuilder.conjureSymbolVal(CS, LCtx, VD->getType(),
currBldrCtx->blockCount());
ProgramStateRef state = Pred->getState();
state = state->bindLoc(state->getLValue(VD, LCtx), V);
state = state->bindLoc(state->getLValue(VD, LCtx), V, LCtx);

StmtNodeBuilder Bldr(Pred, Dst, *currBldrCtx);
Bldr.generateNode(CS, Pred, state);
Expand Down Expand Up @@ -627,7 +627,7 @@ void ExprEngine::VisitLambdaExpr(const LambdaExpr *LE, ExplodedNode *Pred,
InitVal = State->getSVal(SizeExpr, LocCtxt);
}

State = State->bindLoc(FieldLoc, InitVal);
State = State->bindLoc(FieldLoc, InitVal, LocCtxt);
}

// Decay the Loc into an RValue, because there might be a
Expand Down

0 comments on commit b570195

Please sign in to comment.