# HG changeset patch # User Eldar Insafutdinov # Date 1284069104 -3600 # Node ID 60bb0fe4563e7eca081bf739df294afa3d636c07 # Parent 010eb8f0e18deb24d2ad16c8ba9f6817df18256b dmdfe 2.037 first main iteration diff -r 010eb8f0e18d -r 60bb0fe4563e commands.linux.txt --- a/commands.linux.txt Sun Sep 05 15:32:22 2010 +0400 +++ b/commands.linux.txt Thu Sep 09 22:51:44 2010 +0100 @@ -113,7 +113,7 @@ dmd/AliasThis.d dmd/AlignDeclaration.d dmd/AnonymousAggregateDeclaration.d -dmd/Argument.d +dmd/Parameter.d dmd/FuncExp.d dmd/ArrayLiteralExp.d dmd/AssocArrayLiteralExp.d @@ -271,6 +271,7 @@ dmd/Param.d dmd/Parser.d dmd/PostBlitDeclaration.d +dmd/PowExp.d dmd/PragmaDeclaration.d dmd/PragmaStatement.d dmd/ProtDeclaration.d @@ -298,6 +299,7 @@ dmd/SymbolDeclaration.d dmd/SynchronizedStatement.d dmd/TOK.d +dmd/TRUST.d dmd/TY.d dmd/TemplateAliasParameter.d dmd/TemplateDeclaration.d diff -r 010eb8f0e18d -r 60bb0fe4563e commands.txt --- a/commands.txt Sun Sep 05 15:32:22 2010 +0400 +++ b/commands.txt Thu Sep 09 22:51:44 2010 +0100 @@ -108,7 +108,7 @@ dmd\AliasThis.d dmd\AlignDeclaration.d dmd\AnonymousAggregateDeclaration.d -dmd\Argument.d +dmd\Parameter.d dmd\FuncExp.d dmd\ArrayLiteralExp.d dmd\AssocArrayLiteralExp.d @@ -266,6 +266,7 @@ dmd\Param.d dmd\Parser.d dmd\PostBlitDeclaration.d +dmd\PowExp.d dmd\PragmaDeclaration.d dmd\PragmaStatement.d dmd\ProtDeclaration.d @@ -293,6 +294,7 @@ dmd\SymbolDeclaration.d dmd\SynchronizedStatement.d dmd\TOK.d +dmd\TRUST.d dmd\TY.d dmd\TemplateAliasParameter.d dmd\TemplateDeclaration.d diff -r 010eb8f0e18d -r 60bb0fe4563e ddmd.visualdproj --- a/ddmd.visualdproj Sun Sep 05 15:32:22 2010 +0400 +++ b/ddmd.visualdproj Thu Sep 09 22:51:44 2010 +0100 @@ -175,9 +175,6 @@ *.obj - - - @@ -308,7 +305,6 @@ - @@ -609,6 +605,12 @@ + + + + + + diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/AddAssignExp.d --- a/dmd/AddAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/AddAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -7,7 +7,7 @@ import dmd.Expression; import dmd.Scope; import dmd.InterState; -import dmd.Argument; +import dmd.Parameter; import dmd.STC; import dmd.OutBuffer; import dmd.ArrayTypes; @@ -21,6 +21,7 @@ import dmd.AssignExp; import dmd.Global; import dmd.Id; +import dmd.ArrayLengthExp; import dmd.backend.OPER; import dmd.backend.elem; @@ -49,6 +50,13 @@ Type tb1 = e1.type.toBasetype(); Type tb2 = e2.type.toBasetype(); + if (e1.op == TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + if (e1.op == TOK.TOKslice) { typeCombine(sc); @@ -151,7 +159,7 @@ AssignExp_buildArrayIdent(buf, arguments, "Add"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return AssignExp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/AddExp.d --- a/dmd/AddExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/AddExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -122,7 +122,7 @@ Exp_buildArrayIdent(buf, arguments, "Add"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return Exp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/AggregateDeclaration.d --- a/dmd/AggregateDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/AggregateDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -141,7 +141,7 @@ class AggregateDeclaration : ScopeDsymbol { Type type; - uint storage_class; + STC storage_class; PROT protection = PROT.PROTpublic; Type handle; // 'this' type uint structsize; // size of struct @@ -154,10 +154,11 @@ // 1: size is correct // 2: cannot determine size; fwd referenced bool isdeprecated; // true if deprecated - + +version (DMDV2) { bool isnested; // true if is nested VarDeclaration vthis; // 'this' parameter if this aggregate is nested - +} // Special member functions InvariantDeclaration inv; // invariant NewDeclaration aggNew; // allocator diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/AndAssignExp.d --- a/dmd/AndAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/AndAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -39,7 +39,7 @@ AssignExp_buildArrayIdent(buf, arguments, "And"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return AssignExp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/AndExp.d --- a/dmd/AndExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/AndExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -83,7 +83,7 @@ Exp_buildArrayIdent(buf, arguments, "And"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return Exp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Argument.d --- a/dmd/Argument.d Sun Sep 05 15:32:22 2010 +0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,303 +0,0 @@ -module dmd.Argument; - -import dmd.common; -import dmd.Type; -import dmd.Identifier; -import dmd.TypeArray; -import dmd.TypeFunction; -import dmd.TypeDelegate; -import dmd.TypeTuple; -import dmd.TY; -import dmd.Expression; -import dmd.OutBuffer; -import dmd.HdrGenState; -import dmd.ArrayTypes; -import dmd.StorageClassDeclaration; -import dmd.Global; -import dmd.MOD; -import dmd.CppMangleState; -import dmd.STC; - -class Argument -{ - //enum InOut inout; - STC storageClass; - Type type; - Identifier ident; - Expression defaultArg; - - this(STC storageClass, Type type, Identifier ident, Expression defaultArg) - { - this.type = type; - this.ident = ident; - this.storageClass = storageClass; - this.defaultArg = defaultArg; - } - - Argument clone() - { - return new Argument(storageClass, type, ident, defaultArg); - } - - Argument syntaxCopy() - { - return new Argument(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null); - } - - /**************************************************** - * Determine if parameter is a lazy array of delegates. - * If so, return the return type of those delegates. - * If not, return null. - */ - Type isLazyArray() - { - // if (inout == Lazy) - { - Type tb = type.toBasetype(); - if (tb.ty == Tsarray || tb.ty == Tarray) - { - Type tel = (cast(TypeArray)tb).next.toBasetype(); - if (tel.ty == Tdelegate) - { - TypeDelegate td = cast(TypeDelegate)tel; - TypeFunction tf = cast(TypeFunction)td.next; - - if (!tf.varargs && Argument.dim(tf.parameters) == 0) - { - return tf.next; // return type of delegate - } - } - } - } - return null; - } - - void toDecoBuffer(OutBuffer buf) - { - if (storageClass & STC.STCscope) - buf.writeByte('M'); - switch (storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STClazy)) - { - case STC.STCundefined: - case STC.STCin: - break; - case STC.STCout: - buf.writeByte('J'); - break; - case STC.STCref: - buf.writeByte('K'); - break; - case STC.STClazy: - buf.writeByte('L'); - break; - } -static if (false) { - int mod = 0x100; - if (type.toBasetype().ty == TY.Tclass) - mod = 0; - type.toDecoBuffer(buf, mod); -} else { - //type.toHeadMutable().toDecoBuffer(buf, 0); - type.toDecoBuffer(buf, 0); -} - } - - static Arguments arraySyntaxCopy(Arguments args) - { - typeof(return) a = null; - - if (args) - { - a = new Arguments(); - a.setDim(args.dim); - - for (size_t i = 0; i < a.dim; i++) - { - auto arg = args[i]; - - arg = arg.syntaxCopy(); - a[i] = arg; - } - } - - return a; - } - - static string argsTypesToChars(Arguments args, int varargs) - { - scope OutBuffer buf = new OutBuffer(); - - static if (true) { - HdrGenState hgs; - argsToCBuffer(buf, &hgs, args, varargs); - } else { - buf.writeByte('('); - if (args) - { - OutBuffer argbuf = new OutBuffer(); - HdrGenState hgs; - - for (int i = 0; i < args.dim; i++) - { - if (i) - buf.writeByte(','); - Argument arg = cast(Argument)args.data[i]; - argbuf.reset(); - arg.type.toCBuffer2(&argbuf, &hgs, 0); - buf.write(&argbuf); - } - if (varargs) - { - if (i && varargs == 1) - buf.writeByte(','); - buf.writestring("..."); - } - } - buf.writeByte(')'); - } - return buf.toChars(); - } - - static void argsCppMangle(OutBuffer buf, CppMangleState* cms, Arguments arguments, int varargs) - { - assert(false); - } - - static void argsToCBuffer(OutBuffer buf, HdrGenState* hgs, Arguments arguments, int varargs) - { - buf.writeByte('('); - if (arguments) - { - int i; - scope OutBuffer argbuf = new OutBuffer(); - - for (i = 0; i < arguments.dim; i++) - { - if (i) - buf.writestring(", "); - auto arg = arguments[i]; - - if (arg.storageClass & STCout) - buf.writestring("out "); - else if (arg.storageClass & STCref) - buf.writestring((global.params.Dversion == 1) ? "inout " : "ref "); - else if (arg.storageClass & STCin) - buf.writestring("in "); - else if (arg.storageClass & STClazy) - buf.writestring("lazy "); - else if (arg.storageClass & STCalias) - buf.writestring("alias "); - else if (arg.storageClass & STCauto) - buf.writestring("auto "); - - uint stc = arg.storageClass; - if (arg.type && arg.type.mod & MODshared) - stc &= ~STCshared; - - StorageClassDeclaration.stcToCBuffer(buf, stc & (STCconst | STCimmutable | STCshared | STCscope)); - - argbuf.reset(); - if (arg.storageClass & STCalias) - { - if (arg.ident) - argbuf.writestring(arg.ident.toChars()); - } - else - arg.type.toCBuffer(argbuf, arg.ident, hgs); - if (arg.defaultArg) - { - argbuf.writestring(" = "); - arg.defaultArg.toCBuffer(argbuf, hgs); - } - buf.write(argbuf); - } - if (varargs) - { - if (i && varargs == 1) - buf.writeByte(','); - buf.writestring("..."); - } - } - buf.writeByte(')'); - } - - static void argsToDecoBuffer(OutBuffer buf, Arguments arguments) - { - //printf("Argument::argsToDecoBuffer()\n"); - - // Write argument types - if (arguments) - { - size_t dim = Argument.dim(arguments); - for (size_t i = 0; i < dim; i++) - { - Argument arg = Argument.getNth(arguments, i); - arg.toDecoBuffer(buf); - } - } - } - - static int isTPL(Arguments arguments) - { - assert(false); - } - - /*************************************** - * Determine number of arguments, folding in tuples. - */ - static size_t dim(Arguments args) - { - size_t n = 0; - if (args) - { - foreach (arg; args) - { - Type t = arg.type.toBasetype(); - - if (t.ty == TY.Ttuple) - { - auto tu = cast(TypeTuple)t; - n += dim(tu.arguments); - } - else - n++; - } - } - return n; - } - - /*************************************** - * Get nth Argument, folding in tuples. - * Returns: - * Argument nth Argument - * null not found, *pn gets incremented by the number - * of Arguments - */ - static Argument getNth(Arguments args, size_t nth, size_t* pn = null) - { - if (!args) - return null; - - size_t n = 0; - foreach (arg; args) - { - Type t = arg.type.toBasetype(); - - if (t.ty == TY.Ttuple) - { TypeTuple tu = cast(TypeTuple)t; - arg = getNth(tu.arguments, nth - n, &n); - if (arg) - return arg; - } - else if (n == nth) - return arg; - else - n++; - } - - if (pn) - *pn += n; - - return null; - } -} diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ArrayInitializer.d --- a/dmd/ArrayInitializer.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ArrayInitializer.d Thu Sep 09 22:51:44 2010 +0100 @@ -98,8 +98,6 @@ length = 0; foreach (size_t i, Expression idx; index) { - Initializer val; - if (idx) { idx = idx.semantic(sc); @@ -108,7 +106,7 @@ length = cast(uint)idx.toInteger(); } - val = value[i]; + Initializer val = value[i]; val = val.semantic(sc, t.nextOf()); value[i] = val; length++; @@ -124,9 +122,22 @@ return this; } + int isAssociativeArray() + { + for (size_t i = 0; i < value.dim; i++) + { + if (index[i]) + return 1; + } + return 0; + } + override Type inferType(Scope sc) { //printf("ArrayInitializer.inferType() %s\n", toChars()); + assert(0); + return null; +static if (false) { type = Type.terror; for (size_t i = 0; i < value.dim; i++) { @@ -140,7 +151,9 @@ { Type t = iz.inferType(sc); if (i == 0) - { + { /* BUG: This gets the type from the first element. + * Fix to use all the elements to figure out the type. + */ t = new TypeSArray(t, new IntegerExp(value.dim)); t = t.semantic(loc, sc); type = t; @@ -150,8 +163,9 @@ return type; Laa: - /* It's possibly an associative array initializer - */ + /* It's possibly an associative array initializer. + * BUG: inferring type from first member. + */ Initializer iz = value[0]; Expression indexinit = index[0]; if (iz && indexinit) @@ -165,6 +179,7 @@ else error(loc, "cannot infer type from this array initializer"); return type; +} } /******************************** @@ -256,7 +271,7 @@ return null; } - Initializer toAssocArrayInitializer() + Expression toAssocArrayLiteral() { assert(false); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ArrayLengthExp.d --- a/dmd/ArrayLengthExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ArrayLengthExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -2,6 +2,7 @@ import dmd.common; import dmd.Expression; +import dmd.BinExp; import dmd.backend.elem; import dmd.UnaExp; import dmd.InterState; @@ -13,6 +14,16 @@ import dmd.TOK; import dmd.Type; import dmd.WANT; +import dmd.VarExp; +import dmd.VarDeclaration; +import dmd.PtrExp; +import dmd.Lexer; +import dmd.Identifier; +import dmd.ExpInitializer; +import dmd.DeclarationExp; +import dmd.CommaExp; +import dmd.AssignExp; +import dmd.AddrExp; import dmd.expression.ArrayLength; @@ -28,8 +39,6 @@ override Expression semantic(Scope sc) { - Expression e; - version (LOGSEMANTIC) { printf("ArrayLengthExp::semantic('%s')\n", toChars()); } @@ -43,6 +52,35 @@ return this; } + static Expression rewriteOpAssign(BinExp exp) + { + Expression e; + + assert(exp.e1.op == TOKarraylength); + auto ale = cast(ArrayLengthExp)exp.e1; + if (ale.e1.op == TOK.TOKvar) + { + e = opAssignToOp(exp.loc, exp.op, ale, exp.e2); + e = new AssignExp(exp.loc, ale.syntaxCopy(), e); + } + else + { + /* auto tmp = &array; + * (*tmp).length = (*tmp).length op e2 + */ + Identifier id = Lexer.uniqueId("__arraylength"); + ExpInitializer ei = new ExpInitializer(ale.loc, new AddrExp(ale.loc, ale.e1)); + VarDeclaration tmp = new VarDeclaration(ale.loc, ale.e1.type.pointerTo(), id, ei); + + Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp))); + Expression elvalue = e1.syntaxCopy(); + e = opAssignToOp(exp.loc, exp.op, e1, exp.e2); + e = new AssignExp(exp.loc, elvalue, e); + e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e); + } + return e; + } + override Expression optimize(int result) { //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ArrayLiteralExp.d --- a/dmd/ArrayLiteralExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ArrayLiteralExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -58,58 +58,19 @@ override Expression semantic(Scope sc) { - Expression e; - Type t0 = null; - version (LOGSEMANTIC) { printf("ArrayLiteralExp.semantic('%s')\n", toChars()); } if (type) return this; - // Run semantic() on each element - foreach (ref Expression e; elements) - { - e = e.semantic(sc); - assert(e.type); - } + arrayExpressionSemantic(elements, sc); // run semantic() on each element expandTuples(elements); - foreach (size_t i, Expression e; elements) - { - if (!e.type) - error("%s has no value", e.toChars()); - - e = resolveProperties(sc, e); - - ubyte committed = 1; - if (e.op == TOKstring) - committed = (cast(StringExp)e).committed; - - if (!t0) - { - t0 = e.type; - // Convert any static arrays to dynamic arrays - if (t0.ty == Tsarray) - { - t0 = (cast(TypeSArray)t0).next.arrayOf(); - e = e.implicitCastTo(sc, t0); - } - } - else - e = e.implicitCastTo(sc, t0); - - if (!committed && e.op == TOKstring) - { - auto se = cast(StringExp)e; - se.committed = 0; - } - elements[i] = e; - } - - if (!t0) - t0 = Type.tvoid; + Type t0; + elements = arrayExpressionToCommonType(sc, elements, &t0); + type = new TypeSArray(t0, new IntegerExp(elements.dim)); type = type.semantic(loc, sc); return this; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ArrayTypes.d --- a/dmd/ArrayTypes.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ArrayTypes.d Thu Sep 09 22:51:44 2010 +0100 @@ -6,7 +6,7 @@ import dmd.Statement; import dmd.BaseClass; import dmd.ClassDeclaration; -import dmd.Argument; +import dmd.Parameter; import dmd.Identifier; import dmd.Initializer; @@ -15,6 +15,6 @@ alias Vector!Statement Statements; alias Vector!BaseClass BaseClasses; alias Vector!ClassDeclaration ClassDeclarations; -alias Vector!Argument Arguments; +alias Vector!Parameter Parameters; alias Vector!Identifier Identifiers; alias Vector!Initializer Initializers; \ No newline at end of file diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/AsmStatement.d --- a/dmd/AsmStatement.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/AsmStatement.d Thu Sep 09 22:51:44 2010 +0100 @@ -59,12 +59,16 @@ override Statement semantic(Scope sc) { //printf("AsmStatement.semantic()\n"); - - if (global.params.safe && !sc.module_.safe) - { - error("inline assembler not allowed in safe mode"); - } - +//static if (true) { + if (sc.func && sc.func.isSafe()) + error("inline assembler not allowed in @safe function %s", sc.func.toChars()); +//} else { +// if (global.params.safe && !sc.module_.safe) +// { +// error("inline assembler not allowed in safe mode"); +// } +//} + OP* o; OPND* o1 = null; OPND* o2 = null; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/AssignExp.d --- a/dmd/AssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/AssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -5,7 +5,7 @@ import dmd.Identifier; import dmd.backend.elem; import dmd.InterState; -import dmd.Argument; +import dmd.Parameter; import dmd.IndexExp; import dmd.CallExp; import dmd.CastExp; @@ -390,7 +390,7 @@ buf.writestring("Assign"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { /* Evaluate assign expressions right to left */ @@ -412,9 +412,6 @@ override elem* toElem(IRState* irs) { - elem* e; - IndexExp ae; - int r; Type t1b; //printf("AssignExp.toElem('%s')\n", toChars()); @@ -427,45 +424,25 @@ // _d_arraysetlength(e2, sizeelem, &ale.e1); ArrayLengthExp ale = cast(ArrayLengthExp)e1; - elem* p1; - elem* p2; - elem* p3; - elem* ep; - Type t1; - p1 = e2.toElem(irs); - p3 = ale.e1.toElem(irs); + auto p1 = e2.toElem(irs); + auto p3 = ale.e1.toElem(irs); p3 = addressElem(p3, null); - t1 = ale.e1.type.toBasetype(); + Type t1 = ale.e1.type.toBasetype(); -static if (true) { // call _d_arraysetlengthT(ti, e2, &ale.e1); - p2 = t1.getTypeInfo(null).toElem(irs); - ep = el_params(p3, p1, p2, null); // c function - r = t1.nextOf().isZeroInit(Loc(0)) ? RTLSYM.RTLSYM_ARRAYSETLENGTHT : RTLSYM.RTLSYM_ARRAYSETLENGTHIT; -} else { - if (t1.next.isZeroInit()) - { - p2 = t1.getTypeInfo(null).toElem(irs); - ep = el_params(p3, p1, p2, null); // c function - r = RTLSYM.RTLSYM_ARRAYSETLENGTHT; - } - else - { - p2 = el_long(TYM.TYint, t1.next.size()); - ep = el_params(p3, p2, p1, null); // c function - Expression init = t1.next.defaultInit(); - ep = el_param(el_long(TYM.TYint, init.type.size()), ep); - elem* ei = init.toElem(irs); - ep = el_param(ei, ep); - r = RTLSYM.RTLSYM_ARRAYSETLENGTH3; - } -} - e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[r]), ep); + auto p2 = t1.getTypeInfo(null).toElem(irs); + auto ep = el_params(p3, p1, p2, null); // c function + int r = t1.nextOf().isZeroInit(Loc(0)) ? RTLSYM.RTLSYM_ARRAYSETLENGTHT : RTLSYM.RTLSYM_ARRAYSETLENGTHIT; + + auto e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[r]), ep); el_setLoc(e, loc); return e; } - + + elem *e; + IndexExp ae; + // Look for array[]=n if (e1.op == TOK.TOKslice) { @@ -560,7 +537,7 @@ elem_print(enbytes); } - if (global.params.useArrayBounds && eupr && ta.ty != TY.Tpointer) + if (irs.arrayBoundsCheck() && eupr && ta.ty != TY.Tpointer) { elem *c1; elem *c2; @@ -651,16 +628,13 @@ /* It's array1[]=array2[] * which is a memcpy */ - elem* eto; - elem* efrom; - elem* esize; elem* ep; - eto = e1.toElem(irs); - efrom = e2.toElem(irs); + auto eto = e1.toElem(irs); + auto efrom = e2.toElem(irs); uint size = cast(uint)t1.nextOf().size(); - esize = el_long(TYM.TYint, size); + auto esize = el_long(TYM.TYint, size); /* Determine if we need to do postblit */ @@ -670,16 +644,12 @@ assert(e2.type.ty != TY.Tpointer); - if (!postblit && !global.params.useArrayBounds) + if (!postblit && !irs.arrayBoundsCheck()) { - elem* epto; - elem* epfr; - elem* elen; - elem* ex; - - ex = el_same(&eto); + auto ex = el_same(&eto); // Determine if elen is a constant + elem *elen; if (eto.Eoper == OPER.OPpair && eto.E1.Eoper == OPER.OPconst) { elen = el_copytree(eto.E1); @@ -691,8 +661,8 @@ } esize = el_bin(OPER.OPmul, TYM.TYint, elen, esize); - epto = array_toPtr(e1.type, ex); - epfr = array_toPtr(e2.type, efrom); + auto epto = array_toPtr(e1.type, ex); + auto epfr = array_toPtr(e2.type, efrom); static if (true) { // memcpy() is faster, so if we can't beat 'em, join 'em e = el_params(esize, epfr, epto, null); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/AssocArrayLiteralExp.d --- a/dmd/AssocArrayLiteralExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/AssocArrayLiteralExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -51,8 +51,6 @@ override Expression semantic(Scope sc) { Expression e; - Type tkey = null; - Type tvalue = null; version (LOGSEMANTIC) { printf("AssocArrayLiteralExp.semantic('%s')\n", toChars()); @@ -62,16 +60,8 @@ return this; // Run semantic() on each element - for (size_t i = 0; i < keys.dim; i++) - { auto key = keys[i]; - auto value = values[i]; - - key = key.semantic(sc); - value = value.semantic(sc); - - keys[i] = key; - values[i] = value; - } + arrayExpressionSemantic(keys, sc); + arrayExpressionSemantic(values, sc); expandTuples(keys); expandTuples(values); if (keys.dim != values.dim) @@ -80,34 +70,12 @@ keys.setDim(0); values.setDim(0); } - for (size_t i = 0; i < keys.dim; i++) - { auto key = keys[i]; - auto value = values[i]; - - if (!key.type) - error("%s has no value", key.toChars()); - if (!value.type) - error("%s has no value", value.toChars()); - key = resolveProperties(sc, key); - value = resolveProperties(sc, value); - - if (!tkey) - tkey = key.type; - else - key = key.implicitCastTo(sc, tkey); - keys[i] = key; - - if (!tvalue) - tvalue = value.type; - else - value = value.implicitCastTo(sc, tvalue); - values[i] = value; - } - - if (!tkey) - tkey = Type.tvoid; - if (!tvalue) - tvalue = Type.tvoid; + + Type tkey; + Type tvalue; + keys = arrayExpressionToCommonType(sc, keys, &tkey); + values = arrayExpressionToCommonType(sc, values, &tvalue); + type = new TypeAArray(tvalue, tkey); type = type.semantic(loc, sc); return this; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/BinExp.d --- a/dmd/BinExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/BinExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -54,7 +54,7 @@ import dmd.PREC; import dmd.StringValue; import dmd.StringTable; -import dmd.Argument; +import dmd.Parameter; import dmd.Statement; import dmd.ForeachRangeStatement; import dmd.ArrayLengthExp; @@ -125,11 +125,8 @@ TY ty = cast(TY)Type.impcnvResult[t1b.ty][t2b.ty]; if (ty != TY.Terror) { - TY ty1; - TY ty2; - - ty1 = cast(TY)Type.impcnvType1[t1b.ty][t2b.ty]; - ty2 = cast(TY)Type.impcnvType2[t1b.ty][t2b.ty]; + auto ty1 = cast(TY)Type.impcnvType1[t1b.ty][t2b.ty]; + auto ty2 = cast(TY)Type.impcnvType2[t1b.ty][t2b.ty]; if (t1b.ty == ty1) // if no promotions { @@ -206,16 +203,24 @@ } } else if ((t1.ty == TY.Tsarray || t1.ty == TY.Tarray) && - e2.op == TOK.TOKnull && t2.ty == TY.Tpointer && t2.nextOf().ty == TY.Tvoid) - { /* (T[n] op void*) - * (T[] op void*) - */ + (e2.op == TOK.TOKnull && t2.ty == TY.Tpointer && t2.nextOf().ty == TY.Tvoid || + e2.op == TOK.TOKarrayliteral && t2.ty == TY.Tsarray && t2.nextOf().ty == TY.Tvoid && (cast(TypeSArray)t2).dim.toInteger() == 0) + ) + { /* (T[n] op void*) => T[] + * (T[] op void*) => T[] + * (T[n] op void[0]) => T[] + * (T[] op void[0]) => T[] + */ goto Lx1; } else if ((t2.ty == TY.Tsarray || t2.ty == TY.Tarray) && - e1.op == TOK.TOKnull && t1.ty == TY.Tpointer && t1.nextOf().ty == TY.Tvoid) - { /* (void* op T[n]) - * (void* op T[]) + (e1.op == TOK.TOKnull && t1.ty == TY.Tpointer && t1.nextOf().ty == TY.Tvoid || + e1.op == TOK.TOKarrayliteral && t1.ty == TY.Tsarray && t1.nextOf().ty == TY.Tvoid && (cast(TypeSArray)t1).dim.toInteger() == 0) + ) + { /* (void* op T[n]) => T[] + * (void* op T[]) => T[] + * (void[0] op T[n]) => T[] + * (void[0] op T[]) => T[] */ goto Lx2; } @@ -313,7 +318,7 @@ e2.implicitConvTo(t1.nextOf().arrayOf())) { Lx1: - t = t1.nextOf().arrayOf(); + t = t1.nextOf().arrayOf(); // T[] e1 = e1.castTo(sc, t); e2 = e2.castTo(sc, t); } @@ -450,6 +455,13 @@ if (e) return e; + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + if (e1.op == TOKslice) { // T[] op= ... @@ -490,6 +502,13 @@ if (e) return e; + if (e1.op == TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + if (e1.op == TOK.TOKslice) { // T[] op= ... typeCombine(sc); @@ -1442,7 +1461,7 @@ return new ErrorExp(); } - Expressions arguments = new Expressions(); + auto arguments = new Expressions(); /* The expression to generate an array operation for is mangled * into a name to use as the array operation function name. @@ -1657,7 +1676,7 @@ * return p; */ - Arguments fparams = new Arguments(); + auto fparams = new Parameters(); Expression loopbody = buildArrayLoop(fparams); auto p = fparams[0 /*fparams.dim - 1*/]; version (DMDV1) { @@ -1672,7 +1691,7 @@ } else { // foreach (i; 0 .. p.length) Statement s1 = new ForeachRangeStatement(Loc(0), TOKforeach, - new Argument(STC.STCundefined, null, Id.p, null), + new Parameter(STC.STCundefined, null, Id.p, null), new IntegerExp(Loc(0), 0, Type.tint32), new ArrayLengthExp(Loc(0), new IdentifierExp(Loc(0), p.ident)), new ExpStatement(Loc(0), loopbody)); @@ -2030,7 +2049,7 @@ buf.writestring(Str); } - final Expression AssignExp_buildArrayLoop(AssignExpType)(Arguments fparams)// if (is (AssignExpType : AssignExp)) + final Expression AssignExp_buildArrayLoop(AssignExpType)(Parameters fparams)// if (is (AssignExpType : AssignExp)) { /* Evaluate assign expressions right to left */ @@ -2042,7 +2061,7 @@ return e; } - final Expression Exp_buildArrayLoop(ExpType)(Arguments fparams) if (is (ExpType : BinExp)) + final Expression Exp_buildArrayLoop(ExpType)(Parameters fparams) if (is (ExpType : BinExp)) { /* Evaluate assign expressions left to right */ diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/CallExp.d --- a/dmd/CallExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/CallExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -49,6 +49,7 @@ import dmd.DotVarExp; import dmd.DotIdExp; import dmd.TY; +import dmd.TRUST; import dmd.Id; import dmd.TypeAArray; import dmd.RemoveExp; @@ -214,25 +215,25 @@ * If not, go with partial explicit specialization. */ ti.semanticTiargs(sc); - uint errors = global.errors; - global.gag++; - ti.semantic(sc); - global.gag--; - if (errors != global.errors) + if (ti.needsTypeInference(sc)) { - /* Didn't work, go with partial explicit specialization + /* Go with partial explicit specialization */ - global.errors = errors; targsi = ti.tiargs; tierror = ti; // for error reporting e1 = new IdentifierExp(loc, ti.name); } + else + { + ti.semantic(sc); + } } } /* This recognizes: * expr.foo!(tiargs)(funcargs) */ +Ldotti: if (e1.op == TOK.TOKdotti && !e1.type) { DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)e1; @@ -243,6 +244,7 @@ * If not, go with partial explicit specialization. */ ti.semanticTiargs(sc); +static if (false) { Expression etmp = e1.trySemantic(sc); if (etmp) e1 = etmp; // it worked @@ -252,6 +254,24 @@ tierror = ti; // for error reporting e1 = new DotIdExp(loc, se.e1, ti.name); } +} else { + if (!ti.tempdecl) + { + se.getTempdecl(sc); + } + if (ti.tempdecl && ti.needsTypeInference(sc)) + { + /* Go with partial explicit specialization + */ + targsi = ti.tiargs; + tierror = ti; // for error reporting + e1 = new DotIdExp(loc, se.e1, ti.name); + } + else + { + e1 = e1.semantic(sc); + } +} } } } @@ -259,6 +279,7 @@ istemp = 0; Lagain: //printf("Lagain: %s\n", toChars()); + //printf("test1 %s\n", toChars()); f = null; if (e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper) { @@ -266,7 +287,21 @@ } else { - UnaExp.semantic(sc); + if (e1.op == TOK.TOKdot) + { + auto die = cast(DotIdExp)e1; + e1 = die.semantic(sc, 1); + /* Look for e1 having been rewritten to expr.opDispatch!(string) + * We handle such earlier, so go back. + * Note that in the rewrite, we carefully did not run semantic() on e1 + */ + if (e1.op == TOK.TOKdotti && !e1.type) + { + goto Ldotti; + } + } + else + UnaExp.semantic(sc); /* Look for e1 being a lazy parameter */ @@ -393,7 +428,7 @@ } arrayExpressionSemantic(arguments, sc); - preFunctionArguments(loc, sc, arguments); + preFunctionParameters(loc, sc, arguments); if (e1.op == TOK.TOKdotvar && t1.ty == TY.Tfunction || e1.op == TOK.TOKdottd) @@ -450,6 +485,7 @@ checkDeprecated(sc, f); version (DMDV2) { checkPurity(sc, f); + checkSafety(sc, f); } accessCheck(loc, sc, ue.e1, f); if (!f.needThis()) @@ -563,6 +599,7 @@ checkDeprecated(sc, f); version (DMDV2) { checkPurity(sc, f); + checkSafety(sc, f); } e1 = new DotVarExp(e1.loc, e1, f); e1 = e1.semantic(sc); @@ -602,6 +639,7 @@ checkDeprecated(sc, f); version (DMDV2) { checkPurity(sc, f); + checkSafety(sc, f); } e1 = new DotVarExp(e1.loc, e1, f); e1 = e1.semantic(sc); @@ -669,6 +707,10 @@ { error("pure function '%s' cannot call impure delegate '%s'", sc.func.toChars(), e1.toChars()); } + if (sc.func && sc.func.isSafe() && tf.trust <= TRUST.TRUSTsystem) + { + error("safe function '%s' cannot call system delegate '%s'", sc.func.toChars(), e1.toChars()); + } goto Lcheckargs; } else if (t1.ty == TY.Tpointer && (cast(TypePointer)t1).next.ty == TY.Tfunction) @@ -679,6 +721,10 @@ { error("pure function '%s' cannot call impure function pointer '%s'", sc.func.toChars(), e1.toChars()); } + if (sc.func && sc.func.isSafe() && !(cast(TypeFunction)t1).trust <= TRUST.TRUSTsystem) + { + error("safe function '%s' cannot call system function pointer '%s'", sc.func.toChars(), e1.toChars()); + } e.type = t1; e1 = e; } @@ -708,8 +754,7 @@ else { error("function expected before (), not %s of type %s", e1.toChars(), e1.type.toChars()); - type = Type.terror; - return this; + return new ErrorExp(); } } else if (e1.op == TOK.TOKvar) @@ -726,6 +771,7 @@ checkDeprecated(sc, f); version (DMDV2) { checkPurity(sc, f); + checkSafety(sc, f); } if (f.needThis() && hasThis(sc)) @@ -754,7 +800,7 @@ if (!arguments) arguments = new Expressions(); - functionArguments(loc, sc, tf, arguments); + functionParameters(loc, sc, tf, arguments); if (!type) { diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/CastExp.d --- a/dmd/CastExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/CastExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -153,14 +153,18 @@ to = Type.terror; } - if (global.params.safe && !sc.module_.safe && !sc.intypeof) +//static if (true) { + if (sc.func && sc.func.isSafe() && !sc.intypeof) +//} else { +// if (global.params.safe && !sc.module_.safe && !sc.intypeof) +//} { // Disallow unsafe casts Type tob = to.toBasetype(); Type t1b = e1.type.toBasetype(); if (!t1b.isMutable() && tob.isMutable()) { // Cast not mutable to mutable Lunsafe: - error("cast from %s to %s not allowed in safe mode", e1.type.toChars(), to.toChars()); + error("cast from %s to %s not allowed in safe code", e1.type.toChars(), to.toChars()); } else if (t1b.isShared() && !tob.isShared()) // Cast away shared @@ -459,7 +463,7 @@ Expression.buildArrayIdent(buf, arguments); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { Type tb = type.toBasetype(); if (tb.ty == Tarray || tb.ty == Tsarray) diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/CatAssignExp.d --- a/dmd/CatAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/CatAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -7,6 +7,7 @@ import dmd.Scope; import dmd.InterState; import dmd.SliceExp; +import dmd.ErrorExp; import dmd.Identifier; import dmd.IRState; import dmd.TOK; @@ -56,10 +57,16 @@ e2.rvalue(); + Type tb1next = tb1.nextOf(); + if ((tb1.ty == Tarray) && (tb2.ty == Tarray || tb2.ty == Tsarray) && (e2.implicitConvTo(e1.type) || - tb2.nextOf().implicitConvTo(tb1.nextOf())) +//version(DMDV2) { + tb2.nextOf().implicitConvTo(tb1next) +//} + ) + ) { // Append array e2 = e2.castTo(sc, e1.type); @@ -67,19 +74,31 @@ e = this; } else if ((tb1.ty == Tarray) && - e2.implicitConvTo(tb1.nextOf()) + e2.implicitConvTo(tb1next) ) { // Append element - e2 = e2.castTo(sc, tb1.nextOf()); + e2 = e2.castTo(sc, tb1next); type = e1.type; e = this; } - else - { - error("cannot append type %s to type %s", tb2.toChars(), tb1.toChars()); - type = Type.tint32; - e = this; - } + else if (tb1.ty == Tarray && + (tb1next.ty == Tchar || tb1next.ty == Twchar) && + e2.implicitConvTo(Type.tdchar) + ) + { // Append dchar to char[] or wchar[] + e2 = e2.castTo(sc, Type.tdchar); + type = e1.type; + e = this; + + /* Do not allow appending wchar to char[] because if wchar happens + * to be a surrogate pair, nothing good can result. + */ + } + else + { + error("cannot append type %s to type %s", tb2.toChars(), tb1.toChars()); + e = new ErrorExp(); + } return e; } @@ -100,15 +119,29 @@ Type tb1 = e1.type.toBasetype(); Type tb2 = e2.type.toBasetype(); - if (tb1.ty == Tarray || tb2.ty == Tsarray) - { elem* e1; - elem* e2; - elem* ep; + if (tb1.ty == Tarray && tb2.ty == Tdchar && + (tb1.nextOf().ty == Tchar || tb1.nextOf().ty == Twchar)) + { // Append dchar to char[] or wchar[] - e1 = this.e1.toElem(irs); + auto e1 = this.e1.toElem(irs); e1 = el_una(OPaddr, TYnptr, e1); - e2 = this.e2.toElem(irs); + auto e2 = this.e2.toElem(irs); + + auto ep = el_params(e2, e1, null); + int rtl = (tb1.nextOf().ty == Tchar) + ? RTLSYM_ARRAYAPPENDCD + : RTLSYM_ARRAYAPPENDWD; + e = el_bin(OPcall, TYdarray, el_var(rtlsym[rtl]), ep); + el_setLoc(e,loc); + } + else if (tb1.ty == Tarray || tb2.ty == Tsarray) + { + auto e1 = this.e1.toElem(irs); + e1 = el_una(OPaddr, TYnptr, e1); + + auto e2 = this.e2.toElem(irs); + if (tybasic(e2.Ety) == TYstruct || tybasic(e2.Ety) == TYarray) { e2 = el_una(OPstrpar, TYstruct, e2); @@ -120,23 +153,13 @@ if ((tb2.ty == Tarray || tb2.ty == Tsarray) && tb1n.equals(tb2.nextOf().toBasetype())) { // Append array - static if (true) { - ep = el_params(e2, e1, this.e1.type.getTypeInfo(null).toElem(irs), null); + auto ep = el_params(e2, e1, this.e1.type.getTypeInfo(null).toElem(irs), null); e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDT]), ep); - } else { - ep = el_params(el_long(TYint, tb1n.size()), e2, e1, null); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPEND]), ep); - } } else { // Append element - static if (true) { - ep = el_params(e2, e1, this.e1.type.getTypeInfo(null).toElem(irs), null); + auto ep = el_params(e2, e1, this.e1.type.getTypeInfo(null).toElem(irs), null); e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDCT]), ep); - } else { - ep = el_params(e2, el_long(TYint, tb1n.size()), e1, null); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDC]), ep); - } } el_setLoc(e,loc); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/CatExp.d --- a/dmd/CatExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/CatExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -14,6 +14,7 @@ import dmd.MATCH; import dmd.ArrayLiteralExp; import dmd.StringExp; +import dmd.ErrorExp; import dmd.WANT; import dmd.Id; import dmd.GlobalExpressions; @@ -59,10 +60,13 @@ e1.type.print(); e2.type.print(); } + Type tb1next = tb1.nextOf(); + Type tb2next = tb2.nextOf(); + if ((tb1.ty == Tsarray || tb1.ty == Tarray) && - e2.type.implicitConvTo(tb1.nextOf()) >= MATCHconst) + e2.implicitConvTo(tb1next) >= MATCHconvert) { - type = tb1.nextOf().arrayOf(); + e2 = e2.implicitCastTo(sc, tb1next); if (tb2.ty == Tarray) { // Make e2 into [e2] @@ -72,9 +76,9 @@ return this; } else if ((tb2.ty == Tsarray || tb2.ty == Tarray) && - e1.type.implicitConvTo(tb2.nextOf()) >= MATCHconst) + e1.implicitConvTo(tb2next) >= MATCHconvert) { - type = tb2.nextOf().arrayOf(); + e1 = e1.implicitCastTo(sc, tb2next); if (tb1.ty == Tarray) { // Make e1 into [e1] @@ -86,12 +90,12 @@ if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && - (tb1.nextOf().mod || tb2.nextOf().mod) && - (tb1.nextOf().mod != tb2.nextOf().mod) + (tb1next.mod || tb2next.mod) && + (tb1next.mod != tb2next.mod) ) { - Type t1 = tb1.nextOf().mutableOf().constOf().arrayOf(); - Type t2 = tb2.nextOf().mutableOf().constOf().arrayOf(); + Type t1 = tb1next.mutableOf().constOf().arrayOf(); + Type t2 = tb2next.mutableOf().constOf().arrayOf(); if (e1.op == TOKstring && !(cast(StringExp)e1).committed) e1.type = t1; else @@ -108,8 +112,8 @@ Type tb = type.toBasetype(); if (tb.ty == Tsarray) type = tb.nextOf().arrayOf(); - if (type.ty == Tarray && tb1.nextOf() && tb2.nextOf() && - tb1.nextOf().mod != tb2.nextOf().mod) + if (type.ty == Tarray && tb1next && tb2next && + tb1next.mod != tb2next.mod) { type = type.nextOf().toHeadMutable().arrayOf(); } @@ -133,8 +137,7 @@ //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars()); error("Can only concatenate arrays, not (%s ~ %s)", e1.type.toChars(), e2.type.toChars()); - type = Type.tint32; - e = this; + return new ErrorExp(); } e.type = e.type.semantic(loc, sc); return e; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ClassDeclaration.d --- a/dmd/ClassDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ClassDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -10,7 +10,7 @@ import dmd.CtorDeclaration; import dmd.TypeIdentifier; import dmd.STC; -import dmd.Argument; +import dmd.Parameter; import dmd.TypeTuple; import dmd.TY; import dmd.LINK; @@ -25,6 +25,7 @@ import dmd.ArrayTypes; import dmd.BaseClass; import dmd.ClassInfoDeclaration; +import dmd.TypeInfoClassDeclaration; import dmd.Loc; import dmd.Identifier; import dmd.Dsymbol; @@ -63,7 +64,7 @@ import std.string; version (DMDV2) { - enum CLASSINFO_SIZE = (0x3C+16+4); // value of ClassInfo.size + enum CLASSINFO_SIZE = (0x3C+12+4); // value of ClassInfo.size } else { enum CLASSINFO_SIZE = (0x3C+12+4); // value of ClassInfo.size } @@ -87,6 +88,10 @@ static __gshared ClassDeclaration classinfo; ClassDeclaration baseClass; // null only if this is Object +version(DMDV1) { + CtorDeclaration *ctor; + CtorDeclaration *defaultCtor; // default constructor +} FuncDeclaration staticCtor; FuncDeclaration staticDtor; Array vtbl; // Array of FuncDeclaration's making up the vtbl[] @@ -102,12 +107,14 @@ BaseClasses vtblInterfaces; // array of base interfaces that have // their own vtbl[] - ClassInfoDeclaration vclassinfo; // the ClassInfo object for this ClassDeclaration + TypeInfoClassDeclaration vclassinfo; // the ClassInfo object for this ClassDeclaration bool com; // true if this is a COM class (meaning // it derives from IUnknown) bool isauto; // true if this is an auto class bool isabstract; // true if abstract class - +version(DMDV1) { + int isnested; // !=0 if is nested +} int inuse; // to prevent recursive attempts this(Loc loc, Identifier id, BaseClasses baseclasses) @@ -261,7 +268,8 @@ object = this; } - if (id is Id.ClassInfo) +// if (id is Id.ClassInfo) + if (id is Id.TypeInfo_Class) { if (classinfo) classinfo.error("%s", msg); @@ -377,10 +385,10 @@ TypeTuple tup = cast(TypeTuple)tb; enum PROT protection = b.protection; baseclasses.remove(i); - size_t dim = Argument.dim(tup.arguments); + size_t dim = Parameter.dim(tup.arguments); for (size_t j = 0; j < dim; j++) { - Argument arg = Argument.getNth(tup.arguments, j); + auto arg = Parameter.getNth(tup.arguments, j); b = new BaseClass(arg.type, protection); baseclasses.insert(i + j, b); } @@ -1012,6 +1020,13 @@ } } +version(DMDV1) +{ + int isNested() + { + assert(false); + } +} bool isCOMclass() { return com; @@ -1278,7 +1293,7 @@ // Put out the TypeInfo type.getTypeInfo(null); - type.vtinfo.toObjFile(multiobj); + //type.vtinfo.toObjFile(multiobj); ////////////////////////////////////////////// @@ -1302,7 +1317,7 @@ OffsetTypeInfo[] offTi; void *defaultConstructor; const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function - TypeInfo typeinfo; + //TypeInfo typeinfo; } */ dt_t* dt = null; @@ -1415,7 +1430,7 @@ dtdword(&dt, 0); // module getMembers() function } - dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr); // typeinfo + //dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr); // typeinfo //dtdword(&dt, 0); ////////////////////////////////////////////// @@ -1429,10 +1444,11 @@ ClassDeclaration id = b.base; /* The layout is: - * { + * struct Interface + * { * ClassInfo *interface; * void *[] vtbl; - * unsigned offset; + * ptrdiff_t offset; * } */ @@ -1473,8 +1489,6 @@ assert(id.vtbl.dim == b.vtbl.dim); for (; j < id.vtbl.dim; j++) { - FuncDeclaration fd; - assert(j < b.vtbl.dim); static if (false) { Object o = cast(Object)b.vtbl.data[j]; @@ -1486,7 +1500,7 @@ printf("s.kind() = '%s'\n", s.kind()); } } - fd = cast(FuncDeclaration)b.vtbl.data[j]; + auto fd = cast(FuncDeclaration)b.vtbl.data[j]; if (fd) dtxoff(&dt, fd.toThunkSymbol(b.offset), 0, TYnptr); else @@ -1635,7 +1649,7 @@ { TypeFunction tf = cast(TypeFunction)fd.type; if (tf.ty == Tfunction) - warning("%s%s is hidden by %s\n", fd.toPrettyChars(), Argument.argsTypesToChars(tf.parameters, tf.varargs), toChars()); + warning("%s%s is hidden by %s\n", fd.toPrettyChars(), Parameter.argsTypesToChars(tf.parameters, tf.varargs), toChars()); else warning("%s is hidden by %s\n", fd.toPrettyChars(), toChars()); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ComExp.d --- a/dmd/ComExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ComExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -74,7 +74,7 @@ buf.writestring("Com"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { Expression ex1 = e1.buildArrayLoop(fparams); Expression e = new ComExp(Loc(0), ex1); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/CondExp.d --- a/dmd/CondExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/CondExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -210,8 +210,10 @@ override Expression modifiableLvalue(Scope sc, Expression e) { - error("conditional expression %s is not a modifiable lvalue", toChars()); - return this; + //error("conditional expression %s is not a modifiable lvalue", toChars()); + e1 = e1.modifiableLvalue(sc, e1); + e2 = e2.modifiableLvalue(sc, e1); + return toLvalue(sc, this); } override Expression checkToBoolean() diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/CtorDeclaration.d --- a/dmd/CtorDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/CtorDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -19,15 +19,15 @@ import dmd.Statement; import dmd.ReturnStatement; import dmd.CompoundStatement; -import dmd.Argument; +import dmd.Parameter; import dmd.Id; class CtorDeclaration : FuncDeclaration { - Arguments arguments; + Parameters arguments; int varargs; - this(Loc loc, Loc endloc, Arguments arguments, int varargs) + this(Loc loc, Loc endloc, Parameters arguments, int varargs) { super(loc, endloc, Id.ctor, STC.STCundefined, null); @@ -46,7 +46,7 @@ f.fbody = fbody ? fbody.syntaxCopy() : null; assert(!fthrows); // deprecated - f.arguments = Argument.arraySyntaxCopy(arguments); + f.arguments = Parameter.arraySyntaxCopy(arguments); return f; } @@ -103,7 +103,7 @@ sc.pop(); // See if it's the default constructor - if (ad && varargs == 0 && Argument.dim(arguments) == 0) + if (ad && varargs == 0 && Parameter.dim(arguments) == 0) { if (ad.isStructDeclaration()) error("default constructor not allowed for structs"); else diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/DeclarationExp.d --- a/dmd/DeclarationExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/DeclarationExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -266,6 +266,7 @@ declaration.isClassDeclaration() || declaration.isFuncDeclaration() || declaration.isTypedefDeclaration() || + declaration.isAttribDeclaration() || declaration.isTemplateMixin() ) return COST_MAX; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/DefaultInitExp.d --- a/dmd/DefaultInitExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/DefaultInitExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -19,8 +19,6 @@ this.subop = subop; } - abstract Expression resolve(Loc loc, Scope sc); - override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { buf.writestring(Token.toChars(subop)); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/DeleteDeclaration.d --- a/dmd/DeleteDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/DeleteDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -10,7 +10,7 @@ import dmd.HdrGenState; import dmd.STC; import dmd.Id; -import dmd.Argument; +import dmd.Parameter; import dmd.ClassDeclaration; import dmd.TypeFunction; import dmd.Type; @@ -19,9 +19,9 @@ class DeleteDeclaration : FuncDeclaration { - Arguments arguments; + Parameters arguments; - this(Loc loc, Loc endloc, Arguments arguments) + this(Loc loc, Loc endloc, Parameters arguments) { super(loc, endloc, Id.classDelete, STCstatic, null); this.arguments = arguments; @@ -35,7 +35,7 @@ FuncDeclaration.syntaxCopy(f); - f.arguments = Argument.arraySyntaxCopy(arguments); + f.arguments = Parameter.arraySyntaxCopy(arguments); return f; } @@ -60,13 +60,13 @@ // Check that there is only one argument of type void* TypeFunction tf = cast(TypeFunction)type; - if (Argument.dim(tf.parameters) != 1) + if (Parameter.dim(tf.parameters) != 1) { error("one argument of type void* expected"); } else { - Argument a = Argument.getNth(tf.parameters, 0); + auto a = Parameter.getNth(tf.parameters, 0); if (!a.type.equals(Type.tvoid.pointerTo())) error("one argument of type void* expected, not %s", a.type.toChars()); } @@ -77,7 +77,7 @@ override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { buf.writestring("delete"); - Argument.argsToCBuffer(buf, hgs, arguments, 0); + Parameter.argsToCBuffer(buf, hgs, arguments, 0); bodyToCBuffer(buf, hgs); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/DivAssignExp.d --- a/dmd/DivAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/DivAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -17,6 +17,7 @@ import dmd.CommaExp; import dmd.RealExp; import dmd.AssignExp; +import dmd.ArrayLengthExp; import dmd.backend.elem; import dmd.backend.OPER; @@ -42,6 +43,15 @@ if (e) return e; +version(DMDV2) { + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } +} + if (e1.op == TOKslice) { // T[] -= ... typeCombine(sc); @@ -104,7 +114,7 @@ AssignExp_buildArrayIdent(buf, arguments, "Div"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return AssignExp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/DivExp.d --- a/dmd/DivExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/DivExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -116,7 +116,7 @@ Exp_buildArrayIdent(buf, arguments, "Div"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return Exp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/DotIdExp.d --- a/dmd/DotIdExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/DotIdExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -56,6 +56,12 @@ override Expression semantic(Scope sc) { + // Indicate we didn't come from CallExp::semantic() + return semantic(sc, 0); + } + + Expression semantic(Scope sc, int flag) + { Expression e; Expression eleft; Expression eright; @@ -187,7 +193,7 @@ * The check for 'is sds our current module' is because * the current module should have access to its own imports. */ - Dsymbol s = ie.sds.search(loc, ident, + Dsymbol s = ie.sds.search(loc, ident, //0); (ie.sds.isModule() && ie.sds != sc.module_) ? 1 : 0); if (s) { @@ -355,7 +361,8 @@ else { e = e1.type.dotExp(sc, e1, ident); - e = e.semantic(sc); + if (!(flag && e.op == TOK.TOKdotti)) // let CallExp::semantic() handle this + e = e.semantic(sc); return e; } } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/DotTemplateInstanceExp.d --- a/dmd/DotTemplateInstanceExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/DotTemplateInstanceExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -1,6 +1,7 @@ module dmd.DotTemplateInstanceExp; import dmd.common; +import dmd.ArrayTypes; import dmd.Expression; import dmd.UnaExp; import dmd.OutBuffer; @@ -23,6 +24,10 @@ import dmd.DotVarExp; import dmd.TemplateDeclaration; import dmd.Dsymbol; +import dmd.DotTemplateExp; +import dmd.DotIdExp; +import dmd.TemplateExp; +import dmd.DsymbolExp; import dmd.expression.Util; @@ -33,141 +38,106 @@ { TemplateInstance ti; - this(Loc loc, Expression e, TemplateInstance ti) + this(Loc loc, Expression e, Identifier name, Objects tiargs) { super(loc, TOK.TOKdotti, DotTemplateInstanceExp.sizeof, e); //printf("DotTemplateInstanceExp()\n"); - this.ti = ti; + this.ti = new TemplateInstance(loc, name); + this.ti.tiargs = tiargs; } override Expression syntaxCopy() { - DotTemplateInstanceExp de = new DotTemplateInstanceExp(loc, e1.syntaxCopy(), cast(TemplateInstance)ti.syntaxCopy(null)); + DotTemplateInstanceExp de = new DotTemplateInstanceExp(loc, e1.syntaxCopy(), ti.name, TemplateInstance.arraySyntaxCopy(ti.tiargs)); return de; } - override Expression semantic(Scope sc) + TemplateDeclaration getTempdecl(Scope sc) { - Dsymbol s; - Dsymbol s2; - TemplateDeclaration td; - Expression e; - Identifier id; - Type t1; - Expression eleft = null; - Expression eright; - - version (LOGSEMANTIC) { - printf("DotTemplateInstanceExp.semantic('%s')\n", toChars()); - } - //e1.print(); - //print(); - e1 = e1.semantic(sc); - t1 = e1.type; - if (t1) - t1 = t1.toBasetype(); - //t1.print(); - - /* Extract the following from e1: - * s: the symbol which ti should be a member of - * eleft: if not null, it is the 'this' pointer for ti - */ - - if (e1.op == TOKdotexp) - { - DotExp de = cast(DotExp)e1; - eleft = de.e1; - eright = de.e2; - } - else - { - eleft = null; - eright = e1; - } - if (eright.op == TOKimport) +version(LOGSEMANTIC) { + printf("DotTemplateInstanceExp::getTempdecl('%s')\n", toChars()); +} + if (!ti.tempdecl) { - s = (cast(ScopeExp)eright).sds; - } - else if (e1.op == TOKtype) - { - s = t1.isClassHandle(); - if (!s) + Expression e = new DotIdExp(loc, e1, ti.name); + e = e.semantic(sc); + if (e.op == TOKdottd) { - if (t1.ty == Tstruct) - s = (cast(TypeStruct)t1).sym; - else - goto L1; + auto dte = cast(DotTemplateExp)e; + ti.tempdecl = dte.td; + } + else if (e.op == TOKimport) + { + auto se = cast(ScopeExp)e; + ti.tempdecl = se.sds.isTemplateDeclaration(); } } - else if (t1 && (t1.ty == Tstruct || t1.ty == Tclass)) - { - s = t1.toDsymbol(sc); - eleft = e1; - } - else if (t1 && t1.ty == Tpointer) - { - t1 = (cast(TypePointer)t1).next.toBasetype(); - if (t1.ty != Tstruct) - goto L1; - s = t1.toDsymbol(sc); - eleft = e1; - } - else - { - L1: - error("template %s is not a member of %s", ti.toChars(), e1.toChars()); - goto Lerr; - } - - assert(s); - id = ti.name; - s2 = s.search(loc, id, 0); - if (!s2) + return ti.tempdecl; + } + + override Expression semantic(Scope sc) + { +version (LOGSEMANTIC) { + printf("DotTemplateInstanceExp.semantic('%s')\n", toChars()); +} + Expression eleft; + Expression e = new DotIdExp(loc, e1, ti.name); +L1: + e = e.semantic(sc); + if (e.op == TOKdottd) { - if (!s.ident) - error("template identifier %s is not a member of undefined %s", id.toChars(), s.kind()); - else - error("template identifier %s is not a member of %s %s", id.toChars(), s.kind(), s.ident.toChars()); - goto Lerr; - } - s = s2; - s.semantic(sc); - s = s.toAlias(); - td = s.isTemplateDeclaration(); - if (!td) - { - error("%s is not a template", id.toChars()); - goto Lerr; - } - if (global.errors) - goto Lerr; - - ti.tempdecl = td; - - if (eleft) - { - Declaration v; - + DotTemplateExp dte = cast(DotTemplateExp )e; + TemplateDeclaration td = dte.td; + eleft = dte.e1; + ti.tempdecl = td; ti.semantic(sc); - s = ti.inst.toAlias(); - v = s.isDeclaration(); + Dsymbol s = ti.inst.toAlias(); + Declaration v = s.isDeclaration(); if (v) - { + { e = new DotVarExp(loc, eleft, v); e = e.semantic(sc); return e; } - } - - e = new ScopeExp(loc, ti); - if (eleft) - { + e = new ScopeExp(loc, ti); e = new DotExp(loc, eleft, e); + e = e.semantic(sc); + return e; } - e = e.semantic(sc); - return e; + else if (e.op == TOKimport) + { + auto se = cast(ScopeExp)e; + TemplateDeclaration td = se.sds.isTemplateDeclaration(); + if (!td) + { + error("%s is not a template", e.toChars()); + return new ErrorExp(); + } + ti.tempdecl = td; + e = new ScopeExp(loc, ti); + e = e.semantic(sc); + return e; + } + else if (e.op == TOKdotexp) + { + DotExp de = cast(DotExp )e; - Lerr: + if (de.e2.op == TOKimport) + { + // This should *really* be moved to ScopeExp::semantic() + ScopeExp se = cast(ScopeExp )de.e2; + de.e2 = new DsymbolExp(loc, se.sds); + de.e2 = de.e2.semantic(sc); + } + + if (de.e2.op == TOKtemplate) + { + auto te = cast(TemplateExp) de.e2; + e = new DotTemplateExp(loc,de.e1,te.td); + } + goto L1; + } + error("%s isn't a template", e.toChars()); return new ErrorExp(); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/DsymbolExp.d --- a/dmd/DsymbolExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/DsymbolExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -34,6 +34,7 @@ import dmd.HdrGenState; import dmd.Dsymbol; import dmd.TOK; +import dmd.ErrorExp; class DsymbolExp : Expression { @@ -150,6 +151,7 @@ if (!f.type.deco) { error("forward reference to %s", toChars()); + return new ErrorExp(); } return new VarExp(loc, f, hasOverloads); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/EqualExp.d --- a/dmd/EqualExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/EqualExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -181,21 +181,13 @@ //printf("EqualExp::toElem()\n"); if (t1.ty == Tstruct) { // Do bit compare of struct's - elem* es1; - elem* es2; - elem* ecount; - es1 = e1.toElem(irs); - es2 = e2.toElem(irs); - static if (true) { + auto es1 = e1.toElem(irs); + auto es2 = e2.toElem(irs); es1 = addressElem(es1, t1); es2 = addressElem(es2, t2); - } else { - es1 = el_una(OPaddr, TYnptr, es1); - es2 = el_una(OPaddr, TYnptr, es2); - } e = el_param(es1, es2); - ecount = el_long(TYint, t1.size()); + auto ecount = el_long(TYint, t1.size()); e = el_bin(OPmemcmp, TYint, e, ecount); e = el_bin(eop, TYint, e, el_long(TYint, 0)); el_setLoc(e,loc); @@ -214,24 +206,20 @@ else if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray)) { - elem* ea1; - elem* ea2; - elem* ep; Type telement = t1.nextOf().toBasetype(); - int rtlfunc; - ea1 = e1.toElem(irs); + auto ea1 = e1.toElem(irs); ea1 = array_toDarray(t1, ea1); - ea2 = e2.toElem(irs); + auto ea2 = e2.toElem(irs); ea2 = array_toDarray(t2, ea2); version (DMDV2) { - ep = el_params(telement.arrayOf().getInternalTypeInfo(null).toElem(irs), + auto ep = el_params(telement.arrayOf().getInternalTypeInfo(null).toElem(irs), ea2, ea1, null); - rtlfunc = RTLSYM_ARRAYEQ2; + int rtlfunc = RTLSYM_ARRAYEQ2; } else { - ep = el_params(telement.getInternalTypeInfo(null).toElem(irs), ea2, ea1, null); - rtlfunc = RTLSYM_ARRAYEQ; + auto ep = el_params(telement.getInternalTypeInfo(null).toElem(irs), ea2, ea1, null); + int rtlfunc = RTLSYM_ARRAYEQ; } e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep); if (op == TOKnotequal) diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Expression.d --- a/dmd/Expression.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/Expression.d Thu Sep 09 22:51:44 2010 +0100 @@ -3,7 +3,7 @@ import dmd.common; import dmd.Loc; import dmd.TOK; -import dmd.Argument; +import dmd.Parameter; import dmd.IdentifierExp; import dmd.Type; import dmd.WANT; @@ -705,12 +705,25 @@ static if (true) { if (sc.func) { + /* Given: + * void f() + * { pure void g() + * { + * void h() + * { + * void i() { } + * } + * } + * } + * g() can call h() but not f() + * i() can call h() and g() but not f() + */ FuncDeclaration outerfunc = sc.func; while (outerfunc.toParent2() && outerfunc.toParent2().isFuncDeclaration()) { outerfunc = outerfunc.toParent2().isFuncDeclaration(); } - if (outerfunc.isPure() && !sc.intypeof && (!f.isNested() && !f.isPure())) + if (outerfunc.isPure() && !sc.intypeof && (!f.isNested() && !f.isPure())) error("pure function '%s' cannot call impure function '%s'\n", sc.func.toChars(), f.toChars()); } @@ -720,6 +733,14 @@ sc.func.toChars(), .toChars()); } } + + void checkSafety(Scope sc, FuncDeclaration f) + { + if (sc.func && sc.func.isSafe() && !sc.intypeof && + !f.isSafe() && !f.isTrusted()) + error("safe function '%s' cannot call system function '%s'\n", + sc.func.toChars(), f.toChars()); + } /***************************** * Check that expression can be tested for true or false. @@ -932,6 +953,15 @@ } } + /**************************************** + * Resolve __LINE__ and __FILE__ to loc. + */ + + Expression resolveLoc(Loc loc, Scope sc) + { + return this; + } + int inlineCost(InlineCostState* ics) { return 1; @@ -987,10 +1017,10 @@ arguments.shift(this); } - Expression buildArrayLoop(Arguments fparams) + Expression buildArrayLoop(Parameters fparams) { Identifier id = Identifier.generateId("c", fparams.dim); - auto param = new Argument(STC.STCundefined, type, id, null); + auto param = new Parameter(STC.STCundefined, type, id, null); fparams.shift(param); Expression e = new IdentifierExp(Loc(0), id); return e; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/FileInitExp.d --- a/dmd/FileInitExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/FileInitExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -23,7 +23,7 @@ return this; } - override Expression resolve(Loc loc, Scope sc) + override Expression resolveLoc(Loc loc, Scope sc) { //printf("FileInitExp::resolve() %.*s\n", toChars()); string s = loc.filename ? loc.filename : sc.module_.ident.toChars(); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ForeachRangeStatement.d --- a/dmd/ForeachRangeStatement.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ForeachRangeStatement.d Thu Sep 09 22:51:44 2010 +0100 @@ -4,7 +4,7 @@ import dmd.Statement; import dmd.TOK; import dmd.Token; -import dmd.Argument; +import dmd.Parameter; import dmd.Expression; import dmd.Statement; import dmd.VarDeclaration; @@ -37,14 +37,14 @@ class ForeachRangeStatement : Statement { TOK op; // TOK.TOKforeach or TOK.TOKforeach_reverse - Argument arg; // loop index variable + Parameter arg; // loop index variable Expression lwr; Expression upr; Statement body_; VarDeclaration key = null; - this(Loc loc, TOK op, Argument arg, Expression lwr, Expression upr, Statement body_) + this(Loc loc, TOK op, Parameter arg, Expression lwr, Expression upr, Statement body_) { super(loc); this.op = op; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ForeachStatement.d --- a/dmd/ForeachStatement.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ForeachStatement.d Thu Sep 09 22:51:44 2010 +0100 @@ -64,7 +64,7 @@ import dmd.AddAssignExp; import dmd.CmpExp; import dmd.Id; -import dmd.Argument; +import dmd.Parameter; import dmd.STC; import dmd.expression.Util; @@ -74,7 +74,7 @@ class ForeachStatement : Statement { TOK op; // TOKforeach or TOKforeach_reverse - Arguments arguments; // array of Argument*'s + Parameters arguments; // array of Argument*'s Expression aggr; Statement body_; @@ -86,7 +86,7 @@ Array cases; // put breaks, continues, gotos and returns here Array gotos; // forward referenced goto's go here - this(Loc loc, TOK op, Arguments arguments, Expression aggr, Statement body_) + this(Loc loc, TOK op, Parameters arguments, Expression aggr, Statement body_) { super(loc); @@ -101,9 +101,9 @@ override Statement syntaxCopy() { - Arguments args = Argument.arraySyntaxCopy(arguments); + auto args = Parameter.arraySyntaxCopy(arguments); Expression exp = aggr.syntaxCopy(); - ForeachStatement s = new ForeachStatement(loc, op, args, exp, + auto s = new ForeachStatement(loc, op, args, exp, body_ ? body_.syntaxCopy() : null); return s; } @@ -153,7 +153,7 @@ return s; } - TypeTuple tuple = cast(TypeTuple)tab; + auto tuple = cast(TypeTuple)tab; Statements statements = new Statements(); //printf("aggr: op = %d, %s\n", aggr.op, aggr.toChars()); size_t n; @@ -165,7 +165,7 @@ } else if (aggr.op == TOK.TOKtype) // type tuple { - n = Argument.dim(tuple.arguments); + n = Parameter.dim(tuple.arguments); } else assert(0); @@ -178,7 +178,7 @@ if (te) e = te.exps[k]; else - t = Argument.getNth(tuple.arguments, k).type; + t = Parameter.getNth(tuple.arguments, k).type; auto arg = arguments[0]; auto st = new Statements(); @@ -274,7 +274,7 @@ tn = tab.nextOf().toBasetype(); if (tn.ty == TY.Tchar || tn.ty == TY.Twchar || tn.ty == TY.Tdchar) { - Argument arg; + Parameter arg; int i = (dim == 1) ? 0 : 1; // index of value arg = arguments[i]; @@ -532,11 +532,11 @@ Lapply: { FuncDeclaration fdapply; - Arguments args; + Parameters args; Expression ec; Expression e; FuncLiteralDeclaration fld; - Argument a; + Parameter a; Type t; Expression flde; Identifier id; @@ -553,7 +553,7 @@ // Need a variable to hold value from any return statements in body. if (!sc.func.vresult && tret && tret != Type.tvoid) { - VarDeclaration v = new VarDeclaration(loc, tret, Id.result, null); + auto v = new VarDeclaration(loc, tret, Id.result, null); v.noauto = true; v.semantic(sc); if (!sc.insert(v)) @@ -566,7 +566,7 @@ /* Turn body into the function literal: * int delegate(ref T arg) { body } */ - args = new Arguments(); + args = new Parameters(); for (size_t i = 0; i < dim; i++) { auto arg = arguments[i]; @@ -587,7 +587,7 @@ s = new DeclarationStatement(Loc(0), v); body_ = new CompoundStatement(loc, s, body_); } - a = new Argument(STC.STCref, arg.type, id, null); + a = new Parameter(STC.STCref, arg.type, id, null); args.push(a); } t = new TypeFunction(args, Type.tint32, 0, LINK.LINKd); @@ -711,11 +711,9 @@ /* Call: * aggr.apply!(fld)() */ - TemplateInstance ti = new TemplateInstance(loc, idapply); Objects tiargs = new Objects(); tiargs.push(cast(void*)fld); - ti.tiargs = tiargs; - ec = new DotTemplateInstanceExp(loc, aggr, ti); + ec = new DotTemplateInstanceExp(loc, aggr, idapply, tiargs); } else { diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/FuncDeclaration.d --- a/dmd/FuncDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/FuncDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -54,7 +54,7 @@ import dmd.PtrExp; import dmd.DeclarationExp; import dmd.InlineDoState; -import dmd.Argument; +import dmd.Parameter; import dmd.StructDeclaration; import dmd.ClassDeclaration; import dmd.InterfaceDeclaration; @@ -73,6 +73,7 @@ import dmd.TypeFunction; import dmd.Expression; import dmd.STC; +import dmd.TRUST; import dmd.Dsymbol; import dmd.Scope; import dmd.OutBuffer; @@ -308,7 +309,7 @@ originalType = type; if (!type.deco) { - /* Apply const and invariant storage class + /* Apply const, immutable and shared storage class * to the function type */ type = type.semantic(loc, sc); @@ -360,7 +361,7 @@ return; } f = cast(TypeFunction)type; - size_t nparams = Argument.dim(f.parameters); + size_t nparams = Parameter.dim(f.parameters); linkage = sc.linkage; // if (!parent) @@ -733,7 +734,7 @@ case 1: { - Argument arg0 = Argument.getNth(f.parameters, 0); + auto arg0 = Parameter.getNth(f.parameters, 0); if (arg0.type.ty != TY.Tarray || arg0.type.nextOf().ty != TY.Tarray || arg0.type.nextOf().nextOf().ty != TY.Tchar || @@ -767,7 +768,7 @@ } else { - Argument arg0 = Argument.getNth(f.parameters, 0); + auto arg0 = Parameter.getNth(f.parameters, 0); Type t0 = arg0.type.toBasetype(); Type tb = sd ? sd.type : cd.type; if (arg0.type.implicitConvTo(tb) || @@ -776,7 +777,7 @@ { if (nparams == 1) goto Lassignerr; - Argument arg1 = Argument.getNth(f.parameters, 1); + auto arg1 = Parameter.getNth(f.parameters, 1); if (arg1.defaultArg) goto Lassignerr; } @@ -817,11 +818,11 @@ outId = Id.result; // provide a default Loc loc = fensure.loc; - Arguments arguments = new Arguments(); - Argument a = null; + auto arguments = new Parameters(); + Parameter a = null; if (outId) { - a = new Argument(STCref, f.nextOf(), outId, null); + a = new Parameter(STCref, f.nextOf(), outId, null); arguments.push(a); } TypeFunction tf = new TypeFunction(arguments, Type.tvoid, 0, LINKd); @@ -923,8 +924,10 @@ sc2.sw = null; sc2.fes = fes; sc2.linkage = LINK.LINKd; - sc2.stc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCfinal | STC.STCtls | STC.STCgshared | STC.STCref); - sc2.protection = PROT.PROTpublic; + sc2.stc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCabstract | STC.STCdeprecated | + STC.STC_TYPECTOR | STC.STCfinal | STC.STCtls | STC.STCgshared | STC.STCref | + STCproperty | STCsafe | STCtrusted | STCsystem); + sc2.protection = PROT.PROTpublic; sc2.explicitProtection = 0; sc2.structalign = 8; sc2.incontract = 0; @@ -1060,10 +1063,11 @@ //printf("[%d] arg.type.ty = %d %s\n", i, arg.type.ty, arg.type.toChars()); if (arg.type.ty == TY.Ttuple) { auto t = cast(TypeTuple)arg.type; - size_t dim = Argument.dim(t.arguments); + size_t dim = Parameter.dim(t.arguments); for (size_t j = 0; j < dim; j++) - { Argument narg = Argument.getNth(t.arguments, j); - narg.storageClass = arg.storageClass; + { + auto narg = Parameter.getNth(t.arguments, j); + narg.storageClass = arg.storageClass; } } } @@ -1072,7 +1076,7 @@ /* Declare all the function parameters as variables * and install them in parameters[] */ - size_t nparams = Argument.dim(f.parameters); + size_t nparams = Parameter.dim(f.parameters); if (nparams) { /* parameters[] has all the tuples removed, as the back end * doesn't know about tuples @@ -1081,7 +1085,7 @@ parameters.reserve(nparams); for (size_t i = 0; i < nparams; i++) { - Argument arg = Argument.getNth(f.parameters, i); + auto arg = Parameter.getNth(f.parameters, i); Identifier id = arg.ident; if (!id) { @@ -1119,11 +1123,11 @@ continue; // never used, so ignore if (arg.type.ty == TY.Ttuple) { auto t = cast(TypeTuple)arg.type; - size_t dim = Argument.dim(t.arguments); + size_t dim = Parameter.dim(t.arguments); Objects exps = new Objects(); exps.setDim(dim); for (size_t j = 0; j < dim; j++) - { Argument narg = Argument.getNth(t.arguments, j); + { auto narg = Parameter.getNth(t.arguments, j); assert(narg.ident); VarDeclaration v = sc2.search(Loc(0), narg.ident, null).isVarDeclaration(); assert(v); @@ -1190,15 +1194,16 @@ if (outId) { // Declare result variable - VarDeclaration v; Loc loc = this.loc; if (fensure) loc = fensure.loc; - v = new VarDeclaration(loc, type.nextOf(), outId, null); + auto v = new VarDeclaration(loc, type.nextOf(), outId, null); v.noauto = true; version (DMDV2) { + if (!isVirtual()) + v.storage_class |= STC.STCconst; if (f.isref) { v.storage_class |= STC.STCref | STC.STCforeach; @@ -1897,7 +1902,7 @@ //printf("tf = %s, args = %s\n", tf.deco, ((Expression *)arguments.data[0]).type.deco); error(loc, "%s%s is not callable using argument types %s", - Argument.argsTypesToChars(tf.parameters, tf.varargs), + Parameter.argsTypesToChars(tf.parameters, tf.varargs), buf2.toChars(), buf.toChars()); return m.anyf; // as long as it's not a FuncAliasDeclaration @@ -1910,8 +1915,8 @@ error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s", buf.toChars(), - m.lastf.toPrettyChars(), Argument.argsTypesToChars(t1.parameters, t1.varargs), - m.nextf.toPrettyChars(), Argument.argsTypesToChars(t2.parameters, t2.varargs)); + m.lastf.toPrettyChars(), Parameter.argsTypesToChars(t1.parameters, t1.varargs), + m.nextf.toPrettyChars(), Parameter.argsTypesToChars(t2.parameters, t2.varargs)); } else { error(loc, "overloads %s and %s both match argument list for %s", m.lastf.type.toChars(), @@ -1943,8 +1948,8 @@ TypeFunction tf = cast(TypeFunction)type; TypeFunction tg = cast(TypeFunction)g.type; - size_t nfparams = Argument.dim(tf.parameters); - size_t ngparams = Argument.dim(tg.parameters); + size_t nfparams = Parameter.dim(tf.parameters); + size_t ngparams = Parameter.dim(tg.parameters); MATCH match = MATCHexact; /* If both functions have a 'this' pointer, and the mods are not @@ -1967,7 +1972,7 @@ args.setDim(nfparams); for (int u = 0; u < nfparams; u++) { - Argument p = Argument.getNth(tf.parameters, u); + auto p = Parameter.getNth(tf.parameters, u); Expression e; if (p.storageClass & (STCref | STCout)) { @@ -2252,6 +2257,18 @@ return (cast(TypeFunction)this.type).ispure; } + int isSafe() + { + assert(type.ty == TY.Tfunction); + return (cast(TypeFunction)this.type).trust == TRUST.TRUSTsafe; + } + + int isTrusted() + { + assert(type.ty == TY.Tfunction); + return (cast(TypeFunction)this.type).trust == TRUST.TRUSTtrusted; + } + bool isNested() { //if (!toParent()) @@ -2392,10 +2409,10 @@ // Ensure there are no lazy parameters if (tf.parameters) { - size_t dim = Argument.dim(tf.parameters); + size_t dim = Parameter.dim(tf.parameters); for (size_t i = 0; i < dim; i++) { - Argument arg = Argument.getNth(tf.parameters, i); + auto arg = Parameter.getNth(tf.parameters, i); if (arg.storageClass & STClazy) { cantInterpret = 1; @@ -2433,7 +2450,7 @@ for (size_t i = 0; i < dim; i++) { Expression earg = arguments[i]; - Argument arg = Argument.getNth(tf.parameters, i); + auto arg = Parameter.getNth(tf.parameters, i); if (arg.storageClass & (STCout | STCref)) { @@ -2462,7 +2479,7 @@ for (size_t i = 0; i < dim; i++) { auto earg = eargs[i]; - Argument arg = Argument.getNth(tf.parameters, i); + auto arg = Parameter.getNth(tf.parameters, i); auto v = cast(VarDeclaration)parameters[i]; vsave[i] = v.value; version (LOG) { diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Global.d --- a/dmd/Global.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/Global.d Thu Sep 09 22:51:44 2010 +0100 @@ -39,7 +39,7 @@ string[] path; // Array of char*'s which form the import lookup path string[] filePath; // Array of char*'s which form the file import lookup path int structalign = 8; - string version_ = "v2.036"; + string version_ = "v2.037"; Param params; uint errors; // number of errors reported so far diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/IRState.d --- a/dmd/IRState.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/IRState.d Thu Sep 09 22:51:44 2010 +0100 @@ -9,6 +9,10 @@ import dmd.FuncDeclaration; import dmd.Global; import dmd.Loc; +import dmd.TRUST; +import dmd.TY; +import dmd.TypeFunction; +import dmd.Type; import dmd.backend.Symbol; import dmd.backend.Blockx; @@ -124,6 +128,28 @@ } return cast(FuncDeclaration)(bc.symbol); } + + /********************** + * Return !=0 if do array bounds checking + */ + int arrayBoundsCheck() + { + int result = global.params.useArrayBounds; + + if (result == 1) + { + // For safe functions only + result = 0; + FuncDeclaration fd = getFunc(); + if (fd) + { + Type t = fd.type; + if (t.ty == TY.Tfunction && (cast(TypeFunction)t).trust == TRUST.TRUSTsafe) + result = 1; + } + } + return result; + } } /********************************************* diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Id.d --- a/dmd/Id.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/Id.d Thu Sep 09 22:51:44 2010 +0100 @@ -79,7 +79,6 @@ ID( "coverage", "__coverage" ), ID( "__vptr" ), ID( "__monitor" ), - ID( "system" ), ID( "TypeInfo" ), ID( "TypeInfo_Class" ), @@ -146,6 +145,9 @@ ID( "idup" ), ID( "property" ), + ID( "safe" ), + ID( "trusted" ), + ID( "system" ), // For inline assembler ID( "___out", "out" ), @@ -211,8 +213,12 @@ ID( "opIn_r" ), ID( "opStar" ), ID( "opDot" ), + ID( "opDispatch" ), ID( "opImplicitCast" ), - + ID( "pow", "opPow" ), + ID( "pow_r", "opPow_r" ), + //ID( "powass", "opPowAssign" ), + ID( "classNew", "new" ), ID( "classDelete", "delete" ), @@ -272,6 +278,7 @@ ID( "cos" ), ID( "tan" ), ID( "_sqrt", "sqrt" ), + ID( "_pow", "pow" ), ID( "fabs" ), // Traits diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/IfStatement.d --- a/dmd/IfStatement.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/IfStatement.d Thu Sep 09 22:51:44 2010 +0100 @@ -2,7 +2,7 @@ import dmd.common; import dmd.Statement; -import dmd.Argument; +import dmd.Parameter; import dmd.Loc; import dmd.Expression; import dmd.VarDeclaration; @@ -32,14 +32,14 @@ class IfStatement : Statement { - Argument arg; + Parameter arg; Expression condition; Statement ifbody; Statement elsebody; VarDeclaration match; // for MatchExpression results - this(Loc loc, Argument arg, Expression condition, Statement ifbody, Statement elsebody) + this(Loc loc, Parameter arg, Expression condition, Statement ifbody, Statement elsebody) { super(loc); this.arg = arg; @@ -58,7 +58,7 @@ if (elsebody) e = elsebody.syntaxCopy(); - Argument a = arg ? arg.syntaxCopy() : null; + Parameter a = arg ? arg.syntaxCopy() : null; IfStatement s = new IfStatement(loc, a, condition.syntaxCopy(), i, e); return s; } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/IndexExp.d --- a/dmd/IndexExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/IndexExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -25,7 +25,7 @@ import dmd.WANT; import dmd.TupleExp; import dmd.TypeTuple; -import dmd.Argument; +import dmd.Parameter; import dmd.TypeExp; import dmd.VarExp; import dmd.STC; @@ -159,7 +159,7 @@ else if (e1.op == TOKtype) { tup = cast(TypeTuple)t1; - length = Argument.dim(tup.arguments); + length = Parameter.dim(tup.arguments); } else assert(0); @@ -169,7 +169,7 @@ if (e1.op == TOKtuple) e = te.exps[cast(size_t)index]; else - e = new TypeExp(e1.loc, Argument.getNth(tup.arguments, cast(size_t)index).type); + e = new TypeExp(e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type); } else { @@ -383,7 +383,7 @@ ep = el_params(n2, valuesize, keyti, n1, null); e = el_bin(OPcall, TYnptr, el_var(s), ep); - if (global.params.useArrayBounds) + if (irs.arrayBoundsCheck()) { elem* ea; @@ -406,7 +406,7 @@ elem* einit = resolveLengthVar(lengthVar, &n1, t1); elem* n2 = e2.toElem(irs); - if (global.params.useArrayBounds) + if (irs.arrayBoundsCheck()) { elem* elength; elem* n2x; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Initializer.d --- a/dmd/Initializer.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/Initializer.d Thu Sep 09 22:51:44 2010 +0100 @@ -38,7 +38,6 @@ Type inferType(Scope sc) { error(loc, "cannot infer type from initializer"); - halt(); return Type.terror; } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/InterfaceDeclaration.d --- a/dmd/InterfaceDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/InterfaceDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -8,7 +8,7 @@ import dmd.Type; import dmd.TY; import dmd.LINK; -import dmd.Argument; +import dmd.Parameter; import dmd.Util; import dmd.TypeTuple; import dmd.PROT; @@ -112,9 +112,9 @@ { TypeTuple tup = cast(TypeTuple)tb; PROT protection = b.protection; baseclasses.remove(i); - size_t dim = Argument.dim(tup.arguments); + size_t dim = Parameter.dim(tup.arguments); for (size_t j = 0; j < dim; j++) - { Argument arg = Argument.getNth(tup.arguments, j); + { auto arg = Parameter.getNth(tup.arguments, j); b = new BaseClass(arg.type, protection); baseclasses.insert(i + j, b); } @@ -203,7 +203,7 @@ // Skip if b has already appeared for (int k = 0; k < i; k++) { - if (b == interfaces[i]) + if (b == interfaces[k]) goto Lcontinue; } @@ -407,7 +407,7 @@ #if DMDV2 const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function #endif - TypeInfo typeinfo; + //TypeInfo typeinfo; } */ dt_t *dt = null; @@ -472,7 +472,7 @@ dtdword(&dt, 0); } - dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr); // typeinfo + //dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr); // typeinfo ////////////////////////////////////////////// diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/IsExp.d --- a/dmd/IsExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/IsExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -28,7 +28,7 @@ import dmd.TypeFunction; import dmd.MATCH; import dmd.TypePointer; -import dmd.Argument; +import dmd.Parameter; import dmd.Token; class IsExp : Expression @@ -164,11 +164,11 @@ goto Lno; else { ClassDeclaration cd = (cast(TypeClass)targ).sym; - auto args = new Arguments; + auto args = new Parameters; args.reserve(cd.baseclasses.dim); foreach (b; cd.baseclasses) { - args.push(new Argument(STCin, b.type, null, null)); + args.push(new Parameter(STCin, b.type, null, null)); } tded = new TypeTuple(args); } @@ -195,15 +195,15 @@ /* Generate tuple from function parameter types. */ assert(tded.ty == Tfunction); - Arguments params = (cast(TypeFunction)tded).parameters; - size_t dim = Argument.dim(params); - Arguments args = new Arguments; + auto params = (cast(TypeFunction)tded).parameters; + size_t dim = Parameter.dim(params); + auto args = new Parameters; args.reserve(dim); for (size_t i = 0; i < dim; i++) { - auto arg = Argument.getNth(params, i); + auto arg = Parameter.getNth(params, i); assert(arg && arg.type); - args.push(new Argument(arg.storageClass, arg.type, null, null)); + args.push(new Parameter(arg.storageClass, arg.type, null, null)); } tded = new TypeTuple(args); break; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Lexer.d --- a/dmd/Lexer.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/Lexer.d Thu Sep 09 22:51:44 2010 +0100 @@ -497,7 +497,9 @@ Token.tochars[TOK.TOKorass] = "|="; Token.tochars[TOK.TOKidentifier] = "identifier"; Token.tochars[TOK.TOKat] = "@"; - + Token.tochars[TOK.TOKpow] = "^^"; + //Token.tochars[TOK.TOKpowass] = "^^="; + // For debugging Token.tochars[TOKerror] = "error"; Token.tochars[TOK.TOKdotexp] = "dotexp"; @@ -1258,6 +1260,30 @@ else t.value = TOK.TOKtilde; // ~ return; + +version(DMDV2) { + case '^': + p++; + if (*p == '^') + { p++; +//static if (false) { +// if (*p == '=') +// { p++; +// t.value = TOKpowass; // ^^= +// } +// else +//} + t.value = TOKpow; // ^^ + } + else if (*p == '=') + { p++; + t.value = TOKxorass; // ^= + } + else + t.value = TOKxor; // ^ + return; +} + /* #define SINGLE(c,tok) case c: p++; t.value = tok; return; @@ -1289,8 +1315,9 @@ DOUBLE('*', TOKmul, '=', TOKmulass) DOUBLE('%', TOKmod, '=', TOKmodass) +#if DMDV1 DOUBLE('^', TOKxor, '=', TOKxorass) - +#endif #undef DOUBLE */ @@ -1326,7 +1353,7 @@ t.value = TOK.TOKmod; } return; - +version(DMDV1) { case '^': p++; if (*p == '=') { @@ -1336,7 +1363,7 @@ t.value = TOK.TOKxor; } return; - +} case '#': p++; pragma_(); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/LineInitExp.d --- a/dmd/LineInitExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/LineInitExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -22,7 +22,7 @@ return this; } - override Expression resolve(Loc loc, Scope sc) + override Expression resolveLoc(Loc loc, Scope sc) { Expression e = new IntegerExp(loc, loc.linnum, Type.tint32); e = e.castTo(sc, type); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/MinAssignExp.d --- a/dmd/MinAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/MinAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -14,6 +14,7 @@ import dmd.TY; import dmd.TOK; import dmd.Id; +import dmd.ArrayLengthExp; import dmd.backend.elem; import dmd.backend.Util; @@ -40,6 +41,13 @@ if (e) return e; + if (e1.op == TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + if (e1.op == TOKslice) { // T[] -= ... typeCombine(sc); @@ -79,7 +87,7 @@ AssignExp_buildArrayIdent(buf, arguments, "Min"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return AssignExp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/MinExp.d --- a/dmd/MinExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/MinExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -148,7 +148,7 @@ Exp_buildArrayIdent(buf, arguments, "Min"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return Exp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ModAssignExp.d --- a/dmd/ModAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ModAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -41,7 +41,7 @@ AssignExp_buildArrayIdent(buf, arguments, "Mod"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return AssignExp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ModExp.d --- a/dmd/ModExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ModExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -83,7 +83,7 @@ Exp_buildArrayIdent(buf, arguments, "Mod"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return Exp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/MulAssignExp.d --- a/dmd/MulAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/MulAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -14,6 +14,7 @@ import dmd.TOK; import dmd.Type; import dmd.TY; +import dmd.ArrayLengthExp; import dmd.backend.elem; import dmd.backend.OPER; @@ -38,6 +39,15 @@ if (e) return e; +version(DMDV2) { + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } +} + if (e1.op == TOKslice) { // T[] -= ... typeCombine(sc); @@ -96,7 +106,7 @@ AssignExp_buildArrayIdent(buf, arguments, "Mul"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return AssignExp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/MulExp.d --- a/dmd/MulExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/MulExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -121,7 +121,7 @@ Exp_buildArrayIdent(buf, arguments, "Mul"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return Exp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/NegExp.d --- a/dmd/NegExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/NegExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -76,7 +76,7 @@ buf.writestring("Neg"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { Expression ex1 = e1.buildArrayLoop(fparams); Expression e = new NegExp(Loc(0), ex1); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/NewDeclaration.d --- a/dmd/NewDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/NewDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -5,7 +5,7 @@ import dmd.Loc; import dmd.ArrayTypes; import dmd.Dsymbol; -import dmd.Argument; +import dmd.Parameter; import dmd.ClassDeclaration; import dmd.Type; import dmd.TypeFunction; @@ -19,10 +19,10 @@ class NewDeclaration : FuncDeclaration { - Arguments arguments; + Parameters arguments; int varargs; - this(Loc loc, Loc endloc, Arguments arguments, int varargs) + this(Loc loc, Loc endloc, Parameters arguments, int varargs) { super(loc, endloc, Id.classNew, STCstatic, null); this.arguments = arguments; @@ -37,7 +37,7 @@ FuncDeclaration.syntaxCopy(f); - f.arguments = Argument.arraySyntaxCopy(arguments); + f.arguments = Parameter.arraySyntaxCopy(arguments); return f; } @@ -64,13 +64,13 @@ // Check that there is at least one argument of type size_t TypeFunction tf = cast(TypeFunction)type; - if (Argument.dim(tf.parameters) < 1) + if (Parameter.dim(tf.parameters) < 1) { error("at least one argument of type size_t expected"); } else { - Argument a = Argument.getNth(tf.parameters, 0); + auto a = Parameter.getNth(tf.parameters, 0); if (!a.type.equals(Type.tsize_t)) error("first argument must be type size_t, not %s", a.type.toChars()); } @@ -81,7 +81,7 @@ override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { buf.writestring("new"); - Argument.argsToCBuffer(buf, hgs, arguments, varargs); + Parameter.argsToCBuffer(buf, hgs, arguments, varargs); bodyToCBuffer(buf, hgs); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/NewExp.d --- a/dmd/NewExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/NewExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -114,9 +114,9 @@ //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco); arrayExpressionSemantic(newargs, sc); - preFunctionArguments(loc, sc, newargs); + preFunctionParameters(loc, sc, newargs); arrayExpressionSemantic(arguments, sc); - preFunctionArguments(loc, sc, arguments); + preFunctionParameters(loc, sc, arguments); if (thisexp && tb.ty != Tclass) error("e.new is only for allocating nested classes, not %s", tb.toChars()); @@ -248,7 +248,7 @@ if (!arguments) arguments = new Expressions(); - functionArguments(loc, sc, tf, arguments); + functionParameters(loc, sc, tf, arguments); } else { @@ -269,7 +269,7 @@ assert(allocator); tf = cast(TypeFunction)f.type; - functionArguments(loc, sc, tf, newargs); + functionParameters(loc, sc, tf, newargs); } else { @@ -299,7 +299,7 @@ if (!arguments) arguments = new Expressions(); - functionArguments(loc, sc, tf, arguments); + functionParameters(loc, sc, tf, arguments); } else { @@ -320,7 +320,7 @@ assert(allocator); tf = cast(TypeFunction)f.type; - functionArguments(loc, sc, tf, newargs); + functionParameters(loc, sc, tf, newargs); static if (false) { e = new VarExp(loc, f); e = new CallExp(loc, e, newargs); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/OrAssignExp.d --- a/dmd/OrAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/OrAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -39,7 +39,7 @@ AssignExp_buildArrayIdent(buf, arguments, "Or"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return AssignExp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/OrExp.d --- a/dmd/OrExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/OrExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -84,7 +84,7 @@ Exp_buildArrayIdent(buf, arguments, "Or"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return Exp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Param.d --- a/dmd/Param.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/Param.d Thu Sep 09 22:51:44 2010 +0100 @@ -31,7 +31,10 @@ bool useInvariants; // generate class invariant checks bool useIn; // generate precondition checks bool useOut; // generate postcondition checks - bool useArrayBounds; // generate array bounds checks + byte useArrayBounds; // 0: no array bounds checks + // 1: array bounds checks for safe functions only + // 2: array bounds checks for all functions + bool noboundscheck; // no array bounds checking at all bool useSwitchError; // check for switches without a default bool useUnitTests; // generate unittest code bool useInline; // inline expand functions @@ -43,7 +46,6 @@ bool nofloat; // code should not pull in floating point support byte Dversion; // D version number bool ignoreUnsupportedPragmas; // rather than error on them - bool safe; // enforce safe memory model string argv0; // program name Array imppath; // array of char*'s of where to look for import modules diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Parameter.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/Parameter.d Thu Sep 09 22:51:44 2010 +0100 @@ -0,0 +1,303 @@ +module dmd.Parameter; + +import dmd.common; +import dmd.Type; +import dmd.Identifier; +import dmd.TypeArray; +import dmd.TypeFunction; +import dmd.TypeDelegate; +import dmd.TypeTuple; +import dmd.TY; +import dmd.Expression; +import dmd.OutBuffer; +import dmd.HdrGenState; +import dmd.ArrayTypes; +import dmd.StorageClassDeclaration; +import dmd.Global; +import dmd.MOD; +import dmd.CppMangleState; +import dmd.STC; + +class Parameter +{ + //enum InOut inout; + STC storageClass; + Type type; + Identifier ident; + Expression defaultArg; + + this(STC storageClass, Type type, Identifier ident, Expression defaultArg) + { + this.type = type; + this.ident = ident; + this.storageClass = storageClass; + this.defaultArg = defaultArg; + } + + Parameter clone() + { + return new Parameter(storageClass, type, ident, defaultArg); + } + + Parameter syntaxCopy() + { + return new Parameter(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null); + } + + /**************************************************** + * Determine if parameter is a lazy array of delegates. + * If so, return the return type of those delegates. + * If not, return null. + */ + Type isLazyArray() + { + // if (inout == Lazy) + { + Type tb = type.toBasetype(); + if (tb.ty == Tsarray || tb.ty == Tarray) + { + Type tel = (cast(TypeArray)tb).next.toBasetype(); + if (tel.ty == Tdelegate) + { + TypeDelegate td = cast(TypeDelegate)tel; + TypeFunction tf = cast(TypeFunction)td.next; + + if (!tf.varargs && Parameter.dim(tf.parameters) == 0) + { + return tf.next; // return type of delegate + } + } + } + } + return null; + } + + void toDecoBuffer(OutBuffer buf) + { + if (storageClass & STC.STCscope) + buf.writeByte('M'); + switch (storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STClazy)) + { + case STC.STCundefined: + case STC.STCin: + break; + case STC.STCout: + buf.writeByte('J'); + break; + case STC.STCref: + buf.writeByte('K'); + break; + case STC.STClazy: + buf.writeByte('L'); + break; + } +static if (false) { + int mod = 0x100; + if (type.toBasetype().ty == TY.Tclass) + mod = 0; + type.toDecoBuffer(buf, mod); +} else { + //type.toHeadMutable().toDecoBuffer(buf, 0); + type.toDecoBuffer(buf, 0); +} + } + + static Parameters arraySyntaxCopy(Parameters args) + { + typeof(return) a = null; + + if (args) + { + a = new Parameters(); + a.setDim(args.dim); + + for (size_t i = 0; i < a.dim; i++) + { + auto arg = args[i]; + + arg = arg.syntaxCopy(); + a[i] = arg; + } + } + + return a; + } + + static string argsTypesToChars(Parameters args, int varargs) + { + scope OutBuffer buf = new OutBuffer(); + + static if (true) { + HdrGenState hgs; + argsToCBuffer(buf, &hgs, args, varargs); + } else { + buf.writeByte('('); + if (args) + { + OutBuffer argbuf = new OutBuffer(); + HdrGenState hgs; + + for (int i = 0; i < args.dim; i++) + { + if (i) + buf.writeByte(','); + auto arg = cast(Parameter)args.data[i]; + argbuf.reset(); + arg.type.toCBuffer2(&argbuf, &hgs, 0); + buf.write(&argbuf); + } + if (varargs) + { + if (i && varargs == 1) + buf.writeByte(','); + buf.writestring("..."); + } + } + buf.writeByte(')'); + } + return buf.toChars(); + } + + static void argsCppMangle(OutBuffer buf, CppMangleState* cms, Parameters arguments, int varargs) + { + assert(false); + } + + static void argsToCBuffer(OutBuffer buf, HdrGenState* hgs, Parameters arguments, int varargs) + { + buf.writeByte('('); + if (arguments) + { + int i; + scope OutBuffer argbuf = new OutBuffer(); + + for (i = 0; i < arguments.dim; i++) + { + if (i) + buf.writestring(", "); + auto arg = arguments[i]; + + if (arg.storageClass & STCout) + buf.writestring("out "); + else if (arg.storageClass & STCref) + buf.writestring((global.params.Dversion == 1) ? "inout " : "ref "); + else if (arg.storageClass & STCin) + buf.writestring("in "); + else if (arg.storageClass & STClazy) + buf.writestring("lazy "); + else if (arg.storageClass & STCalias) + buf.writestring("alias "); + else if (arg.storageClass & STCauto) + buf.writestring("auto "); + + uint stc = arg.storageClass; + if (arg.type && arg.type.mod & MODshared) + stc &= ~STCshared; + + StorageClassDeclaration.stcToCBuffer(buf, stc & (STCconst | STCimmutable | STCshared | STCscope)); + + argbuf.reset(); + if (arg.storageClass & STCalias) + { + if (arg.ident) + argbuf.writestring(arg.ident.toChars()); + } + else + arg.type.toCBuffer(argbuf, arg.ident, hgs); + if (arg.defaultArg) + { + argbuf.writestring(" = "); + arg.defaultArg.toCBuffer(argbuf, hgs); + } + buf.write(argbuf); + } + if (varargs) + { + if (i && varargs == 1) + buf.writeByte(','); + buf.writestring("..."); + } + } + buf.writeByte(')'); + } + + static void argsToDecoBuffer(OutBuffer buf, Parameters arguments) + { + //printf("Parameter::argsToDecoBuffer()\n"); + + // Write argument types + if (arguments) + { + size_t dim = Parameter.dim(arguments); + for (size_t i = 0; i < dim; i++) + { + auto arg = Parameter.getNth(arguments, i); + arg.toDecoBuffer(buf); + } + } + } + + static int isTPL(Parameters arguments) + { + assert(false); + } + + /*************************************** + * Determine number of arguments, folding in tuples. + */ + static size_t dim(Parameters args) + { + size_t n = 0; + if (args) + { + foreach (arg; args) + { + Type t = arg.type.toBasetype(); + + if (t.ty == TY.Ttuple) + { + auto tu = cast(TypeTuple)t; + n += dim(tu.arguments); + } + else + n++; + } + } + return n; + } + + /*************************************** + * Get nth Parameter, folding in tuples. + * Returns: + * Parameter nth Parameter + * null not found, *pn gets incremented by the number + * of Parameters + */ + static Parameter getNth(Parameters args, size_t nth, size_t* pn = null) + { + if (!args) + return null; + + size_t n = 0; + foreach (arg; args) + { + Type t = arg.type.toBasetype(); + + if (t.ty == TY.Ttuple) + { TypeTuple tu = cast(TypeTuple)t; + arg = getNth(tu.arguments, nth - n, &n); + if (arg) + return arg; + } + else if (n == nth) + return arg; + else + n++; + } + + if (pn) + *pn += n; + + return null; + } +} diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Parser.d --- a/dmd/Parser.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/Parser.d Thu Sep 09 22:51:44 2010 +0100 @@ -138,7 +138,7 @@ import dmd.CompoundStatement; import dmd.ConditionalStatement; import dmd.CompoundDeclarationStatement; -import dmd.Argument; +import dmd.Parameter; import dmd.ParseStatementFlags; import dmd.TypeNewArray; import dmd.TypeNext; @@ -235,6 +235,7 @@ bool safe = false; nextToken(); +static if(false) { version (DMDV2) { if (token.value == TOK.TOKlparen) { @@ -254,6 +255,7 @@ check(TOK.TOKrparen); } } +} if (token.value != TOK.TOKidentifier) { @@ -507,6 +509,7 @@ case TOK.TOKgshared: stc = STC.STCgshared; goto Lstc; //case TOK.TOKmanifest: stc = STC.STCmanifest; goto Lstc; + case TOK.TOKat: stc = parseAttribute(); goto Lstc; } Lstc: @@ -545,6 +548,7 @@ case TOK.TOKtls: stc = STC.STCtls; goto Lstc; case TOK.TOKgshared: stc = STC.STCgshared; goto Lstc; //case TOK.TOKmanifest: stc = STC.STCmanifest; goto Lstc; + case TOK.TOKat: stc = parseAttribute(); goto Lstc; default: break; } @@ -835,7 +839,7 @@ } return a; } - +version(DMDV2) { void composeStorageClass(STC stc) { STC u = stc; @@ -847,8 +851,39 @@ u &= STC.STCgshared | STC.STCshared | STC.STCtls; if (u & (u - 1)) error("conflicting storage class %s", Token.toChars(token.value)); + u = stc; + u &= STCsafe | STCsystem | STCtrusted; + if (u & (u - 1)) + error("conflicting attribute @%s", token.toChars()); } - +} + +/*********************************************** + * Parse storage class, lexer is on '@' + */ + +version(DMDV2) { + STC parseAttribute() + { + nextToken(); + STC stc = STCundefined; + if (token.value != TOKidentifier) + { + error("identifier expected after @, not %s", token.toChars()); + } + else if (token.ident == Id.property) + stc = STCproperty; + else if (token.ident == Id.safe) + stc = STCsafe; + else if (token.ident == Id.trusted) + stc = STCtrusted; + else if (token.ident == Id.system) + stc = STCsystem; + else + error("valid attribute identifiers are @property, @safe, @trusted, @system, not @%s", token.toChars()); + return stc; + } +} /************************************** * Parse constraint. * Constraint is of the form: @@ -1575,7 +1610,7 @@ nextToken(); nextToken(); check(TOK.TOKrparen); - PostBlitDeclaration f = new PostBlitDeclaration(loc, Loc(0)); + auto f = new PostBlitDeclaration(loc, Loc(0)); parseContracts(f); return f; } @@ -1589,7 +1624,7 @@ { tpl = parseTemplateParameterList(); int varargs; - Arguments arguments = parseParameters(&varargs); + auto arguments = parseParameters(&varargs); Expression constraint = null; if (tpl) @@ -1608,7 +1643,7 @@ /* Just a regular constructor */ int varargs; - Arguments arguments = parseParameters(&varargs); + auto arguments = parseParameters(&varargs); CtorDeclaration f = new CtorDeclaration(loc, Loc(0), arguments, varargs); parseContracts(f); return f; @@ -1725,7 +1760,7 @@ NewDeclaration parseNew() { NewDeclaration f; - scope Arguments arguments = new Arguments(); + scope arguments = new Parameters(); int varargs; Loc loc = this.loc; @@ -1744,7 +1779,7 @@ DeleteDeclaration parseDelete() { DeleteDeclaration f; - scope Arguments arguments; + scope Parameters arguments; int varargs; Loc loc = this.loc; @@ -1757,9 +1792,9 @@ return f; } - Arguments parseParameters(int* pvarargs) + Parameters parseParameters(int* pvarargs) { - Arguments arguments = new Arguments(); + auto arguments = new Parameters(); int varargs = 0; int hasdefault = 0; @@ -1768,7 +1803,7 @@ { Type *tb; Identifier ai = null; Type at; - Argument a; + Parameter a; STC storageClass = STC.STCundefined; STC stc; Expression ae; @@ -1880,13 +1915,13 @@ if (storageClass & (STC.STCout | STC.STCref)) error("variadic argument cannot be out or ref"); varargs = 2; - a = new Argument(storageClass, at, ai, ae); + a = new Parameter(storageClass, at, ai, ae); arguments.push(a); nextToken(); break; } L3: - a = new Argument(storageClass, at, ai, ae); + a = new Parameter(storageClass, at, ai, ae); arguments.push(a); if (token.value == TOK.TOKcomma) { nextToken(); @@ -2486,11 +2521,11 @@ { //printf("it's type[expression]\n"); inBrackets++; - Expression e = parseExpression(); // [ expression ] + Expression e = parseAssignExp(); // [ expression ] if (token.value == TOK.TOKslice) { nextToken(); - Expression e2 = parseExpression(); // [ exp .. exp ] + Expression e2 = parseAssignExp(); // [ exp .. exp ] t = new TypeSlice(t, e, e2); } else @@ -2505,27 +2540,52 @@ { // Handle delegate declaration: // t delegate(parameter list) nothrow pure // t function(parameter list) nothrow pure - Arguments arguments; + Parameters arguments; int varargs; bool ispure = false; bool isnothrow = false; + bool isproperty = false; TOK save = token.value; + TRUST trust = TRUSTdefault; nextToken(); arguments = parseParameters(&varargs); while (1) { // Postfixes if (token.value == TOK.TOKpure) - ispure = true; + ispure = true; else if (token.value == TOK.TOKnothrow) - isnothrow = true; + isnothrow = true; + else if (token.value == TOKat) + { STC stc = parseAttribute(); + switch (cast(uint)(stc >> 32)) + { case STCproperty >> 32: + isproperty = true; + break; + case STCsafe >> 32: + trust = TRUSTsafe; + break; + case STCsystem >> 32: + trust = TRUSTsystem; + break; + case STCtrusted >> 32: + trust = TRUSTtrusted; + break; + case 0: + break; + default: + assert(0); + } + } else - break; + break; nextToken(); } TypeFunction tf = new TypeFunction(arguments, t, varargs, linkage); tf.ispure = ispure; tf.isnothrow = isnothrow; + tf.isproperty = isproperty; + tf.trust = trust; if (save == TOK.TOKdelegate) t = new TypeDelegate(tf); else @@ -2614,7 +2674,7 @@ else { //printf("It's a static array\n"); - Expression e = parseExpression(); // [ expression ] + Expression e = parseAssignExp(); // [ expression ] ta = new TypeSArray(t, e); check(TOK.TOKrbracket); } @@ -2649,7 +2709,7 @@ } int varargs; - Arguments arguments = parseParameters(&varargs); + auto arguments = parseParameters(&varargs); Type tf = new TypeFunction(arguments, t, varargs, linkage); /* Parse const/invariant/nothrow/pure postfix @@ -2691,19 +2751,31 @@ continue; case TOK.TOKat: - nextToken(); - if (token.value != TOK.TOKidentifier) - { error("attribute identifier expected"); - nextToken(); - continue; - } - Identifier id = token.ident; - if (id is Id.property) - (cast(TypeFunction)tf).isproperty = 1; - else - error("valid attribute identifiers are @property, not @%s", id.toChars()); - nextToken(); - continue; + { + STC stc = parseAttribute(); + auto tfunc = cast(TypeFunction)tf; + switch (cast(uint)(stc >> 32)) + { + case STCproperty >> 32: + tfunc.isproperty = 1; + break; + case STCsafe >> 32: + tfunc.trust = TRUSTsafe; + break; + case STCsystem >> 32: + tfunc.trust = TRUSTsystem; + break; + case STCtrusted >> 32: + tfunc.trust = TRUSTtrusted; + break; + case 0: + break; + default: + assert(0); + } + nextToken(); + continue; + } default: break; /// } @@ -2817,6 +2889,7 @@ case TOK.TOKtls: stc = STC.STCtls; goto L1; case TOK.TOKgshared: stc = STC.STCgshared; goto L1; case TOK.TOKenum: stc = STC.STCmanifest; goto L1; + case TOK.TOKat: stc = parseAttribute(); goto L1; } L1: if (storage_class & stc) @@ -2947,7 +3020,7 @@ auto tf = cast(TypeFunction)t; Expression constraint = null; static if (false) { - if (Argument.isTPL(tf.parameters)) + if (Parameter.isTPL(tf.parameters)) { if (!tpl) tpl = new TemplateParameters(); @@ -3028,7 +3101,6 @@ void parseContracts(FuncDeclaration f) { - Type tb; LINK linksave = linkage; // The following is irrelevant, as it is overridden by sc.linkage in @@ -3071,7 +3143,7 @@ check(TOK.TOKlparen); while (1) { - tb = parseBasicType(); + Type tb = parseBasicType(); f.fthrows.push(tb); if (token.value == TOK.TOKcomma) { nextToken(); @@ -3195,9 +3267,8 @@ case TOK.TOKline: } Lexp: - { Expression exp; - - exp = parseExpression(); + { + auto exp = parseExpression(); check(TOK.TOKsemicolon, "statement"); s = new ExpStatement(loc, exp); break; @@ -3220,6 +3291,16 @@ condition = parseStaticIfCondition(); goto Lcondition; } + if (t.value == TOK.TOKstruct || t.value == TOK.TOKunion || t.value == TOK.TOKclass) + { + nextToken(); + auto a = parseBlock(); + Dsymbol d = new StorageClassDeclaration(STCstatic, a); + s = new DeclarationStatement(loc, d); + if (flags & PSscope) + s = new ScopeStatement(loc, s); + break; + } goto Ldeclaration; } @@ -3255,6 +3336,7 @@ case TOK.TOKpure: case TOK.TOKtls: case TOK.TOKgshared: + case TOK.TOKat: } // case TOK.TOKtypeof: Ldeclaration: @@ -3430,24 +3512,17 @@ case TOK.TOKforeach_reverse: { TOK op = token.value; - Arguments arguments; - - Statement d; - Statement body_; - Expression aggr; nextToken(); check(TOK.TOKlparen); - arguments = new Arguments(); + auto arguments = new Parameters(); while (1) { - Type tb; Identifier ai = null; Type at; STC storageClass = STC.STCundefined; - Argument a; if (token.value == TOK.TOKinout || token.value == TOK.TOKref) { storageClass = STC.STCref; @@ -3467,7 +3542,7 @@ if (!ai) error("no identifier for declarator %s", at.toChars()); Larg: - a = new Argument(storageClass, at, ai, null); + auto a = new Parameter(storageClass, at, ai, null); arguments.push(a); if (token.value == TOK.TOKcomma) { nextToken(); @@ -3477,7 +3552,7 @@ } check(TOK.TOKsemicolon); - aggr = parseExpression(); + Expression aggr = parseExpression(); if (token.value == TOK.TOKslice && arguments.dim == 1) { auto a = arguments[0]; @@ -3485,20 +3560,20 @@ nextToken(); Expression upr = parseExpression(); check(TOK.TOKrparen); - body_ = parseStatement(cast(ParseStatementFlags)0); + auto body_ = parseStatement(cast(ParseStatementFlags)0); s = new ForeachRangeStatement(loc, op, a, aggr, upr, body_); } else { check(TOK.TOKrparen); - body_ = parseStatement(cast(ParseStatementFlags)0); + auto body_ = parseStatement(cast(ParseStatementFlags)0); s = new ForeachStatement(loc, op, arguments, aggr, body_); } break; } case TOK.TOKif: - { Argument arg = null; + { Parameter arg = null; Expression condition2; Statement ifbody2; Statement elsebody2; @@ -3514,7 +3589,7 @@ Token *tt = peek(&token); if (tt.value == TOK.TOKassign) { - arg = new Argument(STC.STCundefined, null, token.ident, null); + arg = new Parameter(STC.STCundefined, null, token.ident, null); nextToken(); nextToken(); } @@ -3535,7 +3610,7 @@ at = parseType(&ai); check(TOK.TOKassign); - arg = new Argument(STC.STCundefined, at, ai, null); + arg = new Parameter(STC.STCundefined, at, ai, null); } // Check for " ident;" @@ -3544,7 +3619,7 @@ Token *tt = peek(&token); if (tt.value == TOK.TOKcomma || tt.value == TOK.TOKsemicolon) { - arg = new Argument(STC.STCundefined, null, token.ident, null); + arg = new Parameter(STC.STCundefined, null, token.ident, null); nextToken(); nextToken(); if (1 || !global.params.useDeprecated) @@ -5137,13 +5212,20 @@ } case TOK.TOKtypeid: - { Type tt; - + { nextToken(); check(TOK.TOKlparen, "typeid"); - tt = parseType(); // ( type ) + Object o; + if (isDeclaration(&token, 0, TOKreserved, NULL)) + { // argument is a type + o = parseType(); + } + else + { // argument is an expression + o = parseAssignExp(); + } check(TOK.TOKrparen); - e = new TypeidExp(loc, tt); + e = new TypeidExp(loc, o); break; } @@ -5345,18 +5427,20 @@ * (parameters) { body } * { body } */ - Arguments arguments; + Parameters arguments; int varargs; FuncLiteralDeclaration fd; Type tt; bool isnothrow = false; bool ispure = false; - + bool isproperty = false; + TRUST trust = TRUSTdefault; + if (token.value == TOK.TOKlcurly) { tt = null; varargs = 0; - arguments = new Arguments(); + arguments = new Parameters(); } else { @@ -5374,8 +5458,31 @@ ispure = true; else if (token.value == TOK.TOKnothrow) isnothrow = true; + else if (token.value == TOKat) + { + STC stc = parseAttribute(); + switch (cast(uint)(stc >> 32)) + { + case STCproperty >> 32: + isproperty = true; + break; + case STCsafe >> 32: + trust = TRUSTsafe; + break; + case STCsystem >> 32: + trust = TRUSTsystem; + break; + case STCtrusted >> 32: + trust = TRUSTtrusted; + break; + case 0: + break; + default: + assert(0); + } + } else - break; + break; nextToken(); } } @@ -5383,6 +5490,8 @@ TypeFunction tf = new TypeFunction(arguments, tt, varargs, linkage); tf.ispure = ispure; tf.isnothrow = isnothrow; + tf.isproperty = isproperty; + tf.trust = trust; fd = new FuncLiteralDeclaration(loc, Loc(0), tf, save, null); parseContracts(fd); e = new FuncExp(loc, fd); @@ -5644,14 +5753,15 @@ if (token.value == TOK.TOKnot && peekNext() != TOK.TOKis) { // identifier!(template-argument-list) TemplateInstance tempinst = new TemplateInstance(loc, id); + Objects tiargs; nextToken(); if (token.value == TOK.TOKlparen) // ident!(template_arguments) - tempinst.tiargs = parseTemplateArgumentList(); + tiargs = parseTemplateArgumentList(); else // ident!template_argument - tempinst.tiargs = parseTemplateArgument(); - e = new DotTemplateInstanceExp(loc, e, tempinst); + tiargs = parseTemplateArgument(); + e = new DotTemplateInstanceExp(loc, e, tiargs); } else e = new DotIdExp(loc, e, id); @@ -5748,8 +5858,9 @@ switch (token.value) { case TOK.TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue; - case TOK.TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue; - case TOK.TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue; + case TOK.TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue; + case TOK.TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue; + case TOK.TOKpow: nextToken(); e2 = parseUnaryExp(); e = new PowExp(loc,e,e2); continue; default: break; @@ -6016,6 +6127,7 @@ case TOK.TOKmulass: nextToken(); e2 = parseAssignExp(); e = new MulAssignExp(loc,e,e2); continue; case TOK.TOKdivass: nextToken(); e2 = parseAssignExp(); e = new DivAssignExp(loc,e,e2); continue; case TOK.TOKmodass: nextToken(); e2 = parseAssignExp(); e = new ModAssignExp(loc,e,e2); continue; +// case TOK.TOKpowass: nextToken(); e2 = parseAssignExp(); e = new PowAssignExp(loc,e,e2); continue; case TOK.TOKandass: nextToken(); e2 = parseAssignExp(); e = new AndAssignExp(loc,e,e2); continue; case TOK.TOKorass: nextToken(); e2 = parseAssignExp(); e = new OrAssignExp(loc,e,e2); continue; case TOK.TOKxorass: nextToken(); e2 = parseAssignExp(); e = new XorAssignExp(loc,e,e2); continue; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/PostExp.d --- a/dmd/PostExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/PostExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -70,11 +70,8 @@ override elem* toElem(IRState* irs) { - elem* e; - elem* einc; - - e = e1.toElem(irs); - einc = e2.toElem(irs); + auto e = e1.toElem(irs); + auto einc = e2.toElem(irs); e = el_bin((op == TOKplusplus) ? OPpostinc : OPpostdec, e.Ety,e,einc); el_setLoc(e,loc); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/PowExp.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/PowExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -0,0 +1,96 @@ +module dmd.PowExp; + +import dmd.BinExp; +import dmd.Scope; +import dmd.Loc; +import dmd.Identifier; +import dmd.Expression; + +version(DMDV2) { + +class PowExp : BinExp +{ + this(Loc loc, Expression e1, Expression e2) + { + super(loc, TOK.TOKpow, PowExp.sizeof, e1, e2); + } + + Expression semantic(Scope sc) + { + Expression e; + + if (type) + return this; + + BinExp.semanticp(sc); + e = op_overload(sc); + if (e) + return e; + + static int importMathChecked = 0; + if (!importMathChecked) + { + importMathChecked = 1; + for (int i = 0; i < Module.amodules.dim; i++) + { + auto mi = cast(Module)Module.amodules.data[i]; + //printf("\t[%d] %s\n", i, mi->toChars()); + if (mi.ident == Id.math && + mi.parent.ident == Id.std && + !mi.parent.parent) + goto L1; + } + error("must import std.math to use ^^ operator"); + + L1: ; + } + + assert(e1.type && e2.type); + if ( (e1.type.isintegral() || e1.type.isfloating()) && + (e2.type.isintegral() || e2.type.isfloating())) + { + // For built-in numeric types, there are three cases: + // x ^^ 1 ----> x + // x ^^ 0.5 ----> sqrt(x) + // x ^^ y ----> pow(x, y) + // TODO: backend support, especially for e1 ^^ 2. + bool wantSqrt = false; + e2 = e2.optimize(0); + if ((e2.op == TOK.TOKfloat64 && e2.toReal() == 1.0) || + (e2.op == TOK.TOKint64 && e2.toInteger() == 1)) + { + return e1; // Replace x ^^ 1 with x. + } + + e = new IdentifierExp(loc, Id.empty); + e = new DotIdExp(loc, e, Id.std); + e = new DotIdExp(loc, e, Id.math); + if (e2.op == TOKfloat64 && e2.toReal() == 0.5) + { // Replace e1 ^^ 0.5 with .std.math.sqrt(x) + e = new CallExp(loc, new DotIdExp(loc, e, Id._sqrt), e1); + } + else + { // Replace e1 ^^ e2 with .std.math.pow(e1, e2) + e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2); + } + e = e.semantic(sc); + return e; + } + error("%s ^^ %s is not supported", e1.type.toChars(), e2.type.toChars() ); + return new ErrorExp(); + } + + + // For operator overloading + Identifier opId() + { + return Id.pow; + } + + Identifier opId_r() + { + return Id.pow_r; + } +} + +} \ No newline at end of file diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/PragmaDeclaration.d --- a/dmd/PragmaDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/PragmaDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -127,6 +127,7 @@ /// goto Lnodecl; /// } /// } +///version(DMDV2) { else if (ident == Id.startaddress) { if (!args || args.dim != 1) @@ -143,6 +144,7 @@ } goto Lnodecl; } +///} /// version (TARGET_NET) { /// else if (ident == Lexer.idPool("assembly")) /// { diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/STC.d --- a/dmd/STC.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/STC.d Thu Sep 09 22:51:44 2010 +0100 @@ -1,6 +1,6 @@ module dmd.STC; -enum STC +enum STC : long { STCundefined = 0, STCstatic = 1, @@ -37,6 +37,10 @@ STCgshared = 0x40000000, // accessible from multiple threads // but not typed as "shared" STC_TYPECTOR = (STCconst | STCimmutable | STCshared), + STCproperty = 0x100000000, + STCsafe = 0x200000000, + STCtrusted = 0x400000000, + STCsystem = 0x800000000, } import dmd.EnumUtils; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ScopeDsymbol.d --- a/dmd/ScopeDsymbol.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ScopeDsymbol.d Thu Sep 09 22:51:44 2010 +0100 @@ -248,8 +248,8 @@ if (!tfgetmembers) { Scope sc; - Arguments arguments = new Arguments(); - Arguments arg = new Argument(STCin, Type.tchar.constOf().arrayOf(), null, null); + auto arguments = new Arguments(); + auto arg = new Argument(STCin, Type.tchar.constOf().arrayOf(), null, null); arguments.push(arg); Type tret = null; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ShlAssignExp.d --- a/dmd/ShlAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ShlAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -35,6 +35,13 @@ if (e) return e; + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + e1 = e1.modifiableLvalue(sc, e1); e1.checkScalar(); e1.checkNoBool(); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ShrAssignExp.d --- a/dmd/ShrAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ShrAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -36,6 +36,13 @@ if (e) return e; + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + e1 = e1.modifiableLvalue(sc, e1); e1.checkScalar(); e1.checkNoBool(); @@ -60,6 +67,15 @@ override elem* toElem(IRState* irs) { - return toElemBin(irs, OPshrass); + //printf("ShrAssignExp::toElem() %s, %s\n", e1->type->toChars(), e1->toChars()); + Type t1 = e1.type; + if (e1.op == TOK.TOKcast) + { + // Use the type before it was integrally promoted to int + auto ce = cast(CastExp)e1; + t1 = ce.e1.type; + } + return toElemBin(irs, t1.isunsigned() ? OPER.OPshrass : OPER.OPashrass); + } } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ShrExp.d --- a/dmd/ShrExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ShrExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -75,7 +75,7 @@ override elem* toElem(IRState* irs) { - return toElemBin(irs, OPER.OPshr); + return toElemBin(irs, e1.type.isunsigned() ? OPER.OPshr : OPER.OPashr); } } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/SliceExp.d --- a/dmd/SliceExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/SliceExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -31,7 +31,7 @@ import dmd.VarDeclaration; import dmd.ErrorExp; import dmd.TypeExp; -import dmd.Argument; +import dmd.Parameter; import dmd.ExpInitializer; import dmd.IRState; import dmd.InlineDoState; @@ -200,7 +200,7 @@ else if (e1.op == TOKtype) // slicing a type tuple { tup = cast(TypeTuple)t; - length = Argument.dim(tup.arguments); + length = Parameter.dim(tup.arguments); } else assert(0); @@ -223,11 +223,11 @@ } else { - auto args = new Arguments; + auto args = new Parameters; args.reserve(j2 - j1); for (size_t i = j1; i < j2; i++) { - auto arg = Argument.getNth(tup.arguments, i); + auto arg = Parameter.getNth(tup.arguments, i); args.push(arg); } e = new TypeExp(e1.loc, new TypeTuple(args)); @@ -379,36 +379,26 @@ override elem* toElem(IRState* irs) { - elem* e; - Type t1; - //printf("SliceExp.toElem()\n"); - t1 = e1.type.toBasetype(); - e = e1.toElem(irs); + auto t1 = e1.type.toBasetype(); + auto e = e1.toElem(irs); if (lwr) { - elem* elwr; - elem* elwr2; - elem* eupr; - elem* eptr; - elem* einit; - int sz; + auto einit = resolveLengthVar(lengthVar, &e, t1); + + int sz = cast(uint)t1.nextOf().size(); - einit = resolveLengthVar(lengthVar, &e, t1); - - sz = cast(uint)t1.nextOf().size(); + auto elwr = lwr.toElem(irs); + auto eupr = upr.toElem(irs); - elwr = lwr.toElem(irs); - eupr = upr.toElem(irs); - - elwr2 = el_same(&elwr); + auto elwr2 = el_same(&elwr); // Create an array reference where: // length is (upr - lwr) // pointer is (ptr + lwr*sz) // Combine as (length pair ptr) - if (global.params.useArrayBounds) + if (irs.arrayBoundsCheck()) { // Checks (unsigned compares): // upr <= array.length @@ -470,7 +460,7 @@ } } - eptr = array_toPtr(e1.type, e); + auto eptr = array_toPtr(e1.type, e); elem *elength = el_bin(OPmin, TYint, eupr, elwr2); eptr = el_bin(OPadd, TYnptr, eptr, el_bin(OPmul, TYint, el_copytree(elwr2), el_long(TYint, sz))); @@ -509,10 +499,10 @@ arguments.shift(this); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { Identifier id = Identifier.generateId("p", fparams.dim); - auto param = new Argument(STCconst, type, id, null); + auto param = new Parameter(STCconst, type, id, null); fparams.shift(param); Expression e = new IdentifierExp(Loc(0), id); Expressions arguments = new Expressions(); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/StorageClassDeclaration.d --- a/dmd/StorageClassDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/StorageClassDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -48,6 +48,8 @@ scstc &= ~(STC.STCconst | STC.STCimmutable | STC.STCmanifest); if (stc & (STC.STCgshared | STC.STCshared | STC.STCtls)) scstc &= ~(STC.STCgshared | STC.STCshared | STC.STCtls); + if (stc & (STC.STCsafe | STC.STCtrusted | STC.STCsystem)) + scstc &= ~(STC.STCsafe | STC.STCtrusted | STC.STCsystem); scstc |= stc; setScopeNewSc(sc, scstc, sc.linkage, sc.protection, sc.explicitProtection, sc.structalign); @@ -71,6 +73,8 @@ scstc &= ~(STC.STCconst | STC.STCimmutable | STC.STCmanifest); if (stc & (STC.STCgshared | STC.STCshared | STC.STCtls)) scstc &= ~(STC.STCgshared | STC.STCshared | STC.STCtls); + if (stc & (STC.STCsafe | STC.STCtrusted | STC.STCsystem)) + scstc &= ~(STC.STCsafe | STC.STCtrusted | STC.STCsystem); scstc |= stc; semanticNewSc(sc, scstc, sc.linkage, sc.protection, sc.explicitProtection, sc.structalign); @@ -114,6 +118,9 @@ /// { STCref, TOKref }, /// { STCtls, TOKtls }, /// { STCgshared, TOKgshared }, +/// { STCproperty, TOKat }, +/// { STCsafe, TOKat }, +/// { STCtrusted, TOKat }, /// } ]; @@ -121,7 +128,22 @@ { if (stc & table[i].stc) { - buf.writestring(Token.toChars(table[i].tok)); + enum TOK tok = table[i].tok; + if (tok == TOKat) + { Identifier id; + + if (stc & STC.STCproperty) + id = Id.property; + else if (stc & STCsafe) + id = Id.safe; + else if (stc & STCtrusted) + id = Id.trusted; + else + assert(0); + buf.writestring(id.toChars()); + } + else + buf.writestring(Token.toChars(tok)); buf.writeByte(' '); } } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/StructDeclaration.d --- a/dmd/StructDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/StructDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -23,7 +23,7 @@ import dmd.ThisExp; import dmd.ThisDeclaration; import dmd.TypeFunction; -import dmd.Argument; +import dmd.Parameter; import dmd.Id; import dmd.TY; import dmd.LINK; @@ -70,6 +70,7 @@ version (DMDV2) { int hasIdentityAssign; // !=0 if has identity opAssign FuncDeclaration cpctor; // generated copy-constructor, if any + FuncDeclaration eq; // bool opEquals(ref const T), if any FuncDeclarations postblits; // Array of postblit functions FuncDeclaration postblit; // aggregate postblit @@ -234,6 +235,10 @@ } } +version(DMDV1) { + /* This doesn't work for DMDV2 because (ref S) and (S) parameter + * lists will overload the same. + */ /* The TypeInfo_Struct is expecting an opEquals and opCmp with * a parameter that is a pointer to the struct. But if there * isn't one, but is an opEquals or opCmp with a value, write @@ -243,8 +248,8 @@ TypeFunction tfeqptr; { - Arguments arguments = new Arguments; - Argument arg = new Argument(STC.STCin, handle, Id.p, null); + auto arguments = new Parameters; + auto arg = new Parameter(STC.STCin, handle, Id.p, null); arguments.push(arg); tfeqptr = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); @@ -253,8 +258,8 @@ TypeFunction tfeq; { - Arguments arguments = new Arguments; - Argument arg = new Argument(STC.STCin, type, null, null); + auto arguments = new Parameters; + auto arg = new Parameter(STC.STCin, type, null, null); arguments.push(arg); tfeq = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); @@ -291,7 +296,39 @@ id = Id.cmp; } +} version (DMDV2) { + /* Try to find the opEquals function. Build it if necessary. + */ + TypeFunction *tfeqptr; + { // bool opEquals(const T*) const; + auto parameters = new Parameters; +version(STRUCTTHISREF) { + // bool opEquals(ref const T) const; + auto param = new Parameter(STC.STCref, type.constOf(), null, null); +} else { + // bool opEquals(const T*) const; + auto param = new Parameter(STC.STCin, type.pointerTo(), null, null); +} + + parameters.push(param); + tfeqptr = new TypeFunction(parameters, Type.tbool, 0, LINK.LINKd); + tfeqptr.mod = MOD.MODconst; + tfeqptr = cast(TypeFunction)(tfeqptr.semantic(0, sc2)); + + Dsymbol s = search_function(this, Id.eq); + FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; + if (fdx) + { + eq = fdx.overloadExactMatch(tfeqptr); + if (!eq) + fdx.error("type signature should be %s not %s", tfeqptr.toChars(), fdx.type.toChars()); + } + + if (!eq) + eq = buildOpEquals(sc2); + } + dtor = buildDtor(sc2); postblit = buildPostBlit(sc2); cpctor = buildCpCtor(sc2); @@ -386,7 +423,17 @@ { assert(false); } - + +version(DMDV1) +{ + Expression cloneMembers() + { + assert(false); + } +} + +version(DMDV2) +{ /******************************************* * We need an opAssign for the struct if * it has a destructor or a postblit. @@ -436,6 +483,46 @@ return true; } + /******************************************* + * We need an opEquals for the struct if + * any fields has an opEquals. + * Generate one if a user-specified one does not exist. + */ + bool needOpEquals() + { + enum X = 0; +static if (X) printf("StructDeclaration::needOpEquals() %s\n", toChars()); + + /* If any of the fields has an opEquals, then we + * need it too. + */ + foreach (s; fields) + { + VarDeclaration v = s.isVarDeclaration(); + assert(v && v.storage_class & STC.STCfield); + if (v.storage_class & STC.STCref) + continue; + Type tv = v.type.toBasetype(); + while (tv.ty == Tsarray) + { auto ta = cast(TypeSArray)tv; + tv = tv.nextOf().toBasetype(); + } + if (tv.ty == Tstruct) + { auto ts = cast(TypeStruct)tv; + StructDeclaration sd = ts.sym; + if (sd.eq) + goto Lneed; + } + } + Ldontneed: +static if (X) printf("\tdontneed\n"); + return false; + + Lneed: +static if (X) printf("\tneed\n"); + return true; + } + /****************************************** * Build opAssign for struct. * S* opAssign(S s) { ... } @@ -449,8 +536,8 @@ FuncDeclaration fop = null; - Argument param = new Argument(STC.STCnodtor, type, Id.p, null); - Arguments fparams = new Arguments; + auto param = new Parameter(STC.STCnodtor, type, Id.p, null); + auto fparams = new Parameters; fparams.push(param); Type ftype = new TypeFunction(fparams, handle, false, LINK.LINKd); version (STRUCTTHISREF) { @@ -543,6 +630,72 @@ return fop; } + /****************************************** + * Build opEquals for struct. + * const bool opEquals(const ref S s) { ... } + */ + FuncDeclaration buildOpEquals(Scope sc) + { + if (!needOpEquals()) + return null; + //printf("StructDeclaration::buildOpEquals() %s\n", toChars()); + Loc loc = this.loc; + + auto parameters = new Parameters; +version (STRUCTTHISREF) { + // bool opEquals(ref const T) const; + auto param = new Parameter(STC.STCref, type.constOf(), Id.p, NULL); +} else { + // bool opEquals(const T*) const; + auto param = new Parameter(STC.STCin, type.pointerTo(), Id.p, NULL); +} + + parameters.push(param); + auto ftype = new TypeFunction(parameters, Type.tbool, 0, LINKd); + ftype.mod = MOD.MODconst; + ftype = cast(TypeFunction)ftype.semantic(loc, sc); + + auto fop = new FuncDeclaration(loc, 0, Id.eq, STD.STCundefined, ftype); + + Expression *e = NULL; + /* Do memberwise compare + */ + //printf("\tmemberwise compare\n"); + foreach (s; fields) + { + VarDeclaration v = s.isVarDeclaration(); + assert(v && v.storage_class & STD.STCfield); + if (v.storage_class & STC.STCref) + assert(0); // what should we do with this? + // this.v == s.v; + auto ec = new EqualExp(TOKequal, loc, + new DotVarExp(loc, new ThisExp(loc), v, 0), + new DotVarExp(loc, new IdentifierExp(loc, Id.p), v, 0)); + if (e) + e = new AndAndExp(loc, e, ec); + else + e = ec; + } + if (!e) + e = new IntegerExp(loc, 1, Type.tbool); + fop.fbody = new ReturnStatement(loc, e); + + members.push(fop); + fop.addMember(sc, this, 1); + + sc = sc.push(); + sc.stc = 0; + sc.linkage = LINK.LINKd; + + fop.semantic(sc); + + sc.pop(); + + //printf("-StructDeclaration::buildOpEquals() %s\n", toChars()); + + return fop; + } + /***************************************** * Create inclusive postblit for struct by aggregating * all the postblits in postblits[] with the postblits for @@ -664,8 +817,8 @@ { //printf("generating cpctor\n"); - Argument param = new Argument(STC.STCref, type, Id.p, null); - Arguments fparams = new Arguments; + auto param = new Parameter(STC.STCref, type, Id.p, null); + auto fparams = new Parameters; fparams.push(param); Type ftype = new TypeFunction(fparams, Type.tvoid, false, LINK.LINKd); @@ -701,7 +854,7 @@ return fcp; } - +} override void toDocBuffer(OutBuffer buf) { assert(false); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/StructInitializer.d --- a/dmd/StructInitializer.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/StructInitializer.d Thu Sep 09 22:51:44 2010 +0100 @@ -152,7 +152,7 @@ { /* Rewrite as empty delegate literal { } */ - auto arguments = new Arguments; + auto arguments = new Parameters; Type tf = new TypeFunction(arguments, null, 0, LINK.LINKd); FuncLiteralDeclaration fd = new FuncLiteralDeclaration(loc, Loc(0), tf, TOK.TOKdelegate, null); fd.fbody = new CompoundStatement(loc, new Statements()); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/SymOffExp.d --- a/dmd/SymOffExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/SymOffExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -59,7 +59,14 @@ if (v) { if (!v.isDataseg()) + { /* BUG: This should be allowed: + * void foo() + * { int a; + * int* bar() { return &a; } + * } + */ error("escaping reference to local variable %s", v.toChars()); + } } } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TOK.d --- a/dmd/TOK.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TOK.d Thu Sep 09 22:51:44 2010 +0100 @@ -126,6 +126,8 @@ TOKfile, TOKshared, TOKat, + TOKpow, + //TOKpowass, TOKMAX } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TRUST.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/TRUST.d Thu Sep 09 22:51:44 2010 +0100 @@ -0,0 +1,12 @@ +module dmd.TRUST; + +enum TRUST +{ + TRUSTdefault = 0, + TRUSTsystem = 1, // @system (same as TRUSTdefault) + TRUSTtrusted = 2, // @trusted + TRUSTsafe = 3, // @safe +}; + +import dmd.EnumUtils; +mixin(BringToCurrentScope!(TRUST)); \ No newline at end of file diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TemplateAliasParameter.d --- a/dmd/TemplateAliasParameter.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TemplateAliasParameter.d Thu Sep 09 22:51:44 2010 +0100 @@ -111,7 +111,7 @@ Dsymbol sa = isDsymbol(oded); assert(sa); - printf("\tArgument alias: %s\n", sa.toChars()); + printf("Parameter alias: %s\n", sa.toChars()); } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TemplateDeclaration.d --- a/dmd/TemplateDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TemplateDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -19,7 +19,7 @@ import dmd.TypeSArray; import dmd.StringExp; import dmd.TOK; -import dmd.Argument; +import dmd.Parameter; import dmd.CtorDeclaration; import dmd.TypeFunction; import dmd.TY; @@ -544,6 +544,7 @@ if (m && constraint && !(flag & 1)) { /* Check to see if constraint is satisfied. */ + makeParamNamesVisibleInConstraint(paramscope); Expression e = constraint.syntaxCopy(); paramscope.flags |= SCOPE.SCOPEstaticif; e = e.semantic(paramscope); @@ -687,7 +688,7 @@ int tuple_dim = 0; MATCH match = MATCHexact; FuncDeclaration fd = onemember.toAlias().isFuncDeclaration(); - Arguments fparameters; // function parameter list + Parameters fparameters; // function parameter list int fvarargs; // function varargs scope Objects dedtypes = new Objects(); // for T:T*, the dedargs is the T*, dedtypes is the T @@ -717,6 +718,7 @@ Scope paramscope = scope_.push(paramsym); TemplateTupleParameter tp = isVariadic(); + int tp_is_declared = 0; static if (false) { @@ -757,6 +759,7 @@ t.objects[i] = targsi[n + i]; } declareParameter(paramscope, tp, t); + tp_is_declared = 1; } else n = nargsi; @@ -808,7 +811,7 @@ fvarargs = fctor.varargs; } - nfparams = Argument.dim(fparameters); // number of function parameters + nfparams = Parameter.dim(fparameters); // number of function parameters nfargs = fargs ? fargs.dim : 0; // number of function arguments /* Check for match of function arguments with variadic template @@ -821,6 +824,8 @@ { if (nfparams == 0 && nfargs != 0) // if no function parameters { + if (tp_is_declared) + goto L2; auto t = new Tuple(); //printf("t = %p\n", t); dedargs[parameters.dim - 1] = t; @@ -848,6 +853,9 @@ if (fvarargs) // variadic function doesn't goto Lnomatch; // go with variadic template + if (tp_is_declared) + goto L2; + /* The types of the function arguments * now form the tuple argument. */ @@ -915,7 +923,7 @@ continue; } - Argument fparam = Argument.getNth(fparameters, i); + auto fparam = Parameter.getNth(fparameters, i); if (i >= nfargs) // if not enough arguments { @@ -963,7 +971,7 @@ TypeDelegate td = cast(TypeDelegate)fparam.type.toBasetype(); TypeFunction tf = cast(TypeFunction)td.next; - if (!tf.varargs && Argument.dim(tf.parameters) == 0) + if (!tf.varargs && Parameter.dim(tf.parameters) == 0) { m = farg.type.deduceType(paramscope, tf.next, parameters, dedtypes); if (!m && tf.next.toBasetype().ty == Tvoid) @@ -1100,6 +1108,7 @@ if (constraint) { /* Check to see if constraint is satisfied. */ + makeParamNamesVisibleInConstraint(paramscope); Expression e = constraint.syntaxCopy(); paramscope.flags |= SCOPE.SCOPEstaticif; e = e.semantic(paramscope); @@ -1366,4 +1375,60 @@ { return true; } + + /**************************** + * Declare all the function parameters as variables + * and add them to the scope + */ + void makeParamNamesVisibleInConstraint(Scope paramscope) + { + /* We do this ONLY if there is only one function in the template. + */ + FuncDeclaration fd = onemember && onemember.toAlias() ? + onemember.toAlias().isFuncDeclaration() : NULL; + if (fd) + { + paramscope.parent = fd; + Parameters fparameters; // function parameter list + int fvarargs; // function varargs + if (fd.type) + { + assert(fd.type.ty == Tfunction); + TypeFunction fdtype = cast(TypeFunction )fd.type; + fparameters = fdtype.parameters; + fvarargs = fdtype.varargs; + } + else // Constructors don't have type's + { CtorDeclaration fctor = fd.isCtorDeclaration(); + assert(fctor); + fparameters = fctor.arguments; + fvarargs = fctor.varargs; + } + size_t nfparams = Parameter.dim(fparameters); // Num function parameters + for (int i = 0; i < nfparams; i++) + { + Parameter fparam = Parameter.getNth(fparameters, i).syntaxCopy(); + if (!fparam.ident) + continue; // don't add it, if it has no name + Type vtype = fparam.type.syntaxCopy(); + // isPure will segfault if called on a ctor, because fd->type is null. + if (fd.type && fd.isPure()) + vtype = vtype.addMod(MODconst); + VarDeclaration v = new VarDeclaration(loc, vtype, fparam.ident, null); + v.storage_class |= STCparameter; + // Not sure if this condition is correct/necessary. + // It's from func.c + if (//fd->type && fd->type->ty == Tfunction && + fvarargs == 2 && i + 1 == nfparams) + v.storage_class |= STCvariadic; + + v.storage_class |= fparam.storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor); + v.semantic(paramscope); + if (!paramscope.insert(v)) + error("parameter %s.%s is already defined", toChars(), v.toChars()); + else + v.parent = this; + } + } + } } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TemplateInstance.d --- a/dmd/TemplateInstance.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TemplateInstance.d Thu Sep 09 22:51:44 2010 +0100 @@ -24,7 +24,7 @@ import dmd.TOK; import dmd.TY; import dmd.TypeTuple; -import dmd.Argument; +import dmd.Parameter; import dmd.WANT; import dmd.ExpInitializer; import dmd.Array; @@ -750,7 +750,48 @@ *ps = null; return true; } - + + /***************************************************** + * Determine if template instance is really a template function, + * and that template function needs to infer types from the function + * arguments. + */ + + bool needsTypeInference(Scope sc) + { + //printf("TemplateInstance::needsTypeInference() %s\n", toChars()); + if (!tempdecl) + tempdecl = findTemplateDeclaration(sc); + for (TemplateDeclaration td = tempdecl; td; td = td.overnext) + { + /* If any of the overloaded template declarations need inference, + * then return TRUE + */ + FuncDeclaration fd; + if (!td.onemember || + (fd = td.onemember.toAlias().isFuncDeclaration()) == null || + fd.type.ty != TY.Tfunction) + { + /* Not a template function, therefore type inference is not possible. + */ + //printf("false\n"); + return false; + } + + /* Determine if the instance arguments, tiargs, are all that is necessary + * to instantiate the template. + */ + TemplateTupleParameter tp = td.isVariadic(); + //printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim); + TypeFunction fdtype = cast(TypeFunction)fd.type; + if (Parameter.dim(fdtype.parameters) && + (tp || tiargs.dim < td.parameters.dim)) + return true; + } + //printf("false\n"); + return false; + } + override string toChars() { scope OutBuffer buf = new OutBuffer(); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TemplateValueParameter.d --- a/dmd/TemplateValueParameter.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TemplateValueParameter.d Thu Sep 09 22:51:44 2010 +0100 @@ -138,11 +138,7 @@ e = e.syntaxCopy(); e = e.semantic(sc); version (DMDV2) { - if (e.op == TOKdefault) - { - DefaultInitExp de = cast(DefaultInitExp)e; - e = de.resolve(loc, sc); - } + e = e.resolveLoc(loc, sc); } } return e; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/ThrowStatement.d --- a/dmd/ThrowStatement.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/ThrowStatement.d Thu Sep 09 22:51:44 2010 +0100 @@ -43,8 +43,11 @@ FuncDeclaration fd = sc.parent.isFuncDeclaration(); fd.hasReturnExp |= 2; +version(DMDV1) { + // See bugzilla 3388. Should this be or not? if (sc.incontract) error("Throw statements cannot be in contracts"); +} exp = exp.semantic(sc); exp = resolveProperties(sc, exp); if (!exp.type.toBasetype().isClassHandle()) diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TupleDeclaration.d --- a/dmd/TupleDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TupleDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -2,7 +2,7 @@ import dmd.common; import dmd.Declaration; -import dmd.Argument; +import dmd.Parameter; import dmd.ArrayTypes; import dmd.TypeTuple; import dmd.Loc; @@ -54,10 +54,8 @@ { /* It's only a type tuple if all the Object's are types */ - for (size_t i = 0; i < objects.dim; i++) + foreach (o; objects) { - Object o = objects[i]; - if (cast(Type)o is null) { //printf("\tnot[%d], %p, %d\n", i, o, o->dyncast()); @@ -67,7 +65,7 @@ /* We know it's a type tuple, so build the TypeTuple */ - Arguments args = new Arguments(); + auto args = new Parameters(); args.setDim(objects.dim); OutBuffer buf = new OutBuffer(); bool hasdeco = 1; @@ -80,9 +78,9 @@ buf.printf("_%s_%d", ident.toChars(), i); char *name = cast(char *)buf.extractData(); Identifier id = new Identifier(name, TOKidentifier); - auto arg = new Argument(STCin, t, id, null); + auto arg = new Parameter(STCin, t, id, null); } else { - auto arg = new Argument(STCundefined, t, null, null); + auto arg = new Parameter(STCundefined, t, null, null); } args[i] = arg; if (!t.deco) diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Type.d --- a/dmd/Type.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/Type.d Thu Sep 09 22:51:44 2010 +0100 @@ -2,7 +2,7 @@ import dmd.common; import dmd.TY; -import dmd.Argument; +import dmd.Parameter; import dmd.TOK; import dmd.STC; import dmd.TypeArray; @@ -396,8 +396,8 @@ DYNCAST dyncast() { return DYNCAST.DYNCAST_TYPE; } // kludge for template.isType() /******************************* - * Covariant means that 'this' can substitute for 't'. - * Returns: + * Covariant means that 'this' can substitute for 't', + * i.e. a pure function is a match for an impure type. * Returns: * 0 types are distinct * 1 this is covariant with t * 2 arguments match as far as overloading goes, @@ -433,14 +433,14 @@ if (t1.parameters && t2.parameters) { - size_t dim = Argument.dim(t1.parameters); - if (dim != Argument.dim(t2.parameters)) + size_t dim = Parameter.dim(t1.parameters); + if (dim != Parameter.dim(t2.parameters)) goto Ldistinct; for (size_t i = 0; i < dim; i++) { - Argument arg1 = Argument.getNth(t1.parameters, i); - Argument arg2 = Argument.getNth(t2.parameters, i); + auto arg1 = Parameter.getNth(t1.parameters, i); + auto arg2 = Parameter.getNth(t2.parameters, i); if (!arg1.type.equals(arg2.type)) { @@ -452,7 +452,8 @@ ///} goto Ldistinct; } - if ((arg1.storageClass & ~STC.STCscope) != (arg2.storageClass & ~STC.STCscope)) + const STC sc = STC.STCref | STC.STCin | STC.STCout | STC.STClazy; + if ((arg1.storageClass & sc) != (arg2.storageClass & sc)) inoutmismatch = 1; // We can add scope, but not subtract it if (!(arg1.storageClass & STC.STCscope) && (arg2.storageClass & STC.STCscope)) @@ -521,6 +522,11 @@ goto Lnotcovariant; if (t1.isref != t2.isref) + goto Lnotcovariant; + + /* Can convert safe/trusted to system + */ + if (t1.trust <= TRUST.TRUSTsystem && t2.trust >= TRUSTtrusted) goto Lnotcovariant; //printf("\tcovaraint: 1\n"); @@ -1764,11 +1770,11 @@ // if (!e.isConst()) // error(loc, ".init cannot be evaluated at compile time"); } - return e; + goto Lreturn; } } - Expression ex = defaultInit(e.loc); - return ex; + e = defaultInit(e.loc); + goto Lreturn; } } if (ident is Id.typeinfo_) @@ -1776,19 +1782,89 @@ if (!global.params.useDeprecated) error(e.loc, ".typeinfo deprecated, use typeid(type)"); e = getTypeInfo(sc); - return e; } - if (ident is Id.stringof_) + else if (ident is Id.stringof_) { string s = e.toChars(); e = new StringExp(e.loc, s, 'c'); - scope Scope sc2 = new Scope(); /// - e = e.semantic(sc2); - return e; } - return getProperty(e.loc, ident); + else + e = getProperty(e.loc, ident); + +Lreturn: + e = e.semantic(sc); + return e; } + /*************************************** + * Figures out what to do with an undefined member reference + * for classes and structs. + */ + Expression noMember(Scope sc, Expression e, Identifier ident) + { + assert(ty == TY.Tstruct || ty == TY.Tclass); + AggregateDeclaration sym = toDsymbol(sc).isAggregateDeclaration(); + assert(sym); + + if (ident != Id.__sizeof && + ident != Id.alignof && + ident != Id.init && + ident != Id.mangleof && + ident != Id.stringof && + ident != Idoffsetof) + { + /* See if we should forward to the alias this. + */ + if (sym.aliasthis) + { /* Rewrite e.ident as: + * e.aliasthis.ident + */ + e = new DotIdExp(e.loc, e, sym.aliasthis.ident); + e = new DotIdExp(e.loc, e, ident); + return e.semantic(sc); + } + + /* Look for overloaded opDot() to see if we should forward request + * to it. + */ + Dsymbol fd = search_function(sym, Id.opDot); + if (fd) + { /* Rewrite e.ident as: + * e.opDot().ident + */ + e = build_overload(e.loc, sc, e, NULL, fd.ident); + e = new DotIdExp(e.loc, e, ident); + return e.semantic(sc); + } + + /* Look for overloaded opDispatch to see if we should forward request + * to it. + */ + fd = search_function(sym, Id.opDispatch); + if (fd) + { + /* Rewrite e.ident as: + * e.opDispatch!("ident") + */ + TemplateDeclaration td = fd.isTemplateDeclaration(); + if (!td) + { + fd.error("must be a template opDispatch(string s), not a %s", fd.kind()); + return new ErrorExp(); + } + auto se = new StringExp(e.loc, ident.toChars()); + auto tiargs = new Objects(); + tiargs.push(se); + e = new DotTemplateInstanceExp(e.loc, e, Id.opDispatch, tiargs); + (cast(DotTemplateInstanceExp)e).ti.tempdecl = td; + return e; + //return e.semantic(sc); + } + } + + return Type.dotExp(sc, e, ident); + } + uint memalign(uint salign) { return salign; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeArray.d --- a/dmd/TypeArray.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeArray.d Thu Sep 09 22:51:44 2010 +0100 @@ -122,6 +122,7 @@ { e = Type.dotExp(sc, e, ident); } + e = e.semantic(sc); return e; } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeBasic.d --- a/dmd/TypeBasic.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeBasic.d Thu Sep 09 22:51:44 2010 +0100 @@ -511,7 +511,8 @@ break; default: - return Type.getProperty(e.loc, ident); + e = Type.getProperty(e.loc, ident); + break; } } else if (ident is Id.im) @@ -543,13 +544,15 @@ break; default: - return Type.getProperty(e.loc, ident); + e = Type.getProperty(e.loc, ident); + break; } } else { return Type.dotExp(sc, e, ident); } + e = e.semantic(sc); return e; } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeClass.d --- a/dmd/TypeClass.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeClass.d Thu Sep 09 22:51:44 2010 +0100 @@ -200,7 +200,7 @@ * at compile time. */ if (!sym.vclassinfo) - sym.vclassinfo = new ClassInfoDeclaration(sym); + sym.vclassinfo = new TypeInfoClassDeclaration(sym.type); e = new VarExp(e.loc, sym.vclassinfo); e = e.addressOf(sc); @@ -273,41 +273,7 @@ } else { - if (ident !is Id.__sizeof && - ident !is Id.alignof_ && - ident !is Id.init_ && - ident !is Id.mangleof_ && - ident !is Id.stringof_ && - ident !is Id.offsetof) - { - /* See if we should forward to the alias this. - */ - if (sym.aliasthis) - { - /* Rewrite e.ident as: - * e.aliasthis.ident - */ - e = new DotIdExp(e.loc, e, sym.aliasthis.ident); - e = new DotIdExp(e.loc, e, ident); - return e.semantic(sc); - } - - /* Look for overloaded opDot() to see if we should forward request - * to it. - */ - Dsymbol fd = search_function(sym, Id.opDot); - if (fd) - { - /* Rewrite e.ident as: - * e.opId().ident - */ - e = build_overload(e.loc, sc, e, null, fd.ident); - e = new DotIdExp(e.loc, e, ident); - return e.semantic(sc); - } - } - - return Type.dotExp(sc, e, ident); + return noMember(sc, e, ident); } } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeDelegate.d --- a/dmd/TypeDelegate.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeDelegate.d Thu Sep 09 22:51:44 2010 +0100 @@ -16,7 +16,7 @@ import dmd.Expression; import dmd.Identifier; import dmd.CppMangleState; -import dmd.Argument; +import dmd.Parameter; import dmd.Loc; import dmd.Scope; import dmd.TypeInfoDeclaration; @@ -105,7 +105,7 @@ tf.next.toCBuffer2(buf, hgs, MODundefined); buf.writestring(" delegate"); - Argument.argsToCBuffer(buf, hgs, tf.parameters, tf.varargs); + Parameter.argsToCBuffer(buf, hgs, tf.parameters, tf.varargs); } override Expression defaultInit(Loc loc) diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeFunction.d --- a/dmd/TypeFunction.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeFunction.d Thu Sep 09 22:51:44 2010 +0100 @@ -26,10 +26,11 @@ import dmd.CppMangleState; import dmd.TypeInfoDeclaration; import dmd.MATCH; -import dmd.Argument; +import dmd.Parameter; import dmd.Expression; import dmd.RET; import dmd.TY; +import dmd.TRUST; import dmd.Util; import dmd.TemplateInstance : isTuple; @@ -49,7 +50,7 @@ { // .next is the return type - Arguments parameters; // function parameters + Parameters parameters; // function parameters int varargs; // 1: T t, ...) style for variable number of arguments // 2: T t ...) style for variable number of arguments bool isnothrow; // true: nothrow @@ -57,10 +58,11 @@ bool isproperty; // can be called without parentheses bool isref; // true: returns a reference LINK linkage; // calling convention + TRUST trust; // level of trust int inuse; - this(Arguments parameters, Type treturn, int varargs, LINK linkage) + this(Parameters parameters, Type treturn, int varargs, LINK linkage) { super(TY.Tfunction, treturn); @@ -70,18 +72,20 @@ this.parameters = parameters; this.varargs = varargs; this.linkage = linkage; + this.trust = TRUSTdefault; } override Type syntaxCopy() { Type treturn = next ? next.syntaxCopy() : null; - Arguments params = Argument.arraySyntaxCopy(parameters); + auto params = Parameter.arraySyntaxCopy(parameters); TypeFunction t = new TypeFunction(params, treturn, varargs, linkage); t.mod = mod; t.isnothrow = isnothrow; t.ispure = ispure; t.isproperty = isproperty; t.isref = isref; + t.trust = trust; return t; } @@ -145,8 +149,29 @@ tf.isnothrow = true; if (sc.stc & STC.STCref) tf.isref = true; + if (sc.stc & STCsafe) + tf.trust = TRUST.TRUSTsafe; + if (sc.stc & STCtrusted) + tf.trust = TRUST.TRUSTtrusted; + if (sc.stc & STCproperty) + tf.isproperty = true; + + tf.linkage = sc.linkage; + + /* If the parent is @safe, then this function defaults to safe + * too. + */ + if (tf.trust == TRUST.TRUSTdefault) + for (Dsymbol p = sc.func; p; p = p.toParent2()) + { FuncDeclaration fd = p.isFuncDeclaration(); + if (fd) + { + if (fd.isSafe()) + tf.trust = TRUST.TRUSTsafe; // default to @safe + break; + } + } - tf.linkage = sc.linkage; if (tf.next) { tf.next = tf.next.semantic(loc,sc); @@ -183,7 +208,7 @@ size_t dim = Argument.dim(tf.parameters); for (size_t i = 0; i < dim; i++) - { Argument arg = Argument.getNth(tf.parameters, i); + { auto arg = Parameter.getNth(tf.parameters, i); tf.inuse++; arg.type = arg.type.semantic(loc, argsc); @@ -220,7 +245,7 @@ * change. */ if (t.ty == TY.Ttuple) - { dim = Argument.dim(tf.parameters); + { dim = Parameter.dim(tf.parameters); i--; } } @@ -235,7 +260,10 @@ return terror; } - if (tf.varargs == 1 && tf.linkage != LINK.LINKd && Argument.dim(tf.parameters) == 0) + if (tf.isproperty && (tf.varargs || Parameter.dim(tf.parameters) > 1)) + error(loc, "properties can only have zero or one parameter"); + + if (tf.varargs == 1 && tf.linkage != LINK.LINKd && Parameter.dim(tf.parameters) == 0) error(loc, "variadic functions with non-D linkage must have at least one parameter"); /* Don't return merge(), because arg identifiers and default args @@ -274,7 +302,7 @@ case LINK.LINKcpp: mc = 'R'; break; } buf.writeByte(mc); - if (ispure || isnothrow || isproperty || isref) + if (ispure || isnothrow || isproperty || isref || trust) { if (ispure) buf.writestring("Na"); @@ -284,9 +312,18 @@ buf.writestring("Nc"); if (isproperty) buf.writestring("Nd"); + switch (trust) + { + case TRUST.TRUSTtrusted: + buf.writestring("Ne"); + break; + case TRUST.TRUSTsafe: + buf.writestring("Nd"); + break; + } } // Write argument types - Argument.argsToDecoBuffer(buf, parameters); + Parameter.argsToDecoBuffer(buf, parameters); //if (buf.data[buf.offset - 1] == '@') halt(); buf.writeByte('Z' - varargs); // mark end of arg list assert(next); @@ -324,6 +361,17 @@ if (isref) buf.writestring("ref "); + switch (trust) + { + case TRUST.TRUSTtrusted: + buf.writestring("@trusted "); + break; + + case TRUST.TRUSTsafe: + buf.writestring("@safe "); + break; + } + if (next && (!ident || ident.toHChars2() == ident.toChars())) next.toCBuffer2(buf, hgs, MODundefined); if (hgs.ddoc != 1) @@ -347,7 +395,7 @@ buf.writeByte(' '); buf.writestring(ident.toHChars2()); } - Argument.argsToCBuffer(buf, hgs, parameters, varargs); + Parameter.argsToCBuffer(buf, hgs, parameters, varargs); inuse--; } @@ -382,7 +430,7 @@ if (!hgs.hdrgen && p) buf.writestring(p); buf.writestring(" function"); - Argument.argsToCBuffer(buf, hgs, parameters, varargs); + Parameter.argsToCBuffer(buf, hgs, parameters, varargs); /* Use postfix style for attributes */ @@ -400,6 +448,16 @@ if (isref) buf.writestring(" ref"); + switch (trust) + { + case TRUSTtrusted: + buf.writestring(" @trusted"); + break; + + case TRUSTsafe: + buf.writestring(" @safe"); + break; + } inuse--; } @@ -417,8 +475,8 @@ linkage != tp.linkage) return MATCHnomatch; - size_t nfargs = Argument.dim(this.parameters); - size_t nfparams = Argument.dim(tp.parameters); + size_t nfargs = Parameter.dim(this.parameters); + size_t nfparams = Parameter.dim(tp.parameters); /* See if tuple match */ @@ -427,7 +485,7 @@ /* See if 'A' of the template parameter matches 'A' * of the type of the last function parameter. */ - Argument fparam = Argument.getNth(tp.parameters, nfparams - 1); + auto fparam = Parameter.getNth(tp.parameters, nfparams - 1); assert(fparam); assert(fparam.type); if (fparam.type.ty != Tident) @@ -465,7 +523,7 @@ return MATCHnomatch; for (size_t i = 0; i < tuple_dim; i++) { - Argument arg = Argument.getNth(this.parameters, nfparams - 1 + i); + auto arg = Parameter.getNth(this.parameters, nfparams - 1 + i); if (!arg.type.equals(t.objects[i])) return MATCHnomatch; } @@ -476,7 +534,7 @@ t.objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) { - Argument arg = Argument.getNth(this.parameters, nfparams - 1 + i); + auto arg = Parameter.getNth(this.parameters, nfparams - 1 + i); t.objects[i] = arg.type; } dedtypes[tupi] = t; @@ -491,8 +549,8 @@ L2: for (size_t i = 0; i < nfparams; i++) { - Argument a = Argument.getNth(this.parameters, i); - Argument ap = Argument.getNth(tp.parameters, i); + auto a = Parameter.getNth(this.parameters, i); + auto ap = Parameter.getNth(tp.parameters, i); if (a.storageClass != ap.storageClass || !a.type.deduceType(sc, ap.type, parameters, dedtypes)) return MATCHnomatch; @@ -531,7 +589,7 @@ * Examine function signature for parameter p and see if * p can 'escape' the scope of the function. */ - bool parameterEscapes(Argument p) + bool parameterEscapes(Parameter p) { /* Scope parameters do not escape. * Allow 'lazy' to imply 'scope' - @@ -586,7 +644,7 @@ } } - size_t nparams = Argument.dim(parameters); + size_t nparams = Parameter.dim(parameters); size_t nargs = args ? args.dim : 0; if (nparams == nargs) { ; @@ -604,7 +662,7 @@ // BUG: what about out and ref? - Argument p = Argument.getNth(parameters, u); + auto p = Parameter.getNth(parameters, u); assert(p); if (u >= nargs) { @@ -745,10 +803,10 @@ type* tp; paramtypes = null; - size_t nparams = Argument.dim(parameters); + size_t nparams = Parameter.dim(parameters); for (size_t i = 0; i < nparams; i++) { - Argument arg = Argument.getNth(parameters, i); + auto arg = Parameter.getNth(parameters, i); tp = arg.type.toCtype(); if (arg.storageClass & (STC.STCout | STC.STCref)) { diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeInfoClassDeclaration.d --- a/dmd/TypeInfoClassDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeInfoClassDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -20,9 +20,19 @@ type = Type.typeinfostruct.type; } + override Symbol* toSymbol() + { + //printf("TypeInfoClassDeclaration::toSymbol(%s), linkage = %d\n", toChars(), linkage); + assert(tinfo.ty == TY.Tclass); + auto tc = cast(TypeClass)tinfo; + return tc.sym.toSymbol(); + } + override void toDt(dt_t** pdt) { //printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars()); + assert(0); +static if(false) { dtxoff(pdt, Type.typeinfoclass.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoClass dtdword(pdt, 0); // monitor @@ -37,6 +47,7 @@ assert(s.Sxtrnnum == 0); dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo +} } } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeInfoInterfaceDeclaration.d --- a/dmd/TypeInfoInterfaceDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeInfoInterfaceDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -32,7 +32,7 @@ Symbol *s; if (!tc.sym.vclassinfo) - tc.sym.vclassinfo = new ClassInfoDeclaration(tc.sym); + tc.sym.vclassinfo = new TypeInfoClassDeclaration(tc.sym); s = tc.sym.vclassinfo.toSymbol(); dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeInfoStructDeclaration.d --- a/dmd/TypeInfoStructDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeInfoStructDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -5,7 +5,7 @@ import dmd.TY; import dmd.MOD; import dmd.Loc; -import dmd.Argument; +import dmd.Parameter; import dmd.STC; import dmd.TypeStruct; import dmd.TypeFunction; @@ -109,6 +109,24 @@ auto arg = new Argument(STC.STCin, tc.pointerTo(), null, null); } + arguments.push(arg); + tfeqptr = new TypeFunction(arguments, Type.tbool, 0, LINK.LINKd); + tfeqptr.mod = MODconst; + tfeqptr = cast(TypeFunction)tfeqptr.semantic(0, &sc); + } + + TypeFunction *tfcmpptr; + { + Scope sc; + auto arguments = new Arguments; +version(STRUCTTHISREF) { + // arg type is ref const T + auto arg = new Argument(STC.STCref, tc.constOf(), null, null); +} else { + // arg type is const T* + auto arg = new Argument(STC.STCin, tc.pointerTo(), null, null); +} + arguments.push(arg); tfeqptr = new TypeFunction(arguments, Type.tbool, 0, LINK.LINKd); tfeqptr.mod = MOD.MODconst; @@ -118,13 +136,13 @@ TypeFunction tfcmpptr; { scope Scope sc = new Scope(); - auto arguments = new Arguments; + auto arguments = new Parameters; version (STRUCTTHISREF) { // arg type is ref const T - auto arg = new Argument(STC.STCref, tc.constOf(), null, null); + auto arg = new Parameter(STC.STCref, tc.constOf(), null, null); } else { // arg type is const T* - auto arg = new Argument(STC.STCin, tc.pointerTo(), null, null); + auto arg = new Parameter(STC.STCin, tc.pointerTo(), null, null); } arguments.push(arg); @@ -147,23 +165,8 @@ else dtdword(pdt, 0); - s = search_function(sd, Id.eq); - fdx = s ? s.isFuncDeclaration() : null; - if (fdx) - { - //printf("test1 %s, %s, %s\n", fdx.toChars(), fdx.type.toChars(), tfeqptr.toChars()); - fd = fdx.overloadExactMatch(tfeqptr); - if (fd) - dtxoff(pdt, fd.toSymbol(), 0, TYM.TYnptr); - else - { - fd = fdx.overloadExactMatch(tfcmpptr); - if (fd) - fdx.error("must return bool, not int"); - //fdx.error("must be declared as extern (D) int %s(%s*)", fdx.toChars(), sd.toChars()); - dtdword(pdt, 0); - } - } + if (sd.eq) + dtxoff(pdt, sd.eq.toSymbol(), 0, TYnptr); else dtdword(pdt, 0); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeInfoTupleDeclaration.d --- a/dmd/TypeInfoTupleDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeInfoTupleDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -5,7 +5,7 @@ import dmd.TypeInfoDeclaration; import dmd.WANT; import dmd.TypeTuple; -import dmd.Argument; +import dmd.Parameter; import dmd.Expression; import dmd.TY; import dmd.backend.TYM; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeReturn.d --- a/dmd/TypeReturn.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeReturn.d Thu Sep 09 22:51:44 2010 +0100 @@ -53,6 +53,11 @@ goto Lerr; } t = sc.func.type.nextOf(); + if (!t) + { + error(loc, "cannot use typeof(return) inside function %s with inferred return type", sc.func.toChars()); + goto Lerr; + } t = t.addMod(mod); if (idents.dim) diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeSArray.d --- a/dmd/TypeSArray.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeSArray.d Thu Sep 09 22:51:44 2010 +0100 @@ -5,7 +5,7 @@ import dmd.TypeInfoStaticArrayDeclaration; import dmd.TypeAArray; import dmd.MOD; -import dmd.Argument; +import dmd.Parameter; import dmd.TypeIdentifier; import dmd.TemplateParameter; import dmd.TemplateValueParameter; @@ -333,6 +333,7 @@ { e = TypeArray.dotExp(sc, e, ident); } + e = e.semantic(sc); return e; } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeSlice.d --- a/dmd/TypeSlice.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeSlice.d Thu Sep 09 22:51:44 2010 +0100 @@ -14,7 +14,7 @@ import dmd.TypeTuple; import dmd.WANT; import dmd.ArrayTypes; -import dmd.Argument; +import dmd.Parameter; import dmd.SliceExp; import dmd.TupleDeclaration; import dmd.ScopeDsymbol; @@ -79,7 +79,7 @@ return Type.terror; } - auto args = new Arguments; + auto args = new Parameters; args.reserve(cast(size_t)(i2 - i1)); for (size_t i = cast(size_t)i1; i < cast(size_t)i2; i++) { diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeStruct.d --- a/dmd/TypeStruct.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeStruct.d Thu Sep 09 22:51:44 2010 +0100 @@ -218,41 +218,7 @@ L1: if (!s) { - if (ident !is Id.__sizeof && - ident !is Id.alignof_ && - ident !is Id.init_ && - ident !is Id.mangleof_ && - ident !is Id.stringof_ && - ident !is Id.offsetof) - { - /* See if we should forward to the alias this. - */ - if (sym.aliasthis) - { - /* Rewrite e.ident as: - * e.aliasthis.ident - */ - e = new DotIdExp(e.loc, e, sym.aliasthis.ident); - e = new DotIdExp(e.loc, e, ident); - return e.semantic(sc); - } - - /* Look for overloaded opDot() to see if we should forward request - * to it. - */ - Dsymbol fd = search_function(sym, Id.opDot); - if (fd) - { - /* Rewrite e.ident as: - * e.opId().ident - */ - e = build_overload(e.loc, sc, e, null, fd.ident); - e = new DotIdExp(e.loc, e, ident); - return e.semantic(sc); - } - } - - return Type.dotExp(sc, e, ident); + return noMember(sc, e, ident); } if (!s.isFuncDeclaration()) // because of overloading diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeTuple.d --- a/dmd/TypeTuple.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeTuple.d Thu Sep 09 22:51:44 2010 +0100 @@ -15,15 +15,15 @@ import dmd.TY; import dmd.Id; import dmd.STC; -import dmd.Argument; +import dmd.Parameter; import dmd.ErrorExp; import dmd.IntegerExp; class TypeTuple : Type { - Arguments arguments; // types making up the tuple + Parameters arguments; // types making up the tuple - this(Arguments arguments) + this(Parameters arguments) { super(TY.Ttuple); //printf("TypeTuple(this = %p)\n", this); @@ -55,7 +55,7 @@ this(Expressions exps) { super(TY.Ttuple); - auto arguments = new Arguments; + auto arguments = new Parameters; if (exps) { arguments.setDim(exps.dim); @@ -63,7 +63,7 @@ { auto e = exps[i]; if (e.type.ty == Ttuple) e.error("cannot form tuple of tuples"); - auto arg = new Argument(STCundefined, e.type, null, null); + auto arg = new Parameter(STCundefined, e.type, null, null); arguments[i] = arg; } } @@ -72,7 +72,7 @@ override Type syntaxCopy() { - auto args = Argument.arraySyntaxCopy(arguments); + auto args = Parameter.arraySyntaxCopy(arguments); auto t = new TypeTuple(args); t.mod = mod; return t; @@ -102,7 +102,7 @@ return 1; } if (t.ty == Ttuple) - { TypeTuple tt = cast(TypeTuple)t; + { auto tt = cast(TypeTuple)t; if (arguments.dim == tt.arguments.dim) { @@ -135,7 +135,7 @@ override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) { - Argument.argsToCBuffer(buf, hgs, arguments, 0); + Parameter.argsToCBuffer(buf, hgs, arguments, 0); } override void toDecoBuffer(OutBuffer buf, int flag) @@ -143,7 +143,7 @@ //printf("TypeTuple::toDecoBuffer() this = %p, %s\n", this, toChars()); Type.toDecoBuffer(buf, flag); OutBuffer buf2 = new OutBuffer(); - Argument.argsToDecoBuffer(buf2, arguments); + Parameter.argsToDecoBuffer(buf2, arguments); uint len = buf2.offset; //buf.printf("%d%.*s", len, len, cast(char *)buf2.extractData()); buf.printf("%d%s", len, buf2.extractString()); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeTypeof.d --- a/dmd/TypeTypeof.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeTypeof.d Thu Sep 09 22:51:44 2010 +0100 @@ -132,6 +132,7 @@ if (exp.op == TOK.TOKtype) { error(loc, "argument %s to typeof is not an expression", exp.toChars()); + goto Lerr; } t = exp.type; if (!t) @@ -140,7 +141,10 @@ goto Lerr; } if (t.ty == TY.Ttypeof) + { error(loc, "forward reference to %s", toChars()); + goto Lerr; + } /* typeof should reflect the true type, * not what 'auto' would have gotten us. diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/TypeidExp.d --- a/dmd/TypeidExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/TypeidExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -11,12 +11,12 @@ class TypeidExp : Expression { - Type typeidType; + Object *obj; - this(Loc loc, Type typeidType) + this(Loc loc, Object o) { super(loc, TOK.TOKtypeid, TypeidExp.sizeof); - this.typeidType = typeidType; + this.obj = o; } version (DumbClone) { @@ -28,7 +28,7 @@ } override Expression syntaxCopy() { - return new TypeidExp(loc, typeidType.syntaxCopy()); + return new TypeidExp(loc, objectSyntaxCopy(obj)); } override Expression semantic(Scope sc) @@ -38,10 +38,46 @@ version (LOGSEMANTIC) { printf("TypeidExp.semantic()\n"); } - typeidType = typeidType.semantic(loc, sc); - e = typeidType.getTypeInfo(sc); - if (e.loc.linnum == 0) - e.loc = loc; // so there's at least some line number info + Type ta = isType(obj); + Expression ea = isExpression(obj); + Dsymbol sa = isDsymbol(obj); + + if (ta) + { + ta.resolve(loc, sc, &ea, &ta, &sa); + } + if (ea) + { + ea = ea.semantic(sc); + ea = resolveProperties(sc, ea); + ta = ea.type; + if (ea.op == TOKtype) + ea = null; + } + + if (!ta) + { error("no type for typeid(%s)", ea ? ea.toChars() : (sa ? sa.toChars() : "")); + return new ErrorExp(); + } + + if (ea && ta.toBasetype().ty == Tclass) + { /* Get the dynamic type, which is .classinfo + */ + e = new DotIdExp(ea.loc, ea, Id.classinfo); + e = e.semantic(sc); + } + else + { /* Get the static type + */ + e = ta.getTypeInfo(sc); + if (e.loc.linnum == 0) + e.loc = loc; // so there's at least some line number info + if (ea) + { + e = new CommaExp(loc, ea, e); // execute ea + e = e.semantic(sc); + } + } return e; } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/UnaExp.d --- a/dmd/UnaExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/UnaExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -86,6 +86,12 @@ return e1.canThrow(); } + Expression resolveLoc(Loc loc, Scope sc) + { + e1 = e1.resolveLoc(loc, sc); + return this; + } + override int inlineCost(InlineCostState* ics) { return 1 + e1.inlineCost(ics); @@ -93,7 +99,7 @@ override Expression doInline(InlineDoState ids) { - UnaExp ue = cast(UnaExp)copy(); + auto ue = cast(UnaExp)copy(); ue.e1 = e1.doInline(ids); return ue; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/UshrAssignExp.d --- a/dmd/UshrAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/UshrAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -33,6 +33,13 @@ if (e) return e; + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + e1 = e1.modifiableLvalue(sc, e1); e1.checkScalar(); e1.checkNoBool(); @@ -56,6 +63,6 @@ override elem* toElem(IRState* irs) { - assert(false); + return toElemBin(irs, OPER.OPshrass); } } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/UshrExp.d --- a/dmd/UshrExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/UshrExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -75,11 +75,6 @@ override elem* toElem(IRState* irs) { - elem *eleft = e1.toElem(irs); - eleft.Ety = touns(eleft.Ety); - elem *eright = e2.toElem(irs); - elem *e = el_bin(OPshr, type.totym(), eleft, eright); - el_setLoc(e, loc); - return e; + return toElemBin(irs, OPER.OPshr); } } \ No newline at end of file diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/Util.d --- a/dmd/Util.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/Util.d Thu Sep 09 22:51:44 2010 +0100 @@ -557,6 +557,7 @@ " -Llinkerflag pass linkerflag to link\n" " -lib generate library rather than object files\n" " -man open web browser on manual page\n" +" -noboundscheck turns off array bounds checking for all functions\n" " -nofloat do not emit reference to floating point\n" " -O optimize\n" " -o- do not write object file\n" @@ -567,7 +568,6 @@ " -quiet suppress unnecessary messages\n" " -release compile release version\n" " -run srcfile args... run resulting program, passing args\n" -" -safe safe memory model\n" " -unittest compile in unit tests\n" " -v verbose\n" " -version=level compile in version code >= level\n" @@ -638,7 +638,8 @@ precedence[TOK.TOKmul] = PREC.PREC_mul; precedence[TOK.TOKdiv] = PREC.PREC_mul; precedence[TOK.TOKmod] = PREC.PREC_mul; - + precedence[TOKpow] = PREC.PREC_mul; + precedence[TOK.TOKadd] = PREC.PREC_add; precedence[TOK.TOKmin] = PREC.PREC_add; precedence[TOK.TOKcat] = PREC.PREC_add; @@ -697,6 +698,7 @@ precedence[TOK.TOKmulass] = PREC.PREC_assign; precedence[TOK.TOKdivass] = PREC.PREC_assign; precedence[TOK.TOKmodass] = PREC.PREC_assign; + //precedence[TOKpowass] = PREC.PREC_assign; precedence[TOK.TOKshlass] = PREC.PREC_assign; precedence[TOK.TOKshrass] = PREC.PREC_assign; precedence[TOK.TOKushrass] = PREC.PREC_assign; diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/VarDeclaration.d --- a/dmd/VarDeclaration.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/VarDeclaration.d Thu Sep 09 22:51:44 2010 +0100 @@ -33,7 +33,7 @@ import dmd.Initializer; import dmd.TypeStruct; import dmd.TypeTuple; -import dmd.Argument; +import dmd.Parameter; import dmd.ExpInitializer; import dmd.ArrayTypes; import dmd.Dsymbol; @@ -198,10 +198,31 @@ if (!type) { inuse++; - type = init.inferType(sc); + + ArrayInitializer ai = init.isArrayInitializer(); + if (ai) + { + Expression e; + if (ai.isAssociativeArray()) + e = ai.toAssocArrayLiteral(); + else + e = init.toExpression(); + init = new ExpInitializer(e.loc, e); + type = init.inferType(sc); + if (type.ty == TY.Tsarray) + type = type.nextOf().arrayOf(); + } + else + type = init.inferType(sc); + inuse--; inferred = 1; + if (init.isArrayInitializer() && type.toBasetype().ty == TY.Tsarray) + { // Prefer array literals to give a T[] type rather than a T[dim] + type = type.toBasetype().nextOf().arrayOf(); + } + /* This is a kludge to support the existing syntax for RAII * declarations. */ @@ -226,11 +247,18 @@ //printf("storage_class = x%x\n", storage_class); version (DMDV2) { +static if (true) { + if (storage_class & STC.STCgshared && sc.func && sc.func.isSafe()) + { + error("__gshared not allowed in safe functions; use shared"); + } +} else { if (storage_class & STC.STCgshared && global.params.safe && !sc.module_.safe) { error("__gshared not allowed in safe mode; use shared"); } } +} Dsymbol parent = toParent(); FuncDeclaration fd = parent.isFuncDeclaration(); @@ -260,15 +288,15 @@ * and add those. */ TypeTuple tt = cast(TypeTuple)tb; - size_t nelems = Argument.dim(tt.arguments); + size_t nelems = Parameter.dim(tt.arguments); Objects exps = new Objects(); exps.setDim(nelems); Expression ie = init ? init.toExpression() : null; for (size_t i = 0; i < nelems; i++) - { Argument arg = Argument.getNth(tt.arguments, i); + { auto arg = Parameter.getNth(tt.arguments, i); - OutBuffer buf = new OutBuffer(); + auto buf = new OutBuffer(); ///buf.printf("_%s_field_%zu", ident.toChars(), i); buf.printf("_%s_field_%s", ident.toChars(), i); buf.writeByte(0); @@ -473,7 +501,8 @@ ArrayInitializer ai = init.isArrayInitializer(); if (ai && tb.ty == TY.Taarray) { - init = ai.toAssocArrayInitializer(); + Expression e = ai.toAssocArrayLiteral(); + init = new ExpInitializer(e.loc, e); } StructInitializer si = init.isStructInitializer(); diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/VarExp.d --- a/dmd/VarExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/VarExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -83,8 +83,22 @@ v.checkNestedReference(sc, loc); version (DMDV2) { static if (true) { - if (sc.func) + if (sc.func && !sc.intypeof) { + /* Given: + * void f() + * { int fx; + * pure void g() + * { int gx; + * void h() + * { int hx; + * void i() { } + * } + * } + * } + * i() can modify hx and gx but not fx + */ + /* Determine if sc.func is pure or if any function that * encloses it is also pure. */ @@ -107,17 +121,23 @@ * If it is pure, it cannot access any mutable variables other * than those inside itself */ - if (hasPureParent && !sc.intypeof && v.isDataseg() && !v.isInvariant()) + if (hasPureParent && v.isDataseg() && !v.isInvariant()) { error("pure function '%s' cannot access mutable static data '%s'", sc.func.toChars(), v.toChars()); } - else if (sc.func.isPure() && sc.parent != v.parent && !sc.intypeof && !v.isInvariant() && !(v.storage_class & STC.STCmanifest)) + else if (sc.func.isPure() && sc.parent != v.parent && !v.isInvariant() && !(v.storage_class & STC.STCmanifest)) { error("pure nested function '%s' cannot access mutable data '%s'", sc.func.toChars(), v.toChars()); if (v.isEnumDeclaration()) error("enum"); - } + } + + /* Do not allow safe functions to access __gshared data + */ + if (sc.func.isSafe() && v.storage_class & STCgshared) + error("safe function '%s' cannot access __gshared data '%s'", + sc.func.toChars(), v.toChars()); } } else { if (sc.func && sc.func.isPure() && !sc.intypeof) diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/XorAssignExp.d --- a/dmd/XorAssignExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/XorAssignExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -38,7 +38,7 @@ AssignExp_buildArrayIdent(buf, arguments, "Xor"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return AssignExp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/XorExp.d --- a/dmd/XorExp.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/XorExp.d Thu Sep 09 22:51:44 2010 +0100 @@ -81,7 +81,7 @@ Exp_buildArrayIdent(buf, arguments, "Xor"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { return Exp_buildArrayLoop!(typeof(this))(fparams); } diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/backend/RTLSYM.d --- a/dmd/backend/RTLSYM.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/backend/RTLSYM.d Thu Sep 09 22:51:44 2010 +0100 @@ -57,6 +57,8 @@ RTLSYM_ARRAYCATNT, RTLSYM_ARRAYAPPENDT, RTLSYM_ARRAYAPPENDCT, + RTLSYM_ARRAYAPPENDCD, + RTLSYM_ARRAYAPPENDWD, RTLSYM_ARRAYSETLENGTHT, RTLSYM_ARRAYSETLENGTHIT, RTLSYM_ARRAYCOPY, diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/codegen/Util.d --- a/dmd/codegen/Util.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/codegen/Util.d Thu Sep 09 22:51:44 2010 +0100 @@ -14,7 +14,7 @@ import dmd.TY; import dmd.LINK; import dmd.Expression; -import dmd.Argument; +import dmd.Parameter; import dmd.STC; import dmd.Global; import dmd.Module; @@ -145,10 +145,10 @@ //writef("\targ[%d]: %s\n", i, arg.toChars()); - size_t nparams = Argument.dim(tf.parameters); + size_t nparams = Parameter.dim(tf.parameters); if (i - j < nparams && i >= j) { - Argument p = Argument.getNth(tf.parameters, i - j); + auto p = Parameter.getNth(tf.parameters, i - j); if (p.storageClass & (STC.STCout | STC.STCref)) { diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/expression/ArrayLength.d --- a/dmd/expression/ArrayLength.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/expression/ArrayLength.d Thu Sep 09 22:51:44 2010 +0100 @@ -10,6 +10,17 @@ import dmd.TOK; import dmd.AssocArrayLiteralExp; import dmd.GlobalExpressions; +import dmd.XorExp; +import dmd.UshrExp; +import dmd.ShrExp; +import dmd.ShlExp; +import dmd.OrExp; +import dmd.MulExp; +import dmd.ModExp; +import dmd.MinExp; +import dmd.AddExp; +import dmd.DivExp; +import dmd.AndExp; Expression ArrayLength(Type type, Expression e1) { @@ -37,4 +48,26 @@ e = EXP_CANT_INTERPRET; return e; +} + +Expression opAssignToOp(Loc loc, TOK op, Expression e1, Expression e2) +{ + Expression e; + + switch (op) + { + case TOK.TOKaddass: e = new AddExp(loc, e1, e2); break; + case TOK.TOKminass: e = new MinExp(loc, e1, e2); break; + case TOK.TOKmulass: e = new MulExp(loc, e1, e2); break; + case TOK.TOKdivass: e = new DivExp(loc, e1, e2); break; + case TOK.TOKmodass: e = new ModExp(loc, e1, e2); break; + case TOK.TOKandass: e = new AndExp(loc, e1, e2); break; + case TOK.TOKorass: e = new OrExp (loc, e1, e2); break; + case TOK.TOKxorass: e = new XorExp(loc, e1, e2); break; + case TOK.TOKshlass: e = new ShlExp(loc, e1, e2); break; + case TOK.TOKshrass: e = new ShrExp(loc, e1, e2); break; + case TOK.TOKushrass: e = new UshrExp(loc, e1, e2); break; + default: assert(0); + } + return e; } \ No newline at end of file diff -r 010eb8f0e18d -r 60bb0fe4563e dmd/expression/Util.d --- a/dmd/expression/Util.d Sun Sep 05 15:32:22 2010 +0400 +++ b/dmd/expression/Util.d Thu Sep 09 22:51:44 2010 +0100 @@ -24,7 +24,8 @@ import dmd.IndexExp; import dmd.AssignExp; import dmd.CommaExp; -import dmd.Argument; +import dmd.CondExp; +import dmd.Parameter; import dmd.DefaultInitExp; import dmd.Identifier; import dmd.Dsymbol; @@ -64,6 +65,7 @@ import dmd.TypeAArray; import dmd.Id; import dmd.PtrExp; +import dmd.ErrorExp; import std.stdio : writef; @@ -188,17 +190,30 @@ struct Param2 { Match* m; +version(DMDV2) { Expression ethis; + int property; // 0: unintialized + // 1: seen @property + // 2: not @property +} Expressions arguments; - int fp2(void*, FuncDeclaration f) - { + int fp2(void* param, FuncDeclaration f) + { + auto p = cast(Param2*)param; MATCH match; if (f != m.lastf) // skip duplicates { m.anyf = f; TypeFunction tf = cast(TypeFunction)f.type; + + int property = (tf.isproperty) ? 1 : 2; + if (p.property == 0) + p.property = property; + else if (p.property != property) + error(f.loc, "cannot overload both property and non-property functions"); + match = tf.callMatch(f.needThis() ? ethis : null, arguments); //printf("test: match = %d\n", match); if (match != MATCH.MATCHnomatch) @@ -216,6 +231,7 @@ else if (f.overrides(m.lastf)) goto LfIsBetter; +version(DMDV2) { /* Try to disambiguate using template-style partial ordering rules. * In essence, if f() and g() are ambiguous, if f() can call g(), * but g() cannot call f(), then pick f(). @@ -230,6 +246,7 @@ if (c1 < c2) goto LlastIsBetter; } +} Lambiguous: m.nextf = f; @@ -264,9 +281,10 @@ } version (DMDV2) { - /* Allow covariant matches, if it's just a const conversion - * of the return type - */ + /* Allow covariant matches, as long as the return type + * is just a const conversion. + * This allows things like pure functions to match with an impure function type. + */ if (t.ty == Tfunction) { TypeFunction tf = cast(TypeFunction)f.type; @@ -287,6 +305,7 @@ Param2 p; p.m = m; p.ethis = ethis; + p.property = 0; p.arguments = arguments; overloadApply(fstart, &p.fp2, &p); } @@ -328,11 +347,108 @@ } } +Expressions arrayExpressionToCommonType(Scope sc, Expressions exps, Type *pt) +{ +//version(DMDV1) { +// /* The first element sets the type +// */ +// Type *t0 = NULL; +// for (size_t i = 0; i < exps->dim; i++) +// { Expression *e = (Expression *)exps->data[i]; +// +// if (!e->type) +// { error("%s has no value", e->toChars()); +// e = new ErrorExp(); +// } +// e = resolveProperties(sc, e); +// +// if (!t0) +// t0 = e->type; +// else +// e = e->implicitCastTo(sc, t0); +// exps->data[i] = (void *)e; +// } +// +// if (!t0) +// t0 = Type::tvoid; +// if (pt) +// *pt = t0; +// +// // Eventually, we want to make this copy-on-write +// return exps; +//} +version(DMDV2) { + /* The type is determined by applying ?: to each pair. + */ + /* Still have a problem with: + * ubyte[][] = [ cast(ubyte[])"hello", [1]]; + * which works if the array literal is initialized top down with the ubyte[][] + * type, but fails with this function doing bottom up typing. + */ + //printf("arrayExpressionToCommonType()\n"); + scope integerexp = new IntegerExp(0); + scope condexp = new CondExp(Loc(0), integerexp, null, null); + + Type t0; + Expression e0; + int j0; + foreach (size_t i, Expression e; exps) + { + e = resolveProperties(sc, e); + if (!e.type) + { error("%s has no value", e.toChars()); + e = new ErrorExp(); + } + + if (t0) + { + if (t0 != e.type) + { + /* This applies ?: to merge the types. It's backwards; + * ?: should call this function to merge types. + */ + condexp.type = null; + condexp.e1 = e0; + condexp.e2 = e; + condexp.semantic(sc); + exps[j0] = condexp.e1; + e = condexp.e2; + j0 = i; + e0 = e; + t0 = e0.type; + } + } + else + { + j0 = i; + e0 = e; + t0 = e.type; + } + exps[i] = e; + } + + if (t0) + { + foreach (ref Expression e; exps) + { + e = e.implicitCastTo(sc, t0); + } + } + else + t0 = Type.tvoid; // [] is typed as void[] + if (pt) + *pt = t0; + + // Eventually, we want to make this copy-on-write + return exps; +} +} + /**************************************** * Preprocess arguments to function. */ -void preFunctionArguments(Loc loc, Scope sc, Expressions exps) +void preFunctionParameters(Loc loc, Scope sc, Expressions exps) { if (exps) { @@ -480,14 +596,14 @@ * 5. call copy constructor for struct value arguments */ -void functionArguments(Loc loc, Scope sc, TypeFunction tf, Expressions arguments) +void functionParameters(Loc loc, Scope sc, TypeFunction tf, Expressions arguments) { uint n; - //printf("functionArguments()\n"); + //printf("functionParameters()\n"); assert(arguments); size_t nargs = arguments ? arguments.dim : 0; - size_t nparams = Argument.dim(tf.parameters); + size_t nparams = Parameter.dim(tf.parameters); if (nargs > nparams && tf.varargs == 0) error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf.toChars()); @@ -508,7 +624,7 @@ if (i < nparams) { - auto p = Argument.getNth(tf.parameters, i); + auto p = Parameter.getNth(tf.parameters, i); if (!arg) { @@ -518,21 +634,13 @@ goto L2; error(loc, "expected %d function arguments, not %d", nparams, nargs); - break; + return; } arg = p.defaultArg; -version (DMDV2) { - if (arg.op == TOK.TOKdefault) - { - DefaultInitExp de = cast(DefaultInitExp)arg; - arg = de.resolve(loc, sc); - } - else - { - arg = arg.copy(); - } -} else { arg = arg.copy(); +version (DMDV2) +{ + arg = arg.resolveLoc(loc, sc); // __FILE__ and __LINE__ } arguments.push(arg); nargs++; @@ -544,7 +652,10 @@ if (arg.implicitConvTo(p.type)) { if (nargs != nparams) + { error(loc, "expected %zu function arguments, not %zu", nparams, nargs); + return; + } goto L1; } L2: @@ -778,6 +889,7 @@ // If D linkage and variadic, add _arguments[] as first argument if (tf.linkage == LINK.LINKd && tf.varargs == 1) { + assert(arguments.dim >= nparams); auto e = createTypeInfoArray(sc, &arguments[nparams], arguments.dim - nparams); arguments.insert(0, e); } @@ -954,11 +1066,11 @@ /* Create the TypeTuple corresponding to the types of args[] */ - Arguments args = new Arguments; + auto args = new Parameters; args.setDim(dim); for (size_t i = 0; i < dim; i++) { - Argument arg = new Argument(STCin, exps[i].type, null, null); + auto arg = new Parameter(STCin, exps[i].type, null, null); args[i] = arg; } TypeTuple tup = new TypeTuple(args); @@ -1274,7 +1386,7 @@ * them from the aggregate type. */ -void inferApplyArgTypes(TOK op, Arguments arguments, Expression aggr) +void inferApplyArgTypes(TOK op, Parameters arguments, Expression aggr) { if (!arguments || !arguments.dim) return; @@ -1286,14 +1398,14 @@ if (u == arguments.dim) return; - Argument arg = arguments[u]; + auto arg = arguments[u]; if (!arg.type) break; } AggregateDeclaration ad; - Argument arg = arguments[0]; + auto arg = arguments[0]; Type taggr = aggr.type; if (!taggr) return; @@ -1315,7 +1427,7 @@ case TY.Taarray: { - TypeAArray taa = cast(TypeAArray)tab; + auto taa = cast(TypeAArray)tab; if (arguments.dim == 2) { @@ -1414,7 +1526,7 @@ int fp3(void*, FuncDeclaration f) { - TypeFunction tf = cast(TypeFunction)f.type; + auto tf = cast(TypeFunction)f.type; if (inferApplyArgTypesY(tf, arguments) == 1) return 0; @@ -1424,10 +1536,10 @@ return 0; } - Arguments arguments; + Parameters arguments; } -void inferApplyArgTypesX(FuncDeclaration fstart, Arguments arguments) +void inferApplyArgTypesX(FuncDeclaration fstart, Parameters arguments) { Param3 p3; p3.arguments = arguments; @@ -1441,15 +1553,15 @@ * 1 no match for this function */ -int inferApplyArgTypesY(TypeFunction tf, Arguments arguments) +int inferApplyArgTypesY(TypeFunction tf, Parameters arguments) { size_t nparams; - Argument p; + Parameter p; - if (Argument.dim(tf.parameters) != 1) + if (Parameter.dim(tf.parameters) != 1) goto Lnomatch; - p = Argument.getNth(tf.parameters, 0); + p = Parameter.getNth(tf.parameters, 0); if (p.type.ty != TY.Tdelegate) goto Lnomatch; @@ -1459,7 +1571,7 @@ /* We now have tf, the type of the delegate. Match it against * the arguments, filling in missing argument types. */ - nparams = Argument.dim(tf.parameters); + nparams = Parameter.dim(tf.parameters); if (nparams == 0 || tf.varargs) goto Lnomatch; // not enough parameters if (arguments.dim != nparams) @@ -1467,8 +1579,8 @@ for (size_t u = 0; u < nparams; u++) { - Argument arg = arguments[u]; - Argument param = Argument.getNth(tf.parameters, u); + auto arg = arguments[u]; + auto param = Parameter.getNth(tf.parameters, u); if (arg.type) { if (!arg.type.equals(param.type)) @@ -1620,4 +1732,4 @@ * so be sure and ignore them. */ memcmp(&x1, &x2, REALSIZE - REALPAD) == 0; -} \ No newline at end of file +} diff -r 010eb8f0e18d -r 60bb0fe4563e main.d --- a/main.d Sun Sep 05 15:32:22 2010 +0400 +++ b/main.d Thu Sep 09 22:51:44 2010 +0100 @@ -214,6 +214,7 @@ int status = ExitCode.EXIT_SUCCESS; int argcstart = args.length; int setdebuglib = 0; + byte noboundscheck = 0; global = new Global(); @@ -229,7 +230,7 @@ global.params.useInvariants = 1; global.params.useIn = 1; global.params.useOut = 1; - global.params.useArrayBounds = 1; + global.params.useArrayBounds = 2; // default to all functions global.params.useSwitchError = 1; global.params.useInline = 0; global.params.obj = 1; @@ -477,8 +478,8 @@ else if (arg == "release") global.params.release = 1; ///version (DMDV2) { - else if (arg == "safe") - global.params.safe = 1; + else if (arg == "noboundscheck") + noboundscheck = 1; ///} else if (arg == "unittest") global.params.useUnitTests = 1; @@ -669,14 +670,18 @@ } if (global.params.release) - { global.params.useInvariants = 0; + { + global.params.useInvariants = 0; global.params.useIn = 0; global.params.useOut = 0; global.params.useAssert = 0; global.params.useArrayBounds = 0; global.params.useSwitchError = 0; } - + + if (noboundscheck) + global.params.useArrayBounds = 0; + if (global.params.run) global.params.quiet = 1;