From: Ted Kremenek Date: Mon, 27 Apr 2009 18:27:22 +0000 (+0000) Subject: Add new checker-specific attribute 'objc_ownership_cfretain'. This is the same X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4064de959853503d9b87065adac1b277fff8af20;p=clang Add new checker-specific attribute 'objc_ownership_cfretain'. This is the same as 'objc_ownership_cfretain' except that the method acts like a CFRetain instead of a [... retain] (important in GC modes). Checker support is wired up, but currently only for Objective-C message expressions (not function calls). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70218 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 549ba632a4..bde0c9b705 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -51,8 +51,9 @@ public: NonNull, ObjCException, ObjCNSObject, - ObjCOwnershipRetain, // Clang/Checker-specific. - ObjCOwnershipReturns, // Clang/Checker-specific. + ObjCOwnershipRetain, // Clang/Checker-specific. + ObjCOwnershipCFRetain, // Clang/Checker-specific. + ObjCOwnershipReturns, // Clang/Checker-specific. Overloadable, // Clang-specific Packed, Pure, @@ -600,6 +601,7 @@ public:\ }; // Checker-specific attributes. +DEF_SIMPLE_ATTR(ObjCOwnershipCFRetain) DEF_SIMPLE_ATTR(ObjCOwnershipRetain) DEF_SIMPLE_ATTR(ObjCOwnershipReturns) diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 6f4e2f2a08..616d293fd6 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -76,10 +76,11 @@ public: AT_nothrow, AT_nsobject, AT_objc_exception, - AT_objc_ownership_retain, // Clang-specific. - AT_objc_ownership_returns, // Clang-specific. + AT_objc_ownership_cfretain, // Clang-specific. + AT_objc_ownership_retain, // Clang-specific. + AT_objc_ownership_returns, // Clang-specific. AT_objc_gc, - AT_overloadable, // Clang-specific. + AT_overloadable, // Clang-specific. AT_packed, AT_pure, AT_regparm, diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index c2369abb2c..6223e7cdba 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -1104,7 +1104,11 @@ RetainSummaryManager::getMethodSummaryFromAnnotations(ObjCMethodDecl *MD) { ScratchArgs.push_back(std::make_pair(i, IncRefMsg)); hasArgEffect = true; } -} + else if ((*I)->getAttr()) { + ScratchArgs.push_back(std::make_pair(i, IncRef)); + hasArgEffect = true; + } + } if (!hasRetEffect && !hasArgEffect) return 0; diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 508d2ef170..50cc031225 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -475,6 +475,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(ObjCException); SIMPLE_ATTR(ObjCNSObject); + SIMPLE_ATTR(ObjCOwnershipCFRetain); SIMPLE_ATTR(ObjCOwnershipRetain); SIMPLE_ATTR(ObjCOwnershipReturns); SIMPLE_ATTR(Overloadable); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 82eb5dffe4..391a1f9165 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1420,6 +1420,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::ObjCException: case Attr::ObjCNSObject: + case Attr::ObjCOwnershipCFRetain: case Attr::ObjCOwnershipRetain: case Attr::ObjCOwnershipReturns: case Attr::Overloadable: diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index a9c552ba17..9e46159153 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -136,12 +136,17 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { case 21: if (!memcmp(Str, "objc_ownership_retain", 21)) return AT_objc_ownership_retain; + break; case 22: if (!memcmp(Str, "objc_ownership_returns", 22)) return AT_objc_ownership_returns; if (!memcmp(Str, "no_instrument_function", 22)) return AT_no_instrument_function; break; + case 23: + if (!memcmp(Str, "objc_ownership_cfretain", 23)) + return AT_objc_ownership_cfretain; + break; } return UnknownAttribute; } diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index c0a3b44c43..7bbfb26954 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1545,6 +1545,18 @@ static void HandleObjCOwnershipRetainAttr(Decl *d, const AttributeList &Attr, d->addAttr(::new (S.Context) ObjCOwnershipRetainAttr()); } +static void HandleObjCOwnershipCFRetainAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + + if (!isa(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + "objc_ownership_cfretain" << 4 /* parameter */; + return; + } + + d->addAttr(::new (S.Context) ObjCOwnershipCFRetainAttr()); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -1587,6 +1599,8 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { HandleObjCOwnershipRetainAttr(D, Attr, S); break; case AttributeList::AT_objc_ownership_returns: HandleObjCOwnershipReturnsAttr(D, Attr, S); break; + case AttributeList::AT_objc_ownership_cfretain: + HandleObjCOwnershipCFRetainAttr(D, Attr, S); break; case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; diff --git a/test/Analysis/retain-release-gc-only.m b/test/Analysis/retain-release-gc-only.m index b378b048ce..5bf0702cf5 100644 --- a/test/Analysis/retain-release-gc-only.m +++ b/test/Analysis/retain-release-gc-only.m @@ -93,3 +93,31 @@ void f3() { CFMakeCollectable(A); CFRetain(A); } + +//===----------------------------------------------------------------------===// +// Tests of ownership attributes. +//===----------------------------------------------------------------------===// + +@interface TestOwnershipAttr : NSObject +- (NSString*) returnsAnOwnedString __attribute__((objc_ownership_returns)); +- (void) myRetain:(id)__attribute__((objc_ownership_retain))obj; +- (void) myCFRetain:(id)__attribute__((objc_ownership_cfretain))obj; +@end + +void test_attr_1(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedString]; // no-warning +} + +void test_attr_2(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedString]; // no-warning + [X myRetain:str]; + [str release]; +} + +void test_attr_3(TestOwnershipAttr *X) { + // FIXME: This should be a leak. Need to change the analyzer to + // to track Objective-C objects retain counts even in GC mode. + NSString *str = [X returnsAnOwnedString]; // no-warning + [X myCFRetain:str]; + [str release]; +} diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index ae1b75c216..b547aa0373 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -412,6 +412,7 @@ void rdar6704930(unsigned char *s, unsigned int length) { @interface TestOwnershipAttr : NSObject - (NSString*) returnsAnOwnedString __attribute__((objc_ownership_returns)); - (void) myRetain:(id)__attribute__((objc_ownership_retain))obj; +- (void) myCFRetain:(id)__attribute__((objc_ownership_cfretain))obj; @end void test_attr_1(TestOwnershipAttr *X) { @@ -424,4 +425,9 @@ void test_attr_2(TestOwnershipAttr *X) { [str release]; } +void test_attr_3(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}} + [X myCFRetain:str]; + [str release]; +}