summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
diff options
context:
space:
mode:
authorDevin Coughlin <dcoughlin@apple.com>2016-10-12 23:57:05 +0000
committerDevin Coughlin <dcoughlin@apple.com>2016-10-12 23:57:05 +0000
commit0bd37a1a367dffdf4513a3068c2f51290366e3f3 (patch)
tree810a173ae3dcc60f2be38e238bc062c0e04401f8 /clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
parent1255c1965655d9200559ba33ddd7bd2b11847dab (diff)
downloadbcm5719-llvm-0bd37a1a367dffdf4513a3068c2f51290366e3f3.tar.gz
bcm5719-llvm-0bd37a1a367dffdf4513a3068c2f51290366e3f3.zip
[analyzer] DeallocChecker: Don't warn about directly-set IBOutlet ivars on macOS
On macOS (but not iOS), if an ObjC property has no setter, the nib-loading code for an IBOutlet is documented as directly setting the backing ivar without retaining the value -- even if the property is 'retain'. This resulted in false positives from the DeallocChecker for code that did not release such ivars in -dealloc. To avoid these false positives, treat IBOutlet ivars that back a property without a setter as having an unknown release requirement in macOS. rdar://problem/28507353 llvm-svn: 284084
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp31
1 files changed, 31 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp b/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
index 4fece1c7fff..1c8ca0f4295 100644
--- a/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
@@ -34,6 +34,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/ExprObjC.h"
#include "clang/Basic/LangOptions.h"
+#include "clang/Basic/TargetInfo.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h"
#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h"
@@ -180,6 +181,7 @@ private:
bool classHasSeparateTeardown(const ObjCInterfaceDecl *ID) const;
bool isReleasedByCIFilterDealloc(const ObjCPropertyImplDecl *PropImpl) const;
+ bool isNibLoadedIvarWithoutRetain(const ObjCPropertyImplDecl *PropImpl) const;
};
} // End anonymous namespace.
@@ -935,6 +937,9 @@ ReleaseRequirement ObjCDeallocChecker::getDeallocReleaseRequirement(
if (isReleasedByCIFilterDealloc(PropImpl))
return ReleaseRequirement::MustNotReleaseDirectly;
+ if (isNibLoadedIvarWithoutRetain(PropImpl))
+ return ReleaseRequirement::Unknown;
+
return ReleaseRequirement::MustRelease;
case ObjCPropertyDecl::Weak:
@@ -1091,6 +1096,32 @@ bool ObjCDeallocChecker::isReleasedByCIFilterDealloc(
return false;
}
+/// Returns whether the ivar backing the property is an IBOutlet that
+/// has its value set by nib loading code without retaining the value.
+///
+/// On macOS, if there is no setter, the nib-loading code sets the ivar
+/// directly, without retaining the value,
+///
+/// On iOS and its derivatives, the nib-loading code will call
+/// -setValue:forKey:, which retains the value before directly setting the ivar.
+bool ObjCDeallocChecker::isNibLoadedIvarWithoutRetain(
+ const ObjCPropertyImplDecl *PropImpl) const {
+ const ObjCIvarDecl *IvarDecl = PropImpl->getPropertyIvarDecl();
+ if (!IvarDecl->hasAttr<IBOutletAttr>())
+ return false;
+
+ const llvm::Triple &Target =
+ IvarDecl->getASTContext().getTargetInfo().getTriple();
+
+ if (!Target.isMacOSX())
+ return false;
+
+ if (PropImpl->getPropertyDecl()->getSetterMethodDecl())
+ return false;
+
+ return true;
+}
+
void ento::registerObjCDeallocChecker(CheckerManager &Mgr) {
const LangOptions &LangOpts = Mgr.getLangOpts();
// These checker only makes sense under MRR.
OpenPOWER on IntegriCloud