Reduced test case shows it's an out-by-1 error in grabbing the arguments. The length ends up in the ptr field.
Probably, it's neglecting the fact that lazy arguments have a pointer as well as the value, or something similar.
import std.stdarg;
void foo(lazy int expr, ...){
char[] tmp_msg = va_arg!(char[])(_argptr);
if (cast(int)(tmp_msg.ptr)=="food_for_thought".length)
assert(0, "length is in the pointer!");
}
void main(){
foo(515,"food_for_thought");
}
Applies to D2 as well as D1.
Comment #3 by clugdbug — 2009-07-02T08:11:13Z
In fact, by replacing the T arg line below with the commented out-line, it gets the correct arguments. So in fact, it's just getting the size of the lazy parameter wrong when it's calculating _argptr.
-------------
alias void* va_list;
template va_arg(T)
{
T va_arg(inout va_list _argptr)
{
T arg = *cast(T*)_argptr; // original from Phobos
// T arg = *(cast(T*)(cast(int *)_argptr+1));
_argptr = _argptr + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1));
return arg;
}
}
void foo(lazy int expr, ...){
char[] tmp_msg = va_arg!(char[])(_argptr);
if (cast(int)(tmp_msg.ptr)=="food_for_thought".length)
assert(0, "length is in the pointer!");
assert(tmp_msg=="food_for_thought");
}
int bar() { return 3; }
void main(){
foo(bar(),"food_for_thought");
}
Comment #4 by clugdbug — 2009-07-20T08:03:56Z
PATCH: func.c, line 1211. Need to account for a lazy last parameter.
- offset = p->type->size();
+ if (p->storage_class & STClazy) {
+ // If the last parameter is lazy, it's the size of a delegate
+ offset = sizeof(int(*)(int)) + sizeof(void *);
+ } else {
+ offset = p->type->size();
+ }