r201911 - [ObjC] Make attribute 'objc_protocol_requires_explicit_implementation' behave correctly with default property synthesis.
Ted Kremenek
kremenek at apple.com
Fri Feb 21 16:02:04 PST 2014
Author: kremenek
Date: Fri Feb 21 18:02:03 2014
New Revision: 201911
URL: http://llvm.org/viewvc/llvm-project?rev=201911&view=rev
Log:
[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.
Modified:
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Sema/SemaObjCProperty.cpp
cfe/trunk/test/SemaObjC/protocols-suppress-conformance.m
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=201911&r1=201910&r2=201911&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Feb 21 18:02:03 2014
@@ -2667,12 +2667,6 @@ public:
ObjCInterfaceDecl *IDecl);
void DefaultSynthesizeProperties(Scope *S, Decl *D);
- /// CollectImmediateProperties - This routine collects all properties in
- /// the class and its conforming protocols; but not those it its super class.
- void CollectImmediateProperties(ObjCContainerDecl *CDecl,
- 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'.
Modified: cfe/trunk/lib/Sema/SemaObjCProperty.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaObjCProperty.cpp?rev=201911&r1=201910&r2=201911&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaObjCProperty.cpp (original)
+++ cfe/trunk/lib/Sema/SemaObjCProperty.cpp Fri Feb 21 18:02:03 2014
@@ -1440,20 +1440,24 @@ bool Sema::DiagnosePropertyAccessorMisma
/// 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(Ob
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::DiagnoseUnimplementedProperti
// 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::DiagnoseUnimplementedProperti
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;
Modified: cfe/trunk/test/SemaObjC/protocols-suppress-conformance.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/protocols-suppress-conformance.m?rev=201911&r1=201910&r2=201911&view=diff
==============================================================================
--- cfe/trunk/test/SemaObjC/protocols-suppress-conformance.m (original)
+++ cfe/trunk/test/SemaObjC/protocols-suppress-conformance.m Fri Feb 21 18:02:03 2014
@@ -32,6 +32,19 @@ __attribute__((objc_protocol_requires_ex
@dynamic theWorstOfTimes;
@end
+ at interface ClassB_AlsoGood : ClassA <Protocol>
+ at property (readonly) id theWorstOfTimes;
+ at end
+
+// Default synthesis acts as if @dynamic
+// had been written for 'theWorstOfTimes' because
+// it is declared in ClassA. This is okay, since
+// the author of ClassB_AlsoGood needs explicitly
+// write @property in the @interface.
+ at implementation ClassB_AlsoGood // no-warning
+- (void) theBestOfTimes {}
+ at end
+
// Test that inherited protocols do not get the explicit conformance requirement.
@protocol Inherited
- (void) fairIsFoul;
More information about the cfe-commits
mailing list