r345100 - [analyzer] Do not stop tracking CXX methods touching OSObject.
George Karpenkov via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 23 16:11:50 PDT 2018
Author: george.karpenkov
Date: Tue Oct 23 16:11:50 2018
New Revision: 345100
URL: http://llvm.org/viewvc/llvm-project?rev=345100&view=rev
Log:
[analyzer] Do not stop tracking CXX methods touching OSObject.
Trust generalized annotations for OSObject.
Differential Revision: https://reviews.llvm.org/D53550
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
cfe/trunk/test/Analysis/osobject-retain-release.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp?rev=345100&r1=345099&r2=345100&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp Tue Oct 23 16:11:50 2018
@@ -45,7 +45,7 @@ ProgramStateRef removeRefBinding(Program
void RefVal::print(raw_ostream &Out) const {
if (!T.isNull())
- Out << "Tracked " << T.getAsString() << '/';
+ Out << "Tracked " << T.getAsString() << " | ";
switch (getKind()) {
default: llvm_unreachable("Invalid RefVal kind");
Modified: cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp?rev=345100&r1=345099&r2=345100&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp Tue Oct 23 16:11:50 2018
@@ -8,8 +8,8 @@
//===----------------------------------------------------------------------===//
//
// This file defines summaries implementation for retain counting, which
-// implements a reference count checker for Core Foundation and Cocoa
-// on (Mac OS X).
+// implements a reference count checker for Core Foundation, Cocoa
+// and OSObject (on Mac OS X).
//
//===----------------------------------------------------------------------===//
@@ -94,6 +94,22 @@ static bool isMakeCollectable(StringRef
return FName.contains_lower("MakeCollectable");
}
+/// A function is OSObject related if it is declared on a subclass
+/// of OSObject, or any of the parameters is a subclass of an OSObject.
+static bool isOSObjectRelated(const CXXMethodDecl *MD) {
+ if (isOSObjectSubclass(MD->getParent()))
+ return true;
+
+ for (ParmVarDecl *Param : MD->parameters()) {
+ QualType PT = Param->getType();
+ if (CXXRecordDecl *RD = PT->getPointeeType()->getAsCXXRecordDecl())
+ if (isOSObjectSubclass(RD))
+ return true;
+ }
+
+ return false;
+}
+
const RetainSummary *
RetainSummaryManager::generateSummary(const FunctionDecl *FD,
bool &AllowAnnotations) {
@@ -322,12 +338,10 @@ RetainSummaryManager::generateSummary(co
}
}
- if (isa<CXXMethodDecl>(FD)) {
-
- // Stop tracking arguments passed to C++ methods, as those might be
- // wrapping smart pointers.
- return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, StopTracking,
- DoNothing);
+ if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
+ if (!(TrackOSObjects && isOSObjectRelated(MD)))
+ return getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, StopTracking,
+ DoNothing);
}
return getDefaultSummary();
@@ -642,6 +656,8 @@ RetainSummaryManager::getRetEffectFromAn
if (D->hasAttr<CFReturnsNotRetainedAttr>())
return RetEffect::MakeNotOwned(RetEffect::CF);
+ else if (hasRCAnnotation(D, "rc_ownership_returns_not_retained"))
+ return RetEffect::MakeNotOwned(RetEffect::Generalized);
return None;
}
Modified: cfe/trunk/test/Analysis/osobject-retain-release.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/osobject-retain-release.cpp?rev=345100&r1=345099&r2=345100&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/osobject-retain-release.cpp (original)
+++ cfe/trunk/test/Analysis/osobject-retain-release.cpp Tue Oct 23 16:11:50 2018
@@ -2,6 +2,11 @@
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 OSTypeID(type) (type::metaClass)
#define OSDynamicCast(type, inst) \
@@ -21,14 +26,53 @@ struct OSArray : public OSObject {
unsigned int getCount();
static OSArray *withCapacity(unsigned int capacity);
+ static void consumeArray(OS_CONSUME OSArray * array);
+
+ static OSArray* consumeArrayHasCode(OS_CONSUME OSArray * array) {
+ return nullptr;
+ }
+
+ static OS_RETURNS_NOT_RETAINED OSArray *MaskedGetter();
+ static OS_RETURNS_RETAINED OSArray *getOoopsActuallyCreate();
+
static const OSMetaClass * const metaClass;
};
+struct OtherStruct {
+ static void doNothingToArray(OSArray *array);
+};
+
struct OSMetaClassBase {
static OSObject *safeMetaCast(const OSObject *inst, const OSMetaClass *meta);
};
+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}}
+ OtherStruct::doNothingToArray(arr);
+} // expected-warning{{Potential leak of an object stored into 'arr'}}
+ // expected-note at -1{{Object leaked}}
+
+void check_rc_consumed() {
+ OSArray *arr = OSArray::withCapacity(10);
+ OSArray::consumeArray(arr);
+}
+
+void check_rc_consume_temporary() {
+ OSArray::consumeArray(OSArray::withCapacity(10));
+}
+
+void check_rc_getter() {
+ OSArray *arr = OSArray::MaskedGetter();
+ (void)arr;
+}
+
+void check_rc_create() {
+ OSArray *arr = OSArray::getOoopsActuallyCreate();
+ arr->release();
+}
+
+
void check_dynamic_cast() {
OSArray *arr = OSDynamicCast(OSArray, OSObject::generateObject(1));
arr->release();
@@ -80,11 +124,6 @@ struct ArrayOwner {
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();
More information about the cfe-commits
mailing list