From: Ted Kremenek Date: Tue, 5 May 2009 00:46:09 +0000 (+0000) Subject: Implement attribute 'cf_returns_owned' (mirrors 'ns_returns_owned'). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e351aa10dab6eb8b9b502166c7035dc7b0e723e0;p=clang Implement attribute 'cf_returns_owned' (mirrors 'ns_returns_owned'). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70952 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 79f41bda5d..d55f26d542 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -61,6 +61,7 @@ public: ObjCNSObject, CFOwnershipRelease, // Clang/Checker-specific. CFOwnershipRetain, // Clang/Checker-specific. + CFOwnershipReturns, // Clang/Checker-specific. NSOwnershipRelease, // Clang/Checker-specific. NSOwnershipRetain, // Clang/Checker-specific. NSOwnershipReturns, // Clang/Checker-specific. @@ -135,7 +136,7 @@ public: class ATTR##Attr : public Attr { \ public: \ ATTR##Attr() : Attr(ATTR) {} \ - virtual Attr *clone(ASTContext &C) const { return ::new (C) ATTR##Attr; } \ + virtual Attr *clone(ASTContext &C) const { return ::new (C) ATTR##Attr; }\ static bool classof(const Attr *A) { return A->getKind() == ATTR; } \ static bool classof(const ATTR##Attr *A) { return true; } \ } @@ -466,8 +467,9 @@ public: // Checker-specific attributes. DEF_SIMPLE_ATTR(CFOwnershipRelease); -DEF_SIMPLE_ATTR(NSOwnershipRelease); DEF_SIMPLE_ATTR(CFOwnershipRetain); +DEF_SIMPLE_ATTR(CFOwnershipReturns); +DEF_SIMPLE_ATTR(NSOwnershipRelease); DEF_SIMPLE_ATTR(NSOwnershipRetain); DEF_SIMPLE_ATTR(NSOwnershipReturns); diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 3666542d67..52f0f149f7 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -78,11 +78,12 @@ public: AT_objc_exception, AT_cf_releases, // Clang-specific. AT_cf_retains, // Clang-specific. - AT_ns_releases, // Clang-specific. - AT_ns_retains, // Clang-specific. - AT_ns_returns_owned, // Clang-specific. + AT_cf_returns_owned, // Clang-specific. + AT_ns_releases, // Clang-specific. + AT_ns_retains, // Clang-specific. + AT_ns_returns_owned, // 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 976bfad188..07dbf10c40 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -1128,6 +1128,9 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, ? RetEffect::MakeGCNotOwned() : RetEffect::MakeOwned(RetEffect::ObjC, true)); } + else if (FD->getAttr()) { + Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); + } } // Determine if there are any arguments with a specific ArgEffect. @@ -1150,6 +1153,9 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, ? RetEffect::MakeGCNotOwned() : RetEffect::MakeOwned(RetEffect::ObjC, true)); } + else if (MD->getAttr()) { + Summ.setRetEffect(RetEffect::MakeOwned(RetEffect::CF, true)); + } } // Determine if there are any arguments with a specific ArgEffect. diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index ff2eb9f7c9..7bcd296bce 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -477,6 +477,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(ObjCNSObject); SIMPLE_ATTR(CFOwnershipRelease); SIMPLE_ATTR(CFOwnershipRetain); + SIMPLE_ATTR(CFOwnershipReturns); SIMPLE_ATTR(NSOwnershipRelease); SIMPLE_ATTR(NSOwnershipRetain); SIMPLE_ATTR(NSOwnershipReturns); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index a1f0cb7f4f..98ed063305 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1551,6 +1551,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::ObjCNSObject: case Attr::CFOwnershipRelease: case Attr::CFOwnershipRetain: + case Attr::CFOwnershipReturns: case Attr::NSOwnershipRelease: case Attr::NSOwnershipRetain: case Attr::NSOwnershipReturns: diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 1cc9a51ec6..933e9f2b09 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -132,6 +132,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { break; case 16: if (!memcmp(Str, "ns_returns_owned", 16)) return AT_ns_returns_owned; + if (!memcmp(Str, "cf_returns_owned", 16)) return AT_cf_returns_owned; break; case 17: if (!memcmp(Str, "transparent_union", 17)) return AT_transparent_union; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 033be2c962..926e5fda68 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1548,15 +1548,37 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { //===----------------------------------------------------------------------===// static void HandleNSOwnershipReturnsAttr(Decl *d, const AttributeList &Attr, - Sema &S) { + Sema &S) { if (!isa(d) && !isa(d)) { + const char *name; + + switch (Attr.getKind()) { + default: + assert(0 && "invalid ownership attribute"); + return; + case AttributeList::AT_cf_returns_owned: + name = "cf_returns_owned"; break; + case AttributeList::AT_ns_returns_owned: + name = "ns_returns_owned"; break; + }; + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << - "ns_returns_owned" << 3 /* function or method */; + name << 3 /* function or method */; return; } - d->addAttr(::new (S.Context) NSOwnershipReturnsAttr()); + switch (Attr.getKind()) { + default: + assert(0 && "invalid ownership attribute"); + return; + case AttributeList::AT_cf_returns_owned: + d->addAttr(::new (S.Context) CFOwnershipReturnsAttr()); + return; + case AttributeList::AT_ns_returns_owned: + d->addAttr(::new (S.Context) NSOwnershipReturnsAttr()); + return; + }; } static void HandleNSOwnershipAttr(Decl *d, const AttributeList &Attr, @@ -1579,9 +1601,9 @@ static void HandleNSOwnershipAttr(Decl *d, const AttributeList &Attr, name = "ns_retains"; break; }; - S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << name - << (attachToMethodDecl ? 5 /* parameter or method decl */ - : 4 /* parameter */); + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + name << (attachToMethodDecl ? 5 /* parameter or method decl */ + : 4 /* parameter */); return; } @@ -1590,13 +1612,17 @@ static void HandleNSOwnershipAttr(Decl *d, const AttributeList &Attr, assert(0 && "invalid ownership attribute"); return; case AttributeList::AT_cf_releases: - d->addAttr(::new (S.Context) CFOwnershipReleaseAttr()); return; + d->addAttr(::new (S.Context) CFOwnershipReleaseAttr()); + return; case AttributeList::AT_cf_retains: - d->addAttr(::new (S.Context) CFOwnershipRetainAttr()); return; + d->addAttr(::new (S.Context) CFOwnershipRetainAttr()); + return; case AttributeList::AT_ns_releases: - d->addAttr(::new (S.Context) NSOwnershipReleaseAttr()); return; + d->addAttr(::new (S.Context) NSOwnershipReleaseAttr()); + return; case AttributeList::AT_ns_retains: - d->addAttr(::new (S.Context) NSOwnershipRetainAttr()); return; + d->addAttr(::new (S.Context) NSOwnershipRetainAttr()); + return; } } @@ -1645,6 +1671,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { case AttributeList::AT_ns_retains: HandleNSOwnershipAttr(D, Attr, S, true); break; case AttributeList::AT_ns_returns_owned: + case AttributeList::AT_cf_returns_owned: HandleNSOwnershipReturnsAttr(D, Attr, S); break; case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; diff --git a/test/Analysis/retain-release-gc-only.m b/test/Analysis/retain-release-gc-only.m index 74d2c94797..3a57bead47 100644 --- a/test/Analysis/retain-release-gc-only.m +++ b/test/Analysis/retain-release-gc-only.m @@ -130,6 +130,7 @@ void f3() { @interface TestOwnershipAttr : NSObject - (NSString*) returnsAnOwnedString __attribute__((ns_returns_owned)); +- (NSString*) returnsAnOwnedCFString __attribute__((cf_returns_owned)); - (void) myRetain:(id)__attribute__((ns_retains))obj; - (void) myCFRetain:(id)__attribute__((cf_retains))obj; - (void) myRelease:(id)__attribute__((ns_releases))obj; @@ -140,12 +141,22 @@ void test_attr_1(TestOwnershipAttr *X) { NSString *str = [X returnsAnOwnedString]; // no-warning } +void test_attr_1b(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}} +} + void test_attr_2(TestOwnershipAttr *X) { NSString *str = [X returnsAnOwnedString]; // no-warning [X myRetain:str]; [str release]; } +void test_attr_2b(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}} + [X myRetain:str]; + [str release]; +} + void test_attr_3(TestOwnershipAttr *X) { NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}} [X myCFRetain:str]; diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index a25c0e2625..b7b2efa797 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -432,6 +432,7 @@ void rdar6704930(unsigned char *s, unsigned int length) { @interface TestOwnershipAttr : NSObject - (NSString*) returnsAnOwnedString __attribute__((ns_returns_owned)); +- (NSString*) returnsAnOwnedCFString __attribute__((cf_returns_owned)); - (void) myRetain:(id)__attribute__((ns_retains))obj; - (void) myCFRetain:(id)__attribute__((cf_retains))obj; - (void) myRelease:(id)__attribute__((ns_releases))obj; @@ -458,12 +459,22 @@ void test_attr_1(TestOwnershipAttr *X) { NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}} } +void test_attr_1b(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}} +} + void test_attr_2(TestOwnershipAttr *X) { NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}} [X myRetain:str]; [str release]; } +void test_attr_2b(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedCFString]; // expected-warning{{leak}} + [X myRetain:str]; + [str release]; +} + void test_attr_3(TestOwnershipAttr *X) { NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}} [X myCFRetain:str];