aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2012-02-25 02:09:09 +0000
committerTed Kremenek <kremenek@apple.com>2012-02-25 02:09:09 +0000
commite571578002fc3d4ebb654d2f31d2446d7cc1831d (patch)
tree4b2c379026a52686063c89fe469717d36c0d529d
parent63787f0343ab3546a5346a833e2f7485779f17e2 (diff)
RetainCountChecker: don't adjust the retain count when analyzing a ReturnStmt unless we are in the top-level call frame. We can do more later, but this makes the checker self-consistent (and fixes a crash).
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151426 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp15
-rw-r--r--test/Analysis/retain-release-inline.m14
2 files changed, 29 insertions, 0 deletions
diff --git a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
index b6f91d9fdc..3ae76e0203 100644
--- a/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -3069,8 +3069,23 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const {
// Handle return statements.
//===----------------------------------------------------------------------===//
+// Return true if the current LocationContext has no caller context.
+static bool inTopFrame(CheckerContext &C) {
+ const LocationContext *LC = C.getLocationContext();
+ return LC->getParent() == 0;
+}
+
void RetainCountChecker::checkPreStmt(const ReturnStmt *S,
CheckerContext &C) const {
+
+ // Only adjust the reference count if this is the top-level call frame,
+ // and not the result of inlining. In the future, we should do
+ // better checking even for inlined calls, and see if they match
+ // with their expected semantics (e.g., the method should return a retained
+ // object, etc.).
+ if (!inTopFrame(C))
+ return;
+
const Expr *RetE = S->getRetValue();
if (!RetE)
return;
diff --git a/test/Analysis/retain-release-inline.m b/test/Analysis/retain-release-inline.m
index 27c0971e2a..bfb00776ec 100644
--- a/test/Analysis/retain-release-inline.m
+++ b/test/Analysis/retain-release-inline.m
@@ -281,3 +281,17 @@ void test_neg() {
bar(s);
}
+//===----------------------------------------------------------------------===//
+// Test returning retained and not-retained values.
+//===----------------------------------------------------------------------===//
+
+id test_return_retained() {
+ return [[NSString alloc] init]; // expected-warning {{leak}}
+}
+
+void test_test_return_retained() {
+ id x = test_return_retained();
+ [x retain];
+ [x release];
+}
+