d: foreach over a tuple doesn't work on 16-bit targets (PR100999)

Improves semantic passes in the front-end around the `foreach' and
`static foreach' statements to be more resilient to compiling in a
minimal D runtime environment.  Checking of the index type has been
improved as well so now there won't be needless compiler errors when
using 8 or 16-bit integers as index types when the size fits the
expected loop range.

gcc/d/ChangeLog:

	PR d/100999
	* dmd/MERGE: Merge upstream dmd 7a3808254.

libphobos/ChangeLog:

	PR d/100999
	* src/MERGE: Merge upstream phobos 55bb17543.
This commit is contained in:
Iain Buclaw 2021-06-11 19:33:07 +02:00
parent b13f297f01
commit 68f46862d3
32 changed files with 388 additions and 80 deletions

View File

@ -1,4 +1,4 @@
4a4e46a6f304a667e0c05d4455706ec2056ffddc 7a3808254878df8cb70a055bea58afc79187b778
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository. merge done from the dlang/dmd repository.

View File

@ -112,6 +112,7 @@ static void lowerArrayAggregate(StaticForeach *sfe, Scope *sc)
sfe->aggrfe->aggr = new TupleExp(aggr->loc, es); sfe->aggrfe->aggr = new TupleExp(aggr->loc, es);
sfe->aggrfe->aggr = expressionSemantic(sfe->aggrfe->aggr, sc); sfe->aggrfe->aggr = expressionSemantic(sfe->aggrfe->aggr, sc);
sfe->aggrfe->aggr = sfe->aggrfe->aggr->optimize(WANTvalue); sfe->aggrfe->aggr = sfe->aggrfe->aggr->optimize(WANTvalue);
sfe->aggrfe->aggr = sfe->aggrfe->aggr->ctfeInterpret();
} }
else else
{ {
@ -198,7 +199,8 @@ static TypeStruct *createTupleType(Loc loc, Expressions *e)
Type *ty = new TypeTypeof(loc, new TupleExp(loc, e)); Type *ty = new TypeTypeof(loc, new TupleExp(loc, e));
sdecl->members->push(new VarDeclaration(loc, ty, fid, NULL)); sdecl->members->push(new VarDeclaration(loc, ty, fid, NULL));
TypeStruct *r = (TypeStruct *)sdecl->type; TypeStruct *r = (TypeStruct *)sdecl->type;
r->vtinfo = TypeInfoStructDeclaration::create(r); // prevent typeinfo from going to object file if (global.params.useTypeInfo && Type::dtypeinfo)
r->vtinfo = TypeInfoStructDeclaration::create(r); // prevent typeinfo from going to object file
return r; return r;
} }
@ -312,15 +314,25 @@ static void lowerNonArrayAggregate(StaticForeach *sfe, Scope *sc)
Identifier *idres = Identifier::generateId("__res"); Identifier *idres = Identifier::generateId("__res");
VarDeclaration *vard = new VarDeclaration(aloc, aty, idres, NULL); VarDeclaration *vard = new VarDeclaration(aloc, aty, idres, NULL);
Statements *s2 = new Statements(); Statements *s2 = new Statements();
s2->push(new ExpStatement(aloc, vard));
Expression *catass = new CatAssignExp(aloc, new IdentifierExp(aloc, idres), res[1]); // Run 'typeof' gagged to avoid duplicate errors and if it fails just create
s2->push(createForeach(sfe, aloc, pparams[1], new ExpStatement(aloc, catass))); // an empty foreach to expose them.
s2->push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres))); unsigned olderrors = global.startGagging();
ety = typeSemantic(ety, aloc, sc);
if (global.endGagging(olderrors))
s2->push(createForeach(sfe, aloc, pparams[1], NULL));
else
{
s2->push(new ExpStatement(aloc, vard));
Expression *catass = new CatAssignExp(aloc, new IdentifierExp(aloc, idres), res[1]);
s2->push(createForeach(sfe, aloc, pparams[1], new ExpStatement(aloc, catass)));
s2->push(new ReturnStatement(aloc, new IdentifierExp(aloc, idres)));
}
Expression *aggr; Expression *aggr;
Type *indexty; Type *indexty;
if (sfe->rangefe && (indexty = typeSemantic(ety, aloc, sc))->isintegral()) if (sfe->rangefe && (indexty = ety)->isintegral())
{ {
sfe->rangefe->lwr->type = indexty; sfe->rangefe->lwr->type = indexty;
sfe->rangefe->upr->type = indexty; sfe->rangefe->upr->type = indexty;
@ -384,11 +396,6 @@ void staticForeachPrepare(StaticForeach *sfe, Scope *sc)
sfe->aggrfe->aggr = expressionSemantic(sfe->aggrfe->aggr, sc); sfe->aggrfe->aggr = expressionSemantic(sfe->aggrfe->aggr, sc);
sc = sc->endCTFE(); sc = sc->endCTFE();
sfe->aggrfe->aggr = sfe->aggrfe->aggr->optimize(WANTvalue); sfe->aggrfe->aggr = sfe->aggrfe->aggr->optimize(WANTvalue);
Type *tab = sfe->aggrfe->aggr->type->toBasetype();
if (tab->ty != Ttuple)
{
sfe->aggrfe->aggr = sfe->aggrfe->aggr->ctfeInterpret();
}
} }
if (sfe->aggrfe && sfe->aggrfe->aggr->type->toBasetype()->ty == Terror) if (sfe->aggrfe && sfe->aggrfe->aggr->type->toBasetype()->ty == Terror)

