summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaObjCProperty.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2014-02-22 00:02:03 +0000
committerTed Kremenek <kremenek@apple.com>2014-02-22 00:02:03 +0000
commit1035a959dafb867fe30eeb70cc59f3cd7f905492 (patch)
tree1b3ee50004c56b783b97bd716fef920971a25226 /lib/Sema/SemaObjCProperty.cpp
parent21db05d136d6af2e90dcb148a307a71908d31049 (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.cpp50
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;