]> granicus.if.org Git - clang/commitdiff
[Win64] Don't widen integer literal zero arguments to unprototyped function calls
authorReid Kleckner <rnk@google.com>
Tue, 3 Jan 2017 21:23:35 +0000 (21:23 +0000)
committerReid Kleckner <rnk@google.com>
Tue, 3 Jan 2017 21:23:35 +0000 (21:23 +0000)
The special case to widen the integer literal zero when passed to
variadic function calls should only apply to variadic functions, not
unprototyped functions. This is consistent with what MSVC does. In this
test case, MSVC uses a 4-byte store to pass the 5th argument to 'kr' and
an 8-byte store to pass the zero to 'v':

  void v(int, ...);
  void kr();
  void f(void) {
    v(1, 2, 3, 4, 0);
    kr(1, 2, 3, 4, 0);
  }

Aaron Ballman discovered this issue in https://reviews.llvm.org/D28166

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@290906 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CodeGenFunction.h
test/CodeGen/variadic-null-win64.c

index acf8863b5803694605f232d0aac3977725b6cb52..1347f54df9acf887fbe3a3c5fff822a5f3a8d76c 100644 (file)
@@ -3571,7 +3571,7 @@ public:
 
     // If we still have any arguments, emit them using the type of the argument.
     for (auto *A : llvm::make_range(Arg, ArgRange.end()))
-      ArgTypes.push_back(getVarArgType(A));
+      ArgTypes.push_back(CallArgTypeInfo ? getVarArgType(A) : A->getType());
 
     EmitCallArgs(Args, ArgTypes, ArgRange, CalleeDecl, ParamsToSkip, Order);
   }
index 3e079cbf8e51e76cdc22167a49517cb7cb69715e..3b2a3707bada7ad229bc8dd3914e746f8bc81e34 100644 (file)
@@ -3,15 +3,21 @@
 
 // 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.
+// platforms we widen null pointer constants passed to variadic functions to a
+// pointer-sized integer. We don't apply this special case to K&R-style
+// unprototyped functions, because MSVC doesn't either.
 
 #define NULL 0
 
 void v(const char *f, ...);
+void kr();
 void f(const char *f) {
   v(f, 1, 2, 3, NULL);
+  kr(f, 1, 2, 3, 0);
 }
 // WINDOWS: define void @f(i8* %f)
 // WINDOWS: call void (i8*, ...) @v(i8* {{.*}}, i32 1, i32 2, i32 3, i64 0)
+// WINDOWS: call void bitcast (void (...)* @kr to void (i8*, i32, i32, i32, i32)*)(i8* {{.*}}, i32 1, i32 2, i32 3, i32 0)
 // LINUX: define void @f(i8* %f)
 // LINUX: call void (i8*, ...) @v(i8* {{.*}}, i32 1, i32 2, i32 3, i32 0)
+// LINUX: call void (i8*, i32, i32, i32, i32, ...) bitcast (void (...)* @kr to void (i8*, i32, i32, i32, i32, ...)*)(i8* %1, i32 1, i32 2, i32 3, i32 0)