Since DMD 2.084.0, the following code fails:
```
void main()
{
void func(T...)(T args){
// here args[1] is received as [0, 0, 64, 64, 38, 86, 0, 0, 1, 2, 3, 4]
assert(args[1][0 .. 12] == [1,2,3,4,5,6,7,8,9,10,11,12]);
}
func(
ubyte(0),
cast(ubyte[12])[1,2,3,4,5,6,7,8,9,10,11,12],
cast(float[3])[1f,2f,3f],
0f,
0f,
0f,
0f,
0f,
0f,
0f,
0f,
0f,
uint(0),
[0,1,2,3,4],
uint(0),
);
}
```
This code works correctly on DMD 2.083.1, but fails on 2.084.0 and 2.084.1-beta.
Adding or removing arguments in the func call (like adding one more 0f value) makes func work correctly and pass its assert.
Changing the value of the first ubyte(0) changes the data received as args[1] (but still fails on the assert)
args[1] seems to be shifted by 8 bytes
Comment #1 by dkorpel — 2022-03-17T12:13:38Z
This is not about variadic parameters, it also happens when you spell them out:
```
void main()
{
void func(
ubyte p0, ubyte[12] p1, float[3] p2, float p3, float p4, float p5, float p6,
float p7, float p8, float p9, float p10, float p11, uint p12, int[] p13, uint p14
) {
// here args[1] is received as [0, 0, 64, 64, 38, 86, 0, 0, 1, 2, 3, 4]
assert(p1[0 .. 12] == [1,2,3,4,5,6,7,8,9,10,11,12]);
}
func(0,
cast(ubyte[12])[1,2,3,4,5,6,7,8,9,10,11,12],
[0, 0, 0],
0, 0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , uint(0), [], uint(0),
);
}
```
Comment #2 by kdevel — 2022-03-17T15:22:04Z
---v.d
import std.stdio;
unittest {
void func(T...)(T args)
{
writeln ("args = ", args);
asssert(args[1][0 .. 12] == [1,2,3,4,5,6,7,8,9,10,11,12]);
}
byte[12] f2 = [1,2,3,4,5,6,7,8,9,10,11,12];
float[3] f3 = [1f,2f,3f];
func(
0,
f2, f3,
0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f,
0, 0, 0, 0,
);
}
---
$ dmd --version
DMD64 D Compiler v2.099.0
Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved written by Walter Bright
$ dmd -g -m64 -unittest -checkaction=context -main -run v
std.exception.ErrnoException@[...]/dmd2/linux/bin64/../../src/phobos/std/stdio.d(3170): Enforcement failed (Bad address)
...
$ dmd -g -m32 -unittest -checkaction=context -main -run v
args = 0[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12][1, 2, 3]0000000000000
1 modules passed unittests
Comment #3 by dkorpel — 2022-11-02T12:18:15Z
Here's a bit more test code, reducing it to only using int and float, and using hex values as arguments that are easy to identify:
```
import core.stdc.stdio;
union U
{
int[22] i = [
0xAAAA_0000,
0xAAAA_0001,
0xAAAA_0002,
0xAAAA_0003,
0xFFFF_0004,
0xFFFF_0005,
0xFFFF_0006,
0xFFFF_0007,
0xFFFF_0008,
0xFFFF_0009,
0xFFFF_0010,
0xFFFF_0011,
0xFFFF_0012,
0xFFFF_0013,
0xFFFF_0014,
0xFFFF_0015,
0xAAAA_0016,
0xAAAA_0017,
0xAAAA_0018,
0xAAAA_0019,
0xAAAA_0020,
0xAAAA_0021,
];
float[22] f;
}
void print(int x) { printf("int %08X\n", x); }
void print(float x) { printf("float %08X\n", *(cast(int*) &x)); }
void main()
{
void func(
int p0, int[3] p1, float[3] p2, float p3, float p4, float p5, float p6, float p7,
float p8, float p9, float p10, float p11, int p12, int[2] p13, int p14, int p15, int p16
) {
print(p0);
print(p1[0]);
print(p1[1]);
print(p1[2]);
print(p2[0]);
print(p2[1]);
print(p2[2]);
print(p3);
print(p4);
print(p5);
print(p6);
print(p7);
print(p8);
print(p9);
print(p10);
print(p11);
print(p12);
print(p13[0]);
print(p13[1]);
print(p14);
print(p15);
print(p16);
}
func(U.init.i[0], [U.init.i[1], U.init.i[2], U.init.i[3]], [U.init.f[4], U.init.f[5], U.init.f[6]],
U.init.f[7], U.init.f[8], U.init.f[9], U.init.f[10], U.init.f[11], U.init.f[12], U.init.f[13],
U.init.f[14], U.init.f[15], U.init.i[16], [U.init.i[17], U.init.i[18]], U.init.i[19], U.init.i[20], U.init.i[21]
);
}
```
Expected / ldc output:
```
int AAAA0000
int AAAA0001
int AAAA0002
int AAAA0003
float FFFF0004
float FFFF0005
float FFFF0006
float FFFF0007
float FFFF0008
float FFFF0009
float FFFF0010
float FFFF0011
float FFFF0012
float FFFF0013
float FFFF0014
float FFFF0015
int AAAA0016
int AAAA0017
int AAAA0018
int AAAA0019
int AAAA0020
int AAAA0021
```
DMD output:
```
int AAAA0003
int FFFF0006
int 00007FFE
int AAAA0001
float EA9E9130
float 00007FFE
float FFFF0004
float FFFF0007
float FFFF0008
float FFFF0009
float FFFF0010
float FFFF0011
float FFFF0012
float FFFF0013
float FFFF0014
float FFFF0015
int AAAA0016
int AAAA0017
int AAAA0018
int AAAA0019
int AAAA0020
int AAAA0021
```
So it's the first 7 arguments which are garbage or reading from another parameter.
Comment #4 by dlang-bot — 2022-11-08T07:51:58Z
@WalterBright created dlang/dmd pull request #14629 "fix Issue 21301 - Wrong values being passed in long parameter list" fixing this issue:
- fix Issue 21301 - Wrong values being passed in long parameter list
https://github.com/dlang/dmd/pull/14629
Comment #5 by dlang-bot — 2022-11-10T09:25:13Z
dlang/dmd pull request #14629 "fix Issue 21301 - Wrong values being passed in long parameter list" was merged into master:
- 0317665d516966417e3a0ceeb12b0ede9cee862b by Walter Bright:
fix Issue 21301 - Wrong values being passed in long parameter list
https://github.com/dlang/dmd/pull/14629