[PATCH] D28166: Properly merge K&R functions that have attributes
Aaron Ballman via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 3 10:24:17 PST 2017
aaron.ballman added a reviewer: majnemer.
aaron.ballman added a comment.
> I *think* the problem is that we gin up the function type for a non-prototyped function based on the function call expression argument types, and the literal `0` is getting the type `signed long long`.
I think this is because of `CodeGenFunction::getVarArgType()` and is specific to the Windows ABI.
// System headers on Windows define NULL to 0 instead of 0LL on Win64. MSVC
// implicitly widens null pointer constants that are arguments to varargs
// functions to pointer-sized ints.
This causes the 0 to be emit as a 64-bit value rather than a 32-bit value. Indeed, if you change your original example to pass `1` rather than `0` when calling `p`, you no longer get the UB:
; Function Attrs: noinline nounwind
define void @f() #0 {
entry:
%0 = load void (...)*, void (...)** @p, align 8
%callee.knr.cast = bitcast void (...)* %0 to void (i32)*
call void %callee.knr.cast(i32 1)
ret void
}
However, when I test with MSVC 2015, I do not get the behavior that Clang produces. My test was:
void h(int i, ...) {}
void i(int i, int j, int k, int l, int m) {}
void(*p)() = i;
void f() {
p(0, 1, 2, 3, 0);
h(0, 1, 2, 3, 0);
i(0, 1, 2, 3, 0);
}
MSVC outputs:
; 8 : p(0, 1, 2, 3, 0);
mov DWORD PTR [rsp+32], 0
mov r9d, 3
mov r8d, 2
mov edx, 1
xor ecx, ecx
call QWORD PTR p
; 9 : h(0, 1, 2, 3, 0);
mov QWORD PTR [rsp+32], 0
mov r9d, 3
mov r8d, 2
mov edx, 1
xor ecx, ecx
call h
; 10 : i(0, 1, 2, 3, 0);
mov DWORD PTR [rsp+32], 0
mov r9d, 3
mov r8d, 2
mov edx, 1
xor ecx, ecx
call i
Clang outputs:
%callee.knr.cast = bitcast void (...)* %0 to void (i64, i32, i32, i32, i64)*
call void %callee.knr.cast(i64 0, i32 1, i32 2, i32 3, i64 0)
call void (i32, ...) @h(i32 0, i32 1, i32 2, i32 3, i64 0)
call void @i(i32 0, i32 1, i32 2, i32 3, i32 0)
Note that the K&R call casts to i64 in Clang but uses a DWORD PTR in MSVC. Only the variadic call to `h()` uses the QWORD PTR. So I think the correct behavior is to only enable the vararg behavior when the function is variadic with an ellipsis rather than variadic due to a lack of prototype.
Thoughts?
https://reviews.llvm.org/D28166
More information about the cfe-commits
mailing list