Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -840,13 +840,13 @@ def OSReturnsRetained : InheritableAttr { let Spellings = [Clang<"os_returns_retained">]; - let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty]>; + let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty, ParmVar]>; let Documentation = [RetainBehaviorDocs]; } def OSReturnsNotRetained : InheritableAttr { let Spellings = [Clang<"os_returns_not_retained">]; - let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty]>; + let Subjects = SubjectList<[Function, ObjCMethod, ObjCProperty, ParmVar]>; let Documentation = [RetainBehaviorDocs]; } Index: clang/include/clang/Basic/DiagnosticSemaKinds.td =================================================================== --- clang/include/clang/Basic/DiagnosticSemaKinds.td +++ clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -3426,10 +3426,10 @@ 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">; + "%select{Objective-C object|pointer|pointer-to-pointer}1 parameters">; def warn_ns_attribute_wrong_parameter_type : Warning< "%0 attribute only applies to " - "%select{Objective-C object|pointer|pointer-to-CF-pointer}1 parameters">, + "%select{Objective-C object|pointer|pointer-to-pointer}1 parameters">, InGroup; def warn_objc_requires_super_protocol : Warning< "%0 attribute cannot be applied to %select{methods in protocols|dealloc}1">, Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -4845,7 +4845,7 @@ ReturnType = Param->getType()->getPointeeType(); if (ReturnType.isNull()) { S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) - << AL << /*pointer-to-CF-pointer*/ 2 << AL.getRange(); + << AL << /*pointer-to-pointer*/ 2 << AL.getRange(); return; } } else if (AL.isUsedAsTypeAttr()) { @@ -4857,11 +4857,11 @@ case ParsedAttr::AT_NSReturnsRetained: case ParsedAttr::AT_NSReturnsAutoreleased: case ParsedAttr::AT_NSReturnsNotRetained: - case ParsedAttr::AT_OSReturnsRetained: - case ParsedAttr::AT_OSReturnsNotRetained: ExpectedDeclKind = ExpectedFunctionOrMethod; break; + case ParsedAttr::AT_OSReturnsRetained: + case ParsedAttr::AT_OSReturnsNotRetained: case ParsedAttr::AT_CFReturnsRetained: case ParsedAttr::AT_CFReturnsNotRetained: ExpectedDeclKind = ExpectedFunctionMethodOrParameter; @@ -4906,7 +4906,7 @@ if (isa(D)) { S.Diag(D->getBeginLoc(), diag::warn_ns_attribute_wrong_parameter_type) - << AL << /*pointer-to-CF*/ 2 << AL.getRange(); + << AL << /*pointer-to-pointer*/ 2 << AL.getRange(); } else { // Needs to be kept in sync with warn_ns_attribute_wrong_return_type. enum : unsigned { 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,8 +86,8 @@ // CHECK-NEXT: NoThrow (SubjectMatchRule_function) // CHECK-NEXT: NotTailCalled (SubjectMatchRule_function) // CHECK-NEXT: OSConsumed (SubjectMatchRule_variable_is_parameter) -// CHECK-NEXT: OSReturnsNotRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property) -// CHECK-NEXT: OSReturnsRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property) +// CHECK-NEXT: OSReturnsNotRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_variable_is_parameter) +// CHECK-NEXT: OSReturnsRetained (SubjectMatchRule_function, SubjectMatchRule_objc_method, SubjectMatchRule_objc_property, SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: ObjCBoxable (SubjectMatchRule_record) // CHECK-NEXT: ObjCBridge (SubjectMatchRule_record, SubjectMatchRule_type_alias) // CHECK-NEXT: ObjCBridgeMutable (SubjectMatchRule_record) Index: clang/test/Sema/attr-osobject.cpp =================================================================== --- clang/test/Sema/attr-osobject.cpp +++ clang/test/Sema/attr-osobject.cpp @@ -37,12 +37,26 @@ return nullptr; } -struct __attribute__((os_returns_retained)) NoRetainAttrOnStruct {}; // expected-warning{{'os_returns_retained' attribute only applies to functions, Objective-C methods, and Objective-C properties}} +struct __attribute__((os_returns_retained)) NoRetainAttrOnStruct {}; // expected-warning{{'os_returns_retained' attribute only applies to functions, Objective-C methods, Objective-C properties, and parameters}} __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}} +struct __attribute__((os_returns_not_retained)) NoNotRetainedAttrOnStruct {}; // expected-warning{{'os_returns_not_retained' attribute only applies to functions, Objective-C methods, Objective-C properties, and parameters}} __attribute__((os_consumes_this)) void no_consumes_this_on_function() {} // expected-warning{{'os_consumes_this' attribute only applies to non-static member functions}} + +void write_into_out_parameter(__attribute__((os_returns_retained)) S** out) {} + +void write_into_out_parameter_ref(__attribute__((os_returns_retained)) S*& out) {} + +typedef S* SPtr; + +void write_into_out_parameter_typedef(__attribute__((os_returns_retained)) SPtr* out) {} + +void write_into_out_parameter_invalid(__attribute__((os_returns_retained)) S* out) {} // expected-warning{{'os_returns_retained' attribute only applies to pointer-to-pointer parameters}} + +void write_into_out_parameter_not_retained(__attribute__((os_returns_not_retained)) S **out) {} + +void write_into_not_retainedout_parameter_invalid(__attribute__((os_returns_not_retained)) S* out) {} // expected-warning{{'os_returns_not_retained' attribute only applies to pointer-to-pointer parameters}} Index: clang/test/Sema/attr-osobject.mm =================================================================== --- clang/test/Sema/attr-osobject.mm +++ clang/test/Sema/attr-osobject.mm @@ -8,8 +8,8 @@ - (void) takeS:(S*) __attribute__((os_consumed)) s; @end -typedef __attribute__((os_returns_retained)) id (^blockType)(); // expected-warning{{'os_returns_retained' attribute only applies to functions, Objective-C methods, and Objective-C properties}} +typedef __attribute__((os_returns_retained)) id (^blockType)(); // expected-warning{{'os_returns_retained' attribute only applies to functions, Objective-C methods, Objective-C properties, and parameters}} -__auto_type b = ^ id (id filter) __attribute__((os_returns_retained)) { // expected-warning{{'os_returns_retained' attribute only applies to functions, Objective-C methods, and Objective-C properties}} +__auto_type b = ^ id (id filter) __attribute__((os_returns_retained)) { // expected-warning{{'os_returns_retained' attribute only applies to functions, Objective-C methods, Objective-C properties, and parameters}} return filter; }; Index: clang/test/SemaObjC/attr-cf_returns.m =================================================================== --- clang/test/SemaObjC/attr-cf_returns.m +++ clang/test/SemaObjC/attr-cf_returns.m @@ -35,11 +35,11 @@ @property id valid2 CF_RETURNS_RETAINED; @end -void invalidParam(int a CF_RETURNS_RETAINED, // expected-warning{{'cf_returns_retained' attribute only applies to pointer-to-CF-pointer parameters}} - int *b CF_RETURNS_RETAINED, // expected-warning{{'cf_returns_retained' attribute only applies to pointer-to-CF-pointer parameters}} - id c CF_RETURNS_RETAINED, // expected-warning{{'cf_returns_retained' attribute only applies to pointer-to-CF-pointer parameters}} - void *d CF_RETURNS_RETAINED, // expected-warning{{'cf_returns_retained' attribute only applies to pointer-to-CF-pointer parameters}} - CFFooRef e CF_RETURNS_RETAINED); // expected-warning{{'cf_returns_retained' attribute only applies to pointer-to-CF-pointer parameters}} +void invalidParam(int a CF_RETURNS_RETAINED, // expected-warning{{'cf_returns_retained' attribute only applies to pointer-to-pointer parameters}} + int *b CF_RETURNS_RETAINED, // expected-warning{{'cf_returns_retained' attribute only applies to pointer-to-pointer parameters}} + id c CF_RETURNS_RETAINED, // expected-warning{{'cf_returns_retained' attribute only applies to pointer-to-pointer parameters}} + void *d CF_RETURNS_RETAINED, // expected-warning{{'cf_returns_retained' attribute only applies to pointer-to-pointer parameters}} + CFFooRef e CF_RETURNS_RETAINED); // expected-warning{{'cf_returns_retained' attribute only applies to pointer-to-pointer parameters}} void validParam(id *a CF_RETURNS_RETAINED, CFFooRef *b CF_RETURNS_RETAINED,