PR4289: Make sure "&func" has the right LLVM type when "func" is a
K&R-style definition.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72690 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index da3f79e..155658e 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -711,8 +711,20 @@
LV.SetGlobalObjCRef(LV, true);
return LV;
} else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(E->getDecl())) {
- return LValue::MakeAddr(CGM.GetAddrOfFunction(GlobalDecl(FD)),
- E->getType().getCVRQualifiers(),
+ llvm::Value* V = CGM.GetAddrOfFunction(GlobalDecl(FD));
+ if (!FD->hasPrototype()) {
+ if (const FunctionProtoType *Proto =
+ FD->getType()->getAsFunctionProtoType()) {
+ // Ugly case: for a K&R-style definition, the type of the definition
+ // isn't the same as the type of a use. Correct for this with a
+ // bitcast.
+ QualType NoProtoType =
+ getContext().getFunctionNoProtoType(Proto->getResultType());
+ NoProtoType = getContext().getPointerType(NoProtoType);
+ V = Builder.CreateBitCast(V, ConvertType(NoProtoType), "tmp");
+ }
+ }
+ return LValue::MakeAddr(V, E->getType().getCVRQualifiers(),
getContext().getObjCGCAttrKind(E->getType()));
}
else if (const ImplicitParamDecl *IPD =
diff --git a/test/CodeGen/2009-06-01-addrofknr.c b/test/CodeGen/2009-06-01-addrofknr.c
new file mode 100644
index 0000000..16a5bbf
--- /dev/null
+++ b/test/CodeGen/2009-06-01-addrofknr.c
@@ -0,0 +1,21 @@
+// RUN: clang-cc %s -o %t -emit-llvm -verify
+// PR4289
+
+struct funcptr {
+ int (*func)();
+};
+
+static int func(f)
+ void *f;
+{
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct funcptr fp;
+
+ fp.func = &func;
+ fp.func = func;
+}
+