malhar1995 updated this revision to Diff 105292.
malhar1995 added a comment.

Corrected one of the two test-cases added in the last-diff.


Repository:
  rL LLVM

https://reviews.llvm.org/D34937

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

Index: test/Analysis/retain-release-inline.m
===================================================================
--- test/Analysis/retain-release-inline.m
+++ test/Analysis/retain-release-inline.m
@@ -12,7 +12,7 @@
 //
 // It includes the basic definitions for the test cases below.
 //===----------------------------------------------------------------------===//
-
+#define NULL 0
 typedef unsigned int __darwin_natural_t;
 typedef unsigned long uintptr_t;
 typedef unsigned int uint32_t;
@@ -267,6 +267,10 @@
 
 extern CFStringRef CFStringCreateWithCStringNoCopy(CFAllocatorRef alloc, const char *cStr, CFStringEncoding encoding, CFAllocatorRef contentsDeallocator);
 
+typedef struct {
+  int ref;
+} isl_basic_map;
+
 //===----------------------------------------------------------------------===//
 // Test cases.
 //===----------------------------------------------------------------------===//
@@ -285,6 +289,7 @@
   foo(s);
   bar(s);
 }
+
 void test_neg() {
   NSString *s = [[NSString alloc] init]; // no-warning  
   foo(s);
@@ -294,6 +299,48 @@
   bar(s);
 }
 
+__attribute__((cf_returns_retained)) isl_basic_map *isl_basic_map_copy(isl_basic_map *bmap);
+__attribute__((cf_returns_retained)) isl_basic_map *isl_basic_map_cow(__attribute__((cf_consumed)) isl_basic_map *bmap);
+isl_basic_map *isl_basic_map_decrement_reference_count(__attribute__((cf_consumed)) isl_basic_map *bmap);
+void free(void *);
+
+__attribute__((annotate("rc_ownership_trusted_implementation"))) __attribute__((cf_returns_retained)) isl_basic_map *test_use_after_release_with_trusted_implementation_annotate_attribute(__attribute__((cf_consumed)) isl_basic_map *bmap) {
+  // After this call, 'temp' has a +1 reference count.
+  isl_basic_map *temp = isl_basic_map_copy(bmap);
+  // After this call, 'bmap' has a +1 reference count.
+  bmap = isl_basic_map_cow(bmap);
+  // After this call, 'bmap' has a +0 reference count.
+  isl_basic_map_decrement_reference_count(bmap);
+  isl_basic_map_decrement_reference_count(bmap); // no-warning {{A 'use-after-release' warning is not raised here as this function has 'rc_ownership_trusted_implementation' annotate attribute}}
+  return temp;
+}
+
+isl_basic_map *isl_basic_map_free(__attribute__((cf_consumed)) isl_basic_map *bmap) {
+  if (!bmap)
+    return NULL;
+
+  if (--bmap->ref > 0)
+    return NULL;
+
+  free(bmap);
+  return NULL;
+}
+
+__attribute__((cf_returns_retained)) isl_basic_map *test_leak_with_trusted_implementation_annotate_attribute(__attribute__((cf_consumed)) isl_basic_map *bmap) {
+  // After this call, 'temp' has a +1 reference count.
+  isl_basic_map *temp = isl_basic_map_copy(bmap);
+  // After this call, 'bmap' has a +1 reference count.
+  bmap = isl_basic_map_cow(bmap); // no-warning {{A 'leak' warning is not raised here as 'foo_bar' (annotated with 'rc_ownership_trusted_implementation') is on the call-stack}}
+  // After this call, assuming the predicate of the second if branch to be true, 'bmap' has a +1 reference count.
+  isl_basic_map_free(bmap);
+  return temp;
+}
+
+__attribute__((annotate("rc_ownership_trusted_implementation"))) __attribute__((cf_returns_retained)) isl_basic_map *foo_bar(__attribute__((cf_consumed)) isl_basic_map *bmap) {
+  bmap = test_leak_with_trusted_implementation_annotate_attribute(bmap);
+  return bmap;
+}
+
 //===----------------------------------------------------------------------===//
 // Test returning retained and not-retained values.
 //===----------------------------------------------------------------------===//
Index: lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
+++ lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
@@ -1894,6 +1894,23 @@
   return SFC->getAnalysisDeclContext()->isBodyAutosynthesized();
 }
 
