forked from OSchip/llvm-project
Stop tracking retain count of OSObject after escape to void * / other primitive types
Escaping to void * / uint64_t / others non-OSObject * should stop tracking, as such functions can have heterogeneous semantics depending on context, and can not always be annotated. rdar://46439133 Differential Revision: https://reviews.llvm.org/D55465 llvm-svn: 348675
This commit is contained in:
parent
4ce6d4611b
commit
041c9fa8ba
|
@ -574,6 +574,25 @@ static ProgramStateRef updateOutParameter(ProgramStateRef State,
|
||||||
return State;
|
return State;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isPointerToObject(QualType QT) {
|
||||||
|
QualType PT = QT->getPointeeType();
|
||||||
|
if (!PT.isNull())
|
||||||
|
if (PT->getAsCXXRecordDecl())
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether the tracked value should be escaped on a given call.
|
||||||
|
/// OSObjects are escaped when passed to void * / etc.
|
||||||
|
static bool shouldEscapeArgumentOnCall(const CallEvent &CE, unsigned ArgIdx,
|
||||||
|
const RefVal *TrackedValue) {
|
||||||
|
if (TrackedValue->getObjKind() != RetEffect::OS)
|
||||||
|
return false;
|
||||||
|
if (ArgIdx >= CE.parameters().size())
|
||||||
|
return false;
|
||||||
|
return !isPointerToObject(CE.parameters()[ArgIdx]->getType());
|
||||||
|
}
|
||||||
|
|
||||||
void RetainCountChecker::checkSummary(const RetainSummary &Summ,
|
void RetainCountChecker::checkSummary(const RetainSummary &Summ,
|
||||||
const CallEvent &CallOrMsg,
|
const CallEvent &CallOrMsg,
|
||||||
CheckerContext &C) const {
|
CheckerContext &C) const {
|
||||||
|
@ -592,6 +611,10 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
|
||||||
state = updateOutParameter(state, V, Effect);
|
state = updateOutParameter(state, V, Effect);
|
||||||
} else if (SymbolRef Sym = V.getAsLocSymbol()) {
|
} else if (SymbolRef Sym = V.getAsLocSymbol()) {
|
||||||
if (const RefVal *T = getRefBinding(state, Sym)) {
|
if (const RefVal *T = getRefBinding(state, Sym)) {
|
||||||
|
|
||||||
|
if (shouldEscapeArgumentOnCall(CallOrMsg, idx, T))
|
||||||
|
Effect = StopTrackingHard;
|
||||||
|
|
||||||
state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
|
state = updateSymbol(state, Sym, *T, Effect, hasErr, C);
|
||||||
if (hasErr) {
|
if (hasErr) {
|
||||||
ErrorRange = CallOrMsg.getArgSourceRange(idx);
|
ErrorRange = CallOrMsg.getArgSourceRange(idx);
|
||||||
|
|
|
@ -89,6 +89,13 @@ struct OSMetaClassBase {
|
||||||
static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta);
|
static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void escape(void *);
|
||||||
|
|
||||||
|
void test_escaping_into_voidstar() {
|
||||||
|
OSObject *obj = new OSObject;
|
||||||
|
escape(obj);
|
||||||
|
}
|
||||||
|
|
||||||
void test_no_infinite_check_recursion(MyArray *arr) {
|
void test_no_infinite_check_recursion(MyArray *arr) {
|
||||||
OSObject *input = new OSObject;
|
OSObject *input = new OSObject;
|
||||||
OSObject *o = arr->generateObject(input);
|
OSObject *o = arr->generateObject(input);
|
||||||
|
|
Loading…
Reference in New Issue