Keep track of the source locations for each protocol reference in
Objective-C classes, protocol definitions, forward protocol
declarations, and categories. This information isn't actually used
yet; that's coming next.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@93636 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclObjC.cpp b/lib/AST/DeclObjC.cpp
index 2506f27..047c349 100644
--- a/lib/AST/DeclObjC.cpp
+++ b/lib/AST/DeclObjC.cpp
@@ -37,6 +37,21 @@
   memcpy(List, InList, sizeof(void*)*Elts);
 }
 
+void ObjCProtocolList::set(ObjCProtocolDecl* const* InList, unsigned Elts, 
+                           const SourceLocation *Locs, ASTContext &Ctx) {
+  if (Elts == 0)
+    return;
+
+  Locations = new (Ctx) SourceLocation[Elts];
+  memcpy(Locations, Locs, sizeof(SourceLocation) * Elts);
+  set(InList, Elts, Ctx);
+}
+
+void ObjCProtocolList::Destroy(ASTContext &Ctx) {
+  Ctx.Deallocate(Locations);
+  Locations = 0;
+  ObjCList<ObjCProtocolDecl>::Destroy(Ctx);
+}
 
 //===----------------------------------------------------------------------===//
 // ObjCInterfaceDecl
@@ -141,16 +156,18 @@
 
 void ObjCInterfaceDecl::mergeClassExtensionProtocolList(
                               ObjCProtocolDecl *const* ExtList, unsigned ExtNum,
+                              const SourceLocation *Locs,
                               ASTContext &C)
 {
   if (ReferencedProtocols.empty()) {
-    ReferencedProtocols.set(ExtList, ExtNum, C);
+    ReferencedProtocols.set(ExtList, ExtNum, Locs, 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
   // 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];
@@ -164,18 +181,23 @@
     }
     // 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++)
+       p != e; ++p, ++pl) {
     ProtocolRefs.push_back(*p);
+    ProtocolLocs.push_back(*pl);
+  }
   ReferencedProtocols.Destroy(C);
   unsigned NumProtoRefs = ProtocolRefs.size();
-  setProtocolList((ObjCProtocolDecl**)&ProtocolRefs[0], NumProtoRefs, C);
+  setProtocolList(ProtocolRefs.data(), NumProtoRefs, ProtocolLocs.data(), C);
 }
 
 ObjCIvarDecl *ObjCInterfaceDecl::lookupInstanceVariable(IdentifierInfo *ID,
@@ -627,9 +649,9 @@
 ObjCForwardProtocolDecl::
 ObjCForwardProtocolDecl(DeclContext *DC, SourceLocation L,
                         ObjCProtocolDecl *const *Elts, unsigned nElts,
-                        ASTContext &C)
+                        const SourceLocation *Locs, ASTContext &C)
 : Decl(ObjCForwardProtocol, DC, L) {
-  ReferencedProtocols.set(Elts, nElts, C);
+  ReferencedProtocols.set(Elts, nElts, Locs, C);
 }
 
 
