summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2019-01-10 18:13:59 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2019-01-10 18:13:59 +0000
commit1aa49324a9eba39191d8d5b739f0088474ed7d18 (patch)
tree4e2a7b85798b60744b6552d5bf9fc80db4eef3af
parent6c6bd3ce01117d7c975f2d847e71764f7cf96f75 (diff)
[analyzer] [NFC] Track object type with ArgEffect in RetainCountChecker.
This would be needed in the future. https://reviews.llvm.org/D56040 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@350858 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/StaticAnalyzer/Core/RetainSummaryManager.h59
-rw-r--r--lib/ARCMigrate/ObjCMT.cpp35
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp27
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h2
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp4
-rw-r--r--lib/StaticAnalyzer/Core/RetainSummaryManager.cpp194
6 files changed, 180 insertions, 141 deletions
diff --git a/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h b/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
index 98aad57517..5461716f9d 100644
--- a/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
+++ b/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h
@@ -52,9 +52,7 @@ enum class ObjKind {
OS
};
-/// An ArgEffect summarizes the retain count behavior on an argument or receiver
-/// to a function or method.
-enum ArgEffect {
+enum ArgEffectKind {
/// There is no effect.
DoNothing,
@@ -133,6 +131,27 @@ enum ArgEffect {
DecRefMsgAndStopTrackingHard
};
+/// An ArgEffect summarizes the retain count behavior on an argument or receiver
+/// to a function or method.
+class ArgEffect {
+ ArgEffectKind K;
+ ObjKind O;
+public:
+ explicit ArgEffect(ArgEffectKind K = DoNothing, ObjKind O = ObjKind::AnyObj)
+ : K(K), O(O) {}
+
+ ArgEffectKind getKind() const { return K; }
+ ObjKind getObjKind() const { return O; }
+
+ ArgEffect withKind(ArgEffectKind NewK) {
+ return ArgEffect(NewK, O);
+ }
+
+ bool operator==(const ArgEffect &Other) const {
+ return K == Other.K && O == Other.O;
+ }
+};
+
/// RetEffect summarizes a call's retain/release behavior with respect
/// to its return value.
class RetEffect {
@@ -218,7 +237,9 @@ class CallEffects {
RetEffect Ret;
ArgEffect Receiver;
- CallEffects(const RetEffect &R) : Ret(R) {}
+ CallEffects(const RetEffect &R,
+ ArgEffect Receiver = ArgEffect(DoNothing, ObjKind::AnyObj))
+ : Ret(R), Receiver(Receiver) {}
public:
/// Returns the argument effects for a call.
@@ -263,7 +284,8 @@ namespace llvm {
template <> struct FoldingSetTrait<ArgEffect> {
static inline void Profile(const ArgEffect X, FoldingSetNodeID &ID) {
- ID.AddInteger((unsigned) X);
+ ID.AddInteger((unsigned) X.getKind());
+ ID.AddInteger((unsigned) X.getObjKind());
}
};
template <> struct FoldingSetTrait<RetEffect> {
@@ -377,8 +399,8 @@ public:
void setThisEffect(ArgEffect e) { This = e; }
bool isNoop() const {
- return Ret == RetEffect::MakeNoRet() && Receiver == DoNothing
- && DefaultArgEffect == MayEscape && This == DoNothing
+ return Ret == RetEffect::MakeNoRet() && Receiver.getKind() == DoNothing
+ && DefaultArgEffect.getKind() == MayEscape && This.getKind() == DoNothing
&& Args.isEmpty();
}
@@ -547,32 +569,31 @@ class RetainSummaryManager {
const RetainSummary *getPersistentSummary(const RetainSummary &OldSumm);
- const RetainSummary *getPersistentSummary(RetEffect RetEff,
- ArgEffects ScratchArgs,
- ArgEffect ReceiverEff = DoNothing,
- ArgEffect DefaultEff = MayEscape,
- ArgEffect ThisEff = DoNothing) {
- RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff,
- ThisEff);
+ const RetainSummary *
+ getPersistentSummary(RetEffect RetEff, ArgEffects ScratchArgs,
+ ArgEffect ReceiverEff = ArgEffect(DoNothing),
+ ArgEffect DefaultEff = ArgEffect(MayEscape),
+ ArgEffect ThisEff = ArgEffect(DoNothing)) {
+ RetainSummary Summ(ScratchArgs, RetEff, DefaultEff, ReceiverEff, ThisEff);
return getPersistentSummary(Summ);
}
const RetainSummary *getDoNothingSummary() {
return getPersistentSummary(RetEffect::MakeNoRet(),
ArgEffects(AF.getEmptyMap()),
- DoNothing, DoNothing);
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
}
const RetainSummary *getDefaultSummary() {
return getPersistentSummary(RetEffect::MakeNoRet(),
ArgEffects(AF.getEmptyMap()),
- DoNothing, MayEscape);
+ ArgEffect(DoNothing), ArgEffect(MayEscape));
}
const RetainSummary *getPersistentStopSummary() {
- return getPersistentSummary(RetEffect::MakeNoRet(),
- ArgEffects(AF.getEmptyMap()),
- StopTracking, StopTracking);
+ return getPersistentSummary(
+ RetEffect::MakeNoRet(), ArgEffects(AF.getEmptyMap()),
+ ArgEffect(StopTracking), ArgEffect(StopTracking));
}
void InitializeClassMethodSummaries();
diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp
index b349434907..c3f849b7fa 100644
--- a/lib/ARCMigrate/ObjCMT.cpp
+++ b/lib/ARCMigrate/ObjCMT.cpp
@@ -1484,13 +1484,13 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
const ParmVarDecl *pd = *pi;
ArgEffect AE = AEArgs[i];
- if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
+ if (AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
NSAPIObj->isMacroDefined("CF_CONSUMED")) {
edit::Commit commit(*Editor);
commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
Editor->commit(commit);
}
- else if (AE == DecRefMsg && !pd->hasAttr<NSConsumedAttr>() &&
+ else if (AE.getKind() == DecRefMsg && !pd->hasAttr<NSConsumedAttr>() &&
NSAPIObj->isMacroDefined("NS_CONSUMED")) {
edit::Commit commit(*Editor);
commit.insertBefore(pd->getLocation(), "NS_CONSUMED ");
@@ -1536,13 +1536,13 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND
pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) {
const ParmVarDecl *pd = *pi;
ArgEffect AE = AEArgs[i];
- if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) {
- if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>())
+ if (AE.getKind() == DecRef /*CFConsumed annotated*/ ||
+ AE.getKind() == IncRef) {
+ if (AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>())
ArgCFAudited = true;
- else if (AE == IncRef)
+ else if (AE.getKind() == IncRef)
ArgCFAudited = true;
- }
- else {
+ } else {
QualType AT = pd->getType();
if (!AuditedType(AT)) {
AddCFAnnotations(Ctx, CE, FuncDecl, FuncIsReturnAnnotated);
@@ -1610,7 +1610,7 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx,
pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
const ParmVarDecl *pd = *pi;
ArgEffect AE = AEArgs[i];
- if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
+ if (AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>() &&
NSAPIObj->isMacroDefined("CF_CONSUMED")) {
edit::Commit commit(*Editor);
commit.insertBefore(pd->getLocation(), "CF_CONSUMED ");
@@ -1626,13 +1626,14 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
return;
CallEffects CE = CallEffects::getEffect(MethodDecl);
- bool MethodIsReturnAnnotated = (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
- MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
- MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
- MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
- MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
-
- if (CE.getReceiver() == DecRefMsg &&
+ bool MethodIsReturnAnnotated =
+ (MethodDecl->hasAttr<CFReturnsRetainedAttr>() ||
+ MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() ||
+ MethodDecl->hasAttr<NSReturnsRetainedAttr>() ||
+ MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() ||
+ MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>());
+
+ if (CE.getReceiver().getKind() == DecRefMsg &&
!MethodDecl->hasAttr<NSConsumesSelfAttr>() &&
MethodDecl->getMethodFamily() != OMF_init &&
MethodDecl->getMethodFamily() != OMF_release &&
@@ -1666,8 +1667,8 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation(
pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) {
const ParmVarDecl *pd = *pi;
ArgEffect AE = AEArgs[i];
- if ((AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) || AE == IncRef ||
- !AuditedType(pd->getType())) {
+ if ((AE.getKind() == DecRef && !pd->hasAttr<CFConsumedAttr>()) ||
+ AE.getKind() == IncRef || !AuditedType(pd->getType())) {
AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated);
return;
}
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
index a9b6d6839d..4e5fac815e 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
@@ -248,7 +248,7 @@ void RetainCountChecker::checkPostStmt(const CastExpr *CE,
if (!BE)
return;
- ArgEffect AE = IncRef;
+ ArgEffectKind AE = IncRef;
switch (BE->getBridgeKind()) {
case OBC_Bridge:
@@ -534,7 +534,7 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
SVal V = CallOrMsg.getArgSVal(idx);
if (SymbolRef Sym = V.getAsLocSymbol()) {
- bool ShouldRemoveBinding = Summ.getArg(idx) == StopTrackingHard;
+ bool ShouldRemoveBinding = Summ.getArg(idx).getKind() == StopTrackingHard;
if (const RefVal *T = getRefBinding(state, Sym))
if (shouldEscapeArgumentOnCall(CallOrMsg, idx, T))
ShouldRemoveBinding = true;
@@ -547,7 +547,7 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
// Evaluate the effect on the message receiver.
if (const auto *MsgInvocation = dyn_cast<ObjCMethodCall>(&CallOrMsg)) {
if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
- if (Summ.getReceiverEffect() == StopTrackingHard) {
+ if (Summ.getReceiverEffect().getKind() == StopTrackingHard) {
state = removeRefBinding(state, Sym);
}
}
@@ -566,7 +566,7 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ,
static ProgramStateRef updateOutParameter(ProgramStateRef State,
SVal ArgVal,
- ArgEffect Effect) {
+ ArgEffectKind Effect) {
auto *ArgRegion = dyn_cast_or_null<TypedValueRegion>(ArgVal.getAsRegion());
if (!ArgRegion)
return State;
@@ -611,7 +611,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) {
SVal V = CallOrMsg.getArgSVal(idx);
- ArgEffect Effect = Summ.getArg(idx);
+ ArgEffectKind Effect = Summ.getArg(idx).getKind();
if (Effect == RetainedOutParameter || Effect == UnretainedOutParameter) {
state = updateOutParameter(state, V, Effect);
} else if (SymbolRef Sym = V.getAsLocSymbol()) {
@@ -637,8 +637,8 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) {
if (const RefVal *T = getRefBinding(state, Sym)) {
ReceiverIsTracked = true;
- state = updateSymbol(state, Sym, *T, Summ.getReceiverEffect(),
- hasErr, C);
+ state = updateSymbol(state, Sym, *T,
+ Summ.getReceiverEffect().getKind(), hasErr, C);
if (hasErr) {
ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange();
ErrorSym = Sym;
@@ -648,7 +648,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
} else if (const auto *MCall = dyn_cast<CXXMemberCall>(&CallOrMsg)) {
if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) {
if (const RefVal *T = getRefBinding(state, Sym)) {
- state = updateSymbol(state, Sym, *T, Summ.getThisEffect(),
+ state = updateSymbol(state, Sym, *T, Summ.getThisEffect().getKind(),
hasErr, C);
if (hasErr) {
ErrorRange = MCall->getOriginExpr()->getSourceRange();
@@ -707,10 +707,11 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ,
}
}
-ProgramStateRef
-RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym,
- RefVal V, ArgEffect E, RefVal::Kind &hasErr,
- CheckerContext &C) const {
+ProgramStateRef RetainCountChecker::updateSymbol(ProgramStateRef state,
+ SymbolRef sym, RefVal V,
+ ArgEffectKind E,
+ RefVal::Kind &hasErr,
+ CheckerContext &C) const {
bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount;
switch (E) {
default:
@@ -1405,7 +1406,7 @@ void RetainCountChecker::checkBeginFunction(CheckerContext &Ctx) const {
QualType Ty = Param->getType();
const ArgEffect *AE = CalleeSideArgEffects.lookup(idx);
- if (AE && *AE == DecRef && isISLObjectRef(Ty)) {
+ if (AE && AE->getKind() == DecRef && isISLObjectRef(Ty)) {
state = setRefBinding(
state, Sym, RefVal::makeOwned(ObjKind::Generalized, Ty));
} else if (isISLObjectRef(Ty)) {
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
index d8bbe6fcdd..80d1b0573c 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h
@@ -347,7 +347,7 @@ public:
void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const;
ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym,
- RefVal V, ArgEffect E, RefVal::Kind &hasErr,
+ RefVal V, ArgEffectKind E, RefVal::Kind &hasErr,
CheckerContext &C) const;
void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange,
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
index 44cb7553c0..5a687ef8d1 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
@@ -48,7 +48,9 @@ static bool shouldGenerateNote(llvm::raw_string_ostream &os,
RefVal PrevV = *PrevT;
// Specially handle -dealloc.
- if (std::find(AEffects.begin(), AEffects.end(), Dealloc) != AEffects.end()) {
+ if (std::find_if(AEffects.begin(), AEffects.end(), [](ArgEffect &E) {
+ return E.getKind() == Dealloc;
+ }) != AEffects.end()) {
// Determine if the object's reference count was pushed to zero.
assert(!PrevV.hasSameState(CurrV) && "The state should have changed.");
// We may not have transitioned to 'release' if we hit an error.
diff --git a/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp b/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
index 465449b150..9f0e60ec3e 100644
--- a/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
+++ b/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
@@ -201,8 +201,8 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
// Part of: <rdar://problem/39390714>.
return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
ScratchArgs,
- DoNothing,
- DoNothing);
+ ArgEffect(DoNothing),
+ ArgEffect(DoNothing));
} else if (FName == "CFPlugInInstanceCreate") {
return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs);
} else if (FName == "IORegistryEntrySearchCFProperty" ||
@@ -213,25 +213,25 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
FName == "IOOpenFirmwarePathMatching"))) {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
- return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
- ScratchArgs, DoNothing, DoNothing);
+ return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
} else if (FName == "IOServiceGetMatchingService" ||
FName == "IOServiceGetMatchingServices") {
// FIXES: <rdar://problem/6326900>
// This should be addressed using a API table. This strcmp is also
// a little gross, but there is no need to super optimize here.
- ScratchArgs = AF.add(ScratchArgs, 1, DecRef);
+ ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(DecRef, ObjKind::CF));
return getPersistentSummary(RetEffect::MakeNoRet(),
ScratchArgs,
- DoNothing, DoNothing);
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
} else if (FName == "IOServiceAddNotification" ||
FName == "IOServiceAddMatchingNotification") {
// Part of <rdar://problem/6961230>. (IOKit)
// This should be addressed using a API table.
- ScratchArgs = AF.add(ScratchArgs, 2, DecRef);
+ ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(DecRef, ObjKind::CF));
return getPersistentSummary(RetEffect::MakeNoRet(),
ScratchArgs,
- DoNothing, DoNothing);
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
} else if (FName == "CVPixelBufferCreateWithBytes") {
// FIXES: <rdar://problem/7283567>
// Eventually this can be improved by recognizing that the pixel
@@ -239,38 +239,38 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
// a callback and doing full IPA to make sure this is done correctly.
// FIXME: This function has an out parameter that returns an
// allocated object.
- ScratchArgs = AF.add(ScratchArgs, 7, StopTracking);
+ ScratchArgs = AF.add(ScratchArgs, 7, ArgEffect(StopTracking));
return getPersistentSummary(RetEffect::MakeNoRet(),
ScratchArgs,
- DoNothing, DoNothing);
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
} else if (FName == "CGBitmapContextCreateWithData") {
// FIXES: <rdar://problem/7358899>
// Eventually this can be improved by recognizing that 'releaseInfo'
// passed to CGBitmapContextCreateWithData is released via
// a callback and doing full IPA to make sure this is done correctly.
- ScratchArgs = AF.add(ScratchArgs, 8, StopTracking);
- return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF),
- ScratchArgs, DoNothing, DoNothing);
+ ScratchArgs = AF.add(ScratchArgs, 8, ArgEffect(ArgEffect(StopTracking)));
+ return getPersistentSummary(RetEffect::MakeOwned(ObjKind::CF), ScratchArgs,
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
} else if (FName == "CVPixelBufferCreateWithPlanarBytes") {
// FIXES: <rdar://problem/7283567>
// Eventually this can be improved by recognizing that the pixel
// buffer passed to CVPixelBufferCreateWithPlanarBytes is released
// via a callback and doing full IPA to make sure this is done
// correctly.
- ScratchArgs = AF.add(ScratchArgs, 12, StopTracking);
+ ScratchArgs = AF.add(ScratchArgs, 12, ArgEffect(StopTracking));
return getPersistentSummary(RetEffect::MakeNoRet(),
ScratchArgs,
- DoNothing, DoNothing);
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
} else if (FName == "VTCompressionSessionEncodeFrame") {
// The context argument passed to VTCompressionSessionEncodeFrame()
// is passed to the callback specified when creating the session
// (e.g. with VTCompressionSessionCreate()) which can release it.
// To account for this possibility, conservatively stop tracking
// the context.
- ScratchArgs = AF.add(ScratchArgs, 5, StopTracking);
+ ScratchArgs = AF.add(ScratchArgs, 5, ArgEffect(StopTracking));
return getPersistentSummary(RetEffect::MakeNoRet(),
ScratchArgs,
- DoNothing, DoNothing);
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
} else if (FName == "dispatch_set_context" ||
FName == "xpc_connection_set_context") {
// <rdar://problem/11059275> - The analyzer currently doesn't have
@@ -279,20 +279,21 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
// <rdar://problem/13783514> - Same problem, but for XPC.
// FIXME: this hack should possibly go away once we can handle
// libdispatch and XPC finalizers.
- ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
+ ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
return getPersistentSummary(RetEffect::MakeNoRet(),
ScratchArgs,
- DoNothing, DoNothing);
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
} else if (FName.startswith("NSLog")) {
return getDoNothingSummary();
} else if (FName.startswith("NS") &&
(FName.find("Insert") != StringRef::npos)) {
// Whitelist NSXXInsertXX, for example NSMapInsertIfAbsent, since they can
// be deallocated by NSMapRemove. (radar://11152419)
- ScratchArgs = AF.add(ScratchArgs, 1, StopTracking);
- ScratchArgs = AF.add(ScratchArgs, 2, StopTracking);
+ ScratchArgs = AF.add(ScratchArgs, 1, ArgEffect(StopTracking));
+ ScratchArgs = AF.add(ScratchArgs, 2, ArgEffect(StopTracking));
return getPersistentSummary(RetEffect::MakeNoRet(),
- ScratchArgs, DoNothing, DoNothing);
+ ScratchArgs, ArgEffect(DoNothing),
+ ArgEffect(DoNothing));
}
if (RetTy->isPointerType()) {
@@ -367,16 +368,17 @@ const RetainSummary *RetainSummaryManager::getSummaryForObjCOrCFObject(
// "AppendValue", or "SetAttribute", then we assume that arguments may
// "escape." This means that something else holds on to the object,
// allowing it be used even after its local retain count drops to 0.
- ArgEffect E = (StrInStrNoCase(FName, "InsertValue") != StringRef::npos ||
- StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
- StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
- StrInStrNoCase(FName, "AppendValue") != StringRef::npos ||
- StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
- ? MayEscape
- : DoNothing;
+ ArgEffectKind E =
+ (StrInStrNoCase(FName, "InsertValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "AddValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "SetValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "AppendValue") != StringRef::npos ||
+ StrInStrNoCase(FName, "SetAttribute") != StringRef::npos)
+ ? MayEscape
+ : DoNothing;
return getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
- DoNothing, E);
+ ArgEffect(DoNothing), ArgEffect(E, ObjKind::CF));
}
}
@@ -415,8 +417,9 @@ RetainSummaryManager::generateSummary(const FunctionDecl *FD,
if (!(TrackOSObjects && isOSObjectRelated(MD)))
return getPersistentSummary(RetEffect::MakeNoRet(),
ArgEffects(AF.getEmptyMap()),
- DoNothing, StopTracking,
- DoNothing);
+ ArgEffect(DoNothing),
+ ArgEffect(StopTracking),
+ ArgEffect(DoNothing));
return getDefaultSummary();
}
@@ -449,7 +452,7 @@ RetainSummaryManager::getFunctionSummary(const FunctionDecl *FD) {
//===----------------------------------------------------------------------===//
static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
- switch (E) {
+ switch (E.getKind()) {
case DoNothing:
case Autorelease:
case DecRefBridgedTransferred:
@@ -461,15 +464,15 @@ static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) {
case MayEscape:
case StopTracking:
case StopTrackingHard:
- return StopTrackingHard;
+ return E.withKind(StopTrackingHard);
case DecRef:
case DecRefAndStopTrackingHard:
- return DecRefAndStopTrackingHard;
+ return E.withKind(DecRefAndStopTrackingHard);
case DecRefMsg:
case DecRefMsgAndStopTrackingHard:
- return DecRefMsgAndStopTrackingHard;
+ return E.withKind(DecRefMsgAndStopTrackingHard);
case Dealloc:
- return Dealloc;
+ return E.withKind(Dealloc);
}
llvm_unreachable("Unknown ArgEffect kind");
@@ -489,7 +492,7 @@ void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
E = CustomArgEffects.end();
I != E; ++I) {
ArgEffect Translated = getStopTrackingHardEquivalent(I->second);
- if (Translated != DefEffect)
+ if (Translated.getKind() != DefEffect.getKind())
ScratchArgs = AF.add(ScratchArgs, I->first, Translated);
}
@@ -535,7 +538,7 @@ void RetainSummaryManager::updateSummaryForCall(const RetainSummary *&S,
ParentMap &PM = LCtx->getAnalysisDeclContext()->getParentMap();
if (!PM.isConsumedExpr(ME)) {
RetainSummaryTemplate ModifiableSummaryTemplate(S, *this);
- ModifiableSummaryTemplate->setReceiverEffect(DoNothing);
+ ModifiableSummaryTemplate->setReceiverEffect(ArgEffect(DoNothing));
ModifiableSummaryTemplate->setRetEffect(RetEffect::MakeNoRet());
}
}
@@ -661,43 +664,43 @@ RetainSummaryManager::getUnarySummary(const FunctionType* FT,
ArgEffect Effect;
switch (func) {
- case cfretain: Effect = IncRef; break;
- case cfrelease: Effect = DecRef; break;
- case cfautorelease: Effect = Autorelease; break;
- case cfmakecollectable: Effect = MakeCollectable; break;
+ case cfretain: Effect = Effect.withKind(IncRef); break;
+ case cfrelease: Effect = Effect.withKind(DecRef); break;
+ case cfautorelease: Effect = Effect.withKind(Autorelease); break;
+ case cfmakecollectable: Effect = Effect.withKind(MakeCollectable); break;
}
ScratchArgs = AF.add(ScratchArgs, 0, Effect);
return getPersistentSummary(RetEffect::MakeNoRet(),
ScratchArgs,
- DoNothing, DoNothing);
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
}
const RetainSummary *
RetainSummaryManager::getOSSummaryRetainRule(const FunctionDecl *FD) {
return getPersistentSummary(RetEffect::MakeNoRet(),
AF.getEmptyMap(),
- /*ReceiverEff=*/DoNothing,
- /*DefaultEff=*/DoNothing,
- /*ThisEff=*/IncRef);
+ /*ReceiverEff=*/ArgEffect(DoNothing),
+ /*DefaultEff=*/ArgEffect(DoNothing),
+ /*ThisEff=*/ArgEffect(IncRef, ObjKind::OS));
}
const RetainSummary *
RetainSummaryManager::getOSSummaryReleaseRule(const FunctionDecl *FD) {
return getPersistentSummary(RetEffect::MakeNoRet(),
AF.getEmptyMap(),
- /*ReceiverEff=*/DoNothing,
- /*DefaultEff=*/DoNothing,
- /*ThisEff=*/DecRef);
+ /*ReceiverEff=*/ArgEffect(DoNothing),
+ /*DefaultEff=*/ArgEffect(DoNothing),
+ /*ThisEff=*/ArgEffect(DecRef, ObjKind::OS));
}
const RetainSummary *
RetainSummaryManager::getOSSummaryFreeRule(const FunctionDecl *FD) {
return getPersistentSummary(RetEffect::MakeNoRet(),
AF.getEmptyMap(),
- /*ReceiverEff=*/DoNothing,
- /*DefaultEff=*/DoNothing,
- /*ThisEff=*/Dealloc);
+ /*ReceiverEff=*/ArgEffect(DoNothing),
+ /*DefaultEff=*/ArgEffect(DoNothing),
+ /*ThisEff=*/ArgEffect(Dealloc, ObjKind::OS));
}
const RetainSummary *
@@ -722,7 +725,7 @@ const RetainSummary *
RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) {
return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::CF),
ArgEffects(AF.getEmptyMap()),
- DoNothing, DoNothing);
+ ArgEffect(DoNothing), ArgEffect(DoNothing));
}
@@ -775,19 +778,24 @@ bool RetainSummaryManager::applyFunctionParamAnnotationEffect(
const ParmVarDecl *pd, unsigned parm_idx, const FunctionDecl *FD,
RetainSummaryTemplate &Template) {
if (hasEnabledAttr<NSConsumedAttr>(pd)) {
- Template->addArg(AF, parm_idx, DecRefMsg);
+ Template->addArg(AF, parm_idx, ArgEffect(DecRefMsg, ObjKind::ObjC));
+ return true;
+ } else if (hasEnabledAttr<CFConsumedAttr>(pd)) {
+ Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::CF));
return true;
- } else if (hasEnabledAttr<CFConsumedAttr>(pd) ||
- hasEnabledAttr<OSConsumedAttr>(pd) ||
- hasRCAnnotation(pd, "rc_ownership_consumed")) {
- Template->addArg(AF, parm_idx, DecRef);
+ } else if (hasEnabledAttr<OSConsumedAttr>(pd)) {
+ Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::OS));
+ return true;
+ } else if (hasRCAnnotation(pd, "rc_ownership_consumed")) {
+ Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::Generalized));
return true;
} else if (hasEnabledAttr<CFReturnsRetainedAttr>(pd) ||
hasRCAnnotation(pd, "rc_ownership_returns_retained")) {
QualType PointeeTy = pd->getType()->getPointeeType();
if (!PointeeTy.isNull()) {
if (coreFoundation::isCFObjectRef(PointeeTy)) {
- Template->addArg(AF, parm_idx, RetainedOutParameter);
+ Template->addArg(AF, parm_idx, ArgEffect(RetainedOutParameter,
+ ObjKind::CF));
return true;
}
}
@@ -795,7 +803,8 @@ bool RetainSummaryManager::applyFunctionParamAnnotationEffect(
QualType PointeeTy = pd->getType()->getPointeeType();
if (!PointeeTy.isNull()) {
if (coreFoundation::isCFObjectRef(PointeeTy)) {
- Template->addArg(AF, parm_idx, UnretainedOutParameter);
+ Template->addArg(AF, parm_idx, ArgEffect(UnretainedOutParameter,
+ ObjKind::CF));
return true;
}
}
@@ -834,7 +843,7 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
Template->setRetEffect(*RetE);
if (hasEnabledAttr<OSConsumesThisAttr>(FD))
- Template->setThisEffect(DecRef);
+ Template->setThisEffect(ArgEffect(DecRef, ObjKind::OS));
}
void
@@ -848,7 +857,7 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
// Effects on the receiver.
if (MD->hasAttr<NSConsumesSelfAttr>())
- Template->setReceiverEffect(DecRefMsg);
+ Template->setReceiverEffect(ArgEffect(DecRefMsg, ObjKind::ObjC));
// Effects on the parameters.
unsigned parm_idx = 0;
@@ -856,19 +865,23 @@ RetainSummaryManager::updateSummaryFromAnnotations(const RetainSummary *&Summ,
pi != pe; ++pi, ++parm_idx) {
const ParmVarDecl *pd = *pi;
if (pd->hasAttr<NSConsumedAttr>()) {
- Template->addArg(AF, parm_idx, DecRefMsg);
- } else if (pd->hasAttr<CFConsumedAttr>() || pd->hasAttr<OSConsumedAttr>()) {
- Template->addArg(AF, parm_idx, DecRef);
+ Template->addArg(AF, parm_idx, ArgEffect(DecRefMsg, ObjKind::ObjC));
+ } else if (pd->hasAttr<CFConsumedAttr>()) {
+ Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::CF));
+ } else if (pd->hasAttr<OSConsumedAttr>()) {
+ Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::OS));
} else if (pd->hasAttr<CFReturnsRetainedAttr>()) {
QualType PointeeTy = pd->getType()->getPointeeType();
if (!PointeeTy.isNull())
if (coreFoundation::isCFObjectRef(PointeeTy))
- Template->addArg(AF, parm_idx, RetainedOutParameter);
+ Template->addArg(AF, parm_idx,
+ ArgEffect(RetainedOutParameter, ObjKind::CF));
} else if (pd->hasAttr<CFReturnsNotRetainedAttr>()) {
QualType PointeeTy = pd->getType()->getPointeeType();
if (!PointeeTy.isNull())
if (coreFoundation::isCFObjectRef(PointeeTy))
- Template->addArg(AF, parm_idx, UnretainedOutParameter);
+ Template->addArg(AF, parm_idx, ArgEffect(UnretainedOutParameter,
+ ObjKind::CF));
}
}
@@ -881,7 +894,7 @@ const RetainSummary *
RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
Selector S, QualType RetTy) {
// Any special effects?
- ArgEffect ReceiverEff = DoNothing;
+ ArgEffect ReceiverEff = ArgEffect(DoNothing, ObjKind::ObjC);
RetEffect ResultEff = RetEffect::MakeNoRet();
// Check the method family, and apply any default annotations.
@@ -918,7 +931,7 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
break;
case OMF_init:
ResultEff = ObjCInitRetE;
- ReceiverEff = DecRefMsg;
+ ReceiverEff = ArgEffect(DecRefMsg, ObjKind::ObjC);
break;
case OMF_alloc:
case OMF_new:
@@ -930,16 +943,16 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
ResultEff = RetEffect::MakeOwned(ObjKind::CF);
break;
case OMF_autorelease:
- ReceiverEff = Autorelease;
+ ReceiverEff = ArgEffect(Autorelease, ObjKind::ObjC);
break;
case OMF_retain:
- ReceiverEff = IncRefMsg;
+ ReceiverEff = ArgEffect(IncRefMsg, ObjKind::ObjC);
break;
case OMF_release:
- ReceiverEff = DecRefMsg;
+ ReceiverEff = ArgEffect(DecRefMsg, ObjKind::ObjC);
break;
case OMF_dealloc:
- ReceiverEff = Dealloc;
+ ReceiverEff = ArgEffect(Dealloc, ObjKind::ObjC);
break;
case OMF_self:
// -self is handled specially by the ExprEngine to propagate the receiver.
@@ -961,17 +974,17 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
if (ResultEff == ObjCInitRetE)
ResultEff = RetEffect::MakeNoRetHard();
else
- ReceiverEff = StopTrackingHard;
+ ReceiverEff = ArgEffect(StopTrackingHard, ObjKind::ObjC);
}
}
}
- if (ReceiverEff == DoNothing &&
+ if (ReceiverEff.getKind() == DoNothing &&
ResultEff.getKind() == RetEffect::NoRet)
return getDefaultSummary();
return getPersistentSummary(ResultEff, ArgEffects(AF.getEmptyMap()),
- ReceiverEff, MayEscape);
+ ArgEffect(ReceiverEff), ArgEffect(MayEscape));
}
const RetainSummary *RetainSummaryManager::getInstanceMethodSummary(
@@ -1037,11 +1050,11 @@ void RetainSummaryManager::InitializeClassMethodSummaries() {
ScratchArgs));
// Create the [NSAutoreleasePool addObject:] summary.
- ScratchArgs = AF.add(ScratchArgs, 0, Autorelease);
+ ScratchArgs = AF.add(ScratchArgs, 0, ArgEffect(Autorelease));
addClassMethSummary("NSAutoreleasePool", "addObject",
- getPersistentSummary(RetEffect::MakeNoRet(),
- ScratchArgs,
- DoNothing, Autorelease));
+ getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
+ ArgEffect(DoNothing),
+ ArgEffect(Autorelease)));
}
void RetainSummaryManager::InitializeMethodSummaries() {
@@ -1051,7 +1064,7 @@ void RetainSummaryManager::InitializeMethodSummaries() {
// receiver.
const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE,
ScratchArgs,
- DecRefMsg);
+ ArgEffect(DecRefMsg));
addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
// awakeAfterUsingCoder: behaves basically like an 'init' method. It
@@ -1067,19 +1080,20 @@ void RetainSummaryManager::InitializeMethodSummaries() {
// Create the "retain" selector.
RetEffect NoRet = RetEffect::MakeNoRet();
- const RetainSummary *Summ = getPersistentSummary(NoRet, ScratchArgs, IncRefMsg);
+ const RetainSummary *Summ =
+ getPersistentSummary(NoRet, ScratchArgs, ArgEffect(IncRefMsg));
addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ);
// Create the "release" selector.
- Summ = getPersistentSummary(NoRet, ScratchArgs, DecRefMsg);
+ Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(DecRefMsg));
addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ);
// Create the -dealloc summary.
- Summ = getPersistentSummary(NoRet, ScratchArgs, Dealloc);
+ Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Dealloc));
addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ);
// Create the "autorelease" selector.
- Summ = getPersistentSummary(NoRet, ScratchArgs, Autorelease);
+ Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Autorelease));
addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ);
// For NSWindow, allocated objects are (initially) self-owned.
@@ -1088,8 +1102,9 @@ void RetainSummaryManager::InitializeMethodSummaries() {
// Thus, we need to track an NSWindow's display status.
// This is tracked in <rdar://problem/6062711>.
// See also http://llvm.org/bugs/show_bug.cgi?id=3714.
- const RetainSummary *NoTrackYet = getPersistentSummary(
- RetEffect::MakeNoRet(), ScratchArgs, StopTracking, StopTracking);
+ const RetainSummary *NoTrackYet =
+ getPersistentSummary(RetEffect::MakeNoRet(), ScratchArgs,
+ ArgEffect(StopTracking), ArgEffect(StopTracking));
addClassMethSummary("NSWindow", "alloc", NoTrackYet);
@@ -1130,8 +1145,7 @@ CallEffects CallEffects::getEffect(const ObjCMethodDecl *MD) {
/*TrackNSAndCFObjects=*/true,
/*TrackOSObjects=*/false);
const RetainSummary *S = M.getMethodSummary(MD);
- CallEffects CE(S->getRetEffect());
- CE.Receiver = S->getReceiverEffect();
+ 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));