mirror of https://github.com/microsoft/clang.git
106 lines
3.8 KiB
C++
106 lines
3.8 KiB
C++
// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core,osx.cocoa.RetainCount -analyzer-config osx.cocoa.RetainCount:CheckOSObject=true -analyzer-output=text -verify %s
|
|
|
|
struct OSObject {
|
|
virtual void retain();
|
|
virtual void release();
|
|
|
|
virtual ~OSObject(){}
|
|
};
|
|
|
|
struct OSArray : public OSObject {
|
|
unsigned int getCount();
|
|
|
|
static OSArray *withCapacity(unsigned int capacity);
|
|
};
|
|
|
|
void use_after_release() {
|
|
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}}
|
|
arr->release(); // expected-note{{Object released}}
|
|
arr->getCount(); // expected-warning{{Reference-counted object is used after it is released}}
|
|
// expected-note@-1{{Reference-counted object is used after it is released}}
|
|
}
|
|
|
|
void potential_leak() {
|
|
OSArray *arr = OSArray::withCapacity(10); // expected-note{{Call to function 'withCapacity' returns an OSObject of type struct OSArray * with a +1 retain count}}
|
|
arr->retain(); // expected-note{{Reference count incremented. The object now has a +2 retain count}}
|
|
arr->release(); // expected-note{{Reference count decremented. The object now has a +1 retain count}}
|
|
arr->getCount();
|
|
} // expected-warning{{Potential leak of an object stored into 'arr'}}
|
|
// expected-note@-1{{Object leaked: object allocated and stored into 'arr' is not referenced later in this execution path and has a retain count of +1}}
|
|
|
|
void proper_cleanup() {
|
|
OSArray *arr = OSArray::withCapacity(10); // +1
|
|
arr->retain(); // +2
|
|
arr->release(); // +1
|
|
arr->getCount();
|
|
arr->release(); // 0
|
|
}
|
|
|
|
struct ArrayOwner {
|
|
OSArray *arr;
|
|
|
|
OSArray *getArray() {
|
|
return arr;
|
|
}
|
|
|
|
OSArray *createArray() {
|
|
return OSArray::withCapacity(10);
|
|
}
|
|
|
|
OSArray *createArraySourceUnknown();
|
|
|
|
OSArray *getArraySourceUnknown();
|
|
};
|
|
|
|
//unsigned int leak_on_create_no_release(ArrayOwner *owner) {
|
|
//OSArray *myArray =
|
|
|
|
//}
|
|
|
|
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}}
|
|
return arr->getCount();
|
|
}
|
|
|
|
unsigned int nowarn_on_release_of_created(ArrayOwner *owner) {
|
|
OSArray *arr = owner->createArray();
|
|
unsigned int out = arr->getCount();
|
|
arr->release();
|
|
return out;
|
|
}
|
|
|
|
unsigned int nowarn_on_release_of_created_source_unknown(ArrayOwner *owner) {
|
|
OSArray *arr = owner->createArraySourceUnknown();
|
|
unsigned int out = arr->getCount();
|
|
arr->release();
|
|
return out;
|
|
}
|
|
|
|
unsigned int no_warn_ok_release(ArrayOwner *owner) {
|
|
OSArray *arr = owner->getArray(); // +0
|
|
arr->retain(); // +1
|
|
arr->release(); // +0
|
|
return arr->getCount(); // no-warning
|
|
}
|
|
|
|
unsigned int warn_on_overrelease_with_unknown_source(ArrayOwner *owner) {
|
|
OSArray *arr = owner->getArraySourceUnknown(); // 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}}
|
|
return arr->getCount();
|
|
}
|
|
|
|
unsigned int ok_release_with_unknown_source(ArrayOwner *owner) {
|
|
OSArray *arr = owner->getArraySourceUnknown(); // +0
|
|
arr->retain(); // +1
|
|
arr->release(); // +0
|
|
return arr->getCount();
|
|
}
|