r283093 - [analyzer] Add extra notes to ObjCDeallocChecker

Artem Dergachev via cfe-commits cfe-commits at lists.llvm.org
Mon Oct 3 01:03:52 PDT 2016


Author: dergachev
Date: Mon Oct  3 03:03:51 2016
New Revision: 283093

URL: http://llvm.org/viewvc/llvm-project?rev=283093&view=rev
Log:
[analyzer] Add extra notes to ObjCDeallocChecker

The report is now highlighting instance variables and properties
referenced by the warning message with the help of the
extra notes feature recently introduced in r283092.

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

Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
    cfe/trunk/test/Analysis/DeallocMissingRelease.m
    cfe/trunk/test/Analysis/PR2978.m
    cfe/trunk/test/Analysis/properties.m

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp?rev=283093&r1=283092&r2=283093&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp Mon Oct  3 03:03:51 2016
@@ -107,6 +107,9 @@ class ObjCDeallocChecker
   std::unique_ptr<BugType> ExtraReleaseBugType;
   std::unique_ptr<BugType> MistakenDeallocBugType;
 
+  static constexpr const char *MsgDeclared = "Property is declared here";
+  static constexpr const char *MsgSynthesized = "Property is synthesized here";
+
 public:
   ObjCDeallocChecker();
 
@@ -128,6 +131,9 @@ public:
   void checkEndFunction(CheckerContext &Ctx) const;
 
 private:
+  void addNoteForDecl(std::unique_ptr<BugReport> &BR, StringRef Msg,
+                           const Decl *D) const;
+
   void diagnoseMissingReleases(CheckerContext &C) const;
 
   bool diagnoseExtraRelease(SymbolRef ReleasedValue, const ObjCMethodCall &M,
@@ -489,6 +495,18 @@ ProgramStateRef ObjCDeallocChecker::chec
   return State;
 }
 
+/// Add an extra note piece describing a declaration that is important
+/// for understanding the bug report.
+void ObjCDeallocChecker::addNoteForDecl(std::unique_ptr<BugReport> &BR,
+                                             StringRef Msg,
+                                             const Decl *D) const {
+  ASTContext &ACtx = D->getASTContext();
+  SourceManager &SM = ACtx.getSourceManager();
+  PathDiagnosticLocation Pos = PathDiagnosticLocation::createBegin(D, SM);
+  if (Pos.isValid() && Pos.asLocation().isValid())
+    BR->addNote(Msg, Pos, D->getSourceRange());
+}
+
 /// Report any unreleased instance variables for the current instance being
 /// dealloced.
 void ObjCDeallocChecker::diagnoseMissingReleases(CheckerContext &C) const {
@@ -586,6 +604,9 @@ void ObjCDeallocChecker::diagnoseMissing
     std::unique_ptr<BugReport> BR(
         new BugReport(*MissingReleaseBugType, OS.str(), ErrNode));
 
+    addNoteForDecl(BR, MsgDeclared, PropDecl);
+    addNoteForDecl(BR, MsgSynthesized, PropImpl);
+
     C.emitReport(std::move(BR));
   }
 
@@ -689,11 +710,12 @@ bool ObjCDeallocChecker::diagnoseExtraRe
          );
 
   const ObjCImplDecl *Container = getContainingObjCImpl(C.getLocationContext());
-  OS << "The '" << *PropImpl->getPropertyIvarDecl()
-     << "' ivar in '" << *Container;
+  const ObjCIvarDecl *IvarDecl = PropImpl->getPropertyIvarDecl();
+  OS << "The '" << *IvarDecl << "' ivar in '" << *Container;
 
+  bool ReleasedByCIFilterDealloc = isReleasedByCIFilterDealloc(PropImpl);
 
-  if (isReleasedByCIFilterDealloc(PropImpl)) {
+  if (ReleasedByCIFilterDealloc) {
     OS << "' will be released by '-[CIFilter dealloc]' but also released here";
   } else {
     OS << "' was synthesized for ";
@@ -710,6 +732,10 @@ bool ObjCDeallocChecker::diagnoseExtraRe
       new BugReport(*ExtraReleaseBugType, OS.str(), ErrNode));
   BR->addRange(M.getOriginExpr()->getSourceRange());
 
+  addNoteForDecl(BR, MsgDeclared, PropDecl);
+  if (!ReleasedByCIFilterDealloc)
+    addNoteForDecl(BR, MsgSynthesized, PropImpl);
+
   C.emitReport(std::move(BR));
 
   return true;

Modified: cfe/trunk/test/Analysis/DeallocMissingRelease.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/DeallocMissingRelease.m?rev=283093&r1=283092&r2=283093&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/DeallocMissingRelease.m (original)
+++ cfe/trunk/test/Analysis/DeallocMissingRelease.m Mon Oct  3 03:03:51 2016
@@ -80,6 +80,9 @@
 
 @interface MyPropertyClass1 : NSObject
 @property (copy) NSObject *ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation MyPropertyClass1
@@ -93,6 +96,9 @@
 
 @interface MyPropertyClass2 : NSObject
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation MyPropertyClass2
@@ -108,10 +114,16 @@
   NSObject *_ivar;
 }
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation MyPropertyClass3
 @synthesize ivar = _ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is synthesized here}}
+#endif
 - (void)dealloc
 {
 #if NON_ARC
@@ -125,6 +137,9 @@
   void (^_blockPropertyIvar)(void);
 }
 @property (copy) void (^blockProperty)(void);
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @property (copy) void (^blockProperty2)(void);
 @property (copy) void (^blockProperty3)(void);
 
@@ -132,6 +147,9 @@
 
 @implementation MyPropertyClass4
 @synthesize blockProperty = _blockPropertyIvar;
+#if NON_ARC
+// expected-note at -2 {{Property is synthesized here}}
+#endif
 - (void)dealloc
 {
 #if NON_ARC
@@ -163,10 +181,16 @@
   NSObject *_ivar;
 }
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation MyPropertyClassWithReturnInDealloc
 @synthesize ivar = _ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is synthesized here}}
+#endif
 - (void)dealloc
 {
   return;
@@ -182,12 +206,18 @@
   MyPropertyClassWithReleaseInOtherInstance *_other;
 }
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 
 -(void)releaseIvars;
 @end
 
 @implementation MyPropertyClassWithReleaseInOtherInstance
 @synthesize ivar = _ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is synthesized here}}
+#endif
 
 -(void)releaseIvars; {
 #if NON_ARC
@@ -208,10 +238,16 @@
   NSObject *_ivar;
 }
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation MyPropertyClassWithNeitherReturnNorSuperDealloc
 @synthesize ivar = _ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is synthesized here}}
+#endif
 - (void)dealloc
 {
 }
@@ -246,6 +282,9 @@
   BOOL _ivar1;
 }
 @property (retain) NSObject *ivar2;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation ClassWithControlFlowInRelease
@@ -287,6 +326,9 @@
 
 @interface ClassWithNildOutIvar : NSObject
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation ClassWithNildOutIvar
@@ -305,6 +347,9 @@
 
 @interface ClassWithUpdatedIvar : NSObject
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation ClassWithUpdatedIvar
@@ -349,6 +394,9 @@
 @property (retain) NSObject *propNilledOutInFunction;
 
 @property (retain) NSObject *ivarNeverReleased;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 - (void)invalidateInMethod;
 @end
 
@@ -425,6 +473,9 @@ void NilOutPropertyHelper(ClassWithDeall
 
 @interface ClassWhereSelfEscapesViaSynthesizedPropertyAccess : NSObject
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @property (retain) NSObject *otherIvar;
 @end
 
@@ -442,6 +493,9 @@ void NilOutPropertyHelper(ClassWithDeall
 
 @interface ClassWhereSelfEscapesViaCallToSystem : NSObject
 @property (retain) NSObject *ivar1;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @property (retain) NSObject *ivar2;
 @property (retain) NSObject *ivar3;
 @property (retain) NSObject *ivar4;
@@ -536,6 +590,9 @@ void ReleaseMe(id arg);
 
 @interface SuperClassOfClassWithInlinedSuperDealloc : NSObject
 @property (retain) NSObject *propInSuper;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation SuperClassOfClassWithInlinedSuperDealloc
@@ -548,6 +605,9 @@ void ReleaseMe(id arg);
 
 @interface ClassWithInlinedSuperDealloc : SuperClassOfClassWithInlinedSuperDealloc
 @property (retain) NSObject *propInSub;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation ClassWithInlinedSuperDealloc
@@ -605,6 +665,9 @@ void ReleaseMe(id arg);
 
 @interface SuperClassOfClassThatEscapesBeforeInliningSuper : NSObject
 @property (retain) NSObject *propInSuper;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation SuperClassOfClassThatEscapesBeforeInliningSuper
@@ -794,6 +857,9 @@ __attribute__((objc_root_class))
 
 @property(retain) NSObject *inputIvar;
 @property(retain) NSObject *nonInputIvar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @property(retain) NSObject *inputAutoSynthesizedIvar;
 @property(retain) NSObject *inputExplicitlySynthesizedToNonPrefixedIvar;
 @property(retain) NSObject *nonPrefixedPropertyBackedByExplicitlySynthesizedPrefixedIvar;
@@ -803,6 +869,9 @@ __attribute__((objc_root_class))
 @implementation ImmediateSubCIFilter
 @synthesize inputIvar = inputIvar;
 @synthesize nonInputIvar = nonInputIvar;
+#if NON_ARC
+// expected-note at -2 {{Property is synthesized here}}
+#endif
 @synthesize inputExplicitlySynthesizedToNonPrefixedIvar = notPrefixedButBackingPrefixedProperty;
 @synthesize nonPrefixedPropertyBackedByExplicitlySynthesizedPrefixedIvar = inputPrefixedButBackingNonPrefixedProperty;
 
@@ -841,6 +910,9 @@ __attribute__((objc_root_class))
 }
 
 @property(retain) NSObject *inputIvar;
+#if NON_ARC
+// expected-note at -2 {{Property is declared here}}
+#endif
 @end
 
 @implementation OverreleasingCIFilter

Modified: cfe/trunk/test/Analysis/PR2978.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/PR2978.m?rev=283093&r1=283092&r2=283093&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/PR2978.m (original)
+++ cfe/trunk/test/Analysis/PR2978.m Mon Oct  3 03:03:51 2016
@@ -29,22 +29,22 @@
   id _nonPropertyIvar;
 }
 @property(retain) id X;
- at property(retain) id Y;
- at property(assign) id Z;
+ at property(retain) id Y; // expected-note{{Property is declared here}}
+ at property(assign) id Z; // expected-note{{Property is declared here}}
 @property(assign) id K;
 @property(weak) id L;
 @property(readonly) id N;
 @property(retain) id M;
 @property(weak) id P;
- at property(weak) id Q;
+ at property(weak) id Q; // expected-note{{Property is declared here}}
 @property(retain) id R;
- at property(weak, readonly) id S;
+ at property(weak, readonly) id S; // expected-note{{Property is declared here}}
 
 @property(assign, readonly) id T; // Shadowed in class extension
 @property(assign) id U;
 
 @property(retain) id V;
- at property(retain) id W;
+ at property(retain) id W; // expected-note{{Property is declared here}}
 -(id) O;
 -(void) setO: (id) arg;
 @end
@@ -56,16 +56,16 @@
 
 @implementation MyClass
 @synthesize X = _X;
- at synthesize Y = _Y;
- at synthesize Z = _Z;
+ at synthesize Y = _Y; // expected-note{{Property is synthesized here}}
+ at synthesize Z = _Z; // expected-note{{Property is synthesized here}}
 @synthesize K = _K;
 @synthesize L = _L;
 @synthesize N = _N;
 @synthesize M = _M;
- at synthesize Q = _Q;
+ at synthesize Q = _Q; // expected-note{{Property is synthesized here}}
 @synthesize R = _R;
 @synthesize V = _V;
- at synthesize W = _W;
+ at synthesize W = _W; // expected-note{{Property is synthesized here}}
 
 -(id) O{ return 0; }
 -(void) setO:(id)arg { }

Modified: cfe/trunk/test/Analysis/properties.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/properties.m?rev=283093&r1=283092&r2=283093&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/properties.m (original)
+++ cfe/trunk/test/Analysis/properties.m Mon Oct  3 03:03:51 2016
@@ -134,11 +134,17 @@ NSNumber* numberFromMyNumberProperty(MyN
   NSString *_name;
 }
 @property (retain) NSString * name;
+#if !__has_feature(objc_arc)
+// expected-note at -2 {{Property is declared here}}
+#endif
 @property (assign) id friend;
 @end
 
 @implementation Person
 @synthesize name = _name;
+#if !__has_feature(objc_arc)
+// expected-note at -2 {{Property is synthesized here}}
+#endif
 
 -(void)dealloc {
 #if !__has_feature(objc_arc)




More information about the cfe-commits mailing list