diff options
author | Artem Dergachev <artem.dergachev@gmail.com> | 2019-04-26 02:05:18 +0000 |
---|---|---|
committer | Artem Dergachev <artem.dergachev@gmail.com> | 2019-04-26 02:05:18 +0000 |
commit | a4ed8a5aedb2d6c3524a57ff37bb7d4ca4732e56 (patch) | |
tree | 5ab6b8054164050d74cfa86b0d0f3c983c5c6654 /lib/Analysis/RetainSummaryManager.cpp | |
parent | 4968e43c2681452bed09ba11ad3583f746cce35a (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.cpp | 35 |
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); |