Index: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp @@ -31,6 +31,7 @@ ProgramStateRef setRefBinding(ProgramStateRef State, SymbolRef Sym, RefVal Val) { + assert(Sym != nullptr); return State->set(Sym, Val); } @@ -418,17 +419,19 @@ } // Consult the summary for the return value. - SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol(); RetEffect RE = Summ.getRetEffect(); - if (const auto *MCall = dyn_cast(&CallOrMsg)) { - if (Optional updatedRefVal = - refValFromRetEffect(RE, MCall->getResultType())) { - state = setRefBinding(state, Sym, *updatedRefVal); + + if (SymbolRef Sym = CallOrMsg.getReturnValue().getAsSymbol()) { + if (const auto *MCall = dyn_cast(&CallOrMsg)) { + if (Optional updatedRefVal = + refValFromRetEffect(RE, MCall->getResultType())) { + state = setRefBinding(state, Sym, *updatedRefVal); + } } - } - if (RE.getKind() == RetEffect::NoRetHard && Sym) - state = removeRefBinding(state, Sym); + if (RE.getKind() == RetEffect::NoRetHard) + state = removeRefBinding(state, Sym); + } C.addTransition(state); } Index: cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp +++ cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp @@ -19,6 +19,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ParentMap.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" using namespace clang; using namespace ento; @@ -53,29 +54,19 @@ return Summ; } -static bool isOSObjectSubclass(QualType T); - -static bool isOSObjectSubclass(const CXXRecordDecl *RD) { - if (RD->getDeclName().getAsString() == "OSObject") - return true; - - const CXXRecordDecl *RDD = RD->getDefinition(); - if (!RDD) - return false; +static bool isSubclass(const Decl *D, + StringRef ClassName) { + using namespace ast_matchers; + DeclarationMatcher SubclassM = cxxRecordDecl(isSameOrDerivedFrom(ClassName)); + return !(match(SubclassM, *D, D->getASTContext()).empty()); +} - for (const CXXBaseSpecifier Spec : RDD->bases()) { - if (isOSObjectSubclass(Spec.getType())) - return true; - } - return false; +static bool isOSObjectSubclass(const Decl *D) { + return isSubclass(D, "OSObject"); } -/// \return Whether type represents an OSObject successor. -static bool isOSObjectSubclass(QualType T) { - if (const auto *RD = T->getAsCXXRecordDecl()) { - return isOSObjectSubclass(RD); - } - return false; +static bool isOSIteratorSubclass(const Decl *D) { + return isSubclass(D, "OSIterator"); } static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) { @@ -221,15 +212,22 @@ } if (RetTy->isPointerType()) { - if (TrackOSObjects && isOSObjectSubclass(RetTy->getPointeeType())) { + + const CXXRecordDecl *PD = RetTy->getPointeeType()->getAsCXXRecordDecl(); + if (TrackOSObjects && PD && isOSObjectSubclass(PD)) { if (const IdentifierInfo *II = FD->getIdentifier()) { - StringRef FuncName = II->getName(); - if (FuncName.contains_lower("with") - || FuncName.contains_lower("create") - || FuncName.contains_lower("copy")) + + // All objects returned with functions starting with "get" are getters. + if (II->getName().startswith("get")) { + + // ...except for iterators. + if (isOSIteratorSubclass(PD)) + return getOSSummaryCreateRule(FD); + return getOSSummaryGetRule(FD); + } else { return getOSSummaryCreateRule(FD); + } } - return getOSSummaryGetRule(FD); } // For CoreFoundation ('CF') types. @@ -279,11 +277,11 @@ if (const auto *MD = dyn_cast(FD)) { const CXXRecordDecl *Parent = MD->getParent(); - if (TrackOSObjects && isOSObjectSubclass(Parent)) { - if (isRelease(FD, FName)) + if (TrackOSObjects && Parent && isOSObjectSubclass(Parent)) { + if (FName == "release") return getOSSummaryReleaseRule(FD); - if (isRetain(FD, FName)) + if (FName == "retain") return getOSSummaryRetainRule(FD); } }