]> granicus.if.org Git - clang/commitdiff
Split ObjCInterfaceDecl::ReferencedProtocols into two lists: ReferencedProtocols...
authorTed Kremenek <kremenek@apple.com>
Wed, 1 Sep 2010 01:21:15 +0000 (01:21 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 1 Sep 2010 01:21:15 +0000 (01:21 +0000)
(and thus protocol_begin(), protocol_end()) now only contains the list of protocols that were directly referenced in
an @interface declaration.  'all_referenced_protocol_[begin,end]()' now returns the set of protocols that were referenced
in both the @interface and class extensions.  The latter is needed for semantic analysis/codegen, while the former is
needed to maintain the lexical information of the original source.

Fixes <rdar://problem/8380046>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112691 91177308-0d34-0410-b5e6-96231b3b80d8

12 files changed:
include/clang/AST/DeclObjC.h
lib/AST/ASTContext.cpp
lib/AST/ASTImporter.cpp
lib/AST/DeclObjC.cpp
lib/CodeGen/CGObjCMac.cpp
lib/Sema/SemaCodeComplete.cpp
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaLookup.cpp
lib/Sema/SemaObjCProperty.cpp
lib/Serialization/ASTReaderDecl.cpp
lib/Serialization/ASTWriterDecl.cpp
test/Index/local-symbols.m

index da1278cf5d8d6b222fb98cc5fb454af9e296b485..ad26748e1343d888a645cca2dc99f9db857fdd42 100644 (file)
@@ -443,8 +443,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl {
   /// Class's super class.
   ObjCInterfaceDecl *SuperClass;
 
-  /// Protocols referenced in interface header declaration
+  /// Protocols referenced in the @interface  declaration
   ObjCProtocolList ReferencedProtocols;
+  
+  /// Protocols reference in both the @interface and class extensions.
+  ObjCList<ObjCProtocolDecl> AllReferencedProtocols;
 
   /// List of categories defined for this class.
   /// FIXME: Why is this a linked list??
@@ -489,23 +492,44 @@ public:
   }
 
   typedef ObjCProtocolList::iterator protocol_iterator;
-  protocol_iterator protocol_begin() const {return ReferencedProtocols.begin();}
-  protocol_iterator protocol_end() const { return ReferencedProtocols.end(); }
+  
+  protocol_iterator protocol_begin() const {
+    return ReferencedProtocols.begin();
+  }
+  protocol_iterator protocol_end() const {
+    return ReferencedProtocols.end();
+  }
+
   typedef ObjCProtocolList::loc_iterator protocol_loc_iterator;
+
   protocol_loc_iterator protocol_loc_begin() const { 
     return ReferencedProtocols.loc_begin(); 
   }
+
   protocol_loc_iterator protocol_loc_end() const { 
     return ReferencedProtocols.loc_end(); 
   }
-  unsigned protocol_size() const { return ReferencedProtocols.size(); }
+  
+  typedef ObjCList<ObjCProtocolDecl>::iterator all_protocol_iterator;
+  
+  all_protocol_iterator all_referenced_protocol_begin() const {
+    return AllReferencedProtocols.empty() ? protocol_begin()
+      : AllReferencedProtocols.begin();
+  }
+  all_protocol_iterator all_referenced_protocol_end() const {
+    return AllReferencedProtocols.empty() ? protocol_end() 
+      : AllReferencedProtocols.end();
+  }
 
   typedef specific_decl_iterator<ObjCIvarDecl> ivar_iterator;
+
   ivar_iterator ivar_begin() const { return  ivar_iterator(decls_begin()); }
   ivar_iterator ivar_end() const { return ivar_iterator(decls_end()); }
+
   unsigned ivar_size() const {
     return std::distance(ivar_begin(), ivar_end());
   }
+  
   bool ivar_empty() const { return ivar_begin() == ivar_end(); }
   
   ObjCIvarDecl  *all_declared_ivar_begin();
@@ -522,7 +546,6 @@ public:
   /// into the protocol list for this class.
   void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, 
                                        unsigned Num,
-                                       const SourceLocation *Locs,
                                        ASTContext &C);
 
   bool isForwardDecl() const { return ForwardDecl; }
