# HG changeset patch # User korDen # Date 1282580955 -14400 # Node ID 4290d870944a540963fd55f9ebd9f0b6dec6dab7 # Parent cab4c37afb8994297e44697ca7f5a87f5d196535 More fixes diff -r cab4c37afb89 -r 4290d870944a dmd/AssocArrayLiteralExp.d --- a/dmd/AssocArrayLiteralExp.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/AssocArrayLiteralExp.d Mon Aug 23 20:29:15 2010 +0400 @@ -1,6 +1,9 @@ module dmd.AssocArrayLiteralExp; import dmd.Expression; +import dmd.GlobalExpressions; +import dmd.WANT; +import dmd.expression.Equal; import dmd.backend.elem; import dmd.InterState; import dmd.MATCH; @@ -11,6 +14,7 @@ import dmd.Scope; import dmd.InlineCostState; import dmd.IRState; +import dmd.TY; import dmd.InlineDoState; import dmd.HdrGenState; import dmd.InlineScanState; @@ -163,22 +167,170 @@ Expression optimize(int result) { - assert(false); + assert(keys.dim == values.dim); + for (size_t i = 0; i < keys.dim; i++) + { + Expression e = cast(Expression)keys.data[i]; + + e = e.optimize(WANTvalue | (result & WANTinterpret)); + keys.data[i] = cast(void*)e; + + e = cast(Expression)values.data[i]; + e = e.optimize(WANTvalue | (result & WANTinterpret)); + values.data[i] = cast(void*)e; + } + return this; } Expression interpret(InterState istate) { - assert(false); + Expressions keysx = keys; + Expressions valuesx = values; + +version (LOG) { + printf("AssocArrayLiteralExp.interpret() %s\n", toChars()); +} + for (size_t i = 0; i < keys.dim; i++) + { + Expression ekey = cast(Expression)keys.data[i]; + Expression evalue = cast(Expression)values.data[i]; + Expression ex; + + ex = ekey.interpret(istate); + if (ex is EXP_CANT_INTERPRET) + goto Lerr; + + /* If any changes, do Copy On Write + */ + if (ex != ekey) + { + if (keysx == keys) + keysx = cast(Expressions)keys.copy(); + keysx.data[i] = cast(void*)ex; + } + + ex = evalue.interpret(istate); + if (ex is EXP_CANT_INTERPRET) + goto Lerr; + + /* If any changes, do Copy On Write + */ + if (ex != evalue) + { + if (valuesx == values) + valuesx = cast(Expressions)values.copy(); + valuesx.data[i] = cast(void*)ex; + } + } + + if (keysx != keys) + expandTuples(keysx); + if (valuesx != values) + expandTuples(valuesx); + if (keysx.dim != valuesx.dim) + goto Lerr; + + /* Remove duplicate keys + */ + for (size_t i = 1; i < keysx.dim; i++) + { + Expression ekey = cast(Expression)keysx.data[i - 1]; + + for (size_t j = i; j < keysx.dim; j++) + { + Expression ekey2 = cast(Expression)keysx.data[j]; + Expression ex = Equal(TOKequal, Type.tbool, ekey, ekey2); + if (ex is EXP_CANT_INTERPRET) + goto Lerr; + if (ex.isBool(true)) // if a match + { + // Remove ekey + if (keysx == keys) + keysx = cast(Expressions)keys.copy(); + if (valuesx == values) + valuesx = cast(Expressions)values.copy(); + keysx.remove(i - 1); + valuesx.remove(i - 1); + i -= 1; // redo the i'th iteration + break; + } + } + } + + if (keysx != keys || valuesx != values) + { + AssocArrayLiteralExp ae; + ae = new AssocArrayLiteralExp(loc, keysx, valuesx); + ae.type = type; + return ae; + } + return this; + + Lerr: + if (keysx != keys) + delete keysx; + if (valuesx != values) + delete values; + return EXP_CANT_INTERPRET; } MATCH implicitConvTo(Type t) { - assert(false); + MATCH result = MATCHexact; + + Type typeb = type.toBasetype(); + Type tb = t.toBasetype(); + if (tb.ty == Taarray && typeb.ty == Taarray) + { + for (size_t i = 0; i < keys.dim; i++) + { + Expression e = cast(Expression)keys.data[i]; + MATCH m = cast(MATCH)e.implicitConvTo((cast(TypeAArray)tb).index); + if (m < result) + result = m; // remember worst match + if (result == MATCHnomatch) + break; // no need to check for worse + e = cast(Expression)values.data[i]; + m = cast(MATCH)e.implicitConvTo(tb.nextOf()); + if (m < result) + result = m; // remember worst match + if (result == MATCHnomatch) + break; // no need to check for worse + } + return result; + } + else + return Expression.implicitConvTo(t); } Expression castTo(Scope sc, Type t) { - assert(false); + if (type == t) + return this; + AssocArrayLiteralExp e = this; + Type typeb = type.toBasetype(); + Type tb = t.toBasetype(); + if (tb.ty == Taarray && typeb.ty == Taarray && tb.nextOf().toBasetype().ty != Tvoid) + { + e = cast(AssocArrayLiteralExp)copy(); + e.keys = cast(Expressions)keys.copy(); + e.values = cast(Expressions)values.copy(); + assert(keys.dim == values.dim); + for (size_t i = 0; i < keys.dim; i++) + { + Expression ex = cast(Expression)values.data[i]; + ex = ex.castTo(sc, tb.nextOf()); + e.values.data[i] = cast(void*)ex; + + ex = cast(Expression)keys.data[i]; + ex = ex.castTo(sc, (cast(TypeAArray)tb).index); + e.keys.data[i] = cast(void*)ex; + } + e.type = t; + return e; + } + L1: + return e.Expression.castTo(sc, t); } bool canThrow() diff -r cab4c37afb89 -r 4290d870944a dmd/CallExp.d --- a/dmd/CallExp.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/CallExp.d Mon Aug 23 20:29:15 2010 +0400 @@ -1021,7 +1021,9 @@ void scanForNestedRef(Scope sc) { - assert(false); + //printf("CallExp.scanForNestedRef(Scope *sc): %s\n", toChars()); + e1.scanForNestedRef(sc); + arrayExpressionScanForNestedRef(sc, arguments); } version (DMDV2) { diff -r cab4c37afb89 -r 4290d870944a dmd/CaseRangeStatement.d --- a/dmd/CaseRangeStatement.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/CaseRangeStatement.d Mon Aug 23 20:29:15 2010 +0400 @@ -1,10 +1,17 @@ module dmd.CaseRangeStatement; import dmd.Statement; +import dmd.ArrayTypes; import dmd.Expression; +import dmd.ExpStatement; +import dmd.IntegerExp; +import dmd.CaseStatement; +import dmd.CompoundStatement; import dmd.Statement; import dmd.Loc; import dmd.OutBuffer; +import dmd.WANT; +import dmd.SwitchStatement; import dmd.HdrGenState; import dmd.Scope; @@ -29,11 +36,60 @@ Statement semantic(Scope sc) { - assert(false); + SwitchStatement sw = sc.sw; + + //printf("CaseRangeStatement.semantic() %s\n", toChars()); + if (sw.isFinal) + error("case ranges not allowed in final switch"); + + first = first.semantic(sc); + first = first.implicitCastTo(sc, sw.condition.type); + first = first.optimize(WANTvalue | WANTinterpret); + long fval = first.toInteger(); + + last = last.semantic(sc); + last = last.implicitCastTo(sc, sw.condition.type); + last = last.optimize(WANTvalue | WANTinterpret); + long lval = last.toInteger(); + + if (lval - fval > 256) + { + error("more than 256 cases in case range"); + lval = fval + 256; + } + + /* This works by replacing the CaseRange with an array of Case's. + * + * case a: .. case b: s; + * => + * case a: + * [...] + * case b: + * s; + */ + + Statements statements = new Statements(); + for (long i = fval; i <= lval; i++) + { + Statement s = statement; + if (i != lval) + s = new ExpStatement(loc, null); + Expression e = new IntegerExp(loc, i, first.type); + Statement cs = new CaseStatement(loc, e, s); + statements.push(cast(void*)cs); + } + Statement s = new CompoundStatement(loc, statements); + s = s.semantic(sc); + return s; } void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + buf.writestring("case "); + first.toCBuffer(buf, hgs); + buf.writestring(": .. case "); + last.toCBuffer(buf, hgs); + buf.writenl(); + statement.toCBuffer(buf, hgs); } } \ No newline at end of file diff -r cab4c37afb89 -r 4290d870944a dmd/CondExp.d --- a/dmd/CondExp.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/CondExp.d Mon Aug 23 20:29:15 2010 +0400 @@ -190,7 +190,16 @@ bool checkSideEffect(int flag) { - assert(false); + if (flag == 2) + { + return econd.checkSideEffect(2) || e1.checkSideEffect(2) || e2.checkSideEffect(2); + } + else + { + econd.checkSideEffect(1); + e1.checkSideEffect(flag); + return e2.checkSideEffect(flag); + } } void toCBuffer(OutBuffer buf, HdrGenState* hgs) diff -r cab4c37afb89 -r 4290d870944a dmd/ConditionalStatement.d --- a/dmd/ConditionalStatement.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/ConditionalStatement.d Mon Aug 23 20:29:15 2010 +0400 @@ -34,7 +34,22 @@ Statement semantic(Scope sc) { - assert(false); + //printf("ConditionalStatement.semantic()\n"); + + // If we can short-circuit evaluate the if statement, don't do the + // semantic analysis of the skipped code. + // This feature allows a limited form of conditional compilation. + if (condition.include(sc, null)) + { + ifbody = ifbody.semantic(sc); + return ifbody; + } + else + { + if (elsebody) + elsebody = elsebody.semantic(sc); + return elsebody; + } } Statements flatten(Scope sc) diff -r cab4c37afb89 -r 4290d870944a dmd/DefaultStatement.d --- a/dmd/DefaultStatement.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/DefaultStatement.d Mon Aug 23 20:29:15 2010 +0400 @@ -61,7 +61,7 @@ bool usesEH() { - assert(false); + return statement.usesEH(); } BE blockExit() @@ -81,7 +81,8 @@ void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + buf.writestring("default:\n"); + statement.toCBuffer(buf, hgs); } Statement inlineScan(InlineScanState* iss) diff -r cab4c37afb89 -r 4290d870944a dmd/GotoCaseStatement.d --- a/dmd/GotoCaseStatement.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/GotoCaseStatement.d Mon Aug 23 20:29:15 2010 +0400 @@ -10,6 +10,7 @@ import dmd.OutBuffer; import dmd.HdrGenState; import dmd.BE; +import dmd.WANT; class GotoCaseStatement : Statement { @@ -18,18 +19,35 @@ this(Loc loc, Expression exp) { - assert(false); super(loc); + cs = null; + this.exp = exp; } Statement syntaxCopy() { - assert(false); + Expression e = exp ? exp.syntaxCopy() : null; + GotoCaseStatement s = new GotoCaseStatement(loc, e); + return s; } Statement semantic(Scope sc) { - assert(false); + if (exp) + exp = exp.semantic(sc); + + if (!sc.sw) + error("goto case not in switch statement"); + else + { + sc.sw.gotoCases.push(cast(void*)this); + if (exp) + { + exp = exp.implicitCastTo(sc, sc.sw.condition.type); + exp = exp.optimize(WANTvalue); + } + } + return this; } Expression interpret(InterState istate) @@ -39,12 +57,19 @@ BE blockExit() { - assert(false); + return BEgoto; } void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + buf.writestring("goto case"); + if (exp) + { + buf.writebyte(' '); + exp.toCBuffer(buf, hgs); + } + buf.writebyte(';'); + buf.writenl(); } void toIR(IRState* irs) diff -r cab4c37afb89 -r 4290d870944a dmd/GotoDefaultStatement.d --- a/dmd/GotoDefaultStatement.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/GotoDefaultStatement.d Mon Aug 23 20:29:15 2010 +0400 @@ -23,12 +23,16 @@ Statement syntaxCopy() { - assert(false); + GotoDefaultStatement s = new GotoDefaultStatement(loc); + return s; } Statement semantic(Scope sc) { - assert(false); + sw = sc.sw; + if (!sw) + error("goto default not in switch statement"); + return this; } Expression interpret(InterState istate) @@ -38,12 +42,12 @@ BE blockExit() { - assert(false); + return BEgoto; } void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + buf.writestring("goto default;\n"); } void toIR(IRState *irs) diff -r cab4c37afb89 -r 4290d870944a dmd/InterfaceDeclaration.d --- a/dmd/InterfaceDeclaration.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/InterfaceDeclaration.d Mon Aug 23 20:29:15 2010 +0400 @@ -292,7 +292,31 @@ bool isBaseOf(BaseClass bc, int* poffset) { - assert(false); + //printf("%s.InterfaceDeclaration.isBaseOf(bc = '%s')\n", toChars(), bc.base.toChars()); + for (uint j = 0; j < bc.baseInterfaces.length; j++) + { + BaseClass b = bc.baseInterfaces[j]; + + if (this == b.base) + { + if (poffset) + { + *poffset = b.offset; + if (j && bc.base.isInterfaceDeclaration()) + *poffset = OFFSET_RUNTIME; + } + return 1; + } + if (isBaseOf(b, poffset)) + { + if (j && poffset && bc.base.isInterfaceDeclaration()) + *poffset = OFFSET_RUNTIME; + return 1; + } + } + if (poffset) + *poffset = 0; + return 0; } string kind() diff -r cab4c37afb89 -r 4290d870944a dmd/NewExp.d --- a/dmd/NewExp.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/NewExp.d Mon Aug 23 20:29:15 2010 +0400 @@ -736,7 +736,12 @@ void scanForNestedRef(Scope sc) { - assert(false); + //printf("NewExp.scanForNestedRef(Scope *sc): %s\n", toChars()); + + if (thisexp) + thisexp.scanForNestedRef(sc); + arrayExpressionScanForNestedRef(sc, newargs); + arrayExpressionScanForNestedRef(sc, arguments); } version (DMDV2) { diff -r cab4c37afb89 -r 4290d870944a dmd/NullExp.d --- a/dmd/NullExp.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/NullExp.d Mon Aug 23 20:29:15 2010 +0400 @@ -54,7 +54,7 @@ void toMangleBuffer(OutBuffer buf) { - assert(false); + buf.writeByte('n'); } MATCH implicitConvTo(Type t) diff -r cab4c37afb89 -r 4290d870944a dmd/SliceExp.d --- a/dmd/SliceExp.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/SliceExp.d Mon Aug 23 20:29:15 2010 +0400 @@ -489,7 +489,17 @@ void scanForNestedRef(Scope sc) { - assert(false); + e1.scanForNestedRef(sc); + + if (lengthVar) + { + //printf("lengthVar\n"); + lengthVar.parent = sc.parent; + } + if (lwr) + lwr.scanForNestedRef(sc); + if (upr) + upr.scanForNestedRef(sc); } void buildArrayIdent(OutBuffer buf, Expressions arguments) diff -r cab4c37afb89 -r 4290d870944a dmd/StructLiteralExp.d --- a/dmd/StructLiteralExp.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/StructLiteralExp.d Mon Aug 23 20:29:15 2010 +0400 @@ -1,6 +1,8 @@ module dmd.StructLiteralExp; import dmd.Expression; +import dmd.MOD; +import dmd.TypeStruct; import dmd.expression.Util; import dmd.ErrorExp; import dmd.Dsymbol; @@ -217,12 +219,39 @@ bool canThrow() { - assert(false); + return arrayExpressionCanThrow(elements); } MATCH implicitConvTo(Type t) { - assert(false); +static if (false) { + printf("StructLiteralExp.implicitConvTo(this=%.*s, type=%.*s, t=%.*s)\n", + toChars(), type.toChars(), t.toChars()); +} + MATCH m = Expression.implicitConvTo(t); + if (m != MATCHnomatch) + return m; + if (type.ty == t.ty && type.ty == Tstruct && (cast(TypeStruct)type).sym == (cast(TypeStruct)t).sym) + { + m = MATCHconst; + for (int i = 0; i < elements.dim; i++) + { + Expression e = cast(Expression)elements.data[i]; + Type te = e.type; + if (t.mod == 0) + te = te.mutableOf(); + else + { + assert(t.mod == MODinvariant); + te = te.invariantOf(); + } + MATCH m2 = e.implicitConvTo(te); + //printf("\t%s => %s, match = %d\n", e.toChars(), te.toChars(), m2); + if (m2 < m) + m = m2; + } + } + return m; } int inlineCost(InlineCostState* ics) diff -r cab4c37afb89 -r 4290d870944a dmd/SymOffExp.d --- a/dmd/SymOffExp.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/SymOffExp.d Mon Aug 23 20:29:15 2010 +0400 @@ -206,7 +206,10 @@ void scanForNestedRef(Scope sc) { - assert(false); + //printf("SymOffExp.scanForNestedRef(%s)\n", toChars()); + VarDeclaration v = var.isVarDeclaration(); + if (v) + v.checkNestedReference(sc, Loc(0)); } dt_t** toDt(dt_t** pdt) diff -r cab4c37afb89 -r 4290d870944a dmd/TemplateValueParameter.d --- a/dmd/TemplateValueParameter.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/TemplateValueParameter.d Mon Aug 23 20:29:15 2010 +0400 @@ -262,6 +262,16 @@ void* dummyArg() { - assert(false); + Expression e; + + e = specValue; + if (!e) + { + // Create a dummy value + if (!edummy) + edummy = valType.defaultInit(Loc(0)); + e = edummy; + } + return cast(void*)e; } } \ No newline at end of file diff -r cab4c37afb89 -r 4290d870944a dmd/TypeClass.d --- a/dmd/TypeClass.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/TypeClass.d Mon Aug 23 20:29:15 2010 +0400 @@ -2,6 +2,7 @@ import dmd.Type; import dmd.ClassDeclaration; +import dmd.TypeInstance; import dmd.Loc; import dmd.Dsymbol; import dmd.Scope; @@ -10,6 +11,7 @@ import dmd.Expression; import dmd.Identifier; import dmd.MATCH; +import dmd.DYNCAST; import dmd.CppMangleState; import dmd.ArrayTypes; import dmd.TypeInfoDeclaration; @@ -529,7 +531,53 @@ MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) { - assert(false); + //printf("TypeClass.deduceType(this = %s)\n", toChars()); + + /* If this class is a template class, and we're matching + * it against a template instance, convert the class type + * to a template instance, too, and try again. + */ + TemplateInstance ti = sym.parent.isTemplateInstance(); + + if (tparam && tparam.ty == Tinstance) + { + if (ti && ti.toAlias() == sym) + { + TypeInstance t = new TypeInstance(Loc(0), ti); + return t.deduceType(sc, tparam, parameters, dedtypes); + } + + /* Match things like: + * S!(T).foo + */ + TypeInstance tpi = cast(TypeInstance)tparam; + if (tpi.idents.dim) + { Identifier id = cast(Identifier)tpi.idents.data[tpi.idents.dim - 1]; + if (id.dyncast() == DYNCAST.DYNCAST_IDENTIFIER && sym.ident.equals(id)) + { + Type tparent = sym.parent.getType(); + if (tparent) + { + /* Slice off the .foo in S!(T).foo + */ + tpi.idents.dim--; + MATCH m = tparent.deduceType(sc, tpi, parameters, dedtypes); + tpi.idents.dim++; + return m; + } + } + } + } + + // Extra check + if (tparam && tparam.ty == Tclass) + { + TypeClass tp = cast(TypeClass)tparam; + + //printf("\t%d\n", (MATCH) implicitConvTo(tp)); + return implicitConvTo(tp); + } + return Type.deduceType(sc, tparam, parameters, dedtypes); } bool isauto() diff -r cab4c37afb89 -r 4290d870944a dmd/TypeInfoStaticArrayDeclaration.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/TypeInfoStaticArrayDeclaration.d Mon Aug 23 20:29:15 2010 +0400 @@ -0,0 +1,18 @@ +module dmd.TypeInfoStaticArrayDeclaration; + +import dmd.Type; +import dmd.TypeInfoDeclaration; +import dmd.backend.dt_t; + +class TypeInfoStaticArrayDeclaration : TypeInfoDeclaration +{ + this(Type tinfo) + { + super(tinfo, 0); + } + + void toDt(dt_t **pdt) + { + assert(false); + } +} \ No newline at end of file diff -r cab4c37afb89 -r 4290d870944a dmd/TypeSArray.d --- a/dmd/TypeSArray.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/TypeSArray.d Mon Aug 23 20:29:15 2010 +0400 @@ -1,6 +1,7 @@ module dmd.TypeSArray; import dmd.TypeArray; +import dmd.TypeInfoStaticArrayDeclaration; import dmd.TypeAArray; import dmd.MOD; import dmd.Argument; @@ -330,7 +331,8 @@ bool isString() { - assert(false); + TY nty = next.toBasetype().ty; + return nty == Tchar || nty == Twchar || nty == Tdchar; } bool isZeroInit(Loc loc) @@ -575,7 +577,7 @@ TypeInfoDeclaration getTypeInfoDeclaration() { - assert(false); + return new TypeInfoStaticArrayDeclaration(this); } Expression toExpression() diff -r cab4c37afb89 -r 4290d870944a dmd/TypeTypedef.d --- a/dmd/TypeTypedef.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/TypeTypedef.d Mon Aug 23 20:29:15 2010 +0400 @@ -98,7 +98,14 @@ Expression getProperty(Loc loc, Identifier ident) { - assert(false); +version (LOGDOTEXP) { + printf("TypeTypedef.getProperty(ident = '%s') '%s'\n", ident.toChars(), toChars()); +} + if (ident == Id.init_) + { + return Type.getProperty(loc, ident); + } + return sym.basetype.getProperty(loc, ident); } bool isbit() @@ -146,7 +153,7 @@ bool checkBoolean() { - assert(false); + return sym.basetype.checkBoolean(); } int isAssignable() diff -r cab4c37afb89 -r 4290d870944a dmd/UnaExp.d --- a/dmd/UnaExp.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/UnaExp.d Mon Aug 23 20:29:15 2010 +0400 @@ -72,7 +72,7 @@ void scanForNestedRef(Scope sc) { - assert(false); + e1.scanForNestedRef(sc); } Expression interpretCommon(InterState istate, Expression *(*fp)(Type* a0, Expression* a1)) diff -r cab4c37afb89 -r 4290d870944a dmd/VarExp.d --- a/dmd/VarExp.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/VarExp.d Mon Aug 23 20:29:15 2010 +0400 @@ -232,7 +232,10 @@ void scanForNestedRef(Scope sc) { - assert(false); + //printf("VarExp.scanForNestedRef(%s)\n", toChars()); + VarDeclaration v = var.isVarDeclaration(); + if (v) + v.checkNestedReference(sc, Loc(0)); } int inlineCost(InlineCostState* ics) diff -r cab4c37afb89 -r 4290d870944a dmd/expression/Util.d --- a/dmd/expression/Util.d Mon Aug 23 16:52:24 2010 +0400 +++ b/dmd/expression/Util.d Mon Aug 23 20:29:15 2010 +0400 @@ -1529,4 +1529,25 @@ while (u < v) u = (u << 1) | 1; return u; +} + +/****************************** + * Perform scanForNestedRef() on an array of Expressions. + */ + +void arrayExpressionScanForNestedRef(Scope sc, Expressions a) +{ + //printf("arrayExpressionScanForNestedRef(%p)\n", a); + if (a) + { + for (int i = 0; i < a.dim; i++) + { + Expression e = cast(Expression)a.data[i]; + + if (e) + { + e.scanForNestedRef(sc); + } + } + } } \ No newline at end of file