+/// Returns true if any declaration on the call-stack contains
+/// 'rc_ownership_trusted_implementation' annotate attribute.
+bool isTrustedReferenceCountImplementation(const LocationContext *LCtx) {
+  while (LCtx) {
+    if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LCtx)) {
+      const Decl *D = SFC->getDecl();
+      for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) {
+        if (Ann->getAnnotation() == "rc_ownership_trusted_implementation") {
+          return true;
+        }
+      }
+    }
+    LCtx = LCtx->getParent();
+  }
+  return false;
+}
+
 std::shared_ptr<PathDiagnosticPiece>
 CFRefReportVisitor::VisitNode(const ExplodedNode *N, const ExplodedNode *PrevN,
                               BugReporterContext &BRC, BugReport &BR) {
@@ -3345,11 +3362,13 @@
   }
 
   assert(BT);
-  auto report = std::unique_ptr<BugReport>(
-      new CFRefReport(*BT, C.getASTContext().getLangOpts(), C.isObjCGCEnabled(),
-                      SummaryLog, N, Sym));
-  report->addRange(ErrorRange);
-  C.emitReport(std::move(report));
+  if (!isTrustedReferenceCountImplementation(N->getLocationContext())) {
+    auto report = std::unique_ptr<BugReport>(
+        new CFRefReport(*BT, C.getASTContext().getLangOpts(),
+                        C.isObjCGCEnabled(), SummaryLog, N, Sym));
+    report->addRange(ErrorRange);
+    C.emitReport(std::move(report));
+  }
 }
 
 //===----------------------------------------------------------------------===//
@@ -3579,9 +3598,10 @@
         if (N) {
           const LangOptions &LOpts = C.getASTContext().getLangOpts();
           bool GCEnabled = C.isObjCGCEnabled();
-          C.emitReport(std::unique_ptr<BugReport>(new CFRefLeakReport(
-              *getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled,
-              SummaryLog, N, Sym, C, IncludeAllocationLine)));
+          if (!isTrustedReferenceCountImplementation(N->getLocationContext()))
+            C.emitReport(std::unique_ptr<BugReport>(new CFRefLeakReport(
+                *getLeakAtReturnBug(LOpts, GCEnabled), LOpts, GCEnabled,
+                SummaryLog, N, Sym, C, IncludeAllocationLine)));
         }
       }
     }
@@ -3606,9 +3626,10 @@
           if (!returnNotOwnedForOwned)
             returnNotOwnedForOwned.reset(new ReturnedNotOwnedForOwned(this));
 
-          C.emitReport(std::unique_ptr<BugReport>(new CFRefReport(
-              *returnNotOwnedForOwned, C.getASTContext().getLangOpts(),
-              C.isObjCGCEnabled(), SummaryLog, N, Sym)));
+          if (!isTrustedReferenceCountImplementation(N->getLocationContext()))
+            C.emitReport(std::unique_ptr<BugReport>(new CFRefReport(
+                *returnNotOwnedForOwned, C.getASTContext().getLangOpts(),
+                C.isObjCGCEnabled(), SummaryLog, N, Sym)));
         }
       }
     }
@@ -3811,9 +3832,10 @@
       overAutorelease.reset(new OverAutorelease(this));
 
     const LangOptions &LOpts = Ctx.getASTContext().getLangOpts();
-    Ctx.emitReport(std::unique_ptr<BugReport>(
-        new CFRefReport(*overAutorelease, LOpts, /* GCEnabled = */ false,
-                        SummaryLog, N, Sym, os.str())));
+    if (!isTrustedReferenceCountImplementation(N->getLocationContext()))
+      Ctx.emitReport(std::unique_ptr<BugReport>(
+          new CFRefReport(*overAutorelease, LOpts, /* GCEnabled = */ false,
+                          SummaryLog, N, Sym, os.str())));
   }
 
   return nullptr;
@@ -3865,9 +3887,10 @@
                           : getLeakAtReturnBug(LOpts, GCEnabled);
       assert(BT && "BugType not initialized.");
 
-      Ctx.emitReport(std::unique_ptr<BugReport>(
-          new CFRefLeakReport(*BT, LOpts, GCEnabled, SummaryLog, N, *I, Ctx,
-                              IncludeAllocationLine)));
+      if (!isTrustedReferenceCountImplementation(N->getLocationContext()))
+        Ctx.emitReport(std::unique_ptr<BugReport>(
+            new CFRefLeakReport(*BT, LOpts, GCEnabled, SummaryLog, N, *I, Ctx,
+                                IncludeAllocationLine)));
     }
   }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to