@@ -604,6 +627,9 @@ public:
   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
   static bool classof(const ObjCInterfaceDecl *D) { return true; }
   static bool classofKind(Kind K) { return K == ObjCInterface; }
+
+  friend class ASTDeclReader;
+  friend class ASTDeclWriter;
 };
 
 /// ObjCIvarDecl - Represents an ObjC instance variable. In general, ObjC
index 8c61b5c7503a9037236c3cfcd70b19acc8f62020..574ada39807bd72f838185d553c90e9f5002f06c 100644 (file)
@@ -897,8 +897,10 @@ void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI,
 void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
                           llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols) {
   if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) {
-    for (ObjCInterfaceDecl::protocol_iterator P = OI->protocol_begin(),
-         PE = OI->protocol_end(); P != PE; ++P) {
+    // We can use protocol_iterator here instead of
+    // all_referenced_protocol_iterator since we are walking all categories.    
+    for (ObjCInterfaceDecl::all_protocol_iterator P = OI->all_referenced_protocol_begin(),
+         PE = OI->all_referenced_protocol_end(); P != PE; ++P) {
       ObjCProtocolDecl *Proto = (*P);
       Protocols.insert(Proto);
       for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(),
@@ -918,7 +920,7 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl,
         SD = SD->getSuperClass();
       }
   } else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) {
-    for (ObjCInterfaceDecl::protocol_iterator P = OC->protocol_begin(),
+    for (ObjCCategoryDecl::protocol_iterator P = OC->protocol_begin(),
          PE = OC->protocol_end(); P != PE; ++P) {
       ObjCProtocolDecl *Proto = (*P);
       Protocols.insert(Proto);
index eee41a6c2e36433423eb17b8b229fd9d40ebb7bb..2edd09c067e98e163c17439243dffb79bccdca24 100644 (file)
@@ -2553,6 +2553,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
     llvm::SmallVector<SourceLocation, 4> ProtocolLocs;
     ObjCInterfaceDecl::protocol_loc_iterator 
       FromProtoLoc = D->protocol_loc_begin();
+    
+    // FIXME: Should we be usng all_referenced_protocol_begin() here?
     for (ObjCInterfaceDecl::protocol_iterator FromProto = D->protocol_begin(),
                                            FromProtoEnd = D->protocol_end();
        FromProto != FromProtoEnd;
index 28c7a49a1322eb4103c37ec6c3c1cccc8c1094f4..d952cc36ef1dd8db128a86d875c93716bf3fd877 100644 (file)
@@ -120,8 +120,9 @@ ObjCContainerDecl::FindPropertyDeclaration(IdentifierInfo *PropertyId) const {
             return P;
 
       // Look through protocols.
-      for (ObjCInterfaceDecl::protocol_iterator
-            I = OID->protocol_begin(), E = OID->protocol_end(); I != E; ++I)
+      for (ObjCInterfaceDecl::all_protocol_iterator
+            I = OID->all_referenced_protocol_begin(),
+            E = OID->all_referenced_protocol_end(); I != E; ++I)
         if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
           return P;
 
@@ -157,8 +158,9 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
     return PD;
 
   // Look through protocols.
-  for (ObjCInterfaceDecl::protocol_iterator
-        I = protocol_begin(), E = protocol_end(); I != E; ++I)
+  for (ObjCInterfaceDecl::all_protocol_iterator
+        I = all_referenced_protocol_begin(),
+        E = all_referenced_protocol_end(); I != E; ++I)
     if (ObjCPropertyDecl *P = (*I)->FindPropertyDeclaration(PropertyId))
       return P;
 
@@ -167,23 +169,23 @@ ObjCInterfaceDecl::FindPropertyVisibleInPrimaryClass(
 
 void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
                               ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
-                              const SourceLocation *Locs,
                               ASTContext &C)
 {
-  if (ReferencedProtocols.empty()) {
-    ReferencedProtocols.set(ExtList, ExtNum, Locs, C);
+  if (AllReferencedProtocols.empty() && ReferencedProtocols.empty()) {
+    AllReferencedProtocols.set(ExtList, ExtNum, C);
     return;
   }
+  
   // Check for duplicate protocol in class's protocol list.
-  // This is (O)2. But it is extremely rare and number of protocols in
+  // This is O(n*m). But it is extremely rare and number of protocols in
   // class or its extension are very few.
   llvm::SmallVector<ObjCProtocolDecl*, 8> ProtocolRefs;
-  llvm::SmallVector<SourceLocation, 8> ProtocolLocs;
   for (unsigned i = 0; i < ExtNum; i++) {
     bool protocolExists = false;
     ObjCProtocolDecl *ProtoInExtension = ExtList[i];
-    for (protocol_iterator p = protocol_begin(), e = protocol_end();
-         p != e; p++) {
+    for (all_protocol_iterator
+          p = all_referenced_protocol_begin(),
+          e = all_referenced_protocol_end(); p != e; ++p) {
       ObjCProtocolDecl *Proto = (*p);
       if (C.ProtocolCompatibleWithProtocol(ProtoInExtension, Proto)) {
         protocolExists = true;
@@ -192,22 +194,20 @@ void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
     }
     // Do we want to warn on a protocol in extension class which
     // already exist in the class? Probably not.
-    if (!protocolExists) {
+    if (!protocolExists)
       ProtocolRefs.push_back(ProtoInExtension);
-      ProtocolLocs.push_back(Locs[i]);
-    }
   }
+
   if (ProtocolRefs.empty())
     return;
+
   // Merge ProtocolRefs into class's protocol list;
-  protocol_loc_iterator pl = protocol_loc_begin();
-  for (protocol_iterator p = protocol_begin(), e = protocol_end();
-       p != e; ++p, ++pl) {
+  for (all_protocol_iterator p = all_referenced_protocol_begin(), 
+        e = all_referenced_protocol_end(); p != e; ++p) {
     ProtocolRefs.push_back(*p);
-    ProtocolLocs.push_back(*pl);
   }
-  unsigned NumProtoRefs = ProtocolRefs.size();
-  setProtocolList(ProtocolRefs.data(), NumProtoRefs, ProtocolLocs.data(), C);
+
+  AllReferencedProtocols.set(ProtocolRefs.data(), ProtocolRefs.size(), C);
 }
 
 /// getFirstClassExtension - Find first class extension of the given class.
index f4ff951be27cdb6b6203135e7f74f661bb339dac..f397c56b6deed4226b23fb8a17eeb81f1709eda3 100644 (file)
@@ -1990,8 +1990,9 @@ llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
                                                    Prop));
   }
   if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
-    for (ObjCInterfaceDecl::protocol_iterator P = OID->protocol_begin(),
-         E = OID->protocol_end(); P != E; ++P)
+    for (ObjCInterfaceDecl::all_protocol_iterator
+         P = OID->all_referenced_protocol_begin(),
+         E = OID->all_referenced_protocol_end(); P != E; ++P)
       PushProtocolProperties(PropertySet, Properties, Container, (*P), 
                              ObjCTypes);
   }
@@ -2179,8 +2180,8 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
     const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
   llvm::Constant *Protocols =
     EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
-                     Interface->protocol_begin(),
-                     Interface->protocol_end());
+                     Interface->all_referenced_protocol_begin(),
+                     Interface->all_referenced_protocol_end());
   unsigned Flags = eClassFlags_Factory;
   if (ID->getNumIvarInitializers())
     Flags |= eClassFlags_HasCXXStructors;
@@ -4804,8 +4805,8 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
   assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
   Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
                                 + OID->getName(),
-                                OID->protocol_begin(),
-                                OID->protocol_end());
+                                OID->all_referenced_protocol_begin(),
+                                OID->all_referenced_protocol_end());
 
   if (flags & CLS_META)
     Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
index cef3546cc10b6dc48f4ce2fb3da1f19b93903c37..7088e55304f1f863445e0eceb8a33b3361cb97ed 100644 (file)
@@ -2686,9 +2686,9 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
     }
     
     // Look through protocols.
