From da2c77f92bbb9387073bf55ad60f7aadaa1bc742 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Thu, 6 Dec 2018 22:06:59 +0000 Subject: [PATCH] [attributes] Add an attribute os_consumes_this, with similar semantics to ns_consumes_self The attribute specifies that the call of the C++ method consumes a reference to "this". Differential Revision: https://reviews.llvm.org/D55155 llvm-svn: 348532 --- clang/include/clang/Basic/Attr.td | 14 ++++++++++++-- clang/include/clang/Basic/AttrDocs.td | 9 ++++++++- clang/lib/Sema/SemaDeclAttr.cpp | 3 +++ clang/test/Sema/attr-osobject.cpp | 8 +++++++- 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index d644040..04125e6 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -90,6 +90,10 @@ def NonBitField : SubsetSubjectisBitField()}], "non-bit-field non-static data members">; +def NonStaticCXXMethod : SubsetSubjectisStatic()}], + "non-static member functions">; + def NonStaticNonConstCXXMethod : SubsetSubjectisStatic() && !S->isConst()}], @@ -846,6 +850,12 @@ def OSReturnsNotRetained : InheritableAttr { let Documentation = [RetainBehaviorDocs]; } +def OSConsumesThis : InheritableAttr { + let Spellings = [Clang<"os_consumes_this">]; + let Subjects = SubjectList<[NonStaticCXXMethod]>; + let Documentation = [RetainBehaviorDocs]; +} + def Cleanup : InheritableAttr { let Spellings = [GCC<"cleanup">]; let Args = [FunctionArgument<"FunctionDecl">]; @@ -1649,13 +1659,13 @@ def NSReturnsAutoreleased : InheritableAttr { 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 { diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 5c9f2b9..e72ef25 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -862,6 +862,9 @@ is responsible for freeing it. 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 @@ the same attribute family is present: ``__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 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. diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a2520c0..78374b8 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -6408,6 +6408,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case ParsedAttr::AT_NSConsumesSelf: handleSimpleAttribute(S, D, AL); break; + case ParsedAttr::AT_OSConsumesThis: + handleSimpleAttribute(S, D, AL); + break; case ParsedAttr::AT_NSReturnsAutoreleased: case ParsedAttr::AT_NSReturnsNotRetained: case ParsedAttr::AT_NSReturnsRetained: diff --git a/clang/test/Sema/attr-osobject.cpp b/clang/test/Sema/attr-osobject.cpp index fe9ed6b..8d87453 100644 --- a/clang/test/Sema/attr-osobject.cpp +++ b/clang/test/Sema/attr-osobject.cpp @@ -4,6 +4,10 @@ struct S { __attribute__((os_returns_retained)) S* method_returns_retained() { return nullptr; } + + __attribute__((os_consumes_this)) void method_consumes_this(); + + __attribute__((os_consumes_this)) static void rejected_on_static(); // expected-warning{{'os_consumes_this' attribute only applies to non-static member functions}} }; __attribute__((os_returns_retained)) S *ret_retained() { return nullptr; @@ -37,6 +41,8 @@ struct __attribute__((os_returns_retained)) NoRetainAttrOnStruct {}; // expected __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 non-static member functions}} -- 2.7.4