- 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

Reply via email to