]> granicus.if.org Git - clang/commitdiff
[analyzer] Fix a bug in RetainCountDiagnostics while printing a note on mismatched...
authorGeorge Karpenkov <ekarpenkov@apple.com>
Fri, 21 Dec 2018 02:16:23 +0000 (02:16 +0000)
committerGeorge Karpenkov <ekarpenkov@apple.com>
Fri, 21 Dec 2018 02:16:23 +0000 (02:16 +0000)
Previously, we were not printing a note at all if at least one of the parameters was not annotated.

rdar://46888422

Differential Revision: https://reviews.llvm.org/D55972

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@349875 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/RetainCountChecker/RetainCountDiagnostics.cpp
test/Analysis/osobject-retain-release.cpp

index 9dff0be138520dad3f30a55c7ba9c5ae88ed7f36..8fdd105f189562b3aade854a8fb407d867648a6a 100644 (file)
@@ -268,7 +268,7 @@ annotateConsumedSummaryMismatch(const ExplodedNode *N,
     const ParmVarDecl *PVD = Parameters[I];
 
     if (!PVD->hasAttr<OSConsumedAttr>())
-      return nullptr;
+      continue;
 
     if (SymbolRef SR = Call->getArgSVal(I).getAsLocSymbol()) {
       const RefVal *CountBeforeCall = getRefBinding(CN->getState(), SR);
@@ -311,10 +311,9 @@ CFRefReportVisitor::VisitNode(const ExplodedNode *N,
                               BugReporterContext &BRC, BugReport &BR) {
   const SourceManager &SM = BRC.getSourceManager();
   CallEventManager &CEMgr = BRC.getStateManager().getCallEventManager();
-  if (auto CE = N->getLocationAs<CallExitBegin>()) {
+  if (auto CE = N->getLocationAs<CallExitBegin>())
     if (auto PD = annotateConsumedSummaryMismatch(N, *CE, SM, CEMgr))
       return PD;
-  }
 
   // FIXME: We will eventually need to handle non-statement-based events
   // (__attribute__((cleanup))).
index c8bc4aeaa0a3c3dc72310fdcc3bfea35622d7647..2efd20709bb59c808e10b577e7fd695eb64b5b5f 100644 (file)
@@ -93,6 +93,15 @@ struct OSMetaClassBase {
 void escape(void *);
 bool coin();
 
+bool os_consume_violation_two_args(OS_CONSUME OSObject *obj, bool extra) {
+  if (coin()) { // expected-note{{Assuming the condition is false}}
+                // expected-note@-1{{Taking false branch}}
+    escape(obj);
+    return true;
+  }
+  return false; // expected-note{{Parameter 'obj' is marked as consuming, but the function does not consume the reference}}
+}
+
 bool os_consume_violation(OS_CONSUME OSObject *obj) {
   if (coin()) { // expected-note{{Assuming the condition is false}}
                 // expected-note@-1{{Taking false branch}}
@@ -113,6 +122,13 @@ void use_os_consume_violation() {
 } // expected-note{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
   // expected-warning@-1{{Potential leak of an object stored into 'obj'}}
 
+void use_os_consume_violation_two_args() {
+  OSObject *obj = new OSObject; // expected-note{{Operator 'new' returns an OSObject of type OSObject with a +1 retain count}}
+  os_consume_violation_two_args(obj, coin()); // expected-note{{Calling 'os_consume_violation_two_args'}}
+                             // expected-note@-1{{Returning from 'os_consume_violation_two_args'}}
+} // expected-note{{Object leaked: object allocated and stored into 'obj' is not referenced later in this execution path and has a retain count of +1}}
+  // expected-warning@-1{{Potential leak of an object stored into 'obj'}}
+
 void use_os_consume_ok() {
   OSObject *obj = new OSObject;
   os_consume_ok(obj);