Bug 2479 – Cannot use variadic arguments inside a closure
Status
RESOLVED
Resolution
WORKSFORME
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2008-11-29T10:13:35Z
Last change time
2019-10-10T15:05:27Z
Keywords
rejects-valid
Assigned to
No Owner
Creator
dick
Comments
Comment #0 by dick221z — 2008-11-29T10:13:35Z
char [32] tmp;
sformat(tmp,"hi");
writefln(tmp);
tmp is null after calling sformat. In some other cases an EXCEPTION_ACCESS_VIOLATION is thrown.
Oddly enough format works fine
The problem seems to be in passing the variable argument list to sformat, the argptr passed to sformat is null.
Workaround is to go back to 2.021
Comment #1 by gide — 2009-05-20T07:37:33Z
Set importance to regression.
Comment #2 by braddr — 2009-08-29T14:45:40Z
A reduced test case (larger, but complete and doesn't import large swaths of code). This is a massive reduction of all the irrelevant parts of doFormat torn away, and sformat reduced a good bit as well.
module bug2479;
import std.stdarg;
void doFormat(void delegate(dchar) myputc, TypeInfo[] arguments, va_list argptr)
{
string fmt = va_arg!(string)(argptr);
assert(!(fmt is null)); // fires when it shouldn't.
}
char[] sformat(char[] s, ...)
{
void putc(dchar c) { s[0] = cast(char)c; }
doFormat(&putc, _arguments, _argptr);
return s[0 .. 1];
}
void main()
{
char[32] tmp;
sformat(tmp, "%s", "hi");
}
Changing putc to not touch 's' causes the va_arg call to succeed an fmt is no longer null.
Comment #3 by braddr — 2009-08-29T14:55:44Z
Adding a printf at the top of doFormat...
The broken case:
argptr = 0xf7ceeffc
[email protected](11): Assertion failure
With putc emptied out:
argptr = 0xffb004d4
(no assert)
Comment #4 by clugdbug — 2009-08-31T01:59:58Z
Even further reduced, removing all imports. My patch to bug 814 does not fix this.
------
alias void* va_list;
T va_arg(T)(inout va_list _argptr) {
T arg = *cast(T*)_argptr;
_argptr = _argptr + ((T.sizeof + int.sizeof - 1) & ~(int.sizeof - 1));
return arg;
}
void doFormat(void delegate(dchar) myputc, TypeInfo[] args, va_list
argptr){
string fmt = va_arg!(string)(argptr);
assert(!(fmt is null)); // fires when it shouldn't.
}
char[] sformat(char[] s, ...){
void putc(dchar c) { s[0] = cast(char)c; }
doFormat(&putc, _arguments, _argptr);
return s[0 .. 1];
}
void main(){
char[32] tmp;
sformat(tmp, "%s", "hi");
}
Comment #5 by clugdbug — 2009-10-15T05:21:36Z
Reduced test case. This does not seem to be a Phobos bug.
If you remove any reference to s from the delegate (so that it stops being a
closure), the code works correctly.
----
void doFormat(void delegate() myputc, void * argptr){
assert(!(*cast(string*)argptr is null));
}
void sformat(string s, ...){
void putc() { assert(s[0]==s[0]); }
doFormat(&putc, _argptr);
}
void main(){
sformat("xxx", "hi");
}
Comment #6 by clugdbug — 2009-11-02T00:20:19Z
I have patched Phobos so that original symptom is fixed.
The compiler bug is that in FuncDeclaration::buildClosure() in toir.c, variadic arguments aren't supported, but _argptr is set in FuncDeclaration::semantic3() as if they were.
Partial patch, to turn this from a wrong-code into a rejects-valid bug, until the bug is actually fixed:
func.c, line 1282.
---
if (argptr)
{ // Initialize _argptr to point past non-variadic arg
#if IN_GCC
// Handled in FuncDeclaration::toObjFile
v_argptr = argptr;
v_argptr->init = new VoidInitializer(loc);
#else
+ // BUG: Fix this in FuncDeclaration::buildClosure() in toir.c.
+ if (needsClosure())
+ error("Closures are not yet supported with variadic arguments (Bugzilla 2479)");
Type *t = argptr->type;
VarDeclaration *p;
unsigned offset;
Comment #7 by leandro.lucarella — 2009-11-02T05:40:56Z