]> granicus.if.org Git - clang/commitdiff
Make IRGen compatible with declaring a function with incomplete
authorEli Friedman <eli.friedman@gmail.com>
Thu, 5 Mar 2009 04:18:07 +0000 (04:18 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Thu, 5 Mar 2009 04:18:07 +0000 (04:18 +0000)
return/argument types.  (The generated IR isn't ideal, but we can't
really do better in general.)

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

lib/CodeGen/CodeGenModule.cpp
test/CodeGen/incomplete-function-type.c

index 422415c2e2432026dda7015ed70b5a5f463d966d..a187f8a51bb4f1046f6d77dc0b980ba984237d3a 100644 (file)
@@ -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;
 }
 
index 6bd872b72571ff0fefc35ac2019011ae4bdc4b1b..09e08d729c2d45f4efdda0ddba5a4e3b6696edbd 100644 (file)
@@ -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; };