summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Sema.h1
-rw-r--r--clang/lib/Sema/SemaDeclObjC.cpp20
-rw-r--r--clang/lib/Sema/SemaObjCProperty.cpp8
-rw-r--r--clang/test/CodeGenObjC/arc-property.m45
4 files changed, 64 insertions, 10 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d17557260ed..5b93e513eaf 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -6361,6 +6361,7 @@ public:
ObjCMethodDecl *LookupMethodInObjectType(Selector Sel, QualType Ty,
bool IsInstance);
+ bool CheckARCMethodDecl(ObjCMethodDecl *method);
bool inferObjCARCLifetime(ValueDecl *decl);
ExprResult
diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp
index 5d16f3eae6f..96a432a108e 100644
--- a/clang/lib/Sema/SemaDeclObjC.cpp
+++ b/clang/lib/Sema/SemaDeclObjC.cpp
@@ -193,7 +193,7 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
/// \brief Check a method declaration for compatibility with the Objective-C
/// ARC conventions.
-static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) {
+bool Sema::CheckARCMethodDecl(ObjCMethodDecl *method) {
ObjCMethodFamily family = method->getMethodFamily();
switch (family) {
case OMF_None:
@@ -207,17 +207,17 @@ static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) {
return false;
case OMF_dealloc:
- if (!S.Context.hasSameType(method->getResultType(), S.Context.VoidTy)) {
+ if (!Context.hasSameType(method->getResultType(), Context.VoidTy)) {
SourceRange ResultTypeRange;
if (const TypeSourceInfo *ResultTypeInfo
= method->getResultTypeSourceInfo())
ResultTypeRange = ResultTypeInfo->getTypeLoc().getSourceRange();
if (ResultTypeRange.isInvalid())
- S.Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
+ Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
<< method->getResultType()
<< FixItHint::CreateInsertion(method->getSelectorLoc(0), "(void)");
else
- S.Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
+ Diag(method->getLocation(), diag::error_dealloc_bad_result_type)
<< method->getResultType()
<< FixItHint::CreateReplacement(ResultTypeRange, "void");
return true;
@@ -226,11 +226,11 @@ static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) {
case OMF_init:
// If the method doesn't obey the init rules, don't bother annotating it.
- if (S.checkInitMethod(method, QualType()))
+ if (checkInitMethod(method, QualType()))
return true;
- method->addAttr(new (S.Context) NSConsumesSelfAttr(SourceLocation(),
- S.Context));
+ method->addAttr(new (Context) NSConsumesSelfAttr(SourceLocation(),
+ Context));
// Don't add a second copy of this attribute, but otherwise don't
// let it be suppressed.
@@ -249,8 +249,8 @@ static bool CheckARCMethodDecl(Sema &S, ObjCMethodDecl *method) {
break;
}
- method->addAttr(new (S.Context) NSReturnsRetainedAttr(SourceLocation(),
- S.Context));
+ method->addAttr(new (Context) NSReturnsRetainedAttr(SourceLocation(),
+ Context));
return false;
}
@@ -3032,7 +3032,7 @@ Decl *Sema::ActOnMethodDeclaration(
bool ARCError = false;
if (getLangOpts().ObjCAutoRefCount)
- ARCError = CheckARCMethodDecl(*this, ObjCMethod);
+ ARCError = CheckARCMethodDecl(ObjCMethod);
// Infer the related result type when possible.
if (!ARCError && RTC == Sema::RTC_Compatible &&
diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp
index 824a249084c..68fb07f8feb 100644
--- a/clang/lib/Sema/SemaObjCProperty.cpp
+++ b/clang/lib/Sema/SemaObjCProperty.cpp
@@ -1936,6 +1936,9 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
if (property->hasAttr<NSReturnsNotRetainedAttr>())
GetterMethod->addAttr(
::new (Context) NSReturnsNotRetainedAttr(Loc, Context));
+
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckARCMethodDecl(GetterMethod);
} else
// A user declared getter will be synthesize when @synthesize of
// the property with the same name is seen in the @implementation
@@ -1984,6 +1987,11 @@ void Sema::ProcessPropertyDecl(ObjCPropertyDecl *property,
// and the real context should be the same.
if (lexicalDC)
SetterMethod->setLexicalDeclContext(lexicalDC);
+
+ // It's possible for the user to have set a very odd custom
+ // setter selector that causes it to have a method family.
+ if (getLangOpts().ObjCAutoRefCount)
+ CheckARCMethodDecl(SetterMethod);
} else
// A user declared setter will be synthesize when @synthesize of
// the property with the same name is seen in the @implementation
diff --git a/clang/test/CodeGenObjC/arc-property.m b/clang/test/CodeGenObjC/arc-property.m
index 0e01fb7edae..dde02d7dd71 100644
--- a/clang/test/CodeGenObjC/arc-property.m
+++ b/clang/test/CodeGenObjC/arc-property.m
@@ -86,4 +86,49 @@ static Class theGlobalClass;
// CHECK-NEXT: call void @objc_storeStrong(i8** [[T3]], i8* null) [[NUW]]
// CHECK-NEXT: ret void
+// rdar://13115896
+@interface Test3
+@property id copyMachine;
+@end
+
+void test3(Test3 *t) {
+ id x = t.copyMachine;
+ x = [t copyMachine];
+}
+// CHECK: define void @test3([[TEST3:%.*]]*
+// Prologue.
+// CHECK: [[T:%.*]] = alloca [[TEST3]]*,
+// CHECK-NEXT: [[X:%.*]] = alloca i8*,
+// Property access.
+// CHECK: [[T0:%.*]] = load [[TEST3]]** [[T]],
+// CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8*
+// CHECK-NEXT: [[T2:%.*]] = call i8* bitcast ({{.*}} @objc_msgSend to {{.*}})(i8* [[T1]], i8* [[SEL]])
+// CHECK-NEXT: store i8* [[T2]], i8** [[X]],
+// Message send.
+// CHECK-NEXT: [[T0:%.*]] = load [[TEST3]]** [[T]],
+// CHECK-NEXT: [[SEL:%.*]] = load i8** @"\01L_OBJC_SELECTOR_REFERENCES
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[TEST3]]* [[T0]] to i8*
+// CHECK-NEXT: [[T2:%.*]] = call i8* bitcast ({{.*}} @objc_msgSend to {{.*}})(i8* [[T1]], i8* [[SEL]])
+// CHECK-NEXT: [[T3:%.*]] = load i8** [[X]],
+// CHECK-NEXT: store i8* [[T2]], i8** [[X]],
+// CHECK-NEXT: call void @objc_release(i8* [[T3]])
+// Epilogue.
+// CHECK-NEXT: call void @objc_storeStrong(i8** [[X]], i8* null)
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[TEST3]]** [[T]] to i8**
+// CHECK-NEXT: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK-NEXT: ret void
+
+@implementation Test3
+- (id) copyMachine {
+ extern id test3_helper(void);
+ return test3_helper();
+}
+// CHECK: define internal i8* @"\01-[Test3 copyMachine]"(
+// CHECK: [[T0:%.*]] = call i8* @test3_helper()
+// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retainAutoreleasedReturnValue(i8* [[T0]])
+// CHECK-NEXT: ret i8* [[T1]]
+- (void) setCopyMachine: (id) x {}
+@end
+
// CHECK: attributes [[NUW]] = { nounwind }
OpenPOWER on IntegriCloud