aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td3
-rw-r--r--lib/Sema/SemaDeclAttr.cpp2
-rw-r--r--lib/Sema/SemaObjCProperty.cpp12
-rw-r--r--test/SemaObjC/arc.m20
-rw-r--r--test/SemaObjC/property-ns-returns-not-retained-attr.m21
5 files changed, 57 insertions, 1 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index dd378fa191..1fc43c9dd0 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -441,6 +441,9 @@ def warn_atomic_property_rule : Warning<
def warn_ownin_getter_rule : Warning<
"property's synthesized getter follows Cocoa naming"
" convention for returning 'owned' objects">;
+def warn_property_getter_owning_mismatch : Warning<
+ "property declared as returning non-retained objects"
+ "; getter returning retained objects">;
def err_ownin_getter_rule : Error<
"property's synthesized getter follows Cocoa naming"
" convention for returning 'owned' objects">;
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 240c15a8e0..9302277e13 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -2716,6 +2716,8 @@ static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &attr,
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
returnType = MD->getResultType();
+ else if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(d))
+ returnType = PD->getType();
else if (S.getLangOptions().ObjCAutoRefCount && hasDeclarator(d) &&
(attr.getKind() == AttributeList::AT_ns_returns_retained))
return; // ignore: was handled as a type attribute
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 22f9b3e092..012e2569c3 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -737,6 +737,12 @@ Decl *Sema::ActOnPropertyImplDecl(Scope *S,
PIDecl->setGetterCXXConstructor(ResExpr);
}
}
+ if (property->hasAttr<NSReturnsNotRetainedAttr>() &&
+ !getterMethod->hasAttr<NSReturnsNotRetainedAttr>()) {
+ Diag(getterMethod->getLocation(),
+ diag::warn_property_getter_owning_mismatch);
+ Diag(property->getLocation(), diag::note_property_declare);
+ }
}
if (ObjCMethodDecl *setterMethod = property->getSetterMethodDecl()) {
setterMethod->createImplicitParams(Context, IDecl);
@@ -1369,7 +1375,8 @@ void Sema::DiagnoseOwningPropertyGetterSynthesis(const ObjCImplementationDecl *D
continue;
const ObjCPropertyDecl *PD = PID->getPropertyDecl();
- if (PD && !D->getInstanceMethod(PD->getGetterName())) {
+ if (PD && !PD->hasAttr<NSReturnsNotRetainedAttr>() &&
+ !D->getInstanceMethod(PD->getGetterName())) {
ObjCMethodDecl *method = PD->getGetterMethodDecl();
if (!method)
continue;
@@ -1465,6 +1472,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// and the real context should be the same.
if (lexicalDC)
GetterMethod->setLexicalDeclContext(lexicalDC);
+ if (property->hasAttr<NSReturnsNotRetainedAttr>())
+ GetterMethod->addAttr(
+ ::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
} else
// A user declared getter will be synthesize when @synthesize of
// the property with the same name is seen in the @implementation
diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m
index 3a548e084a..8d42d101dd 100644
--- a/test/SemaObjC/arc.m
+++ b/test/SemaObjC/arc.m
@@ -572,3 +572,23 @@ int Test33(id someid) {
return (int)someid;
}
+// rdar://9636091
+@interface I34
+@property (nonatomic, retain) id newName __attribute__((ns_returns_not_retained)) ;
+
+@property (nonatomic, retain) id newName1 __attribute__((ns_returns_not_retained)) ;
+- (id) newName1 __attribute__((ns_returns_not_retained));
+
+@property (nonatomic, retain) id newName2 __attribute__((ns_returns_not_retained)); // expected-note {{roperty declared here}}
+- (id) newName2; // expected-warning {{property declared as returning non-retained objects; getter returning retained objects}}
+@end
+
+@implementation I34
+@synthesize newName;
+
+@synthesize newName1;
+- (id) newName1 { return 0; }
+
+@synthesize newName2;
+@end
+
diff --git a/test/SemaObjC/property-ns-returns-not-retained-attr.m b/test/SemaObjC/property-ns-returns-not-retained-attr.m
new file mode 100644
index 0000000000..187c93f3d3
--- /dev/null
+++ b/test/SemaObjC/property-ns-returns-not-retained-attr.m
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin11 -fobjc-nonfragile-abi -fsyntax-only -verify %s
+// rdar://9636091
+
+@interface I
+@property (nonatomic, retain) id newName __attribute__((ns_returns_not_retained)) ;
+
+@property (nonatomic, retain) id newName1 __attribute__((ns_returns_not_retained)) ;
+- (id) newName1 __attribute__((ns_returns_not_retained));
+
+@property (nonatomic, retain) id newName2 __attribute__((ns_returns_not_retained)); // expected-note {{roperty declared here}}
+- (id) newName2; // expected-warning {{property declared as returning non-retained objects; getter returning retained objects}}
+@end
+
+@implementation I
+@synthesize newName;
+
+@synthesize newName1;
+- (id) newName1 { return 0; }
+
+@synthesize newName2;
+@end