forked from OSchip/llvm-project
[analyzer] [ARCMT] [NFC] Unify entry point into RetainSummaryManager
Just use one single entry point, since we have AnyCall utility now. Differential Revision: https://reviews.llvm.org/D57346 llvm-svn: 352532
This commit is contained in:
parent
38bc347ff5
commit
2e46667853
|
@ -203,40 +203,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Encapsulates the retain count semantics on the arguments, return value,
|
|
||||||
/// and receiver (if any) of a function/method call.
|
|
||||||
///
|
|
||||||
/// Note that construction of these objects is not highly efficient. That
|
|
||||||
/// is okay for clients where creating these objects isn't really a bottleneck.
|
|
||||||
/// The purpose of the API is to provide something simple. The actual
|
|
||||||
/// static analyzer checker that implements retain/release typestate
|
|
||||||
/// tracking uses something more efficient.
|
|
||||||
class CallEffects {
|
|
||||||
llvm::SmallVector<ArgEffect, 10> Args;
|
|
||||||
RetEffect Ret;
|
|
||||||
ArgEffect Receiver;
|
|
||||||
|
|
||||||
CallEffects(const RetEffect &R,
|
|
||||||
ArgEffect Receiver = ArgEffect(DoNothing, ObjKind::AnyObj))
|
|
||||||
: Ret(R), Receiver(Receiver) {}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Returns the argument effects for a call.
|
|
||||||
ArrayRef<ArgEffect> getArgs() const { return Args; }
|
|
||||||
|
|
||||||
/// Returns the effects on the receiver.
|
|
||||||
ArgEffect getReceiver() const { return Receiver; }
|
|
||||||
|
|
||||||
/// Returns the effect on the return value.
|
|
||||||
RetEffect getReturnValue() const { return Ret; }
|
|
||||||
|
|
||||||
/// Return the CallEfect for a given Objective-C method.
|
|
||||||
static CallEffects getEffect(const ObjCMethodDecl *MD);
|
|
||||||
|
|
||||||
/// Return the CallEfect for a given C/C++ function.
|
|
||||||
static CallEffects getEffect(const FunctionDecl *FD);
|
|
||||||
};
|
|
||||||
|
|
||||||
/// A key identifying a summary.
|
/// A key identifying a summary.
|
||||||
class ObjCSummaryKey {
|
class ObjCSummaryKey {
|
||||||
IdentifierInfo* II;
|
IdentifierInfo* II;
|
||||||
|
@ -690,9 +656,13 @@ public:
|
||||||
bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);
|
bool isTrustedReferenceCountImplementation(const FunctionDecl *FD);
|
||||||
|
|
||||||
const RetainSummary *getSummary(AnyCall C,
|
const RetainSummary *getSummary(AnyCall C,
|
||||||
bool HasNonZeroCallbackArg,
|
bool HasNonZeroCallbackArg=false,
|
||||||
bool IsReceiverUnconsumedSelf,
|
bool IsReceiverUnconsumedSelf=false,
|
||||||
QualType ReceiverType=QualType());
|
QualType ReceiverType={});
|
||||||
|
|
||||||
|
RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
/// getMethodSummary - This version of getMethodSummary is used to query
|
/// getMethodSummary - This version of getMethodSummary is used to query
|
||||||
/// the summary for the current method being analyzed.
|
/// the summary for the current method being analyzed.
|
||||||
|
@ -700,9 +670,6 @@ public:
|
||||||
|
|
||||||
const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
|
const RetainSummary *getFunctionSummary(const FunctionDecl *FD);
|
||||||
|
|
||||||
RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
|
const RetainSummary *getMethodSummary(Selector S, const ObjCInterfaceDecl *ID,
|
||||||
const ObjCMethodDecl *MD,
|
const ObjCMethodDecl *MD,
|
||||||
QualType RetTy,
|
QualType RetTy,
|
||||||
|
|
|
@ -64,9 +64,11 @@ class ObjCMigrateASTConsumer : public ASTConsumer {
|
||||||
ObjCInstanceTypeFamily OIT_Family = OIT_None);
|
ObjCInstanceTypeFamily OIT_Family = OIT_None);
|
||||||
|
|
||||||
void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
|
void migrateCFAnnotation(ASTContext &Ctx, const Decl *Decl);
|
||||||
void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
|
void AddCFAnnotations(ASTContext &Ctx,
|
||||||
|
const RetainSummary *RS,
|
||||||
const FunctionDecl *FuncDecl, bool ResultAnnotated);
|
const FunctionDecl *FuncDecl, bool ResultAnnotated);
|
||||||
void AddCFAnnotations(ASTContext &Ctx, const CallEffects &CE,
|
void AddCFAnnotations(ASTContext &Ctx,
|
||||||
|
const RetainSummary *RS,
|
||||||
const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);
|
const ObjCMethodDecl *MethodDecl, bool ResultAnnotated);
|
||||||
|
|
||||||
void AnnotateImplicitBridging(ASTContext &Ctx);
|
void AnnotateImplicitBridging(ASTContext &Ctx);
|
||||||
|
@ -84,6 +86,8 @@ class ObjCMigrateASTConsumer : public ASTConsumer {
|
||||||
|
|
||||||
bool InsertFoundation(ASTContext &Ctx, SourceLocation Loc);
|
bool InsertFoundation(ASTContext &Ctx, SourceLocation Loc);
|
||||||
|
|
||||||
|
std::unique_ptr<RetainSummaryManager> Summaries;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::string MigrateDir;
|
std::string MigrateDir;
|
||||||
unsigned ASTMigrateActions;
|
unsigned ASTMigrateActions;
|
||||||
|
@ -102,6 +106,14 @@ public:
|
||||||
llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates;
|
llvm::SmallVector<const Decl *, 8> CFFunctionIBCandidates;
|
||||||
llvm::StringSet<> WhiteListFilenames;
|
llvm::StringSet<> WhiteListFilenames;
|
||||||
|
|
||||||
|
RetainSummaryManager &getSummaryManager(ASTContext &Ctx) {
|
||||||
|
if (!Summaries)
|
||||||
|
Summaries.reset(new RetainSummaryManager(Ctx,
|
||||||
|
/*TrackNSCFObjects=*/true,
|
||||||
|
/*TrackOSObjects=*/false));
|
||||||
|
return *Summaries;
|
||||||
|
}
|
||||||
|
|
||||||
ObjCMigrateASTConsumer(StringRef migrateDir,
|
ObjCMigrateASTConsumer(StringRef migrateDir,
|
||||||
unsigned astMigrateActions,
|
unsigned astMigrateActions,
|
||||||
FileRemapper &remapper,
|
FileRemapper &remapper,
|
||||||
|
@ -1452,12 +1464,12 @@ void ObjCMigrateASTConsumer::migrateCFAnnotation(ASTContext &Ctx, const Decl *De
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
|
void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
|
||||||
const CallEffects &CE,
|
const RetainSummary *RS,
|
||||||
const FunctionDecl *FuncDecl,
|
const FunctionDecl *FuncDecl,
|
||||||
bool ResultAnnotated) {
|
bool ResultAnnotated) {
|
||||||
// Annotate function.
|
// Annotate function.
|
||||||
if (!ResultAnnotated) {
|
if (!ResultAnnotated) {
|
||||||
RetEffect Ret = CE.getReturnValue();
|
RetEffect Ret = RS->getRetEffect();
|
||||||
const char *AnnotationString = nullptr;
|
const char *AnnotationString = nullptr;
|
||||||
if (Ret.getObjKind() == ObjKind::CF) {
|
if (Ret.getObjKind() == ObjKind::CF) {
|
||||||
if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
|
if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
|
||||||
|
@ -1477,12 +1489,11 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
|
||||||
Editor->commit(commit);
|
Editor->commit(commit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArrayRef<ArgEffect> AEArgs = CE.getArgs();
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
|
for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
|
||||||
pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
|
pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
|
||||||
const ParmVarDecl *pd = *pi;
|
const ParmVarDecl *pd = *pi;
|
||||||
ArgEffect AE = AEArgs[i];
|
ArgEffect AE = RS->getArg(i);
|
||||||
if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::CF &&
|
if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::CF &&
|
||||||
!pd->hasAttr<CFConsumedAttr>() &&
|
!pd->hasAttr<CFConsumedAttr>() &&
|
||||||
NSAPIObj->isMacroDefined("CF_CONSUMED")) {
|
NSAPIObj->isMacroDefined("CF_CONSUMED")) {
|
||||||
|
@ -1506,7 +1517,8 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
|
||||||
if (FuncDecl->hasBody())
|
if (FuncDecl->hasBody())
|
||||||
return CF_BRIDGING_NONE;
|
return CF_BRIDGING_NONE;
|
||||||
|
|
||||||
CallEffects CE = CallEffects::getEffect(FuncDecl);
|
const RetainSummary *RS =
|
||||||
|
getSummaryManager(Ctx).getSummary(AnyCall(FuncDecl));
|
||||||
bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() ||
|
bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() ||
|
||||||
FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
|
FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
|
||||||
FuncDecl->hasAttr<NSReturnsRetainedAttr>() ||
|
FuncDecl->hasAttr<NSReturnsRetainedAttr>() ||
|
||||||
|
@ -1519,7 +1531,7 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
|
||||||
|
|
||||||
bool ReturnCFAudited = false;
|
bool ReturnCFAudited = false;
|
||||||
if (!FuncIsReturnAnnotated) {
|
if (!FuncIsReturnAnnotated) {
|
||||||
RetEffect Ret = CE.getReturnValue();
|
RetEffect Ret = RS->getRetEffect();
|
||||||
if (Ret.getObjKind() == ObjKind::CF &&
|
if (Ret.getObjKind() == ObjKind::CF &&
|
||||||
(Ret.isOwned() || Ret.notOwned()))
|
(Ret.isOwned() || Ret.notOwned()))
|
||||||
ReturnCFAudited = true;
|
ReturnCFAudited = true;
|
||||||
|
@ -1528,14 +1540,12 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point result type is audited for potential inclusion.
|
// At this point result type is audited for potential inclusion.
|
||||||
// Now, how about argument types.
|
|
||||||
ArrayRef<ArgEffect> AEArgs = CE.getArgs();
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
bool ArgCFAudited = false;
|
bool ArgCFAudited = false;
|
||||||
for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
|
for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(),
|
||||||
pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
|
pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
|
||||||
const ParmVarDecl *pd = *pi;
|
const ParmVarDecl *pd = *pi;
|
||||||
ArgEffect AE = AEArgs[i];
|
ArgEffect AE = RS->getArg(i);
|
||||||
if ((AE.getKind() == DecRef /*CFConsumed annotated*/ ||
|
if ((AE.getKind() == DecRef /*CFConsumed annotated*/ ||
|
||||||
AE.getKind() == IncRef) && AE.getObjKind() == ObjKind::CF) {
|
AE.getKind() == IncRef) && AE.getObjKind() == ObjKind::CF) {
|
||||||
if (AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>())
|
if (AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>())
|
||||||
|
@ -1545,7 +1555,7 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
|
||||||
} else {
|
} else {
|
||||||
QualType AT = pd->getType();
|
QualType AT = pd->getType();
|
||||||
if (!AuditedType(AT)) {
|
if (!AuditedType(AT)) {
|
||||||
AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
|
AddCFAnnotations(Ctx, RS, FuncDecl, FuncIsReturnAnnotated);
|
||||||
return CF_BRIDGING_NONE;
|
return CF_BRIDGING_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1567,12 +1577,12 @@ void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
|
void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
|
||||||
const CallEffects &CE,
|
const RetainSummary *RS,
|
||||||
const ObjCMethodDecl *MethodDecl,
|
const ObjCMethodDecl *MethodDecl,
|
||||||
bool ResultAnnotated) {
|
bool ResultAnnotated) {
|
||||||
// Annotate function.
|
// Annotate function.
|
||||||
if (!ResultAnnotated) {
|
if (!ResultAnnotated) {
|
||||||
RetEffect Ret = CE.getReturnValue();
|
RetEffect Ret = RS->getRetEffect();
|
||||||
const char *AnnotationString = nullptr;
|
const char *AnnotationString = nullptr;
|
||||||
if (Ret.getObjKind() == ObjKind::CF) {
|
if (Ret.getObjKind() == ObjKind::CF) {
|
||||||
if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
|
if (Ret.isOwned() && NSAPIObj->isMacroDefined("CF_RETURNS_RETAINED"))
|
||||||
|
@ -1604,12 +1614,11 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
|
||||||
Editor->commit(commit);
|
Editor->commit(commit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ArrayRef<ArgEffect> AEArgs = CE.getArgs();
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
|
for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
|
||||||
pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
|
pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
|
||||||
const ParmVarDecl *pd = *pi;
|
const ParmVarDecl *pd = *pi;
|
||||||
ArgEffect AE = AEArgs[i];
|
ArgEffect AE = RS->getArg(i);
|
||||||
if (AE.getKind() == DecRef
|
if (AE.getKind() == DecRef
|
||||||
&& AE.getObjKind() == ObjKind::CF
|
&& AE.getObjKind() == ObjKind::CF
|
||||||
&& !pd->hasAttr<CFConsumedAttr>() &&
|
&& !pd->hasAttr<CFConsumedAttr>() &&
|
||||||
|
@ -1627,7 +1636,9 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
|
||||||
if (MethodDecl->hasBody() || MethodDecl->isImplicit())
|
if (MethodDecl->hasBody() || MethodDecl->isImplicit())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CallEffects CE = CallEffects::getEffect(MethodDecl);
|
const RetainSummary *RS =
|
||||||
|
getSummaryManager(Ctx).getSummary(AnyCall(MethodDecl));
|
||||||
|
|
||||||
bool MethodIsReturnAnnotated =
|
bool MethodIsReturnAnnotated =
|
||||||
(MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
|
(MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
|
||||||
MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
|
MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
|
||||||
|
@ -1635,7 +1646,7 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
|
||||||
MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
|
MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
|
||||||
MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
|
MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
|
||||||
|
|
||||||
if (CE.getReceiver().getKind() == DecRef &&
|
if (RS->getReceiverEffect().getKind() == DecRef &&
|
||||||
!MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
|
!MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
|
||||||
MethodDecl->getMethodFamily() != OMF_init &&
|
MethodDecl->getMethodFamily() != OMF_init &&
|
||||||
MethodDecl->getMethodFamily() != OMF_release &&
|
MethodDecl->getMethodFamily() != OMF_release &&
|
||||||
|
@ -1651,27 +1662,25 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!MethodIsReturnAnnotated) {
|
if (!MethodIsReturnAnnotated) {
|
||||||
RetEffect Ret = CE.getReturnValue();
|
RetEffect Ret = RS->getRetEffect();
|
||||||
if ((Ret.getObjKind() == ObjKind::CF ||
|
if ((Ret.getObjKind() == ObjKind::CF ||
|
||||||
Ret.getObjKind() == ObjKind::ObjC) &&
|
Ret.getObjKind() == ObjKind::ObjC) &&
|
||||||
(Ret.isOwned() || Ret.notOwned())) {
|
(Ret.isOwned() || Ret.notOwned())) {
|
||||||
AddCFAnnotations(Ctx, CE, MethodDecl, false);
|
AddCFAnnotations(Ctx, RS, MethodDecl, false);
|
||||||
return;
|
return;
|
||||||
} else if (!AuditedType(MethodDecl->getReturnType()))
|
} else if (!AuditedType(MethodDecl->getReturnType()))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// At this point result type is either annotated or audited.
|
// At this point result type is either annotated or audited.
|
||||||
// Now, how about argument types.
|
|
||||||
ArrayRef<ArgEffect> AEArgs = CE.getArgs();
|
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
|
for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(),
|
||||||
pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
|
pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
|
||||||
const ParmVarDecl *pd = *pi;
|
const ParmVarDecl *pd = *pi;
|
||||||
ArgEffect AE = AEArgs[i];
|
ArgEffect AE = RS->getArg(i);
|
||||||
if ((AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>()) ||
|
if ((AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>()) ||
|
||||||
AE.getKind() == IncRef || !AuditedType(pd->getType())) {
|
AE.getKind() == IncRef || !AuditedType(pd->getType())) {
|
||||||
AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
|
AddCFAnnotations(Ctx, RS, MethodDecl, MethodIsReturnAnnotated);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -635,11 +635,14 @@ RetainSummaryManager::getSummary(AnyCall C,
|
||||||
// FIXME: These calls are currently unsupported.
|
// FIXME: These calls are currently unsupported.
|
||||||
return getPersistentStopSummary();
|
return getPersistentStopSummary();
|
||||||
case AnyCall::ObjCMethod: {
|
case AnyCall::ObjCMethod: {
|
||||||
const auto *ME = cast<ObjCMessageExpr>(C.getExpr());
|
const auto *ME = cast_or_null<ObjCMessageExpr>(C.getExpr());
|
||||||
if (ME->isInstanceMessage())
|
if (!ME) {
|
||||||
|
return getMethodSummary(cast<ObjCMethodDecl>(C.getDecl()));
|
||||||
|
} else if (ME->isInstanceMessage()) {
|
||||||
Summ = getInstanceMethodSummary(ME, ReceiverType);
|
Summ = getInstanceMethodSummary(ME, ReceiverType);
|
||||||
else
|
} else {
|
||||||
Summ = getClassMethodSummary(ME);
|
Summ = getClassMethodSummary(ME);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1238,31 +1241,3 @@ RetainSummaryManager::getMethodSummary(const ObjCMethodDecl *MD) {
|
||||||
|
|
||||||
return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
|
return getMethodSummary(S, ID, MD, ResultTy, *CachedSummaries);
|
||||||
}
|
}
|
||||||
|
|
||||||
CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
|
|
||||||
ASTContext &Ctx = MD->getASTContext();
|
|
||||||
RetainSummaryManager M(Ctx,
|
|
||||||
/*TrackNSAndCFObjects=*/true,
|
|
||||||
/*TrackOSObjects=*/false);
|
|
||||||
const RetainSummary *S = M.getMethodSummary(MD);
|
|
||||||
CallEffects CE(S->getRetEffect(), S->getReceiverEffect());
|
|
||||||
unsigned N = MD->param_size();
|
|
||||||
for (unsigned i = 0; i < N; ++i) {
|
|
||||||
CE.Args.push_back(S->getArg(i));
|
|
||||||
}
|
|
||||||
return CE;
|
|
||||||
}
|
|
||||||
|
|
||||||
CallEffects CallEffects::getEffect(const FunctionDecl *FD) {
|
|
||||||
ASTContext &Ctx = FD->getASTContext();
|
|
||||||
RetainSummaryManager M(Ctx,
|
|
||||||
/*TrackNSAndCFObjects=*/true,
|
|
||||||
/*TrackOSObjects=*/false);
|
|
||||||
const RetainSummary *S = M.getFunctionSummary(FD);
|
|
||||||
CallEffects CE(S->getRetEffect());
|
|
||||||
unsigned N = FD->param_size();
|
|
||||||
for (unsigned i = 0; i < N; ++i) {
|
|
||||||
CE.Args.push_back(S->getArg(i));
|
|
||||||
}
|
|
||||||
return CE;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1031,11 +1031,11 @@ ExplodedNode * RetainCountChecker::processReturn(const ReturnStmt *S,
|
||||||
|
|
||||||
// FIXME: What is the convention for blocks? Is there one?
|
// FIXME: What is the convention for blocks? Is there one?
|
||||||
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
|
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(CD)) {
|
||||||
const RetainSummary *Summ = Summaries.getMethodSummary(MD);
|
const RetainSummary *Summ = Summaries.getSummary(AnyCall(MD));
|
||||||
RE = Summ->getRetEffect();
|
RE = Summ->getRetEffect();
|
||||||
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
|
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(CD)) {
|
||||||
if (!isa<CXXMethodDecl>(FD)) {
|
if (!isa<CXXMethodDecl>(FD)) {
|
||||||
const RetainSummary *Summ = Summaries.getFunctionSummary(FD);
|
const RetainSummary *Summ = Summaries.getSummary(AnyCall(FD));
|
||||||
RE = Summ->getRetEffect();
|
RE = Summ->getRetEffect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1324,7 +1324,7 @@ void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ProgramStateRef state = Ctx.getState();
|
ProgramStateRef state = Ctx.getState();
|
||||||
const RetainSummary *FunctionSummary = SmrMgr.getFunctionSummary(FD);
|
const RetainSummary *FunctionSummary = SmrMgr.getSummary(AnyCall(FD));
|
||||||
ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
|
ArgEffects CalleeSideArgEffects = FunctionSummary->getArgEffects();
|
||||||
|
|
||||||
for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
|
for (unsigned idx = 0, e = FD->getNumParams(); idx != e; ++idx) {
|
||||||
|
|
Loading…
Reference in New Issue