diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index dbdfb1ebef3c..ef39bd260dcb 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2418,6 +2418,12 @@ public: llvm::DenseMap& PropMap, llvm::DenseMap& 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/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index b3ba2dc4ae92..0ed460cc5e28 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/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/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index f1f810402026..16f4a43bd77f 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/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/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 1fe88a26ab0e..e238b7ea20d4 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/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/clang/test/SemaObjC/warn-direct-ivar-access.m b/clang/test/SemaObjC/warn-direct-ivar-access.m index 4f242e6b338c..283a00faee8c 100644 --- a/clang/test/SemaObjC/warn-direct-ivar-access.m +++ b/clang/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 +@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 +