@@ -637,8 +659,9 @@
 ObjCForwardProtocolDecl::Create(ASTContext &C, DeclContext *DC,
                                 SourceLocation L,
                                 ObjCProtocolDecl *const *Elts,
-                                unsigned NumElts) {
-  return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, C);
+                                unsigned NumElts,
+                                const SourceLocation *Locs) {
+  return new (C) ObjCForwardProtocolDecl(DC, L, Elts, NumElts, Locs, C);
 }
 
 void ObjCForwardProtocolDecl::Destroy(ASTContext &C) {
diff --git a/lib/Frontend/PCHReaderDecl.cpp b/lib/Frontend/PCHReaderDecl.cpp
index 69343ed..138ad82 100644
--- a/lib/Frontend/PCHReaderDecl.cpp
+++ b/lib/Frontend/PCHReaderDecl.cpp
@@ -223,7 +223,12 @@
   Protocols.reserve(NumProtocols);
   for (unsigned I = 0; I != NumProtocols; ++I)
     Protocols.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
-  ID->setProtocolList(Protocols.data(), NumProtocols, *Reader.getContext());
+  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+  ProtoLocs.reserve(NumProtocols);
+  for (unsigned I = 0; I != NumProtocols; ++I)
+    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  ID->setProtocolList(Protocols.data(), NumProtocols, ProtoLocs.data(),
+                      *Reader.getContext());
   unsigned NumIvars = Record[Idx++];
   llvm::SmallVector<ObjCIvarDecl *, 16> IVars;
   IVars.reserve(NumIvars);
@@ -253,7 +258,12 @@
   ProtoRefs.reserve(NumProtoRefs);
   for (unsigned I = 0; I != NumProtoRefs; ++I)
     ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
-  PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, *Reader.getContext());
+  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+  ProtoLocs.reserve(NumProtoRefs);
+  for (unsigned I = 0; I != NumProtoRefs; ++I)
+    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  PD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+                      *Reader.getContext());
 }
 
 void PCHDeclReader::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *FD) {
@@ -282,7 +292,12 @@
   ProtoRefs.reserve(NumProtoRefs);
   for (unsigned I = 0; I != NumProtoRefs; ++I)
     ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
-  FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, *Reader.getContext());
+  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+  ProtoLocs.reserve(NumProtoRefs);
+  for (unsigned I = 0; I != NumProtoRefs; ++I)
+    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  FPD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+                       *Reader.getContext());
 }
 
 void PCHDeclReader::VisitObjCCategoryDecl(ObjCCategoryDecl *CD) {
@@ -293,7 +308,12 @@
   ProtoRefs.reserve(NumProtoRefs);
   for (unsigned I = 0; I != NumProtoRefs; ++I)
     ProtoRefs.push_back(cast<ObjCProtocolDecl>(Reader.GetDecl(Record[Idx++])));
-  CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, *Reader.getContext());
+  llvm::SmallVector<SourceLocation, 16> ProtoLocs;
+  ProtoLocs.reserve(NumProtoRefs);
+  for (unsigned I = 0; I != NumProtoRefs; ++I)
+    ProtoLocs.push_back(SourceLocation::getFromRawEncoding(Record[Idx++]));
+  CD->setProtocolList(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(),
+                      *Reader.getContext());
   CD->setNextClassCategory(cast_or_null<ObjCCategoryDecl>(Reader.GetDecl(Record[Idx++])));
   CD->setLocEnd(SourceLocation::getFromRawEncoding(Record[Idx++]));
 }
diff --git a/lib/Frontend/PCHWriterDecl.cpp b/lib/Frontend/PCHWriterDecl.cpp
index 2dbcc27..6f4cd8f 100644
--- a/lib/Frontend/PCHWriterDecl.cpp
+++ b/lib/Frontend/PCHWriterDecl.cpp
@@ -223,6 +223,10 @@
          PEnd = D->protocol_end();
        P != PEnd; ++P)
     Writer.AddDeclRef(*P, Record);
+  for (ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
+         PLEnd = D->protocol_loc_end();
+       PL != PLEnd; ++PL)
+    Writer.AddSourceLocation(*PL, Record);
   Record.push_back(D->ivar_size());
   for (ObjCInterfaceDecl::ivar_iterator I = D->ivar_begin(),
                                      IEnd = D->ivar_end(); I != IEnd; ++I)
@@ -251,6 +255,10 @@
   for (ObjCProtocolDecl::protocol_iterator
        I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
     Writer.AddDeclRef(*I, Record);
+  for (ObjCProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin(),
+         PLEnd = D->protocol_loc_end();
+       PL != PLEnd; ++PL)
+    Writer.AddSourceLocation(*PL, Record);
   Code = pch::DECL_OBJC_PROTOCOL;
 }
 
@@ -272,9 +280,13 @@
 void PCHDeclWriter::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
   VisitDecl(D);
   Record.push_back(D->protocol_size());
