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: + 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 { 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 "); @@ -1666,8 +1666,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.cpp =================================================================== --- clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp +++ clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp @@ -580,7 +580,7 @@ if (!Pointee) return State; - switch (Effect) { + switch (Effect.getKind()) { case UnretainedOutParameter: State = setRefBinding(State, Pointee, RefVal::makeNotOwned(ObjKind::CF, PointeeTy)); @@ -709,9 +709,10 @@ ProgramStateRef RetainCountChecker::updateSymbol(ProgramStateRef state, SymbolRef sym, - RefVal V, ArgEffect E, RefVal::Kind &hasErr, + RefVal V, ArgEffect AE, RefVal::Kind &hasErr, CheckerContext &C) const { bool IgnoreRetainMsg = (bool)C.getASTContext().getLangOpts().ObjCAutoRefCount; + ArgEffectKind E = AE.getKind(); switch (E) { default: break; Index: clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp =================================================================== --- clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp +++ clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp @@ -220,7 +220,7 @@ // 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); @@ -228,7 +228,7 @@ 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); @@ -367,16 +367,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); + DoNothing, ArgEffect(E, ObjKind::CF)); } } @@ -449,7 +450,7 @@ //===----------------------------------------------------------------------===// static ArgEffect getStopTrackingHardEquivalent(ArgEffect E) { - switch (E) { + switch (E.getKind()) { case DoNothing: case Autorelease: case DecRefBridgedTransferred: @@ -461,15 +462,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 +490,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); } @@ -661,10 +662,10 @@ 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); @@ -881,7 +882,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. @@ -1130,8 +1131,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));