malhar1995 updated this revision to Diff 105160.
malhar1995 added a comment.
Herald added a subscriber: eraman.

Changed function name from 'isAnnotatedToSkipDiagnostics' to 
'isTrustedReferenceCountImplementation'.
Added some test-cases to test/Analysis/retain-release-inline.m.
Applied clang-format to the changed code.


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
@@ -285,6 +285,14 @@
   foo(s);
   bar(s);
 }
+
+__attribute__((annotate("rc_ownership_trusted_implementation"))) void test_with_trusted_implementation_annotate_attribute() {
+  NSString *s = [[NSString alloc] init]; // no-warning {{Ideally, a "leak" warning should've been raised here. But, as this function contains "rc_ownership_trusted_implementation" annotate attribute, the warning is suppressed}}
+  foo(s);
+  foo(s);
+  bar(s);
+}
+
 void test_neg() {
   NSString *s = [[NSString alloc] init]; // no-warning  
   foo(s);
@@ -294,6 +302,34 @@
   bar(s);
 }
 
+void test2() {
+  NSString *s = [[NSString alloc] init];
+  foo(s);
+  foo(s);
+  bar(s);
+  bar(s);
+  bar(s);
+  [s release]; // expected-warning {{Reference-counted object is used after it is released}}
+}
+
+__attribute__((annotate("rc_ownership_trusted_implementation"))) void test2_with_trusted_implementation_annotate_attribute() {
+  NSString *s = [[NSString alloc] init];
+  foo(s);
+  foo(s);
+  bar(s);
+  bar(s);
+  bar(s);
+  [s release]; // no-warning {{Ideally, a "use-after-release" warning should've been raised here. But, as this function contains "rc_ownership_trusted_implementation" annotate attribute, the warning is suppressed}}
+}
+
+void foo_bar() {
+  NSString *s = [[NSString alloc] init]; // no-warning {{Ideally, a "leak" warning should've been raised. But, as "test3" on the callstack has annotate attribute "rc_ownership_trusted_implementation", the warning is suppressed}}
+}
+
+__attribute__((annotate("rc_ownership_trusted_implementation"))) void test3_with_trusted_implementation_annotate_attribute() {
+  foo_bar();
+}
+
 //===----------------------------------------------------------------------===//
 // Test returning retained and not-retained values.
 //===----------------------------------------------------------------------===//
@@ -343,6 +379,14 @@
   CFRelease(str);
 }
 
+__attribute__((annotate("rc_ownership_trusted_implementation"))) void test_test_return_inline_2_with_trusted_implementation_annotate_attribute(char *bytes) {
+  CFStringRef str = CFStringCreateWithCStringNoCopy(0, bytes, NSNEXTSTEPStringEncoding, 0); // no-warning {{Ideally, a "leak" warning should've been raised here. But, as this function contains "rc_ownership_trusted_implementation" annotate attribute, the warning is suppressed}}
+  // After this call, 'str' really has +2 reference count.
+  CFStringRef str2 = test_return_inline(str);
+  // After this call, 'str' really has a +1 reference count.
+  CFRelease(str);
+}
+
 extern CFStringRef getString(void);
 CFStringRef testCovariantReturnType(void) __attribute__((cf_returns_retained));
 
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