aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/RetainSummaryManager.cpp
diff options
context:
space:
mode:
authorArtem Dergachev <artem.dergachev@gmail.com>2019-04-26 02:05:18 +0000
committerArtem Dergachev <artem.dergachev@gmail.com>2019-04-26 02:05:18 +0000
commita4ed8a5aedb2d6c3524a57ff37bb7d4ca4732e56 (patch)
tree5ab6b8054164050d74cfa86b0d0f3c983c5c6654 /lib/Analysis/RetainSummaryManager.cpp
parent4968e43c2681452bed09ba11ad3583f746cce35a (diff)
[analyzer] RetainCount: Add a suppression for "the Matching rule".
In the OSObject universe there appears to be another slightly popular contract, apart from "create" and "get", which is "matching". It optionally consumes a "table" parameter and if a table is passed, it fills in the table and returns it at +0; otherwise, it creates a new table, fills it in and returns it at +1. For now suppress false positives by doing a conservative escape on all functions that end with "Matching", which is the naming convention that seems to be followed by all such methods. Differential Revision: https://reviews.llvm.org/D61161 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@359264 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/RetainSummaryManager.cpp')
-rw-r--r--lib/Analysis/RetainSummaryManager.cpp35
1 files changed, 21 insertions, 14 deletions
diff --git a/lib/Analysis/RetainSummaryManager.cpp b/lib/Analysis/RetainSummaryManager.cpp
index ae8ccb13ca..4f0fced60b 100644
--- a/lib/Analysis/RetainSummaryManager.cpp
+++ b/lib/Analysis/RetainSummaryManager.cpp
@@ -228,29 +228,36 @@ RetainSummaryManager::isKnownSmartPointer(QualType QT) {
const RetainSummary *
RetainSummaryManager::getSummaryForOSObject(const FunctionDecl *FD,
StringRef FName, QualType RetTy) {
+ assert(TrackOSObjects &&
+ "Requesting a summary for an OSObject but OSObjects are not tracked");
+
if (RetTy->isPointerType()) {
const CXXRecordDecl *PD = RetTy->getPointeeType()->getAsCXXRecordDecl();
if (PD && isOSObjectSubclass(PD)) {
- if (const IdentifierInfo *II = FD->getIdentifier()) {
- StringRef FuncName = II->getName();
- if (isOSObjectDynamicCast(FuncName) || isOSObjectThisCast(FuncName))
- return getDefaultSummary();
-
- // All objects returned with functions *not* starting with
- // get, or iterators, are returned at +1.
- if ((!FuncName.startswith("get") && !FuncName.startswith("Get")) ||
- isOSIteratorSubclass(PD)) {
- return getOSSummaryCreateRule(FD);
- } else {
- return getOSSummaryGetRule(FD);
- }
+ if (isOSObjectDynamicCast(FName) || isOSObjectThisCast(FName))
+ return getDefaultSummary();
+
+ // TODO: Add support for the slightly common *Matching(table) idiom.
+ // Cf. IOService::nameMatching() etc. - these function have an unusual
+ // contract of returning at +0 or +1 depending on their last argument.
+ if (FName.endswith("Matching")) {
+ return getPersistentStopSummary();
+ }
+
+ // All objects returned with functions *not* starting with 'get',
+ // or iterators, are returned at +1.
+ if ((!FName.startswith("get") && !FName.startswith("Get")) ||
+ isOSIteratorSubclass(PD)) {
+ return getOSSummaryCreateRule(FD);
+ } else {
+ return getOSSummaryGetRule(FD);
}
}
}
if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) {
const CXXRecordDecl *Parent = MD->getParent();
- if (TrackOSObjects && Parent && isOSObjectSubclass(Parent)) {
+ if (Parent && isOSObjectSubclass(Parent)) {
if (FName == "release" || FName == "taggedRelease")
return getOSSummaryReleaseRule(FD);