From: Ted Kremenek Date: Thu, 1 May 2008 21:31:50 +0000 (+0000) Subject: Correctly invalidate reference count state when passing objects by reference in messa... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9040c65860932fc8eded28e1558394d66d44b4cf;p=clang Correctly invalidate reference count state when passing objects by reference in message expressions we don't understand. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@50541 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 5400904013..98287921d3 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -294,7 +294,7 @@ CFRefSummary* CFRefSummaryManager::getCFSummary(FunctionDecl* FD, if (strcmp(FName, "Release") == 0) return getUnaryCFSummary(FT, cfrelease); - + if (strcmp(FName, "MakeCollectable") == 0) return getUnaryCFSummary(FT, cfmakecollectable); @@ -962,8 +962,43 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst, ObjCMessageExpr* ME, ExplodedNode* Pred) { - if (EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred)) - GRSimpleVals::EvalObjCMessageExpr(Dst, Eng, Builder, ME, Pred); + if (!EvalObjCMessageExprAux(Dst, Eng, Builder, ME, Pred)) + return; + + // The basic transfer function logic for message expressions does nothing. + // We just invalidate all arguments passed in by references. + + ValueStateManager& StateMgr = Eng.getStateManager(); + ValueState* St = Builder.GetState(Pred); + RefBindings B = GetRefBindings(*St); + + for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end(); + I != E; ++I) { + + RVal V = StateMgr.GetRVal(St, *I); + + if (isa(V)) { + + LVal lv = cast(V); + + // Did the lval bind to a symbol? + RVal X = StateMgr.GetRVal(St, lv); + + if (isa(X)) { + SymbolID Sym = cast(V).getSymbol(); + B = Remove(B, Sym); + + // Create a new state with the updated bindings. + ValueState StVals = *St; + SetRefBindings(StVals, B); + St = StateMgr.getPersistentState(StVals); + } + + St = StateMgr.SetRVal(St, cast(V), UnknownVal()); + } + } + + Builder.MakeNode(Dst, ME, Pred, St); } bool CFRefCount::EvalObjCMessageExprAux(ExplodedNodeSet& Dst, diff --git a/lib/Analysis/ValueState.cpp b/lib/Analysis/ValueState.cpp index 19ff06f004..96b94ea8cf 100644 --- a/lib/Analysis/ValueState.cpp +++ b/lib/Analysis/ValueState.cpp @@ -203,6 +203,12 @@ RVal ValueStateManager::GetRVal(ValueState* St, LVal LV, QualType T) { return UnknownVal(); } + + case lval::ConcreteIntKind: + // Some clients may call GetRVal with such an option simply because + // they are doing a quick scan through their LVals (potentially to + // invalidate their bindings). Just return Undefined. + return UndefinedVal(); case lval::ArrayOffsetKind: case lval::FieldOffsetKind: