summaryrefslogtreecommitdiffstats
path: root/clang/lib/CodeGen/CGExpr.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-09-21 08:08:30 +0000
committerJohn McCall <rjmccall@apple.com>2011-09-21 08:08:30 +0000
commitcbc038a6c3fcb45439473a70d0284916d47d900e (patch)
tree068e2cd6328fb13ba95832e950d6bc6a8e0e2c7e /clang/lib/CodeGen/CGExpr.cpp
parent3b4de99158766ca7f41d7f6baafbd9b94a81e0a5 (diff)
downloadbcm5719-llvm-cbc038a6c3fcb45439473a70d0284916d47d900e.tar.gz
bcm5719-llvm-cbc038a6c3fcb45439473a70d0284916d47d900e.zip
ANSI C requires that a call to an unprototyped function type succeed
if the definition has a non-variadic prototype with compatible parameters. Therefore, the default rule for such calls must be to use a non-variadic convention. Achieve this by casting the callee to the function type with which it is required to be compatible, unless the target specifically opts out and insists that unprototyped calls should use the variadic rules. The only case of that I'm aware of is the x86-64 convention, which passes arguments the same way in both cases but also sets a small amount of extra information; here we seek to maintain compatibility with GCC, which does set this when calling an unprototyped function. Addresses PR10810 and PR10713. llvm-svn: 140241
Diffstat (limited to 'clang/lib/CodeGen/CGExpr.cpp')
-rw-r--r--clang/lib/CodeGen/CGExpr.cpp32
1 files changed, 30 insertions, 2 deletions
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index f4c552b0850..62be62b79ed 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -18,6 +18,7 @@
#include "CGDebugInfo.h"
#include "CGRecordLayout.h"
#include "CGObjCRuntime.h"
+#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclObjC.h"
#include "clang/Frontend/CodeGenOptions.h"
@@ -2414,8 +2415,35 @@ RValue CodeGenFunction::EmitCall(QualType CalleeType, llvm::Value *Callee,
CallArgList Args;
EmitCallArgs(Args, dyn_cast<FunctionProtoType>(FnType), ArgBeg, ArgEnd);
- return EmitCall(CGM.getTypes().getFunctionInfo(Args, FnType),
- Callee, ReturnValue, Args, TargetDecl);
+ const CGFunctionInfo &FnInfo = CGM.getTypes().getFunctionInfo(Args, FnType);
+
+ // C99 6.5.2.2p6:
+ // If the expression that denotes the called function has a type
+ // that does not include a prototype, [the default argument
+ // promotions are performed]. If the number of arguments does not
+ // equal the number of parameters, the behavior is undefined. If
+ // the function is defined with a type that includes a prototype,
+ // and either the prototype ends with an ellipsis (, ...) or the
+ // types of the arguments after promotion are not compatible with
+ // the types of the parameters, the behavior is undefined. If the
+ // function is defined with a type that does not include a
+ // prototype, and the types of the arguments after promotion are
+ // not compatible with those of the parameters after promotion,
+ // the behavior is undefined [except in some trivial cases].
+ // That is, in the general case, we should assume that a call
+ // through an unprototyped function type works like a *non-variadic*
+ // call. The way we make this work is to cast to the exact type
+ // of the promoted arguments.
+ if (isa<FunctionNoProtoType>(FnType) &&
+ !getTargetHooks().isNoProtoCallVariadic(FnType->getCallConv())) {
+ assert(cast<llvm::FunctionType>(Callee->getType()->getContainedType(0))
+ ->isVarArg());
+ llvm::Type *CalleeTy = getTypes().GetFunctionType(FnInfo, false);
+ CalleeTy = CalleeTy->getPointerTo();
+ Callee = Builder.CreateBitCast(Callee, CalleeTy, "callee.knr.cast");
+ }
+
+ return EmitCall(FnInfo, Callee, ReturnValue, Args, TargetDecl);
}
LValue CodeGenFunction::
OpenPOWER on IntegriCloud