Skip to content

Commit bbdf473

Browse files
committed
Fix for issue #326.
For a foreach (int i, dchar c; str) loop the compiler generates a delegate with a different type signature then the runtime uses. The runtime declares the parameters as void* and passes a pointer to a size_t variable for the index. The code generated by the compiler expects a ref int. This works on a little endian architecture, but on a big endian architecture the index is always 0. This fix changes the parameter type of the passed index to size_t and generates a cast to the type specified by the user.
1 parent a28f143 commit bbdf473

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

dmd2/statement.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2156,6 +2156,10 @@ Statement *ForeachStatement::semantic(Scope *sc)
21562156

21572157
arg->type = arg->type->semantic(loc, sc);
21582158
arg->type = arg->type->addStorageClass(arg->storageClass);
2159+
#if IN_LLVM
2160+
// Type of parameter may be different; see below
2161+
Type *para_type = arg->type;
2162+
#endif
21592163
if (tfld)
21602164
{ Parameter *prm = Parameter::getNth(tfld->parameters, i);
21612165
//printf("\tprm = %s%s\n", (prm->storageClass&STCref?"ref ":""), prm->ident->toChars());
@@ -2178,12 +2182,35 @@ Statement *ForeachStatement::semantic(Scope *sc)
21782182
LcopyArg:
21792183
id = Lexer::uniqueId("__applyArg", (int)i);
21802184

2185+
#if IN_LLVM
2186+
// In case of a foreach loop on an array the index passed
2187+
// to the delegate is always of type size_t. The type of
2188+
// the parameter must be changed to size_t and a cast to
2189+
// the type used must be inserted. Otherwise the index is
2190+
// always 0 on a big endian architecture. This fixes
2191+
// issue #326.
2192+
Initializer *ie;
2193+
if (dim == 2 && i == 0 && (tab->ty == Tarray || tab->ty == Tsarray))
2194+
{
2195+
para_type = Type::tsize_t;
2196+
ie = new ExpInitializer(0,
2197+
new CastExp(0,
2198+
new IdentifierExp(0, id), arg->type));
2199+
}
2200+
else
2201+
ie = new ExpInitializer(0, new IdentifierExp(0, id));
2202+
#else
21812203
Initializer *ie = new ExpInitializer(0, new IdentifierExp(0, id));
2204+
#endif
21822205
VarDeclaration *v = new VarDeclaration(0, arg->type, arg->ident, ie);
21832206
s = new ExpStatement(0, v);
21842207
body = new CompoundStatement(loc, s, body);
21852208
}
2209+
#if IN_LLVM
2210+
args->push(new Parameter(stc, para_type, id, NULL));
2211+
#else
21862212
args->push(new Parameter(stc, arg->type, id, NULL));
2213+
#endif
21872214
}
21882215
tfld = new TypeFunction(args, Type::tint32, 0, LINKd);
21892216
cases = new Statements();

0 commit comments

Comments
 (0)