Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -846,6 +846,12 @@ let Documentation = [RetainBehaviorDocs]; } +def OSConsumesThis : InheritableAttr { + let Spellings = [Clang<"os_consumes_this">]; + let Subjects = SubjectList<[CXXMethod]>; + let Documentation = [RetainBehaviorDocs]; +} + def Cleanup : InheritableAttr { let Spellings = [GCC<"cleanup">]; let Args = [FunctionArgument<"FunctionDecl">]; @@ -1649,13 +1655,13 @@ def NSConsumesSelf : InheritableAttr { let Spellings = [Clang<"ns_consumes_self">]; let Subjects = SubjectList<[ObjCMethod]>; - let Documentation = [Undocumented]; + let Documentation = [RetainBehaviorDocs]; } def NSConsumed : InheritableParamAttr { let Spellings = [Clang<"ns_consumed">]; let Subjects = SubjectList<[ParmVar]>; - let Documentation = [Undocumented]; + let Documentation = [RetainBehaviorDocs]; } def ObjCException : InheritableAttr { Index: clang/include/clang/Basic/AttrDocs.td =================================================================== --- clang/include/clang/Basic/AttrDocs.td +++ clang/include/clang/Basic/AttrDocs.td @@ -862,6 +862,9 @@ Similiarly, the annotation ``__attribute__((ns_returns_not_retained))`` specifies that the object is returned at ``+0`` and the ownership remains with the callee. +The annotation ``__attribute__((ns_consumes_self))`` specifies that +the Objective-C method call consumes the reference to ``self``, e.g. by +attaching it to a supplied parameter. Additionally, parameters can have an annotation ``__attribute__((ns_consumed))``, which specifies that passing an owned object as that parameter effectively transfers the ownership, and the caller is no @@ -881,7 +884,11 @@ ``__attribute__((os_returns_not_retained))``, ``__attribute__((os_returns_retained))`` and ``__attribute__((os_consumed))``, with the same respective semantics. -These attributes are also used by the Clang Static Analyzer. +Similar to ``__attribute__((ns_consumes_self))``, +``__attribute__((os_consumes_this))`` specifies that the method call consumes +the reference to "this" (e.g. when attaching it to a different object, e.g. +supplied as a parameter). +These attributes are only used by the Clang Static Analyzer. The family of attributes ``X_returns_X_retained`` can be added to functions, C++ methods, and Objective-C methods and properties. Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3461,6 +3461,9 @@ "%0 attribute only applies to %select{functions|methods|properties}1 that " "return %select{an Objective-C object|a pointer|a non-retainable pointer}2">, InGroup; +def warn_os_consumes_this_static : Warning< + "%0 attribute only applies to non-static methods">, + InGroup; def err_ns_attribute_wrong_parameter_type : Error< "%0 attribute only applies to " "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">; Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -6080,6 +6080,13 @@ handleSimpleAttributeWithExclusions(S, D, A); } +static void handleConsumesThisAttr(Sema &S, Decl *D, const ParsedAttr &AL) { + const auto *MD = cast(D); + if (MD->isStatic()) + S.Diag(D->getBeginLoc(), diag::warn_os_consumes_this_static) << AL; + handleSimpleAttribute(S, D, AL); +} + //===----------------------------------------------------------------------===// // Top Level Sema Entry Points //===----------------------------------------------------------------------===// @@ -6408,6 +6415,9 @@ case ParsedAttr::AT_NSConsumesSelf: handleSimpleAttribute(S, D, AL); break; + case ParsedAttr::AT_OSConsumesThis: + handleConsumesThisAttr(S, D, AL); + break; case ParsedAttr::AT_NSReturnsAutoreleased: case ParsedAttr::AT_NSReturnsNotRetained: case ParsedAttr::AT_NSReturnsRetained: Index: clang/test/Misc/pragma-attribute-supported-attributes-list.test =================================================================== --- clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -86,6 +86,7 @@ // CHECK-NEXT: NoThrow (SubjectMatchRule_function) // CHECK-NEXT: NotTailCalled (SubjectMatchRule_function) // CHECK-NEXT: OSConsumed (SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: OSConsumesThis (SubjectMatchRule_function_is_member) // CHECK-NEXT: OSReturnsNotRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property) // CHECK-NEXT: OSReturnsRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property) // CHECK-NEXT: ObjCBoxable (SubjectMatchRule_record) Index: clang/test/Sema/attr-osobject.cpp =================================================================== --- clang/test/Sema/attr-osobject.cpp +++ clang/test/Sema/attr-osobject.cpp @@ -4,6 +4,13 @@ __attribute__((os_returns_retained)) S* method_returns_retained() { return nullptr; } + + __attribute__((os_consumes_this)) void method_consumes_this(); + + __attribute__((os_consumes_this)) static void static_method_no_consume_this(); // expected-warning{{'os_consumes_this' attribute only applies to non-static methods}} + + + __attribute__((os_consumes_this(10))) void os_consumes_no_params() {}; // expected-error{{'os_consumes_this' attribute takes no arguments}} }; __attribute__((os_returns_retained)) S *ret_retained() { return nullptr; @@ -37,6 +44,10 @@ __attribute__((os_returns_not_retained(10))) S* os_returns_no_retained_no_extra_args( S *arg) { // expected-error{{'os_returns_not_retained' attribute takes no arguments}} return nullptr; -} +} struct __attribute__((os_returns_not_retained)) NoNotRetainedAttrOnStruct {}; // expected-warning{{'os_returns_not_retained' attribute only applies to functions, Objective-C methods, and Objective-C properties}} + +__attribute__((os_consumes_this)) void no_consumes_this_on_function() {}; // expected-warning{{'os_consumes_this' attribute only applies to functions}} + +