diff options
author | John McCall <rjmccall@apple.com> | 2011-07-22 08:53:00 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-07-22 08:53:00 +0000 |
commit | dc7c5ad7a15914b7ae24f31f18a20ad2f8ecd0bc (patch) | |
tree | 23cf6002f7ceff79c1c2eedeb9e3371ad4734800 /lib/Sema | |
parent | 159a7b3c531d09d98176699f212928da9bed8602 (diff) |
Document the existing objc_precise_lifetime attribute.
Introduce and document a new objc_returns_inner_pointer
attribute, and consume it by performing a retain+autorelease
on message receivers when they're not immediately loaded from
an object with precise lifetime.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@135764 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/AttributeList.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDeclAttr.cpp | 30 |
2 files changed, 31 insertions, 0 deletions
diff --git a/lib/Sema/AttributeList.cpp b/lib/Sema/AttributeList.cpp index 5a8330bbfd..21068538e8 100644 --- a/lib/Sema/AttributeList.cpp +++ b/lib/Sema/AttributeList.cpp @@ -163,6 +163,7 @@ AttributeList::Kind AttributeList::getKind(const IdentifierInfo *Name) { .Case("vec_type_hint", IgnoredAttribute) .Case("objc_exception", AT_objc_exception) .Case("objc_method_family", AT_objc_method_family) + .Case("objc_returns_inner_pointer", AT_objc_returns_inner_pointer) .Case("ext_vector_type", AT_ext_vector_type) .Case("neon_vector_type", AT_neon_vector_type) .Case("neon_polyvector_type", AT_neon_polyvector_type) diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 61b7b3ee05..ad9b6ddba9 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -2767,6 +2767,33 @@ static void handleNSReturnsRetainedAttr(Sema &S, Decl *D, }; } +static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D, + const AttributeList &attr) { + SourceLocation loc = attr.getLoc(); + + ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D); + + if (!isa<ObjCMethodDecl>(method)) { + S.Diag(method->getLocStart(), diag::err_attribute_wrong_decl_type) + << SourceRange(loc, loc) << attr.getName() << 13 /* methods */; + return; + } + + // Check that the method returns a normal pointer. + QualType resultType = method->getResultType(); + if (!resultType->isPointerType() || resultType->isObjCRetainableType()) { + S.Diag(method->getLocStart(), diag::warn_ns_attribute_wrong_return_type) + << SourceRange(loc) + << attr.getName() << /*method*/ 1 << /*non-retainable pointer*/ 2; + + // Drop the attribute. + return; + } + + method->addAttr( + ::new (S.Context) ObjCReturnsInnerPointerAttr(loc, S.Context)); +} + static void handleObjCOwnershipAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (hasDeclarator(D)) return; @@ -2969,6 +2996,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_objc_precise_lifetime: handleObjCPreciseLifetimeAttr(S, D, Attr); break; + case AttributeList::AT_objc_returns_inner_pointer: + handleObjCReturnsInnerPointerAttr(S, D, Attr); break; + // Checker-specific. case AttributeList::AT_cf_consumed: case AttributeList::AT_ns_consumed: handleNSConsumedAttr (S, D, Attr); break; |