Index: clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h +++ clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h @@ -68,20 +68,10 @@ /// if CFRelease has been called on the argument. DecRef, - /// The argument has its reference count decreased by 1. This is as - /// if a -release message has been sent to the argument. This differs - /// in behavior from DecRef when ARC is enabled. - DecRefMsg, - /// The argument has its reference count decreased by 1 to model /// a transferred bridge cast under ARC. DecRefBridgedTransferred, - /// The argument has its reference count increased by 1. This is as - /// if a -retain message has been sent to the argument. This differs - /// in behavior from IncRef when ARC is enabled. - IncRefMsg, - /// The argument has its reference count increased by 1. This is as /// if CFRetain has been called on the argument. IncRef, @@ -122,13 +112,6 @@ /// count of the argument and all typestate tracking on that argument /// should cease. DecRefAndStopTrackingHard, - - /// Performs the combined functionality of DecRefMsg and StopTrackingHard. - /// - /// The models the effect that the called function decrements the reference - /// count of the argument and all typestate tracking on that argument - /// should cease. - DecRefMsgAndStopTrackingHard }; /// An ArgEffect summarizes the retain count behavior on an argument or receiver Index: clang/lib/ARCMigrate/ObjCMT.cpp =================================================================== --- clang/lib/ARCMigrate/ObjCMT.cpp +++ clang/lib/ARCMigrate/ObjCMT.cpp @@ -1484,14 +1484,15 @@ pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) { const ParmVarDecl *pd = *pi; ArgEffect AE = AEArgs[i]; - if (AE.getKind() == DecRef && !pd->hasAttr() && + if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::CF && + !pd->hasAttr() && NSAPIObj->isMacroDefined("CF_CONSUMED")) { edit::Commit commit(*Editor); commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); Editor->commit(commit); - } - else if (AE.getKind() == DecRefMsg && !pd->hasAttr() && - NSAPIObj->isMacroDefined("NS_CONSUMED")) { + } else if (AE.getKind() == DecRef && AE.getObjKind() == ObjKind::ObjC && + !pd->hasAttr() && + NSAPIObj->isMacroDefined("NS_CONSUMED")) { edit::Commit commit(*Editor); commit.insertBefore(pd->getLocation(), "NS_CONSUMED "); Editor->commit(commit); @@ -1536,8 +1537,8 @@ pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) { const ParmVarDecl *pd = *pi; ArgEffect AE = AEArgs[i]; - if (AE.getKind() == DecRef /*CFConsumed annotated*/ || - AE.getKind() == IncRef) { + if ((AE.getKind() == DecRef /*CFConsumed annotated*/ || + AE.getKind() == IncRef) && AE.getObjKind() == ObjKind::CF) { if (AE.getKind() == DecRef && !pd->hasAttr()) ArgCFAudited = true; else if (AE.getKind() == IncRef) @@ -1610,7 +1611,9 @@ pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { const ParmVarDecl *pd = *pi; ArgEffect AE = AEArgs[i]; - if (AE.getKind() == DecRef && !pd->hasAttr() && + if (AE.getKind() == DecRef + && AE.getObjKind() == ObjKind::CF + && !pd->hasAttr() && NSAPIObj->isMacroDefined("CF_CONSUMED")) { edit::Commit commit(*Editor); commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); @@ -1633,7 +1636,7 @@ MethodDecl->hasAttr() || MethodDecl->hasAttr()); - if (CE.getReceiver().getKind() == DecRefMsg && + if (CE.getReceiver().getKind() == DecRef && !MethodDecl->hasAttr() && MethodDecl->getMethodFamily() != OMF_init && MethodDecl->getMethodFamily() != OMF_release && Index: clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h =================================================================== --- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h +++ clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.h @@ -347,7 +347,7 @@ void checkEndFunction(const ReturnStmt *RS, CheckerContext &C) const; ProgramStateRef updateSymbol(ProgramStateRef state, SymbolRef sym, - RefVal V, ArgEffectKind E, RefVal::Kind &hasErr, + RefVal V, ArgEffect E, RefVal::Kind &hasErr, CheckerContext &C) const; void processNonLeakError(ProgramStateRef St, SourceRange ErrorRange, Index: clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp @@ -248,17 +248,17 @@ if (!BE) return; - ArgEffectKind AE = IncRef; + ArgEffect AE = ArgEffect(IncRef, ObjKind::ObjC); switch (BE->getBridgeKind()) { case OBC_Bridge: // Do nothing. return; case OBC_BridgeRetained: - AE = IncRef; + AE = AE.withKind(IncRef); break; case OBC_BridgeTransfer: - AE = DecRefBridgedTransferred; + AE = AE.withKind(DecRefBridgedTransferred); break; } @@ -290,7 +290,8 @@ if (SymbolRef sym = V.getAsSymbol()) if (const RefVal* T = getRefBinding(state, sym)) { RefVal::Kind hasErr = (RefVal::Kind) 0; - state = updateSymbol(state, sym, *T, MayEscape, hasErr, C); + state = updateSymbol(state, sym, *T, + ArgEffect(MayEscape, ObjKind::ObjC), hasErr, C); if (hasErr) { processNonLeakError(state, Child->getSourceRange(), hasErr, sym, C); return; @@ -512,7 +513,7 @@ /// 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, +static bool shouldEscapeOSArgumentOnCall(const CallEvent &CE, unsigned ArgIdx, const RefVal *TrackedValue) { if (TrackedValue->getObjKind() != ObjKind::OS) return false; @@ -536,7 +537,7 @@ if (SymbolRef Sym = V.getAsLocSymbol()) { bool ShouldRemoveBinding = Summ.getArg(idx).getKind() == StopTrackingHard; if (const RefVal *T = getRefBinding(state, Sym)) - if (shouldEscapeArgumentOnCall(CallOrMsg, idx, T)) + if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T)) ShouldRemoveBinding = true; if (ShouldRemoveBinding) @@ -611,14 +612,15 @@ for (unsigned idx = 0, e = CallOrMsg.getNumArgs(); idx != e; ++idx) { SVal V = CallOrMsg.getArgSVal(idx); - ArgEffectKind Effect = Summ.getArg(idx).getKind(); - if (Effect == RetainedOutParameter || Effect == UnretainedOutParameter) { - state = updateOutParameter(state, V, Effect); + ArgEffect Effect = Summ.getArg(idx); + if (Effect.getKind() == RetainedOutParameter || + Effect.getKind() == UnretainedOutParameter) { + state = updateOutParameter(state, V, Effect.getKind()); } else if (SymbolRef Sym = V.getAsLocSymbol()) { if (const RefVal *T = getRefBinding(state, Sym)) { - if (shouldEscapeArgumentOnCall(CallOrMsg, idx, T)) - Effect = StopTrackingHard; + if (shouldEscapeOSArgumentOnCall(CallOrMsg, idx, T)) + Effect = ArgEffect(StopTrackingHard, ObjKind::OS); state = updateSymbol(state, Sym, *T, Effect, hasErr, C); if (hasErr) { @@ -638,7 +640,7 @@ if (const RefVal *T = getRefBinding(state, Sym)) { ReceiverIsTracked = true; state = updateSymbol(state, Sym, *T, - Summ.getReceiverEffect().getKind(), hasErr, C); + Summ.getReceiverEffect(), hasErr, C); if (hasErr) { ErrorRange = MsgInvocation->getOriginExpr()->getReceiverRange(); ErrorSym = Sym; @@ -648,7 +650,7 @@ } else if (const auto *MCall = dyn_cast(&CallOrMsg)) { if (SymbolRef Sym = MCall->getCXXThisVal().getAsLocSymbol()) { if (const RefVal *T = getRefBinding(state, Sym)) { - state = updateSymbol(state, Sym, *T, Summ.getThisEffect().getKind(), + state = updateSymbol(state, Sym, *T, Summ.getThisEffect(), hasErr, C); if (hasErr) { ErrorRange = MCall->getOriginExpr()->getSourceRange(); @@ -709,25 +711,27 @@ ProgramStateRef RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym, RefVal V, - ArgEffectKind E, + ArgEffect AE, RefVal::Kind &hasErr, CheckerContext &C) const { bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount; - switch (E) { - default: - break; - case IncRefMsg: - E = IgnoreRetainMsg ? DoNothing : IncRef; - break; - case DecRefMsg: - E = IgnoreRetainMsg ? DoNothing: DecRef; - break; - case DecRefMsgAndStopTrackingHard: - E = IgnoreRetainMsg ? StopTracking : DecRefAndStopTrackingHard; - break; - case MakeCollectable: - E = DoNothing; + if (AE.getObjKind() == ObjKind::ObjC && IgnoreRetainMsg) { + switch (AE.getKind()) { + default: + break; + case IncRef: + AE = AE.withKind(DoNothing); + break; + case DecRef: + AE = AE.withKind(DoNothing); + break; + case DecRefAndStopTrackingHard: + AE = AE.withKind(StopTracking); + break; + } } + if (AE.getKind() == MakeCollectable) + AE = AE.withKind(DoNothing); // Handle all use-after-releases. if (V.getKind() == RefVal::Released) { @@ -736,12 +740,9 @@ return setRefBinding(state, sym, V); } - switch (E) { - case DecRefMsg: - case IncRefMsg: + switch (AE.getKind()) { case MakeCollectable: - case DecRefMsgAndStopTrackingHard: - llvm_unreachable("DecRefMsg/IncRefMsg/MakeCollectable already converted"); + llvm_unreachable("MakeCollectable already converted"); case UnretainedOutParameter: case RetainedOutParameter: @@ -806,13 +807,13 @@ case RefVal::Owned: assert(V.getCount() > 0); if (V.getCount() == 1) { - if (E == DecRefBridgedTransferred || + if (AE.getKind() == DecRefBridgedTransferred || V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) V = V ^ RefVal::NotOwned; else V = V ^ RefVal::Released; - } else if (E == DecRefAndStopTrackingHard) { + } else if (AE.getKind() == DecRefAndStopTrackingHard) { return removeRefBinding(state, sym); } @@ -821,14 +822,14 @@ case RefVal::NotOwned: if (V.getCount() > 0) { - if (E == DecRefAndStopTrackingHard) + if (AE.getKind() == DecRefAndStopTrackingHard) return removeRefBinding(state, sym); V = V - 1; } else if (V.getIvarAccessHistory() == RefVal::IvarAccessHistory::AccessedDirectly) { // Assume that the instance variable was holding on the object at // +1, and we just didn't know. - if (E == DecRefAndStopTrackingHard) + if (AE.getKind() == DecRefAndStopTrackingHard) return removeRefBinding(state, sym); V = V.releaseViaIvar() ^ RefVal::Released; } else { Index: clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp +++ clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp @@ -457,7 +457,6 @@ case Autorelease: case DecRefBridgedTransferred: case IncRef: - case IncRefMsg: case MakeCollectable: case UnretainedOutParameter: case RetainedOutParameter: @@ -468,9 +467,6 @@ case DecRef: case DecRefAndStopTrackingHard: return E.withKind(DecRefAndStopTrackingHard); - case DecRefMsg: - case DecRefMsgAndStopTrackingHard: - return E.withKind(DecRefMsgAndStopTrackingHard); case Dealloc: return E.withKind(Dealloc); } @@ -649,6 +645,8 @@ return None; } +// TODO: UnaryFuncKind is a very funny enum, it really should not exist: +// just pass the needed effect directly! const RetainSummary * RetainSummaryManager::getUnarySummary(const FunctionType* FT, UnaryFuncKind func) { @@ -662,7 +660,7 @@ if (!FTP || FTP->getNumParams() != 1) return getPersistentStopSummary(); - ArgEffect Effect; + ArgEffect Effect(DoNothing, ObjKind::CF); switch (func) { case cfretain: Effect = Effect.withKind(IncRef); break; case cfrelease: Effect = Effect.withKind(DecRef); break; @@ -778,7 +776,7 @@ const ParmVarDecl *pd, unsigned parm_idx, const FunctionDecl *FD, RetainSummaryTemplate &Template) { if (hasEnabledAttr(pd)) { - Template->addArg(AF, parm_idx, ArgEffect(DecRefMsg, ObjKind::ObjC)); + Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::ObjC)); return true; } else if (hasEnabledAttr(pd)) { Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::CF)); @@ -857,7 +855,7 @@ // Effects on the receiver. if (MD->hasAttr()) - Template->setReceiverEffect(ArgEffect(DecRefMsg, ObjKind::ObjC)); + Template->setReceiverEffect(ArgEffect(DecRef, ObjKind::ObjC)); // Effects on the parameters. unsigned parm_idx = 0; @@ -865,7 +863,7 @@ pi != pe; ++pi, ++parm_idx) { const ParmVarDecl *pd = *pi; if (pd->hasAttr()) { - Template->addArg(AF, parm_idx, ArgEffect(DecRefMsg, ObjKind::ObjC)); + Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::ObjC)); } else if (pd->hasAttr()) { Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::CF)); } else if (pd->hasAttr()) { @@ -931,7 +929,7 @@ break; case OMF_init: ResultEff = ObjCInitRetE; - ReceiverEff = ArgEffect(DecRefMsg, ObjKind::ObjC); + ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC); break; case OMF_alloc: case OMF_new: @@ -946,10 +944,10 @@ ReceiverEff = ArgEffect(Autorelease, ObjKind::ObjC); break; case OMF_retain: - ReceiverEff = ArgEffect(IncRefMsg, ObjKind::ObjC); + ReceiverEff = ArgEffect(IncRef, ObjKind::ObjC); break; case OMF_release: - ReceiverEff = ArgEffect(DecRefMsg, ObjKind::ObjC); + ReceiverEff = ArgEffect(DecRef, ObjKind::ObjC); break; case OMF_dealloc: ReceiverEff = ArgEffect(Dealloc, ObjKind::ObjC); @@ -1062,9 +1060,8 @@ ArgEffects ScratchArgs = AF.getEmptyMap(); // Create the "init" selector. It just acts as a pass-through for the // receiver. - const RetainSummary *InitSumm = getPersistentSummary(ObjCInitRetE, - ScratchArgs, - ArgEffect(DecRefMsg)); + const RetainSummary *InitSumm = getPersistentSummary( + ObjCInitRetE, ScratchArgs, ArgEffect(DecRef, ObjKind::ObjC)); addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm); // awakeAfterUsingCoder: behaves basically like an 'init' method. It @@ -1080,20 +1077,23 @@ // Create the "retain" selector. RetEffect NoRet = RetEffect::MakeNoRet(); - const RetainSummary *Summ = - getPersistentSummary(NoRet, ScratchArgs, ArgEffect(IncRefMsg)); + const RetainSummary *Summ = getPersistentSummary( + NoRet, ScratchArgs, ArgEffect(IncRef, ObjKind::ObjC)); addNSObjectMethSummary(GetNullarySelector("retain", Ctx), Summ); // Create the "release" selector. - Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(DecRefMsg)); + Summ = getPersistentSummary(NoRet, ScratchArgs, + ArgEffect(DecRef, ObjKind::ObjC)); addNSObjectMethSummary(GetNullarySelector("release", Ctx), Summ); // Create the -dealloc summary. - Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Dealloc)); + Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Dealloc, + ObjKind::ObjC)); addNSObjectMethSummary(GetNullarySelector("dealloc", Ctx), Summ); // Create the "autorelease" selector. - Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Autorelease)); + Summ = getPersistentSummary(NoRet, ScratchArgs, ArgEffect(Autorelease, + ObjKind::ObjC)); addNSObjectMethSummary(GetNullarySelector("autorelease", Ctx), Summ); // For NSWindow, allocated objects are (initially) self-owned.