r350130 - [objc-gnustep2] Fix a bug in category generation.

David Chisnall via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 28 09:44:54 PST 2018


Author: theraven
Date: Fri Dec 28 09:44:54 2018
New Revision: 350130

URL: http://llvm.org/viewvc/llvm-project?rev=350130&view=rev
Log:
[objc-gnustep2] Fix a bug in category generation.

We were not emitting a protocol definition while generating the category
method list.  This was fine in most cases, because something else in the
library typically referenced any given protocol, but it caused linker
failures if the category was the only reference to a given protocol.

Added:
    cfe/trunk/test/CodeGenObjC/gnustep2-category-protocol.m
Modified:
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp

Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=350130&r1=350129&r2=350130&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Fri Dec 28 09:44:54 2018
@@ -277,6 +277,8 @@ protected:
     Fields.addInt(Int8Ty, 0);
   }
 
+  virtual llvm::Constant *GenerateCategoryProtocolList(const
+      ObjCCategoryDecl *OCD);
   virtual ConstantArrayBuilder PushPropertyListHeader(ConstantStructBuilder &Fields,
       int count) {
       // int count;
@@ -1164,6 +1166,15 @@ class CGObjCGNUstep2 : public CGObjCGNUs
     return MethodList.finishAndCreateGlobal(".objc_protocol_method_list",
                                             CGM.getPointerAlign());
   }
+  llvm::Constant *GenerateCategoryProtocolList(const ObjCCategoryDecl *OCD)
+    override {
+    SmallVector<llvm::Constant*, 16> Protocols;
+    for (const auto *PI : OCD->getReferencedProtocols())
+      Protocols.push_back(
+          llvm::ConstantExpr::getBitCast(GenerateProtocolRef(PI),
+            ProtocolPtrTy));
+    return GenerateProtocolList(Protocols);
+  }
 
   llvm::Value *LookupIMPSuper(CodeGenFunction &CGF, Address ObjCSuper,
                               llvm::Value *cmd, MessageSendInfo &MSI) override {
@@ -3099,18 +3110,21 @@ llvm::Constant *CGObjCGNU::MakeBitField(
   return ptr;
 }
 
+llvm::Constant *CGObjCGNU::GenerateCategoryProtocolList(const
+    ObjCCategoryDecl *OCD) {
+  SmallVector<std::string, 16> Protocols;
+  for (const auto *PD : OCD->getReferencedProtocols())
+    Protocols.push_back(PD->getNameAsString());
+  return GenerateProtocolList(Protocols);
+}
+
 void CGObjCGNU::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
   const ObjCInterfaceDecl *Class = OCD->getClassInterface();
   std::string ClassName = Class->getNameAsString();
   std::string CategoryName = OCD->getNameAsString();
 
   // Collect the names of referenced protocols
-  SmallVector<std::string, 16> Protocols;
   const ObjCCategoryDecl *CatDecl = OCD->getCategoryDecl();
-  const ObjCList<ObjCProtocolDecl> &Protos = CatDecl->getReferencedProtocols();
-  for (ObjCList<ObjCProtocolDecl>::iterator I = Protos.begin(),
-       E = Protos.end(); I != E; ++I)
-    Protocols.push_back((*I)->getNameAsString());
 
   ConstantInitBuilder Builder(CGM);
   auto Elements = Builder.beginStruct();
@@ -3132,7 +3146,7 @@ void CGObjCGNU::GenerateCategory(const O
           GenerateMethodList(ClassName, CategoryName, ClassMethods, true),
           PtrTy);
   // Protocol list
-  Elements.addBitCast(GenerateProtocolList(Protocols), PtrTy);
+  Elements.addBitCast(GenerateCategoryProtocolList(CatDecl), PtrTy);
   if (isRuntime(ObjCRuntime::GNUstep, 2)) {
     const ObjCCategoryDecl *Category =
       Class->FindCategoryDeclaration(OCD->getIdentifier());

Added: cfe/trunk/test/CodeGenObjC/gnustep2-category-protocol.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/gnustep2-category-protocol.m?rev=350130&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenObjC/gnustep2-category-protocol.m (added)
+++ cfe/trunk/test/CodeGenObjC/gnustep2-category-protocol.m Fri Dec 28 09:44:54 2018
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-freebsd -S -emit-llvm -fobjc-runtime=gnustep-2.0 -o - %s | FileCheck %s
+
+// Regression test.  We weren't emitting definitions for protocols used in
+// categories, causing linker errors when the category was the only reference
+// to a protocol in a binary.
+
+// CHECK: @._OBJC_PROTOCOL_Y = global 
+// CHEKC-SAME: section "__objc_protocols", comdat, align 8
+
+
+ at interface X
+{
+id isa;
+}
+ at end
+ at implementation X
+ at end
+
+ at protocol Y @end
+
+ at interface X (y) <Y>
+ at end
+ at implementation X (y) @end
+
+




More information about the cfe-commits mailing list