forked from OSchip/llvm-project
[analyzer] [RetainSummaryManager] [NFC] Split one function into two, as it's really doing two things
Differential Revision: https://reviews.llvm.org/D57201 llvm-svn: 352533
This commit is contained in:
parent
2e46667853
commit
b0fc58b57c
|
@ -693,10 +693,22 @@ private:
|
||||||
void updateSummaryFromAnnotations(const RetainSummary *&Summ,
|
void updateSummaryFromAnnotations(const RetainSummary *&Summ,
|
||||||
const FunctionDecl *FD);
|
const FunctionDecl *FD);
|
||||||
|
|
||||||
void updateSummaryForCall(const RetainSummary *&Summ,
|
const RetainSummary *updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
|
||||||
AnyCall C,
|
AnyCall &C);
|
||||||
bool HasNonZeroCallbackArg,
|
|
||||||
bool IsReceiverUnconsumedSelf);
|
/// Special case '[super init];' and '[self init];'
|
||||||
|
///
|
||||||
|
/// Even though calling '[super init]' without assigning the result to self
|
||||||
|
/// and checking if the parent returns 'nil' is a bad pattern, it is common.
|
||||||
|
/// Additionally, our Self Init checker already warns about it. To avoid
|
||||||
|
/// overwhelming the user with messages from both checkers, we model the case
|
||||||
|
/// of '[super init]' in cases when it is not consumed by another expression
|
||||||
|
/// as if the call preserves the value of 'self'; essentially, assuming it can
|
||||||
|
/// never fail and return 'nil'.
|
||||||
|
/// Note, we don't want to just stop tracking the value since we want the
|
||||||
|
/// RetainCount checker to report leaks and use-after-free if SelfInit checker
|
||||||
|
/// is turned off.
|
||||||
|
void updateSummaryForReceiverUnconsumedSelf(const RetainSummary *&S);
|
||||||
|
|
||||||
/// Determine whether a declaration {@code D} of correspondent type (return
|
/// Determine whether a declaration {@code D} of correspondent type (return
|
||||||
/// type for functions/methods) {@code QT} has any of the given attributes,
|
/// type for functions/methods) {@code QT} has any of the given attributes,
|
||||||
|
|
|
@ -557,64 +557,47 @@ static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
|
||||||
llvm_unreachable("Unknown ArgEffect kind");
|
llvm_unreachable("Unknown ArgEffect kind");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
|
const RetainSummary *
|
||||||
AnyCall C,
|
RetainSummaryManager::updateSummaryForNonZeroCallbackArg(const RetainSummary *S,
|
||||||
bool HasNonZeroCallbackArg,
|
AnyCall &C) {
|
||||||
bool IsReceiverUnconsumedSelf) {
|
ArgEffect RecEffect = getStopTrackingHardEquivalent(S->getReceiverEffect());
|
||||||
|
ArgEffect DefEffect = getStopTrackingHardEquivalent(S->getDefaultArgEffect());
|
||||||
|
|
||||||
if (HasNonZeroCallbackArg) {
|
ArgEffects ScratchArgs(AF.getEmptyMap());
|
||||||
ArgEffect RecEffect =
|
ArgEffects CustomArgEffects = S->getArgEffects();
|
||||||
getStopTrackingHardEquivalent(S->getReceiverEffect());
|
for (ArgEffects::iterator I = CustomArgEffects.begin(),
|
||||||
ArgEffect DefEffect =
|
E = CustomArgEffects.end();
|
||||||
getStopTrackingHardEquivalent(S->getDefaultArgEffect());
|
I != E; ++I) {
|
||||||
|
ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
|
||||||
ArgEffects ScratchArgs(AF.getEmptyMap());
|
if (Translated.getKind() != DefEffect.getKind())
|
||||||
ArgEffects CustomArgEffects = S->getArgEffects();
|
ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
|
||||||
for (ArgEffects::iterator I = CustomArgEffects.begin(),
|
|
||||||
E = CustomArgEffects.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
|
|
||||||
if (Translated.getKind() != DefEffect.getKind())
|
|
||||||
ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
|
|
||||||
}
|
|
||||||
|
|
||||||
RetEffect RE = RetEffect::MakeNoRetHard();
|
|
||||||
|
|
||||||
// Special cases where the callback argument CANNOT free the return value.
|
|
||||||
// This can generally only happen if we know that the callback will only be
|
|
||||||
// called when the return value is already being deallocated.
|
|
||||||
if (C.getKind() == AnyCall::Function) {
|
|
||||||
if (const IdentifierInfo *Name = C.getIdentifier()) {
|
|
||||||
// When the CGBitmapContext is deallocated, the callback here will free
|
|
||||||
// the associated data buffer.
|
|
||||||
// The callback in dispatch_data_create frees the buffer, but not
|
|
||||||
// the data object.
|
|
||||||
if (Name->isStr("CGBitmapContextCreateWithData") ||
|
|
||||||
Name->isStr("dispatch_data_create"))
|
|
||||||
RE = S->getRetEffect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
S = getPersistentSummary(RE, ScratchArgs, RecEffect, DefEffect);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special case '[super init];' and '[self init];'
|
RetEffect RE = RetEffect::MakeNoRetHard();
|
||||||
//
|
|
||||||
// Even though calling '[super init]' without assigning the result to self
|
// Special cases where the callback argument CANNOT free the return value.
|
||||||
// and checking if the parent returns 'nil' is a bad pattern, it is common.
|
// This can generally only happen if we know that the callback will only be
|
||||||
// Additionally, our Self Init checker already warns about it. To avoid
|
// called when the return value is already being deallocated.
|
||||||
// overwhelming the user with messages from both checkers, we model the case
|
if (const IdentifierInfo *Name = C.getIdentifier()) {
|
||||||
// of '[super init]' in cases when it is not consumed by another expression
|
// When the CGBitmapContext is deallocated, the callback here will free
|
||||||
// as if the call preserves the value of 'self'; essentially, assuming it can
|
// the associated data buffer.
|
||||||
// never fail and return 'nil'.
|
// The callback in dispatch_data_create frees the buffer, but not
|
||||||
// Note, we don't want to just stop tracking the value since we want the
|
// the data object.
|
||||||
// RetainCount checker to report leaks and use-after-free if SelfInit checker
|
if (Name->isStr("CGBitmapContextCreateWithData") ||
|
||||||
// is turned off.
|
Name->isStr("dispatch_data_create"))
|
||||||
if (IsReceiverUnconsumedSelf) {
|
RE = S->getRetEffect();
|
||||||
RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
|
|
||||||
ModifiableSummaryTemplate->setReceiverEffect(ArgEffect(DoNothing));
|
|
||||||
ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return getPersistentSummary(RE, ScratchArgs, RecEffect, DefEffect);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RetainSummaryManager::updateSummaryForReceiverUnconsumedSelf(
|
||||||
|
const RetainSummary *&S) {
|
||||||
|
|
||||||
|
RetainSummaryTemplate Template(S, *this);
|
||||||
|
|
||||||
|
Template->setReceiverEffect(ArgEffect(DoNothing));
|
||||||
|
Template->setRetEffect(RetEffect::MakeNoRet());
|
||||||
}
|
}
|
||||||
|
|
||||||
const RetainSummary *
|
const RetainSummary *
|
||||||
|
@ -647,8 +630,11 @@ RetainSummaryManager::getSummary(AnyCall C,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateSummaryForCall(Summ, C, HasNonZeroCallbackArg,
|
if (HasNonZeroCallbackArg)
|
||||||
IsReceiverUnconsumedSelf);
|
Summ = updateSummaryForNonZeroCallbackArg(Summ, C);
|
||||||
|
|
||||||
|
if (IsReceiverUnconsumedSelf)
|
||||||
|
updateSummaryForReceiverUnconsumedSelf(Summ);
|
||||||
|
|
||||||
assert(Summ && "Unknown call type?");
|
assert(Summ && "Unknown call type?");
|
||||||
return Summ;
|
return Summ;
|
||||||
|
|
Loading…
Reference in New Issue