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