diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index da3f79e83a20..155658e92daf 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -711,8 +711,20 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) { LV.SetGlobalObjCRef(LV, true); return LV; } else if (const FunctionDecl *FD = dyn_cast(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/clang/test/CodeGen/2009-06-01-addrofknr.c b/clang/test/CodeGen/2009-06-01-addrofknr.c new file mode 100644 index 000000000000..16a5bbffc3af --- /dev/null +++ b/clang/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; +} +