]> granicus.if.org Git - clang/commitdiff
Properly pass the address of a lazily-generated function declaration with
authorJohn McCall <rjmccall@apple.com>
Wed, 28 Apr 2010 00:00:30 +0000 (00:00 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 28 Apr 2010 00:00:30 +0000 (00:00 +0000)
incomplete type.  Fixes PR6911.

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

lib/CodeGen/CodeGenModule.cpp
test/CodeGen/functions.c

index 599df96723c36a8de52f38758f07e97cd676ec2e..825ca8ba04d0b3a4389ef2edc043dd220bc5ad32 100644 (file)
@@ -779,12 +779,16 @@ CodeGenModule::GetOrCreateLLVMFunction(llvm::StringRef MangledName,
   // type is an incomplete struct). Use a fake type instead, and make
   // sure not to try to set attributes.
   bool IsIncompleteFunction = false;
-  if (!isa<llvm::FunctionType>(Ty)) {
-    Ty = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
-                                 std::vector<const llvm::Type*>(), false);
+
+  const llvm::FunctionType *FTy;
+  if (isa<llvm::FunctionType>(Ty)) {
+    FTy = cast<llvm::FunctionType>(Ty);
+  } else {
+    FTy = llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
+                                  std::vector<const llvm::Type*>(), false);
     IsIncompleteFunction = true;
   }
-  llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty),
+  llvm::Function *F = llvm::Function::Create(FTy,
                                              llvm::Function::ExternalLinkage,
                                              MangledName, &getModule());
   assert(F->getName() == MangledName && "name was uniqued!");
@@ -826,7 +830,14 @@ CodeGenModule::GetOrCreateLLVMFunction(llvm::StringRef MangledName,
     }
   }
 
-  return F;
+  // Make sure the result is of the requested type.
+  if (!IsIncompleteFunction) {
+    assert(F->getType()->getElementType() == Ty);
+    return F;
+  }
+
+  const llvm::Type *PTy = llvm::PointerType::getUnqual(Ty);
+  return llvm::ConstantExpr::getBitCast(F, PTy);
 }
 
 /// GetAddrOfFunction - Return the address of the given function.  If Ty is
index 5629ef582a607b71344f72870814d9d50117d711..a2c692d0ce3ea517b36111e73fad6dfdc10a96cb 100644 (file)
@@ -47,3 +47,15 @@ void f7(float f, float g) {
 // CHECK: define void @f7(float{{.*}}, float{{.*}})
 // CHECK: call void @f6(float{{.*}}, float{{.*}})
 }
+
+// PR6911 - incomplete function types
+struct Incomplete;
+void f8_callback(struct Incomplete);
+void f8_user(void (*callback)(struct Incomplete));
+void f8_test() {
+  f8_user(&f8_callback);
+// CHECK: define void @f8_test()
+// CHECK: call void @f8_user({{.*}}* bitcast (void ()* @f8_callback to {{.*}}*))
+// CHECK: declare void @f8_user({{.*}}*)
+// CHECK: declare void @f8_callback()
+}