On DMD, _argptr is a void *, on GDC it's a char *. This is fairly minor, but I've ended up having to add casts for it in all sorts of code to make it compile on GDC. Because AFAIK there's no compelling reason for it to be a char * instead of a void *, I think it should be changed.
Yes, people should use std.stdarg's va_list ... but they don't X_X
Comment #1 by smjg — 2007-09-17T20:56:51Z
Please remember to assign keywords to bug reports. To everybody reading this: Please look through issues you've reported and check for missing keywords.
It definitely should be changed:
- according to the spec, void* is the correct type of _argptr
- it makes no sense to assume that the data pointed to by it has character semantics.
Comment #2 by afb — 2007-09-18T01:38:00Z
According to the spec, only DMD exists. It doesn't mention portability.
va_list is not a char* always, it's a "target-specific type". Don't cast.
It needs the builtin va_list and the va_arg template for it to work...
I'm not sure how it could be rewritten to support DMD's direct access ?
But David can probably give a much better explanation of the va_lists.
Comment #3 by smjg — 2007-09-18T07:07:38Z
(In reply to comment #2)
> According to the spec, only DMD exists. It doesn't mention portability.
Where is this bit of the spec that states that no other compiler exists?
> va_list is not a char* always, it's a "target-specific type". Don't cast.
> It needs the builtin va_list and the va_arg template for it to work...
std.stdarg, in DMD's implementation, defines va_list to be an alias of void*. This is consistent with
http://www.digitalmars.com/d/function.html
- "These variadic functions have a special local variable declared for them, _argptr, which is a void* pointer to the first of the variadic arguments."
- the code example on that page using std.stdarg
> I'm not sure how it could be rewritten to support DMD's direct access ?
> But David can probably give a much better explanation of the va_lists.
What do you mean by this?
Comment #4 by larsivar — 2007-09-18T07:50:07Z
(In reply to comment #2)
> According to the spec, only DMD exists. It doesn't mention portability.
>
> va_list is not a char* always, it's a "target-specific type". Don't cast.
> It needs the builtin va_list and the va_arg template for it to work...
>
> I'm not sure how it could be rewritten to support DMD's direct access ?
> But David can probably give a much better explanation of the va_lists.
>
Considering that the target-specific type usually is based on some C
specification, it is not particularly useful for D, as has been shown with
Tango's use of indexing into the vararg list on platforms like x86_64. For
this feature to be useful, it needs to be defined in a way that makes it
portable, and afaik, David tries to fix this. The reason it wasn't
implemented this way before, was that the C version already present in gcc
was used.
Comment #5 by afb — 2007-09-18T08:05:29Z
(In reply to comment #3)
> > According to the spec, only DMD exists. It doesn't mention portability.
>
> Where is this bit of the spec that states that no other compiler exists?
I'm just ticked that it's nigh impossible to add the predefined versions.
> > I'm not sure how it could be rewritten to support DMD's direct access ?
> > But David can probably give a much better explanation of the va_lists.
>
> What do you mean by this?
I'm not sure that std.c.stdarg can be done much better. But std.stdarg can
probably be, as larsivi is mentioning. Especially for x86_64, it's needed.
Comment #6 by bugzilla — 2010-11-08T16:12:09Z
va_list is a void* on 64 bit targets, too. I originally had it as a pointer to that wacky struct required for the 64 bit C ABI, but it works better to treat it as a void*, and in the implementation of va_arg do the casting as necessary. This helps preserve encapsulation.
Comment #7 by ibuclaw — 2011-01-16T06:45:15Z
(In reply to comment #6)
> va_list is a void* on 64 bit targets, too. I originally had it as a pointer to
> that wacky struct required for the 64 bit C ABI, but it works better to treat
> it as a void*, and in the implementation of va_arg do the casting as necessary.
> This helps preserve encapsulation.
I'm currently at the point where I'm prototyping passing varargs in a packed structure (generated on the fly by the caller) on the stack. And using C varargs to get the address to assign to _argptr.
Think:
foo (parm, ...)
{
va_start(__cargptr, parm);
_argptr = va_arg(__cargptr, void*);
}
foo(&__argstruct);
So far it seems to be working well on 32bit architectures for simple datatypes...
Needs more testing though before I'd consider it fit for pushing out there.