diff options
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 15 | ||||
-rw-r--r-- | clang/test/CodeGen/incomplete-function-type.c | 6 |
2 files changed, 16 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 422415c2e24..a187f8a51bb 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -779,13 +779,24 @@ void CodeGenModule::EmitGlobalVarDefinition(const VarDecl *D) { llvm::GlobalValue * CodeGenModule::EmitForwardFunctionDefinition(const FunctionDecl *D, const llvm::Type *Ty) { - if (!Ty) + bool DoSetAttributes = true; + if (!Ty) { Ty = getTypes().ConvertType(D->getType()); + if (!isa<llvm::FunctionType>(Ty)) { + // This function doesn't have a complete type (for example, the return + // type is an incomplete struct). Use a fake type instead, and make + // sure not to try to set attributes. + Ty = llvm::FunctionType::get(llvm::Type::VoidTy, + std::vector<const llvm::Type*>(), false); + DoSetAttributes = false; + } + } llvm::Function *F = llvm::Function::Create(cast<llvm::FunctionType>(Ty), llvm::Function::ExternalLinkage, getMangledName(D), &getModule()); - SetFunctionAttributes(D, F); + if (DoSetAttributes) + SetFunctionAttributes(D, F); return F; } diff --git a/clang/test/CodeGen/incomplete-function-type.c b/clang/test/CodeGen/incomplete-function-type.c index 6bd872b7257..09e08d729c2 100644 --- a/clang/test/CodeGen/incomplete-function-type.c +++ b/clang/test/CodeGen/incomplete-function-type.c @@ -1,9 +1,9 @@ // RUN: clang -emit-llvm %s -o - | not grep opaque -enum teste1 (*test1)(void); -struct tests2 (*test2)(); +enum teste1 test1f(void), (*test1)(void) = test1f; +struct tests2 test2f(), (*test2)() = test2f; struct tests3; -void (*test3)(struct tests3); +void test3f(struct tests3), (*test3)(struct tests3) = test3f; enum teste1 { TEST1 }; struct tests2 { int x,y,z,a,b,c,d,e,f,g; }; struct tests3 { float x; }; |