r180170 - [analyzer] IvarInvalidation: correctly handle cases where only partial invalidators exist
Anna Zaks
ganna at apple.com
Tue Apr 23 19:49:17 PDT 2013
Author: zaks
Date: Tue Apr 23 21:49:16 2013
New Revision: 180170
URL: http://llvm.org/viewvc/llvm-project?rev=180170&view=rev
Log:
[analyzer] IvarInvalidation: correctly handle cases where only partial invalidators exist
- If only partial invalidators exist and there are no full invalidators in @implementation, report every ivar that has
not been invalidated. (Previously, we reported the first Ivar in the list, which could actually have been invalidated
by a partial invalidator. The code assumed you cannot have only partial invalidators.)
- Do not report missing invalidation method declaration if a partial invalidation method declaration exists.
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
cfe/trunk/test/Analysis/objc_invalidation.m
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp?rev=180170&r1=180169&r2=180170&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp Tue Apr 23 21:49:16 2013
@@ -437,6 +437,7 @@ visit(const ObjCImplementationDecl *Impl
// Remove ivars invalidated by the partial invalidation methods. They do not
// need to be invalidated in the regular invalidation methods.
+ bool AtImplementationContainsAtLeastOnePartialInvalidationMethod = false;
for (MethodSet::iterator
I = PartialInfo.InvalidationMethods.begin(),
E = PartialInfo.InvalidationMethods.end(); I != E; ++I) {
@@ -446,6 +447,8 @@ visit(const ObjCImplementationDecl *Impl
const ObjCMethodDecl *D = ImplD->getMethod(InterfD->getSelector(),
InterfD->isInstanceMethod());
if (D && D->hasBody()) {
+ AtImplementationContainsAtLeastOnePartialInvalidationMethod = true;
+
bool CalledAnotherInvalidationMethod = false;
// The MethodCrowler is going to remove the invalidated ivars.
MethodCrawler(Ivars,
@@ -471,7 +474,7 @@ visit(const ObjCImplementationDecl *Impl
containsInvalidationMethod(InterfaceD, Info, /*LookForPartial*/ false);
// Report an error in case none of the invalidation methods are declared.
- if (!Info.needsInvalidation()) {
+ if (!Info.needsInvalidation() && !PartialInfo.needsInvalidation()) {
if (Filter.check_MissingInvalidationMethod)
reportNoInvalidationMethod(FirstIvarDecl, IvarToPopertyMap, InterfaceD,
/*MissingDeclaration*/ true);
@@ -520,9 +523,19 @@ visit(const ObjCImplementationDecl *Impl
}
// Report an error in case none of the invalidation methods are implemented.
- if (!AtImplementationContainsAtLeastOneInvalidationMethod)
- reportNoInvalidationMethod(FirstIvarDecl, IvarToPopertyMap, InterfaceD,
- /*MissingDeclaration*/ false);
+ if (!AtImplementationContainsAtLeastOneInvalidationMethod) {
+ if (AtImplementationContainsAtLeastOnePartialInvalidationMethod) {
+ // Warn on the ivars that were not invalidated by the prrtial
+ // invalidation methods.
+ for (IvarSet::const_iterator
+ I = Ivars.begin(), E = Ivars.end(); I != E; ++I)
+ reportIvarNeedsInvalidation(I->first, IvarToPopertyMap, 0);
+ } else {
+ // Otherwise, no invalidation methods were implemented.
+ reportNoInvalidationMethod(FirstIvarDecl, IvarToPopertyMap, InterfaceD,
+ /*MissingDeclaration*/ false);
+ }
+ }
}
void IvarInvalidationCheckerImpl::
@@ -551,19 +564,27 @@ reportNoInvalidationMethod(const ObjCIva
void IvarInvalidationCheckerImpl::
reportIvarNeedsInvalidation(const ObjCIvarDecl *IvarD,
- const IvarToPropMapTy &IvarToPopertyMap,
- const ObjCMethodDecl *MethodD) const {
+ const IvarToPropMapTy &IvarToPopertyMap,
+ const ObjCMethodDecl *MethodD) const {
SmallString<128> sbuf;
llvm::raw_svector_ostream os(sbuf);
printIvar(os, IvarD, IvarToPopertyMap);
os << "needs to be invalidated or set to nil";
- PathDiagnosticLocation MethodDecLocation =
- PathDiagnosticLocation::createEnd(MethodD->getBody(),
- BR.getSourceManager(),
- Mgr.getAnalysisDeclContext(MethodD));
- BR.EmitBasicReport(MethodD, "Incomplete invalidation",
- categories::CoreFoundationObjectiveC, os.str(),
- MethodDecLocation);
+ if (MethodD) {
+ PathDiagnosticLocation MethodDecLocation =
+ PathDiagnosticLocation::createEnd(MethodD->getBody(),
+ BR.getSourceManager(),
+ Mgr.getAnalysisDeclContext(MethodD));
+ BR.EmitBasicReport(MethodD, "Incomplete invalidation",
+ categories::CoreFoundationObjectiveC, os.str(),
+ MethodDecLocation);
+ } else {
+ BR.EmitBasicReport(IvarD, "Incomplete invalidation",
+ categories::CoreFoundationObjectiveC, os.str(),
+ PathDiagnosticLocation::createBegin(IvarD,
+ BR.getSourceManager()));
+
+ }
}
void IvarInvalidationCheckerImpl::MethodCrawler::markInvalidated(
Modified: cfe/trunk/test/Analysis/objc_invalidation.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/objc_invalidation.m?rev=180170&r1=180169&r2=180170&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/objc_invalidation.m (original)
+++ cfe/trunk/test/Analysis/objc_invalidation.m Tue Apr 23 21:49:16 2013
@@ -322,6 +322,47 @@ extern void NSLog(NSString *format, ...)
#endif
@end
+ at interface SomeNotInvalidatedInPartial : SomeInvalidationImplementingObject {
+ SomeInvalidationImplementingObject *Ivar1;
+ SomeInvalidationImplementingObject *Ivar2;
+#if RUN_IVAR_INVALIDATION
+ // expected-warning at -2 {{Instance variable Ivar2 needs to be invalidated or set to nil}}
+#endif
+}
+-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
+-(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial")));
+ at end
+ at implementation SomeNotInvalidatedInPartial {
+ SomeInvalidationImplementingObject *Ivar3;
+#if RUN_IVAR_INVALIDATION
+ // expected-warning at -2 {{Instance variable Ivar3 needs to be invalidated or set to nil}}
+#endif
+}
+-(void)partialInvalidator {
+ Ivar1 = 0;
+}
+-(void)partialInvalidatorCallsPartial {
+ [self partialInvalidator];
+}
+ at end
+
+ at interface OnlyPartialDeclsBase : NSObject
+-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
+ at end
+ at implementation OnlyPartialDeclsBase
+-(void)partialInvalidator {}
+ at end
+
+ at interface OnlyPartialDecls : OnlyPartialDeclsBase {
+ SomeInvalidationImplementingObject *Ivar1;
+#if RUN_IVAR_INVALIDATION
+ // expected-warning at -2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for OnlyPartialDecls}}
+#endif
+}
+ at end
+ at implementation OnlyPartialDecls
+ at end
+
// False negative.
@interface PartialCallsFull : SomeInvalidationImplementingObject {
SomeInvalidationImplementingObject *Ivar1;
More information about the cfe-commits
mailing list