From: Ted Kremenek Date: Tue, 5 May 2009 18:44:20 +0000 (+0000) Subject: Implement attribute 'ns_autorelease'. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=69aa08072decc20094bd1f75f4f9842e9bd357ad;p=clang Implement attribute 'ns_autorelease'. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70990 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index d55f26d542..41f2e9470d 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -62,6 +62,7 @@ public: CFOwnershipRelease, // Clang/Checker-specific. CFOwnershipRetain, // Clang/Checker-specific. CFOwnershipReturns, // Clang/Checker-specific. + NSOwnershipAutorelease, // Clang/Checker-specific. NSOwnershipRelease, // Clang/Checker-specific. NSOwnershipRetain, // Clang/Checker-specific. NSOwnershipReturns, // Clang/Checker-specific. @@ -471,6 +472,7 @@ DEF_SIMPLE_ATTR(CFOwnershipRetain); DEF_SIMPLE_ATTR(CFOwnershipReturns); DEF_SIMPLE_ATTR(NSOwnershipRelease); DEF_SIMPLE_ATTR(NSOwnershipRetain); +DEF_SIMPLE_ATTR(NSOwnershipAutorelease); DEF_SIMPLE_ATTR(NSOwnershipReturns); #undef DEF_SIMPLE_ATTR diff --git a/include/clang/Parse/AttributeList.h b/include/clang/Parse/AttributeList.h index 52f0f149f7..172c07fc61 100644 --- a/include/clang/Parse/AttributeList.h +++ b/include/clang/Parse/AttributeList.h @@ -79,6 +79,7 @@ public: AT_cf_releases, // Clang-specific. AT_cf_retains, // Clang-specific. AT_cf_returns_owned, // Clang-specific. + AT_ns_autoreleases, // Clang-specific. AT_ns_releases, // Clang-specific. AT_ns_retains, // Clang-specific. AT_ns_returns_owned, // Clang-specific. diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 07dbf10c40..ca420006d2 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -779,8 +779,8 @@ public: RetainSummary* getCommonMethodSummary(const ObjCMethodDecl* MD, Selector S, QualType RetTy); - void updateSummaryArgEffFromAnnotations(RetainSummary &Summ, unsigned i, - const ParmVarDecl *PD); + void updateSummaryArgEffFromAnnotations(RetainSummary &Summ, const Decl *D, + unsigned argIdx = 0); void updateSummaryFromAnnotations(RetainSummary &Summ, const ObjCMethodDecl *MD); @@ -1097,22 +1097,32 @@ RetainSummaryManager::getInitMethodSummary(QualType RetTy) { // 'init' methods only return an alias if the return type is a location type. return getPersistentSummary(Loc::IsLocType(RetTy) ? RetEffect::MakeReceiverAlias() - : RetEffect::MakeNoRet()); + : RetEffect::MakeNoRet()); } - void RetainSummaryManager::updateSummaryArgEffFromAnnotations(RetainSummary &Summ, - unsigned i, - const ParmVarDecl *PD){ - if (PD->getAttr()) - Summ.setArgEffect(AF, i, IncRefMsg); - else if (PD->getAttr()) - Summ.setArgEffect(AF, i, IncRef); - else if (PD->getAttr()) - Summ.setArgEffect(AF, i, DecRefMsg); - else if (PD->getAttr()) - Summ.setArgEffect(AF, i, DecRef); + const Decl *D, + unsigned i) { + ArgEffect E = DoNothing; + + if (D->getAttr()) + E = IncRefMsg; + else if (D->getAttr()) + E = IncRef; + else if (D->getAttr()) + E = DecRefMsg; + else if (D->getAttr()) + E = DecRef; + else if (D->getAttr()) + E = Autorelease; + else + return; + + if (isa(D)) + Summ.setArgEffect(AF, i, E); + else + Summ.setReceiverEffect(E); } void @@ -1137,7 +1147,7 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, unsigned i = 0; for (FunctionDecl::param_const_iterator I = FD->param_begin(), E = FD->param_end(); I != E; ++I, ++i) - updateSummaryArgEffFromAnnotations(Summ, i, *I); + updateSummaryArgEffFromAnnotations(Summ, *I, i); } void @@ -1162,13 +1172,10 @@ RetainSummaryManager::updateSummaryFromAnnotations(RetainSummary &Summ, unsigned i = 0; for (ObjCMethodDecl::param_iterator I = MD->param_begin(), E = MD->param_end(); I != E; ++I, ++i) - updateSummaryArgEffFromAnnotations(Summ, i, *I); + updateSummaryArgEffFromAnnotations(Summ, *I, i); // Determine any effects on the receiver. - if (MD->getAttr()) - Summ.setReceiverEffect(IncRefMsg); - else if (MD->getAttr()) - Summ.setReceiverEffect(DecRefMsg); + updateSummaryArgEffFromAnnotations(Summ, MD); } RetainSummary* diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp index 7bcd296bce..059aa259c7 100644 --- a/lib/Frontend/PCHReaderDecl.cpp +++ b/lib/Frontend/PCHReaderDecl.cpp @@ -478,6 +478,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(CFOwnershipRelease); SIMPLE_ATTR(CFOwnershipRetain); SIMPLE_ATTR(CFOwnershipReturns); + SIMPLE_ATTR(NSOwnershipAutorelease); SIMPLE_ATTR(NSOwnershipRelease); SIMPLE_ATTR(NSOwnershipRetain); SIMPLE_ATTR(NSOwnershipReturns); diff --git a/lib/Frontend/PCHWriter.cpp b/lib/Frontend/PCHWriter.cpp index 98ed063305..9b14a94fad 100644 --- a/lib/Frontend/PCHWriter.cpp +++ b/lib/Frontend/PCHWriter.cpp @@ -1552,6 +1552,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::CFOwnershipRelease: case Attr::CFOwnershipRetain: case Attr::CFOwnershipReturns: + case Attr::NSOwnershipAutorelease: case Attr::NSOwnershipRelease: case Attr::NSOwnershipRetain: case Attr::NSOwnershipReturns: diff --git a/lib/Parse/AttributeList.cpp b/lib/Parse/AttributeList.cpp index 933e9f2b09..6dceda6432 100644 --- a/lib/Parse/AttributeList.cpp +++ b/lib/Parse/AttributeList.cpp @@ -129,6 +129,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { break; case 15: if (!memcmp(Str, "ext_vector_type", 15)) return AT_ext_vector_type; + if (!memcmp(Str, "ns_autoreleases", 15)) return AT_ns_autoreleases; break; case 16: if (!memcmp(Str, "ns_returns_owned", 16)) return AT_ns_returns_owned; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 926e5fda68..7701835b38 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -1595,6 +1595,8 @@ static void HandleNSOwnershipAttr(Decl *d, const AttributeList &Attr, name = "cf_releases"; break; case AttributeList::AT_cf_retains: name = "cf_retains"; break; + case AttributeList::AT_ns_autoreleases: + name = "ns_autoreleases"; break; case AttributeList::AT_ns_releases: name = "ns_releases"; break; case AttributeList::AT_ns_retains: @@ -1617,6 +1619,9 @@ static void HandleNSOwnershipAttr(Decl *d, const AttributeList &Attr, case AttributeList::AT_cf_retains: d->addAttr(::new (S.Context) CFOwnershipRetainAttr()); return; + case AttributeList::AT_ns_autoreleases: + d->addAttr(::new (S.Context) NSOwnershipAutoreleaseAttr()); + return; case AttributeList::AT_ns_releases: d->addAttr(::new (S.Context) NSOwnershipReleaseAttr()); return; @@ -1667,6 +1672,7 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { case AttributeList::AT_cf_releases: case AttributeList::AT_cf_retains: HandleNSOwnershipAttr(D, Attr, S); break; + case AttributeList::AT_ns_autoreleases: case AttributeList::AT_ns_releases: case AttributeList::AT_ns_retains: HandleNSOwnershipAttr(D, Attr, S, true); break; diff --git a/test/Analysis/retain-release.m b/test/Analysis/retain-release.m index 9ed10f812f..e9c3f5189b 100644 --- a/test/Analysis/retain-release.m +++ b/test/Analysis/retain-release.m @@ -439,6 +439,8 @@ void rdar6704930(unsigned char *s, unsigned int length) { - (void) myCFRelease:(id)__attribute__((cf_releases))obj; - (void) myRetain __attribute__((ns_retains)); - (void) myRelease __attribute__((ns_releases)); +- (void) myAutorelease __attribute__((ns_autoreleases)); +- (void) myAutorelease:(id)__attribute__((ns_autoreleases))obj; @end @interface TestAttrHelper : NSObject @@ -478,6 +480,10 @@ NSString* test_attr_1d(TestOwnershipAttr *X) { return str; } +void test_attr_1e(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedString]; // no-warning + [X myAutorelease:str]; +} void test_attr_2(TestOwnershipAttr *X) { NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}} @@ -548,6 +554,11 @@ void test_attr_6c() { [X myRelease]; } +void test_attr_6d() { + TestOwnershipAttr *X = [TestOwnershipAttr alloc]; // no-warning + [X myAutorelease]; +} + //===----------------------------------------------------------------------===// // // One build of the analyzer accidentally stopped tracking the allocated