NonNull,
ObjCException,
ObjCNSObject,
- ObjCOwnershipRetain, // Clang/Checker-specific.
- ObjCOwnershipCFRetain, // Clang/Checker-specific.
- ObjCOwnershipReturns, // Clang/Checker-specific.
+ ObjCOwnershipCFRelease, // Clang/Checker-specific.
+ ObjCOwnershipCFRetain, // Clang/Checker-specific.
+ ObjCOwnershipRelease, // Clang/Checker-specific.
+ ObjCOwnershipRetain, // Clang/Checker-specific.
+ ObjCOwnershipReturns, // Clang/Checker-specific.
Overloadable, // Clang-specific
Packed,
Pure,
};
// Checker-specific attributes.
+DEF_SIMPLE_ATTR(ObjCOwnershipCFRelease)
+DEF_SIMPLE_ATTR(ObjCOwnershipRelease)
DEF_SIMPLE_ATTR(ObjCOwnershipCFRetain)
DEF_SIMPLE_ATTR(ObjCOwnershipRetain)
DEF_SIMPLE_ATTR(ObjCOwnershipReturns)
AT_nothrow,
AT_nsobject,
AT_objc_exception,
- AT_objc_ownership_cfretain, // Clang-specific.
- AT_objc_ownership_retain, // Clang-specific.
- AT_objc_ownership_returns, // Clang-specific.
+ AT_objc_ownership_cfrelease, // Clang-specific.
+ AT_objc_ownership_cfretain, // Clang-specific.
+ AT_objc_ownership_release, // Clang-specific.
+ AT_objc_ownership_retain, // Clang-specific.
+ AT_objc_ownership_returns, // Clang-specific.
AT_objc_gc,
AT_overloadable, // Clang-specific.
AT_packed,
else if ((*I)->getAttr<ObjCOwnershipCFRetainAttr>()) {
ScratchArgs.push_back(std::make_pair(i, IncRef));
hasArgEffect = true;
- }
+ }
+ else if ((*I)->getAttr<ObjCOwnershipReleaseAttr>()) {
+ ScratchArgs.push_back(std::make_pair(i, DecRefMsg));
+ hasArgEffect = true;
+ }
+ else if ((*I)->getAttr<ObjCOwnershipCFReleaseAttr>()) {
+ ScratchArgs.push_back(std::make_pair(i, DecRef));
+ hasArgEffect = true;
+ }
}
if (!hasRetEffect && !hasArgEffect)
SIMPLE_ATTR(ObjCException);
SIMPLE_ATTR(ObjCNSObject);
+ SIMPLE_ATTR(ObjCOwnershipCFRelease);
+ SIMPLE_ATTR(ObjCOwnershipRelease);
SIMPLE_ATTR(ObjCOwnershipCFRetain);
SIMPLE_ATTR(ObjCOwnershipRetain);
SIMPLE_ATTR(ObjCOwnershipReturns);
case Attr::ObjCException:
case Attr::ObjCNSObject:
+ case Attr::ObjCOwnershipCFRelease:
+ case Attr::ObjCOwnershipRelease:
case Attr::ObjCOwnershipCFRetain:
case Attr::ObjCOwnershipRetain:
case Attr::ObjCOwnershipReturns:
case 22:
if (!memcmp(Str, "objc_ownership_returns", 22))
return AT_objc_ownership_returns;
+ if (!memcmp(Str, "objc_ownership_release", 22))
+ return AT_objc_ownership_release;
if (!memcmp(Str, "no_instrument_function", 22))
return AT_no_instrument_function;
break;
if (!memcmp(Str, "objc_ownership_cfretain", 23))
return AT_objc_ownership_cfretain;
break;
- }
+ case 24:
+ if (!memcmp(Str, "objc_ownership_cfrelease", 24))
+ return AT_objc_ownership_cfrelease;
+ break;
+ }
return UnknownAttribute;
}
default:
assert(0 && "invalid ownership attribute");
return;
+ case AttributeList::AT_objc_ownership_release:
+ name = "objc_ownership_release"; break;
+ case AttributeList::AT_objc_ownership_cfrelease:
+ name = "objc_ownership_cfrelease"; break;
case AttributeList::AT_objc_ownership_retain:
name = "objc_ownership_retain"; break;
case AttributeList::AT_objc_ownership_cfretain:
default:
assert(0 && "invalid ownership attribute");
return;
+ case AttributeList::AT_objc_ownership_release:
+ d->addAttr(::new (S.Context) ObjCOwnershipReleaseAttr()); return;
+ case AttributeList::AT_objc_ownership_cfrelease:
+ d->addAttr(::new (S.Context) ObjCOwnershipCFReleaseAttr()); return;
case AttributeList::AT_objc_ownership_retain:
d->addAttr(::new (S.Context) ObjCOwnershipRetainAttr()); return;
case AttributeList::AT_objc_ownership_cfretain:
case AttributeList::AT_nothrow: HandleNothrowAttr (D, Attr, S); break;
// Checker-specific.
+ case AttributeList::AT_objc_ownership_release:
+ case AttributeList::AT_objc_ownership_cfrelease:
case AttributeList::AT_objc_ownership_retain:
case AttributeList::AT_objc_ownership_cfretain:
HandleObjCOwnershipParmAttr(D, Attr, S); break;
- (NSString*) returnsAnOwnedString __attribute__((objc_ownership_returns));
- (void) myRetain:(id)__attribute__((objc_ownership_retain))obj;
- (void) myCFRetain:(id)__attribute__((objc_ownership_cfretain))obj;
+- (void) myRelease:(id)__attribute__((objc_ownership_release))obj;
+- (void) myCFRelease:(id)__attribute__((objc_ownership_cfrelease))obj;
@end
void test_attr_1(TestOwnershipAttr *X) {
[X myCFRetain:str];
[str release];
}
+
+void test_attr_4(TestOwnershipAttr *X) {
+ NSString *str = [X returnsAnOwnedString]; // no-warning
+ [X myRetain:str];
+ [X myRelease:str];
+}
+
+void test_attr_5(TestOwnershipAttr *X) {
+ NSString *str = [X returnsAnOwnedString]; // no-warning
+ [X myCFRetain:str];
+ [X myCFRelease:str];
+}
- (NSString*) returnsAnOwnedString __attribute__((objc_ownership_returns));
- (void) myRetain:(id)__attribute__((objc_ownership_retain))obj;
- (void) myCFRetain:(id)__attribute__((objc_ownership_cfretain))obj;
+- (void) myRelease:(id)__attribute__((objc_ownership_release))obj;
+- (void) myCFRelease:(id)__attribute__((objc_ownership_cfrelease))obj;
@end
void test_attr_1(TestOwnershipAttr *X) {
[str release];
}
+void test_attr_4(TestOwnershipAttr *X) {
+ NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}}
+ [X myRetain:str];
+ [X myRelease:str];
+}
+
+void test_attr_5(TestOwnershipAttr *X) {
+ NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}}
+ [X myCFRetain:str];
+ [X myCFRelease:str];
+}
+