initIdentifierInfoAndSelectors(Mgr.getASTContext());
const ObjCInterfaceDecl *ID = D->getClassInterface();
+ // If the class is known to have a lifecycle with a separate teardown method
+ // then it may not require a -dealloc method.
+ if (classHasSeparateTeardown(ID))
+ return;
// Does the class contain any synthesized properties that are retainable?
// If not, skip the check entirely.
- bool containsRetainedSynthesizedProperty = false;
+ const ObjCPropertyImplDecl *PropImplRequiringRelease = nullptr;
+ bool HasOthers = false;
for (const auto *I : D->property_impls()) {
if (getDeallocReleaseRequirement(I) == ReleaseRequirement::MustRelease) {
- containsRetainedSynthesizedProperty = true;
- break;
+ if (!PropImplRequiringRelease)
+ PropImplRequiringRelease = I;
+ else {
+ HasOthers = true;
+ break;
+ }
}
}
- if (!containsRetainedSynthesizedProperty)
- return;
-
- // If the class is known to have a lifecycle with a separate teardown method
- // then it may not require a -dealloc method.
- if (classHasSeparateTeardown(ID))
+ if (!PropImplRequiringRelease)
return;
const ObjCMethodDecl *MD = nullptr;
std::string Buf;
llvm::raw_string_ostream OS(Buf);
- OS << "Objective-C class '" << *D << "' lacks a 'dealloc' instance method";
+ OS << "'" << *D << "' lacks a 'dealloc' instance method but "
+ << "must release '" << *PropImplRequiringRelease->getPropertyIvarDecl()
+ << "'";
+ if (HasOthers)
+ OS << " and others";
PathDiagnosticLocation DLoc =
PathDiagnosticLocation::createBegin(D, BR.getSourceManager());
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.Dealloc -fblocks %s 2>&1 | FileCheck -check-prefix=CHECK %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.Dealloc -fblocks -triple x86_64-apple-darwin10 -fobjc-arc %s 2>&1 | FileCheck -check-prefix=CHECK-ARC -allow-empty '--implicit-check-not=error:' '--implicit-check-not=warning:' %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.Dealloc -fblocks -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=alpha.osx.cocoa.Dealloc -fblocks -verify -triple x86_64-apple-darwin10 -fobjc-arc %s
+
+#define NON_ARC !__has_feature(objc_arc)
+
+// No diagnostics expected under ARC.
+#if !NON_ARC
+ // expected-no-diagnostics
+#endif
typedef signed char BOOL;
@protocol NSObject
@property (copy) NSObject *ivar;
@end
-// CHECK: MissingDealloc.m:[[@LINE+1]]:1: warning: Objective-C class 'MissingDeallocWithCopyProperty' lacks a 'dealloc' instance method
+#if NON_ARC
+// expected-warning@+2{{'MissingDeallocWithCopyProperty' lacks a 'dealloc' instance method but must release '_ivar'}}
+#endif
@implementation MissingDeallocWithCopyProperty
@end
@property (retain) NSObject *ivar;
@end
-// CHECK: MissingDealloc.m:[[@LINE+1]]:1: warning: Objective-C class 'MissingDeallocWithRetainProperty' lacks a 'dealloc' instance method
+#if NON_ARC
+// expected-warning@+2{{'MissingDeallocWithRetainProperty' lacks a 'dealloc' instance method but must release '_ivar'}}
+#endif
@implementation MissingDeallocWithRetainProperty
@end
+@interface MissingDeallocWithMultipleProperties : NSObject
+@property (retain) NSObject *ivar1;
+@property (retain) NSObject *ivar2;
+@end
+
+#if NON_ARC
+// expected-warning@+2{{'MissingDeallocWithMultipleProperties' lacks a 'dealloc' instance method but must release '_ivar1' and others}}
+#endif
+@implementation MissingDeallocWithMultipleProperties
+@end
+
@interface MissingDeallocWithIVarAndRetainProperty : NSObject {
NSObject *_ivar2;
}
@property (retain) NSObject *ivar1;
@end
-// CHECK: MissingDealloc.m:[[@LINE+1]]:1: warning: Objective-C class 'MissingDeallocWithIVarAndRetainProperty' lacks a 'dealloc' instance method
+#if NON_ARC
+// expected-warning@+2{{'MissingDeallocWithIVarAndRetainProperty' lacks a 'dealloc' instance method but must release '_ivar1'}}
+#endif
@implementation MissingDeallocWithIVarAndRetainProperty
@end
@property (readonly,retain) NSObject *ivar;
@end
-// CHECK: MissingDealloc.m:[[@LINE+1]]:1: warning: Objective-C class 'MissingDeallocWithReadOnlyRetainedProperty' lacks a 'dealloc' instance method
+#if NON_ARC
+// expected-warning@+2{{'MissingDeallocWithReadOnlyRetainedProperty' lacks a 'dealloc' instance method but must release '_ivar'}}
+#endif
@implementation MissingDeallocWithReadOnlyRetainedProperty
@end