aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2013-02-14 19:07:19 +0000
committerFariborz Jahanian <fjahanian@apple.com>2013-02-14 19:07:19 +0000
commit26202291b161f8598c0c342cba12c6552e44d44c (patch)
tree28002014819230f52e08411caa739e5200c9f9a4
parent697a68590a75f5cd2326c8f686a6c666b51688b6 (diff)
objective-C: When implementing custom accessor method for
a property, the -Wdirect-ivar-access should not warn when accessing the property's synthesized instance variable. // rdar://13142820 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@175195 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Sema/Sema.h6
-rw-r--r--lib/Sema/SemaExpr.cpp3
-rw-r--r--lib/Sema/SemaExprMember.cpp3
-rw-r--r--lib/Sema/SemaObjCProperty.cpp27
-rw-r--r--test/SemaObjC/warn-direct-ivar-access.m24
5 files changed, 60 insertions, 3 deletions
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index dbdfb1ebef..ef39bd260d 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -2418,6 +2418,12 @@ public:
llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap,
llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& SuperPropMap);
+ /// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
+ /// an ivar synthesized for 'Method' and 'Method' is a property accessor
+ /// declared in class 'IFace'.
+ bool IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
+ ObjCMethodDecl *Method, ObjCIvarDecl *IV);
+
/// Called by ActOnProperty to handle \@property declarations in
/// class extensions.
ObjCPropertyDecl *HandlePropertyInClassExtension(Scope *S,
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index b3ba2dc4ae..0ed460cc5e 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -2042,7 +2042,8 @@ Sema::LookupInObjCMethod(LookupResult &Lookup, Scope *S,
MarkAnyDeclReferenced(Loc, IV, true);
ObjCMethodFamily MF = CurMethod->getMethodFamily();
- if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize)
+ if (MF != OMF_init && MF != OMF_dealloc && MF != OMF_finalize &&
+ !IvarBacksCurrentMethodAccessor(IFace, CurMethod, IV))
Diag(Loc, diag::warn_direct_ivar_access) << IV->getDeclName();
ObjCIvarRefExpr *Result = new (Context) ObjCIvarRefExpr(IV, IV->getType(),
diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp
index f1f8104020..16f4a43bd7 100644
--- a/lib/Sema/SemaExprMember.cpp
+++ b/lib/Sema/SemaExprMember.cpp
@@ -1259,7 +1259,8 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr,
if (ObjCMethodDecl *MD = getCurMethodDecl()) {
ObjCMethodFamily MF = MD->getMethodFamily();
warn = (MF != OMF_init && MF != OMF_dealloc &&
- MF != OMF_finalize);
+ MF != OMF_finalize &&
+ !IvarBacksCurrentMethodAccessor(IDecl, MD, IV));
}
if (warn)
Diag(MemberLoc, diag::warn_direct_ivar_access) << IV->getDeclName();
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp
index 1fe88a26ab..e238b7ea20 100644
--- a/lib/Sema/SemaObjCProperty.cpp
+++ b/lib/Sema/SemaObjCProperty.cpp
@@ -1541,6 +1541,33 @@ static void CollectSuperClassPropertyImplementations(ObjCInterfaceDecl *CDecl,
}
}
+/// IvarBacksCurrentMethodAccessor - This routine returns 'true' if 'IV' is
+/// an ivar synthesized for 'Method' and 'Method' is a property accessor
+/// declared in class 'IFace'.
+bool
+Sema::IvarBacksCurrentMethodAccessor(ObjCInterfaceDecl *IFace,
+ ObjCMethodDecl *Method, ObjCIvarDecl *IV) {
+ if (!IV->getSynthesize())
+ return false;
+ ObjCMethodDecl *IMD = IFace->lookupMethod(Method->getSelector(),
+ Method->isInstanceMethod());
+ if (!IMD || !IMD->isPropertyAccessor())
+ return false;
+
+ // look up a property declaration whose one of its accessors is implemented
+ // by this method.
+ for (ObjCContainerDecl::prop_iterator P = IFace->prop_begin(),
+ E = IFace->prop_end(); P != E; ++P) {
+ ObjCPropertyDecl *property = *P;
+ if ((property->getGetterName() == IMD->getSelector() ||
+ property->getSetterName() == IMD->getSelector()) &&
+ (property->getPropertyIvarDecl() == IV))
+ return true;
+ }
+ return false;
+}
+
+
/// \brief Default synthesizes all properties which must be synthesized
/// in class's \@implementation.
void Sema::DefaultSynthesizeProperties(Scope *S, ObjCImplDecl* IMPDecl,
diff --git a/test/SemaObjC/warn-direct-ivar-access.m b/test/SemaObjC/warn-direct-ivar-access.m
index 4f242e6b33..283a00faee 100644
--- a/test/SemaObjC/warn-direct-ivar-access.m
+++ b/test/SemaObjC/warn-direct-ivar-access.m
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -Wdirect-ivar-access -verify -Wno-objc-root-class %s
+// RUN: %clang_cc1 -fsyntax-only -fobjc-arc -fobjc-runtime-has-weak -fobjc-default-synthesize-properties -Wdirect-ivar-access -verify -Wno-objc-root-class %s
// rdar://6505197
__attribute__((objc_root_class)) @interface MyObject {
@@ -54,3 +54,25 @@ id Test32(__weak ITest32 *x) {
: (*x).ivar; // expected-error {{dereferencing a __weak pointer is not allowed}}
}
+// rdar://13142820
+@protocol PROTOCOL
+@property (copy, nonatomic) id property_in_protocol;
+@end
+
+__attribute__((objc_root_class)) @interface INTF <PROTOCOL>
+@property (copy, nonatomic) id foo;
+- (id) foo;
+@end
+
+@interface INTF()
+@property (copy, nonatomic) id foo1;
+- (id) foo1;
+@end
+
+@implementation INTF
+- (id) foo { return _foo; }
+- (id) property_in_protocol { return _property_in_protocol; } // expected-warning {{instance variable '_property_in_protocol' is being directly accessed}}
+- (id) foo1 { return _foo1; }
+@synthesize property_in_protocol = _property_in_protocol;
+@end
+