View File

@ -643,7 +643,16 @@ Expression *ctfeInterpret(Expression *e)
case TOKfloat64: case TOKfloat64:
case TOKcomplex80: case TOKcomplex80:
case TOKnull: case TOKnull:
case TOKvoid:
case TOKstring: case TOKstring:
case TOKthis:
case TOKsuper:
case TOKtype:
case TOKtypeid:
case TOKtemplate: // non-eponymous template/instance
case TOKscope: // ditto
case TOKdottd: // ditto, e.e1 doesn't matter here
case TOKdot: // ditto
if (e->type->ty == Terror) if (e->type->ty == Terror)
return new ErrorExp(); return new ErrorExp();
/* fall through */ /* fall through */

View File

@ -1044,7 +1044,7 @@ bool Expression::checkPostblit(Scope *sc, Type *t)
t = t->baseElemOf(); t = t->baseElemOf();
if (t->ty == Tstruct) if (t->ty == Tstruct)
{ {
if (global.params.useTypeInfo) if (global.params.useTypeInfo && Type::dtypeinfo)
{ {
// Bugzilla 11395: Require TypeInfo generation for array concatenation // Bugzilla 11395: Require TypeInfo generation for array concatenation
semanticTypeInfo(sc, t); semanticTypeInfo(sc, t);

View File

@ -1082,11 +1082,6 @@ static Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2
if (checkUnsafeAccess(sc, e1, true, true)) if (checkUnsafeAccess(sc, e1, true, true))
return new ErrorExp(); return new ErrorExp();
} }
else if (e1->op == TOKdot)
{
e1->error("expression has no value");
return new ErrorExp();
}
else if (e1->op == TOKcall) else if (e1->op == TOKcall)
{ {
CallExp *ce = (CallExp *)e1; CallExp *ce = (CallExp *)e1;
@ -4513,11 +4508,18 @@ public:
void visit(DotTemplateExp *e) void visit(DotTemplateExp *e)
{ {
if (e->type)
{
result = e;
return;
}
if (Expression *ex = unaSemantic(e, sc)) if (Expression *ex = unaSemantic(e, sc))
{ {
result = ex; result = ex;
return; return;
} }
// 'void' like TemplateExp
e->type = Type::tvoid;
result = e; result = e;
} }

View File

@ -563,9 +563,6 @@ public:
else else
{ {
e = resolveProperties(sc, e); e = resolveProperties(sc, e);
type = e->type;
if (paramtype)
type = paramtype;
Initializer *ie = new ExpInitializer(Loc(), e); Initializer *ie = new ExpInitializer(Loc(), e);
VarDeclaration *v = new VarDeclaration(loc, type, ident, ie); VarDeclaration *v = new VarDeclaration(loc, type, ident, ie);
if (storageClass & STCref) if (storageClass & STCref)
@ -646,22 +643,23 @@ public:
} }
} }
p->type = typeSemantic(p->type, loc, sc); p->type = typeSemantic(p->type, loc, sc);
TY keyty = p->type->ty;
if (keyty != Tint32 && keyty != Tuns32) if (!p->type->isintegral())
{ {
if (global.params.isLP64) fs->error("foreach: key cannot be of non-integral type `%s`",
{ p->type->toChars());
if (keyty != Tint64 && keyty != Tuns64) return false;
{ }
fs->error("foreach: key type must be int or uint, long or ulong, not %s", p->type->toChars());
return false; unsigned length = te ? te->exps->length : tuple->arguments->length;
} IntRange dimrange = IntRange(SignExtendedNumber(length)).cast(Type::tsize_t);
} // https://issues.dlang.org/show_bug.cgi?id=12504
else dimrange.imax = SignExtendedNumber(dimrange.imax.value-1);
{ if (!IntRange::fromType(p->type).contains(dimrange))
fs->error("foreach: key type must be int or uint, not %s", p->type->toChars()); {
return false; fs->error("index type `%s` cannot cover index range 0..%llu",
} p->type->toChars(), (ulonglong)length);
return false;
} }
Initializer *ie = new ExpInitializer(Loc(), new IntegerExp(k)); Initializer *ie = new ExpInitializer(Loc(), new IntegerExp(k));
VarDeclaration *var = new VarDeclaration(loc, p->type, p->ident, ie); VarDeclaration *var = new VarDeclaration(loc, p->type, p->ident, ie);
@ -1073,6 +1071,8 @@ public:
{ {
TypeSArray *ta = (TypeSArray *)tab; TypeSArray *ta = (TypeSArray *)tab;
IntRange dimrange = getIntRange(ta->dim); IntRange dimrange = getIntRange(ta->dim);
// https://issues.dlang.org/show_bug.cgi?id=12504
dimrange.imax = SignExtendedNumber(dimrange.imax.value-1);
if (!IntRange::fromType(var->type).contains(dimrange)) if (!IntRange::fromType(var->type).contains(dimrange))
{ {
fs->error("index type `%s` cannot cover index range 0..%llu", p->type->toChars(), ta->dim->toInteger()); fs->error("index type `%s` cannot cover index range 0..%llu", p->type->toChars(), ta->dim->toInteger());

View File

@ -0,0 +1 @@
module object;

View File

@ -0,0 +1,30 @@
// https://issues.dlang.org/show_bug.cgi?id=21927
/*
TEST_OUTPUT:
---
T1(Args...)
T1!()
T2(Args2...)
T2!()
this.T2(Args2...)
this.T2!()
---
*/
template T1(Args...) {}
pragma(msg, T1); // TOK.template_
pragma(msg, T1!()); // TOK.scope_
struct S
{
template T2(Args2...) {}
pragma(msg, S.T2); // TOK.template_
pragma(msg, S.T2!()); // TOK.scope_
void fun()
{
pragma(msg, this.T2); // TOK.dotTemplateDeclaration
pragma(msg, this.T2!()); // TOK.dot
}
}

View File

@ -0,0 +1,36 @@
// DFLAGS:
// REQUIRED_ARGS: -defaultlib=
// EXTRA_SOURCES: extra-files/minimal/object.d
/**********************************************/
// https://issues.dlang.org/show_bug.cgi?id=19234
void issue19234()
{
static struct A {}
A[10] a;
A[10] b;
b[] = a[];
}
/**********************************************/
// https://issues.dlang.org/show_bug.cgi?id=22005
void issue22005()
{
enum int[4] foo = [1,2,3,4];
static foreach (i, e; foo)
{
}
}
/**********************************************/
// https://issues.dlang.org/show_bug.cgi?id=22006
void issue22006()
{
alias size_t = typeof(int.sizeof);
alias AliasSeq(T...) = T;
foreach (size_t i, e; [0, 1, 2, 3]) { }
static foreach (size_t i, e; [0, 1, 2, 3]) { }
foreach (size_t i, e; AliasSeq!(0, 1, 2, 3)) { }
static foreach (size_t i, e; AliasSeq!(0, 1, 2, 3)) { }
}

View File

@ -115,6 +115,8 @@ bug17688
T T
foo2 foo2
T2 T2
TestStaticForeach2
issue22007
1 2 '3' 1 2 '3'
2 3 '4' 2 3 '4'
0 1 0 1
@ -840,3 +842,39 @@ struct T2{
struct S{} struct S{}
} }
static assert(is(__traits(parent,T2.S)==T2)); static assert(is(__traits(parent,T2.S)==T2));
struct TestStaticForeach2
{
static:
// StringExp
char[] test(string str)()
{
char[] s;
static foreach (c; str)
{
s ~= c;
}
return s;
}
static assert(test!"tёstñ" == ['t', '\xd1', '\x91', 's', 't', '\xc3', '\xb1']);
static foreach (c; "")
{
static assert(0);
}
// NullExp
enum int[] a = null;
static foreach (c; a)
{
static assert(0);
}
}
//https://issues.dlang.org/show_bug.cgi?id=22007
void issue22007()
{
immutable int[32] array = 1;
foreach (size_t a, int b; array) {}
static foreach (size_t a, int b; array) { }
}

View File

@ -0,0 +1,13 @@
// https://issues.dlang.org/show_bug.cgi?id=21742
int foo()() { return 0; }
struct B
{
int foo()() { return 0; }
}
static assert(is(typeof(foo) == void));
// failed, gagged error: expression B().foo()() has no type
static assert(is(typeof(B().foo) == void));

View File

@ -0,0 +1,14 @@
// https://issues.dlang.org/show_bug.cgi?id=22006
void test22006()
{
alias AliasSeq(TList...) = TList;
{
alias aseq = AliasSeq!(0, 1, 2, 3);
static foreach (ubyte i; 0 .. aseq.length) {}
static foreach (ubyte i, x; aseq) {}
}
{
static foreach (ubyte i; 0 .. [0, 1, 2, 3].length) {}
static foreach (ubyte i, x; [0, 1, 2, 3]) {}
}
}

View File

@ -0,0 +1,64 @@
/*
TEST_OUTPUT:
---
fail_compilation/b12504.d(26): Error: cannot implicitly convert expression `257$?:32=u|64=LU$` of type `$?:32=uint|64=ulong$` to `ubyte`
fail_compilation/b12504.d(27): Error: index type `ubyte` cannot cover index range 0..257
fail_compilation/b12504.d(31): Error: cannot implicitly convert expression `129$?:32=u|64=LU$` of type `$?:32=uint|64=ulong$` to `byte`
fail_compilation/b12504.d(32): Error: index type `byte` cannot cover index range 0..129
fail_compilation/b12504.d(36): Error: cannot implicitly convert expression `65537$?:32=u|64=LU$` of type `$?:32=uint|64=ulong$` to `ushort`
fail_compilation/b12504.d(37): Error: index type `ushort` cannot cover index range 0..65537
fail_compilation/b12504.d(41): Error: cannot implicitly convert expression `32769$?:32=u|64=LU$` of type `$?:32=uint|64=ulong$` to `short`
fail_compilation/b12504.d(42): Error: index type `short` cannot cover index range 0..32769
fail_compilation/b12504.d(46): Error: cannot implicitly convert expression `257$?:32=u|64=LU$` of type `$?:32=uint|64=ulong$` to `ubyte`
fail_compilation/b12504.d(47): Error: index type `ubyte` cannot cover index range 0..257
fail_compilation/b12504.d(51): Error: cannot implicitly convert expression `129$?:32=u|64=LU$` of type `$?:32=uint|64=ulong$` to `byte`
fail_compilation/b12504.d(52): Error: index type `byte` cannot cover index range 0..129
fail_compilation/b12504.d(56): Error: cannot implicitly convert expression `65537$?:32=u|64=LU$` of type `$?:32=uint|64=ulong$` to `ushort`
fail_compilation/b12504.d(57): Error: index type `ushort` cannot cover index range 0..65537
fail_compilation/b12504.d(61): Error: cannot implicitly convert expression `32769$?:32=u|64=LU$` of type `$?:32=uint|64=ulong$` to `short`
fail_compilation/b12504.d(62): Error: index type `short` cannot cover index range 0..32769
---
*/
void main()
{
{
int[0xFF + 2] sta;
foreach (ubyte i; 0 .. sta.length) {}
foreach (ubyte i, x; sta) {}
}
{
int[0x7F + 2] sta;
foreach (byte i; 0 .. sta.length) {}
foreach (byte i, x; sta) {}
}
{
int[0xFFFF + 2] sta;
foreach (ushort i; 0 .. sta.length) {}
foreach (ushort i, x; sta) {}
}
{
int[0x7FFF + 2] sta;
foreach (short i; 0 .. sta.length) {}
foreach (short i, x; sta) {}
}
{
immutable int[0xFF + 2] sta;
static foreach (ubyte i; 0 .. sta.length) {}
static foreach (ubyte i, x; sta) {}
}
{
immutable int[0x7F + 2] sta;
static foreach (byte i; 0 .. sta.length) {}
static foreach (byte i, x; sta) {}
}
{
immutable int[0xFFFF + 2] sta;
static foreach (ushort i; 0 .. sta.length) {}
static foreach (ushort i, x; sta) {}
}
{
immutable int[0x7FFF + 2] sta;
static foreach (short i; 0 .. sta.length) {}
static foreach (short i, x; sta) {}
}
}

View File

@ -1,21 +1,37 @@
/* TEST_OUTPUT: /* TEST_OUTPUT:
--- ---
fail_compilation/diag16976.d(28): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(44): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(29): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(45): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(30): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(46): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(31): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(47): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(32): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(48): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(33): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(49): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(34): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(50): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(35): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(51): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(36): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(52): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(37): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(53): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(38): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(54): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(39): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(55): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(40): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(56): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(41): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(57): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(42): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(58): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(43): Error: foreach: key cannot be of non-integral type `float` fail_compilation/diag16976.d(59): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(65): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(66): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(67): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(68): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(69): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(70): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(71): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(72): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(73): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(74): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(75): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(76): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(77): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(78): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(79): Error: foreach: key cannot be of non-integral type `float`
fail_compilation/diag16976.d(80): Error: foreach: key cannot be of non-integral type `float`
--- ---
*/ */
@ -41,4 +57,25 @@ void main()
foreach_reverse(float f, dchar i; sta) {} foreach_reverse(float f, dchar i; sta) {}
foreach_reverse(float f, dchar i; str) {} foreach_reverse(float f, dchar i; str) {}
foreach_reverse(float f, dchar i; chr) {} foreach_reverse(float f, dchar i; chr) {}
immutable int[] idyn = [1,2,3,4,5];
immutable int[5] ista = [1,2,3,4,5];
immutable char[] istr = ['1','2','3','4','5'];
immutable char[5] ichr = ['1','2','3','4','5'];
static foreach(float f, i; idyn) {}
static foreach(float f, i; ista) {}
static foreach(float f, i; istr) {}
static foreach(float f, i; ichr) {}
static foreach(float f, dchar i; idyn) {}
static foreach(float f, dchar i; ista) {}
static foreach(float f, dchar i; istr) {}
static foreach(float f, dchar i; ichr) {}
static foreach_reverse(float f, i; idyn) {}
static foreach_reverse(float f, i; ista) {}
static foreach_reverse(float f, i; istr) {}
static foreach_reverse(float f, i; ichr) {}
static foreach_reverse(float f, dchar i; idyn) {}
static foreach_reverse(float f, dchar i; ista) {}
static foreach_reverse(float f, dchar i; istr) {}
static foreach_reverse(float f, dchar i; ichr) {}
} }

View File

@ -1,8 +1,10 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail117.d(35): Error: expression has no value fail_compilation/fail117.d(37): Error: expression `foo.mixin MGettor!(a) geta;
fail_compilation/fail117.d(36): Error: expression has no value ` is `void` and has no value
fail_compilation/fail117.d(38): Error: expression `foo.mixin MGettor!(b) getb;
` is `void` and has no value
--- ---
*/ */

View File

@ -0,0 +1,22 @@
/*
TEST_OUTPUT:
---
fail_compilation/fail22006.d(15): Error: cannot implicitly convert expression `4$?:32=u|64=LU$` of type `$?:32=uint|64=ulong$` to `bool`
fail_compilation/fail22006.d(16): Error: index type `bool` cannot cover index range 0..4
fail_compilation/fail22006.d(19): Error: cannot implicitly convert expression `4$?:32=u|64=LU$` of type `$?:32=uint|64=ulong$` to `bool`
fail_compilation/fail22006.d(20): Error: index type `bool` cannot cover index range 0..4
---
*/
void test22006()
{
alias AliasSeq(TList...) = TList;
{
alias aseq = AliasSeq!(0, 1, 2, 3);
static foreach (bool i; 0 .. aseq.length) {}
static foreach (bool i, x; aseq) {}
}
{
static foreach (bool i; 0 .. [0, 1, 2, 3].length) {}
static foreach (bool i, x; [0, 1, 2, 3]) {}
}
}

View File

@ -3,10 +3,10 @@
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail238_m32.d(21): Error: cannot implicitly convert expression `"a"` of type `string` to `uint` fail_compilation/fail238_m32.d(21): Error: cannot implicitly convert expression `"a"` of type `string` to `uint`
fail_compilation/fail238_m32.d(24): Error: cannot interpret X!() at compile time fail_compilation/fail238_m32.d(24): Error: cannot implicitly convert expression `X!()` of type `void` to `const(string)`
fail_compilation/fail238_m32.d(29): Error: template instance fail238_m32.A!"a" error instantiating fail_compilation/fail238_m32.d(29): Error: template instance `fail238_m32.A!"a"` error instantiating
fail_compilation/fail238_m32.d(35): instantiated from here: M!(q) fail_compilation/fail238_m32.d(35): instantiated from here: `M!(q)`
fail_compilation/fail238_m32.d(35): while evaluating pragma(msg, M!(q)) fail_compilation/fail238_m32.d(35): while evaluating `pragma(msg, M!(q))`
--- ---
*/ */

View File

@ -3,10 +3,10 @@
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail238_m64.d(21): Error: cannot implicitly convert expression `"a"` of type `string` to `ulong` fail_compilation/fail238_m64.d(21): Error: cannot implicitly convert expression `"a"` of type `string` to `ulong`
fail_compilation/fail238_m64.d(24): Error: cannot interpret X!() at compile time fail_compilation/fail238_m64.d(24): Error: cannot implicitly convert expression `X!()` of type `void` to `const(string)`
fail_compilation/fail238_m64.d(29): Error: template instance fail238_m64.A!"a" error instantiating fail_compilation/fail238_m64.d(29): Error: template instance `fail238_m64.A!"a"` error instantiating
fail_compilation/fail238_m64.d(35): instantiated from here: M!(q) fail_compilation/fail238_m64.d(35): instantiated from here: `M!(q)`
fail_compilation/fail238_m64.d(35): while evaluating pragma(msg, M!(q)) fail_compilation/fail238_m64.d(35): while evaluating `pragma(msg, M!(q))`
--- ---
*/ */

View File

@ -1,7 +1,7 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail7424b.d(10): Error: cannot resolve type for this.g()() fail_compilation/fail7424b.d(10): Error: expression `this.g()()` is `void` and has no value
--- ---
*/ */
struct S7424b struct S7424b

View File

@ -1,7 +1,7 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail7424c.d(10): Error: cannot resolve type for this.g()() fail_compilation/fail7424c.d(10): Error: expression `this.g()()` is `void` and has no value
--- ---
*/ */
struct S7424c struct S7424c

View File

@ -1,7 +1,7 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail7424d.d(10): Error: cannot resolve type for this.g()() fail_compilation/fail7424d.d(10): Error: expression `this.g()()` is `void` and has no value
--- ---
*/ */
struct S7424d struct S7424d

View File

@ -1,7 +1,7 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail7424e.d(10): Error: cannot resolve type for this.g()() fail_compilation/fail7424e.d(10): Error: expression `this.g()()` is `void` and has no value
--- ---
*/ */
struct S7424e struct S7424e

View File

@ -1,7 +1,7 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail7424f.d(10): Error: cannot resolve type for this.g()() fail_compilation/fail7424f.d(10): Error: expression `this.g()()` is `void` and has no value
--- ---
*/ */
struct S7424f struct S7424f

View File

@ -1,7 +1,7 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail7424g.d(10): Error: cannot resolve type for this.g()() fail_compilation/fail7424g.d(10): Error: expression `this.g()()` is `void` and has no value
--- ---
*/ */
struct S7424g struct S7424g

View File

@ -1,7 +1,7 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail7424h.d(10): Error: cannot resolve type for this.g()() fail_compilation/fail7424h.d(10): Error: expression `this.g()()` is `void` and has no value
--- ---
*/ */
struct S7424g struct S7424g

View File

@ -1,7 +1,7 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail7424i.d(10): Error: cannot resolve type for this.g()() fail_compilation/fail7424i.d(10): Error: expression `this.g()()` is `void` and has no value
--- ---
*/ */
struct S7424g struct S7424g

View File

@ -1,7 +1,8 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/fail9766.d(14): Error: cannot interpret Foo!int at compile time fail_compilation/fail9766.d(14): Error: integer constant expression expected instead of `Foo!int`
fail_compilation/fail9766.d(14): Error: alignment must be an integer positive power of 2, not Foo!int
fail_compilation/fail9766.d(17): Error: alignment must be an integer positive power of 2, not -1 fail_compilation/fail9766.d(17): Error: alignment must be an integer positive power of 2, not -1
fail_compilation/fail9766.d(20): Error: alignment must be an integer positive power of 2, not 0 fail_compilation/fail9766.d(20): Error: alignment must be an integer positive power of 2, not 0
fail_compilation/fail9766.d(23): Error: alignment must be an integer positive power of 2, not 3 fail_compilation/fail9766.d(23): Error: alignment must be an integer positive power of 2, not 3
@ -9,6 +10,7 @@ fail_compilation/fail9766.d(26): Error: alignment must be an integer positive po
--- ---
*/ */
#line 12
template Foo(T) {} template Foo(T) {}
align(Foo!int) align(Foo!int)

View File

@ -1,7 +1,8 @@
/* /*
TEST_OUTPUT: TEST_OUTPUT:
--- ---
fail_compilation/ice9406.d(21): Error: expression has no value fail_compilation/ice9406.d(22): Error: `s1.mixin Mixin!() t1;
` has no effect
--- ---
*/ */

View File

@ -0,0 +1,20 @@
// https://issues.dlang.org/show_bug.cgi?id=21927
/*
TEST_OUTPUT:
---
fail_compilation/test21927.d(17): Error: invalid `foreach` aggregate `this.T2(Args2...)`
fail_compilation/test21927.d(18): Error: invalid `foreach` aggregate `this.T2!()`
---
*/
struct S
{
template T2(Args2...) {}
void fun()
{
// original test case
static foreach (p; this.T2) {} // ICE
static foreach (p; this.T2!()) {} // ICE
}
}

View File

@ -0,0 +1,9 @@
// https://issues.dlang.org/show_bug.cgi?id=21939
/*
TEST_OUTPUT:
---
fail_compilation/test21939.d(9): Error: invalid `foreach` aggregate `Object`, define `opApply()`, range primitives, or use `.tupleof`
---
*/
static foreach (a; Object) {}

View File

@ -1,4 +1,4 @@
63f4caa900e17c541042617b2fa187059b86bf88 55bb17543138a87c376a84745f2a30ec00bdecd9
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository. merge done from the dlang/phobos repository.

View File

@ -5935,13 +5935,7 @@ mixin template Proxy(alias a)
// built-in type field, manifest constant, and static non-mutable field // built-in type field, manifest constant, and static non-mutable field
enum opDispatch = mixin("a."~name); enum opDispatch = mixin("a."~name);
} }
else static if (is(typeof(mixin("a."~name))) || __traits(getOverloads, a, name).length != 0) else static if (__traits(isTemplate, mixin("a."~name)))
{
// field or property function
@property auto ref opDispatch(this X)() { return mixin("a."~name); }
@property auto ref opDispatch(this X, V)(auto ref V v) { return mixin("a."~name~" = v"); }
}
else
{ {
// member template // member template
template opDispatch(T...) template opDispatch(T...)
@ -5950,6 +5944,13 @@ mixin template Proxy(alias a)
auto ref opDispatch(this X, Args...)(auto ref Args args){ return mixin("a."~name~targs~"(args)"); } auto ref opDispatch(this X, Args...)(auto ref Args args){ return mixin("a."~name~targs~"(args)"); }
} }
} }
else
{
// field or property function
@property auto ref opDispatch(this X)() { return mixin("a."~name); }
@property auto ref opDispatch(this X, V)(auto ref V v) { return mixin("a."~name~" = v"); }
}
} }
import std.traits : isArray; import std.traits : isArray;