[analyzer] Re-add custom OSIterator rule for RetainCountChecker

Turns out the rule is quite ubiquitous.

Revert of https://reviews.llvm.org/D53628

llvm-svn: 345747
This commit is contained in:
George Karpenkov 2018-10-31 17:38:46 +00:00
parent 6fd5c86d98
commit 83fb536ff9
2 changed files with 19 additions and 4 deletions

View File

@ -69,6 +69,10 @@ static bool isOSObjectDynamicCast(StringRef S) {
return S == "safeMetaCast"; return S == "safeMetaCast";
} }
static bool isOSIteratorSubclass(const Decl *D) {
return isSubclass(D, "OSIterator");
}
static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) { static bool hasRCAnnotation(const Decl *D, StringRef rcAnnotation) {
for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) { for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {
if (Ann->getAnnotation() == rcAnnotation) if (Ann->getAnnotation() == rcAnnotation)
@ -235,11 +239,12 @@ RetainSummaryManager::generateSummary(const FunctionDecl *FD,
if (isOSObjectDynamicCast(II->getName())) if (isOSObjectDynamicCast(II->getName()))
return getDefaultSummary(); return getDefaultSummary();
// All objects returned with functions starting with "get" are getters. // All objects returned with functions *not* starting with
if (II->getName().startswith("get")) { // get, or iterators, are returned at +1.
return getOSSummaryGetRule(FD); if (!II->getName().startswith("get") || isOSIteratorSubclass(PD)) {
} else {
return getOSSummaryCreateRule(FD); return getOSSummaryCreateRule(FD);
} else {
return getOSSummaryGetRule(FD);
} }
} }
} }

View File

@ -23,6 +23,9 @@ struct OSObject {
static const OSMetaClass * const metaClass; static const OSMetaClass * const metaClass;
}; };
struct OSIterator : public OSObject {
};
struct OSArray : public OSObject { struct OSArray : public OSObject {
unsigned int getCount(); unsigned int getCount();
@ -33,6 +36,8 @@ struct OSArray : public OSObject {
return nullptr; return nullptr;
} }
OSIterator * getIterator();
static OS_RETURNS_NOT_RETAINED OSArray *MaskedGetter(); static OS_RETURNS_NOT_RETAINED OSArray *MaskedGetter();
static OS_RETURNS_RETAINED OSArray *getOoopsActuallyCreate(); static OS_RETURNS_RETAINED OSArray *getOoopsActuallyCreate();
@ -49,6 +54,11 @@ struct OSMetaClassBase {
static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta); static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta);
}; };
void check_custom_iterator_rule(OSArray *arr) {
OSIterator *it = arr->getIterator();
it->release();
}
void check_no_invalidation() { void check_no_invalidation() {
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}} OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}}
OtherStruct::doNothingToArray(arr); OtherStruct::doNothingToArray(arr);