summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorGeorge Karpenkov <ekarpenkov@apple.com>2019-01-18 03:12:35 +0000
committerGeorge Karpenkov <ekarpenkov@apple.com>2019-01-18 03:12:35 +0000
commita0425f3a2fe5f00f82e8792d63eb1274839d7a78 (patch)
tree6d03b4a1b9fa286ecdcceeca76c34c941cbb0b5f /clang/lib
parentc6795e07f03ddc8a9ab3e7dd86da713a7a8003c5 (diff)
downloadbcm5719-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.cpp14
-rw-r--r--clang/lib/StaticAnalyzer/Core/RetainSummaryManager.cpp16
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) {
OpenPOWER on IntegriCloud