aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CodeGenModule.cpp21
-rw-r--r--test/CodeGen/functions.c12
2 files changed, 28 insertions, 5 deletions
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 599df96723..825ca8ba04 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -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
diff --git a/test/CodeGen/functions.c b/test/CodeGen/functions.c
index 5629ef582a..a2c692d0ce 100644
--- a/test/CodeGen/functions.c
+++ b/test/CodeGen/functions.c
@@ -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()
+}