diff options
Diffstat (limited to 'lib/Analysis')
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 67 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 18 | ||||
-rw-r--r-- | lib/Analysis/GRTransferFuncs.cpp | 20 |
3 files changed, 87 insertions, 18 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 332533557f..94a502a9b6 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -455,14 +455,9 @@ namespace { } // end anonymous namespace //===----------------------------------------------------------------------===// -// Transfer functions. +// Reference-counting logic (typestate + counts). //===----------------------------------------------------------------------===// -static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) { - IdentifierInfo* II = &Ctx.Idents.get(name); - return Ctx.Selectors.getSelector(0, &II); -} - namespace { class VISIBILITY_HIDDEN RefVal { @@ -543,6 +538,15 @@ void RefVal::print(std::ostream& Out) const { } } +//===----------------------------------------------------------------------===// +// Transfer functions. +//===----------------------------------------------------------------------===// + +static inline Selector GetUnarySelector(const char* name, ASTContext& Ctx) { + IdentifierInfo* II = &Ctx.Idents.get(name); + return Ctx.Selectors.getSelector(0, &II); +} + class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals { // Type definitions. @@ -597,6 +601,7 @@ class VISIBILITY_HIDDEN CFRefCount : public GRSimpleVals { RefVal::Kind hasErr); public: + CFRefCount(ASTContext& Ctx) : Summaries(Ctx), RetainSelector(GetUnarySelector("retain", Ctx)), @@ -630,6 +635,13 @@ public: ObjCMessageExpr* ME, ExplodedNode<ValueState>* Pred); + // Stores. + + virtual void EvalStore(ExplodedNodeSet<ValueState>& Dst, + GRExprEngine& Engine, + GRStmtNodeBuilder<ValueState>& Builder, + Expr* E, ExplodedNode<ValueState>* Pred, + ValueState* St, RVal TargetLV, RVal Val); // End-of-path. virtual void EvalEndPath(GRExprEngine& Engine, @@ -916,6 +928,49 @@ bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet<ValueState>& Dst, return false; } +// Stores. + +void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst, + GRExprEngine& Eng, + GRStmtNodeBuilder<ValueState>& Builder, + Expr* E, ExplodedNode<ValueState>* Pred, + ValueState* St, RVal TargetLV, RVal Val) { + + // Check if we have a binding for "Val" and if we are storing it to something + // we don't understand or otherwise the value "escapes" the function. + + if (!isa<lval::SymbolVal>(Val)) + return; + + // Are we storing to something that causes the value to "escape"? + + bool escapes = false; + + if (!isa<lval::DeclVal>(TargetLV)) + escapes = true; + else + escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage(); + + if (!escapes) + return; + + SymbolID Sym = cast<lval::SymbolVal>(Val).getSymbol(); + RefBindings B = GetRefBindings(*St); + RefBindings::TreeTy* T = B.SlimFind(Sym); + + if (!T) + return; + + // Nuke the binding. + + ValueState StImpl = *St; + StImpl.CheckerState = RefBFactory.Remove(B, Sym).getRoot(); + St = Eng.getStateManager().getPersistentState(StImpl); + + // Hand of the remaining logic to the parent implementation. + GRSimpleVals::EvalStore(Dst, Eng, Builder, E, Pred, St, TargetLV, Val); +} + // End-of-path. void CFRefCount::EvalEndPath(GRExprEngine& Engine, diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 72bae32231..53567c184e 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -709,20 +709,23 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst){ } void GRExprEngine::VisitStore(NodeSet& Dst, Expr* E, NodeTy* Pred, - ValueState* St, LVal TargetLV, RVal Val) { + ValueState* St, RVal TargetLV, RVal Val) { assert (Builder && "GRStmtNodeBuilder must be defined."); unsigned size = Dst.size(); SaveAndRestore<bool> OldSink(Builder->BuildSinks); + assert (!TargetLV.isUndef()); + EvalStore(Dst, E, Pred, St, TargetLV, Val); // Handle the case where no nodes where generated. Auto-generate that // contains the updated state if we aren't generating sinks. if (!Builder->BuildSinks && Dst.size() == size) - MakeNode(Dst, E, Pred, SetRVal(St, TargetLV, Val)); + TF->GRTransferFuncs::EvalStore(Dst, *this, *Builder, E, Pred, St, + TargetLV, Val); } //===----------------------------------------------------------------------===// @@ -1643,21 +1646,12 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, : cast<RVal>(nonlval::SymbolVal(Sym)); } - // Even if the LHS evaluates to an unknown L-Value, the entire - // expression still evaluates to the RHS. - - if (LeftV.isUnknown()) { - St = SetRVal(St, B, RightV); - break; - } - // Simulate the effects of a "store": bind the value of the RHS // to the L-Value represented by the LHS. VisitStore(Dst, B, N2, SetRVal(St, B, RightV), - cast<LVal>(LeftV), RightV); + LeftV, RightV); -// St = SetRVal(SetRVal(St, B, RightV), cast<LVal>(LeftV), RightV); continue; } diff --git a/lib/Analysis/GRTransferFuncs.cpp b/lib/Analysis/GRTransferFuncs.cpp index d11d18d5cb..9c96e3d981 100644 --- a/lib/Analysis/GRTransferFuncs.cpp +++ b/lib/Analysis/GRTransferFuncs.cpp @@ -13,7 +13,27 @@ //===----------------------------------------------------------------------===// #include "clang/Analysis/PathSensitive/GRTransferFuncs.h" +#include "clang/Analysis/PathSensitive/GRExprEngine.h" using namespace clang; void GRTransferFuncs::RegisterChecks(GRExprEngine& Eng) {} + +void GRTransferFuncs::EvalStore(ExplodedNodeSet<ValueState>& Dst, + GRExprEngine& Eng, + GRStmtNodeBuilder<ValueState>& Builder, + Expr* E, ExplodedNode<ValueState>* Pred, + ValueState* St, RVal TargetLV, RVal Val) { + + // This code basically matches the "safety-net" logic of GRExprEngine: + // bind Val to TargetLV, and create a new node. We replicate it here + // because subclasses of GRTransferFuncs may wish to call it. + + assert (!TargetLV.isUndef()); + + if (TargetLV.isUnknown()) + Builder.MakeNode(Dst, E, Pred, St); + else + Builder.MakeNode(Dst, E, Pred, + Eng.getStateManager().SetRVal(St, cast<LVal>(TargetLV), Val)); +} |