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@-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@-2 {{Property is declared here}}
+#endif
 @end
 
 @implementation MyPropertyClass2
@@ -108,10 +114,16 @@
   NSObject *_ivar;
 }
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note@-2 {{Property is declared here}}
+#endif
 @end
 
 @implementation MyPropertyClass3
 @synthesize ivar = _ivar;
+#if NON_ARC
+// expected-note@-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@-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@-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@-2 {{Property is declared here}}
+#endif
 @end
 
 @implementation MyPropertyClassWithReturnInDealloc
 @synthesize ivar = _ivar;
+#if NON_ARC
+// expected-note@-2 {{Property is synthesized here}}
+#endif
 - (void)dealloc
 {
   return;
@@ -182,12 +206,18 @@
   MyPropertyClassWithReleaseInOtherInstance *_other;
 }
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note@-2 {{Property is declared here}}
+#endif
 
 -(void)releaseIvars;
 @end
 
 @implementation MyPropertyClassWithReleaseInOtherInstance
 @synthesize ivar = _ivar;
+#if NON_ARC
+// expected-note@-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@-2 {{Property is declared here}}
+#endif
 @end
 
 @implementation MyPropertyClassWithNeitherReturnNorSuperDealloc
 @synthesize ivar = _ivar;
+#if NON_ARC
+// expected-note@-2 {{Property is synthesized here}}
+#endif
 - (void)dealloc
 {
 }
@@ -246,6 +282,9 @@
   BOOL _ivar1;
 }
 @property (retain) NSObject *ivar2;
+#if NON_ARC
+// expected-note@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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@-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;
-@property(retain) id Y;
-@property(assign) id Z;
+@property(retain) id Y; // expected-note{{Property is declared here}}
+@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;
-@property(weak) id Q;
+@property(weak) id Q; // expected-note{{Property is declared here}}
 @property(retain) id R;
-@property(weak, readonly) id S;
+@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;
-@property(retain) id W;
+@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;
-@synthesize Y = _Y;
-@synthesize Z = _Z;
+@synthesize Y = _Y; // expected-note{{Property is synthesized here}}
+@synthesize Z = _Z; // expected-note{{Property is synthesized here}}
 @synthesize K = _K;
 @synthesize L = _L;
 @synthesize N = _N;
 @synthesize M = _M;
-@synthesize Q = _Q;
+@synthesize Q = _Q; // expected-note{{Property is synthesized here}}
 @synthesize R = _R;
 @synthesize V = _V;
-@synthesize W = _W;
+@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@-2 {{Property is declared here}}
+#endif
 @property (assign) id friend;
 @end
 
 @implementation Person
 @synthesize name = _name;
+#if !__has_feature(objc_arc)
+// expected-note@-2 {{Property is synthesized here}}
+#endif
 
 -(void)dealloc {
 #if !__has_feature(objc_arc)


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to