Index: clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h =================================================================== --- clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h +++ clang/include/clang/StaticAnalyzer/Core/RetainSummaryManager.h @@ -52,9 +52,7 @@ 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,28 @@ DecRefMsgAndStopTrackingHard }; +/// An ArgEffect summarizes the retain count behavior on an argument or receiver +/// to a function or method. +class ArgEffect { +private: + 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 +238,9 @@ 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 +285,8 @@ template <> struct FoldingSetTrait { 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 { @@ -377,8 +400,8 @@ 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 +570,31 @@ 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(); Index: clang/lib/ARCMigrate/ObjCMT.cpp =================================================================== --- clang/lib/ARCMigrate/ObjCMT.cpp +++ clang/lib/ARCMigrate/ObjCMT.cpp @@ -1484,13 +1484,13 @@ pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) { const ParmVarDecl *pd = *pi; ArgEffect AE = AEArgs[i]; - if (AE == DecRef && !pd->hasAttr() && + if (AE.getKind() == DecRef && !pd->hasAttr() && NSAPIObj->isMacroDefined("CF_CONSUMED")) { edit::Commit commit(*Editor); commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); Editor->commit(commit); } - else if (AE == DecRefMsg && !pd->hasAttr() && + else if (AE.getKind() == DecRefMsg && !pd->hasAttr() && NSAPIObj->isMacroDefined("NS_CONSUMED")) { edit::Commit commit(*Editor); commit.insertBefore(pd->getLocation(), "NS_CONSUMED "); @@ -1536,13 +1536,13 @@ 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()) + if (AE.getKind() == DecRef /*CFConsumed annotated*/ || + AE.getKind() == IncRef) { + if (AE.getKind() == DecRef && !pd->hasAttr()) 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 @@ pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { const ParmVarDecl *pd = *pi; ArgEffect AE = AEArgs[i]; - if (AE == DecRef && !pd->hasAttr() && + if (AE.getKind() == DecRef && !pd->hasAttr() && NSAPIObj->isMacroDefined("CF_CONSUMED")) { edit::Commit commit(*Editor); commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); @@ -1626,13 +1626,14 @@ return; CallEffects CE = CallEffects::getEffect(MethodDecl); - bool MethodIsReturnAnnotated = (MethodDecl->hasAttr() || - MethodDecl->hasAttr() || - MethodDecl->hasAttr() || - MethodDecl->hasAttr() || - MethodDecl->hasAttr()); - - if (CE.getReceiver() == DecRefMsg && + bool MethodIsReturnAnnotated = + (MethodDecl->hasAttr() || + MethodDecl->hasAttr() || + MethodDecl->hasAttr() || + MethodDecl->hasAttr() || + MethodDecl->hasAttr()); + + if (CE.getReceiver().getKind() == DecRefMsg && !MethodDecl->hasAttr() && MethodDecl->getMethodFamily() != OMF_init && MethodDecl->getMethodFamily() != OMF_release && @@ -1666,8 +1667,8 @@ pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { const ParmVarDecl *pd = *pi; ArgEffect AE = AEArgs[i]; - if ((AE == DecRef && !pd->hasAttr()) || AE == IncRef || - !AuditedType(pd->getType())) { + if ((AE.getKind() == DecRef && !pd->hasAttr()) || + AE.getKind() == IncRef || !AuditedType(pd->getType())) { AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated); return; } 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, ArgEffect E, RefVal::Kind &hasErr, + RefVal V, ArgEffectKind 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,7 +248,7 @@ if (!BE) return; - ArgEffect AE = IncRef; + ArgEffectKind AE = IncRef; switch (BE->getBridgeKind()) { case OBC_Bridge: @@ -534,7 +534,7 @@ 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 @@ // Evaluate the effect on the message receiver. if (const auto *MsgInvocation = dyn_cast(&CallOrMsg)) { if (SymbolRef Sym = MsgInvocation->getReceiverSVal().getAsLocSymbol()) { - if (Summ.getReceiverEffect() == StopTrackingHard) { + if (Summ.getReceiverEffect().getKind() == StopTrackingHard) { state = removeRefBinding(state, Sym); } } @@ -566,7 +566,7 @@ static ProgramStateRef updateOutParameter(ProgramStateRef State, SVal ArgVal, - ArgEffect Effect) { + ArgEffectKind Effect) { auto *ArgRegion = dyn_cast_or_null(ArgVal.getAsRegion()); if (!ArgRegion) return State; @@ -611,7 +611,7 @@ 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 @@ 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 @@ } 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(), + state = updateSymbol(state, Sym, *T, Summ.getThisEffect().getKind(), hasErr, C); if (hasErr) { ErrorRange = MCall->getOriginExpr()->getSourceRange(); @@ -707,10 +707,11 @@ } } -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 @@ 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)) { Index: clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp +++ clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp @@ -48,7 +48,9 @@ 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. Index: clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp +++ clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp @@ -201,8 +201,8 @@ // Part of: . 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 @@ FName == "IOOpenFirmwarePathMatching"))) { // Part of . (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: // 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 . (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: // Eventually this can be improved by recognizing that the pixel @@ -239,38 +239,38 @@ // 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: // 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: // 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") { // - The analyzer currently doesn't have @@ -279,20 +279,21 @@ // - 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 @@ // "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 @@ 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 @@ //===----------------------------------------------------------------------===// static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) { - switch (E) { + switch (E.getKind()) { case DoNothing: case Autorelease: case DecRefBridgedTransferred: @@ -461,15 +464,15 @@ 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 @@ 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 @@ 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 @@ 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 @@ RetainSummaryManager::getCFSummaryGetRule(const FunctionDecl *FD) { return getPersistentSummary(RetEffect::MakeNotOwned(ObjKind::CF), ArgEffects(AF.getEmptyMap()), - DoNothing, DoNothing); + ArgEffect(DoNothing), ArgEffect(DoNothing)); } @@ -775,19 +778,24 @@ const ParmVarDecl *pd, unsigned parm_idx, const FunctionDecl *FD, RetainSummaryTemplate &Template) { if (hasEnabledAttr(pd)) { - Template->addArg(AF, parm_idx, DecRefMsg); + Template->addArg(AF, parm_idx, ArgEffect(DecRefMsg, ObjKind::ObjC)); + return true; + } else if (hasEnabledAttr(pd)) { + Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::CF)); return true; - } else if (hasEnabledAttr(pd) || - hasEnabledAttr(pd) || - hasRCAnnotation(pd, "rc_ownership_consumed")) { - Template->addArg(AF, parm_idx, DecRef); + } else if (hasEnabledAttr(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(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 @@ 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 @@ Template->setRetEffect(*RetE); if (hasEnabledAttr(FD)) - Template->setThisEffect(DecRef); + Template->setThisEffect(ArgEffect(DecRef, ObjKind::OS)); } void @@ -848,7 +857,7 @@ // Effects on the receiver. if (MD->hasAttr()) - Template->setReceiverEffect(DecRefMsg); + Template->setReceiverEffect(ArgEffect(DecRefMsg, ObjKind::ObjC)); // Effects on the parameters. unsigned parm_idx = 0; @@ -856,19 +865,23 @@ pi != pe; ++pi, ++parm_idx) { const ParmVarDecl *pd = *pi; if (pd->hasAttr()) { - Template->addArg(AF, parm_idx, DecRefMsg); - } else if (pd->hasAttr() || pd->hasAttr()) { - Template->addArg(AF, parm_idx, DecRef); + Template->addArg(AF, parm_idx, ArgEffect(DecRefMsg, ObjKind::ObjC)); + } else if (pd->hasAttr()) { + Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::CF)); + } else if (pd->hasAttr()) { + Template->addArg(AF, parm_idx, ArgEffect(DecRef, ObjKind::OS)); } else if (pd->hasAttr()) { 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()) { 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 @@ 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 @@ break; case OMF_init: ResultEff = ObjCInitRetE; - ReceiverEff = DecRefMsg; + ReceiverEff = ArgEffect(DecRefMsg, ObjKind::ObjC); break; case OMF_alloc: case OMF_new: @@ -930,16 +943,16 @@ 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 @@ 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 @@ 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 @@ // 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 @@ // 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 @@ // Thus, we need to track an NSWindow's display status. // This is tracked in . // 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 @@ /*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));