diff options
author | Ted Kremenek <kremenek@apple.com> | 2012-02-25 02:09:09 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2012-02-25 02:09:09 +0000 |
commit | ef31f376bb7f16f010db30359740a810c2681819 (patch) | |
tree | 5170e74ad73f183e9def69b3bd3e79cd7bc37cf5 | |
parent | d5862ce31774754cede1eec50535249f1b1e8c88 (diff) | |
download | bcm5719-llvm-ef31f376bb7f16f010db30359740a810c2681819.tar.gz bcm5719-llvm-ef31f376bb7f16f010db30359740a810c2681819.zip |
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).
llvm-svn: 151426
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp | 15 | ||||
-rw-r--r-- | clang/test/Analysis/retain-release-inline.m | 14 |
2 files changed, 29 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index b6f91d9fdca..3ae76e02030 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/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/clang/test/Analysis/retain-release-inline.m b/clang/test/Analysis/retain-release-inline.m index 27c0971e2a2..bfb00776ec1 100644 --- a/clang/test/Analysis/retain-release-inline.m +++ b/clang/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]; +} + |