-    for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
-                                              E = IFace->protocol_end(); 
-         I != E; ++I)
+    for (ObjCInterfaceDecl::all_protocol_iterator
+         I = IFace->all_referenced_protocol_begin(),
+         E = IFace->all_referenced_protocol_end(); I != E; ++I)
       AddObjCProperties(*I, AllowCategories, CurContext, Results);
     
     // Look in the superclass.
@@ -2698,8 +2698,8 @@ static void AddObjCProperties(ObjCContainerDecl *Container,
   } else if (const ObjCCategoryDecl *Category
                                     = dyn_cast<ObjCCategoryDecl>(Container)) {
     // Look through protocols.
-    for (ObjCInterfaceDecl::protocol_iterator P = Category->protocol_begin(),
-                                           PEnd = Category->protocol_end(); 
+    for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
+                                          PEnd = Category->protocol_end(); 
          P != PEnd; ++P)
       AddObjCProperties(*P, AllowCategories, CurContext, Results);
   }
index 3c6f2243985a7d54696bf65758125902d34d46ca..a6902a3e391c8a15246525aec9d8751b1e4caee5 100644 (file)
@@ -485,8 +485,7 @@ ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc,
     // Protocols in the class extension belong to the class.
     if (CDecl->IsClassExtension())
      IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs, 
