diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/lib/Sema/Sema.h | 9 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaObjCProperty.cpp | 32 | ||||
| -rw-r--r-- | clang/test/SemaObjC/default-synthesize.m | 4 | ||||
| -rw-r--r-- | clang/test/SemaObjC/super-class-protocol-conformance.m | 47 | 
4 files changed, 89 insertions, 3 deletions
diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 6c52ae5ceea..ba20ed1e1a7 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -1539,6 +1539,15 @@ public:    /// the class and its conforming protocols; but not those it its super class.    void CollectImmediateProperties(ObjCContainerDecl *CDecl,                    llvm::DenseMap<IdentifierInfo *, ObjCPropertyDecl*>& PropMap); +   +  /// ProtocolConformsToSuperClass - Returns true if class has a super class +  /// and it, or its nested super class conforms to the protocol. +  bool ProtocolConformsToSuperClass(const ObjCInterfaceDecl *IDecl,  +                                    const ObjCProtocolDecl *PDecl); +  /// ProtocolConformsToProtocol - Returns true if 2nd Protocol (PDecl) is +  /// qualified by the 1st. +  bool ProtocolConformsToProtocol(const ObjCProtocolDecl *NestedProtocol, +                                  const ObjCProtocolDecl *PDecl);    /// LookupPropertyDecl - Looks up a property in the current class and all    /// its protocols. diff --git a/clang/lib/Sema/SemaObjCProperty.cpp b/clang/lib/Sema/SemaObjCProperty.cpp index 13c75e4fe96..b73739fc555 100644 --- a/clang/lib/Sema/SemaObjCProperty.cpp +++ b/clang/lib/Sema/SemaObjCProperty.cpp @@ -719,7 +719,10 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,      // scan through class's protocols.      for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),           E = IDecl->protocol_end(); PI != E; ++PI) -      CollectImmediateProperties((*PI), PropMap); +      // Exclude property for protocols which conform to class's super-class,  +      // as super-class has to implement the property. +      if (!ProtocolConformsToSuperClass(IDecl, (*PI))) +        CollectImmediateProperties((*PI), PropMap);    }    if (ObjCCategoryDecl *CATDecl = dyn_cast<ObjCCategoryDecl>(CDecl)) {      if (!CATDecl->IsClassExtension()) @@ -748,6 +751,33 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,    }  } +/// ProtocolConformsToSuperClass - Returns true if class's given protocol +/// conforms to one of its super class's protocols. +bool Sema::ProtocolConformsToSuperClass(const ObjCInterfaceDecl *IDecl, +                                        const ObjCProtocolDecl *PDecl) { +  if (const ObjCInterfaceDecl *CDecl = IDecl->getSuperClass()) { +    for (ObjCInterfaceDecl::protocol_iterator PI = CDecl->protocol_begin(), +         E = CDecl->protocol_end(); PI != E; ++PI) { +      if (ProtocolConformsToProtocol((*PI), PDecl)) +        return true; +      return ProtocolConformsToSuperClass(CDecl, PDecl); +    } +  } +  return false; +} + +bool Sema::ProtocolConformsToProtocol(const ObjCProtocolDecl *NestedProtocol, +                                      const ObjCProtocolDecl *PDecl) { +  if (PDecl->getIdentifier() == NestedProtocol->getIdentifier()) +    return true; +  // scan through protocol's protocols. +  for (ObjCProtocolDecl::protocol_iterator PI = PDecl->protocol_begin(), +       E = PDecl->protocol_end(); PI != E; ++PI) +    if (ProtocolConformsToProtocol(NestedProtocol, (*PI))) +      return true; +  return false; +} +  /// LookupPropertyDecl - Looks up a property in the current class and all  /// its protocols.  ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl, diff --git a/clang/test/SemaObjC/default-synthesize.m b/clang/test/SemaObjC/default-synthesize.m index 21453d38414..283ad260a94 100644 --- a/clang/test/SemaObjC/default-synthesize.m +++ b/clang/test/SemaObjC/default-synthesize.m @@ -85,14 +85,14 @@  @interface TopClass <TopProtocol>   { -  id myString; // expected-note {{previously declared 'myString' here}} +  id myString;   }  @end  @interface SubClass : TopClass <TopProtocol>   @end -@implementation SubClass @end // expected-error {{property 'myString' attempting to use ivar 'myString' declared in super class 'TopClass'}} +@implementation SubClass @end   // rdar: // 7920807  @interface C @end diff --git a/clang/test/SemaObjC/super-class-protocol-conformance.m b/clang/test/SemaObjC/super-class-protocol-conformance.m new file mode 100644 index 00000000000..ac8bc70a998 --- /dev/null +++ b/clang/test/SemaObjC/super-class-protocol-conformance.m @@ -0,0 +1,47 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// rdar: // 7884086 + +@interface NSObject @end + +@protocol TopProtocol +  @property (readonly) id myString; // expected-warning {{property 'myString' requires method 'myString' to be defined}} +@end + +@protocol SubProtocol <TopProtocol> +@end + +@interface TopClass : NSObject <TopProtocol> {} +@end + +@interface SubClass : TopClass <SubProtocol> {} +@end + +@interface SubClass1 : TopClass {}	 +@end + +@implementation SubClass1 @end // Test1 - No Warning + +@implementation TopClass  // expected-note {{implementation is here}} +@end + +@implementation SubClass // Test3 - No Warning  +@end + +@interface SubClass2  : TopClass<TopProtocol>  +@end + +@implementation SubClass2 @end // Test 4 - No Warning + +@interface SubClass3 : TopClass<SubProtocol> @end +@implementation SubClass3 @end	// Test 5 - No Warning  + +@interface SubClass4 : SubClass3 @end +@implementation SubClass4 @end	// Test 5 - No Warning + +@protocol NewProtocol +  @property (readonly) id myNewString; // expected-warning {{property 'myNewString' requires method 'myNewString' to be defined}} +@end + +@interface SubClass5 : SubClass4 <NewProtocol> @end +@implementation SubClass5 @end   // expected-note {{implementation is here}} +  | 

