Bug 1678 – ref with varargs generates invalid code

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
x86
OS
Windows
Creation time
2007-11-18T17:20:00Z
Last change time
2014-02-24T15:32:56Z
Keywords
patch, wrong-code
Assigned to
nobody
Creator
ary

Comments

Comment #0 by ary — 2007-11-18T17:20:13Z
Given this code: *** module main; import std.stdio; import std.stdarg; void foo(int x, ...) { writefln("%d arguments", _arguments.length); for (int i = 0; i < _arguments.length; i++) { _arguments[i].print(); int j = va_arg!(int)(_argptr); writefln("\t%d", j); } } void fooRef(ref int x, ...) { writefln("%d arguments", _arguments.length); for (int i = 0; i < _arguments.length; i++) { _arguments[i].print(); int j = va_arg!(int)(_argptr); writefln("\t%d", j); } } void main() { foo(1, 2, 3, 4, 5); writefln("---"); int x = 1; fooRef(x, 2, 3, 4, 5); } *** the output is: *** 4 arguments int 2 int 3 int 4 int 5 --- 4 arguments int 1245056 int 4203171 int 1 int 1245004 *** Note that both functions are identical, except the last one has a ref parameter. Without it, the function works as expected.
Comment #1 by smjg — 2007-11-19T09:16:23Z
Please remember to assign keywords to bug reports. To everybody reading this: Please look through issues you've reported and check for missing keywords.
Comment #2 by ary — 2007-11-19T09:29:03Z
Is there a standard keyword list? I always see "accepts-invalid", and now that I know it, I'll use it. For this one, it's "wrong-code", but I was going to write "invalid-code" but I was afraid that wasn't the "standard" keyword. Also, I was going to write "ref varargs"...
Comment #3 by smjg — 2007-11-19T09:44:52Z
Keywords in Bugzilla aren't quite like the keywords you use on web pages to guide search engines. They're more like flags. And if you'd bothered to follow the link that is the word "Keywords", you would have found a list of them.
Comment #4 by ary — 2007-11-19T10:07:56Z
Bill Baxter wrote: > [email protected] wrote: >> http://d.puremagic.com/issues/show_bug.cgi?id=1678 >> >> >> >> >> >> ------- Comment #2 from [email protected] 2007-11-19 09:29 ------- >> Is there a standard keyword list? I always see "accepts-invalid", and >> now that >> I know it, I'll use it. For this one, it's "wrong-code", but I was >> going to >> write "invalid-code" but I was afraid that wasn't the "standard" >> keyword. Also, >> I was going to write "ref varargs"... > > If you click on the word "Keywords" in the report it will take you to a > page listing the keywords. > > It's a bad interface though. If there were some kind of clicky list > probably more people would add keywords. Me included. > > --bb Thanks, I didn't see that link.
Comment #5 by sky — 2010-06-16T17:18:23Z
*** Issue 4336 has been marked as a duplicate of this issue. ***
Comment #6 by clugdbug — 2010-07-24T22:30:56Z
This also applies to 'out' parameters, as well as 'ref'. The problem is in func.c, FuncDeclaration::semantic3(), around line 1380, where __argptr is created. It's set equal to (&p + offset), where p is the last non-variadic parameter. This fails if p is a reference -- it gives the address of the thing p is pointing to.
Comment #7 by clugdbug — 2010-07-26T13:03:13Z
There's probably a simpler way to patch this. What I've done is find the first non-ref parameter, and set __argptr off it. Index: func.c =================================================================== --- func.c (revision 588) +++ func.c (working copy) @@ -1367,18 +1367,32 @@ #else Type *t = argptr->type; VarDeclaration *p; - unsigned offset; - + unsigned offset = 0; Expression *e1 = new VarExp(0, argptr); + // Find the last non-ref parameter if (parameters && parameters->dim) - p = (VarDeclaration *)parameters->data[parameters->dim - 1]; + { + int lastNonref = parameters->dim -1; + p = (VarDeclaration *)parameters->data[lastNonref]; + while (p->storage_class & (STCout | STCref)) + { + --lastNonref; + offset += PTRSIZE; + if (lastNonref < 0) + { + p = v_arguments; + break; + } + p = (VarDeclaration *)parameters->data[lastNonref]; + } + } else - p = v_arguments; // last parameter is _arguments[] + p = v_arguments; if (p->storage_class & STClazy) // If the last parameter is lazy, it's the size of a delegate - offset = PTRSIZE * 2; + offset += PTRSIZE * 2; else - offset = p->type->size(); + offset += p->type->size(); offset = (offset + 3) & ~3; // assume stack aligns on 4 Expression *e = new SymOffExp(0, p, offset); e->type = Type::tvoidptr;
Comment #8 by bugzilla — 2010-08-05T23:09:30Z