diff options
author | Ted Kremenek <kremenek@apple.com> | 2014-02-22 00:02:03 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2014-02-22 00:02:03 +0000 |
commit | 1035a959dafb867fe30eeb70cc59f3cd7f905492 (patch) | |
tree | 1b3ee50004c56b783b97bd716fef920971a25226 /lib/Sema/SemaObjCProperty.cpp | |
parent | 21db05d136d6af2e90dcb148a307a71908d31049 (diff) |
[ObjC] Make attribute 'objc_protocol_requires_explicit_implementation' behave correctly with default property synthesis.
In particular, if we see an @property within the @interface of a class
conforming to a protocol with this attribute, we treat that as
if the implementation were available, per the rules of default
property synthesis.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201911 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaObjCProperty.cpp')
-rw-r--r-- | lib/Sema/SemaObjCProperty.cpp | 50 |
1 files changed, 37 insertions, 13 deletions
diff --git a/lib/Sema/SemaObjCProperty.cpp b/lib/Sema/SemaObjCProperty.cpp index 9b3643a2ed..08013f7cc1 100644 --- a/lib/Sema/SemaObjCProperty.cpp +++ b/lib/Sema/SemaObjCProperty.cpp @@ -1440,20 +1440,24 @@ bool Sema::DiagnosePropertyAccessorMismatch(ObjCPropertyDecl *property, /// CollectImmediateProperties - This routine collects all properties in /// the class and its conforming protocols; but not those in its super class. -void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, - ObjCContainerDecl::PropertyMap &PropMap, - ObjCContainerDecl::PropertyMap &SuperPropMap) { +static void CollectImmediateProperties(ObjCContainerDecl *CDecl, + ObjCContainerDecl::PropertyMap &PropMap, + ObjCContainerDecl::PropertyMap &SuperPropMap, + bool IncludeProtocols = true) { + if (ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl)) { for (ObjCContainerDecl::prop_iterator P = IDecl->prop_begin(), E = IDecl->prop_end(); P != E; ++P) { ObjCPropertyDecl *Prop = *P; PropMap[Prop->getIdentifier()] = Prop; } - // scan through class's protocols. - for (ObjCInterfaceDecl::all_protocol_iterator - PI = IDecl->all_referenced_protocol_begin(), - E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) - CollectImmediateProperties((*PI), PropMap, SuperPropMap); + if (IncludeProtocols) { + // Scan through class's protocols. + for (ObjCInterfaceDecl::all_protocol_iterator + PI = IDecl->all_referenced_protocol_begin(), + E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) + CollectImmediateProperties((*PI), PropMap, SuperPropMap); + } } if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) { if (!CATDecl->IsClassExtension()) @@ -1462,10 +1466,12 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl, ObjCPropertyDecl *Prop = *P; PropMap[Prop->getIdentifier()] = Prop; } - // scan through class's protocols. - for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(), - E = CATDecl->protocol_end(); PI != E; ++PI) - CollectImmediateProperties((*PI), PropMap, SuperPropMap); + if (IncludeProtocols) { + // Scan through class's protocols. + for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(), + E = CATDecl->protocol_end(); PI != E; ++PI) + CollectImmediateProperties((*PI), PropMap, SuperPropMap); + } } else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) { for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), @@ -1678,7 +1684,9 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, // Scan the @interface to see if any of the protocols it adopts // require an explicit implementation, via attribute // 'objc_protocol_requires_explicit_implementation'. - if (IDecl) + if (IDecl) { + OwningPtr<ObjCContainerDecl::PropertyMap> LazyMap; + for (ObjCInterfaceDecl::all_protocol_iterator PI = IDecl->all_referenced_protocol_begin(), PE = IDecl->all_referenced_protocol_end(); @@ -1686,15 +1694,31 @@ void Sema::DiagnoseUnimplementedProperties(Scope *S, ObjCImplDecl* IMPDecl, ObjCProtocolDecl *PDecl = *PI; if (!PDecl->hasAttr<ObjCExplicitProtocolImplAttr>()) continue; + // Lazily construct a set of all the properties in the @interface + // of the class, without looking at the superclass. We cannot + // use the call to CollectImmediateProperties() above as that + // utilizes information fromt he super class's properties as well + // as scans the adopted protocols. This work only triggers for protocols + // with the attribute, which is very rare, and only occurs when + // analyzing the @implementation. + if (!LazyMap) { + ObjCContainerDecl::PropertyMap NoNeedToImplPropMap; + LazyMap.reset(new ObjCContainerDecl::PropertyMap()); + CollectImmediateProperties(CDecl, *LazyMap, NoNeedToImplPropMap, + /* IncludeProtocols */ false); + } // Add the properties of 'PDecl' to the list of properties that // need to be implemented. for (ObjCProtocolDecl::prop_iterator PRI = PDecl->prop_begin(), PRE = PDecl->prop_end(); PRI != PRE; ++PRI) { ObjCPropertyDecl *PropDecl = *PRI; + if ((*LazyMap)[PRI->getIdentifier()]) + continue; PropMap[PRI->getIdentifier()] = PropDecl; } } + } if (PropMap.empty()) return; |