-  for (ObjCProtocolDecl::protocol_iterator
+  for (ObjCForwardProtocolDecl::protocol_iterator
        I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
     Writer.AddDeclRef(*I, Record);
+  for (ObjCForwardProtocolDecl::protocol_loc_iterator 
+         PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
+       PL != PLEnd; ++PL)
+    Writer.AddSourceLocation(*PL, Record);
   Code = pch::DECL_OBJC_FORWARD_PROTOCOL;
 }
 
@@ -282,9 +294,13 @@
   VisitObjCContainerDecl(D);
   Writer.AddDeclRef(D->getClassInterface(), Record);
   Record.push_back(D->protocol_size());
-  for (ObjCProtocolDecl::protocol_iterator
+  for (ObjCCategoryDecl::protocol_iterator
        I = D->protocol_begin(), IEnd = D->protocol_end(); I != IEnd; ++I)
     Writer.AddDeclRef(*I, Record);
+  for (ObjCCategoryDecl::protocol_loc_iterator 
+         PL = D->protocol_loc_begin(), PLEnd = D->protocol_loc_end();
+       PL != PLEnd; ++PL)
+    Writer.AddSourceLocation(*PL, Record);
   Writer.AddDeclRef(D->getNextClassCategory(), Record);
   Writer.AddSourceLocation(D->getLocEnd(), Record);
   Code = pch::DECL_OBJC_CATEGORY;
diff --git a/lib/Frontend/PrintParserCallbacks.cpp b/lib/Frontend/PrintParserCallbacks.cpp
index 95afb90..a91dd8d 100644
--- a/lib/Frontend/PrintParserCallbacks.cpp
+++ b/lib/Frontend/PrintParserCallbacks.cpp
@@ -65,6 +65,7 @@
                                                SourceLocation SuperLoc,
                                                const DeclPtrTy *ProtoRefs,
                                                unsigned NumProtocols,
+                                               const SourceLocation *ProtoLocs,
                                                SourceLocation EndProtoLoc,
                                                AttributeList *AttrList) {
       Out << __FUNCTION__ << "\n";
@@ -72,7 +73,8 @@
                                                      ClassName, ClassLoc,
                                                      SuperName, SuperLoc,
                                                      ProtoRefs, NumProtocols,
-                                                     EndProtoLoc, AttrList);
+                                                     ProtoLocs, EndProtoLoc,
+                                                     AttrList);
     }
 
     /// ActOnForwardClassDeclaration -
diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp
index 8b207fa..5f48897 100644
--- a/lib/Parse/MinimalAction.cpp
+++ b/lib/Parse/MinimalAction.cpp
@@ -204,6 +204,7 @@
                                         SourceLocation SuperLoc,
                                         const DeclPtrTy *ProtoRefs,
                                         unsigned NumProtocols,
+                                        const SourceLocation *ProtoLocs,
                                         SourceLocation EndProtoLoc,
                                         AttributeList *AttrList) {
   // Allocate and add the 'TypeNameInfo' "decl".
diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp
index 5e23635..ae85aa3 100644
--- a/lib/Parse/ParseObjc.cpp
+++ b/lib/Parse/ParseObjc.cpp
@@ -186,6 +186,7 @@
                                           categoryId, categoryLoc,
                                           ProtocolRefs.data(),
                                           ProtocolRefs.size(),
+                                          ProtocolLocs.data(),
                                           EndProtoLoc);
 
     ParseObjCInterfaceDeclList(CategoryType, tok::objc_not_keyword);
@@ -224,6 +225,7 @@
     Actions.ActOnStartClassInterface(atLoc, nameId, nameLoc,
                                      superClassId, superClassLoc,
                                      ProtocolRefs.data(), ProtocolRefs.size(),
+                                     ProtocolLocs.data(),
                                      EndProtoLoc, attrList);
 
   if (Tok.is(tok::l_brace))
@@ -1127,6 +1129,7 @@
     Actions.ActOnStartProtocolInterface(AtLoc, protocolName, nameLoc,
                                         ProtocolRefs.data(),
                                         ProtocolRefs.size(),
+                                        ProtocolLocs.data(),
                                         EndProtoLoc, attrList);
   ParseObjCInterfaceDeclList(ProtoType, tok::objc_protocol);
   return ProtoType;
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index 00a85f8..c14ce29 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3312,6 +3312,7 @@
                                              SourceLocation SuperLoc,
                                              const DeclPtrTy *ProtoRefs,
                                              unsigned NumProtoRefs,
+                                             const SourceLocation *ProtoLocs,
                                              SourceLocation EndProtoLoc,
                                              AttributeList *AttrList);
 
@@ -3329,6 +3330,7 @@
                     SourceLocation AtProtoInterfaceLoc,
                     IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc,
                     const DeclPtrTy *ProtoRefNames, unsigned NumProtoRefs,
+                    const SourceLocation *ProtoLocs,
                     SourceLocation EndProtoLoc,
                     AttributeList *AttrList);
 
@@ -3339,6 +3341,7 @@
                                                 SourceLocation CategoryLoc,
                                                 const DeclPtrTy *ProtoRefs,
                                                 unsigned NumProtoRefs,
+                                                const SourceLocation *ProtoLocs,
                                                 SourceLocation EndProtoLoc);
 
   virtual DeclPtrTy ActOnStartClassImplementation(
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index f2fc1f4..cfea875 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -81,6 +81,7 @@
                          IdentifierInfo *ClassName, SourceLocation ClassLoc,
                          IdentifierInfo *SuperName, SourceLocation SuperLoc,
                          const DeclPtrTy *ProtoRefs, unsigned NumProtoRefs,
+                         const SourceLocation *ProtoLocs, 
                          SourceLocation EndProtoLoc, AttributeList *AttrList) {
   assert(ClassName && "Missing class identifier");
 
@@ -201,7 +202,7 @@
   /// Check then save referenced protocols.
   if (NumProtoRefs) {
     IDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
-                           Context);
+                           ProtoLocs, Context);
     IDecl->setLocEnd(EndProtoLoc);
   }
 
@@ -279,6 +280,7 @@
                                   SourceLocation ProtocolLoc,
                                   const DeclPtrTy *ProtoRefs,
                                   unsigned NumProtoRefs,
+                                  const SourceLocation *ProtoLocs,
                                   SourceLocation EndProtoLoc,
                                   AttributeList *AttrList) {
   // FIXME: Deal with AttrList.
@@ -312,7 +314,8 @@
     ProcessDeclAttributeList(TUScope, PDecl, AttrList);
   if (NumProtoRefs) {
     /// Check then save referenced protocols.
-    PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,Context);
+    PDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs,
+                           ProtoLocs, Context);
     PDecl->setLocEnd(EndProtoLoc);
   }
 
@@ -559,6 +562,7 @@
                                       unsigned NumElts,
                                       AttributeList *attrList) {
   llvm::SmallVector<ObjCProtocolDecl*, 32> Protocols;
+  llvm::SmallVector<SourceLocation, 8> ProtoLocs;
 
   for (unsigned i = 0; i != NumElts; ++i) {
     IdentifierInfo *Ident = IdentList[i].first;
@@ -571,11 +575,13 @@
     if (attrList)
       ProcessDeclAttributeList(TUScope, PDecl, attrList);
     Protocols.push_back(PDecl);
+    ProtoLocs.push_back(IdentList[i].second);
   }
 
   ObjCForwardProtocolDecl *PDecl =
     ObjCForwardProtocolDecl::Create(Context, CurContext, AtProtocolLoc,
-                                    &Protocols[0], Protocols.size());
+                                    Protocols.data(), Protocols.size(),
+                                    ProtoLocs.data());
   CurContext->addDecl(PDecl);
   CheckObjCDeclScope(PDecl);
   return DeclPtrTy::make(PDecl);
@@ -588,6 +594,7 @@
                             SourceLocation CategoryLoc,
                             const DeclPtrTy *ProtoRefs,
                             unsigned NumProtoRefs,
+                            const SourceLocation *ProtoLocs,
                             SourceLocation EndProtoLoc) {
   ObjCCategoryDecl *CDecl =
     ObjCCategoryDecl::Create(Context, CurContext, AtInterfaceLoc, CategoryName);
@@ -623,12 +630,13 @@
 
   if (NumProtoRefs) {
     CDecl->setProtocolList((ObjCProtocolDecl**)ProtoRefs, NumProtoRefs, 
-                           Context);
+                           ProtoLocs, Context);
     CDecl->setLocEnd(EndProtoLoc);
     // Protocols in the class extension belong to the class.
     if (!CDecl->getIdentifier())
      IDecl->mergeClassExtensionProtocolList((ObjCProtocolDecl**)ProtoRefs, 
-                                            NumProtoRefs,Context); 
+                                            NumProtoRefs, ProtoLocs,
+                                            Context); 
   }
 
   CheckObjCDeclScope(CDecl);