From 44e662cd4f911efaf2f645252ec1fe8577b3f52c Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Fri, 24 Apr 2009 23:09:54 +0000 Subject: [PATCH] Add new checker-specific attribute 'objc_ownership_returns'. This isn't hooked up to the checker yet, but essentially it allows a user to specify that an Objective-C method or C function returns an owned an Objective-C object. llvm-svn: 70001 --- clang/include/clang/AST/Attr.h | 16 ++++++++++++++++ clang/include/clang/Parse/AttributeList.h | 3 ++- clang/lib/Frontend/PCHReader.cpp | 1 + clang/lib/Frontend/PCHWriter.cpp | 1 + clang/lib/Parse/AttributeList.cpp | 4 ++++ clang/lib/Sema/SemaDeclAttr.cpp | 21 +++++++++++++++++++++ clang/test/Analysis/retain-release.m | 12 ++++++++++++ 7 files changed, 57 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h index 085b51c5ca7d..93a9edb8077b 100644 --- a/clang/include/clang/AST/Attr.h +++ b/clang/include/clang/AST/Attr.h @@ -51,6 +51,7 @@ public: NonNull, ObjCException, ObjCNSObject, + ObjCOwnershipReturns, // Clang/Checker-specific. Overloadable, // Clang-specific Packed, Pure, @@ -587,6 +588,21 @@ public: static bool classof(const Attr *A) { return A->getKind() == Regparm; } static bool classof(const RegparmAttr *A) { return true; } }; + + +#define DEF_SIMPLE_ATTR(ATTR)\ +class ATTR##Attr : public Attr {\ +public:\ + ATTR##Attr() : Attr(ATTR) {}\ + static bool classof(const Attr *A) { return A->getKind() == ATTR; }\ + static bool classof(const ATTR##Attr *A) { return true; }\ +}; + +// Checker-specific attributes. +DEF_SIMPLE_ATTR(ObjCOwnershipReturns) + +#undef DEF_SIMPLE_ATTR + } // end namespace clang #endif diff --git a/clang/include/clang/Parse/AttributeList.h b/clang/include/clang/Parse/AttributeList.h index 1e94a71a647c..9712cc896eda 100644 --- a/clang/include/clang/Parse/AttributeList.h +++ b/clang/include/clang/Parse/AttributeList.h @@ -75,8 +75,9 @@ public: AT_nothrow, AT_nsobject, AT_objc_exception, + 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/clang/lib/Frontend/PCHReader.cpp b/clang/lib/Frontend/PCHReader.cpp index 2dfb7e0a0a0c..bbe92a0329ef 100644 --- a/clang/lib/Frontend/PCHReader.cpp +++ b/clang/lib/Frontend/PCHReader.cpp @@ -3045,6 +3045,7 @@ Attr *PCHReader::ReadAttributes() { SIMPLE_ATTR(ObjCException); SIMPLE_ATTR(ObjCNSObject); + SIMPLE_ATTR(ObjCOwnershipReturns); SIMPLE_ATTR(Overloadable); UNSIGNED_ATTR(Packed); SIMPLE_ATTR(Pure); diff --git a/clang/lib/Frontend/PCHWriter.cpp b/clang/lib/Frontend/PCHWriter.cpp index 782244c60ed4..4d2f4092ef72 100644 --- a/clang/lib/Frontend/PCHWriter.cpp +++ b/clang/lib/Frontend/PCHWriter.cpp @@ -2181,6 +2181,7 @@ void PCHWriter::WriteAttributeRecord(const Attr *Attr) { case Attr::ObjCException: case Attr::ObjCNSObject: + case Attr::ObjCOwnershipReturns: case Attr::Overloadable: break; diff --git a/clang/lib/Parse/AttributeList.cpp b/clang/lib/Parse/AttributeList.cpp index 5797a1540804..33715899c5cc 100644 --- a/clang/lib/Parse/AttributeList.cpp +++ b/clang/lib/Parse/AttributeList.cpp @@ -133,6 +133,10 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { case 18: if (!memcmp(Str, "warn_unused_result", 18)) return AT_warn_unused_result; break; + case 22: + if (!memcmp(Str, "objc_ownership_returns", 22)) + return AT_objc_ownership_returns; + break; } return UnknownAttribute; } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index d05b99ac365c..5a99fdccd16d 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1517,6 +1517,22 @@ static void HandleRegparmAttr(Decl *d, const AttributeList &Attr, Sema &S) { d->addAttr(::new (S.Context) RegparmAttr(NumParams.getZExtValue())); } +//===----------------------------------------------------------------------===// +// Checker-specific attribute handlers. +//===----------------------------------------------------------------------===// + +static void HandleObjCOwnershipReturnsAttr(Decl *d, const AttributeList &Attr, + Sema &S) { + + if (!isa(d) && !isa(d)) { + S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) << + "objc_ownership_returns" << 3 /* function or method */; + return; + } + + d->addAttr(::new (S.Context) ObjCOwnershipReturnsAttr()); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -1553,6 +1569,11 @@ static void ProcessDeclAttribute(Decl *D, const AttributeList &Attr, Sema &S) { case AttributeList::AT_nonnull: HandleNonNullAttr (D, Attr, S); break; case AttributeList::AT_noreturn: HandleNoReturnAttr (D, Attr, S); break; case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break; + + // Checker-specific. + case AttributeList::AT_objc_ownership_returns: + HandleObjCOwnershipReturnsAttr(D, Attr, S); break; + case AttributeList::AT_packed: HandlePackedAttr (D, Attr, S); break; case AttributeList::AT_section: HandleSectionAttr (D, Attr, S); break; case AttributeList::AT_stdcall: HandleStdCallAttr (D, Attr, S); break; diff --git a/clang/test/Analysis/retain-release.m b/clang/test/Analysis/retain-release.m index 012e340f563e..b8e819012baa 100644 --- a/clang/test/Analysis/retain-release.m +++ b/clang/test/Analysis/retain-release.m @@ -405,3 +405,15 @@ void rdar6704930(unsigned char *s, unsigned int length) { } } +//===----------------------------------------------------------------------===// +// Tests of ownership attributes. +//===----------------------------------------------------------------------===// + +@interface TestOwnershipAttr : NSObject +- (NSString*) returnsAnOwnedString __attribute__((objc_ownership_returns)); +@end + +void test_attr_1(TestOwnershipAttr *X) { + NSString *str = [X returnsAnOwnedString]; +} +