]> granicus.if.org Git - clang/commitdiff
[analyzer] Re-apply r283093 "Add extra notes to ObjCDeallocChecker"
authorArtem Dergachev <artem.dergachev@gmail.com>
Sat, 8 Oct 2016 10:53:00 +0000 (10:53 +0000)
committerArtem Dergachev <artem.dergachev@gmail.com>
Sat, 8 Oct 2016 10:53:00 +0000 (10:53 +0000)
The parent commit (r283092) was reverted before and now finally landed.

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

lib/StaticAnalyzer/Checkers/CheckObjCDealloc.cpp
test/Analysis/DeallocMissingRelease.m
test/Analysis/PR2978.m
test/Analysis/properties.m

index ffb0adc8d636b63129503ad8fb95f5b61a5d01d1..8fd36b828663a1689ea083a09b9464cffba0a0e7 100644 (file)
@@ -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::checkPointerEscape(
   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::diagnoseMissingReleases(CheckerContext &C) const {
     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::diagnoseExtraRelease(SymbolRef ReleasedValue,
          );
 
   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::diagnoseExtraRelease(SymbolRef ReleasedValue,
       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;
index 009e80151814e110f13c5b0bda1e835fd747666c..224f44c1d1ec89994b4924151de9162208712e13 100644 (file)
@@ -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
   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
   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);
 
 
 @implementation MyPropertyClass4
 @synthesize blockProperty = _blockPropertyIvar;
+#if NON_ARC
+// expected-note@-2 {{Property is synthesized here}}
+#endif
 - (void)dealloc
 {
 #if NON_ARC
   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;
   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
   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
 {
 }
   BOOL _ivar1;
 }
 @property (retain) NSObject *ivar2;
+#if NON_ARC
+// expected-note@-2 {{Property is declared here}}
+#endif
 @end
 
 @implementation ClassWithControlFlowInRelease
 
 @interface ClassWithNildOutIvar : NSObject
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note@-2 {{Property is declared here}}
+#endif
 @end
 
 @implementation ClassWithNildOutIvar
 
 @interface ClassWithUpdatedIvar : NSObject
 @property (retain) NSObject *ivar;
+#if NON_ARC
+// expected-note@-2 {{Property is declared here}}
+#endif
 @end
 
 @implementation ClassWithUpdatedIvar
 @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(ClassWithDeallocHelpers *o) {
 
 @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(ClassWithDeallocHelpers *o) {
 
 @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
index b609da5aac24ba678c33c4f7f51e95bb63733ac5..379fe6c0473674fd91dd233b8a58a12b2a274d19 100644 (file)
   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
 
 @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 { }
index b1305341e5d4b9cd232e8efc9f9d8a0299c3042f..55ea2c10be26f341de485d55372014be469f0a05 100644 (file)
@@ -134,11 +134,17 @@ NSNumber* numberFromMyNumberProperty(MyNumber* aMyNumber)
   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)