Index: lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp +++ lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp @@ -420,13 +420,6 @@ RetEffect RE = Summ.getRetEffect(); 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) state = removeRefBinding(state, Sym); } @@ -1103,9 +1096,8 @@ WhitelistedSymbols.insert(SR->getSymbol()); } - for (InvalidatedSymbols::const_iterator I=invalidated->begin(), - E = invalidated->end(); I!=E; ++I) { - SymbolRef sym = *I; + for (SymbolRef sym : + llvm::make_range(invalidated->begin(), invalidated->end())) { if (WhitelistedSymbols.count(sym)) continue; // Remove any existing reference-count binding. Index: lib/StaticAnalyzer/Core/RetainSummaryManager.cpp =================================================================== --- lib/StaticAnalyzer/Core/RetainSummaryManager.cpp +++ lib/StaticAnalyzer/Core/RetainSummaryManager.cpp @@ -101,10 +101,11 @@ return true; for (ParmVarDecl *Param : MD->parameters()) { - QualType PT = Param->getType(); - if (CXXRecordDecl *RD = PT->getPointeeType()->getAsCXXRecordDecl()) - if (isOSObjectSubclass(RD)) - return true; + QualType PT = Param->getType()->getPointeeType(); + if (!PT.isNull()) + if (CXXRecordDecl *RD = PT->getAsCXXRecordDecl()) + if (isOSObjectSubclass(RD)) + return true; } return false; Index: test/Analysis/osobject-retain-release.cpp =================================================================== --- test/Analysis/osobject-retain-release.cpp +++ test/Analysis/osobject-retain-release.cpp @@ -2,10 +2,9 @@ struct OSMetaClass; -#define TRUSTED __attribute__((annotate("rc_ownership_trusted_implementation"))) -#define OS_CONSUME TRUSTED __attribute__((annotate("rc_ownership_consumed"))) -#define OS_RETURNS_RETAINED TRUSTED __attribute__((annotate("rc_ownership_returns_retained"))) -#define OS_RETURNS_NOT_RETAINED TRUSTED __attribute__((annotate("rc_ownership_returns_not_retained"))) +#define OS_CONSUME __attribute__((annotate("rc_ownership_consumed"))) +#define OS_RETURNS_RETAINED __attribute__((annotate("rc_ownership_returns_retained"))) +#define OS_RETURNS_NOT_RETAINED __attribute__((annotate("rc_ownership_returns_not_retained"))) #define OSTypeID(type) (type::metaClass) @@ -62,6 +61,37 @@ // expected-note@-1{{Object leaked}} } +struct ArrayOwner : public OSObject { + OSArray *arr; + ArrayOwner(OSArray *arr) : arr(arr) {} + + static ArrayOwner* create(OSArray *arr) { + return new ArrayOwner(arr); + } + + OSArray *getArray() { + return arr; + } + + OSArray *createArray() { + return OSArray::withCapacity(10); + } + + OSArray *createArraySourceUnknown(); + + OSArray *getArraySourceUnknown(); +}; + +void check_confusing_getters() { + OSArray *arr = OSArray::withCapacity(10); + + ArrayOwner *AO = ArrayOwner::create(arr); + AO->getArray(); + + AO->release(); + arr->release(); +} + void check_rc_consumed() { OSArray *arr = OSArray::withCapacity(10); OSArray::consumeArray(arr); @@ -140,31 +170,17 @@ arr->release(); // 0 } -struct ArrayOwner { - OSArray *arr; - - OSArray *getArray() { - return arr; - } - - OSArray *createArray() { - return OSArray::withCapacity(10); - } - - OSArray *createArraySourceUnknown(); - - OSArray *getArraySourceUnknown(); -}; - unsigned int no_warning_on_getter(ArrayOwner *owner) { OSArray *arr = owner->getArray(); return arr->getCount(); } unsigned int warn_on_overrelease(ArrayOwner *owner) { - OSArray *arr = owner->getArray(); // expected-note{{function call returns an OSObject of type struct OSArray * with a +0 retain count}} - arr->release(); // expected-warning{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}} - // expected-note@-1{{Incorrect decrement of the reference count of an object that is not owned at this point by the caller}} + // FIXME: summaries are not applied in case the source of the getter/setter + // is known. + // rdar://45681203 + OSArray *arr = owner->getArray(); + arr->release(); return arr->getCount(); }