-                                            NumProtoRefs, ProtoLocs,
-                                            Context); 
+                                            NumProtoRefs, Context); 
   }
 
   CheckObjCDeclScope(CDecl);
@@ -924,8 +923,9 @@ void Sema::MatchAllMethodDeclarations(const llvm::DenseSet<Selector> &InsMap,
   }
   if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
     // Check for any implementation of a methods declared in protocol.
-    for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
-         E = I->protocol_end(); PI != E; ++PI)
+    for (ObjCInterfaceDecl::all_protocol_iterator
+          PI = I->all_referenced_protocol_begin(),
+          E = I->all_referenced_protocol_end(); PI != E; ++PI)
       MatchAllMethodDeclarations(InsMap, ClsMap, InsMapSeen, ClsMapSeen,
                                  IMPDecl,
                                  (*PI), IncompleteImpl, false);
@@ -971,8 +971,9 @@ void Sema::ImplMethodsVsClassMethods(Scope *S, ObjCImplDecl* IMPDecl,
   // implemented in the implementation class.
 
   if (ObjCInterfaceDecl *I = dyn_cast<ObjCInterfaceDecl> (CDecl)) {
-    for (ObjCInterfaceDecl::protocol_iterator PI = I->protocol_begin(),
-         E = I->protocol_end(); PI != E; ++PI)
+    for (ObjCInterfaceDecl::all_protocol_iterator
+          PI = I->all_referenced_protocol_begin(),
+          E = I->all_referenced_protocol_end(); PI != E; ++PI)
       CheckProtocolMethodDefs(IMPDecl->getLocation(), *PI, IncompleteImpl,
                               InsMap, ClsMap, I);
     // Check class extensions (unnamed categories)
index 1e047106cd45b389e5373a5f80d63f3649a11ed0..306e95a497e8baabcbc8eb6bbea3c8e8f8eee0c9 100644 (file)
@@ -2502,8 +2502,9 @@ static void LookupVisibleDecls(DeclContext *Ctx, LookupResult &Result,
     }
 
     // Traverse protocols.
-    for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
-         E = IFace->protocol_end(); I != E; ++I) {
+    for (ObjCInterfaceDecl::all_protocol_iterator
+         I = IFace->all_referenced_protocol_begin(),
+         E = IFace->all_referenced_protocol_end(); I != E; ++I) {
       ShadowContextRAII Shadow(Visited);
       LookupVisibleDecls(*I, Result, QualifiedNameLookup, false, Consumer, 
                          Visited);
index 7c3918ac97ecce81e936d137d5b92f5eaeee7016..7181d58f7fb07cb389d51fc9d83bd2f684251cf1 100644 (file)
@@ -731,15 +731,17 @@ void Sema::CompareProperties(Decl *CDecl, Decl *ClassOrProtocol) {
   }
 
   if (ObjCInterfaceDecl *MDecl = dyn_cast<ObjCInterfaceDecl>(ClassDecl)) {
-    for (ObjCInterfaceDecl::protocol_iterator P = MDecl->protocol_begin(),
-         E = MDecl->protocol_end(); P != E; ++P)
+    for (ObjCInterfaceDecl::all_protocol_iterator
+          P = MDecl->all_referenced_protocol_begin(),
+          E = MDecl->all_referenced_protocol_end(); P != E; ++P)
       // Match properties of class IDecl with those of protocol (*P).
       MatchOneProtocolPropertiesInClass(IDecl, *P);
 
     // Go thru the list of protocols for this class and recursively match
     // their properties with those declared in the class.
-    for (ObjCInterfaceDecl::protocol_iterator P = IDecl->protocol_begin(),
-         E = IDecl->protocol_end(); P != E; ++P)
+    for (ObjCInterfaceDecl::all_protocol_iterator
+          P = IDecl->all_referenced_protocol_begin(),
+          E = IDecl->all_referenced_protocol_end(); P != E; ++P)
       CompareProperties(IDecl, *P);
   } else {
     ObjCProtocolDecl *MD = cast<ObjCProtocolDecl>(ClassDecl);
@@ -812,8 +814,9 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
       PropMap[Prop->getIdentifier()] = Prop;
     }
     // scan through class's protocols.
-    for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
-         E = IDecl->protocol_end(); PI != E; ++PI)
+    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)) {
@@ -824,7 +827,7 @@ void Sema::CollectImmediateProperties(ObjCContainerDecl *CDecl,
         PropMap[Prop->getIdentifier()] = Prop;
       }
     // scan through class's protocols.
-    for (ObjCInterfaceDecl::protocol_iterator PI = CATDecl->protocol_begin(),
+    for (ObjCCategoryDecl::protocol_iterator PI = CATDecl->protocol_begin(),
          E = CATDecl->protocol_end(); PI != E; ++PI)
       CollectImmediateProperties((*PI), PropMap, SuperPropMap);
   }
@@ -859,8 +862,9 @@ static void CollectClassPropertyImplementations(ObjCContainerDecl *CDecl,
       ObjCPropertyDecl *Prop = (*P);
       PropMap[Prop->getIdentifier()] = Prop;
     }
-    for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
-         E = IDecl->protocol_end(); PI != E; ++PI)
+    for (ObjCInterfaceDecl::all_protocol_iterator
+         PI = IDecl->all_referenced_protocol_begin(),
+         E = IDecl->all_referenced_protocol_end(); PI != E; ++PI)
       CollectClassPropertyImplementations((*PI), PropMap);
   }
   else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(CDecl)) {
@@ -902,8 +906,9 @@ ObjCPropertyDecl *Sema::LookupPropertyDecl(const ObjCContainerDecl *CDecl,
         return Prop;
     }
     // scan through class's protocols.
-    for (ObjCInterfaceDecl::protocol_iterator PI = IDecl->protocol_begin(),
-         E = IDecl->protocol_end(); PI != E; ++PI) {
+    for (ObjCInterfaceDecl::all_protocol_iterator
+         PI = IDecl->all_referenced_protocol_begin(),
+         E = IDecl->all_referenced_protocol_end(); PI != E; ++PI) {
       ObjCPropertyDecl *Prop = LookupPropertyDecl((*PI), II);
       if (Prop)
         return Prop;
index 9795bd085d4530fd174ef123e14b26c7f781a1ff..512d4b5717431cfd22266060533a58eeac2d9aa7 100644 (file)
@@ -374,6 +374,8 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
   ID->setTypeForDecl(Reader.GetType(Record[Idx++]).getTypePtr());
   ID->setSuperClass(cast_or_null<ObjCInterfaceDecl>
                        (Reader.GetDecl(Record[Idx++])));
+  
+  // Read the directly referenced protocols and their SourceLocations.
   unsigned NumProtocols = Record[Idx++];
   llvm::SmallVector<ObjCProtocolDecl *, 16> Protocols;
   Protocols.reserve(NumProtocols);
@@ -385,6 +387,17 @@ void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) {
     ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
   ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
                       *Reader.getContext());
+  
+  // Read the transitive closure of protocols referenced by this class.
+  NumProtocols = Record[Idx++];
+  Protocols.clear();
+  Protocols.reserve(NumProtocols);
+  for (unsigned I = 0; I != NumProtocols; ++I)
+    Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
+  ID->AllReferencedProtocols.set(Protocols.data(), NumProtocols,
+                                 *Reader.getContext());
+  
+  // Read the ivars.
   unsigned NumIvars = Record[Idx++];
   llvm::SmallVector<ObjCIvarDecl *, 16> IVars;
   IVars.reserve(NumIvars);
index 9ac12fb56e93448e70dfb0e3843cf7fd0dd46b75..90d135dfb38a808ec1b7a22728674927c15a1383 100644 (file)
@@ -343,7 +343,9 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
   VisitObjCContainerDecl(D);
   Writer.AddTypeRef(QualType(D->getTypeForDecl(), 0), Record);
   Writer.AddDeclRef(D->getSuperClass(), Record);
-  Record.push_back(D->protocol_size());
+
+  // Write out the protocols that are directly referenced by the @interface.
+  Record.push_back(D->ReferencedProtocols.size());
   for (ObjCInterfaceDecl::protocol_iterator P = D->protocol_begin(),
          PEnd = D->protocol_end();
        P != PEnd; ++P)
@@ -352,6 +354,16 @@ void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
          PLEnd = D->protocol_loc_end();
        PL != PLEnd; ++PL)
     Writer.AddSourceLocation(*PL, Record);
+
+  // Write out the protocols that are transitively referenced.
+  Record.push_back(D->AllReferencedProtocols.size());
+  for (ObjCList<ObjCProtocolDecl>::iterator
+        P = D->AllReferencedProtocols.begin(),
+        PEnd = D->AllReferencedProtocols.end();
+       P != PEnd; ++P)
+    Writer.AddDeclRef(*P, Record);
+  
+  // Write out the ivars.
   Record.push_back(D->ivar_size());
   for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
                                      IEnd = D->ivar_end(); I != IEnd; ++I)
index 8557e7f49b2d3044fe49695cba2fb7d170d7b98b..b9f4fe2aeabc0afcb1d2a75232e6d2c65231f3e9 100644 (file)
 }
 @end
 
+// From: <rdar://problem/8380046>
+
+@protocol Prot8380046
+@end
+
+@interface R8380046
+@end
+
+@interface R8380046 () <Prot8380046>
+@end
+
 // CHECK: local-symbols.m:6:12: ObjCInterfaceDecl=Foo:6:12 Extent=[6:1 - 10:5]
 // CHECK: local-symbols.m:7:6: ObjCIvarDecl=x:7:6 (Definition) Extent=[7:6 - 7:7]
 // CHECK: local-symbols.m:7:3: TypeRef=id:0:0 Extent=[7:3 - 7:5]
 // CHECK: local-symbols.m:12:1: ObjCImplementationDecl=Foo:12:1 (Definition) Extent=[12:1 - 16:2]
 // CHECK: local-symbols.m:13:1: ObjCInstanceMethodDecl=bar:13:1 (Definition) Extent=[13:1 - 15:2]
 // CHECK: local-symbols.m:13:4: TypeRef=id:0:0 Extent=[13:4 - 13:6]
+// CHECK: local-symbols.m:14:10: UnexposedExpr= Extent=[14:10 - 14:11]
+// CHECK: local-symbols.m:14:10: UnexposedExpr= Extent=[14:10 - 14:11]
+// CHECK: local-symbols.m:20:1: ObjCProtocolDecl=Prot8380046:20:1 (Definition) Extent=[20:1 - 21:5]
+// CHECK: local-symbols.m:23:12: ObjCInterfaceDecl=R8380046:23:12 Extent=[23:1 - 24:5]
+// CHECK: local-symbols.m:26:12: ObjCCategoryDecl=:26:12 Extent=[26:1 - 27:5]
+// CHECK: local-symbols.m:26:12: ObjCClassRef=R8380046:23:12 Extent=[26:12 - 26:20]
+// CHECK: local-symbols.m:26:25: ObjCProtocolRef=Prot8380046:20:1 Extent=[26:25 - 26:36]