# HG changeset patch # User korDen # Date 1287334567 -14400 # Node ID cd48cb899aeedecf882bf66803e0f13a9583873e # Parent e3afd1303184270eee02f65018cdb0f5cee39d97 Updated to dmd2.040 diff -r e3afd1303184 -r cd48cb899aee commands.linux.txt --- a/commands.linux.txt Sun Oct 17 07:42:00 2010 +0400 +++ b/commands.linux.txt Sun Oct 17 20:56:07 2010 +0400 @@ -16,6 +16,7 @@ -version=BREAKABI -version=SNAN_DEFAULT_INIT -version=SARRAYVALUE +-version=MODULEINFO_IS_STRUCT -ofbin/ddmd bridge.o @@ -299,6 +300,8 @@ dmd/SwitchStatement.d dmd/SymbolDeclaration.d dmd/SynchronizedStatement.d +dmd/SharedStaticCtorDeclaration.d +dmd/SharedStaticDtorDeclaration.d dmd/TOK.d dmd/TRUST.d dmd/TY.d diff -r e3afd1303184 -r cd48cb899aee commands.txt --- a/commands.txt Sun Oct 17 07:42:00 2010 +0400 +++ b/commands.txt Sun Oct 17 20:56:07 2010 +0400 @@ -13,6 +13,7 @@ -version=OMFOBJ -version=SNAN_DEFAULT_INIT -version=SARRAYVALUE +-version=MODULEINFO_IS_STRUCT -ofbin\ddmd.exe bridge.obj ddmd.def @@ -294,6 +295,8 @@ dmd\SwitchStatement.d dmd\SymbolDeclaration.d dmd\SynchronizedStatement.d +dmd\SharedStaticCtorDeclaration.d +dmd\SharedStaticDtorDeclaration.d dmd\TOK.d dmd\TRUST.d dmd\TY.d diff -r e3afd1303184 -r cd48cb899aee dmd/AliasDeclaration.d --- a/dmd/AliasDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/AliasDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -132,11 +132,11 @@ ///version (DMDV2) { type = type.addStorageClass(storage_class); - if (storage_class & (STC.STCref | STCnothrow | STCpure)) + if (storage_class & (STC.STCref | STCnothrow | STCpure | STCdisable)) { // For 'ref' to be attached to function types, and picked // up by Type.resolve(), it has to go into sc. sc = sc.push(); - sc.stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared); + sc.stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared | STCdisable); type.resolve(loc, sc, &e, &t, &s); sc = sc.pop(); } diff -r e3afd1303184 -r cd48cb899aee dmd/AnonDeclaration.d --- a/dmd/AnonDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/AnonDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -48,6 +48,8 @@ scx = scope_; scope_ = null; } + + uint dprogress_save = global.dprogress; assert(sc.parent); @@ -107,6 +109,7 @@ scope_.setNoFree(); scope_.module_.addDeferredSemantic(this); } + global.dprogress = dprogress_save; //printf("\tforward reference %p\n", this); return; } diff -r e3afd1303184 -r cd48cb899aee dmd/AssertExp.d --- a/dmd/AssertExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/AssertExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -18,8 +18,11 @@ import dmd.InvariantDeclaration; import dmd.TOK; import dmd.PREC; +import dmd.AddrExp; +import dmd.DotVarExp; import dmd.TY; import dmd.TypeClass; +import dmd.GlobalExpressions; import dmd.Module; import dmd.WANT; import dmd.FuncDeclaration; @@ -36,6 +39,7 @@ import dmd.backend.FL; import dmd.expression.Util; +import dmd.interpret.Util; import core.stdc.string; import std.string : toStringz; @@ -97,8 +101,54 @@ } override Expression interpret(InterState istate) - { - assert(false); + { + Expression e; + Expression e1; + +version (LOG) { + writef("AssertExp::interpret() %s\n", toChars()); +} + if (this.e1.op == TOKaddress) + { + // Special case: deal with compiler-inserted assert(&this, "null this") + AddrExp ade = cast(AddrExp)this.e1; + if (ade.e1.op == TOKthis && istate.localThis) + if (ade.e1.op == TOKdotvar + && (cast(DotVarExp)(istate.localThis)).e1.op == TOKthis) + return getVarExp(loc, istate, (cast(DotVarExp)(istate.localThis)).var); + else + return istate.localThis.interpret(istate); + } + if (this.e1.op == TOKthis) + { + if (istate.localThis) + return istate.localThis.interpret(istate); + } + e1 = this.e1.interpret(istate); + if (e1 is EXP_CANT_INTERPRET) + goto Lcant; + if (e1.isBool(true)) + { + } + else if (e1.isBool(false)) + { + if (msg) + { + e = msg.interpret(istate); + if (e is EXP_CANT_INTERPRET) + goto Lcant; + error("%s", e.toChars()); + } + else + error("%s failed", toChars()); + goto Lcant; + } + else + goto Lcant; + return e1; + + Lcant: + return EXP_CANT_INTERPRET; } override bool checkSideEffect(int flag) diff -r e3afd1303184 -r cd48cb899aee dmd/BinExp.d --- a/dmd/BinExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/BinExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -787,7 +787,7 @@ return e2; // Chase down rebinding of out and ref. - if (e1.op == TOKvar) + if (e1.op == TOKvar) { VarExp ve = cast(VarExp)e1; VarDeclaration v = ve.var.isVarDeclaration(); @@ -813,12 +813,15 @@ // To reduce code complexity of handling dotvar expressions, // extract the aggregate now. Expression aggregate; - if (e1.op == TOKdotvar) { + if (e1.op == TOKdotvar) + { aggregate = (cast(DotVarExp)e1).e1; // Get rid of 'this'. if (aggregate.op == TOKthis && istate.localThis) aggregate = istate.localThis; } + if (e1.op == TOKthis && istate.localThis) + e1 = istate.localThis; /* Assignment to variable of the form: * v = e2 @@ -857,7 +860,8 @@ if (e2 is EXP_CANT_INTERPRET) return e2; - addVarToInterstate(istate, v); + if (istate) + addVarToInterstate(istate, v); v.value = e2; e = Cast(type, type, post ? ev : e2); } @@ -908,16 +912,20 @@ * on the void value - to do that we'd need a VoidExp. * That's probably a good enhancement idea. */ - v.value = v.type.defaultInit(Loc(0)); + v.value = v.type.defaultInitLiteral(Loc(0)); } Expression vie = v.value; + assert(vie !is EXP_CANT_INTERPRET); if (vie.op == TOKvar) { Declaration d = (cast(VarExp)vie).var; vie = getVarExp(e1.loc, istate, d); } if (vie.op != TOKstructliteral) + { + error("Cannot assign %s=%s in CTFE", v.toChars(), vie.toChars()); return EXP_CANT_INTERPRET; + } StructLiteralExp se = cast(StructLiteralExp)vie; VarDeclaration vf = (cast(DotVarExp)e1).var.isVarDeclaration(); if (!vf) @@ -1311,10 +1319,7 @@ if (v.value.op == TOKarrayliteral) dim = (cast(ArrayLiteralExp)v.value).elements.dim; else if (v.value.op ==TOKstring) - { - error("String slice assignment is not yet supported in CTFE"); - return EXP_CANT_INTERPRET; - } + dim = (cast(StringExp)v.value).len; } else { @@ -1324,67 +1329,87 @@ int upperbound = upper ? cast(int)upper.toInteger() : dim; int lowerbound = lower ? cast(int)lower.toInteger() : 0; - ArrayLiteralExp existing; if ((cast(int)lowerbound < 0) || (upperbound > dim)) { error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound); return EXP_CANT_INTERPRET; } - if (upperbound-lowerbound != dim) + // Could either be slice assignment (v[] = e[]), + // or block assignment (v[] = val). + // For the former, we check that the lengths match. + bool isSliceAssignment = (e2.op == TOKarrayliteral) + || (e2.op == TOKstring); + size_t srclen = 0; + if (e2.op == TOKarrayliteral) + srclen = (cast(ArrayLiteralExp)e2).elements.dim; + else if (e2.op == TOKstring) + srclen = (cast(StringExp)e2).len; + if (isSliceAssignment && srclen != (upperbound - lowerbound)) { - // Only modifying part of the array. Must create a new array literal. - // If the existing array is uninitialized (this can only happen - // with static arrays), create it. - if (v.value && v.value.op == TOKarrayliteral) - existing = cast(ArrayLiteralExp)v.value; - else - { - // this can only happen with static arrays - existing = createBlockDuplicatedArrayLiteral(v.type, v.type.defaultInit(Loc(0)), dim); - } + error("Array length mismatch assigning [0..%d] to [%d..%d]", srclen, lowerbound, upperbound); + return e; } - if (e2.op == TOKarrayliteral) { // Static array assignment from literal ArrayLiteralExp ae = cast(ArrayLiteralExp)e2; - if (ae.elements.dim != (upperbound - lowerbound)) - { - error("Array length mismatch assigning [0..%d] to [%d..%d]", ae.elements.dim, lowerbound, upperbound); - return e; - } if (upperbound - lowerbound == dim) v.value = ae; else { + ArrayLiteralExp existing; + // Only modifying part of the array. Must create a new array literal. + // If the existing array is uninitialized (this can only happen + // with static arrays), create it. + if (v.value && v.value.op == TOKarrayliteral) + existing = cast(ArrayLiteralExp)v.value; + else // this can only happen with static arrays + existing = createBlockDuplicatedArrayLiteral(v.type, v.type.defaultInit(Loc(0)), dim); + // value[] = value[0..lower] ~ ae ~ value[upper..$] existing.elements = spliceElements(existing.elements, ae.elements, lowerbound); v.value = existing; } return e2; } - else if (t.nextOf().ty == e2.type.ty) - { - // Static array block assignment - if (upperbound-lowerbound ==dim) - v.value = createBlockDuplicatedArrayLiteral(v.type, e2, dim); - else - { - // value[] = value[0..lower] ~ ae ~ value[upper..$] - existing.elements = spliceElements(existing.elements, createBlockDuplicatedArrayLiteral(v.type, e2, upperbound-lowerbound).elements, lowerbound); - v.value = existing; - } - return e2; - } else if (e2.op == TOKstring) { StringExp se = cast(StringExp)e2; - // This is problematic. char[8] should be storing - // values as a string literal, not - // as an array literal. Then, for static arrays, we - // could do modifications - // in-place, with a dramatic memory and speed improvement. - error("String slice assignment is not yet supported in CTFE"); + if (upperbound-lowerbound == dim) + v.value = e2; + else + { + if (!v.value) + v.value = createBlockDuplicatedStringLiteral(se.type, cast(dchar)se.type.defaultInit(Loc(0)).toInteger(), dim, se.sz); + if (v.value.op==TOKstring) + v.value = spliceStringExp(cast(StringExp)v.value, se, lowerbound); + else + error("String slice assignment is not yet supported in CTFE"); + } + return e2; + } + else if (t.nextOf().ty == e2.type.ty) + { + // Static array block assignment + if (upperbound - lowerbound == dim) + v.value = createBlockDuplicatedArrayLiteral(v.type, e2, dim); + else + { + ArrayLiteralExp existing; + // Only modifying part of the array. Must create a new array literal. + // If the existing array is uninitialized (this can only happen + // with static arrays), create it. + if (v.value && v.value.op == TOKarrayliteral) + existing = cast(ArrayLiteralExp)v.value; + else // this can only happen with static arrays + existing = createBlockDuplicatedArrayLiteral(v.type, v.type.defaultInit(Loc(0)), dim); + // value[] = value[0..lower] ~ ae ~ value[upper..$] + existing.elements = spliceElements(existing.elements, + createBlockDuplicatedArrayLiteral(v.type, e2, upperbound-lowerbound).elements, + lowerbound); + v.value = existing; + } + return e2; } else diff -r e3afd1303184 -r cd48cb899aee dmd/CallExp.d --- a/dmd/CallExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/CallExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -9,6 +9,8 @@ import dmd.TypeFunction; import dmd.ScopeDsymbol; import dmd.CastExp; +import dmd.FuncExp; +import dmd.SymOffExp; import dmd.GlobalExpressions; import dmd.TypePointer; import dmd.ThisExp; @@ -383,6 +385,7 @@ // Create variable that will get constructed Identifier idtmp = Lexer.uniqueId("__ctmp"); VarDeclaration tmp = new VarDeclaration(loc, t1, idtmp, null); + tmp.storage_class |= STCctfe; Expression av = new DeclarationExp(loc, tmp); av = new CommaExp(loc, av, new VarExp(loc, tmp)); @@ -845,6 +848,18 @@ } e1 = e1.optimize(result); +static if (true) { + if (result & WANTinterpret) + { + Expression eresult = interpret(null); + if (eresult is EXP_CANT_INTERPRET) + return e; + if (eresult && eresult !is EXP_VOID_INTERPRET) + e = eresult; + else + error("cannot evaluate %s at compile time", toChars()); + } +} else { if (e1.op == TOK.TOKvar) { FuncDeclaration fd = (cast(VarExp)e1).var.isFuncDeclaration(); @@ -880,7 +895,7 @@ error("cannot evaluate %s at compile time", toChars()); } } - +} return e; } @@ -891,75 +906,122 @@ version (LOG) { printf("CallExp.interpret() %.*s\n", toChars()); } - if (e1.op == TOKdotvar) + Expression pthis = null; + FuncDeclaration fd = null; + Expression ecall = e1; + if (ecall.op == TOKindex) + ecall = e1.interpret(istate); + if (ecall.op == TOKdotvar && !(cast(DotVarExp)ecall).var.isFuncDeclaration()) + ecall = e1.interpret(istate); + + if (ecall.op == TOKdotvar) + { // Calling a member function + pthis = (cast(DotVarExp)e1).e1; + fd = (cast(DotVarExp)e1).var.isFuncDeclaration(); + } + else if (ecall.op == TOKvar) { - Expression pthis = (cast(DotVarExp)e1).e1; - FuncDeclaration fd = (cast(DotVarExp)e1).var.isFuncDeclaration(); - TypeFunction tf = fd ? cast(TypeFunction)fd.type : null; - if (tf) - { - // Member function call - if(pthis.op == TOKthis) - pthis = istate.localThis; - Expression eresult = fd.interpret(istate, arguments, pthis); + VarDeclaration vd = (cast(VarExp)ecall).var.isVarDeclaration(); + if (vd && vd.value) + ecall = vd.value; + else // Calling a function + fd = (cast(VarExp)e1).var.isFuncDeclaration(); + } + if (ecall.op == TOKdelegate) + { + // Calling a delegate + fd = (cast(DelegateExp)ecall).func; + pthis = (cast(DelegateExp)ecall).e1; + } + else if (ecall.op == TOKfunction) + { // Calling a delegate literal + fd = (cast(FuncExp)ecall).fd; + } + else if (ecall.op == TOKstar && (cast(PtrExp)ecall).e1.op == TOKfunction) + { // Calling a function literal + fd = (cast(FuncExp)(cast(PtrExp)ecall).e1).fd; + } + else if (ecall.op == TOKstar && (cast(PtrExp*)ecall).e1.op==TOKvar) + { // Calling a function pointer + VarDeclaration vd = (cast(VarExp)(cast(PtrExp*)ecall).e1).var.isVarDeclaration(); + if (vd && vd.value && vd.value.op == TOKsymoff) + fd = (cast(SymOffExp)vd.value).var.isFuncDeclaration(); + } + + TypeFunction tf = fd ? cast(TypeFunction)(fd.type) : null; + if (!tf) + { + // DAC: I'm not sure if this ever happens + //printf("ecall=%s %d %d\n", ecall->toChars(), ecall->op, TOKcall); + error("cannot evaluate %s at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + if (pthis && fd) + { + // Member function call + if (pthis.op == TOKthis) + pthis = istate.localThis; + else if (pthis.op == TOKcomma) + pthis = pthis.interpret(istate); + Expression eresult = fd.interpret(istate, arguments, pthis); + if (eresult) + e = eresult; + else if (fd.type.toBasetype().nextOf().ty == Tvoid && !global.errors) + e = EXP_VOID_INTERPRET; + else + error("cannot evaluate %s at compile time", toChars()); + return e; + } + else if (fd) + { // function call + +///version (DMDV2) { + BUILTIN b = fd.isBuiltin(); + if (b) + { + scope Expressions args = new Expressions(); + args.setDim(arguments.dim); + for (size_t i = 0; i < args.dim; i++) + { + auto earg = arguments[i]; + earg = earg.interpret(istate); + if (earg == EXP_CANT_INTERPRET) + return earg; + args[i] = earg; + } + e = eval_builtin(b, args); + if (!e) + e = EXP_CANT_INTERPRET; + } + else +///} + // Inline .dup + if (fd.ident == Id.adDup && arguments && arguments.dim == 2) + { + e = arguments[1]; + e = e.interpret(istate); + if (e !is EXP_CANT_INTERPRET) + { + e = expType(type, e); + } + } + else + { + Expression eresult = fd.interpret(istate, arguments); if (eresult) e = eresult; else if (fd.type.toBasetype().nextOf().ty == Tvoid && !global.errors) e = EXP_VOID_INTERPRET; else error("cannot evaluate %s at compile time", toChars()); - return e; - } - error("cannot evaluate %s at compile time", toChars()); - return EXP_CANT_INTERPRET; - } - if (e1.op == TOKvar) - { - FuncDeclaration fd = (cast(VarExp)e1).var.isFuncDeclaration(); - if (fd) - { -///version (DMDV2) { - BUILTIN b = fd.isBuiltin(); - if (b) - { - scope Expressions args = new Expressions(); - args.setDim(arguments.dim); - for (size_t i = 0; i < args.dim; i++) - { - auto earg = arguments[i]; - earg = earg.interpret(istate); - if (earg == EXP_CANT_INTERPRET) - return earg; - args[i] = earg; - } - e = eval_builtin(b, args); - if (!e) - e = EXP_CANT_INTERPRET; - } - else -///} - // Inline .dup - if (fd.ident == Id.adDup && arguments && arguments.dim == 2) - { - e = arguments[1]; - e = e.interpret(istate); - if (e !is EXP_CANT_INTERPRET) - { - e = expType(type, e); - } - } - else - { - Expression eresult = fd.interpret(istate, arguments); - if (eresult) - e = eresult; - else if (fd.type.toBasetype().nextOf().ty == Tvoid && !global.errors) - e = EXP_VOID_INTERPRET; - else - error("cannot evaluate %s at compile time", toChars()); - } } } + else + { + error("cannot evaluate %s at compile time", toChars()); + return EXP_CANT_INTERPRET; + } + return e; } diff -r e3afd1303184 -r cd48cb899aee dmd/ClassDeclaration.d --- a/dmd/ClassDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/ClassDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -363,10 +363,12 @@ Scope scx = null; if (scope_) - { sc = scope_; + { + sc = scope_; scx = scope_; // save so we don't make redundant copies - scope_ = null; + scope_ = null; } + uint dprogress_save = global.dprogress; version (IN_GCC) { methods.setDim(0); } @@ -728,21 +730,24 @@ } if (sizeok == 2) - { // semantic() failed because of forward references. - // Unwind what we did, and defer it for later - fields.setDim(0); - structsize = 0; - alignsize = 0; - structalign = 0; + { + // semantic() failed because of forward references. + // Unwind what we did, and defer it for later + fields.setDim(0); + structsize = 0; + alignsize = 0; + structalign = 0; - sc = sc.pop(); + sc = sc.pop(); - scope_ = scx ? scx : sc.clone(); - scope_.setNoFree(); - scope_.module_.addDeferredSemantic(this); + scope_ = scx ? scx : sc.clone(); + scope_.setNoFree(); + scope_.module_.addDeferredSemantic(this); + + global.dprogress = dprogress_save; - //printf("\tsemantic('%s') failed due to forward references\n", toChars()); - return; + //printf("\tsemantic('%s') failed due to forward references\n", toChars()); + return; } //printf("\tsemantic('%s') successful\n", toChars()); @@ -755,7 +760,7 @@ */ ctor = cast(CtorDeclaration)search(Loc(0), Id.ctor, 0); if (ctor && (ctor.toParent() != this || !ctor.isCtorDeclaration())) - ctor = null; + ctor = null; // dtor = (DtorDeclaration *)search(Id.dtor, 0); // if (dtor && dtor.toParent() != this) @@ -774,24 +779,25 @@ // this() { } if (!ctor && baseClass && baseClass.ctor) { - //printf("Creating default this(){} for class %s\n", toChars()); - CtorDeclaration ctor = new CtorDeclaration(loc, Loc(0), null, 0); - ctor.fbody = new CompoundStatement(Loc(0), new Statements()); - members.push(ctor); - ctor.addMember(sc, this, true); - sc = scsave; // why? What about sc.nofree? /// - sc.offset = structsize; - ctor.semantic(sc); - this.ctor = ctor; - defaultCtor = ctor; + //printf("Creating default this(){} for class %s\n", toChars()); + CtorDeclaration ctor = new CtorDeclaration(loc, Loc(0), null, 0); + ctor.fbody = new CompoundStatement(Loc(0), new Statements()); + members.push(ctor); + ctor.addMember(sc, this, true); + sc = scsave; // why? What about sc.nofree? /// + sc.offset = structsize; + ctor.semantic(sc); + this.ctor = ctor; + defaultCtor = ctor; } static if (false) { if (baseClass) - { if (!aggDelete) - aggDelete = baseClass.aggDelete; - if (!aggNew) - aggNew = baseClass.aggNew; + { + if (!aggDelete) + aggDelete = baseClass.aggDelete; + if (!aggNew) + aggNew = baseClass.aggNew; } } diff -r e3afd1303184 -r cd48cb899aee dmd/CommaExp.d --- a/dmd/CommaExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/CommaExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -6,6 +6,9 @@ import dmd.IRState; import dmd.Scope; import dmd.IntRange; +import dmd.DeclarationExp; +import dmd.VarExp; +import dmd.VarDeclaration; import dmd.Expression; import dmd.GlobalExpressions; import dmd.MATCH; @@ -113,6 +116,23 @@ Expression e; //printf("CommaExp.optimize(result = %d) %s\n", result, toChars()); + // Comma needs special treatment, because it may + // contain compiler-generated declarations. We can interpret them, but + // otherwise we must NOT attempt to constant-fold them. + // In particular, if the comma returns a temporary variable, it needs + // to be an lvalue (this is particularly important for struct constructors) + + if (result & WANTinterpret) + { + // Interpreting comma needs special treatment, because it may + // contain compiler-generated declarations. + e = interpret(null); + return (e is EXP_CANT_INTERPRET) ? this : e; + } + // Don't constant fold if it is a compiler-generated temporary. + if (e1.op == TOKdeclaration) + return this; + e1 = e1.optimize(result & WANTinterpret); e2 = e2.optimize(result); if (!e1 || e1.op == TOKint64 || e1.op == TOKfloat64 || !e1.checkSideEffect(2)) @@ -132,6 +152,21 @@ version (LOG) { printf("CommaExp.interpret() %.*s\n", toChars()); } + // If the comma returns a temporary variable, it needs to be an lvalue + // (this is particularly important for struct constructors) + if (e1.op == TOKdeclaration && e2.op == TOKvar + && (cast(DeclarationExp)e1).declaration == (cast(VarExp)e2).var) + { + VarExp ve = cast(VarExp)e2; + VarDeclaration v = ve.var.isVarDeclaration(); + if (!v.init && !v.value) + v.value = v.type.defaultInitLiteral(Loc(0)); + if (!v.value) + v.value = v.init.toExpression(); + v.value = v.value.interpret(istate); + return e2; + } + Expression e = e1.interpret(istate); if (e !is EXP_CANT_INTERPRET) e = e2.interpret(istate); diff -r e3afd1303184 -r cd48cb899aee dmd/CtorDeclaration.d --- a/dmd/CtorDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/CtorDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -53,19 +53,14 @@ override void semantic(Scope sc) { - AggregateDeclaration ad; - Type tret; - //printf("CtorDeclaration.semantic() %s\n", toChars()); - if (type) - return; - sc = sc.push(); sc.stc &= ~STCstatic; // not a static constructor parent = sc.parent; Dsymbol parent = toParent2(); - ad = parent.isAggregateDeclaration(); + Type tret; + AggregateDeclaration ad = parent.isAggregateDeclaration(); if (!ad || parent.isUnionDeclaration()) { error("constructors are only for class or struct definitions"); @@ -76,7 +71,8 @@ tret = ad.handle; assert(tret); } - type = new TypeFunction(arguments, tret, varargs, LINKd); + if (!type) + type = new TypeFunction(arguments, tret, varargs, LINKd); version (STRUCTTHISREF) { if (ad && ad.isStructDeclaration()) @@ -92,7 +88,7 @@ // Append: // return this; // to the function body - if (fbody) + if (fbody && semanticRun < PASSsemantic) { Expression e = new ThisExp(loc); Statement s = new ReturnStatement(loc, e); diff -r e3afd1303184 -r cd48cb899aee dmd/Declaration.d --- a/dmd/Declaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/Declaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -274,16 +274,6 @@ bool isStatic() { return (storage_class & STC.STCstatic) != 0; } - bool isStaticConstructor() - { - return false; - } - - bool isStaticDestructor() - { - return false; - } - bool isDelete() { return false; diff -r e3afd1303184 -r cd48cb899aee dmd/DelegateExp.d --- a/dmd/DelegateExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/DelegateExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -7,6 +7,7 @@ import dmd.UnaExp; import dmd.TypeDelegate; import dmd.FuncDeclaration; +import dmd.InterState; import dmd.MATCH; import dmd.Type; import dmd.OutBuffer; @@ -55,6 +56,14 @@ } return this; } + + Expression interpret(InterState istate) + { +version (LOG) { + printf("DelegateExp::interpret() %s\n", toChars()); +} + return this; + } override MATCH implicitConvTo(Type t) { diff -r e3afd1303184 -r cd48cb899aee dmd/DeleteDeclaration.d --- a/dmd/DeleteDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/DeleteDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -43,18 +43,17 @@ override void semantic(Scope sc) { - ClassDeclaration cd; - //printf("DeleteDeclaration.semantic()\n"); parent = sc.parent; Dsymbol parent = toParent(); - cd = parent.isClassDeclaration(); + ClassDeclaration cd = parent.isClassDeclaration(); if (!cd && !parent.isStructDeclaration()) { error("new allocators only are for class or struct definitions"); } - type = new TypeFunction(arguments, Type.tvoid, 0, LINKd); + if (!type) + type = new TypeFunction(arguments, Type.tvoid, 0, LINKd); type = type.semantic(loc, sc); assert(type.ty == Tfunction); diff -r e3afd1303184 -r cd48cb899aee dmd/Dsymbol.d --- a/dmd/Dsymbol.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/Dsymbol.d Sun Oct 17 20:56:07 2010 +0400 @@ -12,6 +12,8 @@ import dmd.Id; import dmd.Identifier; import dmd.TemplateInstance; +import dmd.SharedStaticCtorDeclaration; +import dmd.SharedStaticDtorDeclaration; import dmd.HdrGenState; import dmd.AggregateDeclaration; import dmd.ClassDeclaration; @@ -250,21 +252,34 @@ for (Dsymbol sp = sc.parent; sp; sp = sp.parent) { if (sp.isDeprecated()) - return; + goto L1; } for (; sc; sc = sc.enclosing) { if (sc.scopesym && sc.scopesym.isDeprecated()) - return; + goto L1; // If inside a StorageClassDeclaration that is deprecated if (sc.stc & STC.STCdeprecated) - return; + goto L1; } error(loc, "is deprecated"); } + + L1: + Declaration d = isDeclaration(); + if (d && d.storage_class & STCdisable) + { + if (!(sc.func && sc.func.storage_class & STCdisable)) + { + if (d.ident == Id.cpctor && d.toParent()) + d.toParent().error(loc, "is not copyable"); + else + error(loc, "is not callable"); + } + } } Module getModule() @@ -896,6 +911,8 @@ DtorDeclaration isDtorDeclaration() { return null; } StaticCtorDeclaration isStaticCtorDeclaration() { return null; } StaticDtorDeclaration isStaticDtorDeclaration() { return null; } + SharedStaticCtorDeclaration isSharedStaticCtorDeclaration() { return null; } + SharedStaticDtorDeclaration isSharedStaticDtorDeclaration() { return null; } InvariantDeclaration isInvariantDeclaration() { return null; } UnitTestDeclaration isUnitTestDeclaration() { return null; } NewDeclaration isNewDeclaration() { return null; } diff -r e3afd1303184 -r cd48cb899aee dmd/DsymbolExp.d --- a/dmd/DsymbolExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/DsymbolExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -127,7 +127,12 @@ if ((v.storage_class & STC.STCmanifest) && v.init) { e = v.init.toExpression(); - e.semantic(sc); + if (!e) + { + error("cannot make expression out of initializer for %s", v.toChars()); + e = new ErrorExp(); + } + e = e.semantic(sc); return e; } diff -r e3afd1303184 -r cd48cb899aee dmd/DtorDeclaration.d --- a/dmd/DtorDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/DtorDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -48,10 +48,11 @@ { error("destructors are only for class/struct/union definitions, not %s %s", parent.kind(), parent.toChars()); } - else if (ident == Id.dtor) + else if (ident == Id.dtor && semanticRun < PASSsemantic) ad.dtors.push(this); - type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd); + if (!type) + type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd); sc = sc.push(); sc.stc &= ~STCstatic; // not a static destructor diff -r e3afd1303184 -r cd48cb899aee dmd/EnumDeclaration.d --- a/dmd/EnumDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/EnumDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -118,6 +118,8 @@ scx = scope_; // save so we don't make redundant copies scope_ = null; } + + uint dprogress_save = global.dprogress; if (sc.stc & STC.STCdeprecated) isdeprecated = true; @@ -145,7 +147,8 @@ scope_ = scx ? scx : sc.clone(); scope_.setNoFree(); scope_.module_.addDeferredSemantic(this); - writef("\tdeferring %s\n", toChars()); + global.dprogress = dprogress_save; + //writef("\tdeferring %s\n", toChars()); return; } } @@ -160,6 +163,7 @@ } isdone = true; + global.dprogress++; type = type.semantic(loc, sc); if (isAnonymous()) diff -r e3afd1303184 -r cd48cb899aee dmd/Expression.d --- a/dmd/Expression.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/Expression.d Sun Oct 17 20:56:07 2010 +0400 @@ -323,7 +323,8 @@ { auto e = exps[i]; - e = e.syntaxCopy(); + if (e) + e = e.syntaxCopy(); a[i] = e; } } diff -r e3afd1303184 -r cd48cb899aee dmd/ForeachStatement.d --- a/dmd/ForeachStatement.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/ForeachStatement.d Sun Oct 17 20:56:07 2010 +0400 @@ -346,7 +346,7 @@ */ Identifier id = Lexer.uniqueId("__aggr"); ExpInitializer ie = new ExpInitializer(loc, new SliceExp(loc, aggr, null, null)); - VarDeclaration tmp = new VarDeclaration(loc, aggr.type.nextOf().arrayOf(), id, ie); + VarDeclaration tmp = new VarDeclaration(loc, tab.nextOf().arrayOf(), id, ie); Expression tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id.length); diff -r e3afd1303184 -r cd48cb899aee dmd/FuncDeclaration.d --- a/dmd/FuncDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/FuncDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -6,6 +6,7 @@ import dmd.AddrExp; import dmd.TryFinallyStatement; import dmd.TryCatchStatement; +import dmd.SharedStaticDtorDeclaration; import dmd.Catch; import dmd.DeclarationStatement; import dmd.StaticDtorDeclaration; @@ -20,6 +21,7 @@ import dmd.Id; import dmd.StorageClassDeclaration; import dmd.StringExp; +import dmd.PASS; import dmd.DsymbolExp; import dmd.HaltExp; import dmd.CommaExp; @@ -27,6 +29,7 @@ import dmd.IntegerExp; import dmd.ExpStatement; import dmd.CSX; +import dmd.PROT; import dmd.CompoundStatement; import dmd.LabelStatement; import dmd.ThisExp; @@ -150,19 +153,15 @@ Dsymbols parameters; // Array of VarDeclaration's for parameters DsymbolTable labtab; // statement label symbol table Declaration overnext; // next in overload list - Loc endloc; // location of closing curly bracket - int vtblIndex; // for member functions, index into vtbl[] - int naked; // !=0 if naked - int inlineAsm; // !=0 if has inline assembler + Loc endloc; // location of closing curly bracket + int vtblIndex; // for member functions, index into vtbl[] + int naked; // !=0 if naked + int inlineAsm; // !=0 if has inline assembler ILS inlineStatus; - int inlineNest; // !=0 if nested inline + int inlineNest; // !=0 if nested inline int cantInterpret; // !=0 if cannot interpret function - int semanticRun; // 1 semantic() run - // 2 semantic2() run - // 3 semantic3() started - // 4 semantic3() done - // 5 toObjFile() run - // this function's frame ptr + PASS semanticRun; + // this function's frame ptr ForeachStatement fes; // if foreach body, this is the foreach int introducing; // !=0 if 'introducing' function Type tintro; // if !=null, then this is the type @@ -231,7 +230,7 @@ inlineNest = 0; inlineAsm = 0; cantInterpret = 0; - semanticRun = 0; + semanticRun = PASSinit; version (DMDV1) { nestedFrameRef = 0; } @@ -291,7 +290,7 @@ printf("type: %p, %s\n", type, type.toChars()); } - if (semanticRun && isFuncLiteralDeclaration()) + if (semanticRun != PASSinit && isFuncLiteralDeclaration()) { /* Member functions that have return types that are * forward references can have semantic() run more than @@ -300,18 +299,35 @@ */ return; } - assert(semanticRun <= 1); - semanticRun = 1; + + parent = sc.parent; + Dsymbol parent = toParent(); + + if (semanticRun == PASSsemanticdone) + { + if (!parent.isClassDeclaration()) + return; + // need to re-run semantic() in order to set the class's vtbl[] + } + else + { + assert(semanticRun <= PASSsemantic); + semanticRun = PASSsemantic; + } + + uint dprogress_save = global.dprogress; + + foverrides.setDim(0); // reset in case semantic() is being retried for this function storage_class |= sc.stc & ~STC.STCref; - //printf("function storage_class = x%x\n", storage_class); + //printf("function storage_class = x%llx, sc->stc = x%llx\n", storage_class, sc->stc); if (!originalType) originalType = type; if (!type.deco) { sc = sc.push(); - sc.stc |= storage_class & STC.STCref; // forward refness to function type + sc.stc |= storage_class & STCref; // forward to function type type = type.semantic(loc, sc); sc = sc.pop(); @@ -387,13 +403,7 @@ size_t nparams = Parameter.dim(f.parameters); linkage = sc.linkage; - // if (!parent) - { - //parent = sc.scopesym; - parent = sc.parent; - } protection = sc.protection; - Dsymbol parent = toParent(); if (storage_class & STC.STCscope) error("functions cannot be scope"); @@ -434,7 +444,7 @@ { if (isCtorDeclaration()) { - return; + goto Ldone; } static if (false) { // Verify no constructors, destructors, etc. @@ -475,7 +485,7 @@ isInvariantDeclaration() || isUnitTestDeclaration() || isNewDeclaration() || isDelete()) error("special function not allowed in interface %s", id.toChars()); - if (fbody) + if (fbody && isVirtual()) error("function body is not abstract in interface %s", id.toChars()); } @@ -545,8 +555,10 @@ goto Ldone; } - // Find index of existing function in vtbl[] to override - vi = findVtblIndex(cd.vtbl, cd.baseClass ? cd.baseClass.vtbl.dim : 0); + /* Find index of existing function in base class's vtbl[] to override + * (the index will be the same as in cd's current vtbl[]) + */ + vi = cd.baseClass ? findVtblIndex(cd.baseClass.vtbl, cd.baseClass.vtbl.dim) : -1; switch (vi) { case -1: @@ -586,12 +598,14 @@ break; case -2: // can't determine because of fwd refs - cd.sizeok = 2; // can't finish due to forward reference - return; + cd.sizeok = 2; // can't finish due to forward reference + global.dprogress = dprogress_save; + return; default: { - FuncDeclaration fdv = cast(FuncDeclaration)cd.vtbl.data[vi]; + FuncDeclaration fdv = cast(FuncDeclaration)cd.baseClass.vtbl.data[vi]; + // This function is covariant with fdv if (fdv.isFinal()) error("cannot override final function %s", fdv.toPrettyChars()); @@ -665,6 +679,7 @@ case -2: cd.sizeok = 2; // can't finish due to forward reference + global.dprogress = dprogress_save; return; default: @@ -679,23 +694,25 @@ ti = fdv.tintro; else if (!type.equals(fdv.type)) { - /* Only need to have a tintro if the vptr - * offsets differ - */ - int offset; - if (fdv.type.nextOf().isBaseOf(type.nextOf(), &offset)) - { - ti = fdv.type; -static if (false) { - if (offset) - ti = fdv.type; - else if (type.nextOf().ty == Tclass) + /* Only need to have a tintro if the vptr + * offsets differ + */ + uint errors = global.errors; + global.gag++; // suppress printing of error messages + int offset; + int baseOf = fdv.type.nextOf().isBaseOf(type.nextOf(), &offset); + global.gag--; // suppress printing of error messages + if (errors != global.errors) { - ClassDeclaration cdn = (cast(TypeClass)type.nextOf()).sym; - if (cdn && cdn.sizeok != 1) - ti = fdv.type; - } -} + // any error in isBaseOf() is a forward reference error, so we bail out + global.errors = errors; + cd.sizeok = 2; // can't finish due to forward reference + global.dprogress = dprogress_save; + return; + } + if (baseOf) + { + ti = fdv.type; } } if (ti) @@ -717,6 +734,27 @@ } L2: ; + /* Go through all the interface bases. + * Disallow overriding any final functions in the interface(s). + */ + for (int i = 0; i < cd.interfaces_dim; i++) + { + BaseClass b = cd.interfaces[i]; + if (b.base) + { + Dsymbol s = search_function(b.base, ident); + if (s) + { + FuncDeclaration f_ = s.isFuncDeclaration(); + if (f_) + { + f_ = f_.overloadExactMatch(type); + if (f_ && f_.isFinal() && f_.prot() != PROT.PROTprivate) + error("cannot override final function %s.%s", b.base.toChars(), f_.toPrettyChars()); + } + } + } + } } else if (isOverride() && !parent.isTemplateInstance()) error("override only applies to class member functions"); @@ -807,7 +845,7 @@ } } - if (isVirtual()) + if (isVirtual() && semanticRun != PASSsemanticdone) { /* Rewrite contracts as nested functions, then call them. * Doing it as nested functions means that overriding functions @@ -863,6 +901,9 @@ } Ldone: + global.dprogress++; + semanticRun = PASSsemanticdone; + /* Save scope for possible later use (if we need the * function internals) */ @@ -904,9 +945,9 @@ //printf("\tlinkage = %d\n", sc.linkage); //printf(" sc.incontract = %d\n", sc.incontract); - if (semanticRun >= 3) - return; - semanticRun = 3; + if (semanticRun >= PASSsemantic3) + return; + semanticRun = PASSsemantic3; if (!type || type.ty != TY.Tfunction) return; @@ -1671,7 +1712,8 @@ sc2.callSuper = 0; sc2.pop(); } - semanticRun = 4; + + semanticRun = PASSsemantic3done; } // called from semantic3 @@ -1763,17 +1805,22 @@ /************************************************* * Find index of function in vtbl[0..dim] that * this function overrides. + * Prefer an exact match to a covariant one. * Returns: * -1 didn't find one * -2 can't determine because of forward references */ int findVtblIndex(Array vtbl, int dim) { + FuncDeclaration mismatch = null; + int bestvi = -1; for (int vi = 0; vi < dim; vi++) { FuncDeclaration fdv = (cast(Dsymbol)vtbl.data[vi]).isFuncDeclaration(); if (fdv && fdv.ident is ident) { + if (type.equals(fdv.type)) // if exact match + return vi; // no need to look further int cov = type.covariant(fdv.type); //printf("\tbaseclass cov = %d\n", cov); switch (cov) @@ -1782,15 +1829,12 @@ break; case 1: - return vi; + bestvi = vi; // covariant, but not identical + break; // keep looking for an exact match case 2: - //type.print(); - //fdv.type.print(); - //printf("%s %s\n", type.deco, fdv.type.deco); - error("of type %s overrides but is not covariant with %s of type %s", - type.toChars(), fdv.toPrettyChars(), fdv.type.toChars()); - break; + mismatch = fdv; // overrides, but is not covariant + break; // keep looking for an exact match case 3: return -2; // forward references @@ -1801,7 +1845,15 @@ } } } - return -1; + if (bestvi == -1 && mismatch) + { + //type.print(); + //mismatch.type.print(); + //writef("%s %s\n", type.deco, mismatch.type.deco); + error("of type %s overrides but is not covariant with %s of type %s", + type.toChars(), mismatch.toPrettyChars(), mismatch.type.toChars()); + } + return bestvi; } /**************************************************** @@ -2328,7 +2380,11 @@ printf("result is %d\n", isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration()); } - return isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration(); + Dsymbol p = toParent(); + return isMember() && + !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && + p.isClassDeclaration() && + !(p.isInterfaceDeclaration() && isFinal()); } override bool isFinal() @@ -2404,7 +2460,7 @@ } } - if (cantInterpret || semanticRun == 3) + if (cantInterpret || semanticRun == PASSsemantic3) return null; if (!fbody) @@ -2413,13 +2469,13 @@ return null; } - if (semanticRun < 3 && scope_) + if (semanticRun < PASSsemantic3 && scope_) { semantic3(scope_); if (global.errors) // if errors compiling this function return null; } - if (semanticRun < 4) + if (semanticRun < PASSsemantic3done) return null; Type tb = type.toBasetype(); @@ -2433,21 +2489,6 @@ return null; } - // Ensure there are no lazy parameters - if (tf.parameters) - { - size_t dim = Parameter.dim(tf.parameters); - for (size_t i = 0; i < dim; i++) - { - auto arg = Parameter.getNth(tf.parameters, i); - if (arg.storageClass & STClazy) - { - cantInterpret = 1; - return null; - } - } - } - scope InterState istatex = new InterState(); istatex.caller = istate; istatex.fd = this; @@ -2479,7 +2520,7 @@ Expression earg = arguments[i]; auto arg = Parameter.getNth(tf.parameters, i); - if (arg.storageClass & (STCout | STCref)) + if (arg.storageClass & (STCout | STCref | STClazy)) { } else @@ -2686,7 +2727,7 @@ if (needThis() && !hasthis) return 0; - if (inlineNest || (semanticRun < 3 && !hdrscan)) + if (inlineNest || (semanticRun < PASSsemantic3 && !hdrscan)) { version (CANINLINE_LOG) { printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun); @@ -3292,10 +3333,9 @@ return; } - if (semanticRun >= 5) // if toObjFile() already run + if (semanticRun >= PASSobj) // if toObjFile() already run return; - - semanticRun = 5; + semanticRun = PASSobj; if (!func.fbody) { @@ -3349,18 +3389,25 @@ // Pull in RTL startup code if (func.isMain()) - { objextdef("_main"); + { + objextdef("_main"); version (POSIX) { ///TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS obj_ehsections(); // initialize exception handling sections -} else { +} +version (TARGET_WINDOS) { objextdef("__acrtused_con"); } obj_includelib(libname); s.Sclass = SC.SCglobal; } else if (strcmp(s.Sident.ptr, "main".ptr) == 0 && linkage == LINK.LINKc) - s.Sclass = SC.SCglobal; - + { +version (TARGET_WINDOS) { + objextdef("__acrtused_con"); // bring in C startup code + obj_includelib("snn.lib"); // bring in C runtime library +} + s.Sclass = SCglobal; + } else if (func.isWinMain()) { objextdef("__acrtused"); @@ -3640,32 +3687,54 @@ } // If static constructor - if (isStaticConstructor()) + if (isSharedStaticCtorDeclaration()) // must come first because it derives from StaticCtorDeclaration { - elem* e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s)); + elem* e = el_una(OPucall, TYvoid, el_var(s)); + global.esharedctor = el_combine(global.esharedctor, e); + } + else if (isStaticCtorDeclaration()) + { + elem* e = el_una(OPucall, TYvoid, el_var(s)); global.ector = el_combine(global.ector, e); } // If static destructor - if (isStaticDestructor()) + if (auto f_ = isSharedStaticDtorDeclaration()) // must come first because it derives from StaticDtorDeclaration { elem* e; version (STATICCTOR) { - e = el_bin(OPER.OPcall, TYM.TYvoid, el_var(rtlsym[RTLSYM.RTLSYM_FATEXIT]), el_ptr(s)); - ector = el_combine(ector, e); + e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s)); + esharedctor = el_combine(esharedctor, e); + shareddtorcount++; +} else { + if (f_.vgate) + { + /* Increment destructor's vgate at construction time + */ + global.esharedctorgates.push(cast(void*)f_); + } + + e = el_una(OPucall, TYvoid, el_var(s)); + global.eshareddtor = el_combine(e, global.eshareddtor); +} + } + else if (auto f_ = isStaticDtorDeclaration()) + { + elem* e; + +version (STATICCTOR) { + e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s)); + global.ector = el_combine(ector, e); dtorcount++; } else { - StaticDtorDeclaration f2 = isStaticDtorDeclaration(); - assert(f2); - if (f2.vgate) - { - /* Increment destructor's vgate at construction time + if (f_.vgate) + { /* Increment destructor's vgate at construction time */ - global.ectorgates.push(cast(void*)f2); + global.ectorgates.push(cast(void*)f_); } - e = el_una(OPER.OPucall, TYM.TYvoid, el_var(s)); + e = el_una(OPucall, TYvoid, el_var(s)); global.edtor = el_combine(e, global.edtor); } } diff -r e3afd1303184 -r cd48cb899aee dmd/FuncExp.d --- a/dmd/FuncExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/FuncExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -7,6 +7,7 @@ import dmd.Loc; import dmd.Scope; import dmd.InlineCostState; +import dmd.InterState; import dmd.IRState; import dmd.HdrGenState; import dmd.FuncLiteralDeclaration; @@ -85,6 +86,15 @@ return this; } + + Expression interpret(InterState istate) + { +version (LOG) { + writef("FuncExp::interpret() %s\n", toChars()); +} + return this; + + } override void scanForNestedRef(Scope sc) { diff -r e3afd1303184 -r cd48cb899aee dmd/Global.d --- a/dmd/Global.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/Global.d Sun Oct 17 20:56:07 2010 +0400 @@ -60,6 +60,7 @@ string doc_ext = "html"; // for Ddoc generated files string ddoc_ext = "ddoc"; // for Ddoc macro include files string json_ext = "json"; + string map_ext = "map"; // for .map files string hdr_ext = "di"; // for D 'header' import files string copyright= "Copyright (c) 1999-2009 by Digital Mars"; string written = "written by Walter Bright, ported to D by community"; @@ -70,7 +71,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.039"; + string version_ = "v2.040"; Param params; uint errors; // number of errors reported so far @@ -166,6 +167,10 @@ Outbuffer objbuf; string lastmname; int count; + elem* esharedctor; + Array esharedctorgates; + elem* eshareddtor; + int shareddtorcount; // Used in backend.iasm ASM_STATE asmstate; @@ -208,6 +213,7 @@ obj_symbols_towrite = new Array(); ectorgates = new Array(); + esharedctorgates = new Array(); sdummy = new Dsymbol(); edummy = new Expression(Loc(0), TOK.init, 0); diff -r e3afd1303184 -r cd48cb899aee dmd/Id.d --- a/dmd/Id.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/Id.d Sun Oct 17 20:56:07 2010 +0400 @@ -59,6 +59,7 @@ ID( "ptr" ), ID( "funcptr" ), ID( "dollar", "__dollar" ), + ID( "ctfe", "__ctfe" ), ID( "offset" ), ID( "offsetof" ), ID( "ModuleInfo" ), @@ -150,6 +151,7 @@ ID( "safe" ), ID( "trusted" ), ID( "system" ), + ID( "disable" ), // For inline assembler ID( "___out", "out" ), @@ -296,11 +298,14 @@ ID( "isVirtualFunction" ), ID( "isAbstractFunction" ), ID( "isFinalFunction" ), + ID( "isStaticFunction" ), ID( "isRef" ), ID( "isOut" ), ID( "isLazy" ), ID( "hasMember" ), + ID( "identifier" ), ID( "getMember" ), + ID( "getOverloads" ), ID( "getVirtualFunctions" ), ID( "classInstanceSize" ), ID( "allMembers" ), diff -r e3afd1303184 -r cd48cb899aee dmd/IdentifierExp.d --- a/dmd/IdentifierExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/IdentifierExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -7,6 +7,8 @@ import dmd.TypePointer; import dmd.FuncDeclaration; import dmd.TemplateInstance; +import dmd.Id; +import dmd.VarDeclaration; import dmd.TemplateDeclaration; import dmd.TemplateExp; import dmd.DsymbolExp; @@ -132,6 +134,15 @@ return e.semantic(sc); } + + if (ident == Id.ctfe) + { + // Create the magic __ctfe bool variable + VarDeclaration vd = new VarDeclaration(loc, Type.tbool, Id.ctfe, null); + Expression e = new VarExp(loc, vd); + e = e.semantic(sc); + return e; + } error("undefined identifier %s", ident.toChars()); type = Type.terror; diff -r e3afd1303184 -r cd48cb899aee dmd/InvariantDeclaration.d --- a/dmd/InvariantDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/InvariantDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -32,23 +32,21 @@ override void semantic(Scope sc) { - AggregateDeclaration ad; - Type tret; - parent = sc.parent; Dsymbol parent = toParent(); - ad = parent.isAggregateDeclaration(); + AggregateDeclaration ad = parent.isAggregateDeclaration(); if (!ad) { error("invariants are only for struct/union/class definitions"); return; } - else if (ad.inv && ad.inv != this) + else if (ad.inv && ad.inv != this && semanticRun < PASSsemantic) { error("more than one invariant for %s", ad.toChars()); } ad.inv = this; - type = new TypeFunction(null, Type.tvoid, false, LINKd); + if (!type) + type = new TypeFunction(null, Type.tvoid, false, LINKd); sc = sc.push(); sc.stc &= ~STCstatic; // not a static invariant diff -r e3afd1303184 -r cd48cb899aee dmd/Module.d --- a/dmd/Module.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/Module.d Sun Oct 17 20:56:07 2010 +0400 @@ -8,6 +8,8 @@ import dmd.StaticDtorDeclaration; import dmd.Scope; import dmd.Id; +import dmd.SharedStaticCtorDeclaration; +import dmd.SharedStaticDtorDeclaration; import dmd.Import; import dmd.ClassDeclaration; import dmd.ModuleDeclaration; @@ -951,8 +953,12 @@ global.ector = null; global.ectorgates.setDim(0); global.edtor = null; + global.esharedctor = null; + global.esharedctorgates.setDim(0); + global.eshareddtor = null; global.etest = null; global.dtorcount = 0; + global.shareddtorcount = 0; if (doppelganger) { @@ -961,7 +967,7 @@ */ Module m = cast(Module)aimports.data[0]; assert(m); - if (m.sictor || m.sctor || m.sdtor) + if (m.sictor || m.sctor || m.sdtor || m.ssharedctor || m.sshareddtor) { Symbol* s = m.toSymbol(); //objextern(s); @@ -1057,7 +1063,7 @@ } // If coverage / static constructor / destructor / unittest calls - if (global.eictor || global.ector || global.ectorgates.dim || global.edtor || global.etest) + if (global.eictor || global.ector || global.ectorgates.dim || global.edtor || global.esharedctor || global.esharedctorgates.dim || global.eshareddtor || global.etest) { /* t will be the type of the functions generated: * extern (C) void func(); @@ -1118,6 +1124,45 @@ sdtor.Sfunc.Fstartblock = b; writefunc(sdtor); } + + if (global.esharedctor || global.esharedctorgates.dim) + { + global.localgot = null; + ssharedctor = toSymbolX("__modsharedctor", SCglobal, t, moddeco); + cstate.CSpsymtab = &ssharedctor.Sfunc.Flocsym; + + for (int i = 0; i < global.esharedctorgates.dim; i++) + { + SharedStaticDtorDeclaration f = cast(SharedStaticDtorDeclaration)global.esharedctorgates.data[i]; + + Symbol* s = f.vgate.toSymbol(); + elem* e = el_var(s); + e = el_bin(OPaddass, TYint, e, el_long(TYint, 1)); + global.esharedctor = el_combine(global.esharedctor, e); + } + + block* b = block_calloc(); + b.BC = BCret; + b.Belem = global.esharedctor; + ssharedctor.Sfunc.Fstartblock = b; + writefunc(ssharedctor); +version (STATICCTOR) { + obj_staticctor(ssharedctor, shareddtorcount, 1); +} + } + + if (global.eshareddtor) + { + global.localgot = null; + sshareddtor = toSymbolX("__modshareddtor", SCglobal, t, moddeco); + + block *b = block_calloc(); + b.BC = BCret; + b.Belem = global.eshareddtor; + sshareddtor.Sfunc.Fstartblock = b; + writefunc(sshareddtor); + } + if (global.etest) { @@ -1292,17 +1337,19 @@ * Run semantic() on deferred symbols. */ - void runDeferredSemantic() + static void runDeferredSemantic() { + if (global.dprogress == 0) + return; + if (global.nested) return; //if (deferred.dim) printf("+Module.runDeferredSemantic('%s'), len = %d\n", toChars(), deferred.dim); global.nested++; - size_t len; - auto deferred = global.deferred; + size_t len; do { global.dprogress = 0; @@ -1380,6 +1427,8 @@ Symbol* sictor; // module order independent constructor Symbol* sctor; // module constructor Symbol* sdtor; // module destructor + Symbol* ssharedctor; // module shared constructor + Symbol* sshareddtor; // module shared destructor Symbol* stest; // module unit test Symbol* sfilename; // symbol for filename @@ -1526,10 +1575,15 @@ uint offset; version (DMDV2) { - uint sizeof_ModuleInfo = 18 * PTRSIZE; + uint sizeof_ModuleInfo = 16 * PTRSIZE; } else { uint sizeof_ModuleInfo = 14 * PTRSIZE; } + + version (MODULEINFO_IS_STRUCT) {} else { + sizeof_ModuleInfo -= 2 * PTRSIZE; + } + //printf("moduleinfo size = x%x\n", sizeof_ModuleInfo); ////////////////////////////////////////////// @@ -1550,11 +1604,14 @@ void *unitTest; const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function void *ictor; - void*[4] reserved; + void *sharedctor; + void *shareddtor; + uint index; + void*[1] reserved; } */ dt_t* dt = null; - +version (MODULEINFO_IS_STRUCT) {} else { if (global.moduleinfo) dtxoff(&dt, global.moduleinfo.toVtblSymbol(), 0, TYM.TYnptr); // vtbl for ModuleInfo else @@ -1563,7 +1620,7 @@ dtdword(&dt, 0); // BUG: should be an assert() } dtdword(&dt, 0); // monitor - +} // name[] string name = toPrettyChars(); size_t namelen = name.length; @@ -1606,13 +1663,13 @@ else dtdword(&dt, 8|4); // flags (4 means MIstandalone) - if (sctor) - dtxoff(&dt, sctor, 0, TYM.TYnptr); + if (ssharedctor) + dtxoff(&dt, ssharedctor, 0, TYnptr); else dtdword(&dt, 0); - if (sdtor) - dtxoff(&dt, sdtor, 0, TYM.TYnptr); + if (sshareddtor) + dtxoff(&dt, sshareddtor, 0, TYnptr); else dtdword(&dt, 0); @@ -1635,10 +1692,19 @@ dtdword(&dt, 0); version (DMDV2) { - // void*[4] reserved; - dtdword(&dt, 0); - dtdword(&dt, 0); - dtdword(&dt, 0); + if (sctor) + dtxoff(&dt, sctor, 0, TYnptr); + else + dtdword(&dt, 0); + + if (sdtor) + dtxoff(&dt, sdtor, 0, TYnptr); + else + dtdword(&dt, 0); + + dtdword(&dt, 0); // index + + // void*[1] reserved; dtdword(&dt, 0); } ////////////////////////////////////////////// diff -r e3afd1303184 -r cd48cb899aee dmd/NewDeclaration.d --- a/dmd/NewDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/NewDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -45,20 +45,18 @@ override void semantic(Scope sc) { - ClassDeclaration cd; - Type tret; - //printf("NewDeclaration.semantic()\n"); parent = sc.parent; Dsymbol parent = toParent(); - cd = parent.isClassDeclaration(); + ClassDeclaration cd = parent.isClassDeclaration(); if (!cd && !parent.isStructDeclaration()) { error("new allocators only are for class or struct definitions"); } - tret = Type.tvoid.pointerTo(); - type = new TypeFunction(arguments, tret, varargs, LINKd); + Type tret = Type.tvoid.pointerTo(); + if (!type) + type = new TypeFunction(arguments, tret, varargs, LINKd); type = type.semantic(loc, sc); assert(type.ty == Tfunction); diff -r e3afd1303184 -r cd48cb899aee dmd/NewExp.d --- a/dmd/NewExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/NewExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -2,9 +2,11 @@ import dmd.common; import dmd.Expression; +import dmd.GlobalExpressions; import dmd.NewDeclaration; import dmd.CtorDeclaration; import dmd.ClassDeclaration; +import dmd.InterState; import dmd.Type; import dmd.OutBuffer; import dmd.PREC; @@ -31,6 +33,9 @@ import dmd.IntegerExp; import dmd.TypePointer; +import dmd.interpret.Util; +import dmd.expression.Util; + import dmd.backend.elem; import dmd.backend.TYM; import dmd.backend.SC; @@ -41,7 +46,6 @@ import dmd.backend.Util; import dmd.backend.OPER; import dmd.backend.RTLSYM; -import dmd.expression.Util; import dmd.codegen.Util; import std.string : toStringz; @@ -378,6 +382,23 @@ return this; } + + Expression interpret(InterState istate) + { +version (LOG) { + writef("NewExp::interpret() %s\n", toChars()); +} + if (newtype.ty == Tarray && arguments && arguments.dim == 1) + { + Expression lenExpr = arguments[0].interpret(istate); + if (lenExpr is EXP_CANT_INTERPRET) + return EXP_CANT_INTERPRET; + return createBlockDuplicatedArrayLiteral(newtype, newtype.defaultInitLiteral(Loc(0)), cast(uint)lenExpr.toInteger()); + } + error("Cannot interpret %s at compile time", toChars()); + return EXP_CANT_INTERPRET; + + } override Expression optimize(int result) { diff -r e3afd1303184 -r cd48cb899aee dmd/Param.d --- a/dmd/Param.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/Param.d Sun Oct 17 20:56:07 2010 +0400 @@ -18,6 +18,7 @@ bool vtls; // identify thread local variables byte symdebug; // insert debug symbolic information bool optimize; // run optimizer + bool map; // generate linker .map file bool cpu; // target CPU bool isX86_64; // generate X86_64 bit code bool isLinux; // generate code for linux @@ -101,4 +102,5 @@ string deffile; string resfile; string exefile; + string mapfile; } diff -r e3afd1303184 -r cd48cb899aee dmd/Parser.d --- a/dmd/Parser.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/Parser.d Sun Oct 17 20:56:07 2010 +0400 @@ -5,6 +5,8 @@ import dmd.PostBlitDeclaration; import dmd.FileInitExp; import dmd.LineInitExp; +import dmd.SharedStaticCtorDeclaration; +import dmd.SharedStaticDtorDeclaration; import dmd.EnumMember; import dmd.CtorDeclaration; import dmd.ShlAssignExp; @@ -481,25 +483,42 @@ break; case TOK.TOKconst: - if (peek(&token).value == TOK.TOKlparen) + if (peekNext() == TOKlparen) goto Ldeclaration; stc = STC.STCconst; goto Lstc; case TOK.TOKimmutable: - if (peek(&token).value == TOK.TOKlparen) + if (peekNext() == TOKlparen) goto Ldeclaration; stc = STC.STCimmutable; goto Lstc; case TOK.TOKshared: - if (peek(&token).value == TOK.TOKlparen) - goto Ldeclaration; - stc = STC.STCshared; - goto Lstc; - - case TOKwild: - if (peek(&token).value == TOK.TOKlparen) + { + TOK next = peekNext(); + if (next == TOKlparen) + goto Ldeclaration; + if (next == TOKstatic) + { + TOK next2 = peekNext2(); + if (next2 == TOKthis) + { + s = parseSharedStaticCtor(); + break; + } + if (next2 == TOKtilde) + { + s = parseSharedStaticDtor(); + break; + } + } + stc = STCshared; + goto Lstc; + } + + case TOKwild: + if (peekNext() == TOKlparen) goto Ldeclaration; stc = STCwild; goto Lstc; @@ -892,8 +911,11 @@ stc = STCtrusted; else if (token.ident == Id.system) stc = STCsystem; - else - error("valid attribute identifiers are @property, @safe, @trusted, @system, not @%s", token.toChars()); + else if (token.ident == Id.disable) + stc = STCdisable; + else + error("valid attribute identifiers are @property, @safe, @trusted, @system, @disable not @%s", token.toChars()); + return stc; } } @@ -1694,14 +1716,13 @@ */ StaticCtorDeclaration parseStaticCtor() { - StaticCtorDeclaration f; Loc loc = this.loc; nextToken(); check(TOKlparen); check(TOKrparen); - f = new StaticCtorDeclaration(loc, Loc(0)); + StaticCtorDeclaration f = new StaticCtorDeclaration(loc, Loc(0)); parseContracts(f); return f; } @@ -1713,7 +1734,6 @@ */ StaticDtorDeclaration parseStaticDtor() { - StaticDtorDeclaration f; Loc loc = this.loc; nextToken(); @@ -1721,7 +1741,49 @@ check(TOKlparen); check(TOKrparen); - f = new StaticDtorDeclaration(loc, Loc(0)); + StaticDtorDeclaration f = new StaticDtorDeclaration(loc, Loc(0)); + parseContracts(f); + return f; + + } + + /***************************************** + * Parse a shared static constructor definition: + * shared static this() { body } + * Current token is 'shared'. + */ + SharedStaticCtorDeclaration parseSharedStaticCtor() + { + Loc loc = this.loc; + + nextToken(); + nextToken(); + nextToken(); + check(TOKlparen); + check(TOKrparen); + + SharedStaticCtorDeclaration f = new SharedStaticCtorDeclaration(loc, Loc(0)); + parseContracts(f); + return f; + } + + /***************************************** + * Parse a shared static destructor definition: + * shared static ~this() { body } + * Current token is 'shared'. + */ + SharedStaticDtorDeclaration parseSharedStaticDtor() + { + Loc loc = this.loc; + + nextToken(); + nextToken(); + nextToken(); + check(TOKthis); + check(TOKlparen); + check(TOKrparen); + + SharedStaticDtorDeclaration f = new SharedStaticDtorDeclaration(loc, Loc(0)); parseContracts(f); return f; } diff -r e3afd1303184 -r cd48cb899aee dmd/PostBlitDeclaration.d --- a/dmd/PostBlitDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/PostBlitDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -43,7 +43,7 @@ { //writef("PostBlitDeclaration.semantic() %s\n", toChars()); //writef("ident: %s, %s, %p, %p\n", ident.toChars(), Id.dtor.toChars(), ident, Id.dtor); - //writef("stc = x%llx\n", sc.stc); + //writef("stc = x%llx\n", sc.stc); parent = sc.parent; Dsymbol parent = toParent(); StructDeclaration ad = parent.isStructDeclaration(); diff -r e3afd1303184 -r cd48cb899aee dmd/PowExp.d --- a/dmd/PowExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/PowExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -18,6 +18,7 @@ import dmd.Global; import dmd.IntegerExp; import dmd.Type; +import dmd.STC; import dmd.Lexer; import dmd.VarDeclaration; import dmd.ExpInitializer; @@ -86,25 +87,30 @@ e1.type.toBasetype().toChars(), e1.toChars(), e2.toChars()); return new ErrorExp(); } + + // Determine if we're raising to an integer power. + long intpow = 0; + if (e2.op == TOKint64 && (cast(long)e2.toInteger() == 2 || cast(long)e2.toInteger() == 3)) + intpow = e2.toInteger(); + else if (e2.op == TOKfloat64 && (e2.toReal() == cast(long)(e2.toReal()))) + intpow = cast(long)(e2.toReal()); // Deal with x^^2, x^^3 immediately, since they are of practical importance. - // Don't bother if x is a literal, since it will be constant-folded anyway. - if ( ( (e2.op == TOK.TOKint64 && (e2.toInteger() == 2 || e2.toInteger() == 3)) - || (e2.op == TOK.TOKfloat64 && (e2.toReal() == 2.0 || e2.toReal() == 3.0)) - ) && (e1.op == TOK.TOKint64 || e1.op == TOK.TOKfloat64) - ) + if (intpow == 2 || intpow == 3) { typeCombine(sc); // Replace x^^2 with (tmp = x, tmp*tmp) // Replace x^^3 with (tmp = x, tmp*tmp*tmp) Identifier idtmp = Lexer.uniqueId("__tmp"); VarDeclaration tmp = new VarDeclaration(loc, e1.type.toBasetype(), idtmp, new ExpInitializer(Loc(0), e1)); - VarExp ve = new VarExp(loc, tmp); + tmp.storage_class = STC.STCctfe; + Expression ve = new VarExp(loc, tmp); Expression ae = new DeclarationExp(loc, tmp); + /* Note that we're reusing ve. This should be ok. + */ Expression me = new MulExp(loc, ve, ve); - if ( (e2.op == TOK.TOKint64 && e2.toInteger() == 3) - || (e2.op == TOK.TOKfloat64 && e2.toReal() == 3.0)) - me = new MulExp(loc, me, ve); + if (intpow == 3) + me = new MulExp(loc, me, ve); e = new CommaExp(loc, ae, me); e = e.semantic(sc); return e; @@ -143,6 +149,10 @@ // integer powers are treated specially by std.math.pow). if (!e2.type.isintegral()) typeCombine(sc); + // In fact, if it *could* have been an integer, make it one. + if (e2.op == TOKfloat64 && intpow != 0) + e2 = new IntegerExp(loc, intpow, Type.tint64); + e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2); } e = e.semantic(sc); diff -r e3afd1303184 -r cd48cb899aee dmd/STC.d --- a/dmd/STC.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/STC.d Sun Oct 17 20:56:07 2010 +0400 @@ -44,7 +44,9 @@ STCtrusted = 0x400000000, STCsystem = 0x800000000, STCctfe = 0x1000000000, // can be used in CTFE, even if it is static + STCdisable = 0x2000000000, // for functions that are not callable } + alias STC StorageClass; import dmd.EnumUtils; diff -r e3afd1303184 -r cd48cb899aee dmd/SharedStaticCtorDeclaration.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/SharedStaticCtorDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -0,0 +1,31 @@ +module dmd.SharedStaticCtorDeclaration; + +import dmd.StaticCtorDeclaration; +import dmd.Loc; +import dmd.Dsymbol; +import dmd.OutBuffer; +import dmd.HdrGenState; +import dmd.FuncDeclaration; + +class SharedStaticCtorDeclaration : StaticCtorDeclaration +{ + this(Loc loc, Loc endloc) + { + super(loc, endloc, "_sharedStaticCtor"); + } + + Dsymbol syntaxCopy(Dsymbol s) + { + assert(!s); + SharedStaticCtorDeclaration scd = new SharedStaticCtorDeclaration(loc, endloc); + return FuncDeclaration.syntaxCopy(scd); + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + buf.writestring("shared "); + StaticCtorDeclaration.toCBuffer(buf, hgs); + } + + SharedStaticCtorDeclaration isSharedStaticCtorDeclaration() { return this; } +} \ No newline at end of file diff -r e3afd1303184 -r cd48cb899aee dmd/SharedStaticDtorDeclaration.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/SharedStaticDtorDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -0,0 +1,34 @@ +module dmd.SharedStaticDtorDeclaration; + +import dmd.StaticDtorDeclaration; +import dmd.Loc; +import dmd.Dsymbol; +import dmd.OutBuffer; +import dmd.HdrGenState; +import dmd.FuncDeclaration; + +class SharedStaticDtorDeclaration : StaticDtorDeclaration +{ + this(Loc loc, Loc endloc) + { + super(loc, endloc, "_sharedStaticDtor"); + } + + Dsymbol syntaxCopy(Dsymbol s) + { + assert(!s); + SharedStaticDtorDeclaration sdd = new SharedStaticDtorDeclaration(loc, endloc); + return FuncDeclaration.syntaxCopy(sdd); + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + if (!hgs.hdrgen) + { + buf.writestring("shared "); + StaticDtorDeclaration.toCBuffer(buf, hgs); + } + } + + SharedStaticDtorDeclaration isSharedStaticDtorDeclaration() { return this; } +} \ No newline at end of file diff -r e3afd1303184 -r cd48cb899aee dmd/StaticCtorDeclaration.d --- a/dmd/StaticCtorDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/StaticCtorDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -31,12 +31,12 @@ class StaticCtorDeclaration : FuncDeclaration { - this(Loc loc, Loc endloc) + this(Loc loc, Loc endloc, string name = "_staticCtor") { register(); super(loc, endloc, Identifier.generateId("_staticCtor"), STCstatic, null); } - + override Dsymbol syntaxCopy(Dsymbol s) { assert(!s); @@ -48,13 +48,14 @@ { //printf("StaticCtorDeclaration.semantic()\n"); - type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd); + if (!type) + type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd); /* If the static ctor appears within a template instantiation, * it could get called multiple times by the module constructors * for different modules. Thus, protect it with a gate. */ - if (inTemplateInstance()) + if (inTemplateInstance() && semanticRun < PASSsemantic) { /* Add this prefix to the function: * static int gate; @@ -64,7 +65,7 @@ */ Identifier id = Lexer.idPool("__gate"); VarDeclaration v = new VarDeclaration(Loc(0), Type.tint32, id, null); - v.storage_class = STCstatic; + v.storage_class = isSharedStaticCtorDeclaration() ? STCstatic : STCtls; Statements sa = new Statements(); Statement s = new DeclarationStatement(Loc(0), v); sa.push(s); @@ -100,11 +101,6 @@ return null; } - override bool isStaticConstructor() - { - return true; - } - override bool isVirtual() { return false; diff -r e3afd1303184 -r cd48cb899aee dmd/StaticDtorDeclaration.d --- a/dmd/StaticDtorDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/StaticDtorDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -34,10 +34,11 @@ { VarDeclaration vgate; // 'gate' variable - this(Loc loc, Loc endloc) + this(Loc loc, Loc endloc, string name = "_staticDtor") { register(); - super(loc, endloc, Identifier.generateId("_staticDtor"), STCstatic, null); + super(loc, endloc, Identifier.generateId(name), STCstatic, null); + vgate = null; } override Dsymbol syntaxCopy(Dsymbol s) @@ -49,20 +50,15 @@ override void semantic(Scope sc) { - ClassDeclaration cd; - Type tret; - - cd = sc.scopesym.isClassDeclaration(); - if (!cd) - { - } - type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd); + ClassDeclaration cd = sc.scopesym.isClassDeclaration(); + if (!type) + type = new TypeFunction(null, Type.tvoid, false, LINK.LINKd); /* If the static ctor appears within a template instantiation, * it could get called multiple times by the module constructors * for different modules. Thus, protect it with a gate. */ - if (inTemplateInstance()) + if (inTemplateInstance() && semanticRun < PASSsemantic) { /* Add this prefix to the function: * static int gate; @@ -73,7 +69,7 @@ */ Identifier id = Lexer.idPool("__gate"); VarDeclaration v = new VarDeclaration(Loc(0), Type.tint32, id, null); - v.storage_class = STCstatic; + v.storage_class = isSharedStaticDtorDeclaration() ? STCstatic : STCtls; auto sa = new Statements(); Statement s = new DeclarationStatement(Loc(0), v); sa.push(s); @@ -109,11 +105,6 @@ return null; } - override bool isStaticDestructor() - { - return true; - } - override bool isVirtual() { return false; diff -r e3afd1303184 -r cd48cb899aee dmd/StorageClassDeclaration.d --- a/dmd/StorageClassDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/StorageClassDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -113,18 +113,19 @@ { STCalias, TOKalias }, { STCout, TOKout }, { STCin, TOKin }, -/// version (DMDV2) { -/// { STCimmutable, TOKimmutable }, -/// { STCshared, TOKshared }, -/// { STCnothrow, TOKnothrow }, -/// { STCpure, TOKpure }, -/// { STCref, TOKref }, -/// { STCtls, TOKtls }, -/// { STCgshared, TOKgshared }, -/// { STCproperty, TOKat }, -/// { STCsafe, TOKat }, -/// { STCtrusted, TOKat }, -/// } +///version (DMDV2) { + { STCimmutable, TOKimmutable }, + { STCshared, TOKshared }, + { STCnothrow, TOKnothrow }, + { STCpure, TOKpure }, + { STCref, TOKref }, + { STCtls, TOKtls }, + { STCgshared, TOKgshared }, + { STCproperty, TOKat }, + { STCsafe, TOKat }, + { STCtrusted, TOKat }, + { STCdisable, TOKat }, +///} ]; for (int i = 0; i < table.length; i++) @@ -141,6 +142,8 @@ id = Id.safe; else if (stc & STCtrusted) id = Id.trusted; + else if (stc & STCdisable) + id = Id.disable; else assert(0); buf.writestring(id.toChars()); diff -r e3afd1303184 -r cd48cb899aee dmd/StructDeclaration.d --- a/dmd/StructDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/StructDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -133,6 +133,8 @@ scx = scope_; // save so we don't make redundant copies scope_ = null; } + + uint dprogress_save = global.dprogress; parent = sc.parent; type = type.semantic(loc, sc); @@ -363,25 +365,28 @@ sc2.pop(); if (sizeok == 2) - { // semantic() failed because of forward references. - // Unwind what we did, and defer it for later - fields.setDim(0); - structsize = 0; - alignsize = 0; - structalign = 0; + { + // semantic() failed because of forward references. + // Unwind what we did, and defer it for later + fields.setDim(0); + structsize = 0; + alignsize = 0; + structalign = 0; - scope_ = scx ? scx : sc.clone(); - scope_.setNoFree(); - scope_.module_.addDeferredSemantic(this); - writef("\tdeferring %s\n", toChars()); - return; + scope_ = scx ? scx : sc.clone(); + scope_.setNoFree(); + scope_.module_.addDeferredSemantic(this); + + global.dprogress = dprogress_save; + //printf("\tdeferring %s\n", toChars()); + return; } // 0 sized struct's are set to 1 byte if (structsize == 0) { - structsize = 1; - alignsize = 1; + structsize = 1; + alignsize = 1; } // Round struct size up to next alignsize boundary. @@ -600,6 +605,7 @@ { tmp = new VarDeclaration(Loc(0), type, idtmp, new VoidInitializer(Loc(0))); tmp.noauto = true; + tmp.storage_class |= STCctfe; e = new DeclarationExp(Loc(0), tmp); Expression e2; @@ -750,6 +756,7 @@ { //printf("StructDeclaration.buildPostBlit() %s\n", toChars()); Expression e = null; + StorageClass stc = STCundefined; foreach (VarDeclaration v; fields) { @@ -759,37 +766,42 @@ Type tv = v.type.toBasetype(); size_t dim = 1; while (tv.ty == TY.Tsarray) - { TypeSArray ta = cast(TypeSArray)tv; + { + TypeSArray ta = cast(TypeSArray)tv; dim *= (cast(TypeSArray)tv).dim.toInteger(); tv = tv.nextOf().toBasetype(); } if (tv.ty == TY.Tstruct) - { TypeStruct ts = cast(TypeStruct)tv; + { + TypeStruct ts = cast(TypeStruct)tv; StructDeclaration sd = ts.sym; if (sd.postblit) - { Expression ex; + { + Expression ex; + + stc |= sd.postblit.storage_class & STCdisable; - // this.v - ex = new ThisExp(Loc(0)); - ex = new DotVarExp(Loc(0), ex, v, 0); + // this.v + ex = new ThisExp(Loc(0)); + ex = new DotVarExp(Loc(0), ex, v, 0); - if (dim == 1) - { // this.v.postblit() - ex = new DotVarExp(Loc(0), ex, sd.postblit, 0); - ex = new CallExp(Loc(0), ex); - } - else - { - // Typeinfo.postblit(cast(void*)&this.v); - Expression ea = new AddrExp(Loc(0), ex); - ea = new CastExp(Loc(0), ea, Type.tvoid.pointerTo()); + if (dim == 1) + { // this.v.postblit() + ex = new DotVarExp(Loc(0), ex, sd.postblit, 0); + ex = new CallExp(Loc(0), ex); + } + else + { + // Typeinfo.postblit(cast(void*)&this.v); + Expression ea = new AddrExp(Loc(0), ex); + ea = new CastExp(Loc(0), ea, Type.tvoid.pointerTo()); - Expression et = v.type.getTypeInfo(sc); - et = new DotIdExp(Loc(0), et, Id._postblit); + Expression et = v.type.getTypeInfo(sc); + et = new DotIdExp(Loc(0), et, Id._postblit); - ex = new CallExp(Loc(0), et, ea); - } - e = Expression.combine(e, ex); // combine in forward order + ex = new CallExp(Loc(0), et, ea); + } + e = Expression.combine(e, ex); // combine in forward order } } } @@ -797,12 +809,14 @@ /* Build our own "postblit" which executes e */ if (e) - { //printf("Building __fieldPostBlit()\n"); - auto dd = new PostBlitDeclaration(Loc(0), Loc(0), Lexer.idPool("__fieldPostBlit")); - dd.fbody = new ExpStatement(Loc(0), e); - postblits.shift(dd); - members.push(dd); - dd.semantic(sc); + { + //printf("Building __fieldPostBlit()\n"); + auto dd = new PostBlitDeclaration(Loc(0), Loc(0), Lexer.idPool("__fieldPostBlit")); + dd.storage_class |= stc; + dd.fbody = new ExpStatement(Loc(0), e); + postblits.shift(dd); + members.push(dd); + dd.semantic(sc); } switch (postblits.dim) @@ -817,12 +831,14 @@ e = null; foreach(FuncDeclaration fd; postblits) { - Expression ex = new ThisExp(Loc(0)); - ex = new DotVarExp(Loc(0), ex, fd, 0); - ex = new CallExp(Loc(0), ex); - e = Expression.combine(e, ex); + Expression ex = new ThisExp(Loc(0)); + stc |= fd.storage_class & STCdisable; + ex = new DotVarExp(Loc(0), ex, fd, 0); + ex = new CallExp(Loc(0), ex); + e = Expression.combine(e, ex); } auto dd = new PostBlitDeclaration(Loc(0), Loc(0), Lexer.idPool("__aggrPostBlit")); + dd.storage_class |= stc; dd.fbody = new ExpStatement(Loc(0), e); members.push(dd); dd.semantic(sc); @@ -864,6 +880,7 @@ Type ftype = new TypeFunction(fparams, Type.tvoid, false, LINK.LINKd); fcp = new FuncDeclaration(Loc(0), Loc(0), Id.cpctor, STC.STCundefined, ftype); + fcp.storage_class |= postblit.storage_class & STCdisable; // Build *this = p; Expression e = new ThisExp(Loc(0)); diff -r e3afd1303184 -r cd48cb899aee dmd/SymOffExp.d --- a/dmd/SymOffExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/SymOffExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -2,9 +2,11 @@ import dmd.common; import dmd.Expression; +import dmd.GlobalExpressions; import dmd.Declaration; import dmd.MATCH; import dmd.Type; +import dmd.InterState; import dmd.OutBuffer; import dmd.Loc; import dmd.Scope; @@ -54,6 +56,20 @@ v.checkNestedReference(sc, loc); return this; } + + Expression interpret(InterState istate) + { +version (LOG) { + writef("SymOffExp::interpret() %s\n", toChars()); +} + if (var.isFuncDeclaration() && offset == 0) + { + return this; + } + error("Cannot interpret %s at compile time", toChars()); + return EXP_CANT_INTERPRET; + + } override void checkEscape() { diff -r e3afd1303184 -r cd48cb899aee dmd/SymbolExp.d --- a/dmd/SymbolExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/SymbolExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -8,6 +8,7 @@ import dmd.TOK; import dmd.TY; import dmd.Type; +import dmd.Id; import dmd.SymOffExp; import dmd.FuncDeclaration; import dmd.VarDeclaration; @@ -53,6 +54,12 @@ error("need 'this' to access member %s", toChars()); return el_long(TYM.TYint, 0); } + + /* The magic variable __ctfe is always false at runtime + */ + if (op == TOKvar && v && v.ident == Id.ctfe) + return el_long(type.totym(), 0); + s = var.toSymbol(); fd = null; if (var.toParent2()) diff -r e3afd1303184 -r cd48cb899aee dmd/TemplateDeclaration.d --- a/dmd/TemplateDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/TemplateDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -183,7 +183,8 @@ override void semantic(Scope sc) { version (LOG) { - printf("TemplateDeclaration.semantic(this = %p, id = '%s')\n", this, ident.toChars()); + writef("TemplateDeclaration.semantic(this = %p, id = '%s')\n", this, ident.toChars()); + writef("sc.stc = %llx\n", sc.stc); } if (semanticRun) return; // semantic() already run @@ -703,7 +704,9 @@ printf("\tfarg[%d] is %s, type is %s\n", i, e.toChars(), e.type.toChars()); } printf("fd = %s\n", fd.toChars()); - printf("fd.type = %p\n", fd.type); + printf("fd.type = %s\n", fd.type.toChars()); + if (ethis) + printf("ethis.type = %s\n", ethis.type.toChars()); } assert(cast(size_t)cast(void*)scope_ > 0x10000); @@ -875,9 +878,9 @@ L2: version (DMDV2) { - // Match 'ethis' to any TemplateThisParameter's if (ethis) { + // Match 'ethis' to any TemplateThisParameter's for (size_t i = 0; i < parameters.dim; i++) { auto tp2 = parameters[i]; @@ -894,6 +897,35 @@ match = m; // pick worst match } } + + // Match attributes of ethis against attributes of fd + if (fd.type) + { + Type tthis = ethis.type; + MOD mod = fd.type.mod; + StorageClass stc = scope_.stc; + if (stc & (STCshared | STCsynchronized)) + mod |= MODshared; + if (stc & STCimmutable) + mod |= MODimmutable; + if (stc & STCconst) + mod |= MODconst; + if (stc & STCwild) + mod |= MODwild; + // Fix mod + if (mod & MODimmutable) + mod = MODimmutable; + if (mod & MODconst) + mod &= ~STCwild; + if (tthis.mod != mod) + { + if (!MODimplicitConv(tthis.mod, mod)) + goto Lnomatch; + if (MATCHconst < match) + match = MATCHconst; + } + } + } } @@ -1050,8 +1082,8 @@ */ for (size_t i = nargsi; i < dedargs.dim; i++) { - auto tp2 = parameters[i]; - //printf("tp2[%d] = %s\n", i, tp2.ident.toChars()); + auto tparam = parameters[i]; + //printf("tparam[%d] = %s\n", i, tparam.ident.toChars()); /* For T:T*, the dedargs is the T*, dedtypes is the T * But for function templates, we really need them to match */ @@ -1064,30 +1096,39 @@ { if (oded) { - if (tp2.specialization()) + if (tparam.specialization()) { /* The specialization can work as long as afterwards * the oded == oarg */ Declaration sparam; dedargs[i] = oded; - MATCH m2 = tp2.matchArg(paramscope, dedargs, i, parameters, dedtypes, &sparam, 0); + MATCH m2 = tparam.matchArg(paramscope, dedargs, i, parameters, dedtypes, &sparam, 0); //printf("m2 = %d\n", m2); if (!m2) goto Lnomatch; if (m2 < match) match = m2; // pick worst match if (dedtypes[i] !is oded) - error("specialization not allowed for deduced parameter %s", tp2.ident.toChars()); + error("specialization not allowed for deduced parameter %s", tparam.ident.toChars()); } } else { - oded = tp2.defaultArg(loc, paramscope); if (!oded) - goto Lnomatch; + { + if (tp && // if tuple parameter and + fptupindex < 0 && // tuple parameter was not in function parameter list and + nargsi == dedargs.dim - 1) // we're one argument short (i.e. no tuple argument) + { + // make tuple argument an empty tuple + oded = new Tuple(); + } + else + goto Lnomatch; + } } - declareParameter(paramscope, tp2, oded); + declareParameter(paramscope, tparam, oded); dedargs[i] = oded; } } @@ -1169,6 +1210,7 @@ printf("\t%s %s\n", arg.type.toChars(), arg.toChars()); //printf("\tty = %d\n", arg.type.ty); } + printf("stc = %llx\n", scope_.stc); } for (TemplateDeclaration td = this; td; td = td.overnext) diff -r e3afd1303184 -r cd48cb899aee dmd/TraitsExp.d --- a/dmd/TraitsExp.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/TraitsExp.d Sun Oct 17 20:56:07 2010 +0400 @@ -39,37 +39,35 @@ /************************************************ * Delegate to be passed to overloadApply() that looks - * for virtual functions. + * for functions matching a trait. */ -struct Pvirtuals +struct Ptrait { Expression e1; - Expressions exps; + Expressions exps; // collected results + Identifier ident; // which trait we're looking for bool visit(FuncDeclaration f) { - Pvirtuals* p = &this; + if (ident == Id.getVirtualFunctions && !f.isVirtual()) + return false; - if (f.isVirtual()) - { - Expression e; + Expression e; - if (p.e1.op == TOKdotvar) - { - DotVarExp dve = cast(DotVarExp)p.e1; - e = new DotVarExp(Loc(0), dve.e1, f); - } - else - e = new DsymbolExp(Loc(0), f); - p.exps.push(e); + if (e1.op == TOKdotvar) + { + DotVarExp dve = cast(DotVarExp)e1; + e = new DotVarExp(Loc(0), dve.e1, f); } + else + e = new DsymbolExp(Loc(0), f); + exps.push(e); + return false; } } - - class TraitsExp : Expression { Identifier ident; @@ -97,7 +95,6 @@ if (ident != Id.compiles && ident != Id.isSame) TemplateInstance.semanticTiargs(loc, sc, args, 1); size_t dim = args ? args.dim : 0; - Object o; Declaration d; FuncDeclaration f; @@ -180,6 +177,10 @@ mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isFinal()})); } //version(DMDV2) { + else if (ident == Id.isStaticFunction) + { + mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && !f.needThis()})); + } else if (ident == Id.isRef) { mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.isRef()})); @@ -192,14 +193,30 @@ { mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.storage_class & STClazy})); } + else if (ident == Id.identifier) + { + // Get identifier for symbol as a string literal + if (dim != 1) + goto Ldimerror; + auto o = args[0]; + Dsymbol s = getDsymbol(o); + if (!s || !s.ident) + { + error("argument %s has no identifier", ident.toChars()); ///< CHANGED o to ident!!! + goto Lfalse; + } + StringExp se = new StringExp(loc, s.ident.toChars()); + return se.semantic(sc); + } //} else if (ident == Id.hasMember || ident == Id.getMember || + ident == Id.getOverloads || ident == Id.getVirtualFunctions) { if (dim != 2) goto Ldimerror; - auto o_ = args[0]; + auto o = args[0]; Expression e = isExpression(args[1]); if (!e) { error("expression expected as second argument of __traits %s", ident.toChars()); @@ -218,9 +235,9 @@ } Identifier id = Lexer.idPool(fromStringz(cast(char*)se.string_)); - Type t = isType(o_); - e = isExpression(o_); - Dsymbol s = isDsymbol(o_); + Type t = isType(o); + e = isExpression(o); + Dsymbol s = isDsymbol(o); if (t) e = typeDotIdExp(loc, t, id); else if (e) @@ -251,7 +268,7 @@ e = e.semantic(sc); return e; } - else if (ident == Id.getVirtualFunctions) + else if (ident == Id.getVirtualFunctions || ident == Id.getOverloads) { uint errors = global.errors; Expression ex = e; @@ -259,7 +276,7 @@ if (errors < global.errors) error("%s cannot be resolved", ex.toChars()); - /* Create tuple of virtual function overloads of e + /* Create tuple of virtual function overloads of e */ //e.dump(0); Expressions exps = new Expressions(); @@ -277,9 +294,10 @@ else f_ = null; - Pvirtuals p; + Ptrait p; p.exps = exps; p.e1 = e; + p.ident = ident; overloadApply(f_, p); TupleExp tup = new TupleExp(loc, exps); @@ -292,8 +310,8 @@ { if (dim != 1) goto Ldimerror; - Object o_ = args[0]; - Dsymbol s = getDsymbol(o_); + Object o = args[0]; + Dsymbol s = getDsymbol(o); ClassDeclaration cd; if (!s || (cd = s.isClassDeclaration()) is null) { @@ -306,8 +324,8 @@ { if (dim != 1) goto Ldimerror; - Object o_ = args[0]; - Dsymbol s = getDsymbol(o_); + Object o = args[0]; + Dsymbol s = getDsymbol(o); ScopeDsymbol sd; if (!s) { @@ -364,13 +382,13 @@ goto Lfalse; for (size_t i = 0; i < dim; i++) - { Object o_ = args[i]; + { Object o = args[i]; Expression e; uint errors = global.errors; global.gag++; - Type t = isType(o_); + Type t = isType(o); if (t) { Dsymbol s; t.resolve(loc, sc, &e, &t, &s); @@ -441,15 +459,17 @@ goto Lfalse; } else - { error("unrecognized trait %s", ident.toChars()); + { + error("unrecognized trait %s", ident.toChars()); goto Lfalse; } return null; -Lnottype: - error("%s is not a type", o/*.toChars()*/); // BUG: o is Object, no member toChars() - goto Lfalse; +// Not used +//Lnottype: +// error("%s is not a type", o.toChars()); +// goto Lfalse; Ldimerror: error("wrong number of arguments %d", dim); diff -r e3afd1303184 -r cd48cb899aee dmd/TypeAArray.d --- a/dmd/TypeAArray.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/TypeAArray.d Sun Oct 17 20:56:07 2010 +0400 @@ -10,6 +10,8 @@ import dmd.Scope; import dmd.StructDeclaration; import dmd.Loc; +import dmd.DotTemplateInstanceExp; +import dmd.IdentifierExp; import dmd.Global; import dmd.Dsymbol; import dmd.Type; @@ -169,12 +171,18 @@ * But the instantiation can fail if it is a template specialization field * which has Tident's instead of real types. */ - TemplateInstance ti = new TemplateInstance(loc, Id.AssociativeArray); Objects tiargs = new Objects(); tiargs.push(index); tiargs.push(next); - ti.tiargs = tiargs; - + + // Create .AssociativeArray!(index, next) + DotTemplateInstanceExp dti = new DotTemplateInstanceExp(loc, + new IdentifierExp(loc, Id.empty), + Id.AssociativeArray, + tiargs); + dti.semantic(sc); + TemplateInstance ti = dti.ti; + ti.semantic(sc); ti.semantic2(sc); ti.semantic3(sc); diff -r e3afd1303184 -r cd48cb899aee dmd/TypeEnum.d --- a/dmd/TypeEnum.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/TypeEnum.d Sun Oct 17 20:56:07 2010 +0400 @@ -242,7 +242,17 @@ { if (sym.scope_) { - sym.semantic(null); // attempt to resolve forward reference + // Enum is forward referenced. We don't need to resolve the whole thing, + // just the base type + if (sym.memtype) + { + sym.memtype = sym.memtype.semantic(sym.loc, sym.scope_); + } + else + { + if (!sym.isAnonymous()) + sym.memtype = Type.tint32; + } } if (!sym.memtype) { diff -r e3afd1303184 -r cd48cb899aee dmd/UnitTestDeclaration.d --- a/dmd/UnitTestDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/UnitTestDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -48,7 +48,8 @@ { if (global.params.useUnitTests) { - type = new TypeFunction(null, Type.tvoid, false, LINKd); + if (!type) + type = new TypeFunction(null, Type.tvoid, false, LINKd); Scope sc2 = sc.push(); sc2.linkage = LINK.LINKd; FuncDeclaration.semantic(sc2); diff -r e3afd1303184 -r cd48cb899aee dmd/Util.d --- a/dmd/Util.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/Util.d Sun Oct 17 20:56:07 2010 +0400 @@ -559,6 +559,7 @@ " -Llinkerflag pass linkerflag to link\n" " -lib generate library rather than object files\n" " -man open web browser on manual page\n" +" -map generate linker .map file\n" " -noboundscheck turns off array bounds checking for all functions\n" " -nofloat do not emit reference to floating point\n" " -O optimize\n" @@ -758,11 +759,12 @@ } cmdbuf.writeByte(','); - if (global.params.run) + + if (global.params.mapfile) + cmdbuf.writestring(global.params.mapfile); + else if (global.params.run) cmdbuf.writestring("nul"); -// if (mapfile) -// cmdbuf.writestring(output); cmdbuf.writeByte(','); for (i = 0; i < global.params.libfiles.dim; i++) @@ -793,9 +795,10 @@ writeFilename(cmdbuf, global.params.resfile); } + if (global.params.map || global.params.mapfile) + cmdbuf.writestring("/m"); + static if (false) { - if (mapfile) - cmdbuf.writestring("/m"); if (debuginfo) cmdbuf.writestring("/li"); if (codeview) @@ -867,53 +870,81 @@ argv.push(cast(void *)cast(char*)"-o"); if (global.params.exefile) { - argv.push(cast(void*)toStringz(global.params.exefile)); + argv.push(cast(void*)toStringz(global.params.exefile)); } else - { // Generate exe file name from first obj name - string n = (cast(String)global.params.objfiles.data[0]).str; - n = FileName.name(n); - string e = FileName.ext(n); - string ex = e ? n[0..$-(e.length+1)] : "a.out"; + { + // Generate exe file name from first obj name + string n = (cast(String)global.params.objfiles.data[0]).str; + n = FileName.name(n); + string e = FileName.ext(n); + string ex = e ? n[0..$-(e.length+1)] : "a.out"; - argv.push(cast(void*)toStringz(ex)); - global.params.exefile = ex; + argv.push(cast(void*)toStringz(ex)); + global.params.exefile = ex; } // Make sure path to exe file exists - { string p = FileName.path(global.params.exefile); - FileName.ensurePathExists(p); + { + string p = FileName.path(global.params.exefile); + FileName.ensurePathExists(p); } if (global.params.symdebug) - argv.push(cast(void *)cast(char*)"-g"); + argv.push(cast(void*)"-g".ptr); if (global.params.isX86_64) - argv.push(cast(void *)cast(char*)"-m64"); + argv.push(cast(void*)"-m64".ptr); else - argv.push(cast(void *)cast(char*)"-m32"); + argv.push(cast(void*)"-m32".ptr); + + if (global.params.map || global.params.mapfile) + { + argv.push(cast(void*)"-Xlinker".ptr); +version (__APPLE__) { + argv.push(cast(void*)"-map".ptr); +} else { + argv.push(cast(void *)"-Map".ptr); +} + if (!global.params.mapfile) + { + size_t elen = global.params.exefile.length; + size_t extlen = global.map_ext.length; + size_t mlen = elen + 1 + extlen; + char* m = cast(char*)GC.malloc(mlen + 1); + memcpy(m, global.params.exefile.ptr, elen); + m[elen] = '.'; + memcpy(m + elen + 1, global.map_ext.ptr, extlen); + m[mlen] = 0; + global.params.mapfile = cast(string)m[0..mlen]; + } + argv.push(cast(void*)"-Xlinker".ptr); + argv.push(global.params.mapfile.ptr); + } if (0 && global.params.exefile) { - /* This switch enables what is known as 'smart linking' - * in the Windows world, where unreferenced sections - * are removed from the executable. It eliminates unreferenced - * functions, essentially making a 'library' out of a module. - * Although it is documented to work with ld version 2.13, - * in practice it does not, but just seems to be ignored. - * Thomas Kuehne has verified that it works with ld 2.16.1. - * BUG: disabled because it causes exception handling to fail - */ - argv.push(cast(void *)cast(char*)"-Xlinker"); - argv.push(cast(void *)cast(char*)"--gc-sections"); + /* This switch enables what is known as 'smart linking' + * in the Windows world, where unreferenced sections + * are removed from the executable. It eliminates unreferenced + * functions, essentially making a 'library' out of a module. + * Although it is documented to work with ld version 2.13, + * in practice it does not, but just seems to be ignored. + * Thomas Kuehne has verified that it works with ld 2.16.1. + * BUG: disabled because it causes exception handling to fail + * because EH sections are "unreferenced" and elided + */ + argv.push(cast(void *)"-Xlinker".ptr); + argv.push(cast(void *)"--gc-sections".ptr); } for (i = 0; i < global.params.linkswitches.dim; i++) - { char *p = cast(char *)global.params.linkswitches.data[i]; - if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l')) - // Don't need -Xlinker if switch starts with -l - argv.push(cast(void *)cast(char*)"-Xlinker"); - argv.push(cast(void *) p); + { + char* p = cast(char*)global.params.linkswitches.data[i]; + if (!p || !p[0] || !(p[0] == '-' && p[1] == 'l')) + // Don't need -Xlinker if switch starts with -l + argv.push(cast(void *)"-Xlinker".ptr); + argv.push(cast(void*)p); } /* Add each library, prefixing it with "-l". @@ -925,58 +956,59 @@ * 4. standard libraries. */ for (i = 0; i < global.params.libfiles.dim; i++) - { char *p = cast(char *)global.params.libfiles.data[i]; - size_t plen = strlen(p); - if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a') - argv.push(cast(void *)p); - else - { - char *s = cast(char *)GC.malloc(plen + 3); - s[0] = '-'; - s[1] = 'l'; - memcpy(s + 2, p, plen + 1); - argv.push(cast(void *)s); - } + { + char* p = cast(char*)global.params.libfiles.data[i]; + size_t plen = strlen(p); + if (plen > 2 && p[plen - 2] == '.' && p[plen -1] == 'a') + argv.push(cast(void *)p); + else + { + char *s = cast(char *)GC.malloc(plen + 3); + s[0] = '-'; + s[1] = 'l'; + memcpy(s + 2, p, plen + 1); + argv.push(cast(void *)s); + } } /* Standard libraries must go after user specified libraries * passed with -l. */ - const char *libname = (global.params.symdebug) + const char* libname = (global.params.symdebug) ? global.params.debuglibname : global.params.defaultlibname; - char *buf = cast(char *)GC.malloc(2 + strlen(libname) + 1); + char* buf = cast(char*)GC.malloc(2 + strlen(libname) + 1); strcpy(buf, "-l"); strcpy(buf + 2, libname); argv.push(cast(void *)buf); // turns into /usr/lib/libphobos2.a // argv.push((void *)"-ldruntime"); - argv.push(cast(void *)cast(char*)"-lpthread"); - argv.push(cast(void *)cast(char*)"-lm"); + argv.push(cast(void *)"-lpthread".ptr); + argv.push(cast(void *)"-lm".ptr); if (!global.params.quiet || global.params.verbose) { - // Print it - for (i = 0; i < argv.dim; i++) - printf("%s ", cast(char *)argv.data[i]); - printf("\n"); - fflush(stdout); + // Print it + for (i = 0; i < argv.dim; i++) + printf("%s ", cast(char *)argv.data[i]); + printf("\n"); + fflush(stdout); } argv.push(null); childpid = fork(); if (childpid == 0) { - execvp(cast(char *)argv.data[0], cast(char **)argv.data); - perror(cast(char *)argv.data[0]); // failed to execute - return -1; + execvp(cast(char *)argv.data[0], cast(char **)argv.data); + perror(cast(char *)argv.data[0]); // failed to execute + return -1; } waitpid(childpid, &status, 0); status=WEXITSTATUS(status); if (status) - printf("--- errorlevel %d\n", status); + printf("--- errorlevel %d\n", status); return status; } else { diff -r e3afd1303184 -r cd48cb899aee dmd/VarDeclaration.d --- a/dmd/VarDeclaration.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/VarDeclaration.d Sun Oct 17 20:56:07 2010 +0400 @@ -464,272 +464,320 @@ (!(storage_class & (STC.STCfield | STC.STCin | STC.STCforeach | STC.STCparameter)) || (storage_class & STC.STCout)) && type.size() != 0) { - // Provide a default initializer - //printf("Providing default initializer for '%s'\n", toChars()); - if (type.ty == TY.Tstruct && - (cast(TypeStruct)type).sym.zeroInit) - { /* If a struct is all zeros, as a special case - * set it's initializer to the integer 0. - * In AssignExp.toElem(), we check for this and issue - * a memset() to initialize the struct. - * Must do same check in interpreter. - */ - Expression e = new IntegerExp(loc, 0, Type.tint32); - Expression e1; - e1 = new VarExp(loc, this); - e = new AssignExp(loc, e1, e); - e.op = TOK.TOKconstruct; - e.type = e1.type; // don't type check this, it would fail - init = new ExpInitializer(loc, e); - return; - } - else if (type.ty == TY.Ttypedef) - { TypeTypedef td = cast(TypeTypedef)type; - if (td.sym.init) - { init = td.sym.init; - ExpInitializer ie = init.isExpInitializer(); - if (ie) - // Make copy so we can modify it - init = new ExpInitializer(ie.loc, ie.exp); + // Provide a default initializer + //printf("Providing default initializer for '%s'\n", toChars()); + if (type.ty == TY.Tstruct && + (cast(TypeStruct)type).sym.zeroInit) + { /* If a struct is all zeros, as a special case + * set it's initializer to the integer 0. + * In AssignExp.toElem(), we check for this and issue + * a memset() to initialize the struct. + * Must do same check in interpreter. + */ + Expression e = new IntegerExp(loc, 0, Type.tint32); + Expression e1; + e1 = new VarExp(loc, this); + e = new AssignExp(loc, e1, e); + e.op = TOK.TOKconstruct; + e.type = e1.type; // don't type check this, it would fail + init = new ExpInitializer(loc, e); + return; + } + else if (type.ty == TY.Ttypedef) + { + TypeTypedef td = cast(TypeTypedef)type; + if (td.sym.init) + { + init = td.sym.init; + ExpInitializer ie = init.isExpInitializer(); + if (ie) + // Make copy so we can modify it + init = new ExpInitializer(ie.loc, ie.exp); + } + else + init = getExpInitializer(); } else - init = getExpInitializer(); - } - else - { - init = getExpInitializer(); - } - // Default initializer is always a blit - op = TOK.TOKblit; + { + init = getExpInitializer(); + } + // Default initializer is always a blit + op = TOK.TOKblit; } if (init) { - sc = sc.push(); - sc.stc &= ~(STC.STC_TYPECTOR | STC.STCpure | STC.STCnothrow | STC.STCref); - - ArrayInitializer ai = init.isArrayInitializer(); - if (ai && tb.ty == TY.Taarray) - { - Expression e = ai.toAssocArrayLiteral(); - init = new ExpInitializer(e.loc, e); - } - - StructInitializer si = init.isStructInitializer(); - ExpInitializer ei = init.isExpInitializer(); - - // See if initializer is a NewExp that can be allocated on the stack - if (ei && isScope() && ei.exp.op == TOK.TOKnew) - { NewExp ne = cast(NewExp)ei.exp; - if (!(ne.newargs && ne.newargs.dim)) - { ne.onstack = 1; - onstack = 1; - if (type.isBaseOf(ne.newtype.semantic(loc, sc), null)) - onstack = 2; - } - } + sc = sc.push(); + sc.stc &= ~(STC.STC_TYPECTOR | STC.STCpure | STC.STCnothrow | STC.STCref | STCdisable); - // If inside function, there is no semantic3() call - if (sc.func) - { - // If local variable, use AssignExp to handle all the various - // possibilities. - if (fd && - !(storage_class & (STC.STCmanifest | STC.STCstatic | STC.STCtls | STC.STCgshared | STC.STCextern)) && - !init.isVoidInitializer()) - { - //printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars()); - if (!ei) + ArrayInitializer ai = init.isArrayInitializer(); + if (ai && tb.ty == TY.Taarray) { - Expression e = init.toExpression(); - if (!e) - { - init = init.semantic(sc, type); - e = init.toExpression(); - if (!e) - { error("is not a static and cannot have static initializer"); - return; - } - } - ei = new ExpInitializer(init.loc, e); - init = ei; + Expression e = ai.toAssocArrayLiteral(); + init = new ExpInitializer(e.loc, e); } - Expression e1 = new VarExp(loc, this); + StructInitializer si = init.isStructInitializer(); + ExpInitializer ei = init.isExpInitializer(); - Type t = type.toBasetype(); - if (t.ty == TY.Tsarray && !(storage_class & (STC.STCref | STC.STCout))) - { - ei.exp = ei.exp.semantic(sc); - if (!ei.exp.implicitConvTo(type)) - { - int dim = cast(int)(cast(TypeSArray)t).dim.toInteger(); /// - // If multidimensional static array, treat as one large array - while (1) - { - t = t.nextOf().toBasetype(); - if (t.ty != TY.Tsarray) - break; - dim *= (cast(TypeSArray)t).dim.toInteger(); - e1.type = new TypeSArray(t.nextOf(), new IntegerExp(Loc(0), dim, Type.tindex)); + // See if initializer is a NewExp that can be allocated on the stack + if (ei && isScope() && ei.exp.op == TOK.TOKnew) + { NewExp ne = cast(NewExp)ei.exp; + if (!(ne.newargs && ne.newargs.dim)) + { ne.onstack = 1; + onstack = 1; + if (type.isBaseOf(ne.newtype.semantic(loc, sc), null)) + onstack = 2; } - } - e1 = new SliceExp(loc, e1, null, null); } - else if (t.ty == TY.Tstruct) + + // If inside function, there is no semantic3() call + if (sc.func) { - ei.exp = ei.exp.semantic(sc); - ei.exp = resolveProperties(sc, ei.exp); - StructDeclaration sd = (cast(TypeStruct)t).sym; -version (DMDV2) -{ - /* Look to see if initializer is a call to the constructor - */ - if (sd.ctor && // there are constructors - ei.exp.type.ty == TY.Tstruct && // rvalue is the same struct - (cast(TypeStruct)ei.exp.type).sym == sd && - ei.exp.op == TOK.TOKstar) + // If local variable, use AssignExp to handle all the various + // possibilities. + if (fd && + !(storage_class & (STC.STCmanifest | STC.STCstatic | STC.STCtls | STC.STCgshared | STC.STCextern)) && + !init.isVoidInitializer()) { - /* Look for form of constructor call which is: - * *__ctmp.ctor(arguments...) - */ - PtrExp pe = cast(PtrExp)ei.exp; - if (pe.e1.op == TOK.TOKcall) - { CallExp ce = cast(CallExp)pe.e1; - if (ce.e1.op == TOK.TOKdotvar) - { DotVarExp dve = cast(DotVarExp)ce.e1; - if (dve.var.isCtorDeclaration()) - { /* It's a constructor call, currently constructing - * a temporary __ctmp. - */ - /* Before calling the constructor, initialize - * variable with a bit copy of the default - * initializer - */ - Expression e = new AssignExp(loc, new VarExp(loc, this), t.defaultInit(loc)); - e.op = TOK.TOKblit; - e.type = t; - ei.exp = new CommaExp(loc, e, ei.exp); - - /* Replace __ctmp being constructed with e1 - */ - dve.e1 = e1; + //printf("fd = '%s', var = '%s'\n", fd.toChars(), toChars()); + if (!ei) + { + Expression e = init.toExpression(); + if (!e) + { + init = init.semantic(sc, type); + e = init.toExpression(); + if (!e) + { error("is not a static and cannot have static initializer"); return; } } - } + ei = new ExpInitializer(init.loc, e); + init = ei; } -} - if (!ei.exp.implicitConvTo(type)) + + Expression e1 = new VarExp(loc, this); + + Type t = type.toBasetype(); + if (t.ty == TY.Tsarray && !(storage_class & (STC.STCref | STC.STCout))) { - Type ti = ei.exp.type.toBasetype(); - // Look for constructor first - if (sd.ctor && - /* Initializing with the same type is done differently - */ - !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc))) + ei.exp = ei.exp.semantic(sc); + if (!ei.exp.implicitConvTo(type)) + { + int dim = cast(int)(cast(TypeSArray)t).dim.toInteger(); /// + // If multidimensional static array, treat as one large array + while (1) + { + t = t.nextOf().toBasetype(); + if (t.ty != TY.Tsarray) + break; + dim *= (cast(TypeSArray)t).dim.toInteger(); + e1.type = new TypeSArray(t.nextOf(), new IntegerExp(Loc(0), dim, Type.tindex)); + } + } + e1 = new SliceExp(loc, e1, null, null); + } + else if (t.ty == TY.Tstruct) + { + ei.exp = ei.exp.semantic(sc); + ei.exp = resolveProperties(sc, ei.exp); + StructDeclaration sd = (cast(TypeStruct)t).sym; + version (DMDV2) + { + /* Look to see if initializer is a call to the constructor + */ + if (sd.ctor && // there are constructors + ei.exp.type.ty == TY.Tstruct && // rvalue is the same struct + (cast(TypeStruct)ei.exp.type).sym == sd && + ei.exp.op == TOK.TOKstar) { - // Rewrite as e1.ctor(arguments) - Expression ector = new DotIdExp(loc, e1, Id.ctor); - ei.exp = new CallExp(loc, ector, ei.exp); - } - else - /* Look for opCall - * See bugzilla 2702 for more discussion + /* Look for form of constructor call which is: + * *__ctmp.ctor(arguments...) */ + PtrExp pe = cast(PtrExp)ei.exp; + if (pe.e1.op == TOK.TOKcall) + { CallExp ce = cast(CallExp)pe.e1; + if (ce.e1.op == TOK.TOKdotvar) + { DotVarExp dve = cast(DotVarExp)ce.e1; + if (dve.var.isCtorDeclaration()) + { /* It's a constructor call, currently constructing + * a temporary __ctmp. + */ + /* Before calling the constructor, initialize + * variable with a bit copy of the default + * initializer + */ + Expression e = new AssignExp(loc, new VarExp(loc, this), t.defaultInit(loc)); + e.op = TOK.TOKblit; + e.type = t; + ei.exp = new CommaExp(loc, e, ei.exp); - // Don't cast away invariant or mutability in initializer - if (search_function(sd, Id.call) && - /* Initializing with the same type is done differently + /* Replace __ctmp being constructed with e1 + */ + dve.e1 = e1; + return; + } + } + } + } + } + if (!ei.exp.implicitConvTo(type)) + { + Type ti = ei.exp.type.toBasetype(); + // Look for constructor first + if (sd.ctor && + /* Initializing with the same type is done differently + */ + !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc))) + { + // Rewrite as e1.ctor(arguments) + Expression ector = new DotIdExp(loc, e1, Id.ctor); + ei.exp = new CallExp(loc, ector, ei.exp); + } + else + /* Look for opCall + * See bugzilla 2702 for more discussion */ - !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc))) - { // Rewrite as e1.call(arguments) - Expression eCall = new DotIdExp(loc, e1, Id.call); - ei.exp = new CallExp(loc, eCall, ei.exp); + + // Don't cast away invariant or mutability in initializer + if (search_function(sd, Id.call) && + /* Initializing with the same type is done differently + */ + !(ti.ty == Tstruct && t.toDsymbol(sc) == ti.toDsymbol(sc))) + { // Rewrite as e1.call(arguments) + Expression eCall = new DotIdExp(loc, e1, Id.call); + ei.exp = new CallExp(loc, eCall, ei.exp); + } } } + ei.exp = new AssignExp(loc, e1, ei.exp); + ei.exp.op = op; + canassign++; + ei.exp = ei.exp.semantic(sc); + canassign--; + ei.exp.optimize(WANT.WANTvalue); + } + else + { + init = init.semantic(sc, type); + } } - ei.exp = new AssignExp(loc, e1, ei.exp); - ei.exp.op = op; - canassign++; - ei.exp = ei.exp.semantic(sc); - canassign--; - ei.exp.optimize(WANT.WANTvalue); - } - else + else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) || + type.isConst() || type.isImmutable() || + parent.isAggregateDeclaration()) { - init = init.semantic(sc, type); - } - } - else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) || - type.isConst() || type.isImmutable() || - parent.isAggregateDeclaration()) - { - /* Because we may need the results of a const declaration in a - * subsequent type, such as an array dimension, before semantic2() - * gets ordinarily run, try to run semantic2() now. - * Ignore failure. - */ + /* Because we may need the results of a const declaration in a + * subsequent type, such as an array dimension, before semantic2() + * gets ordinarily run, try to run semantic2() now. + * Ignore failure. + */ + + if (!global.errors && !inferred) + { + uint errors = global.errors; + global.gag++; + //printf("+gag\n"); + Expression e; + Initializer i2 = init; + inuse++; + if (ei) + { + e = ei.exp.syntaxCopy(); + e = e.semantic(sc); + e = resolveProperties(sc, e); +version (DMDV2) { + /* The problem is the following code: + * struct CopyTest { + * double x; + * this(double a) { x = a * 10.0;} + * this(this) { x += 2.0; } + * } + * const CopyTest z = CopyTest(5.3); // ok + * const CopyTest w = z; // not ok, postblit not run + * static assert(w.x == 55.0); + * because the postblit doesn't get run on the initialization of w. + */ - if (!global.errors && !inferred) - { - uint errors = global.errors; - global.gag++; - //printf("+gag\n"); - Expression e; - Initializer i2 = init; - inuse++; - if (ei) - { - e = ei.exp.syntaxCopy(); - e = e.semantic(sc); - e = e.implicitCastTo(sc, type); - } - else if (si || ai) - { i2 = init.syntaxCopy(); - i2 = i2.semantic(sc, type); + Type tb_ = e.type.toBasetype(); + if (tb_.ty == Tstruct) + { + StructDeclaration sd = (cast(TypeStruct)tb_).sym; + Type typeb = type.toBasetype(); + /* Look to see if initializer involves a copy constructor + * (which implies a postblit) + */ + if (sd.cpctor && // there is a copy constructor + typeb.equals(tb_)) // rvalue is the same struct + { + // The only allowable initializer is a (non-copy) constructor + if (e.op == TOKcall) + { + CallExp ce = cast(CallExp)e; + if (ce.e1.op == TOKdotvar) + { + DotVarExp dve = cast(DotVarExp)ce.e1; + if (dve.var.isCtorDeclaration()) + goto LNoCopyConstruction; + } + } + global.gag--; + error("of type struct %s uses this(this), which is not allowed in static initialization", typeb.toChars()); + global.gag++; + + LNoCopyConstruction: + ; + } + } +} + e = e.implicitCastTo(sc, type); + } + else if (si || ai) + { + i2 = init.syntaxCopy(); + i2 = i2.semantic(sc, type); + } + inuse--; + global.gag--; + //printf("-gag\n"); + if (errors != global.errors) // if errors happened + { + if (global.gag == 0) + global.errors = errors; // act as if nothing happened +version (DMDV2) { + /* Save scope for later use, to try again + */ + scope_ = sc.clone(); + scope_.setNoFree(); +} + } + else if (ei) + { + if (isDataseg()) + /* static const/invariant does CTFE + */ + e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); + else + e = e.optimize(WANT.WANTvalue); + if (e.op == TOK.TOKint64 || e.op == TOK.TOKstring || e.op == TOK.TOKfloat64) + { + ei.exp = e; // no errors, keep result + } +///version (DMDV2) { + else + { + /* Save scope for later use, to try again + */ + scope_ = sc.clone(); + scope_.setNoFree(); + } +///} + } + else + init = i2; // no errors, keep result + } } - inuse--; - global.gag--; - //printf("-gag\n"); - if (errors != global.errors) // if errors happened - { - if (global.gag == 0) - global.errors = errors; // act as if nothing happened -version (DMDV2) { - /* Save scope for later use, to try again - */ - scope_ = sc.clone(); - scope_.setNoFree(); -} - } - else if (ei) - { - if (isDataseg()) - /* static const/invariant does CTFE - */ - e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); - else - e = e.optimize(WANT.WANTvalue); - if (e.op == TOK.TOKint64 || e.op == TOK.TOKstring || e.op == TOK.TOKfloat64) - { - ei.exp = e; // no errors, keep result - } -///version (DMDV2) { - else - { - /* Save scope for later use, to try again - */ - scope_ = sc.clone(); - scope_.setNoFree(); - } -///} - } - else - init = i2; // no errors, keep result - } - } - sc = sc.pop(); + sc = sc.pop(); } } diff -r e3afd1303184 -r cd48cb899aee dmd/backend/glue.d --- a/dmd/backend/glue.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/backend/glue.d Sun Oct 17 20:56:07 2010 +0400 @@ -14,6 +14,7 @@ import dmd.Global; import dmd.Param; import dmd.backend.Config; +import dmd.backend.elem; import dmd.backend.Configv; import dmd.backend.StringTab; diff -r e3afd1303184 -r cd48cb899aee dmd/expression/Util.d --- a/dmd/expression/Util.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/expression/Util.d Sun Oct 17 20:56:07 2010 +0400 @@ -1115,6 +1115,7 @@ */ Identifier idtmp = Lexer.uniqueId("__tmp"); VarDeclaration tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(Loc(0), e)); + tmp.storage_class |= STCctfe; Expression ae = new DeclarationExp(loc, tmp); e = new CommaExp(loc, ae, new VarExp(loc, tmp)); e = e.semantic(sc); diff -r e3afd1303184 -r cd48cb899aee dmd/interpret/Util.d --- a/dmd/interpret/Util.d Sun Oct 17 07:42:00 2010 +0400 +++ b/dmd/interpret/Util.d Sun Oct 17 20:56:07 2010 +0400 @@ -6,10 +6,12 @@ import dmd.FuncDeclaration; import dmd.InterState; import dmd.ArrayTypes; +import dmd.StringExp; import dmd.GlobalExpressions; import dmd.TOK; import dmd.AssocArrayLiteralExp; import dmd.IntegerExp; +import dmd.Id; import dmd.Type; import dmd.Declaration; import dmd.Loc; @@ -24,6 +26,9 @@ import dmd.VarDeclaration; import dmd.Util; +import core.memory; +import core.stdc.string; + version(DMDV1) { Expression interpret_aaLen(InterState istate, Expressions arguments) @@ -140,6 +145,11 @@ if (v) { ///version (DMDV2) { + /* Magic variable __ctfe always returns true when interpreting + */ + if (v.ident == Id.ctfe) + return new IntegerExp(loc, 1, Type.tbool); + if ((v.isConst() || v.isImmutable() || v.storage_class & STCmanifest) && v.init && !v.value) ///} else { /// if (v.isConst() && v.init) @@ -149,6 +159,17 @@ if (e && !e.type) e.type = v.type; } + else if (v.isCTFE() && !v.value) + { + if (v.init) + { + e = v.init.toExpression(); + e = e.interpret(istate); + } + else // This should never happen + e = v.type.defaultInitLiteral(Loc(0)); + } + else { e = v.value; @@ -198,7 +219,7 @@ } /*************************************** - * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$] + * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint+newelems.length..$] */ Expressions spliceElements(Expressions oldelems, Expressions newelems, size_t insertpoint) { @@ -214,6 +235,48 @@ return expsx; } +/*************************************** + * Returns oldstr[0..insertpoint] ~ newstr ~ oldstr[insertpoint+newlen..$] + */ +StringExp spliceStringExp(StringExp oldstr, StringExp newstr, size_t insertpoint) +{ + assert(oldstr.sz==newstr.sz); + char* s; + size_t oldlen = oldstr.len; + size_t newlen = newstr.len; + size_t sz = oldstr.sz; + s = cast(char*)GC.calloc(oldlen + 1, sz); + memcpy(s, oldstr.string_, oldlen * sz); + memcpy(s + insertpoint * sz, newstr.string_, newlen * sz); + StringExp se2 = new StringExp(oldstr.loc, cast(string)s[0..oldlen]); + se2.committed = oldstr.committed; + se2.postfix = oldstr.postfix; + se2.type = oldstr.type; + return se2; +} + +/****************************** + * Create a string literal consisting of 'value' duplicated 'dim' times. + */ +StringExp createBlockDuplicatedStringLiteral(Type type, dchar value, size_t dim, int sz) +{ + char* s; + s = cast(char*)GC.calloc(dim + 1, sz); + for (int elemi = 0; elemi < dim; ++elemi) + { + switch (sz) + { + case 1: s[elemi] = cast(char)value; break; + case 2: (cast(wchar*)s)[elemi] = cast(wchar)value; break; + case 4: (cast(dchar*)s)[elemi] = value; break; + default: assert(0); + } + } + StringExp se = new StringExp(Loc(0), cast(string)s[0..dim]); + se.type = type; + return se; +} + /****************************** * Create an array literal consisting of 'elem' duplicated 'dim' times. */ diff -r e3afd1303184 -r cd48cb899aee main.d --- a/main.d Sun Oct 17 07:42:00 2010 +0400 +++ b/main.d Sun Oct 17 20:56:07 2010 +0400 @@ -337,6 +337,8 @@ /// else if (arg == "fPIC") /// global.params.pic = 1; ///} + else if (arg == "map") + global.params.map = 1; else if (arg == "multiobj") global.params.multiobj = 1; else if (arg == "g") @@ -860,7 +862,13 @@ if (FileName.equals(ext, global.json_ext)) { global.params.doXGeneration = 1; - global.params.xfilename = (cast(immutable(char)*)files.data[i])[0..0]; + global.params.xfilename = (cast(String)files.data[i]).str; + continue; + } + + if (FileName.equals(ext, global.map_ext)) + { + global.params.mapfile = (cast(String)files.data[i]).str; continue; } @@ -868,13 +876,13 @@ { if (FileName.equals(ext, "res")) { - global.params.resfile = (cast(immutable(char)*)files.data[i])[0..0]; /// !!! + global.params.resfile = (cast(String)files.data[i]).str; continue; } if (FileName.equals(ext, "def")) { - global.params.deffile = (cast(immutable(char)*)files.data[i])[0..0]; + global.params.deffile = (cast(String)files.data[i]).str; continue; } @@ -1053,6 +1061,9 @@ if (global.errors) fatal(); + global.dprogress = 1; + Module.runDeferredSemantic(); + // Do pass 2 semantic analysis for (int i = 0; i < modules.dim; i++) {