- Move changes to CodeGen
http://reviews.llvm.org/D5480
Files:
lib/CodeGen/CGCall.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGen/variadic-null-llp64.c
test/CodeGenCXX/varargs.cpp
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -2589,6 +2589,22 @@
args.add(EmitAnyExprToTemp(E), type);
}
+QualType CodeGenFunction::getVarArgType(const Expr *Arg) {
+ // If this is a literal zero that is narrower than a pointer, widen it to a
+ // pointer-sized integer. This allows passing NULL through variadic functions
+ // in pre-C++11 codebases where NULL is defined to 0 or 0L on LLP64 platforms.
+ if (Arg->getType()->isIntegerType() &&
+ getContext().getTypeSize(Arg->getType()) <
+ getContext().getTargetInfo().getPointerWidth(0) &&
+ Arg->isNullPointerConstant(getContext(),
+ Expr::NPC_ValueDependentIsNotNull)) {
+ llvm::errs() << "getVarArgType, getIntPtrType\n";
+ return getContext().getIntPtrType();
+ }
+
+ return Arg->getType();
+}
+
// In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC
// optimizer it can aggressively ignore unwind edges.
void
@@ -2943,6 +2959,10 @@
else
V = Builder.CreateLoad(RV.getAggregateAddr());
+ if (ArgInfo.getCoerceToType() != V->getType() &&
+ V->getType()->isIntegerTy())
+ V = Builder.CreateZExtOrTrunc(V, ArgInfo.getCoerceToType());
+
// If the argument doesn't match, perform a bitcast to coerce it. This
// can happen due to trivial type mismatches.
if (FirstIRArg < IRFuncTy->getNumParams() &&
Index: lib/CodeGen/CodeGenFunction.h
===================================================================
--- lib/CodeGen/CodeGenFunction.h
+++ lib/CodeGen/CodeGenFunction.h
@@ -2664,7 +2664,7 @@
// If we still have any arguments, emit them using the type of the argument.
for (; Arg != ArgEnd; ++Arg)
- ArgTypes.push_back(Arg->getType());
+ ArgTypes.push_back(getVarArgType(*Arg));
EmitCallArgs(Args, ArgTypes, ArgBeg, ArgEnd, CalleeDecl, ParamsToSkip,
ForceColumnInfo);
@@ -2677,6 +2677,8 @@
unsigned ParamsToSkip = 0, bool ForceColumnInfo = false);
private:
+ QualType getVarArgType(const Expr *Arg);
+
const TargetCodeGenInfo &getTargetHooks() const {
return CGM.getTargetCodeGenInfo();
}
Index: test/CodeGen/variadic-null-llp64.c
===================================================================
--- /dev/null
+++ test/CodeGen/variadic-null-llp64.c
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-windows-msvc | FileCheck %s
+// RUN: %clang_cc1 %s -emit-llvm -o - -triple x86_64-linux | FileCheck %s
+
+// Make it possible to pass NULL through variadic functions on platforms where
+// NULL has an integer type that is more narrow than a pointer. On such
+// platforms we widen null pointer constants to a pointer-sized integer.
+
+#define NULL 0
+
+void v(const char *f, ...);
+void f(const char *f) {
+ v(f, 1, 2, 3, NULL);
+}
+// CHECK: define void @f(i8* %f)
+// CHECK: call void (i8*, ...)* @v(i8* {{.*}}, i32 1, i32 2, i32 3, i64 0)
Index: test/CodeGenCXX/varargs.cpp
===================================================================
--- test/CodeGenCXX/varargs.cpp
+++ test/CodeGenCXX/varargs.cpp
@@ -12,9 +12,11 @@
return -1;
}
- // CHECK: call i32 (...)* @_ZN5test05test1Ez(i32 0)
+ // CHECK: call i32 (...)* @_ZN5test05test1Ez(i64 0)
+ // CHECK: call i32 (...)* @_ZN5test05test1Ez(i32 1)
void test() {
- test1(0);
+ test1(0); // The zero gets implicitly widened.
+ test1(1);
}
}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits