diff options
| author | George Karpenkov <ekarpenkov@apple.com> | 2019-01-18 03:12:35 +0000 |
|---|---|---|
| committer | George Karpenkov <ekarpenkov@apple.com> | 2019-01-18 03:12:35 +0000 |
| commit | a0425f3a2fe5f00f82e8792d63eb1274839d7a78 (patch) | |
| tree | 6d03b4a1b9fa286ecdcceeca76c34c941cbb0b5f /clang/lib | |
| parent | c6795e07f03ddc8a9ab3e7dd86da713a7a8003c5 (diff) | |
| download | bcm5719-llvm-a0425f3a2fe5f00f82e8792d63eb1274839d7a78.tar.gz bcm5719-llvm-a0425f3a2fe5f00f82e8792d63eb1274839d7a78.zip | |
[analyzer] [RetainCountChecker] Smart pointer support.
rdar://47323216
Differential Revision: https://reviews.llvm.org/D56817
llvm-svn: 351508
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp | 14 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp | 16 |
2 files changed, 28 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp index 8fa2a777414..62ac6f6591f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountChecker.cpp @@ -529,6 +529,13 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ, C.addTransition(state); } +static bool isSmartPtrField(const MemRegion *MR) { + const auto *TR = dyn_cast<TypedValueRegion>( + cast<SubRegion>(MR)->getSuperRegion()); + return TR && RetainSummaryManager::isKnownSmartPointer(TR->getValueType()); +} + + /// A value escapes in these possible cases: /// /// - binding to something that is not a memory region. @@ -536,10 +543,15 @@ void RetainCountChecker::processSummaryOfInlined(const RetainSummary &Summ, /// - binding to a variable that has a destructor attached using CleanupAttr /// /// We do not currently model what happens when a symbol is -/// assigned to a struct field, so be conservative here and let the symbol go. +/// assigned to a struct field, unless it is a known smart pointer +/// implementation, about which we know that it is inlined. /// FIXME: This could definitely be improved upon. static bool shouldEscapeRegion(const MemRegion *R) { + if (isSmartPtrField(R)) + return false; + const auto *VR = dyn_cast<VarRegion>(R); + if (!R->hasStackStorage() || !VR) return true; diff --git a/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp b/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp index 2e40cc33381..2eb422f6320 100644 --- a/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp @@ -146,7 +146,7 @@ static bool isSubclass(const Decl *D, } static bool isOSObjectSubclass(const Decl *D) { - return isSubclass(D, "OSObject"); + return isSubclass(D, "OSMetaClassBase"); } static bool isOSObjectDynamicCast(StringRef S) { @@ -199,6 +199,20 @@ static bool isOSObjectRelated(const CXXMethodDecl *MD) { return false; } +bool +RetainSummaryManager::isKnownSmartPointer(QualType QT) { + QT = QT.getCanonicalType(); + const auto *RD = QT->getAsCXXRecordDecl(); + if (!RD) + return false; + const IdentifierInfo *II = RD->getIdentifier(); + if (II && II->getName() == "smart_ptr") + if (const auto *ND = dyn_cast<NamespaceDecl>(RD->getDeclContext())) + if (ND->getNameAsString() == "os") + return true; + return false; +} + const RetainSummary * RetainSummaryManager::getSummaryForOSObject(const FunctionDecl *FD, StringRef FName, QualType RetTy) { |

