ProgramStateRef ObjCLoopChecker::checkPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind) const { SymbolRef ImmutableReceiver = getMethodReceiverIfKnownImmutable(Call); // Remove the invalidated symbols form the collection count map. for (InvalidatedSymbols::const_iterator I = Escaped.begin(), E = Escaped.end(); I != E; ++I) { SymbolRef Sym = *I; // Don't invalidate this symbol's count if we know the method being called // is declared on an immutable class. This isn't completely correct if the // receiver is also passed as an argument, but in most uses of NSArray, // NSDictionary, etc. this isn't likely to happen in a dangerous way. if (Sym == ImmutableReceiver) continue; // The symbol escaped. Pessimistically, assume that the count could have // changed. State = State->remove<ContainerCountMap>(Sym); State = State->remove<ContainerNonEmptyMap>(Sym); } return State; }
ProgramStateRef ObjCContainersChecker::checkPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind) const { for (InvalidatedSymbols::const_iterator I = Escaped.begin(), E = Escaped.end(); I != E; ++I) { SymbolRef Sym = *I; // When a symbol for a mutable array escapes, we can't reason precisely // about its size any more -- so remove it from the map. // Note that we aren't notified here when a CFMutableArrayRef escapes as a // CFArrayRef. This is because CFArrayRef is typedef'd as a pointer to a // const-qualified type. State = State->remove<ArraySizeMap>(Sym); } return State; }
ProgramStateRef ObjCLoopChecker::checkPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind) const { // TODO: If we know that the call cannot change the collection count, there // is nothing to do, just return. // Remove the invalidated symbols form the collection count map. for (InvalidatedSymbols::const_iterator I = Escaped.begin(), E = Escaped.end(); I != E; ++I) { SymbolRef Sym = *I; // The symbol escaped. Pessimistically, assume that the count could have // changed. State = State->remove<ContainerCountMap>(Sym); } return State; }
// If the pointer we are tracking escaped, do not track the symbol as // we cannot reason about it anymore. ProgramStateRef SimpleStreamChecker::checkPointerEscape(ProgramStateRef State, const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind) const { // If we know that the call cannot close a file, there is nothing to do. if (Kind == PSK_DirectEscapeOnCall && guaranteedNotToCloseFile(*Call)) { return State; } for (InvalidatedSymbols::const_iterator I = Escaped.begin(), E = Escaped.end(); I != E; ++I) { SymbolRef Sym = *I; // The symbol escaped. Optimistically, assume that the corresponding file // handle will be closed somewhere else. State = State->remove<StreamMap>(Sym); } return State; }