]> granicus.if.org Git - clang/commitdiff
RetainCountChecker: don't adjust the retain count when analyzing a ReturnStmt unless...
authorTed Kremenek <kremenek@apple.com>
Sat, 25 Feb 2012 02:09:09 +0000 (02:09 +0000)
committerTed Kremenek <kremenek@apple.com>
Sat, 25 Feb 2012 02:09:09 +0000 (02:09 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151426 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
test/Analysis/retain-release-inline.m

index b6f91d9fdcab20ec644e809ba505db8647f643f3..3ae76e02030f74bbc3fef48a54ce9beed0d07eda 100644 (file)
@@ -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;
index 27c0971e2a251911a3f7a03b3bc839de443aa24b..bfb00776ec1661f35d9707588c8d25bf59783bed 100644 (file)
@@ -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];
+}
+