Bug 874 – Bad codegen: wrong value variable in tuple foreach, D1 only
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
x86
OS
All
Creation time
2007-01-22T22:12:00Z
Last change time
2014-02-15T13:12:53Z
Keywords
patch, wrong-code
Assigned to
nobody
Creator
jarrett.billingsley
Comments
Comment #0 by jarrett.billingsley — 2007-01-22T22:12:26Z
I don't know how else to describe this.
template AA(V, K)
{
V[K] AA(T...)(T args)
{
V[K] ret;
K key;
foreach(i, arg; args)
{
static if(!(i & 1))
key = arg;
else
ret[key] = arg;
}
return ret;
}
}
void main()
{
char[][char[]] array = AA!(char[], char[])("a", "b", "c", "d");
writefln("length = ", array.length);
foreach(k, v; array)
writefln("array[", k, "] = ", v);
}
This code will give bizarre output when printing out the contents of the returned AA. This usually is weird characters, and usually results in a "4invalid UTF-8 sequence" exception. Stranger still, the output changes depending on how many string literals there are in main(). This happens in both -debug and -release modes, although they give different output.
The equivalent code (below) works correctly on D2. This is a D1-only bug.
---------
import std.stdio;
template AA(V, K) {
V[K] AA(T...)(T args) {
V[K] ret;
K key;
foreach(i, arg; args) {
static if(!(i & 1))
key = arg;
else
ret[key] = arg;
}
return ret;
}
}
void main()
{
string[string] array = AA!(string, string)("a", "b"[], "c"[], "d"[]);
writefln("length = %d\n", array.length);
foreach(k, v; array)
writefln("array[%d]=%s", k, v);
}
Comment #3 by clugdbug — 2009-10-30T01:53:50Z
Original title was: "Incorrect codegen with tuples, string constants, and AAs".
This bug has nothing to do with AAs, actually. The problem is that the 'value' in a tuple foreach isn't dealt with correctly.
Workarounds: Change the code into: ret = arg.dup; or ret = args[0];
char[] bug874(T...)(T args)
{
char[] ret;
foreach(arg; args) {
ret = arg;
}
assert(ret=="b"); // passes
return ret;
}
void main()
{
char[] s = bug874("b");
assert(s == "b"); // fails
}
Comment #4 by clugdbug — 2009-10-30T02:16:21Z
Looks like this is just a D2 fix which didn't get transferred across to D1.
PATCH (against DMD1 svn 227):
expression.c, ForeachStatement::semantic, line 1380.
// Declare value
if (arg->storageClass & (STCout | STCref | STClazy))
error("no storage class for value %s", arg->ident->toChars());
Dsymbol *var;
if (te)
- {
- if (e->type->toBasetype()->ty == Tfunction &&
- e->op == TOKvar)
+ { Type *tb = e->type->toBasetype();
+ if ((tb->ty == Tfunction || tb->ty == Tsarray) && e->op == TOKvar)
{ VarExp *ve = (VarExp *)e;
var = new AliasDeclaration(loc, arg->ident, ve->var);
}
Comment #5 by leandro.lucarella — 2009-11-04T06:40:53Z