[clang] 6eb969b - [objc_direct] fix codegen for mismatched Decl/Impl return types

Pierre Habouzit via cfe-commits cfe-commits at lists.llvm.org
Thu Jan 30 18:19:13 PST 2020


Author: Pierre Habouzit
Date: 2020-01-30T18:17:45-08:00
New Revision: 6eb969b7c5b5195d7f85b70e2e060eb2989cdc3c

URL: https://github.com/llvm/llvm-project/commit/6eb969b7c5b5195d7f85b70e2e060eb2989cdc3c
DIFF: https://github.com/llvm/llvm-project/commit/6eb969b7c5b5195d7f85b70e2e060eb2989cdc3c.diff

LOG: [objc_direct] fix codegen for mismatched Decl/Impl return types

For non direct methods, the codegen uses the type of the Implementation.
Because Objective-C rules allow some differences between the Declaration
and Implementation return types, when the Implementation is in this
translation unit, the type of the Implementation should be preferred to
emit the Function over the Declaration.

Radar-Id: rdar://problem/58797748
Signed-off-by: Pierre Habouzit <phabouzit at apple.com>
Differential Revision: https://reviews.llvm.org/D73208

Added: 
    clang/test/CodeGenObjC/direct-method-ret-mismatch.m

Modified: 
    clang/lib/CodeGen/CGObjCMac.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index f994ec92da14..547a1f352f94 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -4032,22 +4032,49 @@ llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
 llvm::Function *
 CGObjCCommonMac::GenerateDirectMethod(const ObjCMethodDecl *OMD,
                                       const ObjCContainerDecl *CD) {
-  auto I = DirectMethodDefinitions.find(OMD->getCanonicalDecl());
-  if (I != DirectMethodDefinitions.end())
-    return I->second;
+  auto *COMD = OMD->getCanonicalDecl();
+  auto I = DirectMethodDefinitions.find(COMD);
+  llvm::Function *OldFn = nullptr, *Fn = nullptr;
 
-  SmallString<256> Name;
-  GetNameForMethod(OMD, CD, Name, /*ignoreCategoryNamespace*/true);
+  if (I != DirectMethodDefinitions.end()) {
+    // Objective-C allows for the declaration and implementation types
+    // to 
diff er slightly.
+    //
+    // If we're being asked for the Function associated for a method
+    // implementation, a previous value might have been cached
+    // based on the type of the canonical declaration.
+    //
+    // If these do not match, then we'll replace this function with
+    // a new one that has the proper type below.
+    if (!OMD->getBody() || COMD->getReturnType() == OMD->getReturnType())
+      return I->second;
+    OldFn = I->second;
+  }
 
   CodeGenTypes &Types = CGM.getTypes();
   llvm::FunctionType *MethodTy =
     Types.GetFunctionType(Types.arrangeObjCMethodDeclaration(OMD));
-  llvm::Function *Method =
-      llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
-                             Name.str(), &CGM.getModule());
-  DirectMethodDefinitions.insert(std::make_pair(OMD->getCanonicalDecl(), Method));
 
-  return Method;
+  if (OldFn) {
+    Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
+                                "", &CGM.getModule());
+    Fn->takeName(OldFn);
+    OldFn->replaceAllUsesWith(
+        llvm::ConstantExpr::getBitCast(Fn, OldFn->getType()));
+    OldFn->eraseFromParent();
+
+    // Replace the cached function in the map.
+    I->second = Fn;
+  } else {
+    SmallString<256> Name;
+    GetNameForMethod(OMD, CD, Name, /*ignoreCategoryNamespace*/ true);
+
+    Fn = llvm::Function::Create(MethodTy, llvm::GlobalValue::ExternalLinkage,
+                                Name.str(), &CGM.getModule());
+    DirectMethodDefinitions.insert(std::make_pair(COMD, Fn));
+  }
+
+  return Fn;
 }
 
 void CGObjCCommonMac::GenerateDirectMethodPrologue(

diff  --git a/clang/test/CodeGenObjC/direct-method-ret-mismatch.m b/clang/test/CodeGenObjC/direct-method-ret-mismatch.m
new file mode 100644
index 000000000000..65b253de1476
--- /dev/null
+++ b/clang/test/CodeGenObjC/direct-method-ret-mismatch.m
@@ -0,0 +1,19 @@
+// RUN: %clang_cc1 -emit-llvm -fobjc-arc -triple x86_64-apple-darwin10 %s -o - | FileCheck %s
+
+__attribute__((objc_root_class))
+ at interface Root
+- (Root *)method __attribute__((objc_direct));
+ at end
+
+ at implementation Root
+// CHECK-LABEL: define internal i8* @"\01-[Root something]"(
+- (id)something {
+  // CHECK: %{{[^ ]*}} = call {{.*}} @"\01-[Root method]"
+  return [self method];
+}
+
+// CHECK-LABEL: define hidden i8* @"\01-[Root method]"(
+- (id)method {
+  return self;
+}
+ at end


        


More information about the cfe-commits mailing list