# HG changeset patch # User Trass3r # Date 1284472010 -7200 # Node ID 78bf0fe43974d4626403be6b53e58e9bf6572a59 # Parent 95b3ed3cddd55c42fa37300312239586a20bb961# Parent 786ea1839396698db91c9af56e547eecc4404528 merge diff -r 786ea1839396 -r 78bf0fe43974 commands.linux.txt --- a/commands.linux.txt Tue Aug 31 18:02:48 2010 +0200 +++ b/commands.linux.txt Tue Sep 14 15:46:50 2010 +0200 @@ -48,6 +48,7 @@ dmd/templates/Util.d dmd/expression/Util.d dmd/expression/Add.d +dmd/expression/Bool.d dmd/expression/Xor.d dmd/expression/Ptr.d dmd/expression/Min.d @@ -78,6 +79,7 @@ dmd/ArrayLengthExp.d dmd/TypeInfoConstDeclaration.d dmd/TypeInfoInvariantDeclaration.d +dmd/TypeInfoWildDeclaration.d dmd/TypeInfoSharedDeclaration.d dmd/TypeInfoStructDeclaration.d dmd/TypeInfoInterfaceDeclaration.d @@ -113,7 +115,7 @@ dmd/AliasThis.d dmd/AlignDeclaration.d dmd/AnonymousAggregateDeclaration.d -dmd/Argument.d +dmd/Parameter.d dmd/FuncExp.d dmd/ArrayLiteralExp.d dmd/AssocArrayLiteralExp.d @@ -271,6 +273,8 @@ dmd/Param.d dmd/Parser.d dmd/PostBlitDeclaration.d +dmd/PowExp.d +dmd/PowAssignExp.d dmd/PragmaDeclaration.d dmd/PragmaStatement.d dmd/ProtDeclaration.d @@ -298,6 +302,7 @@ dmd/SymbolDeclaration.d dmd/SynchronizedStatement.d dmd/TOK.d +dmd/TRUST.d dmd/TY.d dmd/TemplateAliasParameter.d dmd/TemplateDeclaration.d @@ -388,3 +393,4 @@ dmd/backend/rel.d dmd/backend/LIST.d dmd/codegen/Util.d +dmd/codegen/linkhelper.d \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 commands.txt --- a/commands.txt Tue Aug 31 18:02:48 2010 +0200 +++ b/commands.txt Tue Sep 14 15:46:50 2010 +0200 @@ -43,6 +43,7 @@ dmd\templates\Util.d dmd\expression\Util.d dmd\expression\Add.d +dmd\expression\Bool.d dmd\expression\Xor.d dmd\expression\Ptr.d dmd\expression\Min.d @@ -73,6 +74,7 @@ dmd\ArrayLengthExp.d dmd\TypeInfoConstDeclaration.d dmd\TypeInfoInvariantDeclaration.d +dmd\TypeInfoWildDeclaration.d dmd\TypeInfoSharedDeclaration.d dmd\TypeInfoStructDeclaration.d dmd\TypeInfoInterfaceDeclaration.d @@ -108,7 +110,7 @@ dmd\AliasThis.d dmd\AlignDeclaration.d dmd\AnonymousAggregateDeclaration.d -dmd\Argument.d +dmd\Parameter.d dmd\FuncExp.d dmd\ArrayLiteralExp.d dmd\AssocArrayLiteralExp.d @@ -266,6 +268,8 @@ dmd\Param.d dmd\Parser.d dmd\PostBlitDeclaration.d +dmd\PowExp.d +dmd\PowAssignExp.d dmd\PragmaDeclaration.d dmd\PragmaStatement.d dmd\ProtDeclaration.d @@ -293,6 +297,7 @@ dmd\SymbolDeclaration.d dmd\SynchronizedStatement.d dmd\TOK.d +dmd\TRUST.d dmd\TY.d dmd\TemplateAliasParameter.d dmd\TemplateDeclaration.d @@ -383,4 +388,5 @@ dmd\backend\iasm.d dmd\backend\rel.d dmd\backend\LIST.d -dmd\codegen\Util.d \ No newline at end of file +dmd\codegen\Util.d +dmd\codegen\linkhelper.d \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 ddmd.sln --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ddmd.sln Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 11.00 +# Visual Studio 2010 +Project("{002A2DE9-8BB6-484D-9802-7E4AD4084715}") = "ddmd", "ddmd.visualdproj", "{C58DB54F-7447-4ADC-80C0-7DD2392E5F28}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C58DB54F-7447-4ADC-80C0-7DD2392E5F28}.Debug|Win32.ActiveCfg = Debug|Win32 + {C58DB54F-7447-4ADC-80C0-7DD2392E5F28}.Debug|Win32.Build.0 = Debug|Win32 + {C58DB54F-7447-4ADC-80C0-7DD2392E5F28}.Release|Win32.ActiveCfg = Release|Win32 + {C58DB54F-7447-4ADC-80C0-7DD2392E5F28}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff -r 786ea1839396 -r 78bf0fe43974 ddmd.visualdproj --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ddmd.visualdproj Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,620 @@ + + {C58DB54F-7447-4ADC-80C0-7DD2392E5F28} + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + + + $(ConfigurationName) + $(OutDir) + + + 0 + + + + 0 + + + 1 + $(IntDir)\$(ProjectName).json + 0 + + 0 + DMDV2 TX86 MARS _WIN32 TARGET_WINDOS OMFOBJ WindowsXP DumbClone BREAKABI SEH STRUCTTHISREF CCASTSYNTAX CARRAYDECL SNAN_DEFAULT_INIT SARRAYVALUE + 0 + 0 + 0 + + + + 0 + + 1 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + + + dmd.lib + + + + $(OutDir)\$(ProjectName).exe + + dmc -c bridge\bridge.cpp + + $(TARGETPATH) + + + 0 + + *.obj + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 1 + 1 + 0 + 0 + 0 + 0 + 0 + 2 + 0 + 0 + $(DMDInstallDir)windows\bin\dmd.exe + + + $(ConfigurationName) + $(OutDir) + + + 0 + + + + 0 + + + 1 + $(IntDir)\$(ProjectName).json + 0 + + 0 + DMDV2 TX86 MARS _WIN32 TARGET_WINDOS OMFOBJ WindowsXP DumbClone BREAKABI SEH STRUCTTHISREF CCASTSYNTAX CARRAYDECL SNAN_DEFAULT_INIT SARRAYVALUE + 0 + 0 + 0 + + + + 0 + + 0 + $(VisualDInstallDir)cv2pdb\cv2pdb.exe + + + dmdrelease.lib + + + + $(OutDir)\$(ProjectName).exe + + + + $(TARGETPATH) + + + 0 + + *.obj + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 786ea1839396 -r 78bf0fe43974 dmd/AddAssignExp.d --- a/dmd/AddAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AddAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,11 +1,13 @@ module dmd.AddAssignExp; +import dmd.common; +import dmd.expression.Add; import dmd.BinExp; import dmd.Loc; import dmd.Expression; import dmd.Scope; import dmd.InterState; -import dmd.Argument; +import dmd.Parameter; import dmd.STC; import dmd.OutBuffer; import dmd.ArrayTypes; @@ -19,6 +21,7 @@ import dmd.AssignExp; import dmd.Global; import dmd.Id; +import dmd.ArrayLengthExp; import dmd.backend.OPER; import dmd.backend.elem; @@ -47,6 +50,13 @@ Type tb1 = e1.type.toBasetype(); Type tb2 = e2.type.toBasetype(); + if (e1.op == TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + if (e1.op == TOK.TOKslice) { typeCombine(sc); @@ -141,7 +151,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Add); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -149,16 +159,9 @@ AssignExp_buildArrayIdent(buf, arguments, "Add"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - /* Evaluate assign expressions right to left - */ - Expression ex2 = e2.buildArrayLoop(fparams); - Expression ex1 = e1.buildArrayLoop(fparams); - Argument param = cast(Argument)fparams.data[0]; - param.storageClass = STCundefined; - Expression e = new AddAssignExp(Loc(0), ex1, ex2); - return e; + return AssignExp_buildArrayLoop!(typeof(this))(fparams); } override Identifier opId() /* For operator overloading */ diff -r 786ea1839396 -r 78bf0fe43974 dmd/AddExp.d --- a/dmd/AddExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AddExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AddExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; @@ -113,7 +114,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &Add); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -121,14 +122,9 @@ Exp_buildArrayIdent(buf, arguments, "Add"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - /* Evaluate assign expressions left to right - */ - Expression ex1 = e1.buildArrayLoop(fparams); - Expression ex2 = e2.buildArrayLoop(fparams); - Expression e = new AddExp(Loc(0), ex1, ex2); - return e; + return Exp_buildArrayLoop!(typeof(this))(fparams); } override bool isCommutative() diff -r 786ea1839396 -r 78bf0fe43974 dmd/AddrExp.d --- a/dmd/AddrExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AddrExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AddrExp; +import dmd.common; import dmd.Expression; import dmd.UnaExp; import dmd.MATCH; @@ -65,7 +66,6 @@ return new ErrorExp(); } - //printf("test3 deco = %p\n", e1.type.deco); type = e1.type.pointerTo(); // See if this should really be a delegate @@ -126,6 +126,11 @@ return this; } + override void checkEscape() + { + e1.checkEscapeRef(); + } + override elem* toElem(IRState* irs) { elem* e; diff -r 786ea1839396 -r 78bf0fe43974 dmd/AggregateDeclaration.d --- a/dmd/AggregateDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AggregateDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AggregateDeclaration; +import dmd.common; import dmd.ScopeDsymbol; import dmd.Type; import dmd.Id; @@ -108,9 +109,8 @@ ClassDeclaration cdthis = dthis.isClassDeclaration(); if (cdthis) { - for (int i = 0; i < cdthis.baseclasses.dim; i++) + foreach (b; cdthis.baseclasses) { - BaseClass b = cast(BaseClass)cdthis.baseclasses.data[i]; PROT access = b.base.getAccess(smember); if (access >= PROT.PROTprotected || accessCheckX(smember, sfunc, b.base, cdscope)) @@ -126,10 +126,8 @@ ClassDeclaration cdthis = dthis.isClassDeclaration(); if (cdthis) { - for (int i = 0; i < cdthis.baseclasses.dim; i++) + foreach (b; cdthis.baseclasses) { - BaseClass b = cast(BaseClass)cdthis.baseclasses.data[i]; - if (accessCheckX(smember, sfunc, b.base, cdscope)) return true; } @@ -143,7 +141,7 @@ class AggregateDeclaration : ScopeDsymbol { Type type; - uint storage_class; + StorageClass storage_class; PROT protection = PROT.PROTpublic; Type handle; // 'this' type uint structsize; // size of struct @@ -156,10 +154,11 @@ // 1: size is correct // 2: cannot determine size; fwd referenced bool isdeprecated; // true if deprecated - + +version (DMDV2) { bool isnested; // true if is nested VarDeclaration vthis; // 'this' parameter if this aggregate is nested - +} // Special member functions InvariantDeclaration inv; // invariant NewDeclaration aggNew; // allocator diff -r 786ea1839396 -r 78bf0fe43974 dmd/AliasDeclaration.d --- a/dmd/AliasDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AliasDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AliasDeclaration; +import dmd.common; import dmd.LINK; import dmd.Declaration; import dmd.TypedefDeclaration; @@ -99,9 +100,10 @@ } this.inSemantic = 1; +version(DMDV1) { // don't really know why this is here if (storage_class & STC.STCconst) error("cannot be const"); - +} storage_class |= sc.stc & STC.STCdeprecated; // Given: @@ -127,11 +129,12 @@ goto L2; // it's a symbolic alias ///version (DMDV2) { + type = type.addStorageClass(storage_class); if (storage_class & (STC.STCref | STCnothrow | STCpure)) { // 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); + sc.stc |= storage_class & (STCref | STCnothrow | STCpure | STCshared); type.resolve(loc, sc, &e, &t, &s); sc = sc.pop(); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/AliasThis.d --- a/dmd/AliasThis.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AliasThis.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AliasThis; +import dmd.common; import dmd.Dsymbol; import dmd.Identifier; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/AlignDeclaration.d --- a/dmd/AlignDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AlignDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AlignDeclaration; +import dmd.common; import dmd.AttribDeclaration; import dmd.OutBuffer; import dmd.HdrGenState; diff -r 786ea1839396 -r 78bf0fe43974 dmd/AndAndExp.d --- a/dmd/AndAndExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AndAndExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AndAndExp; +import dmd.common; import dmd.Expression; import dmd.InterState; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/AndAssignExp.d --- a/dmd/AndAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AndAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,7 @@ module dmd.AndAssignExp; +import dmd.common; +import dmd.expression.And; import dmd.BinExp; import dmd.Loc; import dmd.Expression; @@ -29,7 +31,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &And); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -37,9 +39,9 @@ AssignExp_buildArrayIdent(buf, arguments, "And"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - assert(false); + return AssignExp_buildArrayLoop!(typeof(this))(fparams); } override Identifier opId() /* For operator overloading */ diff -r 786ea1839396 -r 78bf0fe43974 dmd/AndExp.d --- a/dmd/AndExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AndExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AndExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.InterState; @@ -49,11 +50,10 @@ else { typeCombine(sc); - if (e1.op != TOK.TOKslice && e2.op != TOK.TOKslice) - { + if (!e1.isArrayOperand()) e1.checkIntegral(); + if (!e2.isArrayOperand()) e2.checkIntegral(); - } } } return this; @@ -75,7 +75,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &And); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -83,14 +83,9 @@ Exp_buildArrayIdent(buf, arguments, "And"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - /* Evaluate assign expressions left to right - */ - Expression ex1 = e1.buildArrayLoop(fparams); - Expression ex2 = e2.buildArrayLoop(fparams); - Expression e = new AndExp(Loc(0), ex1, ex2); - return e; + return Exp_buildArrayLoop!(typeof(this))(fparams); } override IntRange getIntRange() diff -r 786ea1839396 -r 78bf0fe43974 dmd/AnonDeclaration.d --- a/dmd/AnonDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AnonDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AnonDeclaration; +import dmd.common; import dmd.OutBuffer; import dmd.Loc; import dmd.Scope; diff -r 786ea1839396 -r 78bf0fe43974 dmd/AnonymousAggregateDeclaration.d --- a/dmd/AnonymousAggregateDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AnonymousAggregateDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AnonymousAggregateDeclaration; +import dmd.common; import dmd.AggregateDeclaration; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Argument.d --- a/dmd/Argument.d Tue Aug 31 18:02:48 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,304 +0,0 @@ -module dmd.Argument; - -import dmd.Type; -import dmd.Identifier; -import dmd.TypeArray; -import dmd.TypeFunction; -import dmd.TypeDelegate; -import dmd.TypeTuple; -import dmd.TY; -import dmd.Expression; -import dmd.OutBuffer; -import dmd.HdrGenState; -import dmd.ArrayTypes; -import dmd.StorageClassDeclaration; -import dmd.Global; -import dmd.MOD; -import dmd.CppMangleState; -import dmd.STC; - -class Argument -{ - //enum InOut inout; - STC storageClass; - Type type; - Identifier ident; - Expression defaultArg; - - this(STC storageClass, Type type, Identifier ident, Expression defaultArg) - { - this.type = type; - this.ident = ident; - this.storageClass = storageClass; - this.defaultArg = defaultArg; - } - - Argument clone() - { - return new Argument(storageClass, type, ident, defaultArg); - } - - Argument syntaxCopy() - { - return new Argument(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null); - } - - /**************************************************** - * Determine if parameter is a lazy array of delegates. - * If so, return the return type of those delegates. - * If not, return null. - */ - Type isLazyArray() - { - // if (inout == Lazy) - { - Type tb = type.toBasetype(); - if (tb.ty == Tsarray || tb.ty == Tarray) - { - Type tel = (cast(TypeArray)tb).next.toBasetype(); - if (tel.ty == Tdelegate) - { - TypeDelegate td = cast(TypeDelegate)tel; - TypeFunction tf = cast(TypeFunction)td.next; - - if (!tf.varargs && Argument.dim(tf.parameters) == 0) - { - return tf.next; // return type of delegate - } - } - } - } - return null; - } - - void toDecoBuffer(OutBuffer buf) - { - if (storageClass & STC.STCscope) - buf.writeByte('M'); - switch (storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STClazy)) - { - case STC.STCundefined: - case STC.STCin: - break; - case STC.STCout: - buf.writeByte('J'); - break; - case STC.STCref: - buf.writeByte('K'); - break; - case STC.STClazy: - buf.writeByte('L'); - break; - } -static if (false) { - int mod = 0x100; - if (type.toBasetype().ty == TY.Tclass) - mod = 0; - type.toDecoBuffer(buf, mod); -} else { - //type.toHeadMutable().toDecoBuffer(buf, 0); - type.toDecoBuffer(buf, 0); -} - } - - static Arguments arraySyntaxCopy(Arguments args) - { - Arguments a = null; - - if (args) - { - a = new Arguments(); - a.setDim(args.dim); - - for (size_t i = 0; i < a.dim; i++) - { - Argument arg = cast(Argument)args.data[i]; - - arg = arg.syntaxCopy(); - a.data[i] = cast(void*)arg; - } - } - - return a; - } - - static string argsTypesToChars(Arguments args, int varargs) - { - scope OutBuffer buf = new OutBuffer(); - - static if (true) { - HdrGenState hgs; - argsToCBuffer(buf, &hgs, args, varargs); - } else { - buf.writeByte('('); - if (args) - { - OutBuffer argbuf = new OutBuffer(); - HdrGenState hgs; - - for (int i = 0; i < args.dim; i++) - { - if (i) - buf.writeByte(','); - Argument arg = cast(Argument)args.data[i]; - argbuf.reset(); - arg.type.toCBuffer2(&argbuf, &hgs, 0); - buf.write(&argbuf); - } - if (varargs) - { - if (i && varargs == 1) - buf.writeByte(','); - buf.writestring("..."); - } - } - buf.writeByte(')'); - } - return buf.toChars(); - } - - static void argsCppMangle(OutBuffer buf, CppMangleState* cms, Arguments arguments, int varargs) - { - assert(false); - } - - static void argsToCBuffer(OutBuffer buf, HdrGenState* hgs, Arguments arguments, int varargs) - { - buf.writeByte('('); - if (arguments) - { - int i; - scope OutBuffer argbuf = new OutBuffer(); - - for (i = 0; i < arguments.dim; i++) - { - if (i) - buf.writestring(", "); - Argument arg = cast(Argument)arguments.data[i]; - - if (arg.storageClass & STCout) - buf.writestring("out "); - else if (arg.storageClass & STCref) - buf.writestring((global.params.Dversion == 1) ? "inout " : "ref "); - else if (arg.storageClass & STCin) - buf.writestring("in "); - else if (arg.storageClass & STClazy) - buf.writestring("lazy "); - else if (arg.storageClass & STCalias) - buf.writestring("alias "); - else if (arg.storageClass & STCauto) - buf.writestring("auto "); - - uint stc = arg.storageClass; - if (arg.type && arg.type.mod & MODshared) - stc &= ~STCshared; - - StorageClassDeclaration.stcToCBuffer(buf, stc & (STCconst | STCimmutable | STCshared | STCscope)); - - argbuf.reset(); - if (arg.storageClass & STCalias) - { - if (arg.ident) - argbuf.writestring(arg.ident.toChars()); - } - else - arg.type.toCBuffer(argbuf, arg.ident, hgs); - if (arg.defaultArg) - { - argbuf.writestring(" = "); - arg.defaultArg.toCBuffer(argbuf, hgs); - } - buf.write(argbuf); - } - if (varargs) - { - if (i && varargs == 1) - buf.writeByte(','); - buf.writestring("..."); - } - } - buf.writeByte(')'); - } - - static void argsToDecoBuffer(OutBuffer buf, Arguments arguments) - { - //printf("Argument::argsToDecoBuffer()\n"); - - // Write argument types - if (arguments) - { - size_t dim = Argument.dim(arguments); - for (size_t i = 0; i < dim; i++) - { - Argument arg = Argument.getNth(arguments, i); - arg.toDecoBuffer(buf); - } - } - } - - static int isTPL(Arguments arguments) - { - assert(false); - } - - /*************************************** - * Determine number of arguments, folding in tuples. - */ - static size_t dim(Arguments args) - { - size_t n = 0; - if (args) - { - for (size_t i = 0; i < args.dim; i++) - { - Argument arg = cast(Argument)args.data[i]; - Type t = arg.type.toBasetype(); - - if (t.ty == TY.Ttuple) - { - TypeTuple tu = cast(TypeTuple)t; - n += dim(tu.arguments); - } - else - n++; - } - } - return n; - } - - /*************************************** - * Get nth Argument, folding in tuples. - * Returns: - * Argument nth Argument - * null not found, *pn gets incremented by the number - * of Arguments - */ - static Argument getNth(Arguments args, size_t nth, size_t* pn = null) - { - if (!args) - return null; - - size_t n = 0; - for (size_t i = 0; i < args.dim; i++) - { - Argument arg = cast(Argument)args.data[i]; - Type t = arg.type.toBasetype(); - - if (t.ty == TY.Ttuple) - { TypeTuple tu = cast(TypeTuple)t; - arg = getNth(tu.arguments, nth - n, &n); - if (arg) - return arg; - } - else if (n == nth) - return arg; - else - n++; - } - - if (pn) - *pn += n; - - return null; - } -} diff -r 786ea1839396 -r 78bf0fe43974 dmd/Array.d --- a/dmd/Array.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Array.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Array; +import dmd.common; import core.memory; import std.exception; @@ -204,14 +205,14 @@ return _dim; } */ - +/* + // Use [] for accessing members instead + // or ptr() to get the pointer to the first element @property T *data() { return _data; } - - - +*/ @property T *ptr() { return _data; @@ -245,6 +246,12 @@ _data[_dim++] = elem; } + final void zero() + { + memset(_data, 0, dim * T.sizeof); + // TODO fix to assign T.init + } + final void reserve(size_t nentries) { //printf("Array::reserve: size = %d, offset = %d, nbytes = %d\n", size, offset, nbytes); diff -r 786ea1839396 -r 78bf0fe43974 dmd/ArrayExp.d --- a/dmd/ArrayExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ArrayExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ArrayExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.UnaExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ArrayInitializer.d --- a/dmd/ArrayInitializer.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ArrayInitializer.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ArrayInitializer; +import dmd.common; import dmd.ArrayTypes; import dmd.Type; import dmd.TypeAArray; @@ -56,9 +57,9 @@ e = e.syntaxCopy(); ai.index[i] = e; - Initializer init = cast(Initializer)value.data[i]; + auto init = value[i]; init = init.syntaxCopy(); - ai.value.data[i] = cast(void*)init; + ai.value[i] = init; } return ai; } @@ -66,7 +67,7 @@ void addInit(Expression index, Initializer value) { this.index.push(index); - this.value.push(cast(void*)value); + this.value.push(value); dim = 0; type = null; } @@ -97,8 +98,6 @@ length = 0; foreach (size_t i, Expression idx; index) { - Initializer val; - if (idx) { idx = idx.semantic(sc); @@ -107,9 +106,9 @@ length = cast(uint)idx.toInteger(); } - val = cast(Initializer)value.data[i]; + Initializer val = value[i]; val = val.semantic(sc, t.nextOf()); - value.data[i] = cast(void*)val; + value[i] = val; length++; if (length == 0) error(loc, "array dimension overflow"); @@ -123,9 +122,22 @@ return this; } + int isAssociativeArray() + { + for (size_t i = 0; i < value.dim; i++) + { + if (index[i]) + return 1; + } + return 0; + } + override Type inferType(Scope sc) { //printf("ArrayInitializer.inferType() %s\n", toChars()); + assert(0); + return null; +static if (false) { type = Type.terror; for (size_t i = 0; i < value.dim; i++) { @@ -133,14 +145,15 @@ goto Laa; } - for (size_t i = 0; i < value.dim; i++) + foreach (size_t i, Initializer iz; value) { - Initializer iz = cast(Initializer)value.data[i]; if (iz) { Type t = iz.inferType(sc); if (i == 0) - { + { /* BUG: This gets the type from the first element. + * Fix to use all the elements to figure out the type. + */ t = new TypeSArray(t, new IntegerExp(value.dim)); t = t.semantic(loc, sc); type = t; @@ -150,9 +163,10 @@ return type; Laa: - /* It's possibly an associative array initializer - */ - Initializer iz = cast(Initializer)value.data[0]; + /* It's possibly an associative array initializer. + * BUG: inferring type from first member. + */ + Initializer iz = value[0]; Expression indexinit = index[0]; if (iz && indexinit) { @@ -165,6 +179,7 @@ else error(loc, "cannot infer type from this array initializer"); return type; +} } /******************************** @@ -220,7 +235,7 @@ if (index[i]) j = cast(uint)(index[i].toInteger()); assert(j < edim); - Initializer iz = cast(Initializer)value.data[i]; + Initializer iz = value[i]; if (!iz) goto Lno; Expression ex = iz.toExpression(); @@ -256,7 +271,7 @@ return null; } - Initializer toAssocArrayInitializer() + Expression toAssocArrayLiteral() { assert(false); } @@ -272,7 +287,7 @@ Type tb = type.toBasetype(); Type tn = tb.nextOf().toBasetype(); - scope Array dts = new Array(); + scope dts = new Vector!(dt_t*)(); uint size; uint length; uint i; @@ -298,11 +313,11 @@ //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); assert(length < dim); - val = cast(Initializer)value.data[i]; + val = value[i]; dt = val.toDt(); - if (dts.data[length]) + if (dts[length]) error(loc, "duplicate initializations for index %d", length); - dts.data[length] = cast(void*)dt; + dts[length] = dt; length++; } @@ -319,7 +334,7 @@ pdtend = &d; for (i = 0; i < dim; i++) { - dt = cast(dt_t*)dts.data[i]; + dt = dts[i]; if (dt) pdtend = dtcat(pdtend, dt); else diff -r 786ea1839396 -r 78bf0fe43974 dmd/ArrayLengthExp.d --- a/dmd/ArrayLengthExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ArrayLengthExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,6 +1,8 @@ module dmd.ArrayLengthExp; +import dmd.common; import dmd.Expression; +import dmd.BinExp; import dmd.backend.elem; import dmd.UnaExp; import dmd.InterState; @@ -12,6 +14,16 @@ import dmd.TOK; import dmd.Type; import dmd.WANT; +import dmd.VarExp; +import dmd.VarDeclaration; +import dmd.PtrExp; +import dmd.Lexer; +import dmd.Identifier; +import dmd.ExpInitializer; +import dmd.DeclarationExp; +import dmd.CommaExp; +import dmd.AssignExp; +import dmd.AddrExp; import dmd.expression.ArrayLength; @@ -27,8 +39,6 @@ override Expression semantic(Scope sc) { - Expression e; - version (LOGSEMANTIC) { printf("ArrayLengthExp::semantic('%s')\n", toChars()); } @@ -42,6 +52,35 @@ return this; } + static Expression rewriteOpAssign(BinExp exp) + { + Expression e; + + assert(exp.e1.op == TOKarraylength); + auto ale = cast(ArrayLengthExp)exp.e1; + if (ale.e1.op == TOK.TOKvar) + { + e = opAssignToOp(exp.loc, exp.op, ale, exp.e2); + e = new AssignExp(exp.loc, ale.syntaxCopy(), e); + } + else + { + /* auto tmp = &array; + * (*tmp).length = (*tmp).length op e2 + */ + Identifier id = Lexer.uniqueId("__arraylength"); + ExpInitializer ei = new ExpInitializer(ale.loc, new AddrExp(ale.loc, ale.e1)); + VarDeclaration tmp = new VarDeclaration(ale.loc, ale.e1.type.pointerTo(), id, ei); + + Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp))); + Expression elvalue = e1.syntaxCopy(); + e = opAssignToOp(exp.loc, exp.op, e1, exp.e2); + e = new AssignExp(exp.loc, elvalue, e); + e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e); + } + return e; + } + override Expression optimize(int result) { //printf("ArrayLengthExp::optimize(result = %d) %s\n", result, toChars()); diff -r 786ea1839396 -r 78bf0fe43974 dmd/ArrayLiteralExp.d --- a/dmd/ArrayLiteralExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ArrayLiteralExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ArrayLiteralExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.InterState; @@ -15,6 +16,7 @@ import dmd.HdrGenState; import dmd.backend.dt_t; import dmd.InlineScanState; +import dmd.GlobalExpressions; import dmd.Array; import dmd.ArrayTypes; import dmd.TOK; @@ -56,58 +58,19 @@ override Expression semantic(Scope sc) { - Expression e; - Type t0 = null; - version (LOGSEMANTIC) { printf("ArrayLiteralExp.semantic('%s')\n", toChars()); } if (type) return this; - // Run semantic() on each element - foreach (ref Expression e; elements) - { - e = e.semantic(sc); - assert(e.type); - } + arrayExpressionSemantic(elements, sc); // run semantic() on each element expandTuples(elements); - foreach (size_t i, Expression e; elements) - { - if (!e.type) - error("%s has no value", e.toChars()); - - e = resolveProperties(sc, e); - - ubyte committed = 1; - if (e.op == TOKstring) - committed = (cast(StringExp)e).committed; - - if (!t0) - { - t0 = e.type; - // Convert any static arrays to dynamic arrays - if (t0.ty == Tsarray) - { - t0 = (cast(TypeSArray)t0).next.arrayOf(); - e = e.implicitCastTo(sc, t0); - } - } - else - e = e.implicitCastTo(sc, t0); - - if (!committed && e.op == TOKstring) - { - auto se = cast(StringExp)e; - se.committed = 0; - } - elements[i] = e; - } - - if (!t0) - t0 = Type.tvoid; + Type t0; + elements = arrayExpressionToCommonType(sc, elements, &t0); + type = new TypeSArray(t0, new IntegerExp(elements.dim)); type = type.semantic(loc, sc); return this; @@ -237,7 +200,56 @@ override Expression interpret(InterState istate) { - assert(false); + Expressions expsx = null; + +version (LOG) { + printf("ArrayLiteralExp.interpret() %.*s\n", toChars()); +} + if (elements) + { + foreach (size_t i, Expression e; elements) + { + Expression ex; + + ex = e.interpret(istate); + if (ex is EXP_CANT_INTERPRET) + goto Lerror; + + /* If any changes, do Copy On Write + */ + if (ex != e) + { + if (!expsx) + { + expsx = new Expressions(); + expsx.setDim(elements.dim); + for (size_t j = 0; j < elements.dim; j++) + { + expsx[j] = elements[j]; + } + } + expsx[i] = ex; + } + } + } + if (elements && expsx) + { + expandTuples(expsx); + if (expsx.dim != elements.dim) + goto Lerror; + + ArrayLiteralExp ae = new ArrayLiteralExp(loc, expsx); + ae.type = type; + + return ae; + } + return this; + + Lerror: + if (expsx) + delete expsx; + error("cannot interpret array literal"); + return EXP_CANT_INTERPRET; } override MATCH implicitConvTo(Type t) diff -r 786ea1839396 -r 78bf0fe43974 dmd/ArrayScopeSymbol.d --- a/dmd/ArrayScopeSymbol.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ArrayScopeSymbol.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ArrayScopeSymbol; +import dmd.common; import dmd.ScopeDsymbol; import dmd.Expression; import dmd.TypeTuple; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ArrayTypes.d --- a/dmd/ArrayTypes.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ArrayTypes.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,21 +1,20 @@ module dmd.ArrayTypes; +import dmd.common; import dmd.Array; - -class TemplateParameters : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } } - -class Statements : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } } - -class BaseClasses : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } } - -class ClassDeclarations : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } } +import dmd.TemplateParameter; +import dmd.Statement; +import dmd.BaseClass; +import dmd.ClassDeclaration; +import dmd.Parameter; +import dmd.Identifier; +import dmd.Initializer; -//class Dsymbols : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } } - -class Objects : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } } - -class Arguments : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } } - -class Identifiers : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } } - -class Initializers : Array { final typeof(this) copy() { auto a = new typeof(this); copyTo(a); return a; } } \ No newline at end of file +alias Vector!Object Objects; +alias Vector!TemplateParameter TemplateParameters; +alias Vector!Statement Statements; +alias Vector!BaseClass BaseClasses; +alias Vector!ClassDeclaration ClassDeclarations; +alias Vector!Parameter Parameters; +alias Vector!Identifier Identifiers; +alias Vector!Initializer Initializers; \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/AsmStatement.d --- a/dmd/AsmStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AsmStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AsmStatement; +import dmd.common; import dmd.Loc; import dmd.Statement; import dmd.Token; @@ -58,12 +59,16 @@ override Statement semantic(Scope sc) { //printf("AsmStatement.semantic()\n"); - - if (global.params.safe && !sc.module_.safe) - { - error("inline assembler not allowed in safe mode"); - } - +//static if (true) { + if (sc.func && sc.func.isSafe()) + error("inline assembler not allowed in @safe function %s", sc.func.toChars()); +//} else { +// if (global.params.safe && !sc.module_.safe) +// { +// error("inline assembler not allowed in safe mode"); +// } +//} + OP* o; OPND* o1 = null; OPND* o2 = null; diff -r 786ea1839396 -r 78bf0fe43974 dmd/AssertExp.d --- a/dmd/AssertExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AssertExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AssertExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.UnaExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/AssignExp.d --- a/dmd/AssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,10 +1,11 @@ module dmd.AssignExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; import dmd.InterState; -import dmd.Argument; +import dmd.Parameter; import dmd.IndexExp; import dmd.CallExp; import dmd.CastExp; @@ -389,7 +390,7 @@ buf.writestring("Assign"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { /* Evaluate assign expressions right to left */ @@ -403,7 +404,7 @@ ex2 = new CastExp(Loc(0), ex2, e1.type.nextOf()); } Expression ex1 = e1.buildArrayLoop(fparams); - Argument param = cast(Argument)fparams.data[0]; + auto param = fparams[0]; param.storageClass = STCundefined; Expression e = new AssignExp(Loc(0), ex1, ex2); return e; @@ -411,9 +412,6 @@ override elem* toElem(IRState* irs) { - elem* e; - IndexExp ae; - int r; Type t1b; //printf("AssignExp.toElem('%s')\n", toChars()); @@ -426,45 +424,25 @@ // _d_arraysetlength(e2, sizeelem, &ale.e1); ArrayLengthExp ale = cast(ArrayLengthExp)e1; - elem* p1; - elem* p2; - elem* p3; - elem* ep; - Type t1; - p1 = e2.toElem(irs); - p3 = ale.e1.toElem(irs); + auto p1 = e2.toElem(irs); + auto p3 = ale.e1.toElem(irs); p3 = addressElem(p3, null); - t1 = ale.e1.type.toBasetype(); + Type t1 = ale.e1.type.toBasetype(); -static if (true) { // call _d_arraysetlengthT(ti, e2, &ale.e1); - p2 = t1.getTypeInfo(null).toElem(irs); - ep = el_params(p3, p1, p2, null); // c function - r = t1.nextOf().isZeroInit(Loc(0)) ? RTLSYM.RTLSYM_ARRAYSETLENGTHT : RTLSYM.RTLSYM_ARRAYSETLENGTHIT; -} else { - if (t1.next.isZeroInit()) - { - p2 = t1.getTypeInfo(null).toElem(irs); - ep = el_params(p3, p1, p2, null); // c function - r = RTLSYM.RTLSYM_ARRAYSETLENGTHT; - } - else - { - p2 = el_long(TYM.TYint, t1.next.size()); - ep = el_params(p3, p2, p1, null); // c function - Expression init = t1.next.defaultInit(); - ep = el_param(el_long(TYM.TYint, init.type.size()), ep); - elem* ei = init.toElem(irs); - ep = el_param(ei, ep); - r = RTLSYM.RTLSYM_ARRAYSETLENGTH3; - } -} - e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[r]), ep); + auto p2 = t1.getTypeInfo(null).toElem(irs); + auto ep = el_params(p3, p1, p2, null); // c function + int r = t1.nextOf().isZeroInit(Loc(0)) ? RTLSYM.RTLSYM_ARRAYSETLENGTHT : RTLSYM.RTLSYM_ARRAYSETLENGTHIT; + + auto e = el_bin(OPER.OPcall, type.totym(), el_var(rtlsym[r]), ep); el_setLoc(e, loc); return e; } - + + elem *e; + IndexExp ae; + // Look for array[]=n if (e1.op == TOK.TOKslice) { @@ -559,7 +537,7 @@ elem_print(enbytes); } - if (global.params.useArrayBounds && eupr && ta.ty != TY.Tpointer) + if (irs.arrayBoundsCheck() && eupr && ta.ty != TY.Tpointer) { elem *c1; elem *c2; @@ -650,16 +628,13 @@ /* It's array1[]=array2[] * which is a memcpy */ - elem* eto; - elem* efrom; - elem* esize; elem* ep; - eto = e1.toElem(irs); - efrom = e2.toElem(irs); + auto eto = e1.toElem(irs); + auto efrom = e2.toElem(irs); uint size = cast(uint)t1.nextOf().size(); - esize = el_long(TYM.TYint, size); + auto esize = el_long(TYM.TYint, size); /* Determine if we need to do postblit */ @@ -669,16 +644,12 @@ assert(e2.type.ty != TY.Tpointer); - if (!postblit && !global.params.useArrayBounds) + if (!postblit && !irs.arrayBoundsCheck()) { - elem* epto; - elem* epfr; - elem* elen; - elem* ex; - - ex = el_same(&eto); + auto ex = el_same(&eto); // Determine if elen is a constant + elem *elen; if (eto.Eoper == OPER.OPpair && eto.E1.Eoper == OPER.OPconst) { elen = el_copytree(eto.E1); @@ -690,8 +661,8 @@ } esize = el_bin(OPER.OPmul, TYM.TYint, elen, esize); - epto = array_toPtr(e1.type, ex); - epfr = array_toPtr(e2.type, efrom); + auto epto = array_toPtr(e1.type, ex); + auto epfr = array_toPtr(e2.type, efrom); static if (true) { // memcpy() is faster, so if we can't beat 'em, join 'em e = el_params(esize, epfr, epto, null); diff -r 786ea1839396 -r 78bf0fe43974 dmd/AssocArrayLiteralExp.d --- a/dmd/AssocArrayLiteralExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AssocArrayLiteralExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AssocArrayLiteralExp; +import dmd.common; import dmd.Expression; import dmd.GlobalExpressions; import dmd.WANT; @@ -50,24 +51,17 @@ override Expression semantic(Scope sc) { Expression e; - Type tkey = null; - Type tvalue = null; version (LOGSEMANTIC) { printf("AssocArrayLiteralExp.semantic('%s')\n", toChars()); } - // Run semantic() on each element - for (size_t i = 0; i < keys.dim; i++) - { auto key = keys[i]; - auto value = values[i]; + if (type) + return this; - key = key.semantic(sc); - value = value.semantic(sc); - - keys[i] = key; - values[i] = value; - } + // Run semantic() on each element + arrayExpressionSemantic(keys, sc); + arrayExpressionSemantic(values, sc); expandTuples(keys); expandTuples(values); if (keys.dim != values.dim) @@ -76,34 +70,12 @@ keys.setDim(0); values.setDim(0); } - for (size_t i = 0; i < keys.dim; i++) - { auto key = keys[i]; - auto value = values[i]; - - if (!key.type) - error("%s has no value", key.toChars()); - if (!value.type) - error("%s has no value", value.toChars()); - key = resolveProperties(sc, key); - value = resolveProperties(sc, value); - - if (!tkey) - tkey = key.type; - else - key = key.implicitCastTo(sc, tkey); - keys[i] = key; - - if (!tvalue) - tvalue = value.type; - else - value = value.implicitCastTo(sc, tvalue); - values[i] = value; - } - - if (!tkey) - tkey = Type.tvoid; - if (!tvalue) - tvalue = Type.tvoid; + + Type tkey; + Type tvalue; + keys = arrayExpressionToCommonType(sc, keys, &tkey); + values = arrayExpressionToCommonType(sc, values, &tvalue); + type = new TypeAArray(tvalue, tkey); type = type.semantic(loc, sc); return this; @@ -147,6 +119,8 @@ assert(t.ty == Taarray); auto ta = cast(TypeAArray)t; +static if(false) +{ /* Unfortunately, the hash function for Aa (array of chars) is custom and * different from Axa and Aya, which get the generic hash function. * So, rewrite the type of the AArray so that if it's key type @@ -160,6 +134,7 @@ ta = new TypeAArray(ta.nextOf(), tkey); ta = cast(TypeAArray)ta.merge(); } +} e = el_param(e, ta.getTypeInfo(null).toElem(irs)); diff -r 786ea1839396 -r 78bf0fe43974 dmd/AttribDeclaration.d --- a/dmd/AttribDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/AttribDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.AttribDeclaration; +import dmd.common; import dmd.Dsymbol; import dmd.Array; import dmd.Scope; @@ -39,7 +40,7 @@ return m; } - void setScopeNewSc(Scope sc, STC stc, LINK linkage, PROT protection, int explicitProtection, uint structalign) + void setScopeNewSc(Scope sc, StorageClass stc, LINK linkage, PROT protection, int explicitProtection, uint structalign) { if (decl) { @@ -65,7 +66,7 @@ } } - void semanticNewSc(Scope sc, STC stc, LINK linkage, PROT protection, int explicitProtection, uint structalign) + void semanticNewSc(Scope sc, StorageClass stc, LINK linkage, PROT protection, int explicitProtection, uint structalign) { if (decl) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/BaseClass.d --- a/dmd/BaseClass.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/BaseClass.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.BaseClass; +import dmd.common; import dmd.Type; import dmd.PROT; import dmd.ClassDeclaration; @@ -132,7 +133,7 @@ baseInterfaces[i] = b; if (i) // single inheritance is i==0 - vtblInterfaces.push(cast(void*)b); // only need for M.I. + vtblInterfaces.push(b); // only need for M.I. b.copyBaseInterfaces(vtblInterfaces); } //printf("-copyBaseInterfaces\n"); diff -r 786ea1839396 -r 78bf0fe43974 dmd/BinExp.d --- a/dmd/BinExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/BinExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.BinExp; +import dmd.common; import dmd.SliceExp; import dmd.IndexExp; import dmd.StructDeclaration; @@ -53,7 +54,7 @@ import dmd.PREC; import dmd.StringValue; import dmd.StringTable; -import dmd.Argument; +import dmd.Parameter; import dmd.Statement; import dmd.ForeachRangeStatement; import dmd.ArrayLengthExp; @@ -124,11 +125,8 @@ TY ty = cast(TY)Type.impcnvResult[t1b.ty][t2b.ty]; if (ty != TY.Terror) { - TY ty1; - TY ty2; - - ty1 = cast(TY)Type.impcnvType1[t1b.ty][t2b.ty]; - ty2 = cast(TY)Type.impcnvType2[t1b.ty][t2b.ty]; + auto ty1 = cast(TY)Type.impcnvType1[t1b.ty][t2b.ty]; + auto ty2 = cast(TY)Type.impcnvType2[t1b.ty][t2b.ty]; if (t1b.ty == ty1) // if no promotions { @@ -205,16 +203,24 @@ } } else if ((t1.ty == TY.Tsarray || t1.ty == TY.Tarray) && - e2.op == TOK.TOKnull && t2.ty == TY.Tpointer && t2.nextOf().ty == TY.Tvoid) - { /* (T[n] op void*) - * (T[] op void*) - */ + (e2.op == TOK.TOKnull && t2.ty == TY.Tpointer && t2.nextOf().ty == TY.Tvoid || + e2.op == TOK.TOKarrayliteral && t2.ty == TY.Tsarray && t2.nextOf().ty == TY.Tvoid && (cast(TypeSArray)t2).dim.toInteger() == 0) + ) + { /* (T[n] op void*) => T[] + * (T[] op void*) => T[] + * (T[n] op void[0]) => T[] + * (T[] op void[0]) => T[] + */ goto Lx1; } else if ((t2.ty == TY.Tsarray || t2.ty == TY.Tarray) && - e1.op == TOK.TOKnull && t1.ty == TY.Tpointer && t1.nextOf().ty == TY.Tvoid) - { /* (void* op T[n]) - * (void* op T[]) + (e1.op == TOK.TOKnull && t1.ty == TY.Tpointer && t1.nextOf().ty == TY.Tvoid || + e1.op == TOK.TOKarrayliteral && t1.ty == TY.Tsarray && t1.nextOf().ty == TY.Tvoid && (cast(TypeSArray)t1).dim.toInteger() == 0) + ) + { /* (void* op T[n]) => T[] + * (void* op T[]) => T[] + * (void[0] op T[n]) => T[] + * (void[0] op T[]) => T[] */ goto Lx2; } @@ -312,7 +318,7 @@ e2.implicitConvTo(t1.nextOf().arrayOf())) { Lx1: - t = t1.nextOf().arrayOf(); + t = t1.nextOf().arrayOf(); // T[] e1 = e1.castTo(sc, t); e2 = e2.castTo(sc, t); } @@ -449,6 +455,13 @@ if (e) return e; + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + if (e1.op == TOKslice) { // T[] op= ... @@ -489,6 +502,13 @@ if (e) return e; + if (e1.op == TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + if (e1.op == TOK.TOKslice) { // T[] op= ... typeCombine(sc); @@ -532,6 +552,7 @@ case TOK.TOKandass: case TOK.TOKorass: case TOK.TOKxorass: + case TOK.TOKpowass: case TOK.TOKin: case TOK.TOKremove: return true; @@ -654,7 +675,7 @@ bool isunsigned() { - assert(false); + return e1.type.isunsigned() || e2.type.isunsigned(); } void incompatibleTypes() @@ -669,25 +690,83 @@ assert(false); } - void scanForNestedRef(Scope *sc) + void scanForNestedRef(Scope sc) { - assert(false); + e1.scanForNestedRef(sc); + e2.scanForNestedRef(sc); } - - Expression interpretCommon(InterState istate, Expression *(*fp)(Type *, Expression *, Expression *)) + + Expression interpretCommon(InterState istate, Expression function(Type, Expression, Expression) fp) { - assert(false); + Expression e; + Expression e1; + Expression e2; + +version(LOG) +{ + writef("BinExp::interpretCommon() %s\n", toChars()); +} + e1 = this.e1.interpret(istate); + if (e1 is EXP_CANT_INTERPRET) + goto Lcant; + if (e1.isConst() != 1) + goto Lcant; + + e2 = this.e2.interpret(istate); + if (e2 is EXP_CANT_INTERPRET) + goto Lcant; + if (e2.isConst() != 1) + goto Lcant; + + e = fp(type, e1, e2); + return e; + + Lcant: + return EXP_CANT_INTERPRET; } - Expression interpretCommon2(InterState istate, Expression *(*fp)(TOK, Type *, Expression *, Expression *)) + Expression interpretCommon2(InterState istate, Expression function(TOK, Type, Expression, Expression) fp) { - assert(false); + Expression e; + Expression e1; + Expression e2; + +version(LOG) +{ + writef("BinExp::interpretCommon2() %s\n", toChars()); +} + e1 = this.e1.interpret(istate); + if (e1 is EXP_CANT_INTERPRET) + goto Lcant; + if (e1.isConst() != 1 && + e1.op != TOKnull && + e1.op != TOKstring && + e1.op != TOKarrayliteral && + e1.op != TOKstructliteral) + goto Lcant; + + e2 = this.e2.interpret(istate); + if (e2 is EXP_CANT_INTERPRET) + goto Lcant; + if (e2.isConst() != 1 && + e2.op != TOKnull && + e2.op != TOKstring && + e2.op != TOKarrayliteral && + e2.op != TOKstructliteral) + goto Lcant; + + e = fp(op, type, e1, e2); + return e; + + Lcant: + return EXP_CANT_INTERPRET; } - Expression interpretAssignCommon(InterState istate, Expression (*fp)(Type, Expression, Expression), int post = 0) + Expression interpretAssignCommon(InterState istate, Expression function(Type, Expression, Expression) fp, int post = 0) { -version (LOG) { - printf("BinExp.interpretAssignCommon() %.*s\n", toChars()); +version (LOG) +{ + writef("BinExp.interpretAssignCommon() %.*s\n", toChars()); } Expression e = EXP_CANT_INTERPRET; Expression e1 = this.e1; @@ -725,7 +804,7 @@ } else if (v && v.value && (v.value.op==TOKindex || v.value.op == TOKdotvar)) { - // It is no longer be a TOKvar, eg when a[4] is passed by ref. + // It is no longer a TOKvar, eg when a[4] is passed by ref. e1 = v.value; } } @@ -748,13 +827,13 @@ VarExp ve = cast(VarExp)e1; VarDeclaration v = ve.var.isVarDeclaration(); assert(v); - if (v && v.isDataseg()) + if (v && !v.isCTFE()) { // Can't modify global or static data error("%s cannot be modified at compile time", v.toChars()); return EXP_CANT_INTERPRET; } - if (v && !v.isDataseg()) + if (v && v.isCTFE()) { Expression ev = v.value; if (fp && !ev) @@ -770,7 +849,7 @@ */ if (v.type.toBasetype().ty == Tstruct && e2.op == TOKint64) { - e2 = v.type.defaultInit(Loc(0)); + e2 = v.type.defaultInitLiteral(Loc(0)); } e2 = Cast(v.type, v.type, e2); } @@ -794,7 +873,7 @@ { VarDeclaration v = (cast(VarExp)aggregate).var.isVarDeclaration(); - if (v.isDataseg()) + if (!v.isCTFE()) { // Can't modify global or static data error("%s cannot be modified at compile time", v.toChars()); @@ -871,7 +950,7 @@ SymOffExp soe = cast(SymOffExp)(cast(PtrExp)e1).e1; VarDeclaration v = soe.var.isVarDeclaration(); - if (v.isDataseg()) + if (!v.isCTFE()) { error("%s cannot be modified at compile time", v.toChars()); return EXP_CANT_INTERPRET; @@ -919,7 +998,7 @@ IndexExp ie = cast(IndexExp)e1; VarExp ve = cast(VarExp)ie.e1; VarDeclaration v = ve.var.isVarDeclaration(); - if (!v || v.isDataseg()) + if (!v || !v.isCTFE()) { error("%s cannot be modified at compile time", v ? v.toChars(): "void"); return EXP_CANT_INTERPRET; @@ -1087,7 +1166,7 @@ IndexExp ie = cast(IndexExp)aggregate; VarExp ve = cast(VarExp)(ie.e1); VarDeclaration v = ve.var.isVarDeclaration(); - if (!v || v.isDataseg()) + if (!v || !v.isCTFE()) { error("%s cannot be modified at compile time", v ? v.toChars(): "void"); return EXP_CANT_INTERPRET; @@ -1110,8 +1189,7 @@ if (telem.ty != Tstruct) { return EXP_CANT_INTERPRET; } // Create a default struct literal... - StructDeclaration sym = (cast(TypeStruct)telem).sym; - StructLiteralExp structinit = createDefaultInitStructLiteral(v.loc, sym); + Expression structinit = telem.defaultInitLiteral(v.loc); // ... and use to create a blank array literal size_t dim = cast(size_t)(cast(TypeSArray)t2).dim.toInteger(); @@ -1179,7 +1257,7 @@ SliceExp sexp = cast(SliceExp)e1; VarExp ve = cast(VarExp)(sexp.e1); VarDeclaration v = ve.var.isVarDeclaration(); - if (!v || v.isDataseg()) + if (!v || !v.isCTFE()) { error("%s cannot be modified at compile time", v.toChars()); return EXP_CANT_INTERPRET; @@ -1323,7 +1401,8 @@ } return e; } - + + version(DMDV2) override bool canThrow() { return e1.canThrow() || e2.canThrow(); @@ -1382,7 +1461,7 @@ return new ErrorExp(); } - Expressions arguments = new Expressions(); + auto arguments = new Expressions(); /* The expression to generate an array operation for is mangled * into a name to use as the array operation function name. @@ -1597,9 +1676,9 @@ * return p; */ - Arguments fparams = new Arguments(); + auto fparams = new Parameters(); Expression loopbody = buildArrayLoop(fparams); - Argument p = cast(Argument)fparams.data[0 /*fparams.dim - 1*/]; + auto p = fparams[0 /*fparams.dim - 1*/]; version (DMDV1) { // for (size_t i = 0; i < p.length; i++) Initializer init = new ExpInitializer(0, new IntegerExp(0, 0, Type.tsize_t)); @@ -1612,7 +1691,7 @@ } else { // foreach (i; 0 .. p.length) Statement s1 = new ForeachRangeStatement(Loc(0), TOKforeach, - new Argument(STC.STCundefined, null, Id.p, null), + new Parameter(STC.STCundefined, null, Id.p, null), new IntegerExp(Loc(0), 0, Type.tint32), new ArrayLengthExp(Loc(0), new IdentifierExp(Loc(0), p.ident)), new ExpStatement(Loc(0), loopbody)); @@ -1900,6 +1979,8 @@ case TOK.TOKleg: case TOK.TOKue: break; + default: + break; /// } return e; @@ -1949,6 +2030,15 @@ return e; } + final void AssignExp_buildArrayIdent(OutBuffer buf, Expressions arguments, string Str) + { + /* Evaluate assign expressions right to left + */ + e2.buildArrayIdent(buf, arguments); + e1.buildArrayIdent(buf, arguments); + buf.writestring(Str); + buf.writestring("ass"); + } final void Exp_buildArrayIdent(OutBuffer buf, Expressions arguments, string Str) { @@ -1959,13 +2049,25 @@ buf.writestring(Str); } - final void AssignExp_buildArrayIdent(OutBuffer buf, Expressions arguments, string Str) - { - /* Evaluate assign expressions right to left - */ - e2.buildArrayIdent(buf, arguments); - e1.buildArrayIdent(buf, arguments); - buf.writestring(Str); - buf.writestring("ass"); + final Expression AssignExp_buildArrayLoop(AssignExpType)(Parameters fparams)// if (is (AssignExpType : AssignExp)) + { + /* Evaluate assign expressions right to left + */ + Expression ex2 = e2.buildArrayLoop(fparams); + Expression ex1 = e1.buildArrayLoop(fparams); + auto param = fparams[0]; + param.storageClass = STCundefined; + Expression e = new AssignExpType(Loc(0), ex1, ex2); + return e; } -} + + final Expression Exp_buildArrayLoop(ExpType)(Parameters fparams) if (is (ExpType : BinExp)) + { + /* Evaluate assign expressions left to right + */ + Expression ex1 = e1.buildArrayLoop(fparams); + Expression ex2 = e2.buildArrayLoop(fparams); + Expression e = new ExpType(Loc(0), ex1, ex2); + return e; + } +} \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/BoolExp.d --- a/dmd/BoolExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/BoolExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.BoolExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.UnaExp; @@ -10,6 +11,7 @@ import dmd.IRState; import dmd.TOK; +import dmd.expression.Bool; import dmd.backend.OPER; import dmd.backend.Util; @@ -23,7 +25,7 @@ override Expression semantic(Scope sc) { - UnaExp.semantic(sc); + super.semantic(sc); e1 = resolveProperties(sc, e1); e1 = e1.checkToBoolean(); type = Type.tboolean; @@ -32,7 +34,16 @@ override Expression optimize(int result) { - assert(false); + Expression e; + + e1 = e1.optimize(result); + if (e1.isConst() == 1) + { + e = Bool(type, e1); + } + else + e = this; + return e; } override Expression interpret(InterState istate) diff -r 786ea1839396 -r 78bf0fe43974 dmd/BreakStatement.d --- a/dmd/BreakStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/BreakStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.BreakStatement; +import dmd.common; import dmd.Statement; import dmd.Loc; import dmd.Identifier; diff -r 786ea1839396 -r 78bf0fe43974 dmd/CallExp.d --- a/dmd/CallExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CallExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CallExp; +import dmd.common; import dmd.ErrorExp; import dmd.Expression; import dmd.Cast; @@ -48,6 +49,7 @@ import dmd.DotVarExp; import dmd.DotIdExp; import dmd.TY; +import dmd.TRUST; import dmd.Id; import dmd.TypeAArray; import dmd.RemoveExp; @@ -184,7 +186,8 @@ return new RemoveExp(loc, dotid.e1, key); } - else if (e1ty == TY.Tarray || e1ty == TY.Tsarray || e1ty == TY.Taarray) + else if (e1ty == TY.Tarray || e1ty == TY.Tsarray || + (e1ty == Taarray && dotid.ident != Id.apply && dotid.ident != Id.applyReverse)) { if (!arguments) arguments = new Expressions(); @@ -212,25 +215,25 @@ * If not, go with partial explicit specialization. */ ti.semanticTiargs(sc); - uint errors = global.errors; - global.gag++; - ti.semantic(sc); - global.gag--; - if (errors != global.errors) + if (ti.needsTypeInference(sc)) { - /* Didn't work, go with partial explicit specialization + /* Go with partial explicit specialization */ - global.errors = errors; targsi = ti.tiargs; tierror = ti; // for error reporting e1 = new IdentifierExp(loc, ti.name); } + else + { + ti.semantic(sc); + } } } /* This recognizes: * expr.foo!(tiargs)(funcargs) */ +Ldotti: if (e1.op == TOK.TOKdotti && !e1.type) { DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)e1; @@ -241,6 +244,7 @@ * If not, go with partial explicit specialization. */ ti.semanticTiargs(sc); +static if (false) { Expression etmp = e1.trySemantic(sc); if (etmp) e1 = etmp; // it worked @@ -250,6 +254,24 @@ tierror = ti; // for error reporting e1 = new DotIdExp(loc, se.e1, ti.name); } +} else { + if (!ti.tempdecl) + { + se.getTempdecl(sc); + } + if (ti.tempdecl && ti.needsTypeInference(sc)) + { + /* Go with partial explicit specialization + */ + targsi = ti.tiargs; + tierror = ti; // for error reporting + e1 = new DotIdExp(loc, se.e1, ti.name); + } + else + { + e1 = e1.semantic(sc); + } +} } } } @@ -264,7 +286,21 @@ } else { - UnaExp.semantic(sc); + if (e1.op == TOK.TOKdot) + { + auto die = cast(DotIdExp)e1; + e1 = die.semantic(sc, 1); + /* Look for e1 having been rewritten to expr.opDispatch!(string) + * We handle such earlier, so go back. + * Note that in the rewrite, we carefully did not run semantic() on e1 + */ + if (e1.op == TOK.TOKdotti && !e1.type) + { + goto Ldotti; + } + } + else + UnaExp.semantic(sc); /* Look for e1 being a lazy parameter */ @@ -391,7 +427,7 @@ } arrayExpressionSemantic(arguments, sc); - preFunctionArguments(loc, sc, arguments); + preFunctionParameters(loc, sc, arguments); if (e1.op == TOK.TOKdotvar && t1.ty == TY.Tfunction || e1.op == TOK.TOKdottd) @@ -448,6 +484,7 @@ checkDeprecated(sc, f); version (DMDV2) { checkPurity(sc, f); + checkSafety(sc, f); } accessCheck(loc, sc, ue.e1, f); if (!f.needThis()) @@ -471,7 +508,7 @@ printf("e1 = %s\n", e1.toChars()); printf("e1.type = %s\n", e1.type.toChars()); } - // Const member function can take const/immutable/mutable this + // Const member function can take const/immutable/mutable/inout this if (!(f.type.isConst())) { // Check for const/immutable compatibility @@ -480,14 +517,14 @@ tthis = tthis.nextOf().toBasetype(); static if (false) { // this checking should have been already done - if (f.type.isInvariant()) + if (f.type.isImmutable()) { - if (tthis.mod != MOD.MODinvariant) + if (tthis.mod != MOD.MODimmutable) error("%s can only be called with an immutable object", e1.toChars()); } else if (f.type.isShared()) { - if (tthis.mod != MOD.MODinvariant && tthis.mod != MOD.MODshared && tthis.mod != (MOD.MODshared | MOD.MODconst)) + if (tthis.mod != MOD.MODimmutable && tthis.mod != MOD.MODshared && tthis.mod != (MOD.MODshared | MOD.MODconst)) error("shared %s can only be called with a shared or immutable object", e1.toChars()); } else @@ -561,6 +598,7 @@ checkDeprecated(sc, f); version (DMDV2) { checkPurity(sc, f); + checkSafety(sc, f); } e1 = new DotVarExp(e1.loc, e1, f); e1 = e1.semantic(sc); @@ -600,6 +638,7 @@ checkDeprecated(sc, f); version (DMDV2) { checkPurity(sc, f); + checkSafety(sc, f); } e1 = new DotVarExp(e1.loc, e1, f); e1 = e1.semantic(sc); @@ -667,6 +706,10 @@ { error("pure function '%s' cannot call impure delegate '%s'", sc.func.toChars(), e1.toChars()); } + if (sc.func && sc.func.isSafe() && tf.trust <= TRUST.TRUSTsystem) + { + error("safe function '%s' cannot call system delegate '%s'", sc.func.toChars(), e1.toChars()); + } goto Lcheckargs; } else if (t1.ty == TY.Tpointer && (cast(TypePointer)t1).next.ty == TY.Tfunction) @@ -677,6 +720,10 @@ { error("pure function '%s' cannot call impure function pointer '%s'", sc.func.toChars(), e1.toChars()); } + if (sc.func && sc.func.isSafe() && !(cast(TypeFunction)t1).trust <= TRUST.TRUSTsystem) + { + error("safe function '%s' cannot call system function pointer '%s'", sc.func.toChars(), e1.toChars()); + } e.type = t1; e1 = e; } @@ -706,8 +753,7 @@ else { error("function expected before (), not %s of type %s", e1.toChars(), e1.type.toChars()); - type = Type.terror; - return this; + return new ErrorExp(); } } else if (e1.op == TOK.TOKvar) @@ -724,6 +770,7 @@ checkDeprecated(sc, f); version (DMDV2) { checkPurity(sc, f); + checkSafety(sc, f); } if (f.needThis() && hasThis(sc)) @@ -747,12 +794,11 @@ Lcheckargs: assert(tf.ty == TY.Tfunction); - type = tf.next; if (!arguments) arguments = new Expressions(); - functionArguments(loc, sc, tf, arguments); + type = functionParameters(loc, sc, tf, arguments); if (!type) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/CaseRangeStatement.d --- a/dmd/CaseRangeStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CaseRangeStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CaseRangeStatement; +import dmd.common; import dmd.Statement; import dmd.ArrayTypes; import dmd.Expression; @@ -76,7 +77,7 @@ s = new ExpStatement(loc, null); Expression e = new IntegerExp(loc, i, first.type); Statement cs = new CaseStatement(loc, e, s); - statements.push(cast(void*)cs); + statements.push(cs); } Statement s = new CompoundStatement(loc, statements); s = s.semantic(sc); diff -r 786ea1839396 -r 78bf0fe43974 dmd/CaseStatement.d --- a/dmd/CaseStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CaseStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CaseStatement; +import dmd.common; import dmd.Statement; import dmd.Expression; import dmd.Statement; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Cast.d --- a/dmd/Cast.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Cast.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Cast; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.Loc; @@ -60,6 +61,9 @@ } } + if (e1.op == TOK.TOKarrayliteral && typeb == tb) + return e1; + if (e1.isConst() != 1) return EXP_CANT_INTERPRET; diff -r 786ea1839396 -r 78bf0fe43974 dmd/CastExp.d --- a/dmd/CastExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CastExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,6 +1,8 @@ module dmd.CastExp; +import dmd.common; import dmd.Expression; +import dmd.GlobalExpressions; import dmd.TY; import dmd.TypeStruct; import dmd.ErrorExp; @@ -106,6 +108,12 @@ } } + if (e1.op == TOKtemplate) + { + error("cannot cast template %s to type %s", e1.toChars(), to.toChars()); + return new ErrorExp(); + } + Type t1b = e1.type.toBasetype(); Type tob = to.toBasetype(); if (tob.ty == TY.Tstruct && @@ -145,14 +153,18 @@ to = Type.terror; } - if (global.params.safe && !sc.module_.safe && !sc.intypeof) +//static if (true) { + if (sc.func && sc.func.isSafe() && !sc.intypeof) +//} else { +// if (global.params.safe && !sc.module_.safe && !sc.intypeof) +//} { // Disallow unsafe casts Type tob = to.toBasetype(); Type t1b = e1.type.toBasetype(); if (!t1b.isMutable() && tob.isMutable()) { // Cast not mutable to mutable Lunsafe: - error("cast from %s to %s not allowed in safe mode", e1.type.toChars(), to.toChars()); + error("cast from %s to %s not allowed in safe code", e1.type.toChars(), to.toChars()); } else if (t1b.isShared() && !tob.isShared()) // Cast away shared @@ -171,6 +183,10 @@ // Cast away pointer to shared goto Lunsafe; + if (t1bn.isWild() && !tobn.isConst() && !tobn.isWild()) + // Cast wild to anything but const | wild + goto Lunsafe; + if (tobn.isTypeBasic() && tobn.size() < t1bn.size()) { // Allow things like casting a long* to an int* ; @@ -358,12 +374,34 @@ override Expression interpret(InterState istate) { - assert(false); + Expression e; + Expression e1; + +version (LOG) { + printf("CastExp.interpret() %.*s\n", toChars()); +} + e1 = this.e1.interpret(istate); + if (e1 is EXP_CANT_INTERPRET) + goto Lcant; + return Cast(type, to, e1); + + Lcant: +version (LOG) { + printf("CastExp.interpret() %.*s CANT\n", toChars()); +} + return EXP_CANT_INTERPRET; } override bool checkSideEffect(int flag) { - assert(false); + /* if not: + * cast(void) + * cast(classtype)func() + */ + if (!to.equals(Type.tvoid) && !(to.ty == Tclass && e1.op == TOKcall && e1.type.ty == Tclass)) + return Expression.checkSideEffect(flag); + + return true; } override void checkEscape() @@ -391,27 +429,7 @@ to.toCBuffer(buf, null, hgs); else { - switch (mod) - { - case MODundefined: - break; - case MODconst: - buf.writestring(Token.tochars[TOKconst]); - break; - case MODinvariant: - buf.writestring(Token.tochars[TOKimmutable]); - break; - case MODshared: - buf.writestring(Token.tochars[TOKshared]); - break; - case MODshared | MODconst: - buf.writestring(Token.tochars[TOKshared]); - buf.writeByte(' '); - buf.writestring(Token.tochars[TOKconst]); - break; - default: - assert(0); - } + MODtoBuffer(buf, mod); } } buf.writeByte(')'); @@ -429,7 +447,7 @@ Expression.buildArrayIdent(buf, arguments); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { Type tb = type.toBasetype(); if (tb.ty == Tarray || tb.ty == Tsarray) diff -r 786ea1839396 -r 78bf0fe43974 dmd/CatAssignExp.d --- a/dmd/CatAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CatAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,11 +1,13 @@ module dmd.CatAssignExp; +import dmd.common; import dmd.BinExp; import dmd.Loc; import dmd.Expression; import dmd.Scope; import dmd.InterState; import dmd.SliceExp; +import dmd.ErrorExp; import dmd.Identifier; import dmd.IRState; import dmd.TOK; @@ -19,6 +21,7 @@ import dmd.backend.TYM; import dmd.backend.mTY; +import dmd.expression.Cat; import dmd.expression.Util; class CatAssignExp : BinExp @@ -54,10 +57,16 @@ e2.rvalue(); + Type tb1next = tb1.nextOf(); + if ((tb1.ty == Tarray) && (tb2.ty == Tarray || tb2.ty == Tsarray) && (e2.implicitConvTo(e1.type) || - tb2.nextOf().implicitConvTo(tb1.nextOf())) +//version(DMDV2) { + tb2.nextOf().implicitConvTo(tb1next) +//} + ) + ) { // Append array e2 = e2.castTo(sc, e1.type); @@ -65,25 +74,37 @@ e = this; } else if ((tb1.ty == Tarray) && - e2.implicitConvTo(tb1.nextOf()) + e2.implicitConvTo(tb1next) ) { // Append element - e2 = e2.castTo(sc, tb1.nextOf()); + e2 = e2.castTo(sc, tb1next); type = e1.type; e = this; } - else - { - error("cannot append type %s to type %s", tb2.toChars(), tb1.toChars()); - type = Type.tint32; - e = this; - } + else if (tb1.ty == Tarray && + (tb1next.ty == Tchar || tb1next.ty == Twchar) && + e2.implicitConvTo(Type.tdchar) + ) + { // Append dchar to char[] or wchar[] + e2 = e2.castTo(sc, Type.tdchar); + type = e1.type; + e = this; + + /* Do not allow appending wchar to char[] because if wchar happens + * to be a surrogate pair, nothing good can result. + */ + } + else + { + error("cannot append type %s to type %s", tb2.toChars(), tb1.toChars()); + e = new ErrorExp(); + } return e; } override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Cat); } override Identifier opId() /* For operator overloading */ @@ -98,16 +119,30 @@ Type tb1 = e1.type.toBasetype(); Type tb2 = e2.type.toBasetype(); - if (tb1.ty == Tarray || tb2.ty == Tsarray) - { elem* e1; - elem* e2; - elem* ep; + if (tb1.ty == Tarray && tb2.ty == Tdchar && + (tb1.nextOf().ty == Tchar || tb1.nextOf().ty == Twchar)) + { // Append dchar to char[] or wchar[] - e1 = this.e1.toElem(irs); + auto e1 = this.e1.toElem(irs); e1 = el_una(OPaddr, TYnptr, e1); - e2 = this.e2.toElem(irs); - if (tybasic(e2.Ety) == TYstruct) + auto e2 = this.e2.toElem(irs); + + auto ep = el_params(e2, e1, null); + int rtl = (tb1.nextOf().ty == Tchar) + ? RTLSYM_ARRAYAPPENDCD + : RTLSYM_ARRAYAPPENDWD; + e = el_bin(OPcall, TYdarray, el_var(rtlsym[rtl]), ep); + el_setLoc(e,loc); + } + else if (tb1.ty == Tarray || tb2.ty == Tsarray) + { + auto e1 = this.e1.toElem(irs); + e1 = el_una(OPaddr, TYnptr, e1); + + auto e2 = this.e2.toElem(irs); + + if (tybasic(e2.Ety) == TYstruct || tybasic(e2.Ety) == TYarray) { e2 = el_una(OPstrpar, TYstruct, e2); e2.Enumbytes = e2.E1.Enumbytes; @@ -118,23 +153,13 @@ if ((tb2.ty == Tarray || tb2.ty == Tsarray) && tb1n.equals(tb2.nextOf().toBasetype())) { // Append array - static if (true) { - ep = el_params(e2, e1, this.e1.type.getTypeInfo(null).toElem(irs), null); + auto ep = el_params(e2, e1, this.e1.type.getTypeInfo(null).toElem(irs), null); e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDT]), ep); - } else { - ep = el_params(el_long(TYint, tb1n.size()), e2, e1, null); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPEND]), ep); - } } else { // Append element - static if (true) { - ep = el_params(e2, e1, this.e1.type.getTypeInfo(null).toElem(irs), null); + auto ep = el_params(e2, e1, this.e1.type.getTypeInfo(null).toElem(irs), null); e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDCT]), ep); - } else { - ep = el_params(e2, el_long(TYint, tb1n.size()), e1, null); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDC]), ep); - } } el_setLoc(e,loc); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/CatExp.d --- a/dmd/CatExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CatExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CatExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.InterState; @@ -13,6 +14,7 @@ import dmd.MATCH; import dmd.ArrayLiteralExp; import dmd.StringExp; +import dmd.ErrorExp; import dmd.WANT; import dmd.Id; import dmd.GlobalExpressions; @@ -58,10 +60,14 @@ e1.type.print(); e2.type.print(); } + Type tb1next = tb1.nextOf(); + Type tb2next = tb2.nextOf(); + if ((tb1.ty == Tsarray || tb1.ty == Tarray) && - e2.type.implicitConvTo(tb1.nextOf()) >= MATCHconst) + e2.implicitConvTo(tb1next) >= MATCHconvert) { - type = tb1.nextOf().arrayOf(); + e2 = e2.implicitCastTo(sc, tb1next); + type = tb1next.arrayOf(); if (tb2.ty == Tarray) { // Make e2 into [e2] @@ -71,9 +77,10 @@ return this; } else if ((tb2.ty == Tsarray || tb2.ty == Tarray) && - e1.type.implicitConvTo(tb2.nextOf()) >= MATCHconst) + e1.implicitConvTo(tb2next) >= MATCHconvert) { - type = tb2.nextOf().arrayOf(); + e1 = e1.implicitCastTo(sc, tb2next); + type = tb2next.arrayOf(); if (tb1.ty == Tarray) { // Make e1 into [e1] @@ -85,12 +92,12 @@ if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && - (tb1.nextOf().mod || tb2.nextOf().mod) && - (tb1.nextOf().mod != tb2.nextOf().mod) + (tb1next.mod || tb2next.mod) && + (tb1next.mod != tb2next.mod) ) { - Type t1 = tb1.nextOf().mutableOf().constOf().arrayOf(); - Type t2 = tb2.nextOf().mutableOf().constOf().arrayOf(); + Type t1 = tb1next.mutableOf().constOf().arrayOf(); + Type t2 = tb2next.mutableOf().constOf().arrayOf(); if (e1.op == TOKstring && !(cast(StringExp)e1).committed) e1.type = t1; else @@ -107,8 +114,8 @@ Type tb = type.toBasetype(); if (tb.ty == Tsarray) type = tb.nextOf().arrayOf(); - if (type.ty == Tarray && tb1.nextOf() && tb2.nextOf() && - tb1.nextOf().mod != tb2.nextOf().mod) + if (type.ty == Tarray && tb1next && tb2next && + tb1next.mod != tb2next.mod) { type = type.nextOf().toHeadMutable().arrayOf(); } @@ -132,8 +139,7 @@ //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars()); error("Can only concatenate arrays, not (%s ~ %s)", e1.type.toChars(), e2.type.toChars()); - type = Type.tint32; - e = this; + return new ErrorExp(); } e.type = e.type.semantic(loc, sc); return e; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Catch.d --- a/dmd/Catch.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Catch.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Catch; +import dmd.common; import dmd.Loc; import dmd.Type; import dmd.Scope; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ClassDeclaration.d --- a/dmd/ClassDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ClassDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ClassDeclaration; +import dmd.common; import dmd.AggregateDeclaration; import dmd.InterfaceDeclaration; import dmd.ThisDeclaration; @@ -9,7 +10,7 @@ import dmd.CtorDeclaration; import dmd.TypeIdentifier; import dmd.STC; -import dmd.Argument; +import dmd.Parameter; import dmd.TypeTuple; import dmd.TY; import dmd.LINK; @@ -24,6 +25,7 @@ import dmd.ArrayTypes; import dmd.BaseClass; import dmd.ClassInfoDeclaration; +import dmd.TypeInfoClassDeclaration; import dmd.Loc; import dmd.Identifier; import dmd.Dsymbol; @@ -62,7 +64,7 @@ import std.string; version (DMDV2) { - enum CLASSINFO_SIZE = (0x3C+16+4); // value of ClassInfo.size + enum CLASSINFO_SIZE = (0x3C+12+4); // value of ClassInfo.size } else { enum CLASSINFO_SIZE = (0x3C+12+4); // value of ClassInfo.size } @@ -86,6 +88,10 @@ static __gshared ClassDeclaration classinfo; ClassDeclaration baseClass; // null only if this is Object +version(DMDV1) { + CtorDeclaration *ctor; + CtorDeclaration *defaultCtor; // default constructor +} FuncDeclaration staticCtor; FuncDeclaration staticDtor; Array vtbl; // Array of FuncDeclaration's making up the vtbl[] @@ -101,12 +107,14 @@ BaseClasses vtblInterfaces; // array of base interfaces that have // their own vtbl[] - ClassInfoDeclaration vclassinfo; // the ClassInfo object for this ClassDeclaration + TypeInfoClassDeclaration vclassinfo; // the ClassInfo object for this ClassDeclaration bool com; // true if this is a COM class (meaning // it derives from IUnknown) bool isauto; // true if this is an auto class bool isabstract; // true if abstract class - +version(DMDV1) { + int isnested; // !=0 if is nested +} int inuse; // to prevent recursive attempts this(Loc loc, Identifier id, BaseClasses baseclasses) @@ -250,6 +258,13 @@ Type.typeinfoshared.error("%s", msg); Type.typeinfoshared = this; } + + if (id == Id.TypeInfo_Wild) + { + if (Type.typeinfowild) + Type.typeinfowild.error("%s", msg); + Type.typeinfowild = this; + } } } @@ -260,7 +275,8 @@ object = this; } - if (id is Id.ClassInfo) +// if (id is Id.ClassInfo) + if (id is Id.TypeInfo_Class) { if (classinfo) classinfo.error("%s", msg); @@ -294,11 +310,11 @@ cd.storage_class |= storage_class; cd.baseclasses.setDim(this.baseclasses.dim); - for (int i = 0; i < cd.baseclasses.dim; i++) + for (size_t i = 0; i < cd.baseclasses.dim; i++) { - BaseClass b = cast(BaseClass)this.baseclasses.data[i]; - BaseClass b2 = new BaseClass(b.type.syntaxCopy(), b.protection); - cd.baseclasses.data[i] = cast(void*)b2; + auto b = this.baseclasses[i]; + auto b2 = new BaseClass(b.type.syntaxCopy(), b.protection); + cd.baseclasses[i] = b2; } ScopeDsymbol.syntaxCopy(cd); @@ -336,7 +352,7 @@ return; } if (symtab) - { if (!scope_) + { if (sizeok == 1 || !scope_) { //printf("\tsemantic for '%s' is already completed\n", toChars()); return; // semantic() already completed } @@ -363,9 +379,9 @@ error("cannot create C++ classes"); // Expand any tuples in baseclasses[] - for (int i = 0; i < baseclasses.dim; ) + for (size_t i = 0; i < baseclasses.dim; ) { - BaseClass b = cast(BaseClass)baseclasses.data[i]; + auto b = baseclasses[i]; //printf("test1 %s %s\n", toChars(), b.type.toChars()); b.type = b.type.semantic(loc, sc); //printf("test2\n"); @@ -376,12 +392,12 @@ TypeTuple tup = cast(TypeTuple)tb; enum PROT protection = b.protection; baseclasses.remove(i); - size_t dim = Argument.dim(tup.arguments); + size_t dim = Parameter.dim(tup.arguments); for (size_t j = 0; j < dim; j++) { - Argument arg = Argument.getNth(tup.arguments, j); + auto arg = Parameter.getNth(tup.arguments, j); b = new BaseClass(arg.type, protection); - baseclasses.insert(i + j, cast(void*)b); + baseclasses.insert(i + j, b); } } else @@ -395,7 +411,7 @@ BaseClass b; Type tb; - b = cast(BaseClass)baseclasses.data[0]; + b = baseclasses[0]; //b.type = b.type.semantic(loc, sc); tb = b.type.toBasetype(); if (tb.ty != TY.Tclass) @@ -463,7 +479,7 @@ BaseClass b; Type tb; - b = cast(BaseClass)baseclasses.data[i]; + b = baseclasses[i]; b.type = b.type.semantic(loc, sc); tb = b.type.toBasetype(); if (tb.ty == TY.Tclass) @@ -492,7 +508,7 @@ // Check for duplicate interfaces for (size_t j = (baseClass ? 1 : 0); j < i; j++) { - BaseClass b2 = cast(BaseClass)baseclasses.data[j]; + auto b2 = baseclasses[j]; if (b2.base == tc.sym) error("inherits from duplicate interface %s", b2.base.toChars()); } @@ -537,7 +553,7 @@ } bt = tbase.semantic(loc, sc).toBasetype(); b = new BaseClass(bt, PROT.PROTpublic); - baseclasses.shift(cast(void*)b); + baseclasses.shift(b); assert(b.type.ty == TY.Tclass); tc = cast(TypeClass)(b.type); baseClass = tc.sym; @@ -546,7 +562,7 @@ } interfaces_dim = baseclasses.dim; - interfaces = cast(BaseClass*)baseclasses.data; + interfaces = baseclasses.ptr; if (baseClass) { @@ -664,7 +680,7 @@ if (isCOMclass()) { -version (_WIN32) { +version (Windows) { sc.linkage = LINK.LINKwindows; } else { /* This enables us to use COM objects under Linux and @@ -690,6 +706,22 @@ structsize = sc.offset; Scope scsave = sc.clone(); sizeok = 0; + + /* Set scope so if there are forward references, we still might be able to + * resolve individual members like enums. + */ + foreach (s; members) + { + /* There are problems doing this in the general case because + * Scope keeps track of things like 'offset' + */ + if (s.isEnumDeclaration() || (s.isAggregateDeclaration() && s.ident)) + { + //printf("setScope %s %s\n", s->kind(), s->toChars()); + s.setScope(sc); + } + } + foreach (Dsymbol s; members) { s.semantic(sc); } @@ -763,9 +795,8 @@ } // Allocate instance of each new interface - for (int i = 0; i < vtblInterfaces.dim; i++) + foreach (b; vtblInterfaces) { - BaseClass b = cast(BaseClass)vtblInterfaces.data[i]; uint thissize = PTRSIZE; alignmember(structalign, thissize, &sc.offset); @@ -812,10 +843,8 @@ if (baseclasses.dim) buf.writestring(" : "); } - for (int i = 0; i < baseclasses.dim; i++) + foreach (size_t i, BaseClass b; baseclasses) { - BaseClass b = cast(BaseClass)baseclasses.data[i]; - if (i) buf.writeByte(','); //buf.writestring(b.base.ident.toChars()); @@ -847,10 +876,8 @@ if (!cd) return 0; //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars()); - for (int i = 0; i < cd.baseclasses.dim; i++) + foreach (b; cd.baseclasses) { - BaseClass b = cast(BaseClass)cd.baseclasses.data[i]; - if (b.base is this || isBaseOf2(b.base)) return 1; } @@ -866,10 +893,8 @@ if (!cd) return 0; //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars()); - for (int i = 0; i < cd.baseclasses.dim; i++) + foreach (b; cd.baseclasses) { - BaseClass b = cast(BaseClass)cd.baseclasses.data[i]; - if (b.base == this || isBaseOf2(b.base)) return 1; } @@ -904,10 +929,8 @@ int i; - for (i = 0; i < baseclasses.dim; i++) + foreach (b; baseclasses) { - BaseClass b = cast(BaseClass)baseclasses.data[i]; - if (b.base) { if (!b.base.symtab) @@ -1015,11 +1038,18 @@ if (b.base.isCPPinterface() && id) id.cpp = 1; - vtblInterfaces.push(cast(void*)b); + vtblInterfaces.push(b); b.copyBaseInterfaces(vtblInterfaces); } } +version(DMDV1) +{ + int isNested() + { + assert(false); + } +} bool isCOMclass() { return com; @@ -1120,17 +1150,14 @@ else { PROT access; - int i; if (smember.isDeclaration().isStatic()) { access_ret = smember.prot(); } - for (i = 0; i < baseclasses.dim; i++) + foreach (b; baseclasses) { - BaseClass b = cast(BaseClass)baseclasses.data[i]; - access = b.base.getAccess(smember); switch (access) { @@ -1170,7 +1197,7 @@ override void addLocalClass(ClassDeclarations aclasses) { - aclasses.push(cast(void*)this); + aclasses.push(this); } // Back end @@ -1289,7 +1316,7 @@ // Put out the TypeInfo type.getTypeInfo(null); - type.vtinfo.toObjFile(multiobj); + //type.vtinfo.toObjFile(multiobj); ////////////////////////////////////////////// @@ -1313,7 +1340,7 @@ OffsetTypeInfo[] offTi; void *defaultConstructor; const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function - TypeInfo typeinfo; + //TypeInfo typeinfo; } */ dt_t* dt = null; @@ -1426,7 +1453,7 @@ dtdword(&dt, 0); // module getMembers() function } - dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr); // typeinfo + //dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr); // typeinfo //dtdword(&dt, 0); ////////////////////////////////////////////// @@ -1435,16 +1462,16 @@ // of the fixup (*) offset += vtblInterfaces.dim * (4 * PTRSIZE); - for (size_t i = 0; i < vtblInterfaces.dim; i++) + foreach (b; vtblInterfaces) { - BaseClass b = cast(BaseClass)vtblInterfaces.data[i]; ClassDeclaration id = b.base; /* The layout is: - * { + * struct Interface + * { * ClassInfo *interface; * void *[] vtbl; - * unsigned offset; + * ptrdiff_t offset; * } */ @@ -1465,9 +1492,8 @@ // Put out the vtblInterfaces.data[].vtbl[] // This must be mirrored with ClassDeclaration.baseVtblOffset() //printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces.dim, toChars()); - for (size_t i = 0; i < vtblInterfaces.dim; i++) + foreach (size_t i, BaseClass b; vtblInterfaces) { - BaseClass b = cast(BaseClass)vtblInterfaces.data[i]; ClassDeclaration id = b.base; int j; @@ -1486,8 +1512,6 @@ assert(id.vtbl.dim == b.vtbl.dim); for (; j < id.vtbl.dim; j++) { - FuncDeclaration fd; - assert(j < b.vtbl.dim); static if (false) { Object o = cast(Object)b.vtbl.data[j]; @@ -1499,7 +1523,7 @@ printf("s.kind() = '%s'\n", s.kind()); } } - fd = cast(FuncDeclaration)b.vtbl.data[j]; + auto fd = cast(FuncDeclaration)b.vtbl.data[j]; if (fd) dtxoff(&dt, fd.toThunkSymbol(b.offset), 0, TYnptr); else @@ -1516,10 +1540,8 @@ for (cd = this.baseClass; cd; cd = cd.baseClass) { - for (int k = 0; k < cd.vtblInterfaces.dim; k++) + foreach (size_t k, BaseClass bs; cd.vtblInterfaces) { - BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k]; - if (bs.fillVtbl(this, bvtbl, 0)) { //printf("\toverriding vtbl[] for %s\n", bs.base.toChars()); @@ -1650,7 +1672,7 @@ { TypeFunction tf = cast(TypeFunction)fd.type; if (tf.ty == Tfunction) - warning("%s%s is hidden by %s\n", fd.toPrettyChars(), Argument.argsTypesToChars(tf.parameters, tf.varargs), toChars()); + warning("%s%s is hidden by %s\n", fd.toPrettyChars(), Parameter.argsTypesToChars(tf.parameters, tf.varargs), toChars()); else warning("%s is hidden by %s\n", fd.toPrettyChars(), toChars()); } @@ -1697,10 +1719,8 @@ csymoffset = CLASSINFO_SIZE; csymoffset += vtblInterfaces.dim * (4 * PTRSIZE); - for (size_t i = 0; i < vtblInterfaces.dim; i++) + foreach (b; vtblInterfaces) { - BaseClass b = cast(BaseClass)vtblInterfaces.data[i]; - if (b == bc) return csymoffset; csymoffset += b.base.vtbl.dim * PTRSIZE; @@ -1715,10 +1735,8 @@ for (cd = this.baseClass; cd; cd = cd.baseClass) { - for (int k = 0; k < cd.vtblInterfaces.dim; k++) + foreach(bs; cd.vtblInterfaces) { - BaseClass bs = cast(BaseClass)cd.vtblInterfaces.data[k]; - if (bs.fillVtbl(this, null, 0)) { if (bc == bs) @@ -1883,10 +1901,8 @@ // Interface vptr initializations toSymbol(); // define csym - for (size_t i = 0; i < vtblInterfaces.dim; i++) + foreach (b; vtblInterfaces) { - BaseClass b = cast(BaseClass)vtblInterfaces.data[i]; - /// version (1 || INTERFACE_VIRTUAL) { for (ClassDeclaration cd2 = cd; 1; cd2 = cd2.baseClass) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/ClassInfoDeclaration.d --- a/dmd/ClassInfoDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ClassInfoDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ClassInfoDeclaration; +import dmd.common; import dmd.VarDeclaration; import dmd.ClassDeclaration; import dmd.Dsymbol; @@ -19,9 +20,9 @@ class ClassInfoDeclaration : VarDeclaration { - ClassDeclaration cd; + ClassDeclaration cd; - this(ClassDeclaration cd) + this(ClassDeclaration cd) { super(Loc(0), ClassDeclaration.classinfo.type, cd.ident, null); @@ -29,26 +30,25 @@ storage_class = STC.STCstatic | STC.STCgshared; } - override Dsymbol syntaxCopy(Dsymbol) + override Dsymbol syntaxCopy(Dsymbol) { - assert(false); + assert(false); // should never be produced by syntax + return null; } - override void semantic(Scope sc) + override void semantic(Scope sc) { - assert(false); } - override void emitComment(Scope sc) + override void emitComment(Scope sc) { - assert(false); } override void toJsonBuffer(OutBuffer buf) { } - - override Symbol* toSymbol() + + override Symbol* toSymbol() { return cd.toSymbol(); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/CmpExp.d --- a/dmd/CmpExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CmpExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CmpExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; @@ -140,7 +141,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon2(istate, &Cmp); } override int isBit() diff -r 786ea1839396 -r 78bf0fe43974 dmd/ComExp.d --- a/dmd/ComExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ComExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ComExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; @@ -12,6 +13,7 @@ import dmd.ArrayTypes; import dmd.TOK; import dmd.TY; +import dmd.Id; import dmd.backend.Util; import dmd.backend.OPER; @@ -68,17 +70,20 @@ override void buildArrayIdent(OutBuffer buf, Expressions arguments) { - assert(false); + e1.buildArrayIdent(buf, arguments); + buf.writestring("Com"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - assert(false); + Expression ex1 = e1.buildArrayLoop(fparams); + Expression e = new ComExp(Loc(0), ex1); + return e; } override Identifier opId() { - assert(false); + return Id.com; } override elem* toElem(IRState* irs) diff -r 786ea1839396 -r 78bf0fe43974 dmd/CommaExp.d --- a/dmd/CommaExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CommaExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CommaExp; +import dmd.common; import dmd.Loc; import dmd.BinExp; import dmd.IRState; @@ -37,6 +38,11 @@ e2.checkEscape(); } + override void checkEscapeRef() + { + e2.checkEscapeRef(); + } + override IntRange getIntRange() { assert(false); diff -r 786ea1839396 -r 78bf0fe43974 dmd/CompileDeclaration.d --- a/dmd/CompileDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CompileDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CompileDeclaration; +import dmd.common; import dmd.AttribDeclaration; import dmd.WANT; import dmd.TOK; diff -r 786ea1839396 -r 78bf0fe43974 dmd/CompileExp.d --- a/dmd/CompileExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CompileExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CompileExp; +import dmd.common; import dmd.Expression; import dmd.UnaExp; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/CompileStatement.d --- a/dmd/CompileStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CompileStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CompileStatement; +import dmd.common; import dmd.Statement; import dmd.Expression; import dmd.Loc; @@ -60,7 +61,7 @@ while (p.token.value != TOK.TOKeof) { Statement s = p.parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope); - a.push(cast(void*)s); + a.push(s); } return a; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/Complex.d --- a/dmd/Complex.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Complex.d Tue Sep 14 15:46:50 2010 +0200 @@ -4,4 +4,6 @@ { T re; T im; + + public static const Complex zero = Complex(0, 0); } \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/ComplexExp.d --- a/dmd/ComplexExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ComplexExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ComplexExp; +import dmd.common; import dmd.Expression; import dmd.InterState; import dmd.Type; @@ -13,6 +14,7 @@ import dmd.TY; import dmd.Port; import dmd.Complex; +import dmd.expression.Util; import dmd.backend.dt_t; import dmd.backend.elem; @@ -104,7 +106,10 @@ override bool isBool(bool result) { - assert(false); + if (result) + return value != Complex!(real).zero; + else + return value == Complex!(real).zero; } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) @@ -114,10 +119,15 @@ override void toMangleBuffer(OutBuffer buf) { - assert(false); + buf.writeByte('c'); + real r = toReal(); + realToMangleBuffer(buf, r); + buf.writeByte('c'); // separate the two + r = toImaginary(); + realToMangleBuffer(buf, r); } + version (_DH) { - OutBuffer hexp; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/CompoundDeclarationStatement.d --- a/dmd/CompoundDeclarationStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CompoundDeclarationStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CompoundDeclarationStatement; +import dmd.common; import dmd.CompoundStatement; import dmd.Loc; import dmd.ArrayTypes; @@ -21,10 +22,10 @@ a.setDim(statements.dim); for (size_t i = 0; i < statements.dim; i++) { - Statement s = cast(Statement)statements.data[i]; + Statement s = statements[i]; if (s) s = s.syntaxCopy(); - a.data[i] = cast(void*)s; + a[i] = s; } CompoundDeclarationStatement cs = new CompoundDeclarationStatement(loc, a); return cs; diff -r 786ea1839396 -r 78bf0fe43974 dmd/CompoundStatement.d --- a/dmd/CompoundStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CompoundStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CompoundStatement; +import dmd.common; import dmd.Loc; import dmd.Statement; import dmd.Array; @@ -42,8 +43,8 @@ statements = new Statements(); statements.reserve(2); - statements.push(cast(void*)s1); - statements.push(cast(void*)s2); + statements.push(s1); + statements.push(s2); } override Statement syntaxCopy() @@ -51,12 +52,11 @@ Statements a = new Statements(); a.setDim(statements.dim); - for (size_t i = 0; i < statements.dim; i++) + foreach (size_t i, Statement s; statements) { - Statement s = cast(Statement)statements.data[i]; if (s) s = s.syntaxCopy(); - a.data[i] = cast(void*)s; + a[i] = s; } return new CompoundStatement(loc, a); @@ -64,8 +64,8 @@ override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - for (int i = 0; i < statements.dim; i++) - { Statement s = cast(Statement) statements.data[i]; + foreach (s; statements) + { if (s) s.toCBuffer(buf, hgs); } @@ -82,7 +82,7 @@ for (size_t i = 0; i < statements.dim; ) { - s = cast(Statement) statements.data[i]; + s = statements[i]; if (s) { Statements a = s.flatten(sc); @@ -96,7 +96,7 @@ s = s.semantic(sc); - statements.data[i] = cast(void*)s; + statements[i] = s; if (s) { Statement sentry; @@ -109,11 +109,11 @@ sentry = sentry.semantic(sc); if (s.isDeclarationStatement()) { - statements.insert(i, cast(void*)sentry); + statements.insert(i, sentry); i++; } else - statements.data[i] = cast(void*)sentry; + statements[i] = sentry; } if (sexception) { @@ -143,7 +143,7 @@ for (int j = i + 1; j < statements.dim; j++) { - aa.push(statements.data[j]); + aa.push(statements[j]); } body_ = new CompoundStatement(Loc(0), aa); body_ = new ScopeStatement(Loc(0), body_); @@ -162,7 +162,7 @@ s = new TryFinallyStatement(Loc(0), s, sfinally); s = s.semantic(sc); statements.setDim(i + 1); - statements.push(cast(void*)s); + statements.push(s); break; } } @@ -170,7 +170,7 @@ { if (0 && i + 1 == statements.dim) { - statements.push(cast(void*)sfinally); + statements.push(sfinally); } else { @@ -184,13 +184,13 @@ for (int j = i + 1; j < statements.dim; j++) { - aa.push(statements.data[j]); + aa.push(statements[j]); } body_ = new CompoundStatement(Loc(0), aa); s = new TryFinallyStatement(Loc(0), body_, sfinally); s = s.semantic(sc); statements.setDim(i + 1); - statements.push(cast(void*)s); + statements.push(s); break; } } @@ -200,22 +200,28 @@ } if (statements.dim == 1) { - return cast(Statement)statements.data[0]; + return statements[0]; } return this; } override bool usesEH() { - assert(false); + foreach (Statement s; statements) + { + if (s && s.usesEH()) + return true; + } + + return false; } override BE blockExit() { //printf("CompoundStatement::blockExit(%p) %d\n", this, statements->dim); BE result = BE.BEfallthru; - for (size_t i = 0; i < statements.dim; i++) - { Statement s = cast(Statement)statements.data[i]; + foreach (s; statements) + { if (s) { //printf("result = x%x\n", result); @@ -243,9 +249,8 @@ override bool isEmpty() { - for (int i = 0; i < statements.dim; i++) + foreach (s; statements) { - Statement s = cast(Statement) statements.data[i]; if (s && !s.isEmpty()) return false; } @@ -261,9 +266,8 @@ { ReturnStatement rs = null; - for (int i = 0; i < statements.dim; i++) + foreach(s; statements) { - Statement s = cast(Statement) statements.data[i]; if (s) { rs = s.isReturnStatement(); @@ -285,10 +289,8 @@ istate.start = null; if (statements) { - for (size_t i = 0; i < statements.dim; i++) + foreach(s; statements) { - Statement s = cast(Statement)statements.data[i]; - if (s) { e = s.interpret(istate); @@ -307,9 +309,8 @@ { int cost = 0; - for (size_t i = 0; i < statements.dim; i++) + foreach(s; statements) { - Statement s = cast(Statement)statements.data[i]; if (s) { cost += s.inlineCost(ics); @@ -326,9 +327,8 @@ Expression e = null; //printf("CompoundStatement.doInline() %d\n", statements.dim); - for (size_t i = 0; i < statements.dim; i++) + foreach(s; statements) { - Statement s = cast(Statement)statements.data[i]; if (s) { Expression e2 = s.doInline(ids); @@ -355,11 +355,10 @@ override Statement inlineScan(InlineScanState* iss) { - for (size_t i = 0; i < statements.dim; i++) + foreach(ref Statement s; statements) { - Statement s = cast(Statement) statements.data[i]; if (s) - statements.data[i] = cast(void*)s.inlineScan(iss); + s = s.inlineScan(iss); } return this; @@ -369,10 +368,8 @@ { if (statements) { - size_t dim = statements.dim; - for (size_t i = 0 ; i < dim ; i++) + foreach(s; statements) { - Statement s = cast(Statement)statements.data[i]; if (s !is null) { s.toIR(irs); diff -r 786ea1839396 -r 78bf0fe43974 dmd/CondExp.d --- a/dmd/CondExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CondExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,9 +1,12 @@ module dmd.CondExp; +import dmd.common; import dmd.BinExp; import dmd.Loc; +import dmd.PtrExp; import dmd.MATCH; import dmd.Expression; +import dmd.GlobalExpressions; import dmd.Scope; import dmd.InterState; import dmd.OutBuffer; @@ -159,7 +162,20 @@ override Expression interpret(InterState istate) { - assert(false); +version (LOG) { + printf("CondExp.interpret() %.*s\n", toChars()); +} + Expression e = econd.interpret(istate); + if (e !is EXP_CANT_INTERPRET) + { + if (e.isBool(true)) + e = e1.interpret(istate); + else if (e.isBool(false)) + e = e2.interpret(istate); + else + e = EXP_CANT_INTERPRET; + } + return e; } override void checkEscape() @@ -168,24 +184,49 @@ e2.checkEscape(); } + override void checkEscapeRef() + { + e1.checkEscapeRef(); + e2.checkEscapeRef(); + } + override int isLvalue() { - assert(false); + return e1.isLvalue() && e2.isLvalue(); } - override Expression toLvalue(Scope sc, Expression e) + override Expression toLvalue(Scope sc, Expression ex) { - assert(false); + PtrExp e; + + // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2) + e = new PtrExp(loc, this, type); + + e1 = e1.addressOf(sc); + //e1 = e1.toLvalue(sc, null); + + e2 = e2.addressOf(sc); + //e2 = e2.toLvalue(sc, null); + + typeCombine(sc); + + type = e2.type; + return e; } override Expression modifiableLvalue(Scope sc, Expression e) { - assert(false); + //error("conditional expression %s is not a modifiable lvalue", toChars()); + e1 = e1.modifiableLvalue(sc, e1); + e2 = e2.modifiableLvalue(sc, e1); + return toLvalue(sc, this); } override Expression checkToBoolean() { - assert(false); + e1 = e1.checkToBoolean(); + e2 = e2.checkToBoolean(); + return this; } override bool checkSideEffect(int flag) diff -r 786ea1839396 -r 78bf0fe43974 dmd/Condition.d --- a/dmd/Condition.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Condition.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Condition; +import dmd.common; import dmd.Loc; import dmd.Scope; import dmd.ScopeDsymbol; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ConditionalDeclaration.d --- a/dmd/ConditionalDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ConditionalDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ConditionalDeclaration; +import dmd.common; import dmd.AttribDeclaration; import dmd.Condition; import dmd.Array; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ConditionalStatement.d --- a/dmd/ConditionalStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ConditionalStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ConditionalStatement; +import dmd.common; import dmd.Statement; import dmd.Condition; import dmd.Loc; @@ -61,8 +62,8 @@ else s = elsebody; - Statements a = new Statements(); - a.push(cast(void*)s); + auto a = new Statements(); + a.push(s); return a; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/ContinueStatement.d --- a/dmd/ContinueStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ContinueStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ContinueStatement; +import dmd.common; import dmd.Statement; import dmd.FuncDeclaration; import dmd.IntegerExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/CppMangleState.d --- a/dmd/CppMangleState.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CppMangleState.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CppMangleState; +import dmd.common; import dmd.Array; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/CtorDeclaration.d --- a/dmd/CtorDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/CtorDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.CtorDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.ArrayTypes; import dmd.Loc; @@ -18,15 +19,15 @@ import dmd.Statement; import dmd.ReturnStatement; import dmd.CompoundStatement; -import dmd.Argument; +import dmd.Parameter; import dmd.Id; class CtorDeclaration : FuncDeclaration { - Arguments arguments; + Parameters arguments; int varargs; - this(Loc loc, Loc endloc, Arguments arguments, int varargs) + this(Loc loc, Loc endloc, Parameters arguments, int varargs) { super(loc, endloc, Id.ctor, STC.STCundefined, null); @@ -45,7 +46,7 @@ f.fbody = fbody ? fbody.syntaxCopy() : null; assert(!fthrows); // deprecated - f.arguments = Argument.arraySyntaxCopy(arguments); + f.arguments = Parameter.arraySyntaxCopy(arguments); return f; } @@ -102,7 +103,7 @@ sc.pop(); // See if it's the default constructor - if (ad && varargs == 0 && Argument.dim(arguments) == 0) + if (ad && varargs == 0 && Parameter.dim(arguments) == 0) { if (ad.isStructDeclaration()) error("default constructor not allowed for structs"); else diff -r 786ea1839396 -r 78bf0fe43974 dmd/DVCondition.d --- a/dmd/DVCondition.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DVCondition.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DVCondition; +import dmd.common; import dmd.Condition; import dmd.Identifier; import dmd.Module; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Dchar.d --- a/dmd/Dchar.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Dchar.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Dchar; +import dmd.common; import core.stdc.wchar_; import core.stdc.string; import core.stdc.ctype; diff -r 786ea1839396 -r 78bf0fe43974 dmd/DebugCondition.d --- a/dmd/DebugCondition.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DebugCondition.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DebugCondition; +import dmd.common; import dmd.DVCondition; import dmd.Module; import dmd.Identifier; @@ -51,9 +52,9 @@ else { if (!mod.debugidsNot) - mod.debugidsNot = new Array(); + mod.debugidsNot = new Vector!string(); - mod.debugidsNot.push(cast(void*)new String(ident.toChars())); + mod.debugidsNot.push(ident.toChars()); } } else if (level <= global.params.debuglevel || level <= mod.debuglevel) diff -r 786ea1839396 -r 78bf0fe43974 dmd/DebugSymbol.d --- a/dmd/DebugSymbol.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DebugSymbol.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,49 +1,96 @@ module dmd.DebugSymbol; +import dmd.common; import dmd.Dsymbol; import dmd.Identifier; import dmd.Loc; import dmd.Scope; import dmd.ScopeDsymbol; +import dmd.Module; import dmd.HdrGenState; +import dmd.Array; import dmd.OutBuffer; +import dmd.condition.util.findCondition; + +/* DebugSymbol's happen for statements like: + * debug = identifier; + * debug = integer; + */ class DebugSymbol : Dsymbol { uint level; this(Loc loc, Identifier ident) { - assert(false); + super(ident); + this.loc = loc; } this(Loc loc, uint level) { - assert(false); + this.level = level; + this.loc = loc; } override Dsymbol syntaxCopy(Dsymbol s) { - assert(false); + assert(!s); + DebugSymbol ds = new DebugSymbol(loc, ident); + ds.level = level; + return ds; } - override bool addMember(Scope sc, ScopeDsymbol s, bool memnum) + override bool addMember(Scope sc, ScopeDsymbol sd, bool memnum) { - assert(false); + //printf("DebugSymbol.addMember('%s') %s\n", sd.toChars(), toChars()); + Module m; + + // Do not add the member to the symbol table, + // just make sure subsequent debug declarations work. + m = sd.isModule(); + if (ident) + { + if (!m) + error("declaration must be at module level"); + else + { + if (findCondition(m.debugidsNot, ident)) + error("defined after use"); + if (!m.debugids) + m.debugids = new Vector!string(); + m.debugids.push(ident.toChars()); /// + } + } + else + { + if (!m) + error("level declaration must be at module level"); + else + m.debuglevel = level; + } + + return false; } override void semantic(Scope sc) { - assert(false); + //printf("DebugSymbol.semantic() %s\n", toChars()); } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + buf.writestring("debug = "); + if (ident) + buf.writestring(ident.toChars()); + else + buf.printf("%u", level); + buf.writestring(";"); + buf.writenl(); } override string kind() { - assert(false); + return "debug"; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/Declaration.d --- a/dmd/Declaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Declaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Declaration; +import dmd.common; import dmd.Dsymbol; import dmd.Type; import dmd.TypedefDeclaration; @@ -81,7 +82,7 @@ { Type type; Type originalType; // before semantic analysis - STC storage_class = STC.STCundefined; + StorageClass storage_class = STC.STCundefined; PROT protection = PROT.PROTundefined; LINK linkage = LINK.LINKdefault; int inuse; // used to detect cycles @@ -157,7 +158,7 @@ string p = null; if (isConst()) p = "const"; - else if (isInvariant()) + else if (isImmutable()) p = "immutable"; else if (storage_class & STC.STCmanifest) p = "enum"; @@ -251,7 +252,6 @@ } case LINK.LINKdefault: - assert(false); error("forward declaration"); return ident.toChars(); @@ -271,7 +271,7 @@ return p; } - int isStatic() { return storage_class & STC.STCstatic; } + bool isStatic() { return (storage_class & STC.STCstatic) != 0; } bool isStaticConstructor() { @@ -303,33 +303,33 @@ return false; } - int isCtorinit() { return storage_class & STC.STCctorinit; } + bool isCtorinit() { return (storage_class & STC.STCctorinit) != 0; } - int isFinal() { return storage_class & STC.STCfinal; } + bool isFinal() { return (storage_class & STC.STCfinal) != 0; } bool isAbstract() { return (storage_class & STC.STCabstract) != 0; } bool isConst() { return (storage_class & STC.STCconst) != 0; } - int isInvariant() { return storage_class & STC.STCinvariant; } + bool isImmutable() { return (storage_class & STC.STCimmutable) != 0; } - int isAuto() { return storage_class & STC.STCauto; } + bool isAuto() { return (storage_class & STC.STCauto) != 0; } - int isScope() { return storage_class & (STC.STCscope | STC.STCauto); } + bool isScope() { return (storage_class & (STC.STCscope | STC.STCauto)) != 0; } - int isSynchronized() { return storage_class & STC.STCsynchronized; } + bool isSynchronized() { return (storage_class & STC.STCsynchronized) != 0; } - int isParameter() { return storage_class & STC.STCparameter; } + bool isParameter() { return (storage_class & STC.STCparameter) != 0; } override bool isDeprecated() { return (storage_class & STC.STCdeprecated) != 0; } - int isOverride() { return storage_class & STC.STCoverride; } + bool isOverride() { return (storage_class & STC.STCoverride) != 0; } - int isIn() { return storage_class & STC.STCin; } + bool isIn() { return (storage_class & STC.STCin) != 0; } - int isOut() { return storage_class & STC.STCout; } + bool isOut() { return (storage_class & STC.STCout) != 0; } - int isRef() { return storage_class & STC.STCref; } + bool isRef() { return (storage_class & STC.STCref) != 0; } override PROT prot() { diff -r 786ea1839396 -r 78bf0fe43974 dmd/DeclarationExp.d --- a/dmd/DeclarationExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DeclarationExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DeclarationExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.InterState; @@ -147,7 +148,7 @@ e = null; } ///version (DMDV2) { - else if (s == v && (v.isConst() || v.isInvariant()) && v.init) + else if (s == v && (v.isConst() || v.isImmutable()) && v.init) ///} else { /// else if (s == v && v.isConst() && v.init) ///} @@ -197,7 +198,8 @@ override void scanForNestedRef(Scope sc) { - assert(false); + //printf("DeclarationExp.scanForNestedRef() %s\n", toChars()); + declaration.parent = sc.parent; } version (DMDV2) { @@ -264,6 +266,7 @@ declaration.isClassDeclaration() || declaration.isFuncDeclaration() || declaration.isTypedefDeclaration() || + declaration.isAttribDeclaration() || declaration.isTemplateMixin() ) return COST_MAX; diff -r 786ea1839396 -r 78bf0fe43974 dmd/DeclarationStatement.d --- a/dmd/DeclarationStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DeclarationStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DeclarationStatement; +import dmd.common; import dmd.Loc; import dmd.ExpStatement; import dmd.Dsymbol; diff -r 786ea1839396 -r 78bf0fe43974 dmd/DefaultInitExp.d --- a/dmd/DefaultInitExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DefaultInitExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DefaultInitExp; +import dmd.common; import dmd.Expression; import dmd.OutBuffer; import dmd.Loc; @@ -18,8 +19,6 @@ this.subop = subop; } - abstract Expression resolve(Loc loc, Scope sc); - override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { buf.writestring(Token.toChars(subop)); diff -r 786ea1839396 -r 78bf0fe43974 dmd/DefaultStatement.d --- a/dmd/DefaultStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DefaultStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DefaultStatement; +import dmd.common; import dmd.Statement; import dmd.Loc; import dmd.Scope; diff -r 786ea1839396 -r 78bf0fe43974 dmd/DelegateExp.d --- a/dmd/DelegateExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DelegateExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DelegateExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.AggregateDeclaration; diff -r 786ea1839396 -r 78bf0fe43974 dmd/DeleteDeclaration.d --- a/dmd/DeleteDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DeleteDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DeleteDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.ArrayTypes; import dmd.Loc; @@ -8,55 +9,101 @@ import dmd.OutBuffer; import dmd.HdrGenState; import dmd.STC; +import dmd.Id; +import dmd.Parameter; +import dmd.ClassDeclaration; +import dmd.TypeFunction; +import dmd.Type; +import dmd.LINK; +import dmd.TY; class DeleteDeclaration : FuncDeclaration { - Arguments arguments; + Parameters arguments; - this(Loc loc, Loc endloc, Arguments arguments) + this(Loc loc, Loc endloc, Parameters arguments) { - assert(false); - super(loc, endloc, null, STC.init, null); + super(loc, endloc, Id.classDelete, STCstatic, null); + this.arguments = arguments; } override Dsymbol syntaxCopy(Dsymbol) { - assert(false); + DeleteDeclaration f; + + f = new DeleteDeclaration(loc, endloc, null); + + FuncDeclaration.syntaxCopy(f); + + f.arguments = Parameter.arraySyntaxCopy(arguments); + + return f; } override void semantic(Scope sc) { - assert(false); + ClassDeclaration cd; + + //printf("DeleteDeclaration.semantic()\n"); + + parent = sc.parent; + Dsymbol parent = toParent(); + 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); + + type = type.semantic(loc, sc); + assert(type.ty == Tfunction); + + // Check that there is only one argument of type void* + TypeFunction tf = cast(TypeFunction)type; + if (Parameter.dim(tf.parameters) != 1) + { + error("one argument of type void* expected"); + } + else + { + auto a = Parameter.getNth(tf.parameters, 0); + if (!a.type.equals(Type.tvoid.pointerTo())) + error("one argument of type void* expected, not %s", a.type.toChars()); + } + + FuncDeclaration.semantic(sc); } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + buf.writestring("delete"); + Parameter.argsToCBuffer(buf, hgs, arguments, 0); + bodyToCBuffer(buf, hgs); } override string kind() { - assert(false); + return "deallocator"; } override bool isDelete() { - assert(false); + return true; } override bool isVirtual() { - assert(false); + return false; } override bool addPreInvariant() { - assert(false); + return false; } override bool addPostInvariant() { - assert(false); + return false; } version (_DH) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/DeleteExp.d --- a/dmd/DeleteExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DeleteExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DeleteExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.UnaExp; @@ -188,7 +189,7 @@ elem* ep; elem* keyti; - if (tybasic(ekey.Ety) == TYstruct) + if (tybasic(ekey.Ety) == TYstruct || tybasic(ekey.Ety) == TYarray) { ekey = el_una(OPstrpar, TYstruct, ekey); ekey.Enumbytes = ekey.E1.Enumbytes; diff -r 786ea1839396 -r 78bf0fe43974 dmd/DivAssignExp.d --- a/dmd/DivAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DivAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DivAssignExp; +import dmd.common; import dmd.BinExp; import dmd.Loc; import dmd.Expression; @@ -16,10 +17,12 @@ import dmd.CommaExp; import dmd.RealExp; import dmd.AssignExp; +import dmd.ArrayLengthExp; import dmd.backend.elem; import dmd.backend.OPER; import dmd.backend.Util; +import dmd.expression.Div; import dmd.expression.Util; class DivAssignExp : BinExp @@ -40,6 +43,15 @@ if (e) return e; +version(DMDV2) { + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } +} + if (e1.op == TOKslice) { // T[] -= ... typeCombine(sc); @@ -94,7 +106,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Div); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -102,9 +114,9 @@ AssignExp_buildArrayIdent(buf, arguments, "Div"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - assert(false); + return AssignExp_buildArrayLoop!(typeof(this))(fparams); } override Identifier opId() /* For operator overloading */ diff -r 786ea1839396 -r 78bf0fe43974 dmd/DivExp.d --- a/dmd/DivExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DivExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DivExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; @@ -41,11 +42,11 @@ return e; typeCombine(sc); - if (e1.op != TOK.TOKslice && e2.op != TOK.TOKslice) - { + if (!e1.isArrayOperand()) e1.checkArithmetic(); + if (!e2.isArrayOperand()) e2.checkArithmetic(); - } + if (type.isfloating()) { Type t1 = e1.type; @@ -107,7 +108,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &Div); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -115,14 +116,9 @@ Exp_buildArrayIdent(buf, arguments, "Div"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - /* Evaluate assign expressions left to right - */ - Expression ex1 = e1.buildArrayLoop(fparams); - Expression ex2 = e2.buildArrayLoop(fparams); - Expression e = new DivExp(Loc(0), ex1, ex2); - return e; + return Exp_buildArrayLoop!(typeof(this))(fparams); } override IntRange getIntRange() diff -r 786ea1839396 -r 78bf0fe43974 dmd/DoStatement.d --- a/dmd/DoStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DoStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DoStatement; +import dmd.common; import dmd.Statement; import dmd.Expression; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/DocComment.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/DocComment.d Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,51 @@ +module dmd.DocComment; + +import dmd.common; +import dmd.Array; +import dmd.Section; +import dmd.Macro; +import dmd.Escape; +import dmd.Scope; +import dmd.Dsymbol; +import dmd.OutBuffer; + +class DocComment +{ + Array sections; // Section*[] + + Section summary; + Section copyright; + Section macros; + Macro** pmacrotable; + Escape** pescapetable; + + this() + { + assert(false); + } + + static DocComment parse(Scope sc, Dsymbol s, ubyte* comment) + { + assert(false); + } + + static void parseMacros(Escape** pescapetable, Macro** pmacrotable, ubyte* m, uint mlen) + { + assert(false); + } + + static void parseEscapes(Escape** pescapetable, ubyte* textstart, uint textlen) + { + assert(false); + } + + void parseSections(ubyte* comment) + { + assert(false); + } + + void writeSections(Scope sc, Dsymbol s, OutBuffer buf) + { + assert(false); + } +} \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/DollarExp.d --- a/dmd/DollarExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DollarExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,11 +1,12 @@ -module dmd.DollarExp; - -import dmd.IdentifierExp; -import dmd.Loc; -import dmd.Identifier; -import dmd.TOK; -import dmd.Id; - +module dmd.DollarExp; + +import dmd.common; +import dmd.IdentifierExp; +import dmd.Loc; +import dmd.Identifier; +import dmd.TOK; +import dmd.Id; + class DollarExp : IdentifierExp { this(Loc loc) diff -r 786ea1839396 -r 78bf0fe43974 dmd/DotExp.d --- a/dmd/DotExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DotExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,8 +1,12 @@ module dmd.DotExp; +import dmd.common; import dmd.Expression; import dmd.Loc; import dmd.Scope; +import dmd.ScopeExp; +import dmd.TemplateDeclaration; +import dmd.DotTemplateExp; import dmd.BinExp; import dmd.TOK; @@ -10,13 +14,31 @@ { this(Loc loc, Expression e1, Expression e2) { - assert(false); - super(loc, TOK.init, 0, e1, e2); + super(loc, TOKdotexp, DotExp.sizeof, e1, e2); } override Expression semantic(Scope sc) { - assert(false); +version (LOGSEMANTIC) { + printf("DotExp.semantic('%s')\n", toChars()); + if (type) printf("\ttype = %s\n", type.toChars()); +} + e1 = e1.semantic(sc); + e2 = e2.semantic(sc); + if (e2.op == TOKimport) + { + ScopeExp se = cast(ScopeExp)e2; + TemplateDeclaration td = se.sds.isTemplateDeclaration(); + if (td) + { + Expression e = new DotTemplateExp(loc, e1, td); + e = e.semantic(sc); + return e; + } + } + if (!type) + type = e2.type; + return this; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/DotIdExp.d --- a/dmd/DotIdExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DotIdExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DotIdExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.IntegerExp; @@ -55,6 +56,12 @@ override Expression semantic(Scope sc) { + // Indicate we didn't come from CallExp::semantic() + return semantic(sc, 0); + } + + Expression semantic(Scope sc, int flag) + { Expression e; Expression eleft; Expression eright; @@ -148,7 +155,7 @@ { auto ee = te.exps[i]; ee = ee.semantic(sc); - ee = new DotIdExp(e.loc, ee, Id.offsetof); + ee = new DotIdExp(ee.loc, ee, Id.offsetof); exps[i] = ee; } e = new TupleExp(loc, exps); @@ -186,7 +193,7 @@ * The check for 'is sds our current module' is because * the current module should have access to its own imports. */ - Dsymbol s = ie.sds.search(loc, ident, + Dsymbol s = ie.sds.search(loc, ident, //0); (ie.sds.isModule() && ie.sds != sc.module_) ? 1 : 0); if (s) { @@ -337,11 +344,13 @@ */ uint errors = global.errors; global.gag++; + Type t1 = e1.type; e = e1.type.dotExp(sc, e1, ident); global.gag--; if (errors != global.errors) // if failed to find the property { global.errors = errors; + e1.type = t1; // kludge to restore type e = new DotIdExp(loc, new IdentifierExp(loc, Id.empty), ident); e = new CallExp(loc, e, e1); } @@ -352,7 +361,8 @@ else { e = e1.type.dotExp(sc, e1, ident); - e = e.semantic(sc); + if (!(flag && e.op == TOK.TOKdotti)) // let CallExp::semantic() handle this + e = e.semantic(sc); return e; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/DotTemplateExp.d --- a/dmd/DotTemplateExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DotTemplateExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DotTemplateExp; +import dmd.common; import dmd.Expression; import dmd.UnaExp; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/DotTemplateInstanceExp.d --- a/dmd/DotTemplateInstanceExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DotTemplateInstanceExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,7 @@ module dmd.DotTemplateInstanceExp; +import dmd.common; +import dmd.ArrayTypes; import dmd.Expression; import dmd.UnaExp; import dmd.OutBuffer; @@ -22,6 +24,10 @@ import dmd.DotVarExp; import dmd.TemplateDeclaration; import dmd.Dsymbol; +import dmd.DotTemplateExp; +import dmd.DotIdExp; +import dmd.TemplateExp; +import dmd.DsymbolExp; import dmd.expression.Util; @@ -32,141 +38,106 @@ { TemplateInstance ti; - this(Loc loc, Expression e, TemplateInstance ti) + this(Loc loc, Expression e, Identifier name, Objects tiargs) { super(loc, TOK.TOKdotti, DotTemplateInstanceExp.sizeof, e); //printf("DotTemplateInstanceExp()\n"); - this.ti = ti; + this.ti = new TemplateInstance(loc, name); + this.ti.tiargs = tiargs; } override Expression syntaxCopy() { - DotTemplateInstanceExp de = new DotTemplateInstanceExp(loc, e1.syntaxCopy(), cast(TemplateInstance)ti.syntaxCopy(null)); + DotTemplateInstanceExp de = new DotTemplateInstanceExp(loc, e1.syntaxCopy(), ti.name, TemplateInstance.arraySyntaxCopy(ti.tiargs)); return de; } - override Expression semantic(Scope sc) + TemplateDeclaration getTempdecl(Scope sc) { - Dsymbol s; - Dsymbol s2; - TemplateDeclaration td; - Expression e; - Identifier id; - Type t1; - Expression eleft = null; - Expression eright; - - version (LOGSEMANTIC) { - printf("DotTemplateInstanceExp.semantic('%s')\n", toChars()); - } - //e1.print(); - //print(); - e1 = e1.semantic(sc); - t1 = e1.type; - if (t1) - t1 = t1.toBasetype(); - //t1.print(); - - /* Extract the following from e1: - * s: the symbol which ti should be a member of - * eleft: if not null, it is the 'this' pointer for ti - */ - - if (e1.op == TOKdotexp) - { - DotExp de = cast(DotExp)e1; - eleft = de.e1; - eright = de.e2; - } - else - { - eleft = null; - eright = e1; - } - if (eright.op == TOKimport) +version(LOGSEMANTIC) { + printf("DotTemplateInstanceExp::getTempdecl('%s')\n", toChars()); +} + if (!ti.tempdecl) { - s = (cast(ScopeExp)eright).sds; - } - else if (e1.op == TOKtype) - { - s = t1.isClassHandle(); - if (!s) + Expression e = new DotIdExp(loc, e1, ti.name); + e = e.semantic(sc); + if (e.op == TOKdottd) { - if (t1.ty == Tstruct) - s = (cast(TypeStruct)t1).sym; - else - goto L1; + auto dte = cast(DotTemplateExp)e; + ti.tempdecl = dte.td; + } + else if (e.op == TOKimport) + { + auto se = cast(ScopeExp)e; + ti.tempdecl = se.sds.isTemplateDeclaration(); } } - else if (t1 && (t1.ty == Tstruct || t1.ty == Tclass)) - { - s = t1.toDsymbol(sc); - eleft = e1; - } - else if (t1 && t1.ty == Tpointer) - { - t1 = (cast(TypePointer)t1).next.toBasetype(); - if (t1.ty != Tstruct) - goto L1; - s = t1.toDsymbol(sc); - eleft = e1; - } - else - { - L1: - error("template %s is not a member of %s", ti.toChars(), e1.toChars()); - goto Lerr; - } - - assert(s); - id = ti.name; - s2 = s.search(loc, id, 0); - if (!s2) + return ti.tempdecl; + } + + override Expression semantic(Scope sc) + { +version (LOGSEMANTIC) { + printf("DotTemplateInstanceExp.semantic('%s')\n", toChars()); +} + Expression eleft; + Expression e = new DotIdExp(loc, e1, ti.name); +L1: + e = e.semantic(sc); + if (e.op == TOKdottd) { - if (!s.ident) - error("template identifier %s is not a member of undefined %s", id.toChars(), s.kind()); - else - error("template identifier %s is not a member of %s %s", id.toChars(), s.kind(), s.ident.toChars()); - goto Lerr; - } - s = s2; - s.semantic(sc); - s = s.toAlias(); - td = s.isTemplateDeclaration(); - if (!td) - { - error("%s is not a template", id.toChars()); - goto Lerr; - } - if (global.errors) - goto Lerr; - - ti.tempdecl = td; - - if (eleft) - { - Declaration v; - + DotTemplateExp dte = cast(DotTemplateExp )e; + TemplateDeclaration td = dte.td; + eleft = dte.e1; + ti.tempdecl = td; ti.semantic(sc); - s = ti.inst.toAlias(); - v = s.isDeclaration(); + Dsymbol s = ti.inst.toAlias(); + Declaration v = s.isDeclaration(); if (v) - { + { e = new DotVarExp(loc, eleft, v); e = e.semantic(sc); return e; } - } - - e = new ScopeExp(loc, ti); - if (eleft) - { + e = new ScopeExp(loc, ti); e = new DotExp(loc, eleft, e); + e = e.semantic(sc); + return e; } - e = e.semantic(sc); - return e; + else if (e.op == TOKimport) + { + auto se = cast(ScopeExp)e; + TemplateDeclaration td = se.sds.isTemplateDeclaration(); + if (!td) + { + error("%s is not a template", e.toChars()); + return new ErrorExp(); + } + ti.tempdecl = td; + e = new ScopeExp(loc, ti); + e = e.semantic(sc); + return e; + } + else if (e.op == TOKdotexp) + { + DotExp de = cast(DotExp )e; - Lerr: + if (de.e2.op == TOKimport) + { + // This should *really* be moved to ScopeExp::semantic() + ScopeExp se = cast(ScopeExp )de.e2; + de.e2 = new DsymbolExp(loc, se.sds); + de.e2 = de.e2.semantic(sc); + } + + if (de.e2.op == TOKtemplate) + { + auto te = cast(TemplateExp) de.e2; + e = new DotTemplateExp(loc,de.e1,te.td); + } + goto L1; + } + error("%s isn't a template", e.toChars()); return new ErrorExp(); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/DotTypeExp.d --- a/dmd/DotTypeExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DotTypeExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DotTypeExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.UnaExp; @@ -13,6 +14,8 @@ import dmd.PREC; import dmd.expression.Util; +import dmd.backend.Util; + class DotTypeExp : UnaExp { Dsymbol sym; @@ -42,7 +45,13 @@ override elem* toElem(IRState* irs) { - assert(false); + // Just a pass-thru to e1 + elem *e; + + //printf("DotTypeExp.toElem() %s\n", toChars()); + e = e1.toElem(irs); + el_setLoc(e,loc); + return e; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/DotVarExp.d --- a/dmd/DotVarExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DotVarExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DotVarExp; +import dmd.common; import dmd.Expression; import dmd.Declaration; import dmd.backend.elem; @@ -68,12 +69,11 @@ * with: * tuple(e1.a, e1.b, e1.c) */ - Expressions exps = new Expressions; + auto exps = new Expressions; exps.reserve(tup.objects.dim); - for (size_t i = 0; i < tup.objects.dim; i++) + foreach (o; tup.objects) { - Object o = cast(Object)tup.objects.data[i]; if (auto e = cast(Expression)o) { if (e.op != TOK.TOKdsymbol) @@ -187,7 +187,7 @@ if (!t1.isMutable() || (t1.ty == TY.Tpointer && !t1.nextOf().isMutable()) || !var.type.isMutable() || !var.type.isAssignable() || var.storage_class & STC.STCmanifest) { - error("cannot modify const/immutable expression %s", toChars()); + error("cannot modify const/immutable/inout expression %s", toChars()); } } } @@ -225,7 +225,41 @@ override Expression interpret(InterState istate) { - assert(false); + Expression e = EXP_CANT_INTERPRET; + +version (LOG) { + printf("DotVarExp.interpret() %.*s\n", toChars()); +} + + Expression ex = e1.interpret(istate); + if (ex !is EXP_CANT_INTERPRET) + { + if (ex.op == TOKstructliteral) + { + StructLiteralExp se = cast(StructLiteralExp)ex; + VarDeclaration v = var.isVarDeclaration(); + if (v) + { + e = se.getField(type, v.offset); + if (!e) + { + error("couldn't find field %s in %s", v.toChars(), type.toChars()); + e = EXP_CANT_INTERPRET; + } + return e; + } + } + else + { + error("%s.%s is not yet implemented at compile time", ex.toChars(), var.toChars()); + } + } + +version (LOG) { + if (e is EXP_CANT_INTERPRET) + printf("DotVarExp.interpret() %.*s = EXP_CANT_INTERPRET\n", toChars()); +} + return e; } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) diff -r 786ea1839396 -r 78bf0fe43974 dmd/Dsymbol.d --- a/dmd/Dsymbol.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Dsymbol.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Dsymbol; +import dmd.common; import dmd.Loc; import dmd.STC; import dmd.Scope; @@ -578,7 +579,7 @@ AggregateDeclaration isThis() // is a 'this' required to access the member { - assert(false); + return null; } ClassDeclaration isClassMember() // are we a member of a class? diff -r 786ea1839396 -r 78bf0fe43974 dmd/DsymbolExp.d --- a/dmd/DsymbolExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DsymbolExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DsymbolExp; +import dmd.common; import dmd.Expression; import dmd.OutBuffer; import dmd.EnumMember; @@ -33,6 +34,7 @@ import dmd.HdrGenState; import dmd.Dsymbol; import dmd.TOK; +import dmd.ErrorExp; class DsymbolExp : Expression { @@ -149,6 +151,7 @@ if (!f.type.deco) { error("forward reference to %s", toChars()); + return new ErrorExp(); } return new VarExp(loc, f, hasOverloads); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/DsymbolTable.d --- a/dmd/DsymbolTable.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DsymbolTable.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DsymbolTable; +import dmd.common; import dmd.StringTable; import dmd.Dsymbol; import dmd.Identifier; diff -r 786ea1839396 -r 78bf0fe43974 dmd/DtorDeclaration.d --- a/dmd/DtorDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/DtorDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.DtorDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.Loc; import dmd.Global; diff -r 786ea1839396 -r 78bf0fe43974 dmd/EnumDeclaration.d --- a/dmd/EnumDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/EnumDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.EnumDeclaration; +import dmd.common; import dmd.ScopeDsymbol; import dmd.AddExp; import dmd.Type; @@ -57,8 +58,10 @@ Expression minval; Expression defaultval; // default initializer } - bool isdeprecated; - + bool isdeprecated = false; + bool isdone = false; // 0: not done + // 1: semantic() successfully completed + this(Loc loc, Identifier id, Type memtype) { super(id); @@ -102,7 +105,7 @@ if (symtab) // if already done { - if (!scope_) + if (isdone || !scope_) return; // semantic() already completed } else @@ -145,7 +148,8 @@ return; } } -static if (false) { +static if (false) +{ // Decided to abandon this restriction for D 2.0 if (!memtype.isintegral()) { error("base type must be of integral type, not %s", memtype.toChars()); @@ -154,6 +158,8 @@ } } + isdone = true; + type = type.semantic(loc, sc); if (isAnonymous()) sce = sc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/EnumMember.d --- a/dmd/EnumMember.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/EnumMember.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.EnumMember; +import dmd.common; import dmd.Dsymbol; import dmd.Expression; import dmd.Type; diff -r 786ea1839396 -r 78bf0fe43974 dmd/EqualExp.d --- a/dmd/EqualExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/EqualExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.EqualExp; +import dmd.common; import dmd.ErrorExp; import dmd.Expression; import dmd.Id; @@ -142,12 +143,12 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon2(istate, &Equal); } - override int isBit() + override bool isBit() { - assert(false); + return true; } override bool isCommutative() @@ -180,21 +181,13 @@ //printf("EqualExp::toElem()\n"); if (t1.ty == Tstruct) { // Do bit compare of struct's - elem* es1; - elem* es2; - elem* ecount; - es1 = e1.toElem(irs); - es2 = e2.toElem(irs); - static if (true) { + auto es1 = e1.toElem(irs); + auto es2 = e2.toElem(irs); es1 = addressElem(es1, t1); es2 = addressElem(es2, t2); - } else { - es1 = el_una(OPaddr, TYnptr, es1); - es2 = el_una(OPaddr, TYnptr, es2); - } e = el_param(es1, es2); - ecount = el_long(TYint, t1.size()); + auto ecount = el_long(TYint, t1.size()); e = el_bin(OPmemcmp, TYint, e, ecount); e = el_bin(eop, TYint, e, el_long(TYint, 0)); el_setLoc(e,loc); @@ -213,24 +206,20 @@ else if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray)) { - elem* ea1; - elem* ea2; - elem* ep; Type telement = t1.nextOf().toBasetype(); - int rtlfunc; - ea1 = e1.toElem(irs); + auto ea1 = e1.toElem(irs); ea1 = array_toDarray(t1, ea1); - ea2 = e2.toElem(irs); + auto ea2 = e2.toElem(irs); ea2 = array_toDarray(t2, ea2); version (DMDV2) { - ep = el_params(telement.arrayOf().getInternalTypeInfo(null).toElem(irs), + auto ep = el_params(telement.arrayOf().getInternalTypeInfo(null).toElem(irs), ea2, ea1, null); - rtlfunc = RTLSYM_ARRAYEQ2; + int rtlfunc = RTLSYM_ARRAYEQ2; } else { - ep = el_params(telement.getInternalTypeInfo(null).toElem(irs), ea2, ea1, null); - rtlfunc = RTLSYM_ARRAYEQ; + auto ep = el_params(telement.getInternalTypeInfo(null).toElem(irs), ea2, ea1, null); + int rtlfunc = RTLSYM_ARRAYEQ; } e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep); if (op == TOKnotequal) diff -r 786ea1839396 -r 78bf0fe43974 dmd/ErrorExp.d --- a/dmd/ErrorExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ErrorExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ErrorExp; +import dmd.common; import dmd.OutBuffer; import dmd.IntegerExp; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ExpInitializer.d --- a/dmd/ExpInitializer.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ExpInitializer.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ExpInitializer; +import dmd.common; import dmd.Initializer; import dmd.DelegateExp; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ExpStatement.d --- a/dmd/ExpStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ExpStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ExpStatement; +import dmd.common; import dmd.Loc; import dmd.Statement; import dmd.AssertExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Expression.d --- a/dmd/Expression.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Expression.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,8 +1,9 @@ module dmd.Expression; +import dmd.common; import dmd.Loc; import dmd.TOK; -import dmd.Argument; +import dmd.Parameter; import dmd.IdentifierExp; import dmd.Type; import dmd.WANT; @@ -52,6 +53,7 @@ import dmd.Complex; import dmd.backend.elem; +import dmd.backend.Util; import dmd.backend.dt_t; import core.memory; @@ -135,6 +137,11 @@ if (t.ty == TY.Tfunction || e.op == TOK.TOKoverloadset) { +static if(false) +{ + if (t.ty == Tfunction && !(cast(TypeFunction)t).isproperty) + error(e.loc, "not a property %s\n", e.toChars()); +} e = new CallExp(e.loc, e); e = e.semantic(sc); } @@ -651,6 +658,10 @@ { } + void checkEscapeRef() + { + } + void checkScalar() { if (!type.isscalar()) @@ -699,12 +710,25 @@ static if (true) { if (sc.func) { + /* Given: + * void f() + * { pure void g() + * { + * void h() + * { + * void i() { } + * } + * } + * } + * g() can call h() but not f() + * i() can call h() and g() but not f() + */ FuncDeclaration outerfunc = sc.func; while (outerfunc.toParent2() && outerfunc.toParent2().isFuncDeclaration()) { outerfunc = outerfunc.toParent2().isFuncDeclaration(); } - if (outerfunc.isPure() && !sc.intypeof && (!f.isNested() && !f.isPure())) + if (outerfunc.isPure() && !sc.intypeof && (!f.isNested() && !f.isPure())) error("pure function '%s' cannot call impure function '%s'\n", sc.func.toChars(), f.toChars()); } @@ -714,6 +738,14 @@ sc.func.toChars(), .toChars()); } } + + void checkSafety(Scope sc, FuncDeclaration f) + { + if (sc.func && sc.func.isSafe() && !sc.intypeof && + !f.isSafe() && !f.isTrusted()) + error("safe function '%s' cannot call system function '%s'\n", + sc.func.toChars(), f.toChars()); + } /***************************** * Check that expression can be tested for true or false. @@ -737,14 +769,13 @@ Expression checkToPointer() { - Expression e; - Type tb; + //writef("Expression::checkToPointer()\n"); + Expression e = this; - //printf("Expression::checkToPointer()\n"); - e = this; - +version(SARRAYVALUE) {} else +{ // If C static array, convert to pointer - tb = type.toBasetype(); + Type tb = type.toBasetype(); if (tb.ty == Tsarray) { TypeSArray ts = cast(TypeSArray)tb; @@ -754,6 +785,7 @@ e = new AddrExp(loc, this); e.type = ts.next.pointerTo(); } +} return e; } @@ -883,9 +915,12 @@ return false; } - int isBit() + /******************************** + * Does this expression result in either a 1 or a 0? + */ + int isBit() { - assert(false); + return false; } /******************************** @@ -926,6 +961,14 @@ } } + /**************************************** + * Resolve __LINE__ and __FILE__ to loc. + */ + Expression resolveLoc(Loc loc, Scope sc) + { + return this; + } + int inlineCost(InlineCostState* ics) { return 1; @@ -981,11 +1024,11 @@ arguments.shift(this); } - Expression buildArrayLoop(Arguments fparams) + Expression buildArrayLoop(Parameters fparams) { Identifier id = Identifier.generateId("c", fparams.dim); - Argument param = new Argument(STC.STCundefined, type, id, null); - fparams.shift(cast(void*)param); + auto param = new Parameter(STC.STCundefined, type, id, null); + fparams.shift(param); Expression e = new IdentifierExp(Loc(0), id); return e; } @@ -1024,12 +1067,21 @@ // Back end elem* toElem(IRState* irs) { + print(); assert(false); + return null; } dt_t** toDt(dt_t** pdt) { - assert(false); + debug + { + writef("Expression::toDt() %d\n", op); + dump(0); + } + error("non-constant expression %s", toChars()); + pdt = dtnzeros(pdt, 1); + return pdt; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/File.d --- a/dmd/File.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/File.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.File; +import dmd.common; import dmd.FileName; import dmd.Array; import dmd.Util; @@ -47,7 +48,7 @@ if (ref_ == 0) { ///free(buffer); } else { -version (_WIN32) { +version (Windows) { if (ref_ == 2) { UnmapViewOfFile(buffer); } @@ -77,7 +78,8 @@ int read() { -version (POSIX) { +version (Posix) +{ int result = 0; string name = this.name.toChars(); @@ -145,7 +147,7 @@ err1: result = 1; return result; -} else version (_WIN32) { +} else version (Windows) { DWORD size; DWORD numread; HANDLE h; @@ -275,7 +277,7 @@ err: return 1; -} else version (_WIN32) { +} else version (Windows) { HANDLE h; DWORD numwritten; diff -r 786ea1839396 -r 78bf0fe43974 dmd/FileExp.d --- a/dmd/FileExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/FileExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.FileExp; +import dmd.common; import dmd.Expression; import dmd.UnaExp; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/FileInitExp.d --- a/dmd/FileInitExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/FileInitExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.FileInitExp; +import dmd.common; import dmd.Expression; import dmd.Loc; import dmd.Scope; @@ -22,7 +23,7 @@ return this; } - override Expression resolve(Loc loc, Scope sc) + override Expression resolveLoc(Loc loc, Scope sc) { //printf("FileInitExp::resolve() %.*s\n", toChars()); string s = loc.filename ? loc.filename : sc.module_.ident.toChars(); diff -r 786ea1839396 -r 78bf0fe43974 dmd/FileName.d --- a/dmd/FileName.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/FileName.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.FileName; +import dmd.common; import dmd.String; import dmd.Array; import dmd.OutBuffer; @@ -41,7 +42,8 @@ override hash_t hashCode() { -version (_WIN32) { +version (Windows) +{ // We need a different hashCode because it must be case-insensitive size_t len = str.length; hash_t hash = 0; @@ -110,11 +112,11 @@ static pure bool absolute(const(char)[] name) { -version (_WIN32) +version (Windows) { return (name[0] == '\\') || (name[0] == '/') || - (name[0] && name[1] == ':'); + ((name.length > 1) && (name[1] == ':')); } else version (POSIX) { @@ -143,7 +145,8 @@ case '/': return null; } -version (_WIN32) { +version (Windows) +{ case '\\': case ':': case '/': @@ -188,11 +191,13 @@ { switch (c) { -version (POSIX) { +version (Posix) +{ case '/': return str[i+1..$]; } -version (_WIN32) { +version (Windows) +{ case '/': case '\\': return str[i+1..$]; @@ -230,13 +235,16 @@ if (n > str.ptr) { auto p = n - 1; -version (POSIX) { +version (Posix) +{ if (*p == '/') n--; -} else version (_WIN32) { +} else version (Windows) +{ if (*p == '\\' || *p == '/') n--; -} else { +} else +{ static assert(false); } } @@ -263,13 +271,16 @@ char* f = cast(char*)GC.malloc(pathlen + 1 + namelen + 1); memcpy(f, path.ptr, pathlen); -version (POSIX) { +version (Posix) +{ if (path[pathlen - 1] != '/') { f[pathlen] = '/'; pathlen++; } -} else version (_WIN32) { +} +else version (Windows) +{ if (path[pathlen - 1] != '\\' && path[pathlen - 1] != '/' && path[pathlen - 1] != ':') @@ -277,7 +288,9 @@ f[pathlen] = '\\'; pathlen++; } -} else { +} +else +{ static assert(false); } memcpy(f + pathlen, name.ptr, namelen + 1); @@ -300,13 +313,15 @@ memcpy(f, path.ptr, pathlen); -version (POSIX) { +version (Posix) { if (path[pathlen - 1] != '/') { f[pathlen] = '/'; pathlen++; } -} else version (_WIN32) { +} +else version (Windows) +{ if (path[pathlen - 1] != '\\' && path[pathlen - 1] != '/' && path[pathlen - 1] != ':') @@ -314,7 +329,9 @@ f[pathlen] = '\\'; pathlen++; } -} else { +} +else +{ static assert(0); } memcpy(f + pathlen, name.ptr, namelen + 1); @@ -355,10 +372,10 @@ version (MACINTOSH) { case ',': } - version (_WIN32) { + version (Windows) { case ';': } - version (POSIX) { + version (Posix) { case ':': } p++; @@ -451,7 +468,7 @@ version (POSIX) { return cmp(e,ext) == 0; -} else version (_WIN32) { +} else version (Windows) { return icmp(e,ext) == 0; } else { static assert(0); @@ -466,9 +483,9 @@ { scope File file = new File(this); -version (_WIN32) { +version (Win32) { file.touchtime = GC.malloc(WIN32_FIND_DATA.sizeof); // keep same file time -} else version (POSIX) { +} else version (Posix) { file.touchtime = GC.malloc(stat_t.sizeof); // keep same file time } else { static assert(0); @@ -537,7 +554,7 @@ static int exists(string name) { -version (POSIX) { +version (Posix) { stat_t st; if (stat(toStringz(name), &st) < 0) @@ -545,7 +562,7 @@ if (S_ISDIR(st.st_mode)) return 2; return 1; -} else version (_WIN32) { +} else version (Win32) { HANDLE h = CreateFileA(toStringz(name), GENERIC_READ, FILE_SHARE_READ, null, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, HANDLE.init); /// if (h == INVALID_HANDLE_VALUE) { return 0; @@ -569,6 +586,8 @@ static void ensurePathExists(string path) { + if (path.length == 0) + return; try { mkdirRecurse(path); } catch { diff -r 786ea1839396 -r 78bf0fe43974 dmd/ForStatement.d --- a/dmd/ForStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ForStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,7 +1,9 @@ module dmd.ForStatement; +import dmd.common; import dmd.Statement; import dmd.Expression; +import dmd.GlobalExpressions; import dmd.Loc; import dmd.Scope; import dmd.InterState; @@ -155,7 +157,79 @@ override Expression interpret(InterState istate) { - assert(false); +version (LOG) { + printf("ForStatement.interpret()\n"); +} + if (istate.start == this) + istate.start = null; + + Expression e; + + if (init) + { + e = init.interpret(istate); + if (e is EXP_CANT_INTERPRET) + return e; + assert(!e); + } + + if (istate.start) + { + e = body_ ? body_.interpret(istate) : null; + if (istate.start) + return null; + if (e is EXP_CANT_INTERPRET) + return e; + if (e is EXP_BREAK_INTERPRET) + return null; + if (e is EXP_CONTINUE_INTERPRET) + goto Lcontinue; + if (e) + return e; + } + + while (true) + { + if (!condition) + goto Lhead; + e = condition.interpret(istate); + if (e is EXP_CANT_INTERPRET) + break; + if (!e.isConst()) + { + e = EXP_CANT_INTERPRET; + break; + } + if (e.isBool(true)) + { + Lhead: + e = body_ ? body_.interpret(istate) : null; + if (e is EXP_CANT_INTERPRET) + break; + if (e is EXP_BREAK_INTERPRET) + { + e = null; + break; + } + if (e && e !is EXP_CONTINUE_INTERPRET) + break; + Lcontinue: + if (increment) + { + e = increment.interpret(istate); + if (e is EXP_CANT_INTERPRET) + break; + } + } + else if (e.isBool(false)) + { + e = null; + break; + } + else + assert(0); + } + return e; } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) diff -r 786ea1839396 -r 78bf0fe43974 dmd/ForeachRangeStatement.d --- a/dmd/ForeachRangeStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ForeachRangeStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,9 +1,10 @@ module dmd.ForeachRangeStatement; +import dmd.common; import dmd.Statement; import dmd.TOK; import dmd.Token; -import dmd.Argument; +import dmd.Parameter; import dmd.Expression; import dmd.Statement; import dmd.VarDeclaration; @@ -36,14 +37,14 @@ class ForeachRangeStatement : Statement { TOK op; // TOK.TOKforeach or TOK.TOKforeach_reverse - Argument arg; // loop index variable + Parameter arg; // loop index variable Expression lwr; Expression upr; Statement body_; VarDeclaration key = null; - this(Loc loc, TOK op, Argument arg, Expression lwr, Expression upr, Statement body_) + this(Loc loc, TOK op, Parameter arg, Expression lwr, Expression upr, Statement body_) { super(loc); this.op = op; @@ -120,17 +121,17 @@ ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr); VarDeclaration tmp = new VarDeclaration(loc, arg.type, id, ie); - Statements cs = new Statements(); + auto cs = new Statements(); // Keep order of evaluation as lwr, then upr if (op == TOKforeach) { - cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, key))); - cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs.push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); + cs.push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); } else { - cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); - cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, key))); + cs.push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs.push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); } Statement forinit = new CompoundDeclarationStatement(loc, cs); diff -r 786ea1839396 -r 78bf0fe43974 dmd/ForeachStatement.d --- a/dmd/ForeachStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ForeachStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ForeachStatement; +import dmd.common; import dmd.Statement; import dmd.TOK; import dmd.Token; @@ -63,7 +64,7 @@ import dmd.AddAssignExp; import dmd.CmpExp; import dmd.Id; -import dmd.Argument; +import dmd.Parameter; import dmd.STC; import dmd.expression.Util; @@ -73,7 +74,7 @@ class ForeachStatement : Statement { TOK op; // TOKforeach or TOKforeach_reverse - Arguments arguments; // array of Argument*'s + Parameters arguments; // array of Argument*'s Expression aggr; Statement body_; @@ -85,7 +86,7 @@ Array cases; // put breaks, continues, gotos and returns here Array gotos; // forward referenced goto's go here - this(Loc loc, TOK op, Arguments arguments, Expression aggr, Statement body_) + this(Loc loc, TOK op, Parameters arguments, Expression aggr, Statement body_) { super(loc); @@ -100,9 +101,9 @@ override Statement syntaxCopy() { - Arguments args = Argument.arraySyntaxCopy(arguments); + auto args = Parameter.arraySyntaxCopy(arguments); Expression exp = aggr.syntaxCopy(); - ForeachStatement s = new ForeachStatement(loc, op, args, exp, + auto s = new ForeachStatement(loc, op, args, exp, body_ ? body_.syntaxCopy() : null); return s; } @@ -114,6 +115,7 @@ Statement s = this; size_t dim = arguments.dim; TypeAArray taa = null; + Dsymbol sapply = null; Type tn = null; Type tnv = null; @@ -152,7 +154,7 @@ return s; } - TypeTuple tuple = cast(TypeTuple)tab; + auto tuple = cast(TypeTuple)tab; Statements statements = new Statements(); //printf("aggr: op = %d, %s\n", aggr.op, aggr.toChars()); size_t n; @@ -164,7 +166,7 @@ } else if (aggr.op == TOK.TOKtype) // type tuple { - n = Argument.dim(tuple.arguments); + n = Parameter.dim(tuple.arguments); } else assert(0); @@ -177,10 +179,10 @@ if (te) e = te.exps[k]; else - t = Argument.getNth(tuple.arguments, k).type; + t = Parameter.getNth(tuple.arguments, k).type; - Argument arg = cast(Argument)arguments.data[0]; - Statements st = new Statements(); + auto arg = arguments[0]; + auto st = new Statements(); if (dim == 2) { @@ -202,8 +204,8 @@ VarDeclaration var = new VarDeclaration(loc, arg.type, arg.ident, ie); var.storage_class |= STC.STCmanifest; DeclarationExp de = new DeclarationExp(loc, var); - st.push(cast(void*)new ExpStatement(loc, de)); - arg = cast(Argument)arguments.data[1]; // value + st.push(new ExpStatement(loc, de)); + arg = arguments[1]; // value } // Declare value if (arg.storageClass & (STC.STCout | STC.STCref | STC.STClazy)) @@ -214,7 +216,7 @@ Type tb = e.type.toBasetype(); if ((tb.ty == TY.Tfunction || tb.ty == TY.Tsarray) && e.op == TOK.TOKvar) { - VarExp ve = cast(VarExp)e; + auto ve = cast(VarExp)e; var = new AliasDeclaration(loc, arg.ident, ve.var); } else @@ -233,13 +235,13 @@ var = new AliasDeclaration(loc, arg.ident, t); } - DeclarationExp de = new DeclarationExp(loc, var); - st.push(cast(void*)new ExpStatement(loc, de)); + auto de = new DeclarationExp(loc, var); + st.push(new ExpStatement(loc, de)); - st.push(cast(void*)body_.syntaxCopy()); + st.push(body_.syntaxCopy()); s = new CompoundStatement(loc, st); s = new ScopeStatement(loc, s); - statements.push(cast(void*)s); + statements.push(s); } s = new UnrolledLoopStatement(loc, statements); @@ -254,6 +256,9 @@ sc.noctor++; Lagain: + Identifier idapply = (op == TOK.TOKforeach_reverse) + ? Id.applyReverse : Id.apply; + sapply = null; switch (tab.ty) { case TY.Tarray: @@ -273,10 +278,10 @@ tn = tab.nextOf().toBasetype(); if (tn.ty == TY.Tchar || tn.ty == TY.Twchar || tn.ty == TY.Tdchar) { - Argument arg; + Parameter arg; int i = (dim == 1) ? 0 : 1; // index of value - arg = cast(Argument)arguments.data[i]; + arg = arguments[i]; arg.type = arg.type.semantic(loc, sc); tnv = arg.type.toBasetype(); if (tnv.ty != tn.ty && (tnv.ty == TY.Tchar || tnv.ty == TY.Twchar || tnv.ty == TY.Tdchar)) @@ -285,7 +290,7 @@ error("foreach: value of UTF conversion cannot be ref"); if (dim == 2) { - arg = cast(Argument)arguments.data[0]; + arg = arguments[0]; if (arg.storageClass & STC.STCref) error("foreach: key cannot be ref"); } @@ -296,9 +301,9 @@ for (size_t i = 0; i < dim; i++) { // Declare args - Argument arg = cast(Argument)arguments.data[i]; + auto arg = arguments[i]; Type argtype = arg.type.semantic(loc, sc); - VarDeclaration var = new VarDeclaration(loc, argtype, arg.ident, null); + auto var = new VarDeclaration(loc, argtype, arg.ident, null); var.storage_class |= STC.STCforeach; var.storage_class |= arg.storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STC_TYPECTOR); if (var.storage_class & (STC.STCref | STC.STCout)) @@ -355,9 +360,9 @@ else key.init = new ExpInitializer(loc, new IntegerExp(0)); - Statements cs = new Statements(); - cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); - cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, key))); + auto cs = new Statements(); + cs.push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs.push(new DeclarationStatement(loc, new DeclarationExp(loc, key))); Statement forinit = new CompoundDeclarationStatement(loc, cs); Expression cond; @@ -444,6 +449,15 @@ case TY.Tclass: case TY.Tstruct: version (DMDV2) { + /* Prefer using opApply, if it exists + */ + if (dim != 1) // only one argument allowed with ranges + goto Lapply; + + sapply = search_function(cast(AggregateDeclaration)tab.toDsymbol(sc), idapply); + if (sapply) + goto Lapply; + { /* Look for range iteration, i.e. the properties * .empty, .next, .retreat, .head and .rear * foreach (e; aggr) { ... } @@ -453,9 +467,6 @@ * ... * } */ - if (dim != 1) // only one argument allowed with ranges - goto Lapply; - AggregateDeclaration ad = (tab.ty == TY.Tclass) ? cast(AggregateDeclaration)(cast(TypeClass)tab).sym : cast(AggregateDeclaration)(cast(TypeStruct)tab).sym; @@ -507,12 +518,12 @@ e = new VarExp(loc, r); Expression einit = new DotIdExp(loc, e, idhead); // einit = einit.semantic(sc); - Argument arg = cast(Argument)arguments.data[0]; - VarDeclaration ve = new VarDeclaration(loc, arg.type, arg.ident, new ExpInitializer(loc, einit)); + auto arg = arguments[0]; + auto ve = new VarDeclaration(loc, arg.type, arg.ident, new ExpInitializer(loc, einit)); ve.storage_class |= STC.STCforeach; ve.storage_class |= arg.storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STC_TYPECTOR); - DeclarationExp de = new DeclarationExp(loc, ve); + auto de = new DeclarationExp(loc, ve); Statement body2 = new CompoundStatement(loc, new DeclarationStatement(loc, de), this.body_); s = new ForStatement(loc, init, condition, increment, body2); @@ -530,16 +541,9 @@ case TY.Tdelegate: Lapply: { - FuncDeclaration fdapply; - Arguments args; Expression ec; Expression e; - FuncLiteralDeclaration fld; - Argument a; - Type t; - Expression flde; - Identifier id; - Type tret; + Parameter a; if (!checkForArgTypes()) { @@ -547,12 +551,12 @@ return this; } - tret = func.type.nextOf(); + Type tret = func.type.nextOf(); // Need a variable to hold value from any return statements in body. if (!sc.func.vresult && tret && tret != Type.tvoid) { - VarDeclaration v = new VarDeclaration(loc, tret, Id.result, null); + auto v = new VarDeclaration(loc, tret, Id.result, null); v.noauto = true; v.semantic(sc); if (!sc.insert(v)) @@ -565,10 +569,11 @@ /* Turn body into the function literal: * int delegate(ref T arg) { body } */ - args = new Arguments(); + auto args = new Parameters(); for (size_t i = 0; i < dim; i++) { - Argument arg = cast(Argument)arguments.data[i]; + auto arg = arguments[i]; + Identifier id; arg.type = arg.type.semantic(loc, sc); if (arg.storageClass & STC.STCref) @@ -576,45 +581,42 @@ else { // Make a copy of the ref argument so it isn't // a reference. - VarDeclaration v; - Initializer ie; - id = Lexer.uniqueId("__applyArg", i); - ie = new ExpInitializer(Loc(0), new IdentifierExp(Loc(0), id)); - v = new VarDeclaration(Loc(0), arg.type, arg.ident, ie); + Initializer ie = new ExpInitializer(Loc(0), new IdentifierExp(Loc(0), id)); + auto v = new VarDeclaration(Loc(0), arg.type, arg.ident, ie); s = new DeclarationStatement(Loc(0), v); body_ = new CompoundStatement(loc, s, body_); } - a = new Argument(STC.STCref, arg.type, id, null); - args.push(cast(void*)a); + a = new Parameter(STC.STCref, arg.type, id, null); + args.push(a); } - t = new TypeFunction(args, Type.tint32, 0, LINK.LINKd); - fld = new FuncLiteralDeclaration(loc, Loc(0), t, TOK.TOKdelegate, this); + Type t = new TypeFunction(args, Type.tint32, 0, LINK.LINKd); + FuncLiteralDeclaration fld = new FuncLiteralDeclaration(loc, Loc(0), t, TOK.TOKdelegate, this); fld.fbody = body_; - flde = new FuncExp(loc, fld); + Expression flde = new FuncExp(loc, fld); flde = flde.semantic(sc); fld.tookAddressOf = 0; // Resolve any forward referenced goto's - for (int i = 0; i < gotos.dim; i++) + for (size_t i = 0; i < gotos.dim; i++) { - CompoundStatement cs = cast(CompoundStatement)gotos.data[i]; - GotoStatement gs = cast(GotoStatement)cs.statements.data[0]; + auto cs = cast(CompoundStatement)gotos.data[i]; + auto gs = cast(GotoStatement)cs.statements[0]; if (!gs.label.statement) { // 'Promote' it to this scope, and replace with a return cases.push(cast(void*)gs); s = new ReturnStatement(Loc(0), new IntegerExp(cases.dim + 1)); - cs.statements.data[0] = cast(void*)s; + cs.statements[0] = s; } } if (tab.ty == TY.Taarray) { // Check types - Argument arg = cast(Argument)arguments.data[0]; + auto arg = arguments[0]; if (dim == 2) { if (arg.storageClass & STC.STCref) @@ -622,7 +624,7 @@ if (!arg.type.equals(taa.index)) error("foreach: index must be type %s, not %s", taa.index.toChars(), arg.type.toChars()); - arg = cast(Argument)arguments.data[1]; + arg = arguments[1]; } if (!arg.type.equals(taa.nextOf())) error("foreach: value must be type %s, not %s", taa.nextOf().toChars(), arg.type.toChars()); @@ -630,6 +632,7 @@ /* Call: * _aaApply(aggr, keysize, flde) */ + FuncDeclaration fdapply; if (dim == 2) fdapply = FuncDeclaration.genCfunc(Type.tindex, "_aaApply2"); else @@ -673,7 +676,7 @@ string r = (op == TOK.TOKforeach_reverse) ? "R" : ""; int j = sprintf(fdname.ptr, "_aApply%.*s%.*s%zd".ptr, r, 2, fntab[flag].ptr, dim); assert(j < fdname.sizeof); - fdapply = FuncDeclaration.genCfunc(Type.tindex, fdname[0..j].idup); + FuncDeclaration fdapply = FuncDeclaration.genCfunc(Type.tindex, fdname[0..j].idup); ec = new VarExp(Loc(0), fdapply); auto exps = new Expressions(); @@ -699,10 +702,9 @@ else { assert(tab.ty == TY.Tstruct || tab.ty == TY.Tclass); - Identifier idapply = (op == TOK.TOKforeach_reverse) - ? Id.applyReverse : Id.apply; - Dsymbol sapply = search_function(cast(AggregateDeclaration)tab.toDsymbol(sc), idapply); - Expressions exps = new Expressions(); + auto exps = new Expressions(); + if (!sapply) + sapply = search_function(cast(AggregateDeclaration)tab.toDsymbol(sc), idapply); static if (false) { TemplateDeclaration td; if (sapply && (td = sapply.isTemplateDeclaration()) !is null) @@ -710,11 +712,9 @@ /* Call: * aggr.apply!(fld)() */ - TemplateInstance ti = new TemplateInstance(loc, idapply); Objects tiargs = new Objects(); tiargs.push(cast(void*)fld); - ti.tiargs = tiargs; - ec = new DotTemplateInstanceExp(loc, aggr, ti); + ec = new DotTemplateInstanceExp(loc, aggr, idapply, tiargs); } else { @@ -743,19 +743,19 @@ else { // Construct a switch statement around the return value // of the apply function. - Statements a2 = new Statements(); + auto a2 = new Statements(); // default: break; takes care of cases 0 and 1 s = new BreakStatement(Loc(0), null); s = new DefaultStatement(Loc(0), s); - a2.push(cast(void*)s); + a2.push(s); // cases 2... for (int i = 0; i < cases.dim; i++) { s = cast(Statement)cases.data[i]; s = new CaseStatement(Loc(0), new IntegerExp(i + 2), s); - a2.push(cast(void*)s); + a2.push(s); } s = new CompoundStatement(loc, a2); @@ -780,9 +780,8 @@ { bool result = true; - for (size_t i = 0; i < arguments.dim; i++) + foreach (arg; arguments) { - Argument arg = cast(Argument)arguments.data[i]; if (!arg.type) { error("cannot infer type for %s", arg.ident.toChars()); @@ -841,7 +840,7 @@ buf.writestring(" ("); for (int i = 0; i < arguments.dim; i++) { - Argument a = cast(Argument)arguments.data[i]; + auto a = arguments[i]; if (i) buf.writestring(", "); if (a.storageClass & STCref) diff -r 786ea1839396 -r 78bf0fe43974 dmd/FuncAliasDeclaration.d --- a/dmd/FuncAliasDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/FuncAliasDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.FuncAliasDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.backend.Symbol; diff -r 786ea1839396 -r 78bf0fe43974 dmd/FuncDeclaration.d --- a/dmd/FuncDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/FuncDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.FuncDeclaration; +import dmd.common; import dmd.Declaration; import dmd.DotIdExp; import dmd.AddrExp; @@ -53,7 +54,7 @@ import dmd.PtrExp; import dmd.DeclarationExp; import dmd.InlineDoState; -import dmd.Argument; +import dmd.Parameter; import dmd.StructDeclaration; import dmd.ClassDeclaration; import dmd.InterfaceDeclaration; @@ -72,6 +73,7 @@ import dmd.TypeFunction; import dmd.Expression; import dmd.STC; +import dmd.TRUST; import dmd.Dsymbol; import dmd.Scope; import dmd.OutBuffer; @@ -193,7 +195,7 @@ int nestedFrameRef; // !=0 if nested variables referenced } - this(Loc loc, Loc endloc, Identifier id, STC storage_class, Type type) + this(Loc loc, Loc endloc, Identifier id, StorageClass storage_class, Type type) { super(id); @@ -307,37 +309,59 @@ originalType = type; if (!type.deco) { - /* Apply const and invariant storage class + sc = sc.push(); + sc.stc |= storage_class & STC.STCref; // forward refness to function type + type = type.semantic(loc, sc); + sc = sc.pop(); + + /* Apply const, immutable and shared storage class * to the function type */ - type = type.semantic(loc, sc); - STC stc = storage_class; - if (type.isInvariant()) + StorageClass stc = storage_class; + if (type.isImmutable()) stc |= STC.STCimmutable; if (type.isConst()) stc |= STC.STCconst; if (type.isShared() || storage_class & STC.STCsynchronized) stc |= STC.STCshared; + if (type.isWild()) + stc |= STC.STCwild; switch (stc & STC.STC_TYPECTOR) { case STC.STCimmutable: case STC.STCimmutable | STC.STCconst: case STC.STCimmutable | STC.STCconst | STC.STCshared: case STC.STCimmutable | STC.STCshared: + case STC.STCimmutable | STC.STCwild: + case STC.STCimmutable | STC.STCconst | STC.STCwild: + case STC.STCimmutable | STC.STCconst | STC.STCshared | STC.STCwild: + case STC.STCimmutable | STC.STCshared | STC.STCwild: // Don't use toInvariant(), as that will do a merge() type = type.makeInvariant(); goto Lmerge; case STC.STCconst: + case STC.STCconst | STC.STCwild: type = type.makeConst(); goto Lmerge; case STC.STCshared | STC.STCconst: + case STC.STCshared | STC.STCconst | STC.STCwild: type = type.makeSharedConst(); goto Lmerge; case STC.STCshared: type = type.makeShared(); + goto Lmerge; + + case STC.STCwild: + type = type.makeWild(); + goto Lmerge; + + case STC.STCshared | STC.STCwild: + type = type.makeSharedWild(); + goto Lmerge; + Lmerge: if (!(type.ty == Tfunction && !type.nextOf())) /* Can't do merge if return type is not known yet @@ -352,14 +376,14 @@ assert(0); } } - //type.print(); + storage_class &= ~STC.STCref; if (type.ty != TY.Tfunction) { error("%s must be a function", toChars()); return; } f = cast(TypeFunction)type; - size_t nparams = Argument.dim(f.parameters); + size_t nparams = Parameter.dim(f.parameters); linkage = sc.linkage; // if (!parent) @@ -376,7 +400,7 @@ if (isAbstract() && !isVirtual()) error("non-virtual functions cannot be abstract"); - if ((f.isConst() || f.isInvariant()) && !isThis()) + if ((f.isConst() || f.isImmutable()) && !isThis()) error("without 'this' cannot be const/immutable"); if (isAbstract() && isFinal()) @@ -732,7 +756,7 @@ case 1: { - Argument arg0 = Argument.getNth(f.parameters, 0); + auto arg0 = Parameter.getNth(f.parameters, 0); if (arg0.type.ty != TY.Tarray || arg0.type.nextOf().ty != TY.Tarray || arg0.type.nextOf().nextOf().ty != TY.Tchar || @@ -766,7 +790,7 @@ } else { - Argument arg0 = Argument.getNth(f.parameters, 0); + auto arg0 = Parameter.getNth(f.parameters, 0); Type t0 = arg0.type.toBasetype(); Type tb = sd ? sd.type : cd.type; if (arg0.type.implicitConvTo(tb) || @@ -775,7 +799,7 @@ { if (nparams == 1) goto Lassignerr; - Argument arg1 = Argument.getNth(f.parameters, 1); + auto arg1 = Parameter.getNth(f.parameters, 1); if (arg1.defaultArg) goto Lassignerr; } @@ -816,12 +840,12 @@ outId = Id.result; // provide a default Loc loc = fensure.loc; - Arguments arguments = new Arguments(); - Argument a = null; + auto arguments = new Parameters(); + Parameter a = null; if (outId) { - a = new Argument(STCref, f.nextOf(), outId, null); - arguments.push(cast(void*)a); + a = new Parameter(STCref, f.nextOf(), outId, null); + arguments.push(a); } TypeFunction tf = new TypeFunction(arguments, Type.tvoid, 0, LINKd); FuncDeclaration fd = new FuncDeclaration(loc, loc, Id.ensure, STCundefined, tf); @@ -922,8 +946,10 @@ sc2.sw = null; sc2.fes = fes; sc2.linkage = LINK.LINKd; - sc2.stc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCabstract | STC.STCdeprecated | STC.STC_TYPECTOR | STC.STCfinal | STC.STCtls | STC.STCgshared | STC.STCref); - sc2.protection = PROT.PROTpublic; + sc2.stc &= ~(STC.STCauto | STC.STCscope | STC.STCstatic | STC.STCabstract | STC.STCdeprecated | + STC.STC_TYPECTOR | STC.STCfinal | STC.STCtls | STC.STCgshared | STC.STCref | + STCproperty | STCsafe | STCtrusted | STCsystem); + sc2.protection = PROT.PROTpublic; sc2.explicitProtection = 0; sc2.structalign = 8; sc2.incontract = 0; @@ -961,7 +987,7 @@ thandle = thandle.nextOf().constOf().pointerTo(); } } - else if (storage_class & STC.STCimmutable || type.isInvariant()) + else if (storage_class & STC.STCimmutable || type.isImmutable()) { if (thandle.ty == TY.Tclass) thandle = thandle.invariantOf(); @@ -1050,29 +1076,29 @@ } } } - +static if(false) { // Propagate storage class from tuple parameters to their element-parameters. if (f.parameters) { - for (size_t i = 0; i < f.parameters.dim; i++) - { Argument arg = cast(Argument)f.parameters.data[i]; - + foreach (arg; f.parameters) + { //printf("[%d] arg.type.ty = %d %s\n", i, arg.type.ty, arg.type.toChars()); if (arg.type.ty == TY.Ttuple) - { TypeTuple t = cast(TypeTuple)arg.type; - size_t dim = Argument.dim(t.arguments); + { auto t = cast(TypeTuple)arg.type; + size_t dim = Parameter.dim(t.arguments); for (size_t j = 0; j < dim; j++) - { Argument narg = Argument.getNth(t.arguments, j); - narg.storageClass = arg.storageClass; + { + auto narg = Parameter.getNth(t.arguments, j); + narg.storageClass = arg.storageClass; } } } } - +} /* Declare all the function parameters as variables * and install them in parameters[] */ - size_t nparams = Argument.dim(f.parameters); + size_t nparams = Parameter.dim(f.parameters); if (nparams) { /* parameters[] has all the tuples removed, as the back end * doesn't know about tuples @@ -1081,7 +1107,7 @@ parameters.reserve(nparams); for (size_t i = 0; i < nparams; i++) { - Argument arg = Argument.getNth(f.parameters, i); + auto arg = Parameter.getNth(f.parameters, i); Identifier id = arg.ident; if (!id) { @@ -1113,26 +1139,25 @@ // but not in parameters[]. if (f.parameters) { - for (size_t i = 0; i < f.parameters.dim; i++) - { Argument arg = cast(Argument)f.parameters.data[i]; - + foreach (arg; f.parameters) + { if (!arg.ident) continue; // never used, so ignore if (arg.type.ty == TY.Ttuple) - { TypeTuple t = cast(TypeTuple)arg.type; - size_t dim = Argument.dim(t.arguments); + { auto t = cast(TypeTuple)arg.type; + size_t dim = Parameter.dim(t.arguments); Objects exps = new Objects(); exps.setDim(dim); for (size_t j = 0; j < dim; j++) - { Argument narg = Argument.getNth(t.arguments, j); + { auto narg = Parameter.getNth(t.arguments, j); assert(narg.ident); VarDeclaration v = sc2.search(Loc(0), narg.ident, null).isVarDeclaration(); assert(v); Expression e = new VarExp(v.loc, v); - exps.data[j] = cast(void*)e; + exps[j] = e; } assert(arg.ident); - TupleDeclaration v = new TupleDeclaration(loc, arg.ident, exps); + auto v = new TupleDeclaration(loc, arg.ident, exps); //printf("declaring tuple %s\n", v.toChars()); v.isexp = 1; if (!sc2.insert(v)) @@ -1191,15 +1216,16 @@ if (outId) { // Declare result variable - VarDeclaration v; Loc loc = this.loc; if (fensure) loc = fensure.loc; - v = new VarDeclaration(loc, type.nextOf(), outId, null); + auto v = new VarDeclaration(loc, type.nextOf(), outId, null); v.noauto = true; version (DMDV2) { + if (!isVirtual()) + v.storage_class |= STC.STCconst; if (f.isref) { v.storage_class |= STC.STCref | STC.STCforeach; @@ -1430,7 +1456,7 @@ } { - Statements a = new Statements(); + auto a = new Statements(); // Merge in initialization of 'out' parameters if (parameters) @@ -1442,7 +1468,7 @@ assert(v.init); ExpInitializer ie = v.init.isExpInitializer(); assert(ie); - a.push(cast(void*)new ExpStatement(Loc(0), ie.exp)); + a.push(new ExpStatement(Loc(0), ie.exp)); } } } @@ -1472,7 +1498,7 @@ Expression e = new SymOffExp(Loc(0), p, offset); e = new AssignExp(Loc(0), e1, e); e.type = t; - a.push(cast(void*)new ExpStatement(Loc(0), e)); + a.push(new ExpStatement(Loc(0), e)); p.isargptr = true; } } @@ -1488,7 +1514,7 @@ e = new AssignExp(Loc(0), e1, e); e.op = TOK.TOKconstruct; e = e.semantic(sc2); - a.push(cast(void*)new ExpStatement(Loc(0), e)); + a.push(new ExpStatement(Loc(0), e)); } // Merge contracts together with body into one compound statement @@ -1500,7 +1526,7 @@ } } else { if (frequire && global.params.useIn) - a.push(cast(void*)frequire); + a.push(frequire); } // Precondition invariant @@ -1542,17 +1568,17 @@ } if (e) { - ExpStatement s = new ExpStatement(Loc(0), e); - a.push(cast(void*)s); + auto s = new ExpStatement(Loc(0), e); + a.push(s); } } if (fbody) - a.push(cast(void*)fbody); + a.push(fbody); if (fensure) { - a.push(cast(void*)returnLabel.statement); + a.push(returnLabel.statement); if (type.nextOf().ty != TY.Tvoid) { @@ -1563,8 +1589,8 @@ { e = e.implicitCastTo(sc, tintro.nextOf()); e = e.semantic(sc); } - ReturnStatement s = new ReturnStatement(Loc(0), e); - a.push(cast(void*)s); + auto s = new ReturnStatement(Loc(0), e); + a.push(s); } } @@ -1898,7 +1924,7 @@ //printf("tf = %s, args = %s\n", tf.deco, ((Expression *)arguments.data[0]).type.deco); error(loc, "%s%s is not callable using argument types %s", - Argument.argsTypesToChars(tf.parameters, tf.varargs), + Parameter.argsTypesToChars(tf.parameters, tf.varargs), buf2.toChars(), buf.toChars()); return m.anyf; // as long as it's not a FuncAliasDeclaration @@ -1911,8 +1937,8 @@ error(loc, "called with argument types:\n\t(%s)\nmatches both:\n\t%s%s\nand:\n\t%s%s", buf.toChars(), - m.lastf.toPrettyChars(), Argument.argsTypesToChars(t1.parameters, t1.varargs), - m.nextf.toPrettyChars(), Argument.argsTypesToChars(t2.parameters, t2.varargs)); + m.lastf.toPrettyChars(), Parameter.argsTypesToChars(t1.parameters, t1.varargs), + m.nextf.toPrettyChars(), Parameter.argsTypesToChars(t2.parameters, t2.varargs)); } else { error(loc, "overloads %s and %s both match argument list for %s", m.lastf.type.toChars(), @@ -1944,8 +1970,8 @@ TypeFunction tf = cast(TypeFunction)type; TypeFunction tg = cast(TypeFunction)g.type; - size_t nfparams = Argument.dim(tf.parameters); - size_t ngparams = Argument.dim(tg.parameters); + size_t nfparams = Parameter.dim(tf.parameters); + size_t ngparams = Parameter.dim(tg.parameters); MATCH match = MATCHexact; /* If both functions have a 'this' pointer, and the mods are not @@ -1968,7 +1994,7 @@ args.setDim(nfparams); for (int u = 0; u < nfparams; u++) { - Argument p = Argument.getNth(tf.parameters, u); + auto p = Parameter.getNth(tf.parameters, u); Expression e; if (p.storageClass & (STCref | STCout)) { @@ -2253,6 +2279,18 @@ return (cast(TypeFunction)this.type).ispure; } + int isSafe() + { + assert(type.ty == TY.Tfunction); + return (cast(TypeFunction)this.type).trust == TRUST.TRUSTsafe; + } + + int isTrusted() + { + assert(type.ty == TY.Tfunction); + return (cast(TypeFunction)this.type).trust == TRUST.TRUSTtrusted; + } + bool isNested() { //if (!toParent()) @@ -2288,7 +2326,7 @@ return isMember() && !(isStatic() || protection == PROT.PROTprivate || protection == PROT.PROTpackage) && toParent().isClassDeclaration(); } - override int isFinal() + override bool isFinal() { ClassDeclaration cd; static if (false) { @@ -2339,13 +2377,28 @@ } if (global.errors) return null; +version(DMDV1) +{ if (ident == Id.aaLen) return interpret_aaLen(istate, arguments); else if (ident == Id.aaKeys) return interpret_aaKeys(istate, arguments); else if (ident == Id.aaValues) return interpret_aaValues(istate, arguments); - +} +else version(DMDV2) +{ + if (thisarg && (!arguments || arguments.dim == 0)) + { + if (ident == Id.length) + return interpret_length(istate, thisarg); + else if (ident == Id.keys) + return interpret_keys(istate, thisarg, this); + else if (ident == Id.values) + return interpret_values(istate, thisarg, this); + } +} + if (cantInterpret || semanticRun == 3) return null; @@ -2368,20 +2421,20 @@ assert(tb.ty == Tfunction); TypeFunction tf = cast(TypeFunction)tb; Type tret = tf.next.toBasetype(); - if (tf.varargs) + if (tf.varargs && arguments && parameters && arguments.dim != parameters.dim) { cantInterpret = 1; - error("Variadic functions are not yet implemented in CTFE"); + error("C-style variadic functions are not yet implemented in CTFE"); return null; } // Ensure there are no lazy parameters if (tf.parameters) { - size_t dim = Argument.dim(tf.parameters); + size_t dim = Parameter.dim(tf.parameters); for (size_t i = 0; i < dim; i++) { - Argument arg = Argument.getNth(tf.parameters, i); + auto arg = Parameter.getNth(tf.parameters, i); if (arg.storageClass & STClazy) { cantInterpret = 1; @@ -2419,7 +2472,7 @@ for (size_t i = 0; i < dim; i++) { Expression earg = arguments[i]; - Argument arg = Argument.getNth(tf.parameters, i); + auto arg = Parameter.getNth(tf.parameters, i); if (arg.storageClass & (STCout | STCref)) { @@ -2448,7 +2501,7 @@ for (size_t i = 0; i < dim; i++) { auto earg = eargs[i]; - Argument arg = Argument.getNth(tf.parameters, i); + auto arg = Parameter.getNth(tf.parameters, i); auto v = cast(VarDeclaration)parameters[i]; vsave[i] = v.value; version (LOG) { @@ -2516,7 +2569,7 @@ } } // Don't restore the value of 'this' upon function return - if (needThis() && thisarg.op==TOKvar) { + if (needThis() && thisarg.op == TOKvar && istate) { VarDeclaration thisvar = (cast(VarExp)thisarg).var.isVarDeclaration(); foreach (size_t i, Dsymbol s; istate.vars) { @@ -2531,7 +2584,7 @@ /* Save the values of the local variables used */ - scope Expressions valueSaves = new Expressions(); + scope valueSaves = new Expressions(); if (istate && !isNested()) { //printf("saving local variables...\n"); @@ -3804,6 +3857,35 @@ } } + /********************************************* + * Return the function's parameter list, and whether + * it is variadic or not. + */ + + Parameters getParameters(int *pvarargs) + { + Parameters fparameters; + int fvarargs; + + if (type) + { + assert(type.ty == Tfunction); + auto fdtype = cast(TypeFunction)type; + fparameters = fdtype.parameters; + fvarargs = fdtype.varargs; + } + else // Constructors don't have type's + { + CtorDeclaration fctor = isCtorDeclaration(); + assert(fctor); + fparameters = fctor.arguments; + fvarargs = fctor.varargs; + } + if (pvarargs) + *pvarargs = fvarargs; + return fparameters; + } + override FuncDeclaration isFuncDeclaration() { return this; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/FuncExp.d --- a/dmd/FuncExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/FuncExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.FuncExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.OutBuffer; @@ -86,7 +87,8 @@ override void scanForNestedRef(Scope sc) { - assert(false); + //printf("FuncExp.scanForNestedRef(%s)\n", toChars()); + //fd.parent = sc.parent; } override string toChars() @@ -121,7 +123,8 @@ override int inlineCost(InlineCostState* ics) { - assert(false); + // Right now, this makes the function be output to the .obj file twice. + return COST_MAX; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/FuncLiteralDeclaration.d --- a/dmd/FuncLiteralDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/FuncLiteralDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.FuncLiteralDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.TOK; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Global.d --- a/dmd/Global.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Global.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Global; +import dmd.common; import dmd.Array; import dmd.Param; @@ -38,7 +39,7 @@ string[] path; // Array of char*'s which form the import lookup path string[] filePath; // Array of char*'s which form the file import lookup path int structalign = 8; - string version_ = "v2.036"; + string version_ = "v2.039"; Param params; uint errors; // number of errors reported so far diff -r 786ea1839396 -r 78bf0fe43974 dmd/GlobalExpressions.d --- a/dmd/GlobalExpressions.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/GlobalExpressions.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.GlobalExpressions; +import dmd.common; import dmd.Expression; import dmd.TOK; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/GotoCaseStatement.d --- a/dmd/GotoCaseStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/GotoCaseStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.GotoCaseStatement; +import dmd.common; import dmd.Statement; import dmd.Expression; import dmd.CaseStatement; @@ -12,6 +13,11 @@ import dmd.BE; import dmd.WANT; +import dmd.backend.Util; +import dmd.backend.block; +import dmd.backend.BC; +import dmd.backend.Blockx; + class GotoCaseStatement : Statement { Expression exp; // NULL, or which case to goto @@ -74,6 +80,39 @@ override void toIR(IRState* irs) { - assert(false); + block* b; + Blockx* blx = irs.blx; + block* bdest = cs.cblock; + + if (!bdest) + { + bdest = block_calloc(blx); + cs.cblock = bdest; + } + + b = blx.curblock; + + // The rest is equivalent to GotoStatement + + // Adjust exception handler scope index if in different try blocks + if (b.Btry != bdest.Btry) + { + // Check that bdest is in an enclosing try block + for (block* bt = b.Btry; bt != bdest.Btry; bt = bt.Btry) + { + if (!bt) + { + //printf("b.Btry = %p, bdest.Btry = %p\n", b.Btry, bdest.Btry); + error("cannot goto into try block"); + break; + } + } + + //setScopeIndex(blx, b, bdest.Btry ? bdest.Btry.Bscope_index : -1); + } + + list_append(&b.Bsucc,bdest); + incUsage(irs, loc); + block_next(blx, BC.BCgoto, null); } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/GotoDefaultStatement.d --- a/dmd/GotoDefaultStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/GotoDefaultStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.GotoDefaultStatement; +import dmd.common; import dmd.Statement; import dmd.SwitchStatement; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/GotoStatement.d --- a/dmd/GotoStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/GotoStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.GotoStatement; +import dmd.common; import dmd.Loc; import dmd.Scope; import dmd.Statement; @@ -55,10 +56,10 @@ * so we can patch it later, and add it to a 'look at this later' * list. */ - Statements a = new Statements(); + auto a = new Statements(); Statement s; - a.push(cast(void*)this); + a.push(this); s = new CompoundStatement(loc, a); sc.fes.gotos.push(cast(void*)s); // 'look at this later' list return s; diff -r 786ea1839396 -r 78bf0fe43974 dmd/HaltExp.d --- a/dmd/HaltExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/HaltExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.HaltExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/IRState.d --- a/dmd/IRState.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/IRState.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.IRState; +import dmd.common; import dmd.Statement; import dmd.Module; import dmd.Dsymbol; @@ -8,6 +9,10 @@ import dmd.FuncDeclaration; import dmd.Global; import dmd.Loc; +import dmd.TRUST; +import dmd.TY; +import dmd.TypeFunction; +import dmd.Type; import dmd.backend.Symbol; import dmd.backend.Blockx; @@ -123,6 +128,28 @@ } return cast(FuncDeclaration)(bc.symbol); } + + /********************** + * Return !=0 if do array bounds checking + */ + int arrayBoundsCheck() + { + int result = global.params.useArrayBounds; + + if (result == 1) + { + // For safe functions only + result = 0; + FuncDeclaration fd = getFunc(); + if (fd) + { + Type t = fd.type; + if (t.ty == TY.Tfunction && (cast(TypeFunction)t).trust == TRUST.TRUSTsafe) + result = 1; + } + } + return result; + } } /********************************************* diff -r 786ea1839396 -r 78bf0fe43974 dmd/Id.d --- a/dmd/Id.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Id.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Id; +import dmd.common; import dmd.Identifier; import dmd.Lexer; @@ -78,7 +79,6 @@ ID( "coverage", "__coverage" ), ID( "__vptr" ), ID( "__monitor" ), - ID( "system" ), ID( "TypeInfo" ), ID( "TypeInfo_Class" ), @@ -96,6 +96,8 @@ ID( "TypeInfo_Const" ), ID( "TypeInfo_Invariant" ), ID( "TypeInfo_Shared" ), + ID( "TypeInfo_Wild", "TypeInfo_Inout" ), + ID( "elements" ), ID( "_arguments_typeinfo" ), ID( "_arguments" ), @@ -145,6 +147,9 @@ ID( "idup" ), ID( "property" ), + ID( "safe" ), + ID( "trusted" ), + ID( "system" ), // For inline assembler ID( "___out", "out" ), @@ -210,8 +215,12 @@ ID( "opIn_r" ), ID( "opStar" ), ID( "opDot" ), + ID( "opDispatch" ), ID( "opImplicitCast" ), - + ID( "pow", "opPow" ), + ID( "pow_r", "opPow_r" ), + ID( "powass", "opPowAssign" ), + ID( "classNew", "new" ), ID( "classDelete", "delete" ), @@ -271,6 +280,7 @@ ID( "cos" ), ID( "tan" ), ID( "_sqrt", "sqrt" ), + ID( "_pow", "pow" ), ID( "fabs" ), // Traits @@ -286,6 +296,9 @@ ID( "isVirtualFunction" ), ID( "isAbstractFunction" ), ID( "isFinalFunction" ), + ID( "isRef" ), + ID( "isOut" ), + ID( "isLazy" ), ID( "hasMember" ), ID( "getMember" ), ID( "getVirtualFunctions" ), diff -r 786ea1839396 -r 78bf0fe43974 dmd/Identifier.d --- a/dmd/Identifier.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Identifier.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Identifier; +import dmd.common; import dmd.TOK; import dmd.DYNCAST; import dmd.Lexer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/IdentifierExp.d --- a/dmd/IdentifierExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/IdentifierExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.IdentifierExp; +import dmd.common; import dmd.Expression; import dmd.Declaration; import dmd.TY; diff -r 786ea1839396 -r 78bf0fe43974 dmd/IdentityExp.d --- a/dmd/IdentityExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/IdentityExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.IdentityExp; +import dmd.common; import dmd.Expression; import dmd.InterState; import dmd.Loc; @@ -52,12 +53,10 @@ override Expression optimize(int result) { - Expression e; - //printf("IdentityExp.optimize(result = %d) %s\n", result, toChars()); e1 = e1.optimize(WANT.WANTvalue | (result & WANT.WANTinterpret)); e2 = e2.optimize(WANT.WANTvalue | (result & WANT.WANTinterpret)); - e = this; + Expression e = this; if ((this.e1.isConst() && this.e2.isConst()) || (this.e1.op == TOK.TOKnull && this.e2.op == TOK.TOKnull)) { @@ -71,7 +70,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon2(istate, &Identity); } override elem* toElem(IRState* irs) diff -r 786ea1839396 -r 78bf0fe43974 dmd/IfStatement.d --- a/dmd/IfStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/IfStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,7 +1,8 @@ module dmd.IfStatement; +import dmd.common; import dmd.Statement; -import dmd.Argument; +import dmd.Parameter; import dmd.Loc; import dmd.Expression; import dmd.VarDeclaration; @@ -31,14 +32,14 @@ class IfStatement : Statement { - Argument arg; + Parameter arg; Expression condition; Statement ifbody; Statement elsebody; VarDeclaration match; // for MatchExpression results - this(Loc loc, Argument arg, Expression condition, Statement ifbody, Statement elsebody) + this(Loc loc, Parameter arg, Expression condition, Statement ifbody, Statement elsebody) { super(loc); this.arg = arg; @@ -57,7 +58,7 @@ if (elsebody) e = elsebody.syntaxCopy(); - Argument a = arg ? arg.syntaxCopy() : null; + Parameter a = arg ? arg.syntaxCopy() : null; IfStatement s = new IfStatement(loc, a, condition.syntaxCopy(), i, e); return s; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/Import.d --- a/dmd/Import.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Import.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,7 +1,9 @@ module dmd.Import; +import dmd.common; import dmd.Dsymbol; import dmd.Array; +import dmd.ArrayTypes; import dmd.DsymbolTable; import dmd.PROT; import dmd.Identifier; @@ -40,7 +42,7 @@ class Import : Dsymbol { - Array packages; // array of Identifier's representing packages + Identifiers packages; // array of Identifier's representing packages Identifier id; // module Identifier Identifier aliasId; int isstatic; // !=0 if static import @@ -54,7 +56,7 @@ Module mod; Package pkg; // leftmost package/module - this(Loc loc, Array packages, Identifier id, Identifier aliasId, int isstatic) + this(Loc loc, Identifiers packages, Identifier id, Identifier aliasId, int isstatic) { super(id); @@ -73,7 +75,7 @@ this.ident = aliasId; // Kludge to change Import identifier to first package else if (packages && packages.dim) - this.ident = cast(Identifier)packages.data[0]; + this.ident = packages[0]; } void addAlias(Identifier name, Identifier alias_) @@ -246,9 +248,8 @@ if (packages) { - for (size_t i = 0; i < packages.dim; i++) + foreach (pid; packages) { - Identifier pid = cast(Identifier)packages.data[i]; ob.printf("%s.", pid.toChars()); } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/InExp.d --- a/dmd/InExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/InExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.InExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/IndexExp.d --- a/dmd/IndexExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/IndexExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.IndexExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.InterState; @@ -12,6 +13,7 @@ import dmd.ScopeDsymbol; import dmd.TY; import dmd.ArrayScopeSymbol; +import dmd.PREC; import dmd.TypeNext; import dmd.TypeSArray; import dmd.TypeAArray; @@ -23,7 +25,7 @@ import dmd.WANT; import dmd.TupleExp; import dmd.TypeTuple; -import dmd.Argument; +import dmd.Parameter; import dmd.TypeExp; import dmd.VarExp; import dmd.STC; @@ -34,6 +36,7 @@ import dmd.expression.util.arrayTypeCompatible; import dmd.expression.Util; import dmd.expression.Index; +import dmd.expression.ArrayLength; import dmd.backend.Symbol; import dmd.backend.Util; @@ -156,7 +159,7 @@ else if (e1.op == TOKtype) { tup = cast(TypeTuple)t1; - length = Argument.dim(tup.arguments); + length = Parameter.dim(tup.arguments); } else assert(0); @@ -164,9 +167,9 @@ if (index < length) { if (e1.op == TOKtuple) - e = cast(Expression)te.exps.data[cast(size_t)index]; + e = te.exps[cast(size_t)index]; else - e = new TypeExp(e1.loc, Argument.getNth(tup.arguments, cast(size_t)index).type); + e = new TypeExp(e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type); } else { @@ -187,7 +190,7 @@ override int isLvalue() { - assert(false); + return true; } override Expression toLvalue(Scope sc, Expression e) @@ -212,7 +215,10 @@ override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + expToCBuffer(buf, hgs, e1, PREC.PREC_primary); + buf.writeByte('['); + expToCBuffer(buf, hgs, e2, PREC.PREC_assign); + buf.writeByte(']'); } override Expression optimize(int result) @@ -245,7 +251,35 @@ override Expression interpret(InterState istate) { - assert(false); + Expression e; + Expression e1; + Expression e2; + + version (LOG) { + printf("IndexExp.interpret() %s\n", toChars()); + } + e1 = this.e1.interpret(istate); + if (e1 is EXP_CANT_INTERPRET) + goto Lcant; + + if (e1.op == TOKstring || e1.op == TOKarrayliteral) + { + /* Set the $ variable + */ + e = ArrayLength(Type.tsize_t, e1); + if (e is EXP_CANT_INTERPRET) + goto Lcant; + if (lengthVar) + lengthVar.value = e; + } + + e2 = this.e2.interpret(istate); + if (e2 is EXP_CANT_INTERPRET) + goto Lcant; + return Index(type, e1, e2); + + Lcant: + return EXP_CANT_INTERPRET; } override Expression doInline(InlineDoState ids) @@ -287,7 +321,14 @@ override void scanForNestedRef(Scope sc) { - assert(false); + e1.scanForNestedRef(sc); + + if (lengthVar) + { + //printf("lengthVar\n"); + lengthVar.parent = sc.parent; + } + e2.scanForNestedRef(sc); } override elem* toElem(IRState* irs) @@ -342,7 +383,7 @@ ep = el_params(n2, valuesize, keyti, n1, null); e = el_bin(OPcall, TYnptr, el_var(s), ep); - if (global.params.useArrayBounds) + if (irs.arrayBoundsCheck()) { elem* ea; @@ -365,7 +406,7 @@ elem* einit = resolveLengthVar(lengthVar, &n1, t1); elem* n2 = e2.toElem(irs); - if (global.params.useArrayBounds) + if (irs.arrayBoundsCheck()) { elem* elength; elem* n2x; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Initializer.d --- a/dmd/Initializer.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Initializer.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Initializer; +import dmd.common; import dmd.Loc; import dmd.Scope; import dmd.Type; @@ -37,7 +38,6 @@ Type inferType(Scope sc) { error(loc, "cannot infer type from initializer"); - halt(); return Type.terror; } @@ -64,10 +64,10 @@ a = new Initializers(); a.setDim(ai.dim); for (int i = 0; i < a.dim; i++) - { Initializer e = cast(Initializer)ai.data[i]; + { Initializer e = ai[i]; e = e.syntaxCopy(); - a.data[i] = cast(void*) e; + a[i] = e; } } return a; diff -r 786ea1839396 -r 78bf0fe43974 dmd/InlineCostState.d --- a/dmd/InlineCostState.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/InlineCostState.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.InlineCostState; +import dmd.common; import dmd.FuncDeclaration; import dmd.Expression; diff -r 786ea1839396 -r 78bf0fe43974 dmd/InlineDoState.d --- a/dmd/InlineDoState.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/InlineDoState.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.InlineDoState; +import dmd.common; import dmd.Array; import dmd.Dsymbol; import dmd.VarDeclaration; diff -r 786ea1839396 -r 78bf0fe43974 dmd/InlineScanState.d --- a/dmd/InlineScanState.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/InlineScanState.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.InlineScanState; +import dmd.common; import dmd.FuncDeclaration; import dmd.ExpInitializer; import dmd.Dsymbol; @@ -30,7 +31,7 @@ { for (size_t i = 0; i < td.objects.dim; i++) { - DsymbolExp se = cast(DsymbolExp)td.objects.data[i]; + auto se = cast(DsymbolExp)td.objects[i]; assert(se.op == TOKdsymbol); scanVar(se.s, iss); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/IntegerExp.d --- a/dmd/IntegerExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/IntegerExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.IntegerExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.TY; @@ -168,11 +169,7 @@ */ if (!global.errors) { - printf("ty = %d, %d\n", type.ty, t.ty); - if (type.ty == Tenum) { - printf("test1\n"); - } - ///type.print(); + writef("%s %p\n", type.toChars(), type); assert(0); } break; @@ -212,7 +209,8 @@ override bool isBool(bool result) { - return result ? value != 0 : value == 0; + int r = toInteger() != 0; + return cast(bool)(result ? r : !r); } override MATCH implicitConvTo(Type t) diff -r 786ea1839396 -r 78bf0fe43974 dmd/InterState.d --- a/dmd/InterState.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/InterState.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.InterState; +import dmd.common; import dmd.FuncDeclaration; import dmd.Dsymbol; import dmd.Expression; diff -r 786ea1839396 -r 78bf0fe43974 dmd/InterfaceDeclaration.d --- a/dmd/InterfaceDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/InterfaceDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.InterfaceDeclaration; +import dmd.common; import dmd.ClassDeclaration; import dmd.Loc; import dmd.DsymbolTable; @@ -7,7 +8,7 @@ import dmd.Type; import dmd.TY; import dmd.LINK; -import dmd.Argument; +import dmd.Parameter; import dmd.Util; import dmd.TypeTuple; import dmd.PROT; @@ -49,7 +50,15 @@ override Dsymbol syntaxCopy(Dsymbol s) { - assert(false); + InterfaceDeclaration id; + + if (s) + id = cast(InterfaceDeclaration)s; + else + id = new InterfaceDeclaration(loc, ident, null); + + ClassDeclaration.syntaxCopy(id); + return id; } override void semantic(Scope sc) @@ -95,7 +104,7 @@ // Expand any tuples in baseclasses[] for (size_t i = 0; i < baseclasses.dim; ) { - BaseClass b = cast(BaseClass)baseclasses.data[0]; + auto b = baseclasses[0]; b.type = b.type.semantic(loc, sc); Type tb = b.type.toBasetype(); @@ -103,11 +112,11 @@ { TypeTuple tup = cast(TypeTuple)tb; PROT protection = b.protection; baseclasses.remove(i); - size_t dim = Argument.dim(tup.arguments); + size_t dim = Parameter.dim(tup.arguments); for (size_t j = 0; j < dim; j++) - { Argument arg = Argument.getNth(tup.arguments, j); + { auto arg = Parameter.getNth(tup.arguments, j); b = new BaseClass(arg.type, protection); - baseclasses.insert(i + j, cast(void*)b); + baseclasses.insert(i + j, b); } } else @@ -124,7 +133,7 @@ BaseClass b; Type tb; - b = cast(BaseClass)baseclasses.data[i]; + b = baseclasses[i]; b.type = b.type.semantic(loc, sc); tb = b.type.toBasetype(); if (tb.ty == TY.Tclass) @@ -142,7 +151,7 @@ // Check for duplicate interfaces for (size_t j = 0; j < i; j++) { - BaseClass b2 = cast(BaseClass)baseclasses.data[j]; + auto b2 = baseclasses[j]; if (b2.base is tc.sym) error("inherits from duplicate interface %s", b2.base.toChars()); } @@ -179,7 +188,7 @@ } interfaces_dim = baseclasses.dim; - interfaces = cast(BaseClass*)baseclasses.data; + interfaces = baseclasses.ptr; interfaceSemantic(sc); @@ -194,7 +203,7 @@ // Skip if b has already appeared for (int k = 0; k < i; k++) { - if (b == interfaces[i]) + if (b == interfaces[k]) goto Lcontinue; } @@ -398,7 +407,7 @@ #if DMDV2 const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function #endif - TypeInfo typeinfo; + //TypeInfo typeinfo; } */ dt_t *dt = null; @@ -463,7 +472,7 @@ dtdword(&dt, 0); } - dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr); // typeinfo + //dtxoff(&dt, type.vtinfo.toSymbol(), 0, TYnptr); // typeinfo ////////////////////////////////////////////// @@ -471,9 +480,8 @@ // of the fixup (*) offset += vtblInterfaces.dim * (4 * PTRSIZE); - for (size_t i = 0; i < vtblInterfaces.dim; i++) + foreach (b; vtblInterfaces) { - BaseClass b = cast(BaseClass)vtblInterfaces.data[i]; ClassDeclaration id = b.base; // ClassInfo diff -r 786ea1839396 -r 78bf0fe43974 dmd/InvariantDeclaration.d --- a/dmd/InvariantDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/InvariantDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.InvariantDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.Loc; import dmd.Dsymbol; diff -r 786ea1839396 -r 78bf0fe43974 dmd/IsExp.d --- a/dmd/IsExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/IsExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.IsExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.ArrayTypes; @@ -27,7 +28,7 @@ import dmd.TypeFunction; import dmd.MATCH; import dmd.TypePointer; -import dmd.Argument; +import dmd.Parameter; import dmd.Token; class IsExp : Expression @@ -64,8 +65,8 @@ p.setDim(parameters.dim); for (int i = 0; i < p.dim; i++) { - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; - p.data[i] = cast(void*)tp.syntaxCopy(); + auto tp = parameters[i]; + p[i] = tp.syntaxCopy(); } } @@ -83,6 +84,7 @@ Type tded; /* is(targ id tok tspec) + * is(targ id : tok2) * is(targ id == tok2) */ @@ -144,13 +146,19 @@ case TOKinvariant: case TOKimmutable: - if (!targ.isInvariant()) + if (!targ.isImmutable()) goto Lno; tded = targ; break; case TOKshared: if (!targ.isShared()) + goto Lno; + tded = targ; + break; + + case TOKwild: + if (!targ.isWild()) goto Lno; tded = targ; break; @@ -162,12 +170,11 @@ goto Lno; else { ClassDeclaration cd = (cast(TypeClass)targ).sym; - Arguments args = new Arguments; + auto args = new Parameters; args.reserve(cd.baseclasses.dim); - for (size_t i = 0; i < cd.baseclasses.dim; i++) + foreach (b; cd.baseclasses) { - BaseClass b = cast(BaseClass)cd.baseclasses.data[i]; - args.push(cast(void*)new Argument(STCin, b.type, null, null)); + args.push(new Parameter(STCin, b.type, null, null)); } tded = new TypeTuple(args); } @@ -194,15 +201,15 @@ /* Generate tuple from function parameter types. */ assert(tded.ty == Tfunction); - Arguments params = (cast(TypeFunction)tded).parameters; - size_t dim = Argument.dim(params); - Arguments args = new Arguments; + auto params = (cast(TypeFunction)tded).parameters; + size_t dim = Parameter.dim(params); + auto args = new Parameters; args.reserve(dim); for (size_t i = 0; i < dim; i++) { - Argument arg = Argument.getNth(params, i); + auto arg = Parameter.getNth(params, i); assert(arg && arg.type); - args.push(cast(void*)new Argument(arg.storageClass, arg.type, null, null)); + args.push(new Parameter(arg.storageClass, arg.type, null, null)); } tded = new TypeTuple(args); break; @@ -238,14 +245,13 @@ * If true, declare id as an alias for the specialized type. */ - MATCH m; assert(parameters && parameters.dim); - scope Objects dedtypes = new Objects(); + scope dedtypes = new Objects(); dedtypes.setDim(parameters.dim); dedtypes.zero(); - m = targ.deduceType(null, tspec, parameters, dedtypes); + MATCH m = targ.deduceType(null, tspec, parameters, dedtypes); if (m == MATCHnomatch || (m != MATCHexact && tok == TOKequal)) { @@ -253,19 +259,19 @@ } else { - tded = cast(Type)dedtypes.data[0]; + tded = cast(Type)dedtypes[0]; if (!tded) tded = targ; scope Objects tiargs = new Objects(); tiargs.setDim(1); - tiargs.data[0] = cast(void*)targ; + tiargs[0] = targ; /* Declare trailing parameters */ for (int i = 1; i < parameters.dim; i++) { - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; + auto tp = parameters[i]; Declaration s = null; m = tp.matchArg(sc, tiargs, i, parameters, dedtypes, &s); @@ -358,7 +364,7 @@ for (int i = 1; i < parameters.dim; i++) { buf.writeByte(','); - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; + auto tp = parameters[i]; tp.toCBuffer(buf, hgs); } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/Json.d --- a/dmd/Json.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Json.d Tue Sep 14 15:46:50 2010 +0200 @@ -3,6 +3,7 @@ */ module dmd.Json; +import dmd.common; import dmd.String; import std.stdio : write, writef; @@ -23,7 +24,7 @@ void json_generate(Array modules) { - OutBuffer buf; + OutBuffer buf = new OutBuffer(); buf.writestring("[\n"); for (int i = 0; i < modules.dim; i++) diff -r 786ea1839396 -r 78bf0fe43974 dmd/Keyword.d --- a/dmd/Keyword.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Keyword.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Keyword; +import dmd.common; import dmd.TOK; struct Keyword diff -r 786ea1839396 -r 78bf0fe43974 dmd/LabelDsymbol.d --- a/dmd/LabelDsymbol.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/LabelDsymbol.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.LabelDsymbol; +import dmd.common; import dmd.Dsymbol; import dmd.LabelStatement; import dmd.Identifier; diff -r 786ea1839396 -r 78bf0fe43974 dmd/LabelStatement.d --- a/dmd/LabelStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/LabelStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.LabelStatement; +import dmd.common; import dmd.Statement; import dmd.Identifier; import dmd.TryFinallyStatement; @@ -76,12 +77,12 @@ if (a) { if (!a.dim) - a.push(cast(void*)new ExpStatement(loc, null)); + a.push(new ExpStatement(loc, null)); - Statement s = cast(Statement)a.data[0]; + Statement s = a[0]; s = new LabelStatement(loc, ident, s); - a.data[0] = cast(void*)s; + a[0] = s; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/Lexer.d --- a/dmd/Lexer.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Lexer.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Lexer; +import dmd.common; import dmd.StringTable; import dmd.OutBuffer; import dmd.Token; @@ -496,7 +497,9 @@ Token.tochars[TOK.TOKorass] = "|="; Token.tochars[TOK.TOKidentifier] = "identifier"; Token.tochars[TOK.TOKat] = "@"; - + Token.tochars[TOK.TOKpow] = "^^"; + Token.tochars[TOK.TOKpowass] = "^^="; + // For debugging Token.tochars[TOKerror] = "error"; Token.tochars[TOK.TOKdotexp] = "dotexp"; @@ -747,16 +750,29 @@ case 'Z': case '_': case_ident: - { ubyte c; - StringValue *sv; - Identifier id; + { + ubyte c; - do - { - c = *++p; - } while (isidchar(c) || (c & 0x80 && isUniAlpha(decodeUTF()))); - sv = stringtable.update((cast(immutable(char)*)t.ptr)[0.. p - t.ptr]); /// - id = cast(Identifier) sv.ptrvalue; + while (1) + { + c = *++p; + if (isidchar(c)) + continue; + else if (c & 0x80) + { + ubyte *s = p; + uint u = decodeUTF(); + if (isUniAlpha(u)) + continue; + error("char 0x%04x not allowed in identifier", u); + p = s; + } + break; + } + + StringValue *sv = stringtable.update((cast(immutable(char)*)t.ptr)[0.. p - t.ptr]); + Identifier id = cast(Identifier) sv.ptrvalue; + if (id is null) { id = new Identifier(sv.lstring.string_, TOK.TOKidentifier); sv.ptrvalue = cast(void*)id; @@ -1257,6 +1273,28 @@ else t.value = TOK.TOKtilde; // ~ return; + +version(DMDV2) { + case '^': + p++; + if (*p == '^') + { p++; + if (*p == '=') + { p++; + t.value = TOKpowass; // ^^= + } + else + t.value = TOKpow; // ^^ + } + else if (*p == '=') + { p++; + t.value = TOKxorass; // ^= + } + else + t.value = TOKxor; // ^ + return; +} + /* #define SINGLE(c,tok) case c: p++; t.value = tok; return; @@ -1288,8 +1326,9 @@ DOUBLE('*', TOKmul, '=', TOKmulass) DOUBLE('%', TOKmod, '=', TOKmodass) +#if DMDV1 DOUBLE('^', TOKxor, '=', TOKxorass) - +#endif #undef DOUBLE */ @@ -1325,7 +1364,7 @@ t.value = TOK.TOKmod; } return; - +version(DMDV1) { case '^': p++; if (*p == '=') { @@ -1335,30 +1374,30 @@ t.value = TOK.TOKxor; } return; - +} case '#': p++; pragma_(); continue; default: - { ubyte c = *p; + { uint c = *p; if (c & 0x80) - { uint u = decodeUTF(); + { c = decodeUTF(); // Check for start of unicode identifier - if (isUniAlpha(u)) + if (isUniAlpha(c)) goto case_ident; - if (u == PS || u == LS) + if (c == PS || c == LS) { loc.linnum++; p++; continue; } } - if (isprint(c)) + if (c < 0x80 && isprint(c)) error("unsupported char '%c'", c); else error("unsupported char 0x%02x", c); @@ -1691,7 +1730,7 @@ if (u == PS || u == LS) loc.linnum++; else - error("non-hex character \\u%x", u); + error("non-hex character \\u%04x", u); } else error("non-hex character '%c'", c); @@ -2627,7 +2666,7 @@ stringbuffer.writeByte(0); - version (_WIN32) { /// && __DMC__ + version (Windows) { /// && __DMC__ char* save = __locale_decpoint; __locale_decpoint = cast(char*)".".ptr; } @@ -2675,7 +2714,7 @@ } } - version (_WIN32) { ///&& __DMC__ + version (Windows) { ///&& __DMC__ __locale_decpoint = save; } if (errno == ERANGE) diff -r 786ea1839396 -r 78bf0fe43974 dmd/Library.d --- a/dmd/Library.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Library.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Library; +import dmd.common; import dmd.File; import dmd.Array; import dmd.StringTable; diff -r 786ea1839396 -r 78bf0fe43974 dmd/LineInitExp.d --- a/dmd/LineInitExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/LineInitExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.LineInitExp; +import dmd.common; import dmd.Expression; import dmd.Loc; import dmd.Scope; @@ -21,7 +22,7 @@ return this; } - override Expression resolve(Loc loc, Scope sc) + override Expression resolveLoc(Loc loc, Scope sc) { Expression e = new IntegerExp(loc, loc.linnum, Type.tint32); e = e.castTo(sc, type); diff -r 786ea1839396 -r 78bf0fe43974 dmd/LinkDeclaration.d --- a/dmd/LinkDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/LinkDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.LinkDeclaration; +import dmd.common; import dmd.AttribDeclaration; import dmd.LINK; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Loc.d --- a/dmd/Loc.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Loc.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Loc; +import dmd.common; import dmd.Module; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Lstring.d --- a/dmd/Lstring.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Lstring.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Lstring; +import dmd.common; import dmd.Dchar; struct Lstring diff -r 786ea1839396 -r 78bf0fe43974 dmd/MOD.d --- a/dmd/MOD.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/MOD.d Tue Sep 14 15:46:50 2010 +0200 @@ -5,8 +5,9 @@ MODundefined = 0, MODconst = 1, // type is const MODshared = 2, // type is shared - MODinvariant = 4, // type is immutable MODimmutable = 4, // type is immutable + MODwild = 8, // type is wild + MODmutable = 0x10, // type is mutable (only used in wildcard matching) } import dmd.EnumUtils; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Macro.d --- a/dmd/Macro.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Macro.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,113 +1,5 @@ module dmd.Macro; -struct Macro /// ??? -{ -} - -/** -It is very important to use version control macros correctly - the -idea is that host and target are independent. If these are done -correctly, cross compilers can be built. -The host compiler and host operating system are also different, -and are predefined by the host compiler. The ones used in -dmd are: - -Macros defined by the compiler, not the code: - - Compiler: - __DMC__ Digital Mars compiler - _MSC_VER Microsoft compiler - __GNUC__ Gnu compiler - - Host operating system: - _WIN32 Microsoft NT, Windows 95, Windows 98, Win32s, - Windows 2000, Win XP, Vista - _WIN64 Windows for AMD64 - linux Linux - __APPLE__ Mac OSX - __FreeBSD__ FreeBSD - __sun&&__SVR4 Solaris, OpenSolaris (yes, both macros are necessary) - -For the target systems, there are the target operating system and -the target object file format: - - Target operating system: - TARGET_WINDOS Covers 32 bit windows and 64 bit windows - TARGET_LINUX Covers 32 and 64 bit linux - TARGET_OSX Covers 32 and 64 bit Mac OSX - TARGET_FREEBSD Covers 32 and 64 bit FreeBSD - TARGET_SOLARIS Covers 32 and 64 bit Solaris - TARGET_NET Covers .Net - - It is expected that the compiler for each platform will be able - to generate 32 and 64 bit code from the same compiler binary. - - Target object module format: - OMFOBJ Intel Object Module Format, used on Windows - ELFOBJ Elf Object Module Format, used on linux, FreeBSD and Solaris - MACHOBJ Mach-O Object Module Format, used on Mac OSX - - There are currently no macros for byte endianness order. - */ -//version definitions from mars.h - -version(IN_GCC) // Changes for the GDC compiler by David Friedman +struct Macro { - static assert(false, "GDC not supported"); -} - -// default to DMDV2 -version(DMDV1) {} else -version = DMDV2; // Version 2.0 features -version = BREAKABI; // 0 if not ready to break the ABI just yet -version(DMDV2) -{ - version = STRUCTTHISREF; // if 'this' for struct is a reference, not a pointer - version = SNAN_DEFAULT_INIT;// if floats are default initialized to signalling NaN - version = SARRAYVALUE; // static arrays are value types -} - -// Set if C++ mangling is done by the front end -version(DMDV2) -{ - version(POSIX) // TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS - version = CPP_MANGLE; -} - -/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD and - * TARGET_SOLARIS, which are - * set on the command line via the compiler makefile. - */ - -version(_WIN32) -{ - version = TARGET_WINDOS; // Windows dmd generates Windows targets - version = OMFOBJ; -} - -version(TARGET_LINUX) - version = ELFOBJ; -version(TARGET_FREEBSD) - version = ELFOBJ; -version(TARGET_SOLARIS) - version = ELFOBJ; - - -version(TARGET_OSX) - version = MACHOBJ; - -/* TODO: -//Modify OutBuffer::writewchar to write the correct size of wchar -#if _WIN32 -#define writewchar writeword -#else -//This needs a configuration test... -#define writewchar write4 -#endif - -#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry -//in interface vtbl[]'s -#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears -//in the inheritance graph multiple -//times, only one is used -*/ \ No newline at end of file +} \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/MinAssignExp.d --- a/dmd/MinAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/MinAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,7 @@ module dmd.MinAssignExp; +import dmd.common; +import dmd.expression.Min; import dmd.BinExp; import dmd.Loc; import dmd.Expression; @@ -12,6 +14,7 @@ import dmd.TY; import dmd.TOK; import dmd.Id; +import dmd.ArrayLengthExp; import dmd.backend.elem; import dmd.backend.Util; @@ -38,6 +41,13 @@ if (e) return e; + if (e1.op == TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + if (e1.op == TOKslice) { // T[] -= ... typeCombine(sc); @@ -69,7 +79,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Min); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -77,9 +87,9 @@ AssignExp_buildArrayIdent(buf, arguments, "Min"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - assert(false); + return AssignExp_buildArrayLoop!(typeof(this))(fparams); } override Identifier opId() /* For operator overloading */ diff -r 786ea1839396 -r 78bf0fe43974 dmd/MinExp.d --- a/dmd/MinExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/MinExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.MinExp; +import dmd.common; import dmd.Expression; import dmd.TY; import dmd.ErrorExp; @@ -139,7 +140,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &Min); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -147,14 +148,9 @@ Exp_buildArrayIdent(buf, arguments, "Min"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - /* Evaluate assign expressions left to right - */ - Expression ex1 = e1.buildArrayLoop(fparams); - Expression ex2 = e2.buildArrayLoop(fparams); - Expression e = new MinExp(Loc(0), ex1, ex2); - return e; + return Exp_buildArrayLoop!(typeof(this))(fparams); } override Identifier opId() diff -r 786ea1839396 -r 78bf0fe43974 dmd/ModAssignExp.d --- a/dmd/ModAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ModAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,7 @@ module dmd.ModAssignExp; +import dmd.common; +import dmd.expression.Mod; import dmd.BinExp; import dmd.Loc; import dmd.Expression; @@ -31,17 +33,17 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Mod); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) { - assert(false); + AssignExp_buildArrayIdent(buf, arguments, "Mod"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - assert(false); + return AssignExp_buildArrayLoop!(typeof(this))(fparams); } override Identifier opId() /* For operator overloading */ diff -r 786ea1839396 -r 78bf0fe43974 dmd/ModExp.d --- a/dmd/ModExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ModExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ModExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; @@ -40,11 +41,11 @@ return e; typeCombine(sc); - if (e1.op != TOKslice && e2.op != TOKslice) - { + if (!e1.isArrayOperand()) e1.checkArithmetic(); + if (!e2.isArrayOperand()) e2.checkArithmetic(); - } + if (type.isfloating()) { type = e1.type; @@ -74,7 +75,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &Mod); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -82,14 +83,9 @@ Exp_buildArrayIdent(buf, arguments, "Mod"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - /* Evaluate assign expressions left to right - */ - Expression ex1 = e1.buildArrayLoop(fparams); - Expression ex2 = e2.buildArrayLoop(fparams); - Expression e = new ModExp(Loc(0), ex1, ex2); - return e; + return Exp_buildArrayLoop!(typeof(this))(fparams); } override Identifier opId() diff -r 786ea1839396 -r 78bf0fe43974 dmd/Module.d --- a/dmd/Module.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Module.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Module; +import dmd.common; import dmd.Package; import dmd.DsymbolTable; import dmd.backend.TYM; @@ -222,8 +223,8 @@ ModuleInfoDeclaration vmoduleinfo; uint debuglevel; // debug level - Array debugids; // debug identifiers - Array debugidsNot; // forward referenced debug identifiers + Vector!string debugids; // debug identifiers + Vector!string debugidsNot; // forward referenced debug identifiers uint versionlevel; // version level Array versionids; // version identifiers @@ -296,7 +297,7 @@ symfile = new File(symfilename); } - static Module load(Loc loc, Array packages, Identifier ident) + static Module load(Loc loc, Vector!Identifier packages, Identifier ident) { Module m; string filename; @@ -313,14 +314,15 @@ scope OutBuffer buf = new OutBuffer(); int i; - for (i = 0; i < packages.dim; i++) + foreach (pid; packages) { - Identifier pid = cast(Identifier)packages.data[i]; - buf.writestring(pid.toChars()); -version (_WIN32) { +version (Windows) +{ buf.writeByte('\\'); -} else { +} +else +{ buf.writeByte('/'); } } @@ -375,9 +377,8 @@ writef("import "); if (packages) { - for (size_t i = 0; i < packages.dim; i++) + foreach (pid; packages) { - Identifier pid = cast(Identifier)packages.data[i]; writef("%s.", pid.toChars()); } } @@ -1673,9 +1674,8 @@ } } - for (int i = 0; i < aclasses.dim; i++) + foreach (cd; aclasses) { - ClassDeclaration cd = cast(ClassDeclaration)aclasses.data[i]; dtxoff(&dt, cd.toSymbol(), 0, TYM.TYnptr); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/ModuleDeclaration.d --- a/dmd/ModuleDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ModuleDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,15 +1,16 @@ module dmd.ModuleDeclaration; +import dmd.common; import dmd.Identifier; -import dmd.Array; +import dmd.ArrayTypes; class ModuleDeclaration { Identifier id; - Array packages; // array of Identifier's representing packages + Identifiers packages; // array of Identifier's representing packages bool safe; - this(Array packages, Identifier id, bool safe) + this(Identifiers packages, Identifier id, bool safe) { this.packages = packages; this.id = id; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ModuleInfoDeclaration.d --- a/dmd/ModuleInfoDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ModuleInfoDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ModuleInfoDeclaration; +import dmd.common; import dmd.VarDeclaration; import dmd.Module; import dmd.OutBuffer; @@ -11,34 +12,32 @@ class ModuleInfoDeclaration : VarDeclaration { - Module mod; + Module mod; - this(Module mod) + this(Module mod) { - assert(false); - super(Loc(0), null, null, null); + super(Loc(0), Module.moduleinfo.type, mod.ident, null); } - override Dsymbol syntaxCopy(Dsymbol) + override Dsymbol syntaxCopy(Dsymbol) { - assert(false); + assert(false); // should never be produced by syntax + return null; } - override void semantic(Scope sc) + override void semantic(Scope sc) { - assert(false); } - void emitComment(Scope *sc) + void emitComment(Scope *sc) { - assert(false); } override void toJsonBuffer(OutBuffer buf) { } - override Symbol* toSymbol() + override Symbol* toSymbol() { assert(false); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/MulAssignExp.d --- a/dmd/MulAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/MulAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.MulAssignExp; +import dmd.common; import dmd.BinExp; import dmd.Loc; import dmd.Expression; @@ -13,9 +14,11 @@ import dmd.TOK; import dmd.Type; import dmd.TY; +import dmd.ArrayLengthExp; import dmd.backend.elem; import dmd.backend.OPER; +import dmd.expression.Mul; import dmd.expression.Util; class MulAssignExp : BinExp @@ -36,6 +39,15 @@ if (e) return e; +version(DMDV2) { + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } +} + if (e1.op == TOKslice) { // T[] -= ... typeCombine(sc); @@ -86,7 +98,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Mul); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -94,9 +106,9 @@ AssignExp_buildArrayIdent(buf, arguments, "Mul"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - assert(false); + return AssignExp_buildArrayLoop!(typeof(this))(fparams); } override Identifier opId() /* For operator overloading */ diff -r 786ea1839396 -r 78bf0fe43974 dmd/MulExp.d --- a/dmd/MulExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/MulExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.MulExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; @@ -46,11 +47,11 @@ return e; typeCombine(sc); - if (e1.op != TOKslice && e2.op != TOKslice) - { + if (!e1.isArrayOperand()) e1.checkArithmetic(); + if (!e2.isArrayOperand()) e2.checkArithmetic(); - } + if (type.isfloating()) { Type t1 = e1.type; @@ -112,7 +113,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &Mul); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -120,14 +121,9 @@ Exp_buildArrayIdent(buf, arguments, "Mul"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - /* Evaluate assign expressions left to right - */ - Expression ex1 = e1.buildArrayLoop(fparams); - Expression ex2 = e2.buildArrayLoop(fparams); - Expression e = new MulExp(Loc(0), ex1, ex2); - return e; + return Exp_buildArrayLoop!(typeof(this))(fparams); } override bool isCommutative() diff -r 786ea1839396 -r 78bf0fe43974 dmd/NegExp.d --- a/dmd/NegExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/NegExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.NegExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; @@ -41,7 +42,7 @@ return e; e1.checkNoBool(); - if (e1.op != TOKslice) + if (!e1.isArrayOperand()) e1.checkArithmetic(); type = e1.type; @@ -71,12 +72,15 @@ override void buildArrayIdent(OutBuffer buf, Expressions arguments) { - assert(false); + e1.buildArrayIdent(buf, arguments); + buf.writestring("Neg"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - assert(false); + Expression ex1 = e1.buildArrayLoop(fparams); + Expression e = new NegExp(Loc(0), ex1); + return e; } override Identifier opId() diff -r 786ea1839396 -r 78bf0fe43974 dmd/NewAnonClassExp.d --- a/dmd/NewAnonClassExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/NewAnonClassExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,13 +1,19 @@ module dmd.NewAnonClassExp; +import dmd.common; import dmd.Expression; import dmd.OutBuffer; import dmd.Loc; import dmd.Scope; import dmd.ClassDeclaration; +import dmd.DeclarationExp; +import dmd.NewExp; +import dmd.CommaExp; +import dmd.PREC; import dmd.HdrGenState; import dmd.ArrayTypes; import dmd.TOK; +import dmd.expression.Util; class NewAnonClassExp : Expression { @@ -20,33 +26,75 @@ this(Loc loc, Expression thisexp, Expressions newargs, ClassDeclaration cd, Expressions arguments) { - assert(false); - super(loc, TOK.init, 0); + super(loc, TOKnewanonclass, NewAnonClassExp.sizeof); + this.thisexp = thisexp; + this.newargs = newargs; + this.cd = cd; + this.arguments = arguments; } override Expression syntaxCopy() { - assert(false); + return new NewAnonClassExp(loc, + thisexp ? thisexp.syntaxCopy() : null, + arraySyntaxCopy(newargs), + cast(ClassDeclaration)cd.syntaxCopy(null), + arraySyntaxCopy(arguments)); } - + override Expression semantic(Scope sc) { - assert(false); +version (LOGSEMANTIC) { + printf("NewAnonClassExp.semantic() %s\n", toChars()); + //printf("thisexp = %p\n", thisexp); + //printf("type: %s\n", type.toChars()); +} + + Expression d = new DeclarationExp(loc, cd); + d = d.semantic(sc); + + Expression n = new NewExp(loc, thisexp, newargs, cd.type, arguments); + + Expression c = new CommaExp(loc, d, n); + return c.semantic(sc); } override bool checkSideEffect(int flag) { - assert(false); + return true; } - void toCBuffer(OutBuffer buf, HdrGenState hgs) + void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + if (thisexp) + { + expToCBuffer(buf, hgs, thisexp, PREC.PREC_primary); + buf.writeByte('.'); + } + buf.writestring("new"); + if (newargs && newargs.dim) + { + buf.writeByte('('); + argsToCBuffer(buf, newargs, hgs); + buf.writeByte(')'); + } + buf.writestring(" class "); + if (arguments && arguments.dim) + { + buf.writeByte('('); + argsToCBuffer(buf, arguments, hgs); + buf.writeByte(')'); + } + //buf.writestring(" { }"); + if (cd) + { + cd.toCBuffer(buf, hgs); + } } override bool canThrow() { - assert(false); + return true; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/NewDeclaration.d --- a/dmd/NewDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/NewDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,58 +1,108 @@ module dmd.NewDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.Loc; import dmd.ArrayTypes; import dmd.Dsymbol; +import dmd.Parameter; +import dmd.ClassDeclaration; +import dmd.Type; +import dmd.TypeFunction; +import dmd.LINK; +import dmd.TY; import dmd.Scope; import dmd.OutBuffer; import dmd.HdrGenState; import dmd.STC; +import dmd.Id; class NewDeclaration : FuncDeclaration { - Arguments arguments; + Parameters arguments; int varargs; - this(Loc loc, Loc endloc, Arguments arguments, int varargs) + this(Loc loc, Loc endloc, Parameters arguments, int varargs) { - assert(false); - super(loc, loc, null, STC.init, null); + super(loc, endloc, Id.classNew, STCstatic, null); + this.arguments = arguments; + this.varargs = varargs; } override Dsymbol syntaxCopy(Dsymbol) { - assert(false); + NewDeclaration f; + + f = new NewDeclaration(loc, endloc, null, varargs); + + FuncDeclaration.syntaxCopy(f); + + f.arguments = Parameter.arraySyntaxCopy(arguments); + + return f; } override void semantic(Scope sc) { - assert(false); + ClassDeclaration cd; + Type tret; + + //printf("NewDeclaration.semantic()\n"); + + parent = sc.parent; + Dsymbol parent = toParent(); + 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 = type.semantic(loc, sc); + assert(type.ty == Tfunction); + + // Check that there is at least one argument of type size_t + TypeFunction tf = cast(TypeFunction)type; + if (Parameter.dim(tf.parameters) < 1) + { + error("at least one argument of type size_t expected"); + } + else + { + auto a = Parameter.getNth(tf.parameters, 0); + if (!a.type.equals(Type.tsize_t)) + error("first argument must be type size_t, not %s", a.type.toChars()); + } + + FuncDeclaration.semantic(sc); } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + buf.writestring("new"); + Parameter.argsToCBuffer(buf, hgs, arguments, varargs); + bodyToCBuffer(buf, hgs); } override string kind() { - assert(false); + return "allocator"; } override bool isVirtual() { - assert(false); + return false; } override bool addPreInvariant() { - assert(false); + return false; } override bool addPostInvariant() { - assert(false); + return false; } override NewDeclaration isNewDeclaration() { return this; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/NewExp.d --- a/dmd/NewExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/NewExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.NewExp; +import dmd.common; import dmd.Expression; import dmd.NewDeclaration; import dmd.CtorDeclaration; @@ -113,9 +114,9 @@ //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco); arrayExpressionSemantic(newargs, sc); - preFunctionArguments(loc, sc, newargs); + preFunctionParameters(loc, sc, newargs); arrayExpressionSemantic(arguments, sc); - preFunctionArguments(loc, sc, arguments); + preFunctionParameters(loc, sc, arguments); if (thisexp && tb.ty != Tclass) error("e.new is only for allocating nested classes, not %s", tb.toChars()); @@ -247,7 +248,7 @@ if (!arguments) arguments = new Expressions(); - functionArguments(loc, sc, tf, arguments); + functionParameters(loc, sc, tf, arguments); } else { @@ -268,7 +269,7 @@ assert(allocator); tf = cast(TypeFunction)f.type; - functionArguments(loc, sc, tf, newargs); + functionParameters(loc, sc, tf, newargs); } else { @@ -298,7 +299,7 @@ if (!arguments) arguments = new Expressions(); - functionArguments(loc, sc, tf, arguments); + functionParameters(loc, sc, tf, arguments); } else { @@ -319,7 +320,7 @@ assert(allocator); tf = cast(TypeFunction)f.type; - functionArguments(loc, sc, tf, newargs); + functionParameters(loc, sc, tf, newargs); static if (false) { e = new VarExp(loc, f); e = new CallExp(loc, e, newargs); @@ -719,7 +720,7 @@ override bool checkSideEffect(int flag) { - assert(false); + return true; } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) diff -r 786ea1839396 -r 78bf0fe43974 dmd/NotExp.d --- a/dmd/NotExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/NotExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.NotExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.UnaExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/NullExp.d --- a/dmd/NullExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/NullExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.NullExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.InterState; @@ -20,9 +21,10 @@ { ubyte committed; - this(Loc loc) + this(Loc loc, Type type = null) { super(loc, TOK.TOKnull, NullExp.sizeof); + this.type = type; } override Expression semantic(Scope sc) @@ -137,7 +139,7 @@ override Expression interpret(InterState istate) { - assert(false); + return this; } override elem* toElem(IRState* irs) diff -r 786ea1839396 -r 78bf0fe43974 dmd/OnScopeStatement.d --- a/dmd/OnScopeStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/OnScopeStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.OnScopeStatement; +import dmd.common; import dmd.Statement; import dmd.OutBuffer; import dmd.HdrGenState; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Optimize.d --- a/dmd/Optimize.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Optimize.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Optimize; +import dmd.common; import dmd.Expression; import dmd.TOK; import dmd.VarExp; @@ -21,9 +22,9 @@ Expression e = null; if (!v) - return e; + return e; - if (v.isConst() || v.isInvariant() || v.storage_class & STC.STCmanifest) + if (v.isConst() || v.isImmutable() || v.storage_class & STC.STCmanifest) { if (!v.type) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/OrAssignExp.d --- a/dmd/OrAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/OrAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,7 @@ module dmd.OrAssignExp; +import dmd.common; +import dmd.expression.Or; import dmd.BinExp; import dmd.Loc; import dmd.Expression; @@ -29,17 +31,17 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Or); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) { - assert(false); + AssignExp_buildArrayIdent(buf, arguments, "Or"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - assert(false); + return AssignExp_buildArrayLoop!(typeof(this))(fparams); } override Identifier opId() /* For operator overloading */ diff -r 786ea1839396 -r 78bf0fe43974 dmd/OrExp.d --- a/dmd/OrExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/OrExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.OrExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.InterState; @@ -48,11 +49,10 @@ else { typeCombine(sc); - if (e1.op != TOK.TOKslice && e2.op != TOK.TOKslice) - { + if (!e1.isArrayOperand()) e1.checkIntegral(); + if (!e2.isArrayOperand()) e2.checkIntegral(); - } } } @@ -76,17 +76,17 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &Or); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) { - assert(false); + Exp_buildArrayIdent(buf, arguments, "Or"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - assert(false); + return Exp_buildArrayLoop!(typeof(this))(fparams); } override MATCH implicitConvTo(Type t) diff -r 786ea1839396 -r 78bf0fe43974 dmd/OrOrExp.d --- a/dmd/OrOrExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/OrOrExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.OrOrExp; +import dmd.common; import dmd.BinExp; import dmd.Scope; import dmd.InterState; diff -r 786ea1839396 -r 78bf0fe43974 dmd/OutBuffer.d --- a/dmd/OutBuffer.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/OutBuffer.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.OutBuffer; +import dmd.common; import std.stdarg; import std.exception; @@ -94,7 +95,7 @@ final void writenl() // write newline { -version (_WIN32) +version (Windows) { version (M_UNICODE) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/OverExp.d --- a/dmd/OverExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/OverExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.OverExp; +import dmd.common; import dmd.Expression; import dmd.OverloadSet; import dmd.Scope; @@ -7,6 +8,8 @@ import dmd.TOK; import dmd.Type; +//! overload set +version(DMDV2) class OverExp : Expression { OverloadSet vars; @@ -21,12 +24,12 @@ override int isLvalue() { - assert(false); + return true; } override Expression toLvalue(Scope sc, Expression e) { - assert(false); + return this; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/OverloadSet.d --- a/dmd/OverloadSet.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/OverloadSet.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.OverloadSet; +import dmd.common; import dmd.Dsymbol; import dmd.ArrayTypes; diff -r 786ea1839396 -r 78bf0fe43974 dmd/PREC.d --- a/dmd/PREC.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/PREC.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.PREC; +import dmd.common; import dmd.TOK; /********************************** @@ -24,6 +25,7 @@ PREC_shift, PREC_add, PREC_mul, + PREC_pow, PREC_unary, PREC_primary, } diff -r 786ea1839396 -r 78bf0fe43974 dmd/Package.d --- a/dmd/Package.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Package.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,8 +1,9 @@ module dmd.Package; +import dmd.common; import dmd.ScopeDsymbol; import dmd.Identifier; -import dmd.Array; +import dmd.ArrayTypes; import dmd.DsymbolTable; import dmd.Scope; import dmd.Dsymbol; @@ -21,7 +22,7 @@ assert(false); } - static DsymbolTable resolve(Array packages, Dsymbol* pparent, Package* ppkg) + static DsymbolTable resolve(Identifiers packages, Dsymbol* pparent, Package* ppkg) { DsymbolTable dst = Module.modules; Dsymbol parent = null; @@ -32,9 +33,8 @@ if (packages) { - for (int i = 0; i < packages.dim; i++) + foreach (pid; packages) { - Identifier pid = cast(Identifier)packages.data[i]; Dsymbol p = dst.lookup(pid); if (!p) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/Param.d --- a/dmd/Param.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Param.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Param; +import dmd.common; import dmd.Array; import dmd.OutBuffer; @@ -30,7 +31,10 @@ bool useInvariants; // generate class invariant checks bool useIn; // generate precondition checks bool useOut; // generate postcondition checks - bool useArrayBounds; // generate array bounds checks + byte useArrayBounds; // 0: no array bounds checks + // 1: array bounds checks for safe functions only + // 2: array bounds checks for all functions + bool noboundscheck; // no array bounds checking at all bool useSwitchError; // check for switches without a default bool useUnitTests; // generate unittest code bool useInline; // inline expand functions @@ -42,7 +46,6 @@ bool nofloat; // code should not pull in floating point support byte Dversion; // D version number bool ignoreUnsupportedPragmas; // rather than error on them - bool safe; // enforce safe memory model string argv0; // program name Array imppath; // array of char*'s of where to look for import modules @@ -64,7 +67,7 @@ string xfilename; // write JSON file to xfilename uint debuglevel; // debug level - Array debugids; // debug identifiers + Vector!string debugids; // debug identifiers uint versionlevel; // version level Array versionids; // version identifiers diff -r 786ea1839396 -r 78bf0fe43974 dmd/Parameter.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/Parameter.d Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,304 @@ +module dmd.Parameter; + +import dmd.common; +import dmd.Type; +import dmd.Identifier; +import dmd.TypeArray; +import dmd.TypeFunction; +import dmd.TypeDelegate; +import dmd.TypeTuple; +import dmd.TY; +import dmd.Expression; +import dmd.OutBuffer; +import dmd.HdrGenState; +import dmd.ArrayTypes; +import dmd.StorageClassDeclaration; +import dmd.Global; +import dmd.MOD; +import dmd.CppMangleState; +import dmd.STC; + +class Parameter +{ + //enum InOut inout; + StorageClass storageClass; + Type type; + Identifier ident; + Expression defaultArg; + + this(StorageClass storageClass, Type type, Identifier ident, Expression defaultArg) + { + this.type = type; + this.ident = ident; + this.storageClass = storageClass; + this.defaultArg = defaultArg; + } + + Parameter clone() + { + return new Parameter(storageClass, type, ident, defaultArg); + } + + Parameter syntaxCopy() + { + return new Parameter(storageClass, type ? type.syntaxCopy() : null, ident, defaultArg ? defaultArg.syntaxCopy() : null); + } + + /**************************************************** + * Determine if parameter is a lazy array of delegates. + * If so, return the return type of those delegates. + * If not, return null. + */ + Type isLazyArray() + { + // if (inout == Lazy) + { + Type tb = type.toBasetype(); + if (tb.ty == Tsarray || tb.ty == Tarray) + { + Type tel = (cast(TypeArray)tb).next.toBasetype(); + if (tel.ty == Tdelegate) + { + TypeDelegate td = cast(TypeDelegate)tel; + TypeFunction tf = cast(TypeFunction)td.next; + + if (!tf.varargs && Parameter.dim(tf.parameters) == 0) + { + return tf.next; // return type of delegate + } + } + } + } + return null; + } + + void toDecoBuffer(OutBuffer buf) + { + if (storageClass & STC.STCscope) + buf.writeByte('M'); + switch (storageClass & (STC.STCin | STC.STCout | STC.STCref | STC.STClazy)) + { + case STC.STCundefined: + case STC.STCin: + break; + case STC.STCout: + buf.writeByte('J'); + break; + case STC.STCref: + buf.writeByte('K'); + break; + case STC.STClazy: + buf.writeByte('L'); + break; + } +static if (false) { + int mod = 0x100; + if (type.toBasetype().ty == TY.Tclass) + mod = 0; + type.toDecoBuffer(buf, mod); +} else { + //type.toHeadMutable().toDecoBuffer(buf, 0); + type.toDecoBuffer(buf, 0); +} + } + + static Parameters arraySyntaxCopy(Parameters args) + { + typeof(return) a = null; + + if (args) + { + a = new Parameters(); + a.setDim(args.dim); + + for (size_t i = 0; i < a.dim; i++) + { + auto arg = args[i]; + + arg = arg.syntaxCopy(); + a[i] = arg; + } + } + + return a; + } + + static string argsTypesToChars(Parameters args, int varargs) + { + scope OutBuffer buf = new OutBuffer(); + + static if (true) { + HdrGenState hgs; + argsToCBuffer(buf, &hgs, args, varargs); + } else { + buf.writeByte('('); + if (args) + { + OutBuffer argbuf = new OutBuffer(); + HdrGenState hgs; + + for (int i = 0; i < args.dim; i++) + { + if (i) + buf.writeByte(','); + auto arg = cast(Parameter)args.data[i]; + argbuf.reset(); + arg.type.toCBuffer2(&argbuf, &hgs, 0); + buf.write(&argbuf); + } + if (varargs) + { + if (i && varargs == 1) + buf.writeByte(','); + buf.writestring("..."); + } + } + buf.writeByte(')'); + } + return buf.toChars(); + } + + static void argsCppMangle(OutBuffer buf, CppMangleState* cms, Parameters arguments, int varargs) + { + assert(false); + } + + static void argsToCBuffer(OutBuffer buf, HdrGenState* hgs, Parameters arguments, int varargs) + { + buf.writeByte('('); + if (arguments) + { + int i; + scope OutBuffer argbuf = new OutBuffer(); + + for (i = 0; i < arguments.dim; i++) + { + if (i) + buf.writestring(", "); + auto arg = arguments[i]; + + if (arg.storageClass & STCauto) + buf.writestring("auto "); + + if (arg.storageClass & STCout) + buf.writestring("out "); + else if (arg.storageClass & STCref) + buf.writestring((global.params.Dversion == 1) ? "inout " : "ref "); + else if (arg.storageClass & STCin) + buf.writestring("in "); + else if (arg.storageClass & STClazy) + buf.writestring("lazy "); + else if (arg.storageClass & STCalias) + buf.writestring("alias "); + + StorageClass stc = arg.storageClass; + if (arg.type && arg.type.mod & MODshared) + stc &= ~STCshared; + + StorageClassDeclaration.stcToCBuffer(buf, stc & (STCconst | STCimmutable | STCshared | STCscope)); + + argbuf.reset(); + if (arg.storageClass & STCalias) + { + if (arg.ident) + argbuf.writestring(arg.ident.toChars()); + } + else + arg.type.toCBuffer(argbuf, arg.ident, hgs); + if (arg.defaultArg) + { + argbuf.writestring(" = "); + arg.defaultArg.toCBuffer(argbuf, hgs); + } + buf.write(argbuf); + } + if (varargs) + { + if (i && varargs == 1) + buf.writeByte(','); + buf.writestring("..."); + } + } + buf.writeByte(')'); + } + + static void argsToDecoBuffer(OutBuffer buf, Parameters arguments) + { + //printf("Parameter::argsToDecoBuffer()\n"); + + // Write argument types + if (arguments) + { + size_t dim = Parameter.dim(arguments); + for (size_t i = 0; i < dim; i++) + { + auto arg = Parameter.getNth(arguments, i); + arg.toDecoBuffer(buf); + } + } + } + + static int isTPL(Parameters arguments) + { + assert(false); + } + + /*************************************** + * Determine number of arguments, folding in tuples. + */ + static size_t dim(Parameters args) + { + size_t n = 0; + if (args) + { + foreach (arg; args) + { + Type t = arg.type.toBasetype(); + + if (t.ty == TY.Ttuple) + { + auto tu = cast(TypeTuple)t; + n += dim(tu.arguments); + } + else + n++; + } + } + return n; + } + + /*************************************** + * Get nth Parameter, folding in tuples. + * Returns: + * Parameter nth Parameter + * null not found, *pn gets incremented by the number + * of Parameters + */ + static Parameter getNth(Parameters args, size_t nth, size_t* pn = null) + { + if (!args) + return null; + + size_t n = 0; + foreach (arg; args) + { + Type t = arg.type.toBasetype(); + + if (t.ty == TY.Ttuple) + { TypeTuple tu = cast(TypeTuple)t; + arg = getNth(tu.arguments, nth - n, &n); + if (arg) + return arg; + } + else if (n == nth) + return arg; + else + n++; + } + + if (pn) + *pn += n; + + return null; + } +} diff -r 786ea1839396 -r 78bf0fe43974 dmd/Parser.d --- a/dmd/Parser.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Parser.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Parser; +import dmd.common; import dmd.Lexer; import dmd.PostBlitDeclaration; import dmd.FileInitExp; @@ -78,6 +79,7 @@ import dmd.DivAssignExp; import dmd.AndAssignExp; import dmd.AddAssignExp; +import dmd.PowAssignExp; import dmd.ModuleDeclaration; import dmd.CaseRangeStatement; import dmd.CommaExp; @@ -137,7 +139,7 @@ import dmd.CompoundStatement; import dmd.ConditionalStatement; import dmd.CompoundDeclarationStatement; -import dmd.Argument; +import dmd.Parameter; import dmd.ParseStatementFlags; import dmd.TypeNewArray; import dmd.TypeNext; @@ -202,6 +204,8 @@ import dmd.VersionSymbol; import dmd.AliasThis; import dmd.Global; +import dmd.TRUST; +import dmd.PowExp; import core.stdc.string : memcpy; @@ -234,6 +238,7 @@ bool safe = false; nextToken(); +static if(false) { version (DMDV2) { if (token.value == TOK.TOKlparen) { @@ -253,6 +258,7 @@ check(TOK.TOKrparen); } } +} if (token.value != TOK.TOKidentifier) { @@ -261,13 +267,13 @@ } else { - Array a = null; + Identifiers a = null; Identifier id = token.ident; while (nextToken() == TOK.TOKdot) { if (!a) - a = new Array(); - a.push(cast(void*)id); + a = new Identifiers(); + a.push(id); nextToken(); if (token.value != TOK.TOKidentifier) { error("Identifier expected following package"); @@ -310,8 +316,8 @@ Dsymbols a; Dsymbols aelse; PROT prot; - STC stc; - STC storageClass; + StorageClass stc; + StorageClass storageClass; Condition condition; string comment; @@ -491,6 +497,12 @@ stc = STC.STCshared; goto Lstc; + case TOKwild: + if (peek(&token).value == TOK.TOKlparen) + goto Ldeclaration; + stc = STCwild; + goto Lstc; + case TOK.TOKfinal: stc = STC.STCfinal; goto Lstc; case TOK.TOKauto: stc = STC.STCauto; goto Lstc; case TOK.TOKscope: stc = STC.STCscope; goto Lstc; @@ -506,6 +518,7 @@ case TOK.TOKgshared: stc = STC.STCgshared; goto Lstc; //case TOK.TOKmanifest: stc = STC.STCmanifest; goto Lstc; + case TOK.TOKat: stc = parseAttribute(); goto Lstc; } Lstc: @@ -521,6 +534,7 @@ case TOK.TOKinvariant: case TOK.TOKimmutable: case TOK.TOKshared: + case TOKwild: // If followed by a (, it is not a storage class if (peek(&token).value == TOK.TOKlparen) break; @@ -528,6 +542,8 @@ stc = STC.STCconst; else if (token.value == TOK.TOKshared) stc = STC.STCshared; + else if (token.value == TOKwild) + stc = STC.STCwild; else stc = STC.STCimmutable; goto Lstc; @@ -544,6 +560,7 @@ case TOK.TOKtls: stc = STC.STCtls; goto Lstc; case TOK.TOKgshared: stc = STC.STCgshared; goto Lstc; //case TOK.TOKmanifest: stc = STC.STCmanifest; goto Lstc; + case TOK.TOKat: stc = parseAttribute(); goto Lstc; default: break; } @@ -750,7 +767,7 @@ */ version (DMDV2) { - Dsymbols parseAutoDeclarations(STC storageClass, const(char)[] comment) + Dsymbols parseAutoDeclarations(StorageClass storageClass, const(char)[] comment) { auto a = new Dsymbols; @@ -834,10 +851,10 @@ } return a; } - - void composeStorageClass(STC stc) +version(DMDV2) { + void composeStorageClass(StorageClass stc) { - STC u = stc; + StorageClass u = stc; u &= STC.STCconst | STC.STCimmutable | STC.STCmanifest; if (u & (u - 1)) error("conflicting storage class %s", Token.toChars(token.value)); @@ -846,8 +863,39 @@ u &= STC.STCgshared | STC.STCshared | STC.STCtls; if (u & (u - 1)) error("conflicting storage class %s", Token.toChars(token.value)); + u = stc; + u &= STCsafe | STCsystem | STCtrusted; + if (u & (u - 1)) + error("conflicting attribute @%s", token.toChars()); } - +} + +/*********************************************** + * Parse storage class, lexer is on '@' + */ + +version(DMDV2) { + StorageClass parseAttribute() + { + nextToken(); + StorageClass stc = STCundefined; + if (token.value != TOKidentifier) + { + error("identifier expected after @, not %s", token.toChars()); + } + else if (token.ident == Id.property) + stc = STCproperty; + else if (token.ident == Id.safe) + stc = STCsafe; + else if (token.ident == Id.trusted) + stc = STCtrusted; + else if (token.ident == Id.system) + stc = STCsystem; + else + error("valid attribute identifiers are @property, @safe, @trusted, @system, not @%s", token.toChars()); + return stc; + } +} /************************************** * Parse constraint. * Constraint is of the form: @@ -1068,7 +1116,7 @@ } tp = new TemplateValueParameter(loc, tp_ident, tp_valtype, tp_specvalue, tp_defaultvalue); } - tpl.push(cast(void*)tp); + tpl.push(tp); if (token.value != TOKcomma) break; nextToken(); @@ -1202,7 +1250,7 @@ if (isDeclaration(&token, 0, TOKreserved, null)) { // Template argument is a type Type ta = parseType(); - tiargs.push(cast(void*)ta); + tiargs.push(ta); } else { // Template argument is an expression @@ -1221,9 +1269,8 @@ * a deduced type. */ TemplateParameters tpl = null; - for (int i = 0; i < tf.parameters.dim; i++) + foreach (param; tf.parameters) { - Argument param = cast(Argument)tf.parameters.data[i]; if (param.ident is null && param.type && param.type.ty == Tident && @@ -1233,14 +1280,14 @@ /* Switch parameter type to parameter identifier, * parameterize with template type parameter _T */ - TypeIdentifier pt = cast(TypeIdentifier)param.type; + auto pt = cast(TypeIdentifier)param.type; param.ident = pt.ident; Identifier id = Lexer.uniqueId("__T"); param.type = new TypeIdentifier(pt.loc, id); - TemplateParameter tp = new TemplateTypeParameter(fd.loc, id, null, null); + auto tp = new TemplateTypeParameter(fd.loc, id, null, null); if (!tpl) tpl = new TemplateParameters(); - tpl.push(cast(void*)tp); + tpl.push(tp); } } @@ -1251,13 +1298,13 @@ decldefs.push(fd); auto tempdecl = new TemplateDeclaration(fd.loc, fd.ident, tpl, null, decldefs); tempdecl.literal = 1; // it's a template 'literal' - tiargs.push(cast(void*)tempdecl); + tiargs.push(tempdecl); goto L1; } } } - tiargs.push(cast(void*)ea); + tiargs.push(ea); } L1: if (token.value != TOKcomma) @@ -1310,7 +1357,7 @@ case TOKwchar: ta = Type.twchar; goto LabelX; case TOKdchar: ta = Type.tdchar; goto LabelX; LabelX: - tiargs.push(cast(void*)ta); + tiargs.push(ta); nextToken(); break; @@ -1336,7 +1383,7 @@ { // Template argument is an expression Expression ea = parsePrimaryExp(); - tiargs.push(cast(void*)ea); + tiargs.push(ea); break; } @@ -1428,9 +1475,12 @@ } else if (id == Id.System) { -version (_WIN32) { +version (Windows) +{ link = LINK.LINKwindows; -} else { +} +else +{ link = LINK.LINKc; } } @@ -1572,7 +1622,7 @@ nextToken(); nextToken(); check(TOK.TOKrparen); - PostBlitDeclaration f = new PostBlitDeclaration(loc, Loc(0)); + auto f = new PostBlitDeclaration(loc, Loc(0)); parseContracts(f); return f; } @@ -1586,7 +1636,7 @@ { tpl = parseTemplateParameterList(); int varargs; - Arguments arguments = parseParameters(&varargs); + auto arguments = parseParameters(&varargs); Expression constraint = null; if (tpl) @@ -1605,7 +1655,7 @@ /* Just a regular constructor */ int varargs; - Arguments arguments = parseParameters(&varargs); + auto arguments = parseParameters(&varargs); CtorDeclaration f = new CtorDeclaration(loc, Loc(0), arguments, varargs); parseContracts(f); return f; @@ -1714,19 +1764,49 @@ return f; } + /***************************************** + * Parse a new definition: + * new(arguments) { body } + * Current token is 'new'. + */ NewDeclaration parseNew() { - assert(false); + NewDeclaration f; + scope arguments = new Parameters(); + int varargs; + Loc loc = this.loc; + + nextToken(); + arguments = parseParameters(&varargs); + f = new NewDeclaration(loc, Loc(0), arguments, varargs); + parseContracts(f); + return f; } + /***************************************** + * Parse a delete definition: + * delete(arguments) { body } + * Current token is 'delete'. + */ DeleteDeclaration parseDelete() { - assert(false); + DeleteDeclaration f; + scope Parameters arguments; + int varargs; + Loc loc = this.loc; + + nextToken(); + arguments = parseParameters(&varargs); + if (varargs) + error("... not allowed in delete function parameter list"); + f = new DeleteDeclaration(loc, Loc(0), arguments); + parseContracts(f); + return f; } - Arguments parseParameters(int* pvarargs) + Parameters parseParameters(int* pvarargs) { - Arguments arguments = new Arguments(); + auto arguments = new Parameters(); int varargs = 0; int hasdefault = 0; @@ -1735,9 +1815,9 @@ { Type *tb; Identifier ai = null; Type at; - Argument a; - STC storageClass = STC.STCundefined; - STC stc; + Parameter a; + StorageClass storageClass = STC.STCundefined; + StorageClass stc; Expression ae; for ( ;1; nextToken()) @@ -1770,14 +1850,23 @@ goto Ldefault; stc = STC.STCshared; goto L2; + + case TOKwild: + if (peek(&token).value == TOK.TOKlparen) + goto Ldefault; + stc = STCwild; + goto L2; case TOK.TOKin: stc = STC.STCin; goto L2; case TOK.TOKout: stc = STC.STCout; goto L2; +version(D1INOUT) { case TOK.TOKinout: +} case TOK.TOKref: stc = STC.STCref; goto L2; case TOK.TOKlazy: stc = STC.STClazy; goto L2; case TOK.TOKscope: stc = STC.STCscope; goto L2; case TOK.TOKfinal: stc = STC.STCfinal; goto L2; + case TOK.TOKauto: stc = STCauto; goto L2; L2: if (storageClass & stc || (storageClass & STC.STCin && stc & (STC.STCconst | STC.STCscope)) || @@ -1847,14 +1936,14 @@ if (storageClass & (STC.STCout | STC.STCref)) error("variadic argument cannot be out or ref"); varargs = 2; - a = new Argument(storageClass, at, ai, ae); - arguments.push(cast(void*)a); + a = new Parameter(storageClass, at, ai, ae); + arguments.push(a); nextToken(); break; } L3: - a = new Argument(storageClass, at, ai, ae); - arguments.push(cast(void*)a); + a = new Parameter(storageClass, at, ai, ae); + arguments.push(a); if (token.value == TOK.TOKcomma) { nextToken(); goto L1; @@ -2112,8 +2201,8 @@ } if (token.value == TOK.TOKidentifier) { - BaseClass b = new BaseClass(parseBasicType(), protection); - baseclasses.push(cast(void*)b); + auto b = new BaseClass(parseBasicType(), protection); + baseclasses.push(b); if (token.value != TOK.TOKcomma) break; } @@ -2131,7 +2220,7 @@ Import s; Identifier id; Identifier aliasid = null; - Array a; + Identifiers a; Loc loc; //printf("Parser.parseImport()\n"); @@ -2157,8 +2246,8 @@ while (token.value == TOK.TOKdot) { if (!a) - a = new Array(); - a.push(cast(void*)id); + a = new Identifiers(); + a.push(id); nextToken(); if (token.value != TOK.TOKidentifier) { @@ -2246,6 +2335,17 @@ t = t.makeSharedConst(); return t; } + else if (token.value == TOKwild && peekNext() == TOKshared && peekNext2() != TOKlparen || + token.value == TOKshared && peekNext() == TOKwild && peekNext2() != TOKlparen) + { + nextToken(); + nextToken(); + /* shared wild type + */ + t = parseType(pident, tpl); + t = t.makeSharedWild(); + return t; + } else if (token.value == TOK.TOKconst && peekNext() != TOK.TOKlparen) { nextToken(); @@ -2274,6 +2374,15 @@ t = t.makeShared(); return t; } + else if (token.value == TOKwild && peekNext() != TOKlparen) + { + nextToken(); + /* wild type + */ + t = parseType(pident, tpl); + t = t.makeWild(); + return t; + } else t = parseBasicType(); t = parseDeclarator(t, pident, tpl); @@ -2401,10 +2510,24 @@ check(TOK.TOKrparen); if (t.isConst()) t = t.makeSharedConst(); + else if (t.isWild()) + t = t.makeSharedWild(); else t = t.makeShared(); break; + case TOKwild: + // wild(type) + nextToken(); + check(TOK.TOKlparen); + t = parseType(); + check(TOK.TOKrparen); + if (t.isShared()) + t = t.makeSharedWild(); + else + t = t.makeWild(); + break; + default: error("basic type expected, not %s", token.toChars()); t = Type.tint32; @@ -2453,11 +2576,11 @@ { //printf("it's type[expression]\n"); inBrackets++; - Expression e = parseExpression(); // [ expression ] + Expression e = parseAssignExp(); // [ expression ] if (token.value == TOK.TOKslice) { nextToken(); - Expression e2 = parseExpression(); // [ exp .. exp ] + Expression e2 = parseAssignExp(); // [ exp .. exp ] t = new TypeSlice(t, e, e2); } else @@ -2472,27 +2595,52 @@ { // Handle delegate declaration: // t delegate(parameter list) nothrow pure // t function(parameter list) nothrow pure - Arguments arguments; + Parameters arguments; int varargs; bool ispure = false; bool isnothrow = false; + bool isproperty = false; TOK save = token.value; + TRUST trust = TRUSTdefault; nextToken(); arguments = parseParameters(&varargs); while (1) { // Postfixes if (token.value == TOK.TOKpure) - ispure = true; + ispure = true; else if (token.value == TOK.TOKnothrow) - isnothrow = true; + isnothrow = true; + else if (token.value == TOKat) + { StorageClass stc = parseAttribute(); + switch (cast(uint)(stc >> 32)) + { case STCproperty >> 32: + isproperty = true; + break; + case STCsafe >> 32: + trust = TRUSTsafe; + break; + case STCsystem >> 32: + trust = TRUSTsystem; + break; + case STCtrusted >> 32: + trust = TRUSTtrusted; + break; + case 0: + break; + default: + assert(0); + } + } else - break; + break; nextToken(); } TypeFunction tf = new TypeFunction(arguments, t, varargs, linkage); tf.ispure = ispure; tf.isnothrow = isnothrow; + tf.isproperty = isproperty; + tf.trust = trust; if (save == TOK.TOKdelegate) t = new TypeDelegate(tf); else @@ -2581,7 +2729,7 @@ else { //printf("It's a static array\n"); - Expression e = parseExpression(); // [ expression ] + Expression e = parseAssignExp(); // [ expression ] ta = new TypeSArray(t, e); check(TOK.TOKrbracket); } @@ -2616,7 +2764,7 @@ } int varargs; - Arguments arguments = parseParameters(&varargs); + auto arguments = parseParameters(&varargs); Type tf = new TypeFunction(arguments, t, varargs, linkage); /* Parse const/invariant/nothrow/pure postfix @@ -2647,6 +2795,14 @@ nextToken(); continue; + case TOKwild: + if (tf.isShared()) + tf = tf.makeSharedWild(); + else + tf = tf.makeWild(); + nextToken(); + continue; + case TOK.TOKnothrow: (cast(TypeFunction)tf).isnothrow = 1; nextToken(); @@ -2658,19 +2814,31 @@ continue; case TOK.TOKat: - nextToken(); - if (token.value != TOK.TOKidentifier) - { error("attribute identifier expected"); - nextToken(); - continue; - } - Identifier id = token.ident; - if (id is Id.property) - (cast(TypeFunction)tf).isproperty = 1; - else - error("valid attribute identifiers are @property, not @%s", id.toChars()); - nextToken(); - continue; + { + StorageClass stc = parseAttribute(); + auto tfunc = cast(TypeFunction)tf; + switch (cast(uint)(stc >> 32)) + { + case STCproperty >> 32: + tfunc.isproperty = 1; + break; + case STCsafe >> 32: + tfunc.trust = TRUSTsafe; + break; + case STCsystem >> 32: + tfunc.trust = TRUSTsystem; + break; + case STCtrusted >> 32: + tfunc.trust = TRUSTtrusted; + break; + case 0: + break; + default: + assert(0); + } + nextToken(); + continue; + } default: break; /// } @@ -2699,9 +2867,9 @@ return ts; } - Dsymbols parseDeclarations(STC storage_class) + Dsymbols parseDeclarations(StorageClass storage_class) { - STC stc; + StorageClass stc; Type ts; Type t; Type tfirst; @@ -2767,6 +2935,12 @@ if (peek(&token).value == TOK.TOKlparen) break; stc = STC.STCshared; + goto L1; + + case TOKwild: + if (peek(&token).value == TOK.TOKlparen) + break; + stc = STC.STCwild; goto L1; case TOK.TOKstatic: stc = STC.STCstatic; goto L1; @@ -2784,6 +2958,7 @@ case TOK.TOKtls: stc = STC.STCtls; goto L1; case TOK.TOKgshared: stc = STC.STCgshared; goto L1; case TOK.TOKenum: stc = STC.STCmanifest; goto L1; + case TOK.TOKat: stc = parseAttribute(); goto L1; } L1: if (storage_class & stc) @@ -2914,7 +3089,7 @@ auto tf = cast(TypeFunction)t; Expression constraint = null; static if (false) { - if (Argument.isTPL(tf.parameters)) + if (Parameter.isTPL(tf.parameters)) { if (!tpl) tpl = new TemplateParameters(); @@ -2995,7 +3170,6 @@ void parseContracts(FuncDeclaration f) { - Type tb; LINK linksave = linkage; // The following is irrelevant, as it is overridden by sc.linkage in @@ -3038,7 +3212,7 @@ check(TOK.TOKlparen); while (1) { - tb = parseBasicType(); + Type tb = parseBasicType(); f.fthrows.push(tb); if (token.value == TOK.TOKcomma) { nextToken(); @@ -3162,9 +3336,8 @@ case TOK.TOKline: } Lexp: - { Expression exp; - - exp = parseExpression(); + { + auto exp = parseExpression(); check(TOK.TOKsemicolon, "statement"); s = new ExpStatement(loc, exp); break; @@ -3187,6 +3360,16 @@ condition = parseStaticIfCondition(); goto Lcondition; } + if (tt.value == TOK.TOKstruct || tt.value == TOK.TOKunion || tt.value == TOK.TOKclass) + { + nextToken(); + auto a = parseBlock(); + Dsymbol d = new StorageClassDeclaration(STCstatic, a); + s = new DeclarationStatement(loc, d); + if (flags & ParseStatementFlags.PSscope) + s = new ScopeStatement(loc, s); + break; + } goto Ldeclaration; } @@ -3218,10 +3401,12 @@ version (DMDV2) { case TOK.TOKimmutable: case TOK.TOKshared: + case TOKwild: case TOK.TOKnothrow: case TOK.TOKpure: case TOK.TOKtls: case TOK.TOKgshared: + case TOK.TOKat: } // case TOK.TOKtypeof: Ldeclaration: @@ -3235,7 +3420,7 @@ foreach(Dsymbol d; a) { s = new DeclarationStatement(loc, d); - as.push(cast(void*)s); + as.push(s); } s = new CompoundDeclarationStatement(loc, as); } @@ -3308,7 +3493,7 @@ Statements statements = new Statements(); while (token.value != TOK.TOKrcurly && token.value != TOKeof) { - statements.push(cast(void*)parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope)); + statements.push(parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope)); } endloc = this.loc; s = new CompoundStatement(loc, statements); @@ -3397,26 +3582,23 @@ case TOK.TOKforeach_reverse: { TOK op = token.value; - Arguments arguments; - - Statement d; - Statement body_; - Expression aggr; nextToken(); check(TOK.TOKlparen); - arguments = new Arguments(); + auto arguments = new Parameters(); while (1) { - Type tb; Identifier ai = null; Type at; - STC storageClass = STC.STCundefined; - Argument a; - - if (token.value == TOK.TOKinout || token.value == TOK.TOKref) + StorageClass storageClass = STC.STCundefined; + + if (token.value == TOKref +//#if D1INOUT +// || token.value == TOKinout +//#endif + ) { storageClass = STC.STCref; nextToken(); } @@ -3434,8 +3616,8 @@ if (!ai) error("no identifier for declarator %s", at.toChars()); Larg: - a = new Argument(storageClass, at, ai, null); - arguments.push(cast(void*)a); + auto a = new Parameter(storageClass, at, ai, null); + arguments.push(a); if (token.value == TOK.TOKcomma) { nextToken(); continue; @@ -3444,28 +3626,28 @@ } check(TOK.TOKsemicolon); - aggr = parseExpression(); + Expression aggr = parseExpression(); if (token.value == TOK.TOKslice && arguments.dim == 1) { - Argument a = cast(Argument)arguments.data[0]; + auto a = arguments[0]; delete arguments; nextToken(); Expression upr = parseExpression(); check(TOK.TOKrparen); - body_ = parseStatement(cast(ParseStatementFlags)0); + auto body_ = parseStatement(cast(ParseStatementFlags)0); s = new ForeachRangeStatement(loc, op, a, aggr, upr, body_); } else { check(TOK.TOKrparen); - body_ = parseStatement(cast(ParseStatementFlags)0); + auto body_ = parseStatement(cast(ParseStatementFlags)0); s = new ForeachStatement(loc, op, arguments, aggr, body_); } break; } case TOK.TOKif: - { Argument arg = null; + { Parameter arg = null; Expression condition2; Statement ifbody2; Statement elsebody2; @@ -3481,7 +3663,7 @@ Token *tt = peek(&token); if (tt.value == TOK.TOKassign) { - arg = new Argument(STC.STCundefined, null, token.ident, null); + arg = new Parameter(STC.STCundefined, null, token.ident, null); nextToken(); nextToken(); } @@ -3502,7 +3684,7 @@ at = parseType(&ai); check(TOK.TOKassign); - arg = new Argument(STC.STCundefined, at, ai, null); + arg = new Parameter(STC.STCundefined, at, ai, null); } // Check for " ident;" @@ -3511,7 +3693,7 @@ Token *tt = peek(&token); if (tt.value == TOK.TOKcomma || tt.value == TOK.TOKsemicolon) { - arg = new Argument(STC.STCundefined, null, token.ident, null); + arg = new Parameter(STC.STCundefined, null, token.ident, null); nextToken(); nextToken(); if (1 || !global.params.useDeprecated) @@ -3627,14 +3809,14 @@ case TOK.TOKcase: { Expression exp; Statements statements; - scope Array cases = new Array(); // array of Expression's + scope cases = new Expressions(); // array of Expression's Expression last = null; while (1) { nextToken(); exp = parseAssignExp(); - cases.push(cast(void*)exp); + cases.push(exp); if (token.value != TOK.TOKcomma) break; } @@ -3660,7 +3842,7 @@ token.value != TOKeof && token.value != TOK.TOKrcurly) { - statements.push(cast(void*)parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope)); + statements.push(parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope)); } s = new CompoundStatement(loc, statements); s = new ScopeStatement(loc, s); @@ -3676,7 +3858,7 @@ // Keep cases in order by building the case statements backwards for (int i = cases.dim; i; i--) { - exp = cast(Expression)cases.data[i - 1]; + exp = cases[i - 1]; s = new CaseStatement(loc, exp, s); } } @@ -3696,7 +3878,7 @@ token.value != TOKeof && token.value != TOK.TOKrcurly) { - statements.push(cast(void*)parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope)); + statements.push(parseStatement(ParseStatementFlags.PSsemi | ParseStatementFlags.PScurlyscope)); } s = new CompoundStatement(loc, statements); s = new ScopeStatement(loc, s); @@ -3941,7 +4123,7 @@ s = new LabelStatement(labelloc, label, s); label = null; } - statements.push(cast(void*)s); + statements.push(s); } nextToken(); continue; @@ -4264,12 +4446,14 @@ if ((t.value == TOK.TOKconst || t.value == TOK.TOKinvariant || t.value == TOK.TOKimmutable || + t.value == TOKwild || t.value == TOK.TOKshared) && peek(t).value != TOK.TOKlparen) { /* const type * immutable type * shared type + * wild type */ t = peek(t); } @@ -4428,7 +4612,8 @@ case TOK.TOKinvariant: case TOK.TOKimmutable: case TOK.TOKshared: - // const(type) or immutable(type) or shared(type) + case TOKwild: + // const(type) or immutable(type) or shared(type) or wild(type) t = peek(t); if (t.value != TOK.TOKlparen) goto Lfalse; @@ -4593,6 +4778,7 @@ case TOK.TOKinvariant: case TOK.TOKimmutable: case TOK.TOKshared: + case TOKwild: case TOK.TOKpure: case TOK.TOKnothrow: t = peek(t); @@ -4653,18 +4839,22 @@ t = peek(t); break; +version(D1INOUT) { + case TOKinout: +} case TOKin: case TOKout: - case TOKinout: case TOKref: case TOKlazy: case TOKfinal: + case TOKauto: continue; case TOKconst: case TOKinvariant: case TOKimmutable: case TOKshared: + case TOKwild: t = peek(t); if (t.value == TOKlparen) { @@ -5104,13 +5294,20 @@ } case TOK.TOKtypeid: - { Type tt; - + { nextToken(); check(TOK.TOKlparen, "typeid"); - tt = parseType(); // ( type ) + Object o; + if (isDeclaration(&token, 0, TOKreserved, null)) + { // argument is a type + o = parseType(); + } + else + { // argument is an expression + o = parseAssignExp(); + } check(TOK.TOKrparen); - e = new TypeidExp(loc, tt); + e = new TypeidExp(loc, o); break; } @@ -5170,6 +5367,7 @@ token.value == TOK.TOKinvariant && peek(&token).value == TOK.TOKrparen || token.value == TOK.TOKimmutable && peek(&token).value == TOK.TOKrparen || token.value == TOK.TOKshared && peek(&token).value == TOK.TOKrparen || + token.value == TOKwild && peek(&token).value == TOKrparen || ///} token.value == TOK.TOKfunction || token.value == TOK.TOKdelegate || @@ -5192,7 +5390,7 @@ check(TOK.TOKrparen); } TemplateParameter tp = new TemplateTypeParameter(loc2, ident, null, null); - tpl.insert(0, cast(void*)tp); + tpl.insert(0, tp); } else check(TOK.TOKrparen); @@ -5312,18 +5510,20 @@ * (parameters) { body } * { body } */ - Arguments arguments; + Parameters arguments; int varargs; FuncLiteralDeclaration fd; Type tt; bool isnothrow = false; bool ispure = false; - + bool isproperty = false; + TRUST trust = TRUSTdefault; + if (token.value == TOK.TOKlcurly) { tt = null; varargs = 0; - arguments = new Arguments(); + arguments = new Parameters(); } else { @@ -5341,8 +5541,31 @@ ispure = true; else if (token.value == TOK.TOKnothrow) isnothrow = true; + else if (token.value == TOKat) + { + StorageClass stc = parseAttribute(); + switch (cast(uint)(stc >> 32)) + { + case STCproperty >> 32: + isproperty = true; + break; + case STCsafe >> 32: + trust = TRUSTsafe; + break; + case STCsystem >> 32: + trust = TRUSTsystem; + break; + case STCtrusted >> 32: + trust = TRUSTtrusted; + break; + case 0: + break; + default: + assert(0); + } + } else - break; + break; nextToken(); } } @@ -5350,6 +5573,8 @@ TypeFunction tf = new TypeFunction(arguments, tt, varargs, linkage); tf.ispure = ispure; tf.isnothrow = isnothrow; + tf.isproperty = isproperty; + tf.trust = trust; fd = new FuncLiteralDeclaration(loc, Loc(0), tf, save, null); parseContracts(fd); e = new FuncExp(loc, fd); @@ -5437,7 +5662,7 @@ nextToken(); check(TOK.TOKlparen); /* Look for cast(), cast(const), cast(immutable), - * cast(shared), cast(shared const) + * cast(shared), cast(shared const), cast(wild), cast(shared wild) */ MOD m; if (token.value == TOK.TOKrparen) @@ -5452,7 +5677,7 @@ } else if ((token.value == TOK.TOKimmutable || token.value == TOK.TOKinvariant) && peekNext() == TOK.TOKrparen) { - m = MOD.MODinvariant; + m = MOD.MODimmutable; goto Lmod2; } else if (token.value == TOK.TOKshared && peekNext() == TOK.TOKrparen) @@ -5460,10 +5685,22 @@ m = MOD.MODshared; goto Lmod2; } + else if (token.value == TOKwild && peekNext() == TOK.TOKrparen) + { + m = MODwild; + goto Lmod2; + } + else if (token.value == TOKwild && peekNext() == TOK.TOKshared && peekNext2() == TOK.TOKrparen || + token.value == TOK.TOKshared && peekNext() == TOKwild && peekNext2() == TOK.TOKrparen) + { + m = MOD.MODshared | MOD.MODwild; + goto Lmod3; + } else if (token.value == TOK.TOKconst && peekNext() == TOK.TOKshared && peekNext2() == TOK.TOKrparen || token.value == TOK.TOKshared && peekNext() == TOK.TOKconst && peekNext2() == TOK.TOKrparen) { m = MOD.MODshared | MOD.MODconst; + Lmod3: nextToken(); Lmod2: nextToken(); @@ -5590,6 +5827,15 @@ break; } assert(e); + + // ^^ is right associative and has higher precedence than the unary operators + while (token.value == TOK.TOKpow) + { + nextToken(); + Expression e2 = parseUnaryExp(); + e = new PowExp(loc, e, e2); + } + return e; } @@ -5611,14 +5857,15 @@ if (token.value == TOK.TOKnot && peekNext() != TOK.TOKis) { // identifier!(template-argument-list) TemplateInstance tempinst = new TemplateInstance(loc, id); + Objects tiargs; nextToken(); if (token.value == TOK.TOKlparen) // ident!(template_arguments) - tempinst.tiargs = parseTemplateArgumentList(); + tiargs = parseTemplateArgumentList(); else // ident!template_argument - tempinst.tiargs = parseTemplateArgument(); - e = new DotTemplateInstanceExp(loc, e, tempinst); + tiargs = parseTemplateArgument(); + e = new DotTemplateInstanceExp(loc, e, id, tiargs); } else e = new DotIdExp(loc, e, id); @@ -5715,8 +5962,8 @@ switch (token.value) { case TOK.TOKmul: nextToken(); e2 = parseUnaryExp(); e = new MulExp(loc,e,e2); continue; - case TOK.TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue; - case TOK.TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue; + case TOK.TOKdiv: nextToken(); e2 = parseUnaryExp(); e = new DivExp(loc,e,e2); continue; + case TOK.TOKmod: nextToken(); e2 = parseUnaryExp(); e = new ModExp(loc,e,e2); continue; default: break; @@ -5983,6 +6230,7 @@ case TOK.TOKmulass: nextToken(); e2 = parseAssignExp(); e = new MulAssignExp(loc,e,e2); continue; case TOK.TOKdivass: nextToken(); e2 = parseAssignExp(); e = new DivAssignExp(loc,e,e2); continue; case TOK.TOKmodass: nextToken(); e2 = parseAssignExp(); e = new ModAssignExp(loc,e,e2); continue; + case TOK.TOKpowass: nextToken(); e2 = parseAssignExp(); e = new PowAssignExp(loc,e,e2); continue; case TOK.TOKandass: nextToken(); e2 = parseAssignExp(); e = new AndAssignExp(loc,e,e2); continue; case TOK.TOKorass: nextToken(); e2 = parseAssignExp(); e = new OrAssignExp(loc,e,e2); continue; case TOK.TOKxorass: nextToken(); e2 = parseAssignExp(); e = new XorAssignExp(loc,e,e2); continue; diff -r 786ea1839396 -r 78bf0fe43974 dmd/PeelStatement.d --- a/dmd/PeelStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/PeelStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.PeelStatement; +import dmd.common; import dmd.Statement; import dmd.Scope; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Port.d --- a/dmd/Port.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Port.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Port; +import dmd.common; import core.stdc.math; struct Port diff -r 786ea1839396 -r 78bf0fe43974 dmd/PostBlitDeclaration.d --- a/dmd/PostBlitDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/PostBlitDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.PostBlitDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.Global; import dmd.LINK; diff -r 786ea1839396 -r 78bf0fe43974 dmd/PostExp.d --- a/dmd/PostExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/PostExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.PostExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; @@ -69,11 +70,8 @@ override elem* toElem(IRState* irs) { - elem* e; - elem* einc; - - e = e1.toElem(irs); - einc = e2.toElem(irs); + auto e = e1.toElem(irs); + auto einc = e2.toElem(irs); e = el_bin((op == TOKplusplus) ? OPpostinc : OPpostdec, e.Ety,e,einc); el_setLoc(e,loc); diff -r 786ea1839396 -r 78bf0fe43974 dmd/PowAssignExp.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/PowAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,77 @@ +module dmd.PowAssignExp; + +import dmd.BinExp; +import dmd.Scope; +import dmd.Loc; +import dmd.Identifier; +import dmd.Expression; +import dmd.TOK; +import dmd.STC; +import dmd.PowExp; +import dmd.AssignExp; +import dmd.Lexer; +import dmd.VarDeclaration; +import dmd.ExpInitializer; +import dmd.DeclarationExp; +import dmd.VarExp; +import dmd.CommaExp; +import dmd.ErrorExp; +import dmd.Id; + +// Only a reduced subset of operations for now. +class PowAssignExp : BinExp +{ + this(Loc loc, Expression e1, Expression e2) + { + super(loc, TOK.TOKpowass, PowAssignExp.sizeof, e1, e2); + } + + override Expression semantic(Scope sc) + { + Expression e; + + if (type) + return this; + + BinExp.semantic(sc); + e2 = resolveProperties(sc, e2); + + e = op_overload(sc); + if (e) + return e; + + e1 = e1.modifiableLvalue(sc, e1); + assert(e1.type && e2.type); + + if ( (e1.type.isintegral() || e1.type.isfloating()) && + (e2.type.isintegral() || e2.type.isfloating())) + { + if (e1.op == TOKvar) + { // Rewrite: e1 = e1 ^^ e2 + e = new PowExp(loc, e1.syntaxCopy(), e2); + e = new AssignExp(loc, e1, e); + } + else + { // Rewrite: ref tmp = e1; tmp = tmp ^^ e2 + Identifier id = Lexer.uniqueId("__powtmp"); + auto v = new VarDeclaration(e1.loc, e1.type, id, new ExpInitializer(loc, e1)); + v.storage_class |= STC.STCref | STC.STCforeach; + Expression de = new DeclarationExp(e1.loc, v); + VarExp ve = new VarExp(e1.loc, v); + e = new PowExp(loc, ve, e2); + e = new AssignExp(loc, new VarExp(e1.loc, v), e); + e = new CommaExp(loc, de, e); + } + e = e.semantic(sc); + return e; + } + error("%s ^^= %s is not supported", e1.type.toChars(), e2.type.toChars() ); + return new ErrorExp(); + } + + // For operator overloading + Identifier opId() + { + return Id.powass; + } +}; \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/PowExp.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/PowExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,171 @@ +module dmd.PowExp; + +import dmd.BinExp; +import dmd.Scope; +import dmd.Loc; +import dmd.Identifier; +import dmd.Expression; +import dmd.TOK; +import dmd.Module; +import dmd.Id; +import dmd.IdentifierExp; +import dmd.DotIdExp; +import dmd.CallExp; +import dmd.ErrorExp; +import dmd.CommaExp; +import dmd.AndExp; +import dmd.CondExp; +import dmd.IntegerExp; +import dmd.Type; +import dmd.Lexer; +import dmd.VarDeclaration; +import dmd.ExpInitializer; +import dmd.VarExp; +import dmd.DeclarationExp; +import dmd.MulExp; +import dmd.WANT; + +version(DMDV2) { + +class PowExp : BinExp +{ + this(Loc loc, Expression e1, Expression e2) + { + super(loc, TOK.TOKpow, PowExp.sizeof, e1, e2); + } + + override Expression semantic(Scope sc) + { + Expression e; + + if (type) + return this; + + //printf("PowExp::semantic() %s\n", toChars()); + BinExp.semanticp(sc); + e = op_overload(sc); + if (e) + return e; + + assert(e1.type && e2.type); + if ( (e1.type.isintegral() || e1.type.isfloating()) && + (e2.type.isintegral() || e2.type.isfloating())) + { + // For built-in numeric types, there are several cases. + // TODO: backend support, especially for e1 ^^ 2. + + bool wantSqrt = false; + e1 = e1.optimize(0); + e2 = e2.optimize(0); + + // Replace 1 ^^ x or 1.0^^x by (x, 1) + if ((e1.op == TOK.TOKint64 && e1.toInteger() == 1) || + (e1.op == TOK.TOKfloat64 && e1.toReal() == 1.0)) + { + typeCombine(sc); + e = new CommaExp(loc, e2, e1); + e = e.semantic(sc); + return e; + } + // Replace -1 ^^ x by (x&1) ? -1 : 1, where x is integral + if (e2.type.isintegral() && e1.op == TOKint64 && cast(long)e1.toInteger() == -1) + { + typeCombine(sc); + Type resultType = type; + e = new AndExp(loc, e2, new IntegerExp(loc, 1, e2.type)); + e = new CondExp(loc, e, new IntegerExp(loc, -1, resultType), new IntegerExp(loc, 1, resultType)); + e = e.semantic(sc); + return e; + } + // All other negative integral powers are illegal + if ((e1.type.isintegral()) && (e2.op == TOK.TOKint64) && cast(long)e2.toInteger() < 0) + { + error("cannot raise %s to a negative integer power. Did you mean (cast(real)%s)^^%s ?", + e1.type.toBasetype().toChars(), e1.toChars(), e2.toChars()); + return new ErrorExp(); + } + + // 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) + ) + { + 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); + Expression ae = new DeclarationExp(loc, tmp); + 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); + e = new CommaExp(loc, ae, me); + e = e.semantic(sc); + return e; + } + + static int importMathChecked = 0; + if (!importMathChecked) + { + importMathChecked = 1; + for (int i = 0; i < Module.amodules.dim; i++) + { + auto mi = cast(Module)Module.amodules.data[i]; + //printf("\t[%d] %s\n", i, mi->toChars()); + if (mi.ident == Id.math && + mi.parent.ident == Id.std && + !mi.parent.parent) + goto L1; + } + error("must import std.math to use ^^ operator"); + + L1: ; + } + + e = new IdentifierExp(loc, Id.empty); + e = new DotIdExp(loc, e, Id.std); + e = new DotIdExp(loc, e, Id.math); + if (e2.op == TOK.TOKfloat64 && e2.toReal() == 0.5) + { // Replace e1 ^^ 0.5 with .std.math.sqrt(x) + typeCombine(sc); + e = new CallExp(loc, new DotIdExp(loc, e, Id._sqrt), e1); + } + else + { + // Replace e1 ^^ e2 with .std.math.pow(e1, e2) + // We don't combine the types if raising to an integer power (because + // integer powers are treated specially by std.math.pow). + if (!e2.type.isintegral()) + typeCombine(sc); + e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2); + } + e = e.semantic(sc); + // Always constant fold integer powers of literals. This will run the interpreter + // on .std.math.pow + if ((e1.op == TOK.TOKfloat64 || e1.op == TOK.TOKint64) && (e2.op == TOK.TOKint64)) + e = e.optimize(WANT.WANTvalue | WANT.WANTinterpret); + + return e; + } + error("%s ^^ %s is not supported", e1.type.toChars(), e2.type.toChars() ); + return new ErrorExp(); + } + + + // For operator overloading + override Identifier opId() + { + return Id.pow; + } + + override Identifier opId_r() + { + return Id.pow_r; + } +} + +} \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/PragmaDeclaration.d --- a/dmd/PragmaDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/PragmaDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.PragmaDeclaration; +import dmd.common; import dmd.ArrayTypes; import dmd.AttribDeclaration; import dmd.Loc; @@ -60,7 +61,7 @@ if (e.op == TOKstring) { auto se = cast(StringExp)e; - writef("%s", se.toChars()[1..$-3] /*se.len, cast(char*)se.string_*/); + writef("%s", se.toChars()[1..$-2]); // strip the '"'s, TODO: change to original?: /*se.len, cast(char*)se.string_*/ } else writef(e.toChars()); @@ -126,6 +127,7 @@ /// goto Lnodecl; /// } /// } +///version(DMDV2) { else if (ident == Id.startaddress) { if (!args || args.dim != 1) @@ -142,6 +144,7 @@ } goto Lnodecl; } +///} /// version (TARGET_NET) { /// else if (ident == Lexer.idPool("assembly")) /// { diff -r 786ea1839396 -r 78bf0fe43974 dmd/PragmaStatement.d --- a/dmd/PragmaStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/PragmaStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,7 +1,12 @@ module dmd.PragmaStatement; +import dmd.common; +import dmd.expression.Util; import dmd.Statement; +import dmd.StringExp; +import dmd.Id; import dmd.Identifier; +import dmd.Dsymbol; import dmd.Expression; import dmd.Loc; import dmd.Identifier; @@ -10,44 +15,168 @@ import dmd.HdrGenState; import dmd.IRState; import dmd.BE; +import dmd.TOK; +import dmd.WANT; class PragmaStatement : Statement { - Identifier ident; - Expressions args; // array of Expression's - Statement body_; + Identifier ident; + Expressions args; // array of Expression's + Statement body_; - this(Loc loc, Identifier ident, Expressions args, Statement body_) + this(Loc loc, Identifier ident, Expressions args, Statement body_) { super(loc); + this.ident = ident; + this.args = args; + this.body_ = body_; } - override Statement syntaxCopy() + override Statement syntaxCopy() { - assert(false); + Statement b = null; + if (body_) + b = body_.syntaxCopy(); + PragmaStatement s = new PragmaStatement(loc, + ident, Expression.arraySyntaxCopy(args), b); + return s; + } - override Statement semantic(Scope sc) + override Statement semantic(Scope sc) { - assert(false); - } + // Should be merged with PragmaDeclaration + //writef("PragmaStatement.semantic() %s\n", toChars()); + //writef("body = %p\n", body_); + if (ident == Id.msg) + { + if (args) + { + foreach (Expression e; args) + { + e = e.semantic(sc); + e = e.optimize(WANTvalue | WANTinterpret); + if (e.op == TOK.TOKstring) + { + StringExp se = cast(StringExp)e; + writef("%.*s", se.len, cast(char*)se.string_); + } + else + writef(e.toChars()); + } + writef("\n"); + } + } + else if (ident == Id.lib) + { +static if (true) +{ + /* Should this be allowed? + */ + error("pragma(lib) not allowed as statement"); +} +else +{ + if (!args || args.dim != 1) + error("string expected for library name"); + else + { + Expression e = args[0]; - override bool usesEH() - { - assert(false); + e = e.semantic(sc); + e = e.optimize(WANTvalue | WANTinterpret); + args[0] = e; + if (e.op != TOKstring) + error("string expected for library name, not '%s'", e.toChars()); + else if (global.params.verbose) + { + StringExp se = cast(StringExp)e; + writef("library %.*s\n", se.len, se.string_); + } + } +} + } +//version(DMDV2) // TODO: +//{ + else if (ident == Id.startaddress) + { + if (!args || args.dim != 1) + error("function name expected for start address"); + else + { + Expression e = args[0]; + e = e.semantic(sc); + e = e.optimize(WANTvalue | WANTinterpret); + args[0] = e; + Dsymbol sa = getDsymbol(e); + if (!sa || !sa.isFuncDeclaration()) + error("function name expected for start address, not '%s'", e.toChars()); + if (body_) + { + body_ = body_.semantic(sc); + } + return this; + } + } +//} + else + error("unrecognized pragma(%s)", ident.toChars()); + + if (body_) + { + body_ = body_.semantic(sc); + } + return body_; } - override BE blockExit() + override bool usesEH() + { + return body_ && body_.usesEH(); + } + + override BE blockExit() { - assert(false); + BE result = BEfallthru; +static if (false) // currently, no code is generated for Pragma's, so it's just fallthru +{ + if (arrayExpressionCanThrow(args)) + result |= BEthrow; + if (body_) + result |= body_.blockExit(); +} + return result; } - override void toCBuffer(OutBuffer buf, HdrGenState* hgs) + override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + buf.writestring("pragma ("); + buf.writestring(ident.toChars()); + if (args && args.dim) + { + buf.writestring(", "); + argsToCBuffer(buf, args, hgs); + } + buf.writeByte(')'); + if (body_) + { + buf.writenl(); + buf.writeByte('{'); + buf.writenl(); + + body_.toCBuffer(buf, hgs); + + buf.writeByte('}'); + buf.writenl(); + } + else + { + buf.writeByte(';'); + buf.writenl(); + } + } - override void toIR(IRState* irs) + override void toIR(IRState* irs) { assert(false); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/ProtDeclaration.d --- a/dmd/ProtDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ProtDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ProtDeclaration; +import dmd.common; import dmd.AttribDeclaration; import dmd.PROT; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/PtrExp.d --- a/dmd/PtrExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/PtrExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.PtrExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; @@ -84,7 +85,12 @@ { return 1; } - + + override void checkEscapeRef() + { + e1.checkEscape(); + } + override Expression toLvalue(Scope sc, Expression e) { static if (false) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/RealExp.d --- a/dmd/RealExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/RealExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,7 @@ module dmd.RealExp; +import dmd.common; +import dmd.Complex; import dmd.Expression; import dmd.backend.elem; import dmd.InterState; @@ -14,13 +16,13 @@ import dmd.Port; import dmd.TY; +import dmd.expression.Util; + import dmd.backend.dt_t; import dmd.backend.Util; import dmd.backend.TYM; import dmd.backend.mTY; -import dmd.Complex; - import std.stdio; class RealExp : Expression @@ -37,7 +39,20 @@ override bool equals(Object o) { - assert(false); + if (this is o) + return true; + + Expression e = cast(Expression)o; + if (e.op == TOKfloat64) { + RealExp ne = cast(RealExp)e; + if (type.toHeadMutable().equals(ne.type.toHeadMutable())) { + if (RealEquals(value, ne.value)) { + return true; + } + } + } + + return 0; } override Expression semantic(Scope sc) @@ -109,7 +124,7 @@ override bool isBool(bool result) { - assert(false); + return result ? (value != 0) : (value == 0); } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) @@ -119,7 +134,8 @@ override void toMangleBuffer(OutBuffer buf) { - assert(false); + buf.writeByte('e'); + realToMangleBuffer(buf, value); } override elem* toElem(IRState* irs) diff -r 786ea1839396 -r 78bf0fe43974 dmd/RemoveExp.d --- a/dmd/RemoveExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/RemoveExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.RemoveExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.Loc; @@ -38,7 +39,7 @@ elem* ep; elem* keyti; - if (tybasic(ekey.Ety) == TYstruct) + if (tybasic(ekey.Ety) == TYstruct || tybasic(ekey.Ety) == TYarray) { ekey = el_una(OPstrpar, TYstruct, ekey); ekey.Enumbytes = ekey.E1.Enumbytes; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ReturnStatement.d --- a/dmd/ReturnStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ReturnStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ReturnStatement; +import dmd.common; import dmd.Loc; import dmd.Statement; import dmd.GotoStatement; @@ -34,6 +35,7 @@ import dmd.VarDeclaration; import dmd.GlobalExpressions; import dmd.BE; +import dmd.Global; import dmd.codegen.Util; @@ -172,14 +174,46 @@ if (fd.returnLabel && tbret.ty != TY.Tvoid) { ; } else if (fd.inferRetType) { - if (fd.type.nextOf()) { - if (!exp.type.equals(fd.type.nextOf())) - error("mismatched function return type inference of %s and %s", exp.type.toChars(), fd.type.nextOf().toChars()); + auto tf = cast(TypeFunction)fd.type; + assert(tf.ty == TY.Tfunction); + Type tfret = tf.nextOf(); + if (tfret) + { + if (!exp.type.equals(tfret)) + error("mismatched function return type inference of %s and %s", exp.type.toChars(), tfret.toChars()); + /* The "refness" is determined by the first return statement, + * not all of them. This means: + * return 3; return x; // ok, x can be a value + * return x; return 3; // error, 3 is not an lvalue + */ } else { - (cast(TypeFunction)fd.type).next = exp.type; - fd.type = fd.type.semantic(loc, sc); + if (tf.isref) + { /* Determine "refness" of function return: + * if it's an lvalue, return by ref, else return by value + */ + if (exp.isLvalue()) + { + /* Return by ref + * (but first ensure it doesn't fail the "check for + * escaping reference" test) + */ + uint errors = global.errors; + global.gag++; + exp.checkEscapeRef(); + global.gag--; + if (errors != global.errors) + { tf.isref = false; // return by value + global.errors = errors; + } + } + else + tf.isref = false; // return by value + } + tf.next = exp.type; + fd.type = tf.semantic(loc, sc); + if (!fd.tintro) { tret = fd.type.nextOf(); @@ -289,19 +323,14 @@ else exp = exp.toLvalue(sc, exp); - if (exp.op == TOK.TOKvar) - { - VarExp ve = cast(VarExp)exp; - VarDeclaration v = ve.var.isVarDeclaration(); - if (v && !v.isDataseg() && !(v.storage_class & (STC.STCref | STC.STCout))) { - error("escaping reference to local variable %s", v.toChars()); - } - } + exp.checkEscapeRef(); } - - //exp.dump(0); - //exp.print(); - exp.checkEscape(); + else + { + //exp.dump(0); + //exp.print(); + exp.checkEscape(); + } } /* BUG: need to issue an error on: diff -r 786ea1839396 -r 78bf0fe43974 dmd/STC.d --- a/dmd/STC.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/STC.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,6 +1,6 @@ module dmd.STC; -enum STC +enum STC : ulong { STCundefined = 0, STCstatic = 1, @@ -23,7 +23,6 @@ STCctorinit = 0x20000, // can only be set inside constructor STCtemplateparameter = 0x40000, // template parameter STCscope = 0x80000, // template parameter - STCinvariant = 0x100000, STCimmutable = 0x100000, STCref = 0x200000, STCinit = 0x400000, // has explicit initializer @@ -36,8 +35,17 @@ STCshared = 0x20000000, // accessible from multiple threads STCgshared = 0x40000000, // accessible from multiple threads // but not typed as "shared" - STC_TYPECTOR = (STCconst | STCimmutable | STCshared), + STCwild = 0x80000000, // for "wild" type constructor + STC_TYPECTOR = (STCconst | STCimmutable | STCshared | STCwild), + + // attributes + STCproperty = 0x100000000, + STCsafe = 0x200000000, + STCtrusted = 0x400000000, + STCsystem = 0x800000000, + STCctfe = 0x1000000000, // can be used in CTFE, even if it is static } +alias STC StorageClass; import dmd.EnumUtils; mixin(BringToCurrentScope!(STC)); \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/Scope.d --- a/dmd/Scope.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Scope.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Scope; +import dmd.common; import dmd.Module; import dmd.ScopeDsymbol; import dmd.FuncDeclaration; @@ -77,7 +78,7 @@ PROT protection = PROT.PROTpublic; // protection for class members int explicitProtection; // set if in an explicit protection attribute - STC stc; // storage class + StorageClass stc; // storage class SCOPE flags; @@ -136,6 +137,7 @@ this.sd = null; this.sw = enclosing.sw; this.tf = enclosing.tf; + this.tinst = enclosing.tinst; this.tinst = enclosing.tinst; this.sbreak = enclosing.sbreak; this.scontinue = enclosing.scontinue; @@ -170,13 +172,7 @@ Scope clone() { - // similar code is used in Type.clone() - // TODO: move to Util or something... - size_t size = __traits(classInstanceSize, typeof(this)); - void* mem = GC.malloc(size); - memcpy(mem, cast(void*)this, size); - - return cast(typeof(this))mem; + return cloneThis(this); } Scope push() diff -r 786ea1839396 -r 78bf0fe43974 dmd/ScopeDsymbol.d --- a/dmd/ScopeDsymbol.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ScopeDsymbol.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ScopeDsymbol; +import dmd.common; import dmd.Dsymbol; import dmd.Declaration; import dmd.Array; @@ -247,8 +248,8 @@ if (!tfgetmembers) { Scope sc; - Arguments arguments = new Arguments(); - Arguments arg = new Argument(STCin, Type.tchar.constOf().arrayOf(), null, null); + auto arguments = new Arguments(); + auto arg = new Argument(STCin, Type.tchar.constOf().arrayOf(), null, null); arguments.push(arg); Type tret = null; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ScopeExp.d --- a/dmd/ScopeExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ScopeExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ScopeExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.ScopeDsymbol; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ScopeStatement.d --- a/dmd/ScopeStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ScopeStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ScopeStatement; +import dmd.common; import dmd.Statement; import dmd.Loc; import dmd.Scope; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ShlAssignExp.d --- a/dmd/ShlAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ShlAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ShlAssignExp; +import dmd.common; import dmd.BinExp; import dmd.Loc; import dmd.Expression; @@ -10,8 +11,10 @@ import dmd.TOK; import dmd.Id; import dmd.Type; +import dmd.ArrayLengthExp; import dmd.backend.elem; import dmd.backend.OPER; +import dmd.expression.Shl; import dmd.expression.Util; class ShlAssignExp : BinExp @@ -33,6 +36,13 @@ if (e) return e; + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + e1 = e1.modifiableLvalue(sc, e1); e1.checkScalar(); e1.checkNoBool(); @@ -46,7 +56,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Shl); } override Identifier opId() /* For operator overloading */ diff -r 786ea1839396 -r 78bf0fe43974 dmd/ShlExp.d --- a/dmd/ShlExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ShlExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ShlExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.backend.elem; @@ -56,7 +57,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &Shl); } override IntRange getIntRange() diff -r 786ea1839396 -r 78bf0fe43974 dmd/ShrAssignExp.d --- a/dmd/ShrAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ShrAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ShrAssignExp; +import dmd.common; import dmd.BinExp; import dmd.Loc; import dmd.Expression; @@ -10,10 +11,13 @@ import dmd.Id; import dmd.TOK; import dmd.Type; +import dmd.ArrayLengthExp; +import dmd.CastExp; import dmd.backend.elem; import dmd.backend.OPER; +import dmd.expression.Shr; import dmd.expression.Util; class ShrAssignExp : BinExp @@ -34,6 +38,13 @@ if (e) return e; + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + e1 = e1.modifiableLvalue(sc, e1); e1.checkScalar(); e1.checkNoBool(); @@ -48,7 +59,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Shr); } override Identifier opId() /* For operator overloading */ @@ -58,6 +69,15 @@ override elem* toElem(IRState* irs) { - return toElemBin(irs, OPshrass); + //printf("ShrAssignExp::toElem() %s, %s\n", e1->type->toChars(), e1->toChars()); + Type t1 = e1.type; + if (e1.op == TOK.TOKcast) + { + // Use the type before it was integrally promoted to int + auto ce = cast(CastExp)e1; + t1 = ce.e1.type; + } + return toElemBin(irs, t1.isunsigned() ? OPER.OPshrass : OPER.OPashrass); + } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/ShrExp.d --- a/dmd/ShrExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ShrExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ShrExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.InterState; @@ -54,7 +55,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &Shr); } override IntRange getIntRange() @@ -74,7 +75,7 @@ override elem* toElem(IRState* irs) { - return toElemBin(irs, OPER.OPshr); + return toElemBin(irs, e1.type.isunsigned() ? OPER.OPshr : OPER.OPashr); } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/SliceExp.d --- a/dmd/SliceExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/SliceExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.SliceExp; +import dmd.common; import dmd.Expression; import dmd.expression.ArrayLength; import dmd.backend.elem; @@ -30,7 +31,7 @@ import dmd.VarDeclaration; import dmd.ErrorExp; import dmd.TypeExp; -import dmd.Argument; +import dmd.Parameter; import dmd.ExpInitializer; import dmd.IRState; import dmd.InlineDoState; @@ -199,7 +200,7 @@ else if (e1.op == TOKtype) // slicing a type tuple { tup = cast(TypeTuple)t; - length = Argument.dim(tup.arguments); + length = Parameter.dim(tup.arguments); } else assert(0); @@ -222,12 +223,12 @@ } else { - Arguments args = new Arguments; + auto args = new Parameters; args.reserve(j2 - j1); for (size_t i = j1; i < j2; i++) { - Argument arg = Argument.getNth(tup.arguments, i); - args.push(cast(void*)arg); + auto arg = Parameter.getNth(tup.arguments, i); + args.push(arg); } e = new TypeExp(e1.loc, new TypeTuple(args)); } @@ -264,6 +265,11 @@ { e1.checkEscape(); } + + override void checkEscapeRef() + { + e1.checkEscapeRef(); + } version (DMDV2) { override int isLvalue() @@ -378,36 +384,26 @@ override elem* toElem(IRState* irs) { - elem* e; - Type t1; - //printf("SliceExp.toElem()\n"); - t1 = e1.type.toBasetype(); - e = e1.toElem(irs); + auto t1 = e1.type.toBasetype(); + auto e = e1.toElem(irs); if (lwr) { - elem* elwr; - elem* elwr2; - elem* eupr; - elem* eptr; - elem* einit; - int sz; + auto einit = resolveLengthVar(lengthVar, &e, t1); + + int sz = cast(uint)t1.nextOf().size(); - einit = resolveLengthVar(lengthVar, &e, t1); - - sz = cast(uint)t1.nextOf().size(); + auto elwr = lwr.toElem(irs); + auto eupr = upr.toElem(irs); - elwr = lwr.toElem(irs); - eupr = upr.toElem(irs); - - elwr2 = el_same(&elwr); + auto elwr2 = el_same(&elwr); // Create an array reference where: // length is (upr - lwr) // pointer is (ptr + lwr*sz) // Combine as (length pair ptr) - if (global.params.useArrayBounds) + if (irs.arrayBoundsCheck()) { // Checks (unsigned compares): // upr <= array.length @@ -469,7 +465,7 @@ } } - eptr = array_toPtr(e1.type, e); + auto eptr = array_toPtr(e1.type, e); elem *elength = el_bin(OPmin, TYint, eupr, elwr2); eptr = el_bin(OPadd, TYnptr, eptr, el_bin(OPmul, TYint, el_copytree(elwr2), el_long(TYint, sz))); @@ -508,11 +504,11 @@ arguments.shift(this); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { Identifier id = Identifier.generateId("p", fparams.dim); - Argument param = new Argument(STCconst, type, id, null); - fparams.shift(cast(void*)param); + auto param = new Parameter(STCconst, type, id, null); + fparams.shift(param); Expression e = new IdentifierExp(Loc(0), id); Expressions arguments = new Expressions(); Expression index = new IdentifierExp(Loc(0), Id.p); diff -r 786ea1839396 -r 78bf0fe43974 dmd/Statement.d --- a/dmd/Statement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Statement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Statement; +import dmd.common; import dmd.TryCatchStatement; import dmd.GotoStatement; import dmd.AsmStatement; @@ -119,9 +120,11 @@ assert(false); } + // TRUE if statement uses exception handling + bool usesEH() { - assert(false); + return false; } BE blockExit() diff -r 786ea1839396 -r 78bf0fe43974 dmd/StaticAssert.d --- a/dmd/StaticAssert.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StaticAssert.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StaticAssert; +import dmd.common; import dmd.Dsymbol; import dmd.Expression; import dmd.OutBuffer; @@ -67,12 +68,11 @@ else error("(%s) is false", exp.toChars()); - if(sc.tinst) + if (sc.tinst) sc.tinst.printInstantiationTrace(); - if (!global.gag) { + if (!global.gag) fatal(); - } } else if (!e.isBool(true)) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/StaticAssertStatement.d --- a/dmd/StaticAssertStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StaticAssertStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StaticAssertStatement; +import dmd.common; import dmd.Statement; import dmd.StaticAssert; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/StaticCtorDeclaration.d --- a/dmd/StaticCtorDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StaticCtorDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StaticCtorDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.Loc; import dmd.Dsymbol; @@ -65,14 +66,14 @@ v.storage_class = STCstatic; Statements sa = new Statements(); Statement s = new DeclarationStatement(Loc(0), v); - sa.push(cast(void*)s); + sa.push(s); Expression e = new IdentifierExp(Loc(0), id); e = new AddAssignExp(Loc(0), e, new IntegerExp(1)); e = new EqualExp(TOKnotequal, Loc(0), e, new IntegerExp(1)); s = new IfStatement(Loc(0), null, e, new ReturnStatement(Loc(0), null), null); - sa.push(cast(void*)s); + sa.push(s); if (fbody) - sa.push(cast(void*)fbody); + sa.push(fbody); fbody = new CompoundStatement(Loc(0), sa); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/StaticDtorDeclaration.d --- a/dmd/StaticDtorDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StaticDtorDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StaticDtorDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.VarDeclaration; import dmd.Dsymbol; @@ -42,7 +43,7 @@ { assert(!s); StaticDtorDeclaration sdd = new StaticDtorDeclaration(loc, endloc); - return FuncDeclaration.syntaxCopy(sdd); + return super.syntaxCopy(sdd); } override void semantic(Scope sc) @@ -72,16 +73,16 @@ Identifier id = Lexer.idPool("__gate"); VarDeclaration v = new VarDeclaration(Loc(0), Type.tint32, id, null); v.storage_class = STCstatic; - Statements sa = new Statements(); + auto sa = new Statements(); Statement s = new DeclarationStatement(Loc(0), v); - sa.push(cast(void*)s); + sa.push(s); Expression e = new IdentifierExp(Loc(0), id); e = new AddAssignExp(Loc(0), e, new IntegerExp(-1)); e = new EqualExp(TOKnotequal, Loc(0), e, new IntegerExp(0)); s = new IfStatement(Loc(0), null, e, new ReturnStatement(Loc(0), null), null); - sa.push(cast(void*)s); + sa.push(s); if (fbody) - sa.push(cast(void*)fbody); + sa.push(fbody); fbody = new CompoundStatement(Loc(0), sa); vgate = v; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/StaticIfCondition.d --- a/dmd/StaticIfCondition.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StaticIfCondition.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StaticIfCondition; +import dmd.common; import dmd.Expression; import dmd.ScopeDsymbol; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/StaticIfDeclaration.d --- a/dmd/StaticIfDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StaticIfDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StaticIfDeclaration; +import dmd.common; import dmd.ConditionalDeclaration; import dmd.ScopeDsymbol; import dmd.AttribDeclaration; diff -r 786ea1839396 -r 78bf0fe43974 dmd/StorageClassDeclaration.d --- a/dmd/StorageClassDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StorageClassDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StorageClassDeclaration; +import dmd.common; import dmd.AttribDeclaration; import dmd.Array; import dmd.TOK; @@ -9,12 +10,14 @@ import dmd.OutBuffer; import dmd.HdrGenState; import dmd.STC; +import dmd.Id; +import dmd.Identifier; class StorageClassDeclaration: AttribDeclaration { - STC stc; + StorageClass stc; - this(STC stc, Dsymbols decl) + this(StorageClass stc, Dsymbols decl) { super(decl); @@ -34,7 +37,7 @@ { if (decl) { - STC scstc = sc.stc; + StorageClass scstc = sc.stc; /* These sets of storage classes are mutually exclusive, * so choose the innermost or most recent one. @@ -47,6 +50,8 @@ scstc &= ~(STC.STCconst | STC.STCimmutable | STC.STCmanifest); if (stc & (STC.STCgshared | STC.STCshared | STC.STCtls)) scstc &= ~(STC.STCgshared | STC.STCshared | STC.STCtls); + if (stc & (STCsafe | STCtrusted | STCsystem)) + scstc &= ~(STCsafe | STCtrusted | STCsystem); scstc |= stc; setScopeNewSc(sc, scstc, sc.linkage, sc.protection, sc.explicitProtection, sc.structalign); @@ -57,7 +62,7 @@ { if (decl) { - STC scstc = sc.stc; + StorageClass scstc = sc.stc; /* These sets of storage classes are mutually exclusive, * so choose the innermost or most recent one. @@ -70,6 +75,8 @@ scstc &= ~(STC.STCconst | STC.STCimmutable | STC.STCmanifest); if (stc & (STC.STCgshared | STC.STCshared | STC.STCtls)) scstc &= ~(STC.STCgshared | STC.STCshared | STC.STCtls); + if (stc & (STCsafe | STCtrusted | STCsystem)) + scstc &= ~(STCsafe | STCtrusted | STCsystem); scstc |= stc; semanticNewSc(sc, scstc, sc.linkage, sc.protection, sc.explicitProtection, sc.structalign); @@ -81,11 +88,11 @@ assert(false); } - static void stcToCBuffer(OutBuffer buf, int stc) + static void stcToCBuffer(OutBuffer buf, StorageClass stc) { struct SCstring { - int stc; + StorageClass stc; TOK tok; }; @@ -113,6 +120,9 @@ /// { STCref, TOKref }, /// { STCtls, TOKtls }, /// { STCgshared, TOKgshared }, +/// { STCproperty, TOKat }, +/// { STCsafe, TOKat }, +/// { STCtrusted, TOKat }, /// } ]; @@ -120,7 +130,22 @@ { if (stc & table[i].stc) { - buf.writestring(Token.toChars(table[i].tok)); + enum TOK tok = table[i].tok; + if (tok == TOKat) + { Identifier id; + + if (stc & STCproperty) + id = Id.property; + else if (stc & STCsafe) + id = Id.safe; + else if (stc & STCtrusted) + id = Id.trusted; + else + assert(0); + buf.writestring(id.toChars()); + } + else + buf.writestring(Token.toChars(tok)); buf.writeByte(' '); } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/String.d --- a/dmd/String.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/String.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.String; +import dmd.common; import dmd.Array; import core.stdc.string : strlen; diff -r 786ea1839396 -r 78bf0fe43974 dmd/StringEntry.d --- a/dmd/StringEntry.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StringEntry.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StringEntry; +import dmd.common; import dmd.StringValue; import dmd.Dchar; import dmd.Lstring; diff -r 786ea1839396 -r 78bf0fe43974 dmd/StringExp.d --- a/dmd/StringExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StringExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StringExp; +import dmd.common; import dmd.Expression; import dmd.backend.elem; import dmd.InterState; @@ -107,7 +108,7 @@ case 'd': for (u = 0; u < len;) { - p = utf_decodeChar(cast(string)string_[0..len], &u, &c); + p = utf_decodeChar((cast(char*)string_)[0..len], &u, &c); if (p !is null) { error("%s", p); @@ -131,7 +132,7 @@ case 'w': for (u = 0; u < len;) { - p = utf_decodeChar(cast(string)string_[0..len], &u, &c); + p = utf_decodeChar((cast(char*)string_)[0..len], &u, &c); if (p !is null) { error("%s", p); @@ -190,7 +191,7 @@ case 1: for (size_t u = 0; u < len;) { - p = utf_decodeChar(cast(string)string_[0..len], &u, &c); + p = utf_decodeChar((cast(char*)string_)[0..len], &u, &c); if (p) { error("%s", p); @@ -204,7 +205,7 @@ case 2: for (size_t u = 0; u < len;) { - p = utf_decodeWchar(cast(wstring)string_[0..len], &u, &c); + p = utf_decodeWchar((cast(wchar*)string_)[0..len], &u, &c); if (p) { error("%s", p); break; @@ -445,7 +446,7 @@ for (size_t u = 0; u < len;) { dchar c; - string p = utf_decodeChar(cast(string)se.string_[0..len], &u, &c); + string p = utf_decodeChar((cast(char*)se.string_)[0..len], &u, &c); if (p !is null) error("%s", p); else @@ -459,7 +460,7 @@ for (size_t u = 0; u < len;) { dchar c; - string p = utf_decodeChar(cast(string)se.string_[0..len], &u, &c); + string p = utf_decodeChar((cast(char*)se.string_)[0..len], &u, &c); if (p !is null) error("%s", p); buffer.write4(c); @@ -472,7 +473,7 @@ for (size_t u = 0; u < len;) { dchar c; - string p = utf_decodeWchar(cast(wstring)se.string_[0..len], &u, &c); + string p = utf_decodeWchar((cast(wchar*)se.string_)[0..len], &u, &c); if (p) error("%s", p); else @@ -486,7 +487,7 @@ for (size_t u = 0; u < len;) { dchar c; - string p = utf_decodeWchar(cast(wstring)se.string_[0..len], &u, &c); + string p = utf_decodeWchar((cast(wchar*)se.string_)[0..len], &u, &c); if (p) error("%s", p); buffer.write4(c); @@ -732,7 +733,7 @@ m = 'w'; for (u = 0; u < len; ) { - p = utf_decodeWchar(cast(wstring)string_[0..len], &u, &c); + p = utf_decodeWchar((cast(wchar*)string_)[0..len], &u, &c); if (p) error("%s", p); else @@ -830,13 +831,12 @@ } else if (tb.ty == TY.Tsarray) { - Symbol *si; dt_t *dt = null; toDt(&dt); dtnzeros(&dt, sz); // leave terminating 0 - si = symbol_generate(SC.SCstatic,type_allocn(TYM.TYarray, tschar)); + Symbol* si = symbol_generate(SC.SCstatic,type_allocn(TYM.TYarray, tschar)); si.Sdt = dt; si.Sfl = FL.FLdata; @@ -846,6 +846,7 @@ outdata(si); e = el_var(si); + e.Enumbytes = len * sz; } else if (tb.ty == TY.Tpointer) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/StringTable.d --- a/dmd/StringTable.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StringTable.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StringTable; +import dmd.common; import dmd.StringValue; import dmd.StringEntry; import dmd.Dchar; diff -r 786ea1839396 -r 78bf0fe43974 dmd/StringValue.d --- a/dmd/StringValue.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StringValue.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StringValue; +import dmd.common; import dmd.Lstring; import dmd.Dchar; diff -r 786ea1839396 -r 78bf0fe43974 dmd/StructDeclaration.d --- a/dmd/StructDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StructDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StructDeclaration; +import dmd.common; import dmd.AggregateDeclaration; import dmd.FuncDeclaration; import dmd.DeclarationExp; @@ -22,7 +23,7 @@ import dmd.ThisExp; import dmd.ThisDeclaration; import dmd.TypeFunction; -import dmd.Argument; +import dmd.Parameter; import dmd.Id; import dmd.TY; import dmd.LINK; @@ -52,6 +53,10 @@ import dmd.NewDeclaration; import dmd.DeleteDeclaration; import dmd.Global; +import dmd.MOD; +import dmd.IntegerExp; +import dmd.EqualExp; +import dmd.AndAndExp; import dmd.backend.dt_t; import dmd.backend.Util; @@ -60,6 +65,8 @@ import dmd.backend.FL; import dmd.backend.glue; +import std.stdio; + class StructDeclaration : AggregateDeclaration { bool zeroInit; // true if initialize with 0 fill @@ -67,6 +74,7 @@ version (DMDV2) { int hasIdentityAssign; // !=0 if has identity opAssign FuncDeclaration cpctor; // generated copy-constructor, if any + FuncDeclaration eq; // bool opEquals(ref const T), if any FuncDeclarations postblits; // Array of postblit functions FuncDeclaration postblit; // aggregate postblit @@ -98,17 +106,22 @@ { Scope sc2; - //printf("+StructDeclaration.semantic(this=%p, '%s')\n", this, toChars()); + //writef("+StructDeclaration.semantic(this=%p, '%s', sizeok = %d)\n", this, toChars(), sizeok); - //static int count; if (++count == 20) *(char*)0=0; + //static int count; if (++count == 20) halt(); assert(type); if (!members) // if forward reference return; - if (symtab) - { if (!scope_) + if (sizeok == 1 || symtab) + { + if (!scope_) + { + // writef("already completed\n"); + scope_ = null; return; // semantic() already completed + } } else symtab = new DsymbolTable(); @@ -199,28 +212,57 @@ sc2.protection = PROT.PROTpublic; sc2.explicitProtection = 0; - int members_dim = members.dim; + + /* Set scope so if there are forward references, we still might be able to + * resolve individual members like enums. + */ + foreach (s; members) + { + /* There are problems doing this in the general case because + * Scope keeps track of things like 'offset' + */ + if (s.isEnumDeclaration() || (s.isAggregateDeclaration() && s.ident)) + { + //printf("setScope %s %s\n", s->kind(), s->toChars()); + s.setScope(sc2); + } + } + foreach(Dsymbol s; members) { - s.semantic(sc2); - if (isUnionDeclaration()) - sc2.offset = 0; + s.semantic(sc2); + if (isUnionDeclaration()) + sc2.offset = 0; static if (false) { - if (sizeok == 2) - { //printf("forward reference\n"); - break; - } + if (sizeok == 2) + { //printf("forward reference\n"); + break; + } } - Type t; - if (s.isDeclaration() && - (t = s.isDeclaration().type) !is null && - t.toBasetype().ty == TY.Tstruct) - { StructDeclaration sd = cast(StructDeclaration)t.toDsymbol(sc); - if (sd.isnested) - error("inner struct %s cannot be a field", sd.toChars()); - } + if (auto d = s.isDeclaration()) + { + if (auto t = d.type) { + if (t.toBasetype().ty == TY.Tstruct) { + auto ad = t.toDsymbol(sc).isThis(); + /* + StructDeclaration sd = cast(StructDeclaration)foo; + if (foo && !sd) { + writeln(t.classin); + writeln(foo.classinfo.name); + assert(false); + } + */ + if (ad && ad.isnested) + error("inner struct %s cannot be a field", ad.toChars()); + } + } + } } +version(DMDV1) { + /* This doesn't work for DMDV2 because (ref S) and (S) parameter + * lists will overload the same. + */ /* The TypeInfo_Struct is expecting an opEquals and opCmp with * a parameter that is a pointer to the struct. But if there * isn't one, but is an opEquals or opCmp with a value, write @@ -230,22 +272,22 @@ TypeFunction tfeqptr; { - Arguments arguments = new Arguments; - Argument arg = new Argument(STC.STCin, handle, Id.p, null); + auto arguments = new Parameters; + auto arg = new Parameter(STC.STCin, handle, Id.p, null); - arguments.push(cast(void*)arg); - tfeqptr = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); - tfeqptr = cast(TypeFunction)tfeqptr.semantic(Loc(0), sc); + arguments.push(arg); + tfeqptr = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); + tfeqptr = cast(TypeFunction)tfeqptr.semantic(Loc(0), sc); } TypeFunction tfeq; { - Arguments arguments = new Arguments; - Argument arg = new Argument(STC.STCin, type, null, null); + auto arguments = new Parameters; + auto arg = new Parameter(STC.STCin, type, null, null); - arguments.push(cast(void*)arg); - tfeq = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); - tfeq = cast(TypeFunction)tfeq.semantic(Loc(0), sc); + arguments.push(arg); + tfeq = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); + tfeq = cast(TypeFunction)tfeq.semantic(Loc(0), sc); } Identifier id = Id.eq; @@ -278,7 +320,39 @@ id = Id.cmp; } +} version (DMDV2) { + /* Try to find the opEquals function. Build it if necessary. + */ + TypeFunction tfeqptr; + { // bool opEquals(const T*) const; + auto parameters = new Parameters; +version(STRUCTTHISREF) { + // bool opEquals(ref const T) const; + auto param = new Parameter(STC.STCref, type.constOf(), null, null); +} else { + // bool opEquals(const T*) const; + auto param = new Parameter(STC.STCin, type.pointerTo(), null, null); +} + + parameters.push(param); + tfeqptr = new TypeFunction(parameters, Type.tbool, 0, LINK.LINKd); + tfeqptr.mod = MOD.MODconst; + tfeqptr = cast(TypeFunction)(tfeqptr.semantic(Loc(0), sc2)); + + Dsymbol s = search_function(this, Id.eq); + FuncDeclaration fdx = s ? s.isFuncDeclaration() : null; + if (fdx) + { + eq = fdx.overloadExactMatch(tfeqptr); + if (!eq) + fdx.error("type signature should be %s not %s", tfeqptr.toChars(), fdx.type.toChars()); + } + + if (!eq) + eq = buildOpEquals(sc2); + } + dtor = buildDtor(sc2); postblit = buildPostBlit(sc2); cpctor = buildCpCtor(sc2); @@ -298,7 +372,7 @@ scope_ = scx ? scx : sc.clone(); scope_.setNoFree(); scope_.module_.addDeferredSemantic(this); - //printf("\tdeferring %s\n", toChars()); + writef("\tdeferring %s\n", toChars()); return; } @@ -358,6 +432,22 @@ } } + Dsymbol search(Loc loc, Identifier ident, int flags) + { + //printf("%s.StructDeclaration::search('%s')\n", toChars(), ident->toChars()); + + if (scope_) + semantic(scope_); + + if (!members || !symtab) + { + error("is forward referenced when looking for '%s'", ident.toChars()); + return null; + } + + return ScopeDsymbol.search(loc, ident, flags); + } + override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { assert(false); @@ -373,7 +463,17 @@ { assert(false); } - + +version(DMDV1) +{ + Expression cloneMembers() + { + assert(false); + } +} + +version(DMDV2) +{ /******************************************* * We need an opAssign for the struct if * it has a destructor or a postblit. @@ -423,6 +523,46 @@ return true; } + /******************************************* + * We need an opEquals for the struct if + * any fields has an opEquals. + * Generate one if a user-specified one does not exist. + */ + bool needOpEquals() + { + enum X = 0; +static if (X) printf("StructDeclaration::needOpEquals() %s\n", toChars()); + + /* If any of the fields has an opEquals, then we + * need it too. + */ + foreach (s; fields) + { + VarDeclaration v = s.isVarDeclaration(); + assert(v && v.storage_class & STC.STCfield); + if (v.storage_class & STC.STCref) + continue; + Type tv = v.type.toBasetype(); + while (tv.ty == Tsarray) + { auto ta = cast(TypeSArray)tv; + tv = tv.nextOf().toBasetype(); + } + if (tv.ty == Tstruct) + { auto ts = cast(TypeStruct)tv; + StructDeclaration sd = ts.sym; + if (sd.eq) + goto Lneed; + } + } + Ldontneed: +static if (X) printf("\tdontneed\n"); + return false; + + Lneed: +static if (X) printf("\tneed\n"); + return true; + } + /****************************************** * Build opAssign for struct. * S* opAssign(S s) { ... } @@ -436,9 +576,9 @@ FuncDeclaration fop = null; - Argument param = new Argument(STC.STCnodtor, type, Id.p, null); - Arguments fparams = new Arguments; - fparams.push(cast(void*)param); + auto param = new Parameter(STC.STCnodtor, type, Id.p, null); + auto fparams = new Parameters; + fparams.push(param); Type ftype = new TypeFunction(fparams, handle, false, LINK.LINKd); version (STRUCTTHISREF) { (cast(TypeFunction)ftype).isref = 1; @@ -530,6 +670,72 @@ return fop; } + /****************************************** + * Build opEquals for struct. + * const bool opEquals(const ref S s) { ... } + */ + FuncDeclaration buildOpEquals(Scope sc) + { + if (!needOpEquals()) + return null; + //printf("StructDeclaration::buildOpEquals() %s\n", toChars()); + Loc loc = this.loc; + + auto parameters = new Parameters; +version (STRUCTTHISREF) { + // bool opEquals(ref const T) const; + auto param = new Parameter(STC.STCref, type.constOf(), Id.p, null); +} else { + // bool opEquals(const T*) const; + auto param = new Parameter(STC.STCin, type.pointerTo(), Id.p, null); +} + + parameters.push(param); + auto ftype = new TypeFunction(parameters, Type.tbool, 0, LINKd); + ftype.mod = MOD.MODconst; + ftype = cast(TypeFunction)ftype.semantic(loc, sc); + + auto fop = new FuncDeclaration(loc, Loc(0), Id.eq, STC.STCundefined, ftype); + + Expression e = null; + /* Do memberwise compare + */ + //printf("\tmemberwise compare\n"); + foreach (s; fields) + { + VarDeclaration v = s.isVarDeclaration(); + assert(v && v.storage_class & STC.STCfield); + if (v.storage_class & STC.STCref) + assert(0); // what should we do with this? + // this.v == s.v; + auto ec = new EqualExp(TOKequal, loc, + new DotVarExp(loc, new ThisExp(loc), v, 0), + new DotVarExp(loc, new IdentifierExp(loc, Id.p), v, 0)); + if (e) + e = new AndAndExp(loc, e, ec); + else + e = ec; + } + if (!e) + e = new IntegerExp(loc, 1, Type.tbool); + fop.fbody = new ReturnStatement(loc, e); + + members.push(fop); + fop.addMember(sc, this, 1); + + sc = sc.push(); + sc.stc = STCundefined; + sc.linkage = LINK.LINKd; + + fop.semantic(sc); + + sc.pop(); + + //printf("-StructDeclaration::buildOpEquals() %s\n", toChars()); + + return fop; + } + /***************************************** * Create inclusive postblit for struct by aggregating * all the postblits in postblits[] with the postblits for @@ -649,46 +855,46 @@ */ if (postblit) { - //printf("generating cpctor\n"); + //printf("generating cpctor\n"); - Argument param = new Argument(STC.STCref, type, Id.p, null); - Arguments fparams = new Arguments; - fparams.push(cast(void*)param); - Type ftype = new TypeFunction(fparams, Type.tvoid, false, LINK.LINKd); + auto param = new Parameter(STC.STCref, type, Id.p, null); + auto fparams = new Parameters; + fparams.push(param); + Type ftype = new TypeFunction(fparams, Type.tvoid, false, LINK.LINKd); - fcp = new FuncDeclaration(Loc(0), Loc(0), Id.cpctor, STC.STCundefined, ftype); + fcp = new FuncDeclaration(Loc(0), Loc(0), Id.cpctor, STC.STCundefined, ftype); - // Build *this = p; - Expression e = new ThisExp(Loc(0)); + // Build *this = p; + Expression e = new ThisExp(Loc(0)); version (STRUCTTHISREF) { } else { - e = new PtrExp(Loc(0), e); + e = new PtrExp(Loc(0), e); } - AssignExp ea = new AssignExp(Loc(0), e, new IdentifierExp(Loc(0), Id.p)); - ea.op = TOK.TOKblit; - Statement s = new ExpStatement(Loc(0), ea); + AssignExp ea = new AssignExp(Loc(0), e, new IdentifierExp(Loc(0), Id.p)); + ea.op = TOK.TOKblit; + Statement s = new ExpStatement(Loc(0), ea); - // Build postBlit(); - e = new VarExp(Loc(0), postblit, 0); - e = new CallExp(Loc(0), e); + // Build postBlit(); + e = new VarExp(Loc(0), postblit, 0); + e = new CallExp(Loc(0), e); - s = new CompoundStatement(Loc(0), s, new ExpStatement(Loc(0), e)); - fcp.fbody = s; + s = new CompoundStatement(Loc(0), s, new ExpStatement(Loc(0), e)); + fcp.fbody = s; - members.push(fcp); + members.push(fcp); - sc = sc.push(); - sc.stc = STC.STCundefined; - sc.linkage = LINK.LINKd; + sc = sc.push(); + sc.stc = STC.STCundefined; + sc.linkage = LINK.LINKd; - fcp.semantic(sc); + fcp.semantic(sc); - sc.pop(); + sc.pop(); } return fcp; } - +} override void toDocBuffer(OutBuffer buf) { assert(false); diff -r 786ea1839396 -r 78bf0fe43974 dmd/StructInitializer.d --- a/dmd/StructInitializer.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StructInitializer.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.StructInitializer; +import dmd.common; import dmd.Initializer; import dmd.TOK; import dmd.TypeSArray; @@ -35,7 +36,7 @@ Identifiers field; // of Identifier *'s Initializers value; // parallel array of Initializer *'s - Array vars; // parallel array of VarDeclaration *'s + VarDeclarations vars; // parallel array of VarDeclaration *'s AggregateDeclaration ad; // which aggregate this is for this(Loc loc) @@ -46,23 +47,23 @@ field = new Identifiers(); value = new Initializers(); - vars = new Array(); + vars = new VarDeclarations(); } override Initializer syntaxCopy() { - StructInitializer ai = new StructInitializer(loc); + auto ai = new StructInitializer(loc); assert(field.dim == value.dim); ai.field.setDim(field.dim); ai.value.setDim(value.dim); for (int i = 0; i < field.dim; i++) { - ai.field.data[i] = field.data[i]; + ai.field[i] = field[i]; - Initializer init = cast(Initializer)value.data[i]; + auto init = value[i]; init = init.syntaxCopy(); - ai.value.data[i] = cast(void*)init; + ai.value[i] = init; } return ai; @@ -71,13 +72,12 @@ void addInit(Identifier field, Initializer value) { //printf("StructInitializer.addInit(field = %p, value = %p)\n", field, value); - this.field.push(cast(void*)field); - this.value.push(cast(void*)value); + this.field.push(field); + this.value.push(value); } override Initializer semantic(Scope sc, Type t) { - TypeStruct ts; int errors = 0; //printf("StructInitializer.semantic(t = %s) %s\n", t.toChars(), toChars()); @@ -85,15 +85,17 @@ t = t.toBasetype(); if (t.ty == Tstruct) { - uint i; uint fieldi = 0; - ts = cast(TypeStruct)t; + auto ts = cast(TypeStruct)t; ad = ts.sym; - for (i = 0; i < field.dim; i++) + if (ad.ctor) + error("%s %s has constructors, cannot use { initializers }, use %s( initializers ) instead", + ad.kind(), ad.toChars(), ad.toChars()); + for (size_t i = 0; i < field.dim; i++) { - Identifier id = cast(Identifier)field.data[i]; - Initializer val = cast(Initializer)value.data[i]; + Identifier id = field[i]; + Initializer val = value[i]; Dsymbol s; VarDeclaration v; @@ -136,8 +138,8 @@ if (s && (v = s.isVarDeclaration()) !is null) { val = val.semantic(sc, v.type); - value.data[i] = cast(void*)val; - vars.data[i] = cast(void*)v; + value[i] = val; + vars[i] = v; } else { @@ -151,7 +153,7 @@ { /* Rewrite as empty delegate literal { } */ - Arguments arguments = new Arguments; + auto arguments = new Parameters; Type tf = new TypeFunction(arguments, null, 0, LINK.LINKd); FuncLiteralDeclaration fd = new FuncLiteralDeclaration(loc, Loc(0), tf, TOK.TOKdelegate, null); fd.fbody = new CompoundStatement(loc, new Statements()); @@ -194,9 +196,9 @@ Expressions elements = new Expressions(); for (size_t i = 0; i < value.dim; i++) { - if (field.data[i]) + if (field[i]) goto Lno; - Initializer iz = cast(Initializer)value.data[i]; + Initializer iz = value[i]; if (!iz) goto Lno; Expression ex = iz.toExpression(); @@ -221,7 +223,7 @@ override dt_t* toDt() { - scope Array dts = new Array(); + scope dts = new Vector!(dt_t*); uint i; uint j; dt_t* dt; @@ -235,8 +237,8 @@ for (i = 0; i < vars.dim; i++) { - VarDeclaration v = cast(VarDeclaration)vars.data[i]; - Initializer val = cast(Initializer)value.data[i]; + VarDeclaration v = vars[i]; + Initializer val = value[i]; //printf("vars[%d] = %s\n", i, v.toChars()); @@ -246,9 +248,9 @@ //printf(" adfield[%d] = %s\n", j, ((VarDeclaration *)ad.fields[j]).toChars()); if (cast(VarDeclaration)ad.fields[j] == v) // TODO: check if 'is' needs to be used here { - if (dts.data[j]) + if (dts[j]) error(loc, "field %s of %s already initialized", v.toChars(), ad.toChars()); - dts.data[j] = cast(void*)val.toDt(); + dts[j] = val.toDt(); break; } } @@ -259,9 +261,9 @@ offset = 0; for (j = 0; j < dts.dim; j++) { - VarDeclaration v = cast(VarDeclaration)ad.fields[j]; + VarDeclaration v = ad.fields[j]; - d = cast(dt_t*)dts.data[j]; + d = dts[j]; if (!d) { // An instance specific initializer was not provided. @@ -284,9 +286,9 @@ v.type.toDt(&d); break; } - VarDeclaration v2 = cast(VarDeclaration)ad.fields[k]; + VarDeclaration v2 = ad.fields[k]; - if (v2.offset < offset2 && dts.data[k]) + if (v2.offset < offset2 && dts[k]) break; // overlap } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/StructLiteralExp.d --- a/dmd/StructLiteralExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/StructLiteralExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,11 +1,14 @@ module dmd.StructLiteralExp; +import dmd.common; import dmd.Expression; +import dmd.GlobalExpressions; import dmd.MOD; import dmd.TypeStruct; import dmd.TypeSArray; import dmd.expression.Util; import dmd.ErrorExp; +import dmd.Array; import dmd.Dsymbol; import dmd.VarDeclaration; import dmd.StructDeclaration; @@ -20,6 +23,7 @@ import dmd.OutBuffer; import dmd.Loc; import dmd.Scope; +import dmd.Initializer; import dmd.InlineCostState; import dmd.IRState; import dmd.InlineDoState; @@ -61,7 +65,7 @@ override Expression syntaxCopy() { - assert(false); + return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements)); } override Expression semantic(Scope sc) @@ -138,12 +142,22 @@ { e = v.init.toExpression(); if (!e) + { error("cannot make expression out of initializer for %s", v.toChars()); + e = new ErrorExp(); + } + else if (v.scope_) + { + // Do deferred semantic anaylsis + Initializer i2 = v.init.syntaxCopy(); + i2 = i2.semantic(v.scope_, v.type); + e = i2.toExpression(); + v.scope_ = null; + } } else { - e = v.type.defaultInit(Loc(0)); - e.loc = loc; + e = v.type.defaultInitLiteral(loc); } offset = v.offset + cast(uint)v.type.size(); } @@ -154,6 +168,10 @@ return this; } + /************************************** + * Gets expression at offset of type. + * Returns null if not found. + */ Expression getField(Type type, uint offset) { //printf("StructLiteralExp.getField(this = %s, type = %s, offset = %u)\n", @@ -442,12 +460,163 @@ override Expression interpret(InterState istate) { - assert(false); + Expressions expsx = null; + +version (LOG) { + printf("StructLiteralExp.interpret() %.*s\n", toChars()); +} + /* We don't know how to deal with overlapping fields + */ + if (sd.hasUnions) + { + error("Unions with overlapping fields are not yet supported in CTFE"); + return EXP_CANT_INTERPRET; + } + + if (elements) + { + foreach (size_t i, Expression e; elements) + { + if (!e) + continue; + + Expression ex = e.interpret(istate); + if (ex is EXP_CANT_INTERPRET) + { + delete expsx; + return EXP_CANT_INTERPRET; + } + + /* If any changes, do Copy On Write + */ + if (ex != e) + { + if (!expsx) + { + expsx = new Expressions(); + expsx.setDim(elements.dim); + for (size_t j = 0; j < elements.dim; j++) + { + expsx[j] = elements[j]; + } + } + expsx[i] = ex; + } + } + } + if (elements && expsx) + { + expandTuples(expsx); + if (expsx.dim != elements.dim) + { + delete expsx; + return EXP_CANT_INTERPRET; + } + StructLiteralExp se = new StructLiteralExp(loc, sd, expsx); + se.type = type; + return se; + } + return this; } override dt_t** toDt(dt_t** pdt) { - assert(false); + Array dts; + dt_t *dt; + dt_t *d; + uint offset; + + //printf("StructLiteralExp.toDt() %s)\n", toChars()); + dts.setDim(sd.fields.dim); + dts.zero(); + assert(elements.dim <= sd.fields.dim); + + foreach (uint i, Expression e; elements) + { + if (!e) + continue; + + dt = null; + e.toDt(&dt); + dts.data[i] = dt; + } + + offset = 0; + foreach (uint j, VarDeclaration v; sd.fields) + { + d = cast(dt_t*)dts.data[j]; + if (!d) + { // An instance specific initializer was not provided. + // Look to see if there's a default initializer from the + // struct definition + if (v.init) + { + d = v.init.toDt(); + } + else if (v.offset >= offset) + { + uint k; + uint offset2 = v.offset + cast(uint)v.type.size(); + // Make sure this field (v) does not overlap any explicitly + // initialized field. + for (k = j + 1; 1; k++) + { + if (k == dts.dim) // didn't find any overlap + { + v.type.toDt(&d); + break; + } + VarDeclaration v2 = sd.fields[k]; + + if (v2.offset < offset2 && dts.data[k]) + break; // overlap + } + } + } + if (d) + { + if (v.offset < offset) + error("duplicate union initialization for %s", v.toChars()); + else + { + uint sz = dt_size(d); + uint vsz = cast(uint)v.type.size(); + uint voffset = v.offset; + assert(sz <= vsz); + + uint dim = 1; + for (Type vt = v.type.toBasetype(); vt.ty == Tsarray; vt = vt.nextOf().toBasetype()) + { + TypeSArray tsa = cast(TypeSArray)vt; + dim *= tsa.dim.toInteger(); + } + + for (size_t i = 0; i < dim; i++) + { + if (offset < voffset) + pdt = dtnzeros(pdt, voffset - offset); + if (!d) + { + if (v.init) + d = v.init.toDt(); + else + v.type.toDt(&d); + } + pdt = dtcat(pdt, d); + d = null; + offset = voffset + sz; + voffset += vsz / dim; + if (sz == vsz) + break; + } + } + } + } + + if (offset < sd.structsize) + pdt = dtnzeros(pdt, sd.structsize - offset); + + return pdt; } version(DMDV2) @@ -490,7 +659,7 @@ te = te.mutableOf(); else { - assert(t.mod == MODinvariant); + assert(t.mod == MODimmutable); te = te.invariantOf(); } MATCH m2 = e.implicitConvTo(te); diff -r 786ea1839396 -r 78bf0fe43974 dmd/SuperExp.d --- a/dmd/SuperExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/SuperExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.SuperExp; +import dmd.common; import dmd.Expression; import dmd.OutBuffer; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/SwitchErrorStatement.d --- a/dmd/SwitchErrorStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/SwitchErrorStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.SwitchErrorStatement; +import dmd.common; import dmd.Statement; import dmd.OutBuffer; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/SwitchStatement.d --- a/dmd/SwitchStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/SwitchStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.SwitchStatement; +import dmd.common; import dmd.Statement; import dmd.Expression; import dmd.DefaultStatement; @@ -166,10 +167,10 @@ } a.reserve(4); - a.push(cast(void*)body_); - a.push(cast(void*)new BreakStatement(loc, null)); + a.push(body_); + a.push(new BreakStatement(loc, null)); sc.sw.sdefault = new DefaultStatement(loc, s); - a.push(cast(void*)sc.sw.sdefault); + a.push(sc.sw.sdefault); cs = new CompoundStatement(loc, a); body_ = cs; } @@ -411,7 +412,7 @@ block_appendexp(mystate.switchBlock, econd); block_next(blx,BCswitch,null); - /// + // Corresponding free is in block_free targ_llong* pu = cast(targ_llong*) malloc(targ_llong.sizeof * (numcases + 1)); mystate.switchBlock.Bswitch = pu; /* First pair is the number of cases, and the default block diff -r 786ea1839396 -r 78bf0fe43974 dmd/SymOffExp.d --- a/dmd/SymOffExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/SymOffExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.SymOffExp; +import dmd.common; import dmd.Expression; import dmd.Declaration; import dmd.MATCH; @@ -19,6 +20,7 @@ import dmd.ErrorExp; import dmd.TY; import dmd.TOK; +import dmd.STC; import dmd.backend.Symbol; import dmd.backend.Util; @@ -57,8 +59,15 @@ VarDeclaration v = var.isVarDeclaration(); if (v) { - if (!v.isDataseg()) - error("escaping reference to local variable %s", v.toChars()); + if (!v.isDataseg() && !(v.storage_class & (STC.STCref | STC.STCout))) + { /* BUG: This should be allowed: + * void foo() + * { int a; + * int* bar() { return &a; } + * } + */ + error("escaping reference to local %s", v.toChars()); + } } } @@ -74,7 +83,7 @@ override bool isBool(bool result) { - assert(false); + return result; } override Expression doInline(InlineDoState ids) @@ -229,5 +238,13 @@ Symbol* s = var.toSymbol(); return dtxoff(pdt, s, offset, TYnptr); } + +static if (false) +{ + override elem* toElem(IRState* irs) + { + assert(false); // this function is #if 0'ed out in dmd + } +} } diff -r 786ea1839396 -r 78bf0fe43974 dmd/SymbolDeclaration.d --- a/dmd/SymbolDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/SymbolDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.SymbolDeclaration; +import dmd.common; import dmd.Declaration; import dmd.StructDeclaration; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/SymbolExp.d --- a/dmd/SymbolExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/SymbolExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.SymbolExp; +import dmd.common; import dmd.Expression; import dmd.Declaration; import dmd.Loc; @@ -19,6 +20,7 @@ import dmd.backend.Util; import dmd.codegen.Util; +version(DMDV2) class SymbolExp : Expression { Declaration var; @@ -97,7 +99,7 @@ if (op == TOK.TOKvar) e = el_una(OPER.OPind, TYM.TYnptr, e); - if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef()) + if (ISREF(var, tb)) e = el_una(OPER.OPind, s.ty(), e); else if (op == TOK.TOKsymoff && nrvo) { @@ -122,7 +124,7 @@ e.Enumbytes = cast(uint)type.size(); el_setLoc(e, loc); } - if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef()) + if (ISREF(var, tb)) { e.Ety = TYM.TYnptr; e = el_una(OPER.OPind, s.ty(), e); @@ -150,7 +152,7 @@ e = el_var(var.toImport()); e = el_una(OPER.OPind,s.ty(),e); } - else if ((var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef()) + else if (ISREF(var, tb)) { // Static arrays are really passed as pointers to the array // Out parameters are really references diff -r 786ea1839396 -r 78bf0fe43974 dmd/SynchronizedStatement.d --- a/dmd/SynchronizedStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/SynchronizedStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.SynchronizedStatement; +import dmd.common; import dmd.Statement; import dmd.IntegerExp; import dmd.TypeSArray; @@ -87,19 +88,19 @@ VarDeclaration tmp = new VarDeclaration(loc, exp.type, id, ie); Statements cs = new Statements(); - cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs.push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); FuncDeclaration fdenter = FuncDeclaration.genCfunc(Type.tvoid, Id.monitorenter); Expression e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp)); e.type = Type.tvoid; // do not run semantic on e - cs.push(cast(void*)new ExpStatement(loc, e)); + cs.push(new ExpStatement(loc, e)); FuncDeclaration fdexit = FuncDeclaration.genCfunc(Type.tvoid, Id.monitorexit); e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp)); e.type = Type.tvoid; // do not run semantic on e Statement s = new ExpStatement(loc, e); s = new TryFinallyStatement(loc, body_, s); - cs.push(cast(void*)s); + cs.push(s); s = new CompoundStatement(loc, cs); return s.semantic(sc); @@ -119,14 +120,14 @@ tmp.storage_class |= STCgshared | STCstatic; Statements cs = new Statements(); - cs.push(cast(void*)new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); + cs.push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp))); FuncDeclaration fdenter = FuncDeclaration.genCfunc(Type.tvoid, Id.criticalenter); Expression e = new DotIdExp(loc, new VarExp(loc, tmp), Id.ptr); e = e.semantic(sc); e = new CallExp(loc, new VarExp(loc, fdenter), e); e.type = Type.tvoid; // do not run semantic on e - cs.push(cast(void*)new ExpStatement(loc, e)); + cs.push(new ExpStatement(loc, e)); FuncDeclaration fdexit = FuncDeclaration.genCfunc(Type.tvoid, Id.criticalexit); e = new DotIdExp(loc, new VarExp(loc, tmp), Id.ptr); @@ -135,7 +136,7 @@ e.type = Type.tvoid; // do not run semantic on e Statement s = new ExpStatement(loc, e); s = new TryFinallyStatement(loc, body_, s); - cs.push(cast(void*)s); + cs.push(s); s = new CompoundStatement(loc, cs); return s.semantic(sc); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TOK.d --- a/dmd/TOK.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TOK.d Tue Sep 14 15:46:50 2010 +0200 @@ -126,6 +126,8 @@ TOKfile, TOKshared, TOKat, + TOKpow, + TOKpowass, TOKMAX } @@ -249,5 +251,7 @@ } } +alias TOK.TOKinout TOKwild; + import dmd.EnumUtils; mixin(BringToCurrentScope!(TOK)); \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/TRUST.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/TRUST.d Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,12 @@ +module dmd.TRUST; + +enum TRUST +{ + TRUSTdefault = 0, + TRUSTsystem = 1, // @system (same as TRUSTdefault) + TRUSTtrusted = 2, // @trusted + TRUSTsafe = 3, // @safe +}; + +import dmd.EnumUtils; +mixin(BringToCurrentScope!(TRUST)); \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/TemplateAliasParameter.d --- a/dmd/TemplateAliasParameter.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TemplateAliasParameter.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TemplateAliasParameter; +import dmd.common; import dmd.TemplateParameter; import dmd.Loc; import dmd.Identifier; @@ -110,7 +111,7 @@ Dsymbol sa = isDsymbol(oded); assert(sa); - printf("\tArgument alias: %s\n", sa.toChars()); + printf("Parameter alias: %s\n", sa.toChars()); } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) @@ -171,14 +172,14 @@ //printf("TemplateAliasParameter.matchArg()\n"); if (i < tiargs.dim) - oarg = cast(Object)tiargs.data[i]; + oarg = tiargs[i]; else { // Get default argument instead oarg = defaultArg(loc, sc); if (!oarg) { assert(i < dedtypes.dim); // It might have already been deduced - oarg = cast(Object)dedtypes.data[i]; + oarg = dedtypes[i]; if (!oarg) goto Lnomatch; } @@ -219,14 +220,14 @@ if (sa != specAlias) goto Lnomatch; } - else if (dedtypes.data[i]) + else if (dedtypes[i]) { // Must match already deduced symbol - Object s_ = cast(Object)dedtypes.data[i]; + Object s_ = dedtypes[i]; if (!sa || s_ != sa) goto Lnomatch; } - dedtypes.data[i] = cast(void*)sa; + dedtypes[i] = sa; s = isDsymbol(sa); if (s) @@ -250,7 +251,7 @@ return MATCHnomatch; } - override void* dummyArg() + override Object dummyArg() { Object s; @@ -261,6 +262,6 @@ sdummy = new Dsymbol(); s = sdummy; } - return cast(void*)s; + return s; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TemplateDeclaration.d --- a/dmd/TemplateDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TemplateDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TemplateDeclaration; +import dmd.common; import dmd.Loc; import dmd.ScopeDsymbol; import dmd.ArrayTypes; @@ -18,7 +19,7 @@ import dmd.TypeSArray; import dmd.StringExp; import dmd.TOK; -import dmd.Argument; +import dmd.Parameter; import dmd.CtorDeclaration; import dmd.TypeFunction; import dmd.TY; @@ -41,6 +42,7 @@ import dmd.VarDeclaration; import dmd.TemplateParameter; import dmd.TemplateTypeParameter; +import dmd.MOD; import dmd.expression.Util; @@ -53,73 +55,73 @@ TemplateTupleParameter isVariadic(TemplateParameters parameters) { size_t dim = parameters.dim; - TemplateTupleParameter tp = null; + TemplateTupleParameter tp = null; - if (dim) - tp = (cast(TemplateParameter)parameters.data[dim - 1]).isTemplateTupleParameter(); + if (dim) + tp = parameters[dim - 1].isTemplateTupleParameter(); - return tp; + return tp; } void ObjectToCBuffer(OutBuffer buf, HdrGenState* hgs, Object oarg) { - //printf("ObjectToCBuffer()\n"); - Type t = isType(oarg); - Expression e = isExpression(oarg); - Dsymbol s = isDsymbol(oarg); - Tuple v = isTuple(oarg); - if (t) - { + //printf("ObjectToCBuffer()\n"); + Type t = isType(oarg); + Expression e = isExpression(oarg); + Dsymbol s = isDsymbol(oarg); + Tuple v = isTuple(oarg); + if (t) + { //printf("\tt: %s ty = %d\n", t.toChars(), t.ty); t.toCBuffer(buf, null, hgs); - } - else if (e) + } + else if (e) e.toCBuffer(buf, hgs); - else if (s) - { + else if (s) + { string p = s.ident ? s.ident.toChars() : s.toChars(); buf.writestring(p); - } - else if (v) - { + } + else if (v) + { Objects args = v.objects; for (size_t i = 0; i < args.dim; i++) { if (i) buf.writeByte(','); - Object o = cast(Object)args.data[i]; + Object o = args[i]; ObjectToCBuffer(buf, hgs, o); } - } - else if (!oarg) - { + } + else if (!oarg) + { buf.writestring("null"); - } - else - { + } + else + { debug writef("bad Object = %p\n", oarg); assert(0); - } + } } class TemplateDeclaration : ScopeDsymbol { - TemplateParameters parameters; // array of TemplateParameter's + TemplateParameters parameters; // array of TemplateParameter's - TemplateParameters origParameters; // originals for Ddoc - Expression constraint; - Array instances; // array of TemplateInstance's + TemplateParameters origParameters; // originals for Ddoc + Expression constraint; + Vector!TemplateInstance instances; // array of TemplateInstance's - TemplateDeclaration overnext; // next overloaded TemplateDeclaration - TemplateDeclaration overroot; // first in overnext list + TemplateDeclaration overnext; // next overloaded TemplateDeclaration + TemplateDeclaration overroot; // first in overnext list - int semanticRun; // 1 semantic() run + int semanticRun; // 1 semantic() run - Dsymbol onemember; // if !=NULL then one member of this template + Dsymbol onemember; // if !=NULL then one member of this template - int literal; // this template declaration is a literal + int literal; // this template declaration is a literal - this(Loc loc, Identifier id, TemplateParameters parameters, Expression constraint, Dsymbols decldefs) + this(Loc loc, Identifier id, TemplateParameters parameters, Expression constraint, Dsymbols decldefs) { super(id); @@ -147,10 +149,10 @@ this.constraint = constraint; this.members = decldefs; - instances = new Array(); + instances = new Vector!TemplateInstance(); } - override Dsymbol syntaxCopy(Dsymbol) + override Dsymbol syntaxCopy(Dsymbol) { //printf("TemplateDeclaration.syntaxCopy()\n"); TemplateDeclaration td; @@ -164,8 +166,8 @@ p.setDim(parameters.dim); for (int i = 0; i < p.dim; i++) { - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; - p.data[i] = cast(void*)tp.syntaxCopy(); + auto tp = parameters[i]; + p[i] = tp.syntaxCopy(); } } @@ -177,7 +179,7 @@ return td; } - override void semantic(Scope sc) + override void semantic(Scope sc) { version (LOG) { printf("TemplateDeclaration.semantic(this = %p, id = '%s')\n", this, ident.toChars()); @@ -227,23 +229,19 @@ { origParameters = new TemplateParameters(); origParameters.setDim(parameters.dim); - for (int i = 0; i < parameters.dim; i++) + foreach (size_t i, TemplateParameter tp; parameters) { - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; - origParameters.data[i] = cast(void*)tp.syntaxCopy(); + origParameters[i] = tp.syntaxCopy(); } } - for (int i = 0; i < parameters.dim; i++) + foreach (tp; parameters) { - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; tp.declareParameter(paramscope); } - for (int i = 0; i < parameters.dim; i++) + foreach (size_t i, TemplateParameter tp; parameters) { - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; - tp.semantic(paramscope); if (i + 1 != parameters.dim && tp.isTemplateTupleParameter()) error("template tuple parameter must be last one"); @@ -273,7 +271,7 @@ * Overload existing TemplateDeclaration 'this' with the new one 's'. * Return !=0 if successful; i.e. no conflict. */ - override bool overloadInsert(Dsymbol s) + override bool overloadInsert(Dsymbol s) { TemplateDeclaration *pf; TemplateDeclaration f; @@ -323,9 +321,48 @@ return true; } - override void toCBuffer(OutBuffer buf, HdrGenState* hgs) + override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); +static if (false) // Should handle template functions +{ + if (onemember && onemember.isFuncDeclaration()) + buf.writestring("foo "); +} + buf.writestring(kind()); + buf.writeByte(' '); + buf.writestring(ident.toChars()); + buf.writeByte('('); + foreach (size_t i, TemplateParameter tp; parameters) + { + if (hgs.ddoc) + tp = origParameters[i]; + if (i) + buf.writeByte(','); + tp.toCBuffer(buf, hgs); + } + buf.writeByte(')'); +version(DMDV2) +{ + if (constraint) + { buf.writestring(" if ("); + constraint.toCBuffer(buf, hgs); + buf.writeByte(')'); + } +} + + if (hgs.hdrgen) + { + hgs.tpltMember++; + buf.writenl(); + buf.writebyte('{'); + buf.writenl(); + foreach (Dsymbol s; members) + s.toCBuffer(buf, hgs); + + buf.writebyte('}'); + buf.writenl(); + hgs.tpltMember--; + } } override void toJsonBuffer(OutBuffer buf) @@ -359,14 +396,14 @@ buf.writestring("}\n"); } - override string kind() + override string kind() { return (onemember && onemember.isAggregateDeclaration()) ? onemember.kind() : "template"; } - override string toChars() + override string toChars() { OutBuffer buf = new OutBuffer(); HdrGenState hgs; @@ -374,9 +411,8 @@ /// memset(&hgs, 0, hgs.sizeof); buf.writestring(ident.toChars()); buf.writeByte('('); - for (int i = 0; i < parameters.dim; i++) + foreach (size_t i, TemplateParameter tp; parameters) { - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; if (i) buf.writeByte(','); tp.toCBuffer(buf, &hgs); @@ -394,12 +430,12 @@ return buf.extractString(); } - override void emitComment(Scope sc) + override void emitComment(Scope sc) { assert(false); } -// void toDocBuffer(OutBuffer *buf); +// void toDocBuffer(OutBuffer *buf); /*************************************** * Given that ti is an instance of this TemplateDeclaration, @@ -412,7 +448,7 @@ * dedtypes deduced arguments * Return match level. */ - MATCH matchWithInstance(TemplateInstance ti, Objects dedtypes, int flag) + MATCH matchWithInstance(TemplateInstance ti, Objects dedtypes, int flag) { MATCH m; int dedtypes_dim = dedtypes.dim; @@ -455,7 +491,7 @@ for (int i = 0; i < dedtypes_dim; i++) { MATCH m2; - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; + auto tp = parameters[i]; Declaration sparam; //printf("\targument [%d]\n", i); @@ -497,10 +533,10 @@ */ for (int i = 0; i < dedtypes_dim; i++) { - if (!dedtypes.data[i]) + if (!dedtypes[i]) { assert(i < ti.tiargs.dim); - dedtypes.data[i] = ti.tiargs.data[i]; + dedtypes[i] = ti.tiargs[i]; } } } @@ -509,6 +545,7 @@ if (m && constraint && !(flag & 1)) { /* Check to see if constraint is satisfied. */ + makeParamNamesVisibleInConstraint(paramscope); Expression e = constraint.syntaxCopy(); paramscope.flags |= SCOPE.SCOPEstaticif; e = e.semantic(paramscope); @@ -574,9 +611,9 @@ * match this is at least as specialized as td2 * 0 td2 is more specialized than this */ - MATCH leastAsSpecialized(TemplateDeclaration td2) + MATCH leastAsSpecialized(TemplateDeclaration td2) { - /* This works by taking the template parameters to this template + /* This works by taking the template parameters to this template * declaration and feeding them to td2 as if it were a template * instance. * If it works, then this template is at least as specialized @@ -596,11 +633,11 @@ ti.tiargs.setDim(parameters.dim); for (int i = 0; i < ti.tiargs.dim; i++) { - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; + auto tp = parameters[i]; - void* p = tp.dummyArg(); + auto p = tp.dummyArg(); if (p) - ti.tiargs.data[i] = p; + ti.tiargs[i] = p; else ti.tiargs.setDim(i); } @@ -643,7 +680,7 @@ * Returns: * match level */ - MATCH deduceFunctionTemplateMatch(Loc loc, Objects targsi, Expression ethis, Expressions fargs, Objects dedargs) + MATCH deduceFunctionTemplateMatch(Loc loc, Objects targsi, Expression ethis, Expressions fargs, Objects dedargs) { size_t nfparams; size_t nfargs; @@ -652,7 +689,7 @@ int tuple_dim = 0; MATCH match = MATCHexact; FuncDeclaration fd = onemember.toAlias().isFuncDeclaration(); - Arguments fparameters; // function parameter list + Parameters fparameters; // function parameter list int fvarargs; // function varargs scope Objects dedtypes = new Objects(); // for T:T*, the dedargs is the T*, dedtypes is the T @@ -682,6 +719,7 @@ Scope paramscope = scope_.push(paramsym); TemplateTupleParameter tp = isVariadic(); + int tp_is_declared = 0; static if (false) { @@ -711,27 +749,28 @@ /* The extra initial template arguments * now form the tuple argument. */ - Tuple t = new Tuple(); + auto t = new Tuple(); assert(parameters.dim); - dedargs.data[parameters.dim - 1] = cast(void*)t; + dedargs[parameters.dim - 1] = t; tuple_dim = nargsi - n; t.objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) { - t.objects.data[i] = cast(void*)targsi.data[n + i]; + t.objects[i] = targsi[n + i]; } declareParameter(paramscope, tp, t); + tp_is_declared = 1; } else n = nargsi; - memcpy(dedargs.data, targsi.data, n * (*dedargs.data).sizeof); + memcpy(dedargs.ptr, targsi.ptr, n * (*dedargs.ptr).sizeof); for (size_t i = 0; i < n; i++) { assert(i < parameters.dim); - TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i]; + auto tp2 = parameters[i]; MATCH m; Declaration sparam = null; @@ -758,22 +797,8 @@ } } - if (fd.type) - { - assert(fd.type.ty == Tfunction); - TypeFunction fdtype = cast(TypeFunction)fd.type; - fparameters = fdtype.parameters; - fvarargs = fdtype.varargs; - } - else - { - CtorDeclaration fctor = fd.isCtorDeclaration(); - assert(fctor); - fparameters = fctor.arguments; - fvarargs = fctor.varargs; - } - - nfparams = Argument.dim(fparameters); // number of function parameters + fparameters = fd.getParameters(&fvarargs); + nfparams = Parameter.dim(fparameters); // number of function parameters nfargs = fargs ? fargs.dim : 0; // number of function arguments /* Check for match of function arguments with variadic template @@ -786,9 +811,11 @@ { if (nfparams == 0 && nfargs != 0) // if no function parameters { - Tuple t = new Tuple(); + if (tp_is_declared) + goto L2; + auto t = new Tuple(); //printf("t = %p\n", t); - dedargs.data[parameters.dim - 1] = cast(void*)t; + dedargs[parameters.dim - 1] = t; declareParameter(paramscope, tp, t); goto L2; } @@ -803,28 +830,31 @@ */ for (fptupindex = 0; fptupindex < nfparams; fptupindex++) { - Argument fparam = cast(Argument)fparameters.data[fptupindex]; + auto fparam = fparameters[fptupindex]; if (fparam.type.ty != Tident) continue; - TypeIdentifier tid = cast(TypeIdentifier)fparam.type; + auto tid = cast(TypeIdentifier)fparam.type; if (!tp.ident.equals(tid.ident) || tid.idents.dim) continue; if (fvarargs) // variadic function doesn't goto Lnomatch; // go with variadic template + if (tp_is_declared) + goto L2; + /* The types of the function arguments * now form the tuple argument. */ - Tuple t = new Tuple(); - dedargs.data[parameters.dim - 1] = cast(void*)t; + auto t = new Tuple(); + dedargs[parameters.dim - 1] = t; tuple_dim = nfargs - (nfparams - 1); t.objects.setDim(tuple_dim); for (size_t i = 0; i < tuple_dim; i++) { auto farg = fargs[fptupindex + i]; - t.objects.data[i] = cast(void*)farg.type; + t.objects[i] = farg.type; } declareParameter(paramscope, tp, t); goto L2; @@ -849,7 +879,7 @@ { for (size_t i = 0; i < parameters.dim; i++) { - TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i]; + auto tp2 = parameters[i]; TemplateThisParameter ttp = tp2.isTemplateThisParameter(); if (ttp) { @@ -880,7 +910,7 @@ continue; } - Argument fparam = Argument.getNth(fparameters, i); + auto fparam = Parameter.getNth(fparameters, i); if (i >= nfargs) // if not enough arguments { @@ -928,7 +958,7 @@ TypeDelegate td = cast(TypeDelegate)fparam.type.toBasetype(); TypeFunction tf = cast(TypeFunction)td.next; - if (!tf.varargs && Argument.dim(tf.parameters) == 0) + if (!tf.varargs && Parameter.dim(tf.parameters) == 0) { m = farg.type.deduceType(paramscope, tf.next, parameters, dedtypes); if (!m && tf.next.toBasetype().ty == Tvoid) @@ -1019,13 +1049,13 @@ */ for (size_t i = nargsi; i < dedargs.dim; i++) { - TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i]; + auto tp2 = parameters[i]; //printf("tp2[%d] = %s\n", i, tp2.ident.toChars()); /* For T:T*, the dedargs is the T*, dedtypes is the T * But for function templates, we really need them to match */ - Object oarg = cast(Object)dedargs.data[i]; - Object oded = cast(Object)dedtypes.data[i]; + Object oarg = dedargs[i]; + Object oded = dedtypes[i]; //printf("1dedargs[%d] = %p, dedtypes[%d] = %p\n", i, oarg, i, oded); //if (oarg) printf("oarg: %s\n", oarg.toChars()); //if (oded) printf("oded: %s\n", oded.toChars()); @@ -1039,14 +1069,14 @@ * the oded == oarg */ Declaration sparam; - dedargs.data[i] = cast(void*)oded; + dedargs[i] = oded; MATCH m2 = tp2.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.data[i] !is cast(void*)oded) + if (dedtypes[i] !is oded) error("specialization not allowed for deduced parameter %s", tp2.ident.toChars()); } } @@ -1057,7 +1087,7 @@ goto Lnomatch; } declareParameter(paramscope, tp2, oded); - dedargs.data[i] = cast(void*)oded; + dedargs[i] = oded; } } @@ -1065,6 +1095,7 @@ if (constraint) { /* Check to see if constraint is satisfied. */ + makeParamNamesVisibleInConstraint(paramscope); Expression e = constraint.syntaxCopy(); paramscope.flags |= SCOPE.SCOPEstaticif; e = e.semantic(paramscope); @@ -1097,7 +1128,7 @@ //printf("\tnomatch\n"); return MATCHnomatch; } - + /************************************************* * Given function arguments, figure out which template function * to expand, and return that function. @@ -1121,7 +1152,7 @@ static if (false) { printf("TemplateDeclaration.deduceFunctionTemplate() %s\n", toChars()); - printf(" targsi:\n"); + printf(" targsi:\n"); if (targsi) { for (int i = 0; i < targsi.dim; i++) @@ -1130,7 +1161,7 @@ printf("\t%s\n", arg.toChars()); } } - printf(" fargs:\n"); + printf(" fargs:\n"); for (int i = 0; i < fargs.dim; i++) { Expression arg = cast(Expression)fargs.data[i]; @@ -1193,7 +1224,7 @@ td_best = td; m_best = m; tdargs.setDim(dedargs.dim); - memcpy(tdargs.data, dedargs.data, tdargs.dim * (void*).sizeof); + memcpy(tdargs.ptr, dedargs.ptr, tdargs.dim * (void*).sizeof); continue; } if (!td_best) @@ -1213,7 +1244,7 @@ */ assert(cast(size_t)cast(void*)td_best.scope_ > 0x10000); ti = new TemplateInstance(loc, td_best, tdargs); - ti.semantic(sc); + ti.semantic(sc, fargs); fd = ti.toAlias().isFuncDeclaration(); if (!fd) goto Lerror; @@ -1234,7 +1265,7 @@ { if (i) bufa.writeByte(','); - Object oarg = cast(Object)args.data[i]; + Object oarg = args[i]; ObjectToCBuffer(bufa, &hgs, oarg); } } @@ -1249,7 +1280,7 @@ /************************************************** * Declare template parameter tp with value o, and install it in the scope sc. */ - void declareParameter(Scope sc, TemplateParameter tp, Object o) + void declareParameter(Scope sc, TemplateParameter tp, Object o) { //printf("TemplateDeclaration.declareParameter('%s', o = %p)\n", tp.ident.toChars(), o); @@ -1317,9 +1348,9 @@ s.semantic(sc); } - override TemplateDeclaration isTemplateDeclaration() { return this; } + override TemplateDeclaration isTemplateDeclaration() { return this; } - TemplateTupleParameter isVariadic() + TemplateTupleParameter isVariadic() { return .isVariadic(parameters); } @@ -1327,8 +1358,51 @@ /*********************************** * We can overload templates. */ - override bool isOverloadable() + override bool isOverloadable() { - return 1; + return true; } + + /**************************** + * Declare all the function parameters as variables + * and add them to the scope + */ + void makeParamNamesVisibleInConstraint(Scope paramscope) + { + /* We do this ONLY if there is only one function in the template. + */ + FuncDeclaration fd = onemember && onemember.toAlias() ? + onemember.toAlias().isFuncDeclaration() : null; + if (fd) + { + paramscope.parent = fd; + int fvarargs; // function varargs + Parameters fparameters = fd.getParameters(&fvarargs); + size_t nfparams = Parameter.dim(fparameters); // Num function parameters + for (int i = 0; i < nfparams; i++) + { + Parameter fparam = Parameter.getNth(fparameters, i).syntaxCopy(); + if (!fparam.ident) + continue; // don't add it, if it has no name + Type vtype = fparam.type.syntaxCopy(); + // isPure will segfault if called on a ctor, because fd->type is null. + if (fd.type && fd.isPure()) + vtype = vtype.addMod(MODconst); + VarDeclaration v = new VarDeclaration(loc, vtype, fparam.ident, null); + v.storage_class |= STCparameter; + // Not sure if this condition is correct/necessary. + // It's from func.c + if (//fd->type && fd->type->ty == Tfunction && + fvarargs == 2 && i + 1 == nfparams) + v.storage_class |= STCvariadic; + + v.storage_class |= fparam.storageClass & (STCin | STCout | STCref | STClazy | STCfinal | STC_TYPECTOR | STCnodtor); + v.semantic(paramscope); + if (!paramscope.insert(v)) + error("parameter %s.%s is already defined", toChars(), v.toChars()); + else + v.parent = this; + } + } + } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TemplateExp.d --- a/dmd/TemplateExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TemplateExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TemplateExp; +import dmd.common; import dmd.Expression; import dmd.OutBuffer; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TemplateInstance.d --- a/dmd/TemplateInstance.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TemplateInstance.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TemplateInstance; +import dmd.common; import dmd.ScopeDsymbol; import dmd.IntegerExp; import dmd.Identifier; @@ -23,7 +24,7 @@ import dmd.TOK; import dmd.TY; import dmd.TypeTuple; -import dmd.Argument; +import dmd.Parameter; import dmd.WANT; import dmd.ExpInitializer; import dmd.Array; @@ -36,6 +37,10 @@ import dmd.FuncExp; import dmd.Declaration; import dmd.MATCH; +import dmd.TypeFunction; +import dmd.TemplateTupleParameter; +import dmd.FuncDeclaration; +import dmd.OverloadSet; import dmd.templates.Util; import dmd.backend.glue; @@ -144,7 +149,7 @@ for (size_t i = 0; i < v1.objects.dim; i++) { - if (!match(cast(Object)v1.objects.data[i], cast(Object)v2.objects.data[i], tempdecl, sc)) + if (!match(v1.objects[i], v2.objects[i], tempdecl, sc)) goto Lnomatch; } } @@ -236,7 +241,7 @@ a.setDim(objs.dim); for (size_t i = 0; i < objs.dim; i++) { - a.data[i] = cast(void*)objectSyntaxCopy(cast(Object)objs.data[i]); + a[i] = objectSyntaxCopy(objs[i]); } } return a; @@ -259,6 +264,11 @@ override void semantic(Scope sc) { + semantic(sc, null); + } + + void semantic(Scope sc, Expressions fargs) + { if (global.errors) { if (!global.gag) @@ -336,9 +346,8 @@ * implements the typeargs. If so, just refer to that one instead. */ - for (size_t i = 0; i < tempdecl.instances.dim; i++) + foreach (ti; tempdecl.instances) { - TemplateInstance ti = cast(TemplateInstance)tempdecl.instances.data[i]; version (LOG) { printf("\t%s: checking for match with instance %d (%p): '%s'\n", toChars(), i, ti, ti.toChars()); } @@ -356,11 +365,39 @@ } for (size_t j = 0; j < tdtypes.dim; j++) { - Object o1 = cast(Object)tdtypes.data[j]; - Object o2 = cast(Object)ti.tdtypes.data[j]; + Object o1 = tdtypes[j]; + Object o2 = ti.tdtypes[j]; if (!match(o1, o2, tempdecl, sc)) { goto L1; + } + } + + /* Template functions may have different instantiations based on + * "auto ref" parameters. + */ + if (fargs) + { + FuncDeclaration fd = ti.toAlias().isFuncDeclaration(); + if (fd) + { + auto fparameters = fd.getParameters(null); + size_t nfparams = Parameter.dim(fparameters); // Num function parameters + for (int i = 0; i < nfparams && i < fargs.dim; i++) + { auto fparam = Parameter.getNth(fparameters, i); + auto farg = fargs[i]; + if (fparam.storageClass & STCauto) // if "auto ref" + { + if (farg.isLvalue()) + { if (!(fparam.storageClass & STC.STCref)) + goto L1; // auto ref's don't match + } + else + { if (fparam.storageClass & STC.STCref) + goto L1; // auto ref's don't match + } + } + } } } @@ -384,7 +421,7 @@ uint errorsave = global.errors; inst = this; int tempdecl_instance_idx = tempdecl.instances.dim; - tempdecl.instances.push(cast(void*)this); + tempdecl.instances.push(this); parent = tempdecl.parent; //printf("parent = '%s'\n", parent.kind()); @@ -511,6 +548,22 @@ } } } + + /* If function template declaration + */ + if (fargs && aliasdecl) + { + FuncDeclaration fd = aliasdecl.toAlias().isFuncDeclaration(); + if (fd) + { + /* Transmit fargs to type so that TypeFunction::semantic() can + * resolve any "auto ref" storage classes. + */ + auto tf = cast(TypeFunction)fd.type; + if (tf && tf.ty == TY.Tfunction) + tf.fargs = fargs; + } + } // Do semantic() analysis on template instance members version (LOG) { @@ -607,10 +660,9 @@ if (global.errors != errorsave) { error("error instantiating"); - if (tinst && !global.gag) + if (tinst) { tinst.printInstantiationTrace(); - fatal(); } errors = 1; if (global.gag) @@ -708,7 +760,7 @@ { if (i) buf.writeByte(','); - Object oarg = cast(Object)args.data[i]; + Object oarg = args[i]; ObjectToCBuffer(buf, hgs, oarg); } nest--; @@ -750,7 +802,48 @@ *ps = null; return true; } - + + /***************************************************** + * Determine if template instance is really a template function, + * and that template function needs to infer types from the function + * arguments. + */ + + bool needsTypeInference(Scope sc) + { + //printf("TemplateInstance::needsTypeInference() %s\n", toChars()); + if (!tempdecl) + tempdecl = findTemplateDeclaration(sc); + for (TemplateDeclaration td = tempdecl; td; td = td.overnext) + { + /* If any of the overloaded template declarations need inference, + * then return TRUE + */ + FuncDeclaration fd; + if (!td.onemember || + (fd = td.onemember.toAlias().isFuncDeclaration()) is null || + fd.type.ty != TY.Tfunction) + { + /* Not a template function, therefore type inference is not possible. + */ + //printf("false\n"); + return false; + } + + /* Determine if the instance arguments, tiargs, are all that is necessary + * to instantiate the template. + */ + TemplateTupleParameter tp = td.isVariadic(); + //printf("tp = %p, td->parameters->dim = %d, tiargs->dim = %d\n", tp, td->parameters->dim, tiargs->dim); + TypeFunction fdtype = cast(TypeFunction)fd.type; + if (Parameter.dim(fdtype.parameters) && + (tp || tiargs.dim < td.parameters.dim)) + return true; + } + //printf("false\n"); + return false; + } + override string toChars() { scope OutBuffer buf = new OutBuffer(); @@ -788,10 +881,82 @@ return id; } + /************************************** + * Given an error instantiating the TemplateInstance, + * give the nested TemplateInstance instantiations that got + * us here. Those are a list threaded into the nested scopes. + */ void printInstantiationTrace() { if (global.gag) - return; + return; +/+ + const int max_shown = 6; + const string format = "%s: instantiated from here: %s\n"; + + // determine instantiation depth and number of recursive instantiations + int n_instantiations = 1; + int n_totalrecursions = 0; + for (TemplateInstance cur = this; cur; cur = cur.tinst) + { + ++n_instantiations; + // If two instantiations use the same declaration, they are recursive. + // (this works even if they are instantiated from different places in the + // same template). + // In principle, we could also check for multiple-template recursion, but it's + // probably not worthwhile. + if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl + && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc)) + ++n_totalrecursions; + } + + // show full trace only if it's short or verbose is on + if (n_instantiations <= max_shown || global.params.verbose) + { + for (TemplateInstance cur = this; cur; cur = cur.tinst) + { + fprintf(stdmsg, format, cur.loc.toChars(), cur.toChars()); + } + } + else if (n_instantiations - n_totalrecursions <= max_shown) + { + // By collapsing recursive instantiations into a single line, + // we can stay under the limit. + int recursionDepth=0; + for (TemplateInstance cur = this; cur; cur = cur.tinst) + { + if (cur.tinst && cur.tempdecl && cur.tinst.tempdecl + && cur.tempdecl.loc.equals(cur.tinst.tempdecl.loc)) + { + ++recursionDepth; + } + else + { + if (recursionDepth) + fprintf(stdmsg, "%s: %d recursive instantiations from here: %s\n", cur.loc.toChars(), recursionDepth+2, cur.toChars()); + else + fprintf(stdmsg,format, cur.loc.toChars(), cur.toChars()); + recursionDepth = 0; + } + } + } + else + { + // Even after collapsing the recursions, the depth is too deep. + // Just display the first few and last few instantiations. + size_t i = 0; + for (TemplateInstance cur = this; cur; cur = cur.tinst) + { + if (i == max_shown / 2) + fprintf(stdmsg," ... (%d instantiations, -v to show) ...\n", n_instantiations - max_shown); + + if (i < max_shown / 2 || + i >= n_instantiations - max_shown + max_shown / 2) + fprintf(stdmsg, format, cur.loc.toChars(), cur.toChars()); + ++i; + } + } ++/ } override void toObjFile(int multiobj) // compile to .obj file @@ -825,7 +990,7 @@ return; for (size_t j = 0; j < tiargs.dim; j++) { - Object o = cast(Object)tiargs.data[j]; + Object o = tiargs[j]; Type ta = isType(o); Expression ea = isExpression(o); Dsymbol sa = isDsymbol(o); @@ -847,11 +1012,11 @@ if (ea.op != TOKvar || flags & 1) ea = ea.optimize(WANTvalue | WANTinterpret); - tiargs.data[j] = cast(void*)ea; + tiargs[j] = ea; } else if (sa) { - tiargs.data[j] = cast(void*)sa; + tiargs[j] = sa; TupleDeclaration d = sa.toAlias().isTupleDeclaration(); if (d) { @@ -867,7 +1032,7 @@ if (ta.ty == Ttuple) { // Expand tuple - TypeTuple tt = cast(TypeTuple)ta; + auto tt = cast(TypeTuple)ta; size_t dim = tt.arguments.dim; tiargs.remove(j); if (dim) @@ -875,19 +1040,19 @@ tiargs.reserve(dim); for (size_t i = 0; i < dim; i++) { - Argument arg = cast(Argument)tt.arguments.data[i]; - tiargs.insert(j + i, cast(void*)arg.type); + auto arg = tt.arguments[i]; + tiargs.insert(j + i, arg.type); } } j--; } else - tiargs.data[j] = cast(void*)ta; + tiargs[j] = ta; } else { assert(global.errors); - tiargs.data[j] = cast(void*)Type.terror; + tiargs[j] = Type.terror; } } else if (ea) @@ -901,7 +1066,7 @@ ea = ea.semantic(sc); if (ea.op != TOKvar || flags & 1) ea = ea.optimize(WANTvalue | WANTinterpret); - tiargs.data[j] = cast(void*)ea; + tiargs[j] = ea; if (ea.op == TOKtype) { ta = ea.type; @@ -917,7 +1082,7 @@ { tiargs.reserve(dim); for (size_t i = 0; i < dim; i++) - tiargs.insert(j + i, cast(void*)te.exps.data[i]); + tiargs.insert(j + i, te.exps[i]); } j--; } @@ -980,9 +1145,32 @@ s = sc.search(loc, id, &scopesym); if (!s) { - error("identifier '%s' is not defined", id.toChars()); + error("template '%s' is not defined", id.toChars()); return null; } + + /* If an OverloadSet, look for a unique member that is a template declaration + */ + OverloadSet os = s.isOverloadSet(); + if (os) + { + s = null; + foreach (s2; os.a) + { + if (s2.isTemplateDeclaration()) + { + if (s) + error("ambiguous template declaration %s and %s", s.toPrettyChars(), s2.toPrettyChars()); + s = s2; + } + } + if (!s) + { + error("template '%s' is not defined", id.toChars()); + return null; + } + } + version (LOG) { printf("It's an instance of '%s' kind '%s'\n", s.toChars(), s.kind()); if (s.parent) @@ -1153,7 +1341,7 @@ td_best = td; m_best = m; tdtypes.setDim(dedtypes.dim); - memcpy(tdtypes.data, dedtypes.data, tdtypes.dim * (void*).sizeof); + memcpy(tdtypes.ptr, dedtypes.ptr, tdtypes.dim * (void*).sizeof); continue; } @@ -1212,9 +1400,9 @@ //printf("TemplateInstance.declareParameters()\n"); for (int i = 0; i < tdtypes.dim; i++) { - TemplateParameter tp = cast(TemplateParameter)tempdecl.parameters.data[i]; + auto tp = tempdecl.parameters[i]; //Object o = cast(Object)tiargs.data[i]; - Object o = cast(Object)tdtypes.data[i]; // initializer for tp + Object o = tdtypes[i]; // initializer for tp //printf("\ttdtypes[%d] = %p\n", i, o); tempdecl.declareParameter(sc, tp, o); @@ -1235,7 +1423,7 @@ */ for (size_t i = 0; i < args.dim; i++) { - Object o = cast(Object)args.data[i]; + Object o = args[i]; Expression ea = isExpression(o); Dsymbol sa = isDsymbol(o); Tuple va = isTuple(o); @@ -1325,7 +1513,7 @@ Objects args = tiargs; for (int i = 0; i < args.dim; i++) { - Object o = cast(Object)args.data[i]; + Object o = args[i]; Type ta = isType(o); Expression ea = isExpression(o); Dsymbol sa = isDsymbol(o); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TemplateMixin.d --- a/dmd/TemplateMixin.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TemplateMixin.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TemplateMixin; +import dmd.common; import dmd.TemplateInstance; import dmd.Array; import dmd.Type; @@ -212,12 +213,12 @@ if (tiargs.dim != tm.tiargs.dim) continue; - for (int i = 0; i < tiargs.dim; i++) - { Object o = cast(Object)tiargs.data[i]; + foreach (size_t i, Object o; tiargs) + { Type ta = isType(o); Expression ea = isExpression(o); Dsymbol sa = isDsymbol(o); - Object tmo = cast(Object)tm.tiargs.data[i]; + Object tmo = tm.tiargs[i]; if (ta) { Type tmta = isType(tmo); @@ -452,7 +453,7 @@ for (int i = 0; i < tiargs.dim; i++) { if (i) buf.writebyte(','); - Object oarg = cast(Object)tiargs.data[i]; + Object oarg = tiargs[i]; Type t = isType(oarg); Expression e = isExpression(oarg); Dsymbol s = isDsymbol(oarg); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TemplateParameter.d --- a/dmd/TemplateParameter.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TemplateParameter.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TemplateParameter; +import dmd.common; import dmd.Loc; import dmd.Identifier; import dmd.Declaration; @@ -13,6 +14,7 @@ import dmd.HdrGenState; import dmd.MATCH; import dmd.ArrayTypes; +import dmd.Array; class TemplateParameter { @@ -83,5 +85,5 @@ /* Create dummy argument based on parameter. */ - abstract void* dummyArg(); + abstract Object dummyArg(); } \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/TemplateThisParameter.d --- a/dmd/TemplateThisParameter.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TemplateThisParameter.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TemplateThisParameter; +import dmd.common; import dmd.TemplateTypeParameter; import dmd.Type; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TemplateTupleParameter.d --- a/dmd/TemplateTupleParameter.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TemplateTupleParameter.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TemplateTupleParameter; +import dmd.common; import dmd.TemplateParameter; import dmd.Loc; import dmd.Identifier; @@ -66,7 +67,7 @@ if (i) writef(", "); - Object o = cast(Object)v.objects.data[i]; + Object o = v.objects[i]; Dsymbol sa = isDsymbol(o); if (sa) @@ -122,8 +123,8 @@ */ assert(i + 1 == dedtypes.dim); // must be the last one Tuple ovar; - if (i + 1 == tiargs.dim && isTuple(cast(Object)tiargs.data[i])) - ovar = isTuple(cast(Object)tiargs.data[i]); + if (i + 1 == tiargs.dim && isTuple(tiargs[i])) + ovar = isTuple(tiargs[i]); else { ovar = new Tuple(); @@ -133,16 +134,16 @@ //printf("i = %d, tiargs.dim = %d\n", i, tiargs.dim); ovar.objects.setDim(tiargs.dim - i); for (size_t j = 0; j < ovar.objects.dim; j++) - ovar.objects.data[j] = tiargs.data[i + j]; + ovar.objects[j] = tiargs[i + j]; } } *psparam = new TupleDeclaration(loc, ident, ovar.objects); - dedtypes.data[i] = cast(void*)ovar; + dedtypes[i] = ovar; return MATCH.MATCHexact; } - override void* dummyArg() + override Object dummyArg() { return null; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TemplateTypeParameter.d --- a/dmd/TemplateTypeParameter.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TemplateTypeParameter.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TemplateTypeParameter; +import dmd.common; import dmd.TemplateParameter; import dmd.Type; import dmd.Loc; @@ -132,7 +133,7 @@ Type ta; if (i < tiargs.dim) - oarg = cast(Object)tiargs.data[i]; + oarg = tiargs[i]; else { // Get default argument instead @@ -141,7 +142,7 @@ { assert(i < dedtypes.dim); // It might have already been deduced - oarg = cast(Object)dedtypes.data[i]; + oarg = dedtypes[i]; if (!oarg) { goto Lnomatch; @@ -158,7 +159,7 @@ } //printf("ta is %s\n", ta.toChars()); - t = cast(Type)dedtypes.data[i]; + t = cast(Type)dedtypes[i]; if (specType) { @@ -172,7 +173,7 @@ if (m2 < m) m = m2; - t = cast(Type)dedtypes.data[i]; + t = cast(Type)dedtypes[i]; } else { @@ -199,7 +200,7 @@ if (!t) { - dedtypes.data[i] = cast(void*)ta; + dedtypes[i] = ta; t = ta; } @@ -213,7 +214,7 @@ return MATCHnomatch; } - override void* dummyArg() + override Object dummyArg() { Type t; @@ -224,6 +225,6 @@ // Use this for alias-parameter's too (?) t = new TypeIdentifier(loc, ident); } - return cast(void *)t; + return t; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TemplateValueParameter.d --- a/dmd/TemplateValueParameter.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TemplateValueParameter.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TemplateValueParameter; +import dmd.common; import dmd.TemplateParameter; import dmd.Scope; import dmd.Declaration; @@ -137,11 +138,7 @@ e = e.syntaxCopy(); e = e.semantic(sc); version (DMDV2) { - if (e.op == TOKdefault) - { - DefaultInitExp de = cast(DefaultInitExp)e; - e = de.resolve(loc, sc); - } + e = e.resolveLoc(loc, sc); } } return e; @@ -179,7 +176,7 @@ Object oarg; if (i < tiargs.dim) - oarg = cast(Object)tiargs.data[i]; + oarg = tiargs[i]; else { // Get default argument instead @@ -188,7 +185,7 @@ { assert(i < dedtypes.dim); // It might have already been deduced - oarg = cast(Object)dedtypes.data[i]; + oarg = dedtypes[i]; if (!oarg) goto Lnomatch; } @@ -227,9 +224,9 @@ if (!ei.equals(e)) goto Lnomatch; } - else if (dedtypes.data[i]) + else if (dedtypes[i]) { // Must match already deduced value - Expression e = cast(Expression)dedtypes.data[i]; + auto e = cast(Expression)dedtypes[i]; if (!ei || !ei.equals(e)) goto Lnomatch; @@ -246,7 +243,7 @@ if (!m) goto Lnomatch; } - dedtypes.data[i] = cast(void*)ei; + dedtypes[i] = ei; init = new ExpInitializer(loc, ei); sparam = new VarDeclaration(loc, vt, ident, init); @@ -260,7 +257,7 @@ return MATCHnomatch; } - override void* dummyArg() + override Object dummyArg() { Expression e; @@ -272,6 +269,6 @@ edummy = valType.defaultInit(Loc(0)); e = edummy; } - return cast(void*)e; + return e; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/ThisDeclaration.d --- a/dmd/ThisDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ThisDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ThisDeclaration; +import dmd.common; import dmd.VarDeclaration; import dmd.Dsymbol; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/ThisExp.d --- a/dmd/ThisExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ThisExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ThisExp; +import dmd.common; import dmd.Expression; import dmd.Declaration; import dmd.StructDeclaration; @@ -130,7 +131,8 @@ override void scanForNestedRef(Scope sc) { - assert(false); + assert(var); + var.isVarDeclaration().checkNestedReference(sc, Loc(0)); } override int inlineCost(InlineCostState* ics) diff -r 786ea1839396 -r 78bf0fe43974 dmd/ThrowStatement.d --- a/dmd/ThrowStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ThrowStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ThrowStatement; +import dmd.common; import dmd.Statement; import dmd.Expression; import dmd.Loc; @@ -42,8 +43,11 @@ FuncDeclaration fd = sc.parent.isFuncDeclaration(); fd.hasReturnExp |= 2; +version(DMDV1) { + // See bugzilla 3388. Should this be or not? if (sc.incontract) error("Throw statements cannot be in contracts"); +} exp = exp.semantic(sc); exp = resolveProperties(sc, exp); if (!exp.type.toBasetype().isClassHandle()) diff -r 786ea1839396 -r 78bf0fe43974 dmd/Token.d --- a/dmd/Token.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Token.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Token; +import dmd.common; import dmd.TOK; import dmd.Identifier; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TraitsExp.d --- a/dmd/TraitsExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TraitsExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TraitsExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.ArrayTypes; @@ -30,6 +31,7 @@ import dmd.TemplateDeclaration; import dmd.TemplateInstance; import dmd.TypeClass; +import dmd.Declaration; import dmd.Util; import dmd.expression.Util; @@ -91,13 +93,14 @@ TemplateInstance.semanticTiargs(loc, sc, args, 1); size_t dim = args ? args.dim : 0; Object o; + Declaration d; FuncDeclaration f; string ISTYPE(string cond) { return ` for (size_t i = 0; i < dim; i++) - { Type t = getType(cast(Object)args.data[i]); + { Type t = getType(args[i]); if (!t) goto Lfalse; if (!(`~cond~`)) @@ -112,7 +115,7 @@ string ISDSYMBOL(string cond) { return `for (size_t i = 0; i < dim; i++) - { Dsymbol s = getDsymbol(cast(Object)args.data[i]); + { Dsymbol s = getDsymbol(args[i]); if (!s) goto Lfalse; if (!(`~cond~`)) @@ -171,14 +174,28 @@ { mixin(ISDSYMBOL(q{(f = s.isFuncDeclaration()) !is null && f.isFinal()})); } +//version(DMDV2) { + else if (ident == Id.isRef) + { + mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.isRef()})); + } + else if (ident == Id.isOut) + { + mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.isOut()})); + } + else if (ident == Id.isLazy) + { + mixin(ISDSYMBOL(q{(d = s.isDeclaration()) !is null && d.storage_class & STClazy})); + } +//} else if (ident == Id.hasMember || ident == Id.getMember || ident == Id.getVirtualFunctions) { if (dim != 2) goto Ldimerror; - Object o_ = cast(Object)args.data[0]; - Expression e = isExpression(cast(Object)args.data[1]); + auto o_ = args[0]; + Expression e = isExpression(args[1]); if (!e) { error("expression expected as second argument of __traits %s", ident.toChars()); goto Lfalse; @@ -188,7 +205,7 @@ { error("string expected as second argument of __traits %s instead of %s", ident.toChars(), e.toChars()); goto Lfalse; } - StringExp se = cast(StringExp)e; + auto se = cast(StringExp)e; se = se.toUTF8(sc); if (se.sz != 1) { error("string must be chars"); @@ -267,7 +284,7 @@ { if (dim != 1) goto Ldimerror; - Object o_ = cast(Object)args.data[0]; + Object o_ = args[0]; Dsymbol s = getDsymbol(o_); ClassDeclaration cd; if (!s || (cd = s.isClassDeclaration()) is null) @@ -281,7 +298,7 @@ { if (dim != 1) goto Ldimerror; - Object o_ = cast(Object)args.data[0]; + Object o_ = args[0]; Dsymbol s = getDsymbol(o_); ScopeDsymbol sd; if (!s) @@ -339,7 +356,7 @@ goto Lfalse; for (size_t i = 0; i < dim; i++) - { Object o_ = cast(Object)args.data[i]; + { Object o_ = args[i]; Expression e; uint errors = global.errors; @@ -375,8 +392,8 @@ if (dim != 2) goto Ldimerror; TemplateInstance.semanticTiargs(loc, sc, args, 0); - Object o1 = cast(Object)args.data[0]; - Object o2 = cast(Object)args.data[1]; + Object o1 = args[0]; + Object o2 = args[1]; Dsymbol s1 = getDsymbol(o1); Dsymbol s2 = getDsymbol(o2); @@ -447,7 +464,7 @@ for (int i = 0; i < args.dim; i++) { buf.writeByte(','); - Object oarg = cast(Object)args.data[i]; + Object oarg = args[i]; ObjectToCBuffer(buf, hgs, oarg); } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TryCatchStatement.d --- a/dmd/TryCatchStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TryCatchStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TryCatchStatement; +import dmd.common; import dmd.Statement; import dmd.Array; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TryFinallyStatement.d --- a/dmd/TryFinallyStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TryFinallyStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TryFinallyStatement; +import dmd.common; import dmd.Statement; import dmd.Loc; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Tuple.d --- a/dmd/Tuple.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Tuple.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Tuple; +import dmd.common; import dmd.ArrayTypes; import dmd.DYNCAST; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TupleDeclaration.d --- a/dmd/TupleDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TupleDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,7 +1,8 @@ module dmd.TupleDeclaration; +import dmd.common; import dmd.Declaration; -import dmd.Argument; +import dmd.Parameter; import dmd.ArrayTypes; import dmd.TypeTuple; import dmd.Loc; @@ -53,10 +54,8 @@ { /* It's only a type tuple if all the Object's are types */ - for (size_t i = 0; i < objects.dim; i++) + foreach (o; objects) { - Object o = cast(Object)objects.data[i]; - if (cast(Type)o is null) { //printf("\tnot[%d], %p, %d\n", i, o, o->dyncast()); @@ -66,12 +65,12 @@ /* We know it's a type tuple, so build the TypeTuple */ - Arguments args = new Arguments(); + auto args = new Parameters(); args.setDim(objects.dim); OutBuffer buf = new OutBuffer(); bool hasdeco = 1; for (size_t i = 0; i < objects.dim; i++) - { Type t = cast(Type)objects.data[i]; + { Type t = cast(Type)objects[i]; //printf("type = %s\n", t->toChars()); static if (false) @@ -79,11 +78,11 @@ buf.printf("_%s_%d", ident.toChars(), i); char *name = cast(char *)buf.extractData(); Identifier id = new Identifier(name, TOKidentifier); - Argument arg = new Argument(STCin, t, id, null); + auto arg = new Parameter(STCin, t, id, null); } else { - Argument arg = new Argument(STCundefined, t, null, null); + auto arg = new Parameter(STCundefined, t, null, null); } - args.data[i] = cast(void *)arg; + args[i] = arg; if (!t.deco) hasdeco = false; } @@ -101,7 +100,7 @@ //printf("TupleDeclaration::needThis(%s)\n", toChars()); for (size_t i = 0; i < objects.dim; i++) { - Object o = cast(Object)objects.data[i]; + Object o = objects[i]; if (auto e = cast(Expression)o) { if (e.op == TOKdsymbol) diff -r 786ea1839396 -r 78bf0fe43974 dmd/TupleExp.d --- a/dmd/TupleExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TupleExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TupleExp; +import dmd.common; import dmd.Expression; import dmd.TupleDeclaration; import dmd.backend.elem; @@ -88,9 +89,8 @@ type = null; exps.reserve(tup.objects.dim); - for (size_t i = 0; i < tup.objects.dim; i++) + foreach (o; tup.objects) { - Object o = cast(Object)tup.objects.data[i]; if (auto e = cast(Expression)o) { e = e.syntaxCopy(); diff -r 786ea1839396 -r 78bf0fe43974 dmd/Type.d --- a/dmd/Type.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Type.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,7 +1,8 @@ module dmd.Type; +import dmd.common; import dmd.TY; -import dmd.Argument; +import dmd.Parameter; import dmd.TOK; import dmd.STC; import dmd.TypeArray; @@ -53,6 +54,15 @@ import dmd.TypeSlice; import dmd.Global; import dmd.StringValue; +import dmd.TRUST; +import dmd.TemplateDeclaration; +import dmd.DotIdExp; +import dmd.AggregateDeclaration; +import dmd.DotTemplateInstanceExp; +import dmd.Token; +import dmd.TypeInfoWildDeclaration; + +import dmd.expression.Util; import dmd.backend.Symbol; import dmd.backend.TYPE; @@ -79,15 +89,15 @@ * REALALIGNSIZE = alignment for reals */ version (TARGET_OSX) { - int REALSIZE = 16; + extern(C++) int REALSIZE = 16; int REALPAD = 6; int REALALIGNSIZE = 16; } else version (POSIX) { /// TARGET_LINUX || TARGET_FREEBSD || TARGET_SOLARIS - int REALSIZE = 12; + extern(C++) int REALSIZE = 12; int REALPAD = 2; int REALALIGNSIZE = 4; } else { - int REALSIZE = 10; + extern(C++) int REALSIZE = 10; int REALPAD = 0; int REALALIGNSIZE = 2; } @@ -99,10 +109,8 @@ int templateIdentifierLookup(Identifier id, TemplateParameters parameters) { - for (size_t i = 0; i < parameters.dim; i++) + foreach (size_t i, TemplateParameter tp; parameters) { - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; - if (tp.ident.equals(id)) return i; } @@ -121,6 +129,102 @@ return -1; } +/*************************** + * Return !=0 if modfrom can be implicitly converted to modto + */ +int MODimplicitConv(MOD modfrom, MOD modto) +{ + if (modfrom == modto) + return 1; + + //printf("MODimplicitConv(from = %x, to = %x)\n", modfrom, modto); + static uint X(MOD m, MOD n) + { + return (((m) << 4) | (n)); + } + switch (X(modfrom, modto)) + { + case X(MOD.MODundefined, MOD.MODconst): + case X(MOD.MODimmutable, MOD.MODconst): + case X(MOD.MODwild, MOD.MODconst): + case X(MOD.MODimmutable, MOD.MODconst | MOD.MODshared): + case X(MOD.MODshared, MOD.MODconst | MOD.MODshared): + case X(MOD.MODwild | MOD.MODshared, MOD.MODconst | MOD.MODshared): + return 1; + + default: + return 0; + } +} + +/********************************* + * Mangling for mod. + */ +void MODtoDecoBuffer(OutBuffer buf, MOD mod) +{ + switch (mod) + { + case MOD.MODundefined: + break; + case MOD.MODconst: + buf.writeByte('x'); + break; + case MOD.MODimmutable: + buf.writeByte('y'); + break; + case MOD.MODshared: + buf.writeByte('O'); + break; + case MOD.MODshared | MOD.MODconst: + buf.writestring("Ox"); + break; + case MOD.MODwild: + buf.writestring("Ng"); + break; + case MOD.MODshared | MOD.MODwild: + buf.writestring("ONg"); + break; + default: + assert(0); + } +} + +/********************************* + * Name for mod. + */ +void MODtoBuffer(OutBuffer buf, MOD mod) +{ + switch (mod) + { + case MOD.MODundefined: + break; + + case MOD.MODimmutable: + buf.writestring(Token.tochars[TOK.TOKimmutable]); + break; + + case MOD.MODshared: + buf.writestring(Token.tochars[TOK.TOKshared]); + break; + + case MOD.MODshared | MOD.MODconst: + buf.writestring(Token.tochars[TOK.TOKshared]); + buf.writeByte(' '); + case MOD.MODconst: + buf.writestring(Token.tochars[TOK.TOKconst]); + break; + + case MOD.MODshared | MOD.MODwild: + buf.writestring(Token.tochars[TOK.TOKshared]); + buf.writeByte(' '); + case MOD.MODwild: + buf.writestring(Token.tochars[TOKwild]); + break; + default: + assert(0); + } +} + class Type { TY ty; @@ -137,12 +241,16 @@ * They should not be referenced by anybody but mtype.c. * They can be null if not lazily evaluated yet. * Note that there is no "shared immutable", because that is just immutable + * Naked == no MOD bits */ - Type cto; // MODconst ? mutable version of this type : const version - Type ito; // MODinvariant ? mutable version of this type : invariant version - Type sto; // MODshared ? mutable version of this type : shared mutable version - Type scto; // MODshared|MODconst ? mutable version of this type : shared const version + Type cto; // MODconst ? naked version of this type : const version + Type ito; // MODimmutable ? naked version of this type : immutable version + Type sto; // MODshared ? naked version of this type : shared mutable version + Type scto; // MODshared|MODconst ? naked version of this type : shared const version + Type wto; // MODwild ? naked version of this type : wild version + Type swto; // MODshared|MODwild ? naked version of this type : shared wild version + Type pto; // merged pointer to this type Type rto; // reference to this type @@ -167,6 +275,7 @@ static ClassDeclaration typeinfoconst; static ClassDeclaration typeinfoinvariant; static ClassDeclaration typeinfoshared; + static ClassDeclaration typeinfowild; static Type basic[TY.TMAX]; static ubyte mangleChar[TY.TMAX]; @@ -397,8 +506,8 @@ DYNCAST dyncast() { return DYNCAST.DYNCAST_TYPE; } // kludge for template.isType() /******************************* - * Covariant means that 'this' can substitute for 't'. - * Returns: + * Covariant means that 'this' can substitute for 't', + * i.e. a pure function is a match for an impure type. * Returns: * 0 types are distinct * 1 this is covariant with t * 2 arguments match as far as overloading goes, @@ -434,14 +543,14 @@ if (t1.parameters && t2.parameters) { - size_t dim = Argument.dim(t1.parameters); - if (dim != Argument.dim(t2.parameters)) + size_t dim = Parameter.dim(t1.parameters); + if (dim != Parameter.dim(t2.parameters)) goto Ldistinct; for (size_t i = 0; i < dim; i++) { - Argument arg1 = Argument.getNth(t1.parameters, i); - Argument arg2 = Argument.getNth(t2.parameters, i); + auto arg1 = Parameter.getNth(t1.parameters, i); + auto arg2 = Parameter.getNth(t2.parameters, i); if (!arg1.type.equals(arg2.type)) { @@ -453,7 +562,8 @@ ///} goto Ldistinct; } - if ((arg1.storageClass & ~STC.STCscope) != (arg2.storageClass & ~STC.STCscope)) + const StorageClass sc = STC.STCref | STC.STCin | STC.STCout | STC.STClazy; + if ((arg1.storageClass & sc) != (arg2.storageClass & sc)) inoutmismatch = 1; // We can add scope, but not subtract it if (!(arg1.storageClass & STC.STCscope) && (arg2.storageClass & STC.STCscope)) @@ -486,7 +596,7 @@ * forward references. */ if ((cast(TypeClass)t1n).sym == (cast(TypeClass)t2n).sym && - t2n.mod == MOD.MODconst) + MODimplicitConv(t1n.mod, t2n.mod)) goto Lcovariant; // If t1n is forward referenced: @@ -505,6 +615,9 @@ Lcovariant: /* Can convert mutable to const */ + if (!MODimplicitConv(t2.mod, t1.mod)) + goto Lnotcovariant; +static if(false) { if (t1.mod != t2.mod) { if (!(t1.mod & MOD.MODconst) && (t2.mod & MOD.MODconst)) @@ -512,7 +625,7 @@ if (!(t1.mod & MOD.MODshared) && (t2.mod & MOD.MODshared)) goto Lnotcovariant; } - +} /* Can convert pure to impure, and nothrow to throw */ if (!t1.ispure && t2.ispure) @@ -522,6 +635,11 @@ goto Lnotcovariant; if (t1.isref != t2.isref) + goto Lnotcovariant; + + /* Can convert safe/trusted to system + */ + if (t1.trust <= TRUST.TRUSTsystem && t2.trust >= TRUST.TRUSTtrusted) goto Lnotcovariant; //printf("\tcovaraint: 1\n"); @@ -616,6 +734,7 @@ mangleChar[TY.Twchar] = 'u'; mangleChar[TY.Tdchar] = 'w'; + // '@' shouldn't appear anywhere in the deco'd names mangleChar[TY.Tbit] = '@'; mangleChar[TY.Tinstance] = '@'; mangleChar[TY.Terror] = '@'; @@ -724,16 +843,7 @@ { if (flag != mod && flag != 0x100) { - if (mod & MOD.MODshared) - buf.writeByte('O'); - - if (mod & MOD.MODconst) - buf.writeByte('x'); - else if (mod & MOD.MODinvariant) - buf.writeByte('y'); - - // Cannot be both const and invariant - assert((mod & (MOD.MODconst | MOD.MODinvariant)) != (MOD.MODconst | MOD.MODinvariant)); + MODtoDecoBuffer(buf, mod); } buf.writeByte(mangleChar[ty]); } @@ -820,40 +930,35 @@ { if (mod != this.mod) { - string p; - if (this.mod & MOD.MODshared) - buf.writestring("shared("); + { + MODtoBuffer(buf, this.mod & MOD.MODshared); + buf.writeByte('('); + } - switch (this.mod & (MOD.MODconst | MOD.MODinvariant)) - { - case MOD.MODundefined: - toCBuffer2(buf, hgs, this.mod); - break; - case MOD.MODconst: - p = "const("; - goto L1; - case MOD.MODinvariant: - p = "immutable("; - L1: buf.writestring(p); - toCBuffer2(buf, hgs, this.mod); - buf.writeByte(')'); - break; - } - - if (this.mod & MOD.MODshared) - buf.writeByte(')'); + if (this.mod & ~MOD.MODshared) + { + MODtoBuffer(buf, this.mod & ~MOD.MODshared); + buf.writeByte('('); + toCBuffer2(buf, hgs, this.mod); + buf.writeByte(')'); + } + else + toCBuffer2(buf, hgs, this.mod); + if (this.mod & MOD.MODshared) + { + buf.writeByte(')'); + } } } void modToBuffer(OutBuffer buf) { - if (mod & MOD.MODshared) - buf.writestring(" shared"); - if (mod & MOD.MODconst) - buf.writestring(" const"); - if (mod & MOD.MODinvariant) - buf.writestring(" immutable"); + if (mod) + { + buf.writeByte(' '); + MODtoBuffer(buf, mod); + } } version (CPP_MANGLE) { @@ -936,13 +1041,20 @@ bool isConst() { return (mod & MOD.MODconst) != 0; } - int isInvariant() { return mod & MOD.MODinvariant; } + int isImmutable() { return mod & MOD.MODimmutable; } - int isMutable() { return !(mod & (MOD.MODconst | MOD.MODinvariant)); } + int isMutable() { return !(mod & (MOD.MODconst | MOD.MODimmutable | MOD.MODwild)); } int isShared() { return mod & MOD.MODshared; } int isSharedConst() { return mod == (MOD.MODshared | MOD.MODconst); } + + int isWild() { return mod & MOD.MODwild; } + + int isSharedWild() { return mod == (MOD.MODshared | MOD.MODwild); } + + int isNaked() { return mod == 0; } + /******************************** * Convert to 'const'. @@ -970,13 +1082,13 @@ Type invariantOf() { //printf("Type.invariantOf() %p %s\n", this, toChars()); - if (isInvariant()) + if (isImmutable()) { return this; } if (ito) { - assert(ito.isInvariant()); + assert(ito.isImmutable()); return ito; } Type t = makeInvariant(); @@ -995,51 +1107,29 @@ if (isShared()) t = sto; // shared const => shared else - t = cto; + t = cto; // const => naked assert(!t || t.isMutable()); } - else if (isInvariant()) + else if (isImmutable()) { t = ito; assert(!t || (t.isMutable() && !t.isShared())); } + else if (isWild()) + { + if (isShared()) + t = sto; // shared wild => shared + else + t = wto; // wild => naked + assert(!t || t.isMutable()); + } if (!t) { - uint sz = this.classinfo.init.length; - t = cast(Type)GC.malloc(sz); - memcpy(cast(void*)t, cast(void*)this, sz); - t.mod = mod & MODshared; - t.deco = null; - t.arrayof = null; - t.pto = null; - t.rto = null; - t.cto = null; - t.ito = null; - t.sto = null; - t.scto = null; - t.vtinfo = null; + t = makeMutable(); t = t.merge(); - t.fixTo(this); - - switch (mod) - { - case MODconst: - t.cto = this; - break; - - case MODinvariant: - t.ito = this; - break; - - case MODshared | MODconst: - t.scto = this; - break; - - default: - assert(0); - } } + assert(t.isMutable()); return t; } @@ -1087,6 +1177,13 @@ /******************************** * Make type unshared. + * 0 => 0 + * const => const + * immutable => immutable + * shared => 0 + * shared const => const + * wild => wild + * shared wild => wild */ Type unSharedOf() { @@ -1097,6 +1194,8 @@ { if (isConst()) t = cto; // shared const => const + else if (isWild()) + t = wto; // shared wild => wild else t = sto; assert(!t || !t.isShared()); @@ -1116,37 +1215,68 @@ t.ito = null; t.sto = null; t.scto = null; + t.wto = null; + t.swto = null; t.vtinfo = null; t = t.merge(); t.fixTo(this); - - switch (mod) - { - case MODshared: - t.sto = this; - break; - - case MODshared | MODconst: - t.scto = this; - break; - - default: - assert(0); - } } assert(!t.isShared()); return t; } + + /******************************** + * Convert to 'wild'. + */ + + Type wildOf() + { + //printf("Type::wildOf() %p %s\n", this, toChars()); + if (mod == MOD.MODwild) + { + return this; + } + if (wto) + { + assert(wto.isWild()); + return wto; + } + Type t = makeWild(); + t = t.merge(); + t.fixTo(this); + //printf("\t%p %s\n", t, t->toChars()); + return t; + } + + Type sharedWildOf() + { + //printf("Type::sharedWildOf() %p, %s\n", this, toChars()); + if (mod == (MOD.MODwild)) + { + return this; + } + if (swto) + { + assert(swto.mod == (MOD.MODshared | MOD.MODwild)); + return swto; + } + Type t = makeSharedWild(); + t = t.merge(); + t.fixTo(this); + //printf("\t%p\n", t); + return t; + } + static uint X(MOD m, MOD n) { - return (((m) << 3) | (n)); + return (((m) << 4) | (n)); } /********************************** * For our new type 'this', which is type-constructed from t, - * fill in the cto, ito, sto, scto shortcuts. + * fill in the cto, ito, sto, scto, wto shortcuts. */ void fixTo(Type t) { @@ -1169,7 +1299,7 @@ cto = t; break; - case X(MOD.MODundefined, MOD.MODinvariant): + case X(MOD.MODundefined, MOD.MODimmutable): ito = t; break; @@ -1181,12 +1311,20 @@ scto = t; break; + case X(MOD.MODundefined, MODwild): + wto = t; + break; + + case X(MOD.MODundefined, MODshared | MODwild): + swto = t; + break; + case X(MOD.MODconst, MOD.MODundefined): cto = null; goto L2; - case X(MOD.MODconst, MOD.MODinvariant): + case X(MOD.MODconst, MOD.MODimmutable): ito = t; goto L2; @@ -1196,30 +1334,48 @@ case X(MOD.MODconst, MOD.MODshared | MOD.MODconst): scto = t; + goto L2; + + case X(MOD.MODconst, MOD.MODwild): + wto = t; + goto L2; + + case X(MOD.MODconst, MOD.MODshared | MOD.MODwild): + swto = t; L2: t.cto = this; break; - case X(MOD.MODinvariant, MOD.MODundefined): + case X(MOD.MODimmutable, MOD.MODundefined): ito = null; goto L3; - case X(MOD.MODinvariant, MOD.MODconst): + case X(MOD.MODimmutable, MOD.MODconst): cto = t; goto L3; - case X(MOD.MODinvariant, MOD.MODshared): + case X(MOD.MODimmutable, MOD.MODshared): sto = t; goto L3; - case X(MOD.MODinvariant, MOD.MODshared | MOD.MODconst): + case X(MOD.MODimmutable, MOD.MODshared | MOD.MODconst): scto = t; + goto L3; + + case X(MOD.MODimmutable, MOD.MODwild): + wto = t; + goto L3; + + case X(MOD.MODimmutable, MOD.MODshared | MOD.MODwild): + swto = t; L3: t.ito = this; if (t.cto) t.cto.ito = this; if (t.sto) t.sto.ito = this; if (t.scto) t.scto.ito = this; + if (t.wto) t.wto.ito = this; + if (t.swto) t.swto.ito = this; break; @@ -1231,12 +1387,20 @@ cto = t; goto L4; - case X(MOD.MODshared, MOD.MODinvariant): + case X(MOD.MODshared, MOD.MODimmutable): ito = t; goto L4; case X(MOD.MODshared, MOD.MODshared | MOD.MODconst): scto = t; + goto L4; + + case X(MOD.MODshared, MOD.MODwild): + wto = t; + goto L4; + + case X(MOD.MODshared, MOD.MODshared | MOD.MODwild): + swto = t; L4: t.sto = this; break; @@ -1244,21 +1408,82 @@ case X(MOD.MODshared | MOD.MODconst, MOD.MODundefined): scto = null; - break; + goto L5; case X(MOD.MODshared | MOD.MODconst, MOD.MODconst): cto = t; - break; + goto L5; - case X(MOD.MODshared | MOD.MODconst, MOD.MODinvariant): + case X(MOD.MODshared | MOD.MODconst, MOD.MODimmutable): ito = t; - break; + goto L5; + + case X(MOD.MODshared | MOD.MODconst, MOD.MODwild): + wto = t; + goto L5; case X(MOD.MODshared | MOD.MODconst, MOD.MODshared): sto = t; + goto L5; + + case X(MOD.MODshared | MOD.MODconst, MOD.MODshared | MOD.MODwild): + swto = t; L5: t.scto = this; break; + + case X(MOD.MODwild, MOD.MODundefined): + wto = null; + goto L6; + + case X(MOD.MODwild, MOD.MODconst): + cto = t; + goto L6; + + case X(MOD.MODwild, MOD.MODimmutable): + ito = t; + goto L6; + + case X(MOD.MODwild, MOD.MODshared): + sto = t; + goto L6; + + case X(MOD.MODwild, MOD.MODshared | MOD.MODconst): + scto = t; + goto L6; + + case X(MOD.MODwild, MOD.MODshared | MOD.MODwild): + swto = t; + L6: + t.wto = this; + break; + + + case X(MOD.MODshared | MOD.MODwild, MOD.MODundefined): + swto = null; + goto L7; + + case X(MOD.MODshared | MOD.MODwild, MOD.MODconst): + cto = t; + goto L7; + + case X(MOD.MODshared | MOD.MODwild, MOD.MODimmutable): + ito = t; + goto L7; + + case X(MOD.MODshared | MOD.MODwild, MOD.MODshared): + sto = t; + goto L7; + + case X(MOD.MODshared | MOD.MODwild, MOD.MODshared | MOD.MODconst): + scto = t; + goto L7; + + case X(MOD.MODshared | MOD.MODwild, MOD.MODwild): + wto = t; + L7: + t.swto = this; + break; } check(); @@ -1275,38 +1500,66 @@ { case MOD.MODundefined: if (cto) assert(cto.mod == MOD.MODconst); - if (ito) assert(ito.mod == MOD.MODinvariant); + if (ito) assert(ito.mod == MOD.MODimmutable); if (sto) assert(sto.mod == MOD.MODshared); if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst)); + if (wto) assert(wto.mod == MOD.MODwild); + if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild)); break; case MOD.MODconst: if (cto) assert(cto.mod == MOD.MODundefined); - if (ito) assert(ito.mod == MOD.MODinvariant); + if (ito) assert(ito.mod == MOD.MODimmutable); if (sto) assert(sto.mod == MOD.MODshared); if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst)); + if (wto) assert(wto.mod == MOD.MODwild); + if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild)); break; - case MOD.MODinvariant: + case MOD.MODimmutable: if (cto) assert(cto.mod == MOD.MODconst); if (ito) assert(ito.mod == MOD.MODundefined); if (sto) assert(sto.mod == MOD.MODshared); if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst)); + if (wto) assert(wto.mod == MOD.MODwild); + if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild)); break; case MOD.MODshared: if (cto) assert(cto.mod == MOD.MODconst); - if (ito) assert(ito.mod == MOD.MODinvariant); + if (ito) assert(ito.mod == MOD.MODimmutable); if (sto) assert(sto.mod == MOD.MODundefined); if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst)); + if (wto) assert(wto.mod == MOD.MODwild); + if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild)); break; case MOD.MODshared | MOD.MODconst: if (cto) assert(cto.mod == MOD.MODconst); - if (ito) assert(ito.mod == MOD.MODinvariant); + if (ito) assert(ito.mod == MOD.MODimmutable); if (sto) assert(sto.mod == MOD.MODshared); if (scto) assert(scto.mod == MOD.MODundefined); + if (wto) assert(wto.mod == MOD.MODwild); + if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild)); break; + + case MOD.MODwild: + if (cto) assert(cto.mod == MOD.MODconst); + if (ito) assert(ito.mod == MOD.MODimmutable); + if (sto) assert(sto.mod == MOD.MODshared); + if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst)); + if (wto) assert(wto.mod == MOD.MODundefined); + if (swto) assert(swto.mod == (MOD.MODshared | MOD.MODwild)); + break; + + case MOD.MODshared | MOD.MODwild: + if (cto) assert(cto.mod == MOD.MODconst); + if (ito) assert(ito.mod == MOD.MODimmutable); + if (sto) assert(sto.mod == MOD.MODshared); + if (scto) assert(scto.mod == (MOD.MODshared | MOD.MODconst)); + if (wto) assert(wto.mod == MOD.MODwild); + if (swto) assert(swto.mod == MOD.MODundefined); + break; } Type tn = nextOf(); @@ -1319,19 +1572,27 @@ break; case MOD.MODconst: - assert(tn.mod & MOD.MODinvariant || tn.mod & MOD.MODconst); + assert(tn.mod & MOD.MODimmutable || tn.mod & MOD.MODconst); break; - case MOD.MODinvariant: - assert(tn.mod == MOD.MODinvariant); + case MOD.MODimmutable: + assert(tn.mod == MOD.MODimmutable); break; case MOD.MODshared: - assert(tn.mod & MOD.MODinvariant || tn.mod & MOD.MODshared); + assert(tn.mod & MOD.MODimmutable || tn.mod & MOD.MODshared); break; case MOD.MODshared | MOD.MODconst: - assert(tn.mod & MOD.MODinvariant || tn.mod & (MOD.MODshared | MOD.MODconst)); + assert(tn.mod & MOD.MODimmutable || tn.mod & (MOD.MODshared | MOD.MODconst)); + break; + + case MOD.MODwild: + assert(tn.mod); + break; + + case MOD.MODshared | MOD.MODwild: + assert(tn.mod == MOD.MODimmutable || tn.mod == (MOD.MODshared | MOD.MODconst) || tn.mod == (MOD.MODshared | MOD.MODwild)); break; } tn.check(); @@ -1348,23 +1609,31 @@ switch (mod) { case 0: - t = mutableOf(); + t = unSharedOf().mutableOf(); break; case MODconst: - t = constOf(); + t = unSharedOf().constOf(); break; - case MODinvariant: + case MODimmutable: t = invariantOf(); break; case MODshared: - t = sharedOf(); + t = mutableOf().sharedOf(); break; case MODshared | MODconst: t = sharedConstOf(); + break; + + case MODwild: + t = unSharedOf().wildOf(); + break; + + case MODshared | MODwild: + t = sharedWildOf(); break; default: @@ -1384,7 +1653,8 @@ /* Add anything to immutable, and it remains immutable */ - if (!t.isInvariant()) + //printf("addMod(%x) %s\n", mod, toChars()); + if (!t.isImmutable()) { switch (mod) { @@ -1398,13 +1668,15 @@ t = constOf(); break; - case MOD.MODinvariant: + case MOD.MODimmutable: t = invariantOf(); break; case MOD.MODshared: if (isConst()) t = sharedConstOf(); + else if (isWild()) + t = sharedWildOf(); else t = sharedOf(); break; @@ -1412,25 +1684,40 @@ case MOD.MODshared | MOD.MODconst: t = sharedConstOf(); break; + + case MOD.MODwild: + if (isConst()) + {} + else if (isShared()) + t = sharedWildOf(); + else + t = wildOf(); + break; + + case MOD.MODshared | MOD.MODwild: + t = sharedWildOf(); + break; } } return t; } - Type addStorageClass(STC stc) + Type addStorageClass(StorageClass stc) { /* Just translate to MOD bits and let addMod() do the work */ MOD mod = MOD.MODundefined; if (stc & STC.STCimmutable) - mod = MOD.MODinvariant; + mod = MOD.MODimmutable; else { if (stc & (STC.STCconst | STC.STCin)) mod = MOD.MODconst; if (stc & STC.STCshared) mod |= MOD.MODshared; + if (stc & STC.STCwild) + mod |= MOD.MODwild; } return addMod(mod); @@ -1502,6 +1789,8 @@ t.ito = null; t.sto = null; t.scto = null; + t.wto = null; + t.swto = null; t.vtinfo = null; //printf("-Type.makeConst() %p, %s\n", t, toChars()); @@ -1515,7 +1804,7 @@ } Type t = clone(); - t.mod = MOD.MODinvariant; + t.mod = MOD.MODimmutable; t.deco = null; t.arrayof = null; @@ -1525,6 +1814,8 @@ t.ito = null; t.sto = null; t.scto = null; + t.wto = null; + t.swto = null; t.vtinfo = null; return t; @@ -1546,6 +1837,8 @@ t.ito = null; t.sto = null; t.scto = null; + t.wto = null; + t.swto = null; t.vtinfo = null; return t; @@ -1567,11 +1860,73 @@ t.ito = null; t.sto = null; t.scto = null; + t.wto = null; + t.swto = null; t.vtinfo = null; return t; } + Type makeWild() + { + if (wto) + return wto; + + Type t = clone(); + t.mod = MOD.MODwild; + t.deco = null; + t.arrayof = null; + t.pto = null; + t.rto = null; + t.cto = null; + t.ito = null; + t.sto = null; + t.scto = null; + t.wto = null; + t.swto = null; + t.vtinfo = null; + return t; + } + + Type makeSharedWild() + { + if (swto) + return swto; + + Type t = clone(); + t.mod = MOD.MODshared | MOD.MODwild; + t.deco = null; + t.arrayof = null; + t.pto = null; + t.rto = null; + t.cto = null; + t.ito = null; + t.sto = null; + t.scto = null; + t.wto = null; + t.swto = null; + t.vtinfo = null; + return t; + } + + Type makeMutable() + { + Type t = clone(); + t.mod = mod & MOD.MODshared; + t.deco = null; + t.arrayof = null; + t.pto = null; + t.rto = null; + t.cto = null; + t.ito = null; + t.sto = null; + t.scto = null; + t.wto = null; + t.swto = null; + t.vtinfo = null; + return t; + } + Dsymbol toDsymbol(Scope sc) { return null; @@ -1615,7 +1970,7 @@ { if (equals(to)) return MATCH.MATCHexact; - if (ty == to.ty && to.mod == MOD.MODconst) + if (ty == to.ty && MODimplicitConv(mod, to.mod)) return MATCH.MATCHconst; return MATCH.MATCHnomatch; } @@ -1765,11 +2120,11 @@ // if (!e.isConst()) // error(loc, ".init cannot be evaluated at compile time"); } - return e; + goto Lreturn; } } - Expression ex = defaultInit(e.loc); - return ex; + e = defaultInit(e.loc); + goto Lreturn; } } if (ident is Id.typeinfo_) @@ -1777,19 +2132,89 @@ if (!global.params.useDeprecated) error(e.loc, ".typeinfo deprecated, use typeid(type)"); e = getTypeInfo(sc); - return e; } - if (ident is Id.stringof_) + else if (ident is Id.stringof_) { string s = e.toChars(); e = new StringExp(e.loc, s, 'c'); - scope Scope sc2 = new Scope(); /// - e = e.semantic(sc2); - return e; } - return getProperty(e.loc, ident); + else + e = getProperty(e.loc, ident); + +Lreturn: + e = e.semantic(sc); + return e; } + /*************************************** + * Figures out what to do with an undefined member reference + * for classes and structs. + */ + Expression noMember(Scope sc, Expression e, Identifier ident) + { + assert(ty == TY.Tstruct || ty == TY.Tclass); + AggregateDeclaration sym = toDsymbol(sc).isAggregateDeclaration(); + assert(sym); + + if (ident !is Id.__sizeof && + ident !is Id.alignof_ && + ident !is Id.init_ && + ident !is Id.mangleof_ && + ident !is Id.stringof_ && + ident !is Id.offsetof) + { + /* See if we should forward to the alias this. + */ + if (sym.aliasthis) + { /* Rewrite e.ident as: + * e.aliasthis.ident + */ + e = new DotIdExp(e.loc, e, sym.aliasthis.ident); + e = new DotIdExp(e.loc, e, ident); + return e.semantic(sc); + } + + /* Look for overloaded opDot() to see if we should forward request + * to it. + */ + Dsymbol fd = search_function(sym, Id.opDot); + if (fd) + { /* Rewrite e.ident as: + * e.opDot().ident + */ + e = build_overload(e.loc, sc, e, null, fd.ident); + e = new DotIdExp(e.loc, e, ident); + return e.semantic(sc); + } + + /* Look for overloaded opDispatch to see if we should forward request + * to it. + */ + fd = search_function(sym, Id.opDispatch); + if (fd) + { + /* Rewrite e.ident as: + * e.opDispatch!("ident") + */ + TemplateDeclaration td = fd.isTemplateDeclaration(); + if (!td) + { + fd.error("must be a template opDispatch(string s), not a %s", fd.kind()); + return new ErrorExp(); + } + auto se = new StringExp(e.loc, ident.toChars()); + auto tiargs = new Objects(); + tiargs.push(se); + e = new DotTemplateInstanceExp(e.loc, e, Id.opDispatch, tiargs); + (cast(DotTemplateInstanceExp)e).ti.tempdecl = td; + return e; + //return e.semantic(sc); + } + } + + return Type.dotExp(sc, e, ident); + } + uint memalign(uint salign) { return salign; @@ -1801,6 +2226,18 @@ assert(false); } + /*************************************** + * Use when we prefer the default initializer to be a literal, + * rather than a global immutable variable. + */ + Expression defaultInitLiteral(Loc loc = Loc(0)) + { +version(LOGDEFAULTINIT) { + printf("Type::defaultInitLiteral() '%s'\n", toChars()); +} + return defaultInit(loc); + } + ///bool isZeroInit(Loc loc = Loc(0)) // if initializer is 0 bool isZeroInit(Loc loc) // if initializer is 0 { @@ -1892,7 +2329,7 @@ Loc loc; if (parameters.dim) { - TemplateParameter tp = cast(TemplateParameter)parameters.data[0]; + auto tp = parameters[0]; loc = tp.loc; } @@ -1904,46 +2341,58 @@ return deduceType(sc, tparam, parameters, dedtypes); } - TemplateParameter tp = cast(TemplateParameter)parameters.data[i]; + auto tp = parameters[i]; // Found the corresponding parameter tp if (!tp.isTemplateTypeParameter()) goto Lnomatch; Type tt = this; - Type at = cast(Type)dedtypes.data[i]; + Type at = cast(Type)dedtypes[i]; // 5*5 == 25 cases - static pure int X(int U, int T) { return ((U << 3) | T); } + static pure int X(int U, int T) { return ((U << 4) | T); } switch (X(tparam.mod, mod)) { case X(0, 0): case X(0, MODconst): - case X(0, MODinvariant): + case X(0, MODimmutable): case X(0, MODshared): case X(0, MODconst | MODshared): + case X(0, MODwild): + case X(0, MODwild | MODshared): // foo(U:U) T => T // foo(U:U) const(T) => const(T) // foo(U:U) immutable(T) => immutable(T) // foo(U:U) shared(T) => shared(T) // foo(U:U) const(shared(T)) => const(shared(T)) + // foo(U:U) wild(T) => wild(T) + // foo(U:U) wild(shared(T)) => wild(shared(T)) if (!at) - { dedtypes.data[i] = cast(void *)tt; + { dedtypes[i] = tt; goto Lexact; } break; case X(MODconst, MODconst): - case X(MODinvariant, MODinvariant): + case X(MODimmutable, MODimmutable): case X(MODshared, MODshared): case X(MODconst | MODshared, MODconst | MODshared): + case X(MODwild, MODwild): + case X(MODwild | MODshared, MODwild | MODshared): + case X(MODconst, MODwild): + case X(MODconst, MODwild | MODshared): // foo(U:const(U)) const(T) => T // foo(U:immutable(U)) immutable(T) => T // foo(U:shared(U)) shared(T) => T // foo(U:const(shared(U)) const(shared(T))=> T + // foo(U:wild(U)) wild(T) => T + // foo(U:wild(shared(U)) wild(shared(T)) => T + // foo(U:const(U)) wild(shared(T)) => shared(T) tt = mutableOf().unSharedOf(); if (!at) - { dedtypes.data[i] = cast(void *)tt; + { + dedtypes[i] = tt; goto Lexact; } break; @@ -1952,13 +2401,15 @@ case X(MODconst, MODimmutable): case X(MODconst, MODconst | MODshared): case X(MODconst | MODshared, MODimmutable): + case X(MODshared, MODwild | MODshared): // foo(U:const(U)) T => T // foo(U:const(U)) immutable(T) => T // foo(U:const(U)) const(shared(T)) => shared(T) // foo(U:const(shared(U)) immutable(T) => T + // foo(U:shared(U)) wild(shared(T)) => wild(T) tt = mutableOf(); if (!at) - { dedtypes.data[i] = cast(void *)tt; + { dedtypes[i] = tt; goto Lconst; } break; @@ -1969,7 +2420,7 @@ // foo(U:const(shared(U)) shared(T) => T tt = unSharedOf(); if (!at) - { dedtypes.data[i] = cast(void *)tt; + { dedtypes[i] = tt; goto Lconst; } break; @@ -1984,6 +2435,23 @@ case X(MODshared, MODimmutable): case X(MODconst | MODshared, 0): case X(MODconst | MODshared, MODconst): + case X(MODimmutable, MODwild): + case X(MODshared, MODwild): + case X(MODconst | MODshared, MODwild): + case X(MODwild, 0): + case X(MODwild, MODconst): + case X(MODwild, MODimmutable): + case X(MODwild, MODshared): + case X(MODwild, MODconst | MODshared): + case X(MODwild | MODshared, 0): + case X(MODwild | MODshared, MODconst): + case X(MODwild | MODshared, MODimmutable): + case X(MODwild | MODshared, MODshared): + case X(MODwild | MODshared, MODconst | MODshared): + case X(MODwild | MODshared, MODwild): + case X(MODimmutable, MODwild | MODshared): + case X(MODconst | MODshared, MODwild | MODshared): + case X(MODwild, MODwild | MODshared): // foo(U:immutable(U)) T => nomatch // foo(U:immutable(U)) const(T) => nomatch // foo(U:immutable(U)) shared(T) => nomatch @@ -1994,6 +2462,23 @@ // foo(U:shared(U)) immutable(T) => nomatch // foo(U:const(shared(U)) T => nomatch // foo(U:const(shared(U)) const(T) => nomatch + // foo(U:immutable(U)) wild(T) => nomatch + // foo(U:shared(U)) wild(T) => nomatch + // foo(U:const(shared(U)) wild(T) => nomatch + // foo(U:wild(U)) T => nomatch + // foo(U:wild(U)) const(T) => nomatch + // foo(U:wild(U)) immutable(T) => nomatch + // foo(U:wild(U)) shared(T) => nomatch + // foo(U:wild(U)) const(shared(T)) => nomatch + // foo(U:wild(shared(U)) T => nomatch + // foo(U:wild(shared(U)) const(T) => nomatch + // foo(U:wild(shared(U)) immutable(T) => nomatch + // foo(U:wild(shared(U)) shared(T) => nomatch + // foo(U:wild(shared(U)) const(shared(T)) => nomatch + // foo(U:wild(shared(U)) wild(T) => nomatch + // foo(U:immutable(U)) wild(shared(T)) => nomatch + // foo(U:const(shared(U))) wild(shared(T)) => nomatch + // foo(U:wild(U)) wild(shared(T)) => nomatch //if (!at) goto Lnomatch; break; @@ -2121,8 +2606,11 @@ t.vtinfo = new TypeInfoSharedDeclaration(t); else if (t.isConst()) t.vtinfo = new TypeInfoConstDeclaration(t); - else if (t.isInvariant()) + else if (t.isImmutable()) t.vtinfo = new TypeInfoInvariantDeclaration(t); + else if (t.isWild()) + t.vtinfo = new TypeInfoWildDeclaration(t); + else t.vtinfo = t.getTypeInfoDeclaration(); } else { @@ -2178,6 +2666,24 @@ return null; } + /*************************************** + * Return !=0 if the type or any of its subtypes is wild. + */ + + int hasWild() + { + return mod & MOD.MODwild; + } + + /*************************************** + * Return MOD bits matching argument type (targ) to wild parameter type (this). + */ + + uint wildMatch(Type targ) + { + return 0; + } + Expression toExpression() { assert(false); @@ -2319,14 +2825,16 @@ case MOD.MODundefined: break; case MOD.MODconst: + case MOD.MODwild: t |= mTY.mTYconst; break; - case MOD.MODinvariant: + case MOD.MODimmutable: t |= mTY.mTYimmutable; break; case MOD.MODshared: t |= mTY.mTYshared; break; + case MOD.MODshared | MOD.MODwild: case MOD.MODshared | MOD.MODconst: t |= mTY.mTYshared | mTY.mTYconst; break; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeAArray.d --- a/dmd/TypeAArray.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeAArray.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeAArray; +import dmd.common; import dmd.TypeArray; import dmd.MOD; import dmd.ArrayTypes; @@ -115,7 +116,7 @@ else index = index.semantic(loc,sc); - if (index.nextOf() && !index.nextOf().isInvariant()) + if (index.nextOf() && !index.nextOf().isImmutable()) { index = index.constOf().mutableOf(); static if (false) @@ -176,8 +177,8 @@ */ TemplateInstance ti = new TemplateInstance(loc, Id.AssociativeArray); Objects tiargs = new Objects(); - tiargs.push(cast(void*)index); - tiargs.push(cast(void*)next); + tiargs.push(index); + tiargs.push(next); ti.tiargs = tiargs; ti.semantic(sc); @@ -329,9 +330,7 @@ version (LOGDEFAULTINIT) { printf("TypeAArray.defaultInit() '%s'\n", toChars()); } - Expression e = new NullExp(loc); - e.type = this; - return e; + return new NullExp(loc, this); } override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) @@ -356,12 +355,12 @@ override bool isZeroInit(Loc loc) { - assert(false); + return true; } override bool checkBoolean() { - assert(false); + return true; } override TypeInfoDeclaration getTypeInfoDeclaration() @@ -384,10 +383,10 @@ { TypeAArray ta = cast(TypeAArray)to; - if (!(next.mod == ta.next.mod || ta.next.mod == MODconst)) + if (!MODimplicitConv(next.mod, ta.next.mod)) return MATCHnomatch; // not const-compatible - if (!(index.mod == ta.index.mod || ta.index.mod == MODconst)) + if (!MODimplicitConv(index.mod, ta.index.mod)) return MATCHnomatch; // not const-compatible MATCH m = next.constConv(ta.next); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeArray.d --- a/dmd/TypeArray.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeArray.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeArray; +import dmd.common; import dmd.Type; import dmd.TypeNext; import dmd.Id; @@ -121,6 +122,7 @@ { e = Type.dotExp(sc, e, ident); } + e = e.semantic(sc); return e; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeBasic.d --- a/dmd/TypeBasic.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeBasic.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeBasic; +import dmd.common; import dmd.Type; import dmd.Id; import dmd.MOD; @@ -307,6 +308,7 @@ case TY.Tcomplex80: case TY.Timaginary80: case TY.Tfloat80: fvalue = real.min; goto Lfvalue; + default: } } else if (ident is Id.nan) @@ -510,7 +512,8 @@ break; default: - return Type.getProperty(e.loc, ident); + e = Type.getProperty(e.loc, ident); + break; } } else if (ident is Id.im) @@ -542,13 +545,15 @@ break; default: - return Type.getProperty(e.loc, ident); + e = Type.getProperty(e.loc, ident); + break; } } else { return Type.dotExp(sc, e, ident); } + e = e.semantic(sc); return e; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeClass.d --- a/dmd/TypeClass.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeClass.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeClass; +import dmd.common; import dmd.Type; import dmd.ClassDeclaration; import dmd.TypeInstance; @@ -199,7 +200,7 @@ * at compile time. */ if (!sym.vclassinfo) - sym.vclassinfo = new ClassInfoDeclaration(sym); + sym.vclassinfo = new TypeInfoClassDeclaration(sym.type); e = new VarExp(e.loc, sym.vclassinfo); e = e.addressOf(sc); @@ -272,41 +273,7 @@ } else { - if (ident !is Id.__sizeof && - ident !is Id.alignof_ && - ident !is Id.init_ && - ident !is Id.mangleof_ && - ident !is Id.stringof_ && - ident !is Id.offsetof) - { - /* See if we should forward to the alias this. - */ - if (sym.aliasthis) - { - /* Rewrite e.ident as: - * e.aliasthis.ident - */ - e = new DotIdExp(e.loc, e, sym.aliasthis.ident); - e = new DotIdExp(e.loc, e, ident); - return e.semantic(sc); - } - - /* Look for overloaded opDot() to see if we should forward request - * to it. - */ - Dsymbol fd = search_function(sym, Id.opDot); - if (fd) - { - /* Rewrite e.ident as: - * e.opId().ident - */ - e = build_overload(e.loc, sc, e, null, fd.ident); - e = new DotIdExp(e.loc, e, ident); - return e.semantic(sc); - } - } - - return Type.dotExp(sc, e, ident); + return noMember(sc, e, ident); } } @@ -519,9 +486,7 @@ version (LOGDEFAULTINIT) { printf("TypeClass::defaultInit() '%s'\n", toChars()); } - Expression e = new NullExp(loc); - e.type = this; - return e; + return new NullExp(loc, this); } override bool isZeroInit(Loc loc) diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeDArray.d --- a/dmd/TypeDArray.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeDArray.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeDArray; +import dmd.common; import dmd.TypeArray; import dmd.MOD; import dmd.Id; @@ -194,7 +195,7 @@ /* Allow conversion to void* */ if (tp.next.ty == Tvoid && - (next.mod == tp.next.mod || tp.next.mod == MODconst)) + MODimplicitConv(next.mod, tp.next.mod)) { return MATCHconvert; } @@ -207,7 +208,7 @@ int offset = 0; TypeDArray ta = cast(TypeDArray)to; - if (!(next.mod == ta.next.mod || ta.next.mod == MODconst)) + if (!MODimplicitConv(next.mod, ta.next.mod)) return MATCHnomatch; // not const-compatible /* Allow conversion to void[] @@ -225,6 +226,7 @@ return m; } +static if(false) { /* Allow conversions of T[][] to const(T)[][] */ if (mod == ta.mod && next.ty == Tarray && ta.next.ty == Tarray) @@ -233,7 +235,7 @@ if (m == MATCHconst) return m; } - +} /* Conversion of array of derived to array of base */ if (ta.next.isBaseOf(next, &offset) && offset == 0) @@ -247,9 +249,7 @@ version (LOGDEFAULTINIT) { printf("TypeDArray.defaultInit() '%s'\n", toChars()); } - Expression e = new NullExp(loc); - e.type = this; - return e; + return new NullExp(loc, this); } override bool builtinTypeInfo() @@ -257,7 +257,7 @@ version (DMDV2) { return !mod && (next.isTypeBasic() !is null && !next.mod || // strings are so common, make them builtin - next.ty == Tchar && next.mod == MODinvariant); + next.ty == Tchar && next.mod == MODimmutable); } else { return next.isTypeBasic() !is null; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeDelegate.d --- a/dmd/TypeDelegate.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeDelegate.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeDelegate; +import dmd.common; import dmd.Type; import dmd.TypeNext; import dmd.MOD; @@ -15,7 +16,7 @@ import dmd.Expression; import dmd.Identifier; import dmd.CppMangleState; -import dmd.Argument; +import dmd.Parameter; import dmd.Loc; import dmd.Scope; import dmd.TypeInfoDeclaration; @@ -104,7 +105,7 @@ tf.next.toCBuffer2(buf, hgs, MODundefined); buf.writestring(" delegate"); - Argument.argsToCBuffer(buf, hgs, tf.parameters, tf.varargs); + Parameter.argsToCBuffer(buf, hgs, tf.parameters, tf.varargs); } override Expression defaultInit(Loc loc) @@ -112,10 +113,7 @@ version (LOGDEFAULTINIT) { printf("TypeDelegate.defaultInit() '%s'\n", toChars()); } - Expression e; - e = new NullExp(loc); - e.type = this; - return e; + return new NullExp(loc, this); } override bool isZeroInit(Loc loc) diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeEnum.d --- a/dmd/TypeEnum.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeEnum.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeEnum; +import dmd.common; import dmd.Type; import dmd.EnumDeclaration; import dmd.Scope; @@ -188,11 +189,20 @@ override MATCH constConv(Type to) { - assert(false); + if (equals(to)) + return MATCHexact; + if (ty == to.ty && sym == (cast(TypeEnum)to).sym && + MODimplicitConv(mod, to.mod)) + return MATCHconst; + return MATCHnomatch; } override Type toBasetype() { + if (sym.scope_) + { + sym.semantic(null); // attempt to resolve forward reference + } if (!sym.memtype) { debug writef("2: "); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeExp.d --- a/dmd/TypeExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,6 +1,9 @@ module dmd.TypeExp; +import dmd.common; import dmd.Expression; +import dmd.backend.TYM; +import dmd.backend.Util; import dmd.backend.elem; import dmd.Type; import dmd.OutBuffer; @@ -41,7 +44,7 @@ override void rvalue() { - assert(false); + error("type %s has no value", toChars()); } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) @@ -56,7 +59,11 @@ override elem* toElem(IRState* irs) { - assert(false); + debug + writef("TypeExp.toElem()\n"); + + error("type %s is not an expression", toChars()); + return el_long(TYint, 0); } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeFunction.d --- a/dmd/TypeFunction.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeFunction.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,8 +1,10 @@ module dmd.TypeFunction; +import dmd.common; import dmd.TypeNext; import dmd.TypeSArray; import dmd.TypeArray; +import dmd.TemplateTupleParameter; import dmd.ArrayTypes; import dmd.LINK; import dmd.StructDeclaration; @@ -11,6 +13,10 @@ import dmd.STC; import dmd.MOD; import dmd.PROT; +import dmd.TypeIdentifier; +import dmd.TemplateParameter; +import dmd.TypeInfoFunctionDeclaration; +import dmd.Tuple; import dmd.Type; import dmd.Loc; import dmd.Scope; @@ -20,11 +26,16 @@ import dmd.CppMangleState; import dmd.TypeInfoDeclaration; import dmd.MATCH; -import dmd.Argument; +import dmd.Parameter; import dmd.Expression; import dmd.RET; import dmd.TY; +import dmd.TRUST; import dmd.Util; +import dmd.FuncDeclaration; +import dmd.Dsymbol; +import dmd.TypeTuple; +import dmd.TemplateInstance : isTuple; import dmd.backend.TYPE; import dmd.backend.PARAM; @@ -36,11 +47,13 @@ import core.stdc.stdlib; import core.stdc.string; +import std.stdio; + class TypeFunction : TypeNext { // .next is the return type - Arguments parameters; // function parameters + Parameters parameters; // function parameters int varargs; // 1: T t, ...) style for variable number of arguments // 2: T t ...) style for variable number of arguments bool isnothrow; // true: nothrow @@ -48,10 +61,12 @@ bool isproperty; // can be called without parentheses bool isref; // true: returns a reference LINK linkage; // calling convention + TRUST trust; // level of trust + Expressions fargs; // function arguments int inuse; - this(Arguments parameters, Type treturn, int varargs, LINK linkage) + this(Parameters parameters, Type treturn, int varargs, LINK linkage) { super(TY.Tfunction, treturn); @@ -61,18 +76,21 @@ this.parameters = parameters; this.varargs = varargs; this.linkage = linkage; + this.trust = TRUSTdefault; } override Type syntaxCopy() { Type treturn = next ? next.syntaxCopy() : null; - Arguments params = Argument.arraySyntaxCopy(parameters); + auto params = Parameter.arraySyntaxCopy(parameters); TypeFunction t = new TypeFunction(params, treturn, varargs, linkage); t.mod = mod; t.isnothrow = isnothrow; t.ispure = ispure; t.isproperty = isproperty; t.isref = isref; + t.trust = trust; + t.fargs = fargs; return t; } @@ -97,11 +115,10 @@ if (parameters) { t.parameters = parameters.copy(); - for (size_t i = 0; i < parameters.dim; i++) + foreach (arg; parameters) { - Argument arg = cast(Argument)parameters.data[i]; Argument cpy = arg.clone(); - t.parameters.data[i] = cast(void*)cpy; + t.parameters[i] = cpy; } } @@ -110,7 +127,7 @@ TypeFunction clone() { - assert(this.classinfo == TypeFunction.classinfo); + assert(this.classinfo is TypeFunction.classinfo); return cloneTo(new TypeFunction(null, next, varargs, linkage)); } } @@ -122,14 +139,14 @@ return this; } //printf("TypeFunction.semantic() this = %p\n", this); - //printf("TypeFunction.semantic() %s, sc.stc = %x\n", toChars(), sc.stc); + //printf("TypeFunction::semantic() %s, sc->stc = %llx, fargs = %p\n", toChars(), sc->stc, fargs); /* Copy in order to not mess up original. * This can produce redundant copies if inferring return type, * as semantic() will get called again on this. */ - TypeFunction tf = cast(TypeFunction)clone(); + TypeFunction tf = cloneThis(this); if (sc.stc & STC.STCpure) tf.ispure = true; @@ -137,30 +154,61 @@ tf.isnothrow = true; if (sc.stc & STC.STCref) tf.isref = true; + if (sc.stc & STCsafe) + tf.trust = TRUST.TRUSTsafe; + if (sc.stc & STCtrusted) + tf.trust = TRUST.TRUSTtrusted; + if (sc.stc & STCproperty) + tf.isproperty = true; + + tf.linkage = sc.linkage; + + /* If the parent is @safe, then this function defaults to safe + * too. + */ + if (tf.trust == TRUST.TRUSTdefault) + for (Dsymbol p = sc.func; p; p = p.toParent2()) + { FuncDeclaration fd = p.isFuncDeclaration(); + if (fd) + { + if (fd.isSafe()) + tf.trust = TRUST.TRUSTsafe; // default to @safe + break; + } + } - tf.linkage = sc.linkage; + bool wildreturn = false; if (tf.next) { tf.next = tf.next.semantic(loc,sc); version(SARRAYVALUE) {} else { if (tf.next.toBasetype().ty == TY.Tsarray) - { error(loc, "functions cannot return static array %s", tf.next.toChars()); + { + error(loc, "functions cannot return static array %s", tf.next.toChars()); tf.next = Type.terror; } } if (tf.next.toBasetype().ty == TY.Tfunction) - { error(loc, "functions cannot return a function"); + { + error(loc, "functions cannot return a function"); tf.next = Type.terror; } if (tf.next.toBasetype().ty == TY.Ttuple) - { error(loc, "functions cannot return a tuple"); + { + error(loc, "functions cannot return a tuple"); tf.next = Type.terror; } if (tf.next.isauto() && !(sc.flags & SCOPE.SCOPEctor)) - error(loc, "functions cannot return scope %s", tf.next.toChars()); - } + error(loc, "functions cannot return scope %s", tf.next.toChars()); + if (tf.next.toBasetype().ty == TY.Tvoid) + tf.isref = false; // rewrite "ref void" as just "void" + if (tf.next.isWild()) + wildreturn = true; + } + bool wildparams = false; + bool wildsubparams = false; if (tf.parameters) { /* Create a scope for evaluating the default arguments for the parameters @@ -169,52 +217,100 @@ argsc.stc = STCundefined; // don't inherit storage class argsc.protection = PROT.PROTpublic; - size_t dim = Argument.dim(tf.parameters); + size_t dim = Parameter.dim(tf.parameters); for (size_t i = 0; i < dim; i++) - { Argument arg = Argument.getNth(tf.parameters, i); + { auto fparam = Parameter.getNth(tf.parameters, i); tf.inuse++; - arg.type = arg.type.semantic(loc, argsc); + fparam.type = fparam.type.semantic(loc, argsc); if (tf.inuse == 1) tf.inuse--; - arg.type = arg.type.addStorageClass(arg.storageClass); + fparam.type = fparam.type.addStorageClass(fparam.storageClass); - if (arg.storageClass & (STC.STCauto | STC.STCalias | STC.STCstatic)) + if (fparam.storageClass & (STC.STCauto | STC.STCalias | STC.STCstatic)) { - if (!arg.type) + if (!fparam.type) continue; } - Type t = arg.type.toBasetype(); + Type t = fparam.type.toBasetype(); - if (arg.storageClass & (STC.STCout | STC.STCref | STC.STClazy)) + if (fparam.storageClass & (STC.STCout | STC.STCref | STC.STClazy)) { //if (t.ty == TY.Tsarray) //error(loc, "cannot have out or ref parameter of type %s", t.toChars()); - if (arg.storageClass & STC.STCout && arg.type.mod & (STCconst | STCimmutable)) + if (fparam.storageClass & STC.STCout && fparam.type.mod & (STCconst | STCimmutable)) error(loc, "cannot have const or immutabl out parameter of type %s", t.toChars()); } - if (!(arg.storageClass & STC.STClazy) && t.ty == TY.Tvoid) - error(loc, "cannot have parameter of type %s", arg.type.toChars()); + if (!(fparam.storageClass & STC.STClazy) && t.ty == TY.Tvoid) + error(loc, "cannot have parameter of type %s", fparam.type.toChars()); - if (arg.defaultArg) - { - arg.defaultArg = arg.defaultArg.semantic(argsc); - arg.defaultArg = resolveProperties(argsc, arg.defaultArg); - arg.defaultArg = arg.defaultArg.implicitCastTo(argsc, arg.type); - } + if (t.isWild()) + { + wildparams = true; + if (tf.next && !wildreturn) + error(loc, "inout on parameter means inout must be on return type as well (if from D1 code, replace with 'ref')"); + } + else if (!wildsubparams && t.hasWild()) + wildsubparams = true; - /* If arg turns out to be a tuple, the number of parameters may + if (fparam.defaultArg) + { + fparam.defaultArg = fparam.defaultArg.semantic(argsc); + fparam.defaultArg = resolveProperties(argsc, fparam.defaultArg); + fparam.defaultArg = fparam.defaultArg.implicitCastTo(argsc, fparam.type); + } + + /* If fparam turns out to be a tuple, the number of parameters may * change. */ if (t.ty == TY.Ttuple) - { dim = Argument.dim(tf.parameters); + { + // Propagate storage class from tuple parameters to their element-parameters. + auto tt = cast(TypeTuple)t; + if (tt.arguments) + { + auto tdim = tt.arguments.dim; + foreach (narg; tt.arguments) + { + narg.storageClass = fparam.storageClass; + } + } + + /* Reset number of parameters, and back up one to do this fparam again, + * now that it is the first element of a tuple + */ + dim = Parameter.dim(tf.parameters); i--; + continue; } + + /* Resolve "auto ref" storage class to be either ref or value, + * based on the argument matching the parameter + */ + if (fparam.storageClass & STC.STCauto) + { + if (fargs && i < fargs.dim) + { + auto farg = fargs[i]; + if (farg.isLvalue()) + {} // ref parameter + else + fparam.storageClass &= ~STC.STCref; // value parameter + } + else + error(loc, "auto can only be used for template function parameters"); + } } argsc.pop(); } + + if (wildreturn && !wildparams) + error(loc, "inout on return means inout must be on a parameter as well for %s", toChars()); + if (wildsubparams && wildparams) + error(loc, "inout must be all or none on top level for %s", toChars()); + if (tf.next) tf.deco = tf.merge().deco; @@ -224,7 +320,10 @@ return terror; } - if (tf.varargs == 1 && tf.linkage != LINK.LINKd && Argument.dim(tf.parameters) == 0) + if (tf.isproperty && (tf.varargs || Parameter.dim(tf.parameters) > 1)) + error(loc, "properties can only have zero or one parameter"); + + if (tf.varargs == 1 && tf.linkage != LINK.LINKd && Parameter.dim(tf.parameters) == 0) error(loc, "variadic functions with non-D linkage must have at least one parameter"); /* Don't return merge(), because arg identifiers and default args @@ -246,14 +345,7 @@ return; } inuse++; -static if (true) { - if (mod & MOD.MODshared) - buf.writeByte('O'); - if (mod & MOD.MODconst) - buf.writeByte('x'); - else if (mod & MOD.MODinvariant) - buf.writeByte('y'); -} + MODtoDecoBuffer(buf, mod); switch (linkage) { case LINK.LINKd: mc = 'F'; break; @@ -263,7 +355,7 @@ case LINK.LINKcpp: mc = 'R'; break; } buf.writeByte(mc); - if (ispure || isnothrow || isproperty || isref) + if (ispure || isnothrow || isproperty || isref || trust) { if (ispure) buf.writestring("Na"); @@ -273,9 +365,19 @@ buf.writestring("Nc"); if (isproperty) buf.writestring("Nd"); + switch (trust) + { + case TRUST.TRUSTtrusted: + buf.writestring("Ne"); + break; + case TRUST.TRUSTsafe: + buf.writestring("Nf"); + break; + default: + } } // Write argument types - Argument.argsToDecoBuffer(buf, parameters); + Parameter.argsToDecoBuffer(buf, parameters); //if (buf.data[buf.offset - 1] == '@') halt(); buf.writeByte('Z' - varargs); // mark end of arg list assert(next); @@ -297,12 +399,11 @@ /* Use 'storage class' style for attributes */ - if (mod & MODconst) - buf.writestring("const "); - if (mod & MODinvariant) - buf.writestring("immutable "); - if (mod & MODshared) - buf.writestring("shared "); + if (mod) + { + MODtoBuffer(buf, mod); + buf.writeByte(' '); + } if (ispure) buf.writestring("pure "); @@ -313,6 +414,17 @@ if (isref) buf.writestring("ref "); + switch (trust) + { + case TRUST.TRUSTtrusted: + buf.writestring("@trusted "); + break; + + case TRUST.TRUSTsafe: + buf.writestring("@safe "); + break; + } + if (next && (!ident || ident.toHChars2() == ident.toChars())) next.toCBuffer2(buf, hgs, MODundefined); if (hgs.ddoc != 1) @@ -336,7 +448,7 @@ buf.writeByte(' '); buf.writestring(ident.toHChars2()); } - Argument.argsToCBuffer(buf, hgs, parameters, varargs); + Parameter.argsToCBuffer(buf, hgs, parameters, varargs); inuse--; } @@ -371,7 +483,7 @@ if (!hgs.hdrgen && p) buf.writestring(p); buf.writestring(" function"); - Argument.argsToCBuffer(buf, hgs, parameters, varargs); + Parameter.argsToCBuffer(buf, hgs, parameters, varargs); /* Use postfix style for attributes */ @@ -389,32 +501,135 @@ if (isref) buf.writestring(" ref"); + switch (trust) + { + case TRUSTtrusted: + buf.writestring(" @trusted"); + break; + + case TRUSTsafe: + buf.writestring(" @safe"); + break; + + default: + } inuse--; } override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) { - assert(false); + //printf("TypeFunction.deduceType()\n"); + //printf("\tthis = %d, ", ty); print(); + //printf("\ttparam = %d, ", tparam.ty); tparam.print(); + + // Extra check that function characteristics must match + if (tparam && tparam.ty == Tfunction) + { + TypeFunction tp = cast(TypeFunction)tparam; + if (varargs != tp.varargs || + linkage != tp.linkage) + return MATCHnomatch; + + size_t nfargs = Parameter.dim(this.parameters); + size_t nfparams = Parameter.dim(tp.parameters); + + /* See if tuple match + */ + if (nfparams > 0 && nfargs >= nfparams - 1) + { + /* See if 'A' of the template parameter matches 'A' + * of the type of the last function parameter. + */ + auto fparam = Parameter.getNth(tp.parameters, nfparams - 1); + assert(fparam); + assert(fparam.type); + if (fparam.type.ty != Tident) + goto L1; + TypeIdentifier tid = cast(TypeIdentifier)fparam.type; + if (tid.idents.dim) + goto L1; + + /* Look through parameters to find tuple matching tid.ident + */ + size_t tupi = 0; + for (; 1; tupi++) + { + if (tupi == parameters.dim) + goto L1; + TemplateParameter t = parameters[tupi]; + TemplateTupleParameter tup = t.isTemplateTupleParameter(); + if (tup && tup.ident.equals(tid.ident)) + break; + } + + /* The types of the function arguments [nfparams - 1 .. nfargs] + * now form the tuple argument. + */ + int tuple_dim = nfargs - (nfparams - 1); + + /* See if existing tuple, and whether it matches or not + */ + Object o = dedtypes[tupi]; + if (o) + { + // Existing deduced argument must be a tuple, and must match + Tuple t = isTuple(o); + if (!t || t.objects.dim != tuple_dim) + return MATCHnomatch; + for (size_t i = 0; i < tuple_dim; i++) + { + auto arg = Parameter.getNth(this.parameters, nfparams - 1 + i); + if (!arg.type.equals(t.objects[i])) + return MATCHnomatch; + } + } + else + { // Create new tuple + Tuple t = new Tuple(); + t.objects.setDim(tuple_dim); + for (size_t i = 0; i < tuple_dim; i++) + { + auto arg = Parameter.getNth(this.parameters, nfparams - 1 + i); + t.objects[i] = arg.type; + } + dedtypes[tupi] = t; + } + nfparams--; // don't consider the last parameter for type deduction + goto L2; + } + + L1: + if (nfargs != nfparams) + return MATCHnomatch; + L2: + for (size_t i = 0; i < nfparams; i++) + { + auto a = Parameter.getNth(this.parameters, i); + auto ap = Parameter.getNth(tp.parameters, i); + if (a.storageClass != ap.storageClass || + !a.type.deduceType(sc, ap.type, parameters, dedtypes)) + return MATCHnomatch; + } + } + return Type.deduceType(sc, tparam, parameters, dedtypes); } override TypeInfoDeclaration getTypeInfoDeclaration() { - assert(false); + return new TypeInfoFunctionDeclaration(this); } override Type reliesOnTident() { - if (parameters) - { - for (size_t i = 0; i < parameters.dim; i++) - { - Argument arg = cast(Argument)parameters.data[i]; - Type t = arg.type.reliesOnTident(); - if (t) - return t; - } - } - return next.reliesOnTident(); + size_t dim = Parameter.dim(parameters); + for (size_t i = 0; i < dim; i++) + { + auto fparam = Parameter.getNth(parameters, i); + Type t = fparam.type.reliesOnTident(); + if (t) + return t; + } + return next ? next.reliesOnTident() : null; } version (CPP_MANGLE) { @@ -428,7 +643,7 @@ * Examine function signature for parameter p and see if * p can 'escape' the scope of the function. */ - bool parameterEscapes(Argument p) + bool parameterEscapes(Parameter p) { /* Scope parameters do not escape. * Allow 'lazy' to imply 'scope' - @@ -467,6 +682,8 @@ { //printf("TypeFunction.callMatch() %s\n", toChars()); MATCH match = MATCH.MATCHexact; // assume exact match + bool exactwildmatch = false; + bool wildmatch = false; if (ethis) { @@ -476,14 +693,14 @@ if (t.mod != mod) { - if (mod == MOD.MODconst) + if (MODimplicitConv(t.mod, mod)) match = MATCH.MATCHconst; else return MATCH.MATCHnomatch; } } - size_t nparams = Argument.dim(parameters); + size_t nparams = Parameter.dim(parameters); size_t nargs = args ? args.dim : 0; if (nparams == nargs) { ; @@ -501,7 +718,7 @@ // BUG: what about out and ref? - Argument p = Argument.getNth(parameters, u); + auto p = Parameter.getNth(parameters, u); assert(p); if (u >= nargs) { @@ -512,7 +729,7 @@ goto Nomatch; // not enough arguments } - arg = cast(Expression)args.data[u]; + arg = cast(Expression)args[u]; assert(arg); // writef("arg: %s, type: %s\n", arg.toChars(), arg.type.toChars()); @@ -526,7 +743,7 @@ if (p.storageClass & STCref) { - /* Don't allow static arrays to be passed to mutable refereces + /* Don't allow static arrays to be passed to mutable references * to static arrays if the argument cannot be modified. */ Type targb = arg.type.toBasetype(); @@ -534,15 +751,36 @@ //writef("%s\n", targb.toChars()); //writef("%s\n", tparb.toChars()); if (targb.nextOf() && tparb.ty == Tsarray && - targb.nextOf().mod != tparb.nextOf().mod && - !tparb.nextOf().isConst()) + !MODimplicitConv(targb.nextOf().mod, tparb.nextOf().mod)) goto Nomatch; } if (p.storageClass & STC.STClazy && p.type.ty == TY.Tvoid && arg.type.ty != TY.Tvoid) m = MATCH.MATCHconvert; else + { m = arg.implicitConvTo(p.type); + if (p.type.isWild()) + { + if (m == MATCHnomatch) + { + m = arg.implicitConvTo(p.type.constOf()); + if (m == MATCHnomatch) + m = arg.implicitConvTo(p.type.sharedConstOf()); + if (m != MATCHnomatch) + wildmatch = true; // mod matched to wild + } + else + exactwildmatch = true; // wild matched to wild + + /* If both are allowed, then there could be more than one + * binding of mod to wild, leaving a gaping type hole. + */ + if (wildmatch && exactwildmatch) + m = MATCHnomatch; + } + } + //printf("\tm = %d\n", m); if (m == MATCH.MATCHnomatch) // if no match { @@ -565,7 +803,7 @@ TypeArray ta = cast(TypeArray)tb; for (; u < nargs; u++) { - arg = cast(Expression)args.data[u]; + arg = cast(Expression)args[u]; assert(arg); static if (true) { /* If lazy array of delegates, @@ -642,10 +880,10 @@ type* tp; paramtypes = null; - size_t nparams = Argument.dim(parameters); + size_t nparams = Parameter.dim(parameters); for (size_t i = 0; i < nparams; i++) { - Argument arg = Argument.getNth(parameters, i); + auto arg = Parameter.getNth(parameters, i); tp = arg.type.toCtype(); if (arg.storageClass & (STC.STCout | STC.STCref)) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeIdentifier.d --- a/dmd/TypeIdentifier.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeIdentifier.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeIdentifier; +import dmd.common; import dmd.TypeQualified; import dmd.MOD; import dmd.Identifier; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoArrayDeclaration.d --- a/dmd/TypeInfoArrayDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoArrayDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoArrayDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.Type; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoAssociativeArrayDeclaration.d --- a/dmd/TypeInfoAssociativeArrayDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoAssociativeArrayDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoAssociativeArrayDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeAArray; import dmd.TY; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoClassDeclaration.d --- a/dmd/TypeInfoClassDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoClassDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoClassDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.ClassInfoDeclaration; @@ -19,9 +20,19 @@ type = Type.typeinfostruct.type; } + override Symbol* toSymbol() + { + //printf("TypeInfoClassDeclaration::toSymbol(%s), linkage = %d\n", toChars(), linkage); + assert(tinfo.ty == TY.Tclass); + auto tc = cast(TypeClass)tinfo; + return tc.sym.toSymbol(); + } + override void toDt(dt_t** pdt) { //printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars()); + assert(0); +static if(false) { dtxoff(pdt, Type.typeinfoclass.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoClass dtdword(pdt, 0); // monitor @@ -36,6 +47,7 @@ assert(s.Sxtrnnum == 0); dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo +} } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoConstDeclaration.d --- a/dmd/TypeInfoConstDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoConstDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoConstDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.Type; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoDeclaration.d --- a/dmd/TypeInfoDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoDeclaration; +import dmd.common; import dmd.VarDeclaration; import dmd.Type; import dmd.Dsymbol; @@ -24,9 +25,9 @@ class TypeInfoDeclaration : VarDeclaration { - Type tinfo; + Type tinfo; - this(Type tinfo, int internal) + this(Type tinfo, int internal) { super(Loc(0), Type.typeinfo.type, tinfo.getTypeInfoIdent(internal), null); this.tinfo = tinfo; @@ -42,22 +43,22 @@ assert(false); } } - override Dsymbol syntaxCopy(Dsymbol) + override Dsymbol syntaxCopy(Dsymbol) { - assert(false); + assert(false); // should never be produced by syntax + return null; } - override void semantic(Scope sc) + override void semantic(Scope sc) { - assert(false); + assert(linkage == LINKc); } - override void emitComment(Scope sc) + override void emitComment(Scope sc) { - assert(false); } - override Symbol* toSymbol() + override Symbol* toSymbol() { //printf("TypeInfoDeclaration::toSymbol(%s), linkage = %d\n", toChars(), linkage); return VarDeclaration.toSymbol(); @@ -67,7 +68,7 @@ { } - override void toObjFile(int multiobj) // compile to .obj file + override void toObjFile(int multiobj) // compile to .obj file { Symbol* s; uint sz; @@ -113,7 +114,7 @@ obj_export(s,0); } - void toDt(dt_t** pdt) + void toDt(dt_t** pdt) { assert(false); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoDelegateDeclaration.d --- a/dmd/TypeInfoDelegateDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoDelegateDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoDelegateDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.TypeDelegate; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoEnumDeclaration.d --- a/dmd/TypeInfoEnumDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoEnumDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoEnumDeclaration; +import dmd.common; import dmd.TY; import dmd.Type; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoFunctionDeclaration.d --- a/dmd/TypeInfoFunctionDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoFunctionDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,20 +1,35 @@ -module dmd.TypeInfoFunctionDeclaration; - -import dmd.Type; -import dmd.TypeInfoDeclaration; -import dmd.backend.dt_t; - +module dmd.TypeInfoFunctionDeclaration; + +import dmd.common; +import dmd.Type; +import dmd.TypeInfoDeclaration; +import dmd.TypeFunction; +import dmd.TY; + +import dmd.backend.dt_t; +import dmd.backend.Util; +import dmd.backend.TYM; + class TypeInfoFunctionDeclaration : TypeInfoDeclaration { this(Type tinfo) { - super(tinfo, 0); - type = Type.typeinfofunction.type; + super(tinfo, 0); + type = Type.typeinfofunction.type; } override void toDt(dt_t** pdt) { - assert(false); + //printf("TypeInfoFunctionDeclaration.toDt()\n"); + dtxoff(pdt, Type.typeinfofunction.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Function + dtdword(pdt, 0); // monitor + + assert(tinfo.ty == Tfunction); + + TypeFunction tc = cast(TypeFunction)tinfo; + + tc.next.getTypeInfo(null); + dtxoff(pdt, tc.next.vtinfo.toSymbol(), 0, TYnptr); // TypeInfo for function return value } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoInterfaceDeclaration.d --- a/dmd/TypeInfoInterfaceDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoInterfaceDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,10 +1,12 @@ module dmd.TypeInfoInterfaceDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.ClassInfoDeclaration; import dmd.TypeClass; import dmd.TY; +import dmd.TypeInfoClassDeclaration; import dmd.backend.dt_t; import dmd.backend.Symbol; @@ -31,7 +33,7 @@ Symbol *s; if (!tc.sym.vclassinfo) - tc.sym.vclassinfo = new ClassInfoDeclaration(tc.sym); + tc.sym.vclassinfo = new TypeInfoClassDeclaration(tc); s = tc.sym.vclassinfo.toSymbol(); dtxoff(pdt, s, 0, TYnptr); // ClassInfo for tinfo } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoInvariantDeclaration.d --- a/dmd/TypeInfoInvariantDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoInvariantDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoInvariantDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.backend.dt_t; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoPointerDeclaration.d --- a/dmd/TypeInfoPointerDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoPointerDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoPointerDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.TypePointer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoSharedDeclaration.d --- a/dmd/TypeInfoSharedDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoSharedDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoSharedDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.backend.dt_t; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoStaticArrayDeclaration.d --- a/dmd/TypeInfoStaticArrayDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoStaticArrayDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoStaticArrayDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.TypeSArray; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoStructDeclaration.d --- a/dmd/TypeInfoStructDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoStructDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,10 +1,11 @@ module dmd.TypeInfoStructDeclaration; +import dmd.common; import dmd.Type; import dmd.TY; import dmd.MOD; import dmd.Loc; -import dmd.Argument; +import dmd.Parameter; import dmd.STC; import dmd.TypeStruct; import dmd.TypeFunction; @@ -98,35 +99,52 @@ TypeFunction tfeqptr; { // bool opEqual(const T*) const; - scope Scope sc = new Scope(); - Arguments arguments = new Arguments; + scope sc = new Scope(); + auto arguments = new Parameters; version (STRUCTTHISREF) { // arg type is ref const T - Argument arg = new Argument(STC.STCref, tc.constOf(), null, null); + auto arg = new Parameter(STC.STCref, tc.constOf(), null, null); } else { // arg type is const T* - Argument arg = new Argument(STC.STCin, tc.pointerTo(), null, null); + auto arg = new Parameter(STC.STCin, tc.pointerTo(), null, null); } - arguments.push(cast(void*)arg); + arguments.push(arg); + tfeqptr = new TypeFunction(arguments, Type.tbool, 0, LINK.LINKd); + tfeqptr.mod = MODconst; + tfeqptr = cast(TypeFunction)tfeqptr.semantic(Loc(0), sc); + } + + { + scope sc = new Scope; + auto arguments = new Parameters; +version(STRUCTTHISREF) { + // arg type is ref const T + auto arg = new Parameter(STC.STCref, tc.constOf(), null, null); +} else { + // arg type is const T* + auto arg = new Parameter(STC.STCin, tc.pointerTo(), null, null); +} + + arguments.push(arg); tfeqptr = new TypeFunction(arguments, Type.tbool, 0, LINK.LINKd); tfeqptr.mod = MOD.MODconst; tfeqptr = cast(TypeFunction)tfeqptr.semantic(Loc(0), sc); } - TypeFunction tfcmpptr; + TypeFunction tfcmpptr; { scope Scope sc = new Scope(); - Arguments arguments = new Arguments; + auto arguments = new Parameters; version (STRUCTTHISREF) { // arg type is ref const T - Argument arg = new Argument(STC.STCref, tc.constOf(), null, null); + auto arg = new Parameter(STC.STCref, tc.constOf(), null, null); } else { // arg type is const T* - Argument arg = new Argument(STC.STCin, tc.pointerTo(), null, null); + auto arg = new Parameter(STC.STCin, tc.pointerTo(), null, null); } - arguments.push(cast(void*)arg); + arguments.push(arg); tfcmpptr = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd); tfcmpptr.mod = MOD.MODconst; tfcmpptr = cast(TypeFunction)tfcmpptr.semantic(Loc(0), sc); @@ -146,23 +164,8 @@ else dtdword(pdt, 0); - s = search_function(sd, Id.eq); - fdx = s ? s.isFuncDeclaration() : null; - if (fdx) - { - //printf("test1 %s, %s, %s\n", fdx.toChars(), fdx.type.toChars(), tfeqptr.toChars()); - fd = fdx.overloadExactMatch(tfeqptr); - if (fd) - dtxoff(pdt, fd.toSymbol(), 0, TYM.TYnptr); - else - { - fd = fdx.overloadExactMatch(tfcmpptr); - if (fd) - fdx.error("must return bool, not int"); - //fdx.error("must be declared as extern (D) int %s(%s*)", fdx.toChars(), sd.toChars()); - dtdword(pdt, 0); - } - } + if (sd.eq) + dtxoff(pdt, sd.eq.toSymbol(), 0, TYnptr); else dtdword(pdt, 0); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoTupleDeclaration.d --- a/dmd/TypeInfoTupleDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoTupleDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,10 +1,11 @@ module dmd.TypeInfoTupleDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.WANT; import dmd.TypeTuple; -import dmd.Argument; +import dmd.Parameter; import dmd.Expression; import dmd.TY; import dmd.backend.TYM; @@ -29,7 +30,7 @@ assert(tinfo.ty == Ttuple); - TypeTuple tu = cast(TypeTuple)tinfo; + auto tu = cast(TypeTuple)tinfo; size_t dim = tu.arguments.dim; dtdword(pdt, dim); // elements.length @@ -37,7 +38,7 @@ dt_t* d = null; for (size_t i = 0; i < dim; i++) { - Argument arg = cast(Argument)tu.arguments.data[i]; + auto arg = tu.arguments[i]; Expression e = arg.type.getTypeInfo(null); e = e.optimize(WANTvalue); e.toDt(&d); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoTypedefDeclaration.d --- a/dmd/TypeInfoTypedefDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInfoTypedefDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInfoTypedefDeclaration; +import dmd.common; import dmd.Type; import dmd.TypeInfoDeclaration; import dmd.TypedefDeclaration; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInfoWildDeclaration.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/TypeInfoWildDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,29 @@ +module dmd.TypeInfoWildDeclaration; + +import dmd.TY; +import dmd.Type; +import dmd.TypeInfoDeclaration; + +import dmd.backend.dt_t; +import dmd.backend.Util; +import dmd.backend.TYM; + +class TypeInfoWildDeclaration : TypeInfoDeclaration +{ + this(Type tinfo) + { + super(tinfo, 0); + type = Type.typeinfowild.type; + } + + override void toDt(dt_t **pdt) + { + //printf("TypeInfoWildDeclaration::toDt() %s\n", toChars()); + dtxoff(pdt, Type.typeinfowild.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfo_Wild + dtdword(pdt, 0); // monitor + Type tm = tinfo.mutableOf(); + tm = tm.merge(); + tm.getTypeInfo(null); + dtxoff(pdt, tm.vtinfo.toSymbol(), 0, TYnptr); + } +}; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeInstance.d --- a/dmd/TypeInstance.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeInstance.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeInstance; +import dmd.common; import dmd.TypeQualified; import dmd.TemplateAliasParameter; import dmd.TemplateDeclaration; @@ -197,7 +198,7 @@ } goto Lnomatch; } - TemplateParameter tpx = cast(TemplateParameter)parameters.data[i]; + TemplateParameter tpx = parameters[i]; // This logic duplicates tpx->matchArg() TemplateAliasParameter ta = tpx.isTemplateAliasParameter(); if (!ta) @@ -207,14 +208,14 @@ goto Lnomatch; if (ta.specAlias && sa != ta.specAlias) goto Lnomatch; - if (dedtypes.data[i]) + if (dedtypes[i]) { // Must match already deduced symbol - Object s = cast(Object)dedtypes.data[i]; + Object s = dedtypes[i]; if (s != sa) goto Lnomatch; } - dedtypes.data[i] = cast(void*)sa; + dedtypes[i] = sa; } } else if (tempinst.tempdecl != tp.tempinst.tempdecl) @@ -227,17 +228,17 @@ //printf("\ttest: tempinst->tiargs[%d]\n", i); Object o1; if (i < tempinst.tiargs.dim) - o1 = cast(Object)tempinst.tiargs.data[i]; + o1 = tempinst.tiargs[i]; else if (i < tempinst.tdtypes.dim && i < tp.tempinst.tiargs.dim) // Pick up default arg - o1 = cast(Object)tempinst.tdtypes.data[i]; + o1 = tempinst.tdtypes[i]; else break; if (i >= tp.tempinst.tiargs.dim) goto Lnomatch; - Object o2 = cast(Object)tp.tempinst.tiargs.data[i]; + Object o2 = tp.tempinst.tiargs[i]; Type t1 = isType(o1); Type t2 = isType(o2); @@ -286,16 +287,16 @@ int vtdim = tempinst.tiargs.dim - i; vt.objects.setDim(vtdim); for (size_t k = 0; k < vtdim; k++) - vt.objects.data[k] = cast(void *)tempinst.tiargs.data[i + k]; + vt.objects[k] = tempinst.tiargs[i + k]; - Tuple v = cast(Tuple)dedtypes.data[j]; + auto v = cast(Tuple)dedtypes[j]; if (v) { if (!match(v, vt, tempinst.tempdecl, sc)) goto Lnomatch; } else - dedtypes.data[j] = cast(void*)vt; + dedtypes[j] = vt; break; //return MATCHexact; } @@ -324,12 +325,12 @@ L1: if (j == -1) goto Lnomatch; - TemplateParameter tp_ = cast(TemplateParameter)parameters.data[j]; + auto tp_ = parameters[j]; // BUG: use tp->matchArg() instead of the following TemplateValueParameter tv = tp_.isTemplateValueParameter(); if (!tv) goto Lnomatch; - Expression e = cast(Expression)dedtypes.data[j]; + Expression e = cast(Expression)dedtypes[j]; if (e) { if (!e1.equals(e)) @@ -340,7 +341,7 @@ MATCH m = cast(MATCH)e1.implicitConvTo(vt); if (!m) goto Lnomatch; - dedtypes.data[j] = cast(void*)e1; + dedtypes[j] = e1; } } else if (s1 && t2 && t2.ty == Tident) @@ -348,12 +349,12 @@ j = templateParameterLookup(t2, parameters); if (j == -1) goto Lnomatch; - TemplateParameter tp_ = cast(TemplateParameter)parameters.data[j]; + auto tp_ = parameters[j]; // BUG: use tp->matchArg() instead of the following TemplateAliasParameter ta = tp_.isTemplateAliasParameter(); if (!ta) goto Lnomatch; - Dsymbol s = cast(Dsymbol)dedtypes.data[j]; + auto s = cast(Dsymbol)dedtypes[j]; if (s) { if (!s1.equals(s)) @@ -361,7 +362,7 @@ } else { - dedtypes.data[j] = cast(void*)s1; + dedtypes[j] = s1; } } else if (s1 && s2) diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeNewArray.d --- a/dmd/TypeNewArray.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeNewArray.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeNewArray; +import dmd.common; import dmd.HdrGenState; import dmd.MOD; import dmd.OutBuffer; diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeNext.d --- a/dmd/TypeNext.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeNext.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeNext; +import dmd.common; import dmd.Type; import dmd.TypeAArray; import dmd.TY; @@ -52,6 +53,35 @@ return next.reliesOnTident(); } + override int hasWild() + { + return mod == MOD.MODwild || next.hasWild(); + } + + /*************************************** + * Return MOD bits matching argument type (targ) to wild parameter type (this). + */ + + override uint wildMatch(Type targ) + { + uint mod; + + Type tb = targ.nextOf(); + if (!tb) + return 0; + tb = tb.toBasetype(); + if (tb.isMutable()) + mod = MOD.MODmutable; + else if (tb.isConst() || tb.isWild()) + return MOD.MODconst; + else if (tb.isImmutable()) + mod = MOD.MODimmutable; + else + assert(0); + mod |= next.wildMatch(tb); + return mod; + } + override Type nextOf() { return next; @@ -69,7 +99,7 @@ TypeNext t = cast(TypeNext)super.makeConst(); if (ty != TY.Tfunction && ty != TY.Tdelegate && (next.deco || next.ty == TY.Tfunction) && - !next.isInvariant() && !next.isConst()) + !next.isImmutable() && !next.isConst()) { if (next.isShared()) t.next = next.sharedConstOf(); @@ -89,11 +119,11 @@ //printf("TypeNext::makeInvariant() %s\n", toChars()); if (ito) { - assert(ito.isInvariant()); + assert(ito.isImmutable()); return ito; } TypeNext t = cast(TypeNext)Type.makeInvariant(); - if (ty != TY.Tfunction && ty != TY.Tdelegate && (next.deco || next.ty == TY.Tfunction) && !next.isInvariant()) + if (ty != TY.Tfunction && ty != TY.Tdelegate && (next.deco || next.ty == TY.Tfunction) && !next.isImmutable()) { t.next = next.invariantOf(); } @@ -115,9 +145,9 @@ TypeNext t = cast(TypeNext)Type.makeShared(); if (ty != Tfunction && ty != Tdelegate && (next.deco || next.ty == Tfunction) && - !next.isInvariant() && !next.isShared()) + !next.isImmutable() && !next.isShared()) { - if (next.isConst()) + if (next.isConst() || next.isWild()) t.next = next.sharedConstOf(); else t.next = next.sharedOf(); @@ -141,7 +171,7 @@ TypeNext t = cast(TypeNext) Type.makeSharedConst(); if (ty != Tfunction && ty != Tdelegate && (next.deco || next.ty == Tfunction) && - !next.isInvariant() && !next.isSharedConst()) + !next.isImmutable() && !next.isSharedConst()) { t.next = next.sharedConstOf(); } @@ -153,6 +183,73 @@ return t; } + override Type makeWild() + { + //printf("TypeNext::makeWild() %s\n", toChars()); + if (wto) + { + assert(wto.mod == MODwild); + return wto; + } + auto t = cast(TypeNext)Type.makeWild(); + if (ty != TY.Tfunction && ty != TY.Tdelegate && + (next.deco || next.ty == TY.Tfunction) && + !next.isImmutable() && !next.isConst() && !next.isWild()) + { + if (next.isShared()) + t.next = next.sharedWildOf(); + else + t.next = next.wildOf(); + } + if (ty == TY.Taarray) + { + (cast(TypeAArray)t).impl = null; // lazily recompute it + } + //printf("TypeNext::makeWild() returns %p, %s\n", t, t->toChars()); + return t; + } + + Type makeSharedWild() + { + //printf("TypeNext::makeSharedWild() %s\n", toChars()); + if (swto) + { + assert(swto.isSharedWild()); + return swto; + } + auto t = cast(TypeNext)Type.makeSharedWild(); + if (ty != TY.Tfunction && ty != TY.Tdelegate && + (next.deco || next.ty == TY.Tfunction) && + !next.isImmutable() && !next.isSharedConst()) + { + t.next = next.sharedWildOf(); + } + if (ty == Taarray) + { + (cast(TypeAArray)t).impl = null; // lazily recompute it + } + //printf("TypeNext::makeSharedWild() returns %p, %s\n", t, t->toChars()); + return t; + } + + Type makeMutable() + { + //printf("TypeNext::makeMutable() %p, %s\n", this, toChars()); + auto t = cast(TypeNext)Type.makeMutable(); + if (ty != TY.Tfunction && ty != TY.Tdelegate && + (next.deco || next.ty == TY.Tfunction) && + next.isWild()) + { + t.next = next.mutableOf(); + } + if (ty == Taarray) + { + (cast(TypeAArray)t).impl = null; // lazily recompute it + } + //printf("TypeNext::makeMutable() returns %p, %s\n", t, t->toChars()); + return t; + } + override MATCH constConv(Type to) { MATCH m = Type.constConv(to); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypePointer.d --- a/dmd/TypePointer.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypePointer.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypePointer; +import dmd.common; import dmd.Type; import dmd.Loc; import dmd.Scope; @@ -107,7 +108,7 @@ TypePointer tp = cast(TypePointer)to; assert(tp.next); - if (!(next.mod == tp.next.mod || tp.next.mod == MOD.MODconst)) + if (!MODimplicitConv(next.mod, tp.next.mod)) return MATCH.MATCHnomatch; // not const-compatible /* Alloc conversion to void[] @@ -144,9 +145,7 @@ version (LOGDEFAULTINIT) { printf("TypePointer::defaultInit() '%s'\n", toChars()); } - Expression e = new NullExp(loc); - e.type = this; - return e; + return new NullExp(loc, this); } override bool isZeroInit(Loc loc) diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeQualified.d --- a/dmd/TypeQualified.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeQualified.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeQualified; +import dmd.common; import dmd.Type; import dmd.Import; import dmd.DsymbolExp; @@ -21,6 +22,7 @@ import dmd.Dsymbol; import dmd.DYNCAST; import dmd.Expression; +import dmd.FuncDeclaration; import dmd.Util; class TypeQualified : Type @@ -99,6 +101,7 @@ void resolveHelper(Loc loc, Scope sc, Dsymbol s, Dsymbol scopesym, Expression* pe, Type* pt, Dsymbol* ps) { VarDeclaration v; + FuncDeclaration fd; EnumMember em; TupleDeclaration td; Expression e; @@ -173,7 +176,7 @@ { id = cast(Identifier)idents.data[i]; //printf("e: '%s', id: '%s', type = %p\n", e.toChars(), id.toChars(), e.type); - if (id == Id.offsetof) + if (id == Id.offsetof || !e.type) { e = new DotIdExp(e.loc, e, id); e = e.semantic(sc); } @@ -194,32 +197,17 @@ v = s.isVarDeclaration(); if (v) { -///static if (false) { -/// // It's not a type, it's an expression -/// Expression *e = v.getConstInitializer(); -/// if (e) -/// { -/// *pe = e.copy(); // make copy so we can change loc -/// (*pe).loc = loc; -/// } -/// else -///} - { -///static if (false) { -/// WithScopeSymbol withsym; -/// if (scopesym && (withsym = scopesym.isWithScopeSymbol()) !is null) -/// { -/// // Same as wthis.ident -/// e = new VarExp(loc, withsym.withstate.wthis); -/// e = new DotIdExp(loc, e, ident); -/// //assert(0); // BUG: should handle this -/// } -/// else -///} - *pe = new VarExp(loc, v); - } + *pe = new VarExp(loc, v); return; } +//#if 0 +// fd = s->isFuncDeclaration(); +// if (fd) +// { +// *pe = new DsymbolExp(loc, fd, 1); +// return; +// } +//#endif em = s.isEnumMember(); if (em) { diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeReference.d --- a/dmd/TypeReference.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeReference.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeReference; +import dmd.common; import dmd.Type; import dmd.MOD; import dmd.TypeNext; @@ -9,6 +10,7 @@ import dmd.HdrGenState; import dmd.Expression; import dmd.Identifier; +import dmd.NullExp; import dmd.CppMangleState; import dmd.TY; @@ -55,7 +57,10 @@ override Expression defaultInit(Loc loc) { - assert(false); +version(LOGDEFAULTINIT) { + printf("TypeReference::defaultInit() '%s'\n", toChars()); +} + return new NullExp(loc, this); } override bool isZeroInit(Loc loc) diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeReturn.d --- a/dmd/TypeReturn.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeReturn.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeReturn; +import dmd.common; import dmd.Loc; import dmd.MOD; import dmd.Type; @@ -52,6 +53,11 @@ goto Lerr; } t = sc.func.type.nextOf(); + if (!t) + { + error(loc, "cannot use typeof(return) inside function %s with inferred return type", sc.func.toChars()); + goto Lerr; + } t = t.addMod(mod); if (idents.dim) diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeSArray.d --- a/dmd/TypeSArray.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeSArray.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,10 +1,11 @@ module dmd.TypeSArray; +import dmd.common; import dmd.TypeArray; import dmd.TypeInfoStaticArrayDeclaration; import dmd.TypeAArray; import dmd.MOD; -import dmd.Argument; +import dmd.Parameter; import dmd.TypeIdentifier; import dmd.TemplateParameter; import dmd.TemplateValueParameter; @@ -129,7 +130,7 @@ ///} ///t = cast(Type)o; - t = cast(Type)sd.objects.data[cast(size_t)d]; + t = cast(Type)sd.objects[cast(size_t)d]; if (t is null) { error(loc, "%s is not a type", toChars()); return Type.terror; @@ -195,7 +196,7 @@ case TY.Ttuple: { // Index the tuple to get the type assert(dim); - TypeTuple tt = cast(TypeTuple)tbn; + auto tt = cast(TypeTuple)tbn; ulong d = dim.toUInteger(); if (d >= tt.arguments.dim) @@ -203,7 +204,7 @@ error(loc, "tuple index %ju exceeds %u", d, tt.arguments.dim); return Type.terror; } - Argument arg = cast(Argument)tt.arguments.data[cast(size_t)d]; + auto arg = tt.arguments[cast(size_t)d]; return arg.type; } case TY.Tstruct: @@ -257,7 +258,7 @@ error(loc, "tuple index %ju exceeds %u", d, td.objects.dim); goto Ldefault; } - Object o = cast(Object)td.objects.data[cast(size_t)d]; + Object o = td.objects[cast(size_t)d]; if ((*ps = isDsymbol(o)) !is null) /// ! { return; @@ -272,11 +273,11 @@ * Do it this way because TemplateInstance.semanticTiargs() * can handle unresolved Objects this way. */ - Objects objects = new Objects; + auto objects = new Objects; objects.setDim(1); - objects.data[0] = cast(void*)o; + objects[0] = o; - TupleDeclaration tds = new TupleDeclaration(loc, td.ident, objects); + auto tds = new TupleDeclaration(loc, td.ident, objects); *ps = tds; } else @@ -332,6 +333,7 @@ { e = TypeArray.dotExp(sc, e, ident); } + e = e.semantic(sc); return e; } @@ -365,7 +367,7 @@ { TypePointer tp = cast(TypePointer)to; - if (next.mod != tp.next.mod && tp.next.mod != MODconst) + if (!MODimplicitConv(next.mod, tp.next.mod)) return MATCHnomatch; if (tp.next.ty == Tvoid || next.constConv(tp.next) != MATCHnomatch) @@ -379,11 +381,12 @@ int offset = 0; TypeDArray ta = cast(TypeDArray)to; - if (next.mod != ta.next.mod && ta.next.mod != MODconst) + if (!MODimplicitConv(next.mod, ta.next.mod)) return MATCHnomatch; if (next.equals(ta.next) || - next.implicitConvTo(ta.next) >= MATCHconst || +// next.implicitConvTo(ta.next) >= MATCHconst || + next.constConv(ta.next) != MATCHnomatch || (ta.next.isBaseOf(next, &offset) && offset == 0) || ta.next.ty == Tvoid ) @@ -507,11 +510,11 @@ // This code matches code in TypeInstance.deduceType() if (i == -1) goto Lnomatch; - TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i]; + auto tp2 = parameters[i]; TemplateValueParameter tvp = tp2.isTemplateValueParameter(); if (!tvp) goto Lnomatch; - Expression e = cast(Expression)dedtypes.data[i]; + Expression e = cast(Expression)dedtypes[i]; if (e) { if (!dim.equals(e)) @@ -523,7 +526,7 @@ MATCH m = cast(MATCH)dim.implicitConvTo(vt); if (!m) goto Lnomatch; - dedtypes.data[i] = cast(void*)dim; + dedtypes[i] = dim; } } else if (dim.toInteger() != tp.dim.toInteger()) @@ -531,10 +534,10 @@ } else if (tparam.ty == Taarray) { - TypeAArray tp = cast(TypeAArray)tparam; + auto tp = cast(TypeAArray)tparam; if (tp.index.ty == Tident) { - TypeIdentifier tident = cast(TypeIdentifier)tp.index; + auto tident = cast(TypeIdentifier)tp.index; if (tident.idents.dim == 0) { @@ -542,7 +545,7 @@ for (size_t i = 0; i < parameters.dim; i++) { - TemplateParameter tp2 = cast(TemplateParameter)parameters.data[i]; + auto tp2 = parameters[i]; if (tp2.ident.equals(id)) { @@ -551,13 +554,13 @@ if (!tvp || !tvp.valType.isintegral()) goto Lnomatch; - if (dedtypes.data[i]) + if (dedtypes[i]) { - if (!dim.equals(cast(Object)dedtypes.data[i])) + if (!dim.equals(dedtypes[i])) goto Lnomatch; } else - { dedtypes.data[i] = cast(void*)dim; + { dedtypes[i] = dim; } return next.deduceType(sc, tparam.nextOf(), parameters, dedtypes); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeSlice.d --- a/dmd/TypeSlice.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeSlice.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeSlice; +import dmd.common; import dmd.Type; import dmd.TypeNext; import dmd.MOD; @@ -13,7 +14,7 @@ import dmd.TypeTuple; import dmd.WANT; import dmd.ArrayTypes; -import dmd.Argument; +import dmd.Parameter; import dmd.SliceExp; import dmd.TupleDeclaration; import dmd.ScopeDsymbol; @@ -78,12 +79,12 @@ return Type.terror; } - Arguments args = new Arguments; + auto args = new Parameters; args.reserve(cast(size_t)(i2 - i1)); for (size_t i = cast(size_t)i1; i < cast(size_t)i2; i++) { - Argument arg = cast(Argument)tt.arguments.data[i]; - args.push(cast(void*)arg); + auto arg = tt.arguments[i]; + args.push(arg); } return new TypeTuple(args); @@ -135,14 +136,14 @@ /* Create a new TupleDeclaration which * is a slice [i1..i2] out of the old one. */ - Objects objects = new Objects; + auto objects = new Objects; objects.setDim(cast(uint)(i2 - i1)); for (size_t i = 0; i < objects.dim; i++) { - objects.data[i] = td.objects.data[cast(size_t)i1 + i]; + objects[i] = td.objects[cast(size_t)i1 + i]; } - TupleDeclaration tds = new TupleDeclaration(loc, td.ident, objects); + auto tds = new TupleDeclaration(loc, td.ident, objects); *ps = tds; } else diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeStruct.d --- a/dmd/TypeStruct.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeStruct.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeStruct; +import dmd.common; import dmd.Type; import dmd.TypeInstance; import dmd.StructDeclaration; @@ -36,6 +37,7 @@ import dmd.VarExp; import dmd.CommaExp; import dmd.ThisExp; +import dmd.StructLiteralExp; import dmd.SymbolDeclaration; import dmd.TypeInfoDeclaration; import dmd.TypeInfoStructDeclaration; @@ -217,41 +219,7 @@ L1: if (!s) { - if (ident !is Id.__sizeof && - ident !is Id.alignof_ && - ident !is Id.init_ && - ident !is Id.mangleof_ && - ident !is Id.stringof_ && - ident !is Id.offsetof) - { - /* See if we should forward to the alias this. - */ - if (sym.aliasthis) - { - /* Rewrite e.ident as: - * e.aliasthis.ident - */ - e = new DotIdExp(e.loc, e, sym.aliasthis.ident); - e = new DotIdExp(e.loc, e, ident); - return e.semantic(sc); - } - - /* Look for overloaded opDot() to see if we should forward request - * to it. - */ - Dsymbol fd = search_function(sym, Id.opDot); - if (fd) - { - /* Rewrite e.ident as: - * e.opId().ident - */ - e = build_overload(e.loc, sc, e, null, fd.ident); - e = new DotIdExp(e.loc, e, ident); - return e.semantic(sc); - } - } - - return Type.dotExp(sc, e, ident); + return noMember(sc, e, ident); } if (!s.isFuncDeclaration()) // because of overloading @@ -410,18 +378,44 @@ override Expression defaultInit(Loc loc) { - Symbol* s; - Declaration d; - version (LOGDEFAULTINIT) { printf("TypeStruct::defaultInit() '%s'\n", toChars()); } - s = sym.toInitializer(); - d = new SymbolDeclaration(sym.loc, s, sym); + Symbol *s = sym.toInitializer(); + Declaration d = new SymbolDeclaration(sym.loc, s, sym); assert(d); d.type = this; return new VarExp(sym.loc, d); } + + /*************************************** + * Use when we prefer the default initializer to be a literal, + * rather than a global immutable variable. + */ + Expression defaultInitLiteral(Loc loc) + { + version (LOGDEFAULTINIT) { + printf("TypeStruct::defaultInitLiteral() '%s'\n", toChars()); + } + auto structelems = new Expressions(); + structelems.setDim(sym.fields.dim); + for (size_t j = 0; j < structelems.dim; j++) + { + auto vd = cast(VarDeclaration)(sym.fields[j]); + Expression e; + if (vd.init) + e = vd.init.toExpression(); + else + e = vd.type.defaultInitLiteral(); + structelems[j] = e; + } + auto structinit = new StructLiteralExp(loc, cast(StructDeclaration)sym, structelems); + // Why doesn't the StructLiteralExp constructor do this, when + // sym->type != NULL ? + structinit.type = sym.type; + return structinit; + } + override bool isZeroInit(Loc loc) { @@ -436,7 +430,7 @@ for (size_t i = 0; i < sym.fields.dim; i++) { VarDeclaration v = cast(VarDeclaration)sym.fields[i]; - if (v.isConst() || v.isInvariant()) + if (v.isConst() || v.isImmutable()) return false; } return true; @@ -513,6 +507,7 @@ override bool hasPointers() { + // Probably should cache this information in sym rather than recompute StructDeclaration s = sym; sym.size(Loc(0)); // give error for forward references @@ -536,7 +531,7 @@ m = MATCHexact; // exact match if (mod != to.mod) { - if (to.mod == MODconst) + if (MODimplicitConv(mod, to.mod)) m = MATCHconst; else { /* Check all the fields. If they can all be converted, @@ -580,7 +575,8 @@ { if (equals(to)) return MATCHexact; - if (ty == to.ty && sym == (cast(TypeStruct)to).sym && to.mod == MODconst) + if (ty == to.ty && sym == (cast(TypeStruct)to).sym && + MODimplicitConv(mod, to.mod)) return MATCHconst; return MATCHnomatch; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeTuple.d --- a/dmd/TypeTuple.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeTuple.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeTuple; +import dmd.common; import dmd.Type; import dmd.ArrayTypes; import dmd.MOD; @@ -14,26 +15,25 @@ import dmd.TY; import dmd.Id; import dmd.STC; -import dmd.Argument; +import dmd.Parameter; import dmd.ErrorExp; import dmd.IntegerExp; class TypeTuple : Type { - Arguments arguments; // types making up the tuple + Parameters arguments; // types making up the tuple - this(Arguments arguments) + this(Parameters arguments) { super(TY.Ttuple); //printf("TypeTuple(this = %p)\n", this); this.arguments = arguments; - //printf("TypeTuple() %s\n", toChars()); + //printf("TypeTuple() %p, %s\n", this, toChars()); debug { if (arguments) { - for (size_t i = 0; i < arguments.dim; i++) + foreach (arg; arguments) { - Argument arg = cast(Argument)arguments.data[i]; assert(arg && arg.type); } } @@ -55,25 +55,26 @@ this(Expressions exps) { super(TY.Ttuple); - Arguments arguments = new Arguments; + auto arguments = new Parameters; if (exps) { arguments.setDim(exps.dim); for (size_t i = 0; i < exps.dim; i++) - { Expression e = cast(Expression)exps.data[i]; + { auto e = exps[i]; if (e.type.ty == Ttuple) e.error("cannot form tuple of tuples"); - Argument arg = new Argument(STCundefined, e.type, null, null); - arguments.data[i] = cast(void *)arg; + auto arg = new Parameter(STCundefined, e.type, null, null); + arguments[i] = arg; } } this.arguments = arguments; + //printf("TypeTuple() %p, %s\n", this, toChars()); } override Type syntaxCopy() { - Arguments args = Argument.arraySyntaxCopy(arguments); - Type t = new TypeTuple(args); + auto args = Parameter.arraySyntaxCopy(arguments); + auto t = new TypeTuple(args); t.mod = mod; return t; } @@ -102,13 +103,13 @@ return 1; } if (t.ty == Ttuple) - { TypeTuple tt = cast(TypeTuple)t; + { auto tt = cast(TypeTuple)t; if (arguments.dim == tt.arguments.dim) { for (size_t i = 0; i < tt.arguments.dim; i++) - { Argument arg1 = cast(Argument)arguments.data[i]; - Argument arg2 = cast(Argument)tt.arguments.data[i]; + { auto arg1 = arguments[i]; + auto arg2 = tt.arguments[i]; if (!arg1.type.equals(arg2.type)) return 0; @@ -123,10 +124,9 @@ { if (arguments) { - for (size_t i = 0; i < arguments.dim; i++) + foreach (arg; arguments) { - Argument arg = cast(Argument)arguments.data[i]; - Type t = arg.type.reliesOnTident(); + auto t = arg.type.reliesOnTident(); if (t) return t; } @@ -136,7 +136,7 @@ override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) { - Argument.argsToCBuffer(buf, hgs, arguments, 0); + Parameter.argsToCBuffer(buf, hgs, arguments, 0); } override void toDecoBuffer(OutBuffer buf, int flag) @@ -144,7 +144,7 @@ //printf("TypeTuple::toDecoBuffer() this = %p, %s\n", this, toChars()); Type.toDecoBuffer(buf, flag); OutBuffer buf2 = new OutBuffer(); - Argument.argsToDecoBuffer(buf2, arguments); + Parameter.argsToDecoBuffer(buf2, arguments); uint len = buf2.offset; //buf.printf("%d%.*s", len, len, cast(char *)buf2.extractData()); buf.printf("%d%s", len, buf2.extractString()); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeTypedef.d --- a/dmd/TypeTypedef.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeTypedef.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeTypedef; +import dmd.common; import dmd.Type; import dmd.TypedefDeclaration; import dmd.MOD; @@ -212,9 +213,6 @@ override Expression defaultInit(Loc loc) { - Expression e; - Type bt; - version (LOGDEFAULTINIT) { printf("TypeTypedef::defaultInit() '%s'\n", toChars()); } @@ -223,8 +221,8 @@ //sym->init->toExpression()->print(); return sym.init.toExpression(); } - bt = sym.basetype; - e = bt.defaultInit(loc); + Type bt = sym.basetype; + Expression e = bt.defaultInit(loc); e.type = this; while (bt.ty == Tsarray) { @@ -298,6 +296,11 @@ return toBasetype().hasPointers(); } + override int hasWild() + { + return mod & MOD.MODwild || toBasetype().hasWild(); + } + override Type toHeadMutable() { assert(false); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeTypeof.d --- a/dmd/TypeTypeof.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeTypeof.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeTypeof; +import dmd.common; import dmd.TypeFunction; import dmd.TypeQualified; import dmd.Expression; @@ -131,6 +132,7 @@ if (exp.op == TOK.TOKtype) { error(loc, "argument %s to typeof is not an expression", exp.toChars()); + goto Lerr; } t = exp.type; if (!t) @@ -139,7 +141,10 @@ goto Lerr; } if (t.ty == TY.Ttypeof) + { error(loc, "forward reference to %s", toChars()); + goto Lerr; + } /* typeof should reflect the true type, * not what 'auto' would have gotten us. diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypedefDeclaration.d --- a/dmd/TypedefDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypedefDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypedefDeclaration; +import dmd.common; import dmd.Declaration; import dmd.Initializer; import dmd.Type; @@ -70,6 +71,9 @@ sem = 1; basetype = basetype.semantic(loc, sc); sem = 2; +version(DMDV2) { + type = type.addStorageClass(storage_class); +} type = type.semantic(loc, sc); if (sc.parent.isFuncDeclaration() && init) semantic2(sc); diff -r 786ea1839396 -r 78bf0fe43974 dmd/TypeidExp.d --- a/dmd/TypeidExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/TypeidExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.TypeidExp; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.OutBuffer; @@ -7,15 +8,22 @@ import dmd.Scope; import dmd.HdrGenState; import dmd.TOK; +import dmd.Dsymbol; +import dmd.TY; +import dmd.Id; +import dmd.ErrorExp; +import dmd.DotIdExp; +import dmd.CommaExp; +import dmd.templates.Util; class TypeidExp : Expression { - Type typeidType; + Object obj; - this(Loc loc, Type typeidType) + this(Loc loc, Object o) { super(loc, TOK.TOKtypeid, TypeidExp.sizeof); - this.typeidType = typeidType; + this.obj = o; } version (DumbClone) { @@ -27,7 +35,7 @@ } override Expression syntaxCopy() { - return new TypeidExp(loc, typeidType.syntaxCopy()); + return new TypeidExp(loc, objectSyntaxCopy(obj)); } override Expression semantic(Scope sc) @@ -35,12 +43,53 @@ Expression e; version (LOGSEMANTIC) { - printf("TypeidExp.semantic()\n"); + printf("TypeidExp.semantic() %s\n", toChars()); } - typeidType = typeidType.semantic(loc, sc); - e = typeidType.getTypeInfo(sc); - if (e.loc.linnum == 0) - e.loc = loc; // so there's at least some line number info + Type ta = isType(obj); + Expression ea = isExpression(obj); + Dsymbol sa = isDsymbol(obj); + + //printf("ta %p ea %p sa %p\n", ta, ea, sa); + + if (ta) + { + ta.resolve(loc, sc, &ea, &ta, &sa); + } + + if (ea) + { + ea = ea.semantic(sc); + ea = resolveProperties(sc, ea); + ta = ea.type; + if (ea.op == TOKtype) + ea = null; + } + + if (!ta) + { + //printf("ta %p ea %p sa %p\n", ta, ea, sa); + error("no type for typeid(%s)", ea ? ea.toChars() : (sa ? sa.toChars() : "")); + return new ErrorExp(); + } + + if (ea && ta.toBasetype().ty == TY.Tclass) + { /* Get the dynamic type, which is .classinfo + */ + e = new DotIdExp(ea.loc, ea, Id.classinfo_); + e = e.semantic(sc); + } + else + { /* Get the static type + */ + e = ta.getTypeInfo(sc); + if (e.loc.linnum == 0) + e.loc = loc; // so there's at least some line number info + if (ea) + { + e = new CommaExp(loc, ea, e); // execute ea + e = e.semantic(sc); + } + } return e; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/UAddExp.d --- a/dmd/UAddExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/UAddExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,11 +1,13 @@ module dmd.UAddExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.UnaExp; import dmd.Loc; import dmd.Scope; import dmd.TOK; +import dmd.Id; class UAddExp : UnaExp { @@ -34,6 +36,6 @@ override Identifier opId() { - assert(false); + return Id.uadd; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/UnaExp.d --- a/dmd/UnaExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/UnaExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.UnaExp; +import dmd.common; import dmd.Expression; import dmd.InterState; import dmd.TY; @@ -85,6 +86,12 @@ return e1.canThrow(); } + Expression resolveLoc(Loc loc, Scope sc) + { + e1 = e1.resolveLoc(loc, sc); + return this; + } + override int inlineCost(InlineCostState* ics) { return 1 + e1.inlineCost(ics); @@ -92,7 +99,7 @@ override Expression doInline(InlineDoState ids) { - UnaExp ue = cast(UnaExp)copy(); + auto ue = cast(UnaExp)copy(); ue.e1 = e1.doInline(ids); return ue; diff -r 786ea1839396 -r 78bf0fe43974 dmd/UnionDeclaration.d --- a/dmd/UnionDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/UnionDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.UnionDeclaration; +import dmd.common; import dmd.StructDeclaration; import dmd.Loc; import dmd.Identifier; diff -r 786ea1839396 -r 78bf0fe43974 dmd/UnitTestDeclaration.d --- a/dmd/UnitTestDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/UnitTestDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.UnitTestDeclaration; +import dmd.common; import dmd.FuncDeclaration; import dmd.Loc; import dmd.Dsymbol; diff -r 786ea1839396 -r 78bf0fe43974 dmd/UnrolledLoopStatement.d --- a/dmd/UnrolledLoopStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/UnrolledLoopStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.UnrolledLoopStatement; +import dmd.common; import dmd.Expression; import dmd.Statement; import dmd.InterState; @@ -43,13 +44,11 @@ scd.sbreak = this; scd.scontinue = this; - for (size_t i = 0; i < statements.dim; i++) + foreach(ref Statement s; statements) { - Statement s = cast(Statement) statements.data[i]; if (s) { s = s.semantic(scd); - statements.data[i] = cast(void*)s; } } @@ -76,9 +75,8 @@ override BE blockExit() { BE result = BEfallthru; - for (size_t i = 0; i < statements.dim; i++) + foreach (s; statements) { - Statement s = cast(Statement) statements.data[i]; if (s) { int r = s.blockExit(); @@ -105,7 +103,18 @@ override int inlineCost(InlineCostState* ics) { - assert(false); + int cost = 0; + + foreach (Statement s; statements) + { + if (s) + { + cost += s.inlineCost(ics); + if (cost >= COST_MAX) + break; + } + } + return cost; } override Expression doInline(InlineDoState ids) @@ -115,7 +124,12 @@ override Statement inlineScan(InlineScanState* iss) { - assert(false); + foreach (ref Statement s; statements) + { + if (s) + s = s.inlineScan(iss); + } + return this; } override void toIR(IRState* irs) @@ -133,10 +147,8 @@ block* bdox; - size_t dim = statements.dim; - for (size_t i = 0 ; i < dim ; i++) + foreach (s; statements) { - Statement s = cast(Statement)statements.data[i]; if (s !is null) { mystate.contBlock = block_calloc(blx); diff -r 786ea1839396 -r 78bf0fe43974 dmd/UshrAssignExp.d --- a/dmd/UshrAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/UshrAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.UshrAssignExp; +import dmd.common; import dmd.BinExp; import dmd.Loc; import dmd.Expression; @@ -10,9 +11,13 @@ import dmd.Id; import dmd.TOK; import dmd.Type; +import dmd.ArrayLengthExp; import dmd.backend.elem; +import dmd.expression.Ushr; import dmd.expression.Util; +import dmd.backend.OPER; + class UshrAssignExp : BinExp { this(Loc loc, Expression e1, Expression e2) @@ -31,6 +36,13 @@ if (e) return e; + if (e1.op == TOK.TOKarraylength) + { + e = ArrayLengthExp.rewriteOpAssign(this); + e = e.semantic(sc); + return e; + } + e1 = e1.modifiableLvalue(sc, e1); e1.checkScalar(); e1.checkNoBool(); @@ -44,7 +56,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Ushr); } override Identifier opId() /* For operator overloading */ @@ -54,6 +66,6 @@ override elem* toElem(IRState* irs) { - assert(false); + return toElemBin(irs, OPER.OPshrass); } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/UshrExp.d --- a/dmd/UshrExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/UshrExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.UshrExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.InterState; @@ -54,7 +55,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &Ushr); } override IntRange getIntRange() @@ -74,12 +75,12 @@ override elem* toElem(IRState* irs) { - elem *eleft = e1.toElem(irs); - eleft.Ety = touns(eleft.Ety); - elem *eright = e2.toElem(irs); - elem *e = el_bin(OPshr, type.totym(), eleft, eright); - el_setLoc(e, loc); - return e; + //return toElemBin(irs, OPER.OPshr); + elem *eleft = e1.toElem(irs); + eleft.Ety = touns(eleft.Ety); + elem *eright = e2.toElem(irs); + elem *e = el_bin(OPER.OPshr, type.totym(), eleft, eright); + el_setLoc(e, loc); + return e; } -} - +} \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/Utf.d --- a/dmd/Utf.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Utf.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Utf; +import dmd.common; import dmd.Dchar; import std.utf; diff -r 786ea1839396 -r 78bf0fe43974 dmd/Util.d --- a/dmd/Util.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/Util.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.Util; +import dmd.common; import dmd.Loc; import dmd.Library; import dmd.File; @@ -13,6 +14,9 @@ import std.process : getenv; import std.c.string; import std.stdio : writef, writefln, write; + +import core.memory; + version (Windows) { import std.c.process : spawnl, spawnlp; @@ -74,7 +78,11 @@ void warning(T...)(Loc loc, string format, T t) { - assert(false); + if (global.params.warnings && !global.gag) + { + write("warning - "); + error(loc, format, t); + } } void error(T...)(Loc loc, string format, T t) @@ -94,6 +102,17 @@ global.errors++; } +T cloneThis(T)(T ptr) +{ + // similar code is used in Type.clone() + // TODO: move to Util or something... + size_t size = __traits(classInstanceSize, T); + void* mem = GC.malloc(size); + memcpy(mem, cast(void*)ptr, size); + + return cast(T)mem; +} + char* strupr(char* s) { char* t = s; @@ -367,7 +386,7 @@ for ( ; *p2; p2++) { if (islower(*p2)) *p2 &= ~0x20; - else if (isspace(*p)) + else if (isspace(*p2)) memmove(p2, p2 + 1, strlen(p2)); else if (*p2 == '=') { @@ -538,6 +557,7 @@ " -Llinkerflag pass linkerflag to link\n" " -lib generate library rather than object files\n" " -man open web browser on manual page\n" +" -noboundscheck turns off array bounds checking for all functions\n" " -nofloat do not emit reference to floating point\n" " -O optimize\n" " -o- do not write object file\n" @@ -548,7 +568,6 @@ " -quiet suppress unnecessary messages\n" " -release compile release version\n" " -run srcfile args... run resulting program, passing args\n" -" -safe safe memory model\n" " -unittest compile in unit tests\n" " -v verbose\n" " -version=level compile in version code >= level\n" @@ -616,10 +635,13 @@ precedence[TOK.TOKnew] = PREC.PREC_unary; precedence[TOK.TOKcast] = PREC.PREC_unary; + precedence[TOK.TOKpow] = PREC.PREC_pow; + precedence[TOK.TOKmul] = PREC.PREC_mul; precedence[TOK.TOKdiv] = PREC.PREC_mul; precedence[TOK.TOKmod] = PREC.PREC_mul; - + precedence[TOKpow] = PREC.PREC_mul; + precedence[TOK.TOKadd] = PREC.PREC_add; precedence[TOK.TOKmin] = PREC.PREC_add; precedence[TOK.TOKcat] = PREC.PREC_add; @@ -678,6 +700,7 @@ precedence[TOK.TOKmulass] = PREC.PREC_assign; precedence[TOK.TOKdivass] = PREC.PREC_assign; precedence[TOK.TOKmodass] = PREC.PREC_assign; + precedence[TOK.TOKpowass] = PREC.PREC_assign; precedence[TOK.TOKshlass] = PREC.PREC_assign; precedence[TOK.TOKshrass] = PREC.PREC_assign; precedence[TOK.TOKushrass] = PREC.PREC_assign; @@ -690,7 +713,8 @@ int runLINK() { -version (_WIN32) { +version (_WIN32) +{ string p; int i; int status; @@ -1045,7 +1069,7 @@ } status = executearg0(cmd, args); -version (_WIN32) { +version (Windows) { if (status == -1) { auto cmdZ = toStringz(cmd); auto argsZ = toStringz(args); @@ -1057,7 +1081,7 @@ if (status) { if (status == -1) - printf("Can't run '%s', check PATH\n", cmd); + printf("Can't run '%.*s', check PATH\n", cmd); else printf("--- errorlevel %d\n", status); } @@ -1092,7 +1116,7 @@ auto fileZ = toStringz(file); auto argsZ = toStringz(args); return spawnl(0, fileZ, fileZ, argsZ, null); -} else version (XXX) { ///#elif linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 +} else version (Posix) { ///#elif linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 assert(false); /+ char *full; diff -r 786ea1839396 -r 78bf0fe43974 dmd/VarDeclaration.d --- a/dmd/VarDeclaration.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/VarDeclaration.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.VarDeclaration; +import dmd.common; import dmd.Array; import dmd.Declaration; import dmd.SliceExp; @@ -32,7 +33,7 @@ import dmd.Initializer; import dmd.TypeStruct; import dmd.TypeTuple; -import dmd.Argument; +import dmd.Parameter; import dmd.ExpInitializer; import dmd.ArrayTypes; import dmd.Dsymbol; @@ -197,10 +198,31 @@ if (!type) { inuse++; - type = init.inferType(sc); + + ArrayInitializer ai = init.isArrayInitializer(); + if (ai) + { + Expression e; + if (ai.isAssociativeArray()) + e = ai.toAssocArrayLiteral(); + else + e = init.toExpression(); + init = new ExpInitializer(e.loc, e); + type = init.inferType(sc); + if (type.ty == TY.Tsarray) + type = type.nextOf().arrayOf(); + } + else + type = init.inferType(sc); + inuse--; inferred = 1; + if (init.isArrayInitializer() && type.toBasetype().ty == TY.Tsarray) + { // Prefer array literals to give a T[] type rather than a T[dim] + type = type.toBasetype().nextOf().arrayOf(); + } + /* This is a kludge to support the existing syntax for RAII * declarations. */ @@ -225,11 +247,18 @@ //printf("storage_class = x%x\n", storage_class); version (DMDV2) { +static if (true) { + if (storage_class & STC.STCgshared && sc.func && sc.func.isSafe()) + { + error("__gshared not allowed in safe functions; use shared"); + } +} else { if (storage_class & STC.STCgshared && global.params.safe && !sc.module_.safe) { error("__gshared not allowed in safe mode; use shared"); } } +} Dsymbol parent = toParent(); FuncDeclaration fd = parent.isFuncDeclaration(); @@ -259,15 +288,15 @@ * and add those. */ TypeTuple tt = cast(TypeTuple)tb; - size_t nelems = Argument.dim(tt.arguments); + size_t nelems = Parameter.dim(tt.arguments); Objects exps = new Objects(); exps.setDim(nelems); Expression ie = init ? init.toExpression() : null; for (size_t i = 0; i < nelems; i++) - { Argument arg = Argument.getNth(tt.arguments, i); + { auto arg = Parameter.getNth(tt.arguments, i); - OutBuffer buf = new OutBuffer(); + auto buf = new OutBuffer(); ///buf.printf("_%s_field_%zu", ident.toChars(), i); buf.printf("_%s_field_%s", ident.toChars(), i); buf.writeByte(0); @@ -276,7 +305,7 @@ Expression einit = ie; if (ie && ie.op == TOK.TOKtuple) - { einit = cast(Expression)(cast(TupleExp)ie).exps.data[i]; + { einit = (cast(TupleExp)ie).exps[i]; } Initializer ti = init; if (einit) @@ -293,10 +322,10 @@ sc.scopesym.members.push(v); } - Expression e = new DsymbolExp(loc, v); - exps.data[i] = cast(void*)e; + auto e = new DsymbolExp(loc, v); + exps[i] = e; } - TupleDeclaration v2 = new TupleDeclaration(loc, ident, exps); + auto v2 = new TupleDeclaration(loc, ident, exps); v2.isexp = 1; aliassym = v2; return; @@ -314,10 +343,12 @@ if (type.isShared()) storage_class |= STC.STCshared; } - else if (type.isInvariant()) + else if (type.isImmutable()) storage_class |= STC.STCimmutable; else if (type.isShared()) storage_class |= STC.STCshared; + else if (type.isWild()) + storage_class |= STC.STCwild; if (isSynchronized()) { @@ -393,6 +424,13 @@ { error("only parameters or foreach declarations can be ref"); } + + if ((storage_class & (STCstatic | STCextern | STCtls | STCgshared | STCmanifest) || + isDataseg()) && + type.hasWild()) + { + error("only fields, parameters or stack based variables can be inout"); + } } if (type.isauto() && !noauto) @@ -409,7 +447,7 @@ } } - if ((isConst() || isInvariant()) && !init && !fd) + if ((isConst() || isImmutable()) && !init && !fd) { // Initialize by constructor only storage_class |= STC.STCctorinit; @@ -472,7 +510,8 @@ ArrayInitializer ai = init.isArrayInitializer(); if (ai && tb.ty == TY.Taarray) { - init = ai.toAssocArrayInitializer(); + Expression e = ai.toAssocArrayLiteral(); + init = new ExpInitializer(e.loc, e); } StructInitializer si = init.isStructInitializer(); @@ -622,7 +661,7 @@ } } else if (storage_class & (STC.STCconst | STC.STCimmutable | STC.STCmanifest) || - type.isConst() || type.isInvariant() || + type.isConst() || type.isImmutable() || parent.isAggregateDeclaration()) { /* Because we may need the results of a const declaration in a @@ -765,7 +804,7 @@ { static if (false) { printf("VarDeclaration.isDataseg(%p, '%s')\n", this, toChars()); - printf("%x, %p, %p\n", storage_class & (STC.STCstatic | STC.STCconst), parent.isModule(), parent.isTemplateInstance()); + printf("%llx, isModule: %p, isTemplateInstance: %p\n", storage_class & (STC.STCstatic | STC.STCconst), parent.isModule(), parent.isTemplateInstance()); printf("parent = '%s'\n", parent.toChars()); } if (storage_class & STC.STCmanifest) @@ -800,6 +839,15 @@ } } + /******************************************** + * Can variable be read and written by CTFE? + */ + + int isCTFE() + { + return (storage_class & STCctfe) || !isDataseg(); + } + override bool hasPointers() { //printf("VarDeclaration.hasPointers() %s, ty = %d\n", toChars(), type.ty); @@ -814,7 +862,7 @@ * const int x = 3; * are not stored and hence cannot have their address taken. */ - if ((isConst() || isInvariant()) && (storage_class & STC.STCinit) && (!(storage_class & (STC.STCstatic | STC.STCextern)) || (storage_class & STC.STCfield)) && + if ((isConst() || isImmutable()) && (storage_class & STC.STCinit) && (!(storage_class & (STC.STCstatic | STC.STCextern)) || (storage_class & STC.STCfield)) && (!parent || toParent().isModule() || toParent().isTemplateInstance()) && type.toBasetype().isTypeBasic()) { return false; @@ -962,7 +1010,7 @@ */ Expression getConstInitializer() { - if ((isConst() || isInvariant() || storage_class & STC.STCmanifest) && storage_class & STC.STCinit) + if ((isConst() || isImmutable() || storage_class & STC.STCmanifest) && storage_class & STC.STCinit) { ExpInitializer ei = getExpInitializer(); if (ei) diff -r 786ea1839396 -r 78bf0fe43974 dmd/VarExp.d --- a/dmd/VarExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/VarExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.VarExp; +import dmd.common; import dmd.Expression; import dmd.Declaration; import dmd.InterState; @@ -22,8 +23,7 @@ import dmd.backend.dt_t; import dmd.expression.Util; -// Variable - +//! Variable class VarExp : SymbolExp { this(Loc loc, Declaration var, bool hasOverloads = false) @@ -70,7 +70,7 @@ if (v) { static if (false) { - if ((v.isConst() || v.isInvariant()) && type.toBasetype().ty != TY.Tsarray && v.init) + if ((v.isConst() || v.isImmutable()) && type.toBasetype().ty != TY.Tsarray && v.init) { ExpInitializer ei = v.init.isExpInitializer(); if (ei) @@ -83,8 +83,22 @@ v.checkNestedReference(sc, loc); version (DMDV2) { static if (true) { - if (sc.func) + if (sc.func && !sc.intypeof) { + /* Given: + * void f() + * { int fx; + * pure void g() + * { int gx; + * void h() + * { int hx; + * void i() { } + * } + * } + * } + * i() can modify hx and gx but not fx + */ + /* Determine if sc.func is pure or if any function that * encloses it is also pure. */ @@ -107,22 +121,28 @@ * If it is pure, it cannot access any mutable variables other * than those inside itself */ - if (hasPureParent && !sc.intypeof && v.isDataseg() && !v.isInvariant()) + if (hasPureParent && v.isDataseg() && !v.isImmutable()) { error("pure function '%s' cannot access mutable static data '%s'", sc.func.toChars(), v.toChars()); } - else if (sc.func.isPure() && sc.parent != v.parent && !sc.intypeof && !v.isInvariant() && !(v.storage_class & STC.STCmanifest)) + else if (sc.func.isPure() && sc.parent != v.parent && !v.isImmutable() && !(v.storage_class & STC.STCmanifest)) { error("pure nested function '%s' cannot access mutable data '%s'", sc.func.toChars(), v.toChars()); if (v.isEnumDeclaration()) error("enum"); - } + } + + /* Do not allow safe functions to access __gshared data + */ + if (sc.func.isSafe() && v.storage_class & STCgshared) + error("safe function '%s' cannot access __gshared data '%s'", + sc.func.toChars(), v.toChars()); } } else { if (sc.func && sc.func.isPure() && !sc.intypeof) { - if (v.isDataseg() && !v.isInvariant()) + if (v.isDataseg() && !v.isImmutable()) error("pure function '%s' cannot access mutable static data '%s'", sc.func.toChars(), v.toChars()); } } @@ -187,8 +207,19 @@ } } } + + override void checkEscapeRef() + { + VarDeclaration v = var.isVarDeclaration(); + if (v) + { + if (!v.isDataseg() && !(v.storage_class & (STCref | STCout))) + error("escaping reference to local variable %s", v.toChars()); + } + } -version (DMDV2) { +version (DMDV2) +{ override int isLvalue() { if (var.storage_class & STClazy) @@ -216,8 +247,8 @@ override Expression modifiableLvalue(Scope sc, Expression e) { //printf("VarExp::modifiableLvalue('%s')\n", var.toChars()); - if (type && type.toBasetype().ty == TY.Tsarray) - error("cannot change reference to static array '%s'", var.toChars()); + //if (type && type.toBasetype().ty == TY.Tsarray) + // error("cannot change reference to static array '%s'", var.toChars()); var.checkModify(loc, sc, type); @@ -230,6 +261,12 @@ assert(false); } + version(DMDV1) + override elem* toElem(IRState* irs) + { + assert(false); + } + override void scanForNestedRef(Scope sc) { //printf("VarExp.scanForNestedRef(%s)\n", toChars()); diff -r 786ea1839396 -r 78bf0fe43974 dmd/VersionCondition.d --- a/dmd/VersionCondition.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/VersionCondition.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.VersionCondition; +import dmd.common; import dmd.DVCondition; import dmd.Loc; import dmd.Module; diff -r 786ea1839396 -r 78bf0fe43974 dmd/VersionSymbol.d --- a/dmd/VersionSymbol.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/VersionSymbol.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.VersionSymbol; +import dmd.common; import dmd.Dsymbol; import dmd.Loc; import dmd.Identifier; @@ -12,14 +13,14 @@ import dmd.String; import dmd.OutBuffer; +/* VersionSymbol's happen for statements like: + * version = identifier; + * version = integer; + */ class VersionSymbol : Dsymbol { uint level; - /* VersionSymbol's happen for statements like: - * version = identifier; - * version = integer; - */ this(Loc loc, Identifier ident) { super(ident); @@ -36,7 +37,10 @@ override Dsymbol syntaxCopy(Dsymbol s) { - assert(false); + assert(!s); + VersionSymbol ds = new VersionSymbol(loc, ident); + ds.level = level; + return ds; } override bool addMember(Scope sc, ScopeDsymbol s, bool memnum) @@ -77,11 +81,17 @@ override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { - assert(false); + buf.writestring("version = "); + if (ident) + buf.writestring(ident.toChars()); + else + buf.printf("%u", level); + buf.writestring(";"); + buf.writenl(); } override string kind() { - assert(false); + return "version"; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/VoidInitializer.d --- a/dmd/VoidInitializer.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/VoidInitializer.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.VoidInitializer; +import dmd.common; import dmd.Initializer; import dmd.Type; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/VolatileStatement.d --- a/dmd/VolatileStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/VolatileStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.VolatileStatement; +import dmd.common; import dmd.Statement; import dmd.ArrayTypes; import dmd.Scope; @@ -14,6 +15,9 @@ import dmd.backend.Blockx; import dmd.backend.Util; import dmd.backend.BC; +import dmd.backend.elem; +import dmd.backend.OPER; +import dmd.backend.mTY; //import dmd.backend.BFL; class VolatileStatement : Statement @@ -43,12 +47,9 @@ Statements a = statement ? statement.flatten(sc) : null; if (a) { - for (int i = 0; i < a.dim; i++) + foreach (ref Statement s; a) { - Statement s = cast(Statement)a.data[i]; - s = new VolatileStatement(loc, s); - a.data[i] = cast(void*)s; } } @@ -72,6 +73,23 @@ return this; } + static void el_setVolatile(elem* e) + { + while (1) + { + e.Ety |= mTYvolatile; + if (OTunary(e.Eoper)) + e = e.E1; + else if (OTbinary(e.Eoper)) + { + el_setVolatile(e.E2); + e = e.E1; + } + else + break; + } + } + override void toIR(IRState* irs) { block* b; diff -r 786ea1839396 -r 78bf0fe43974 dmd/WhileStatement.d --- a/dmd/WhileStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/WhileStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.WhileStatement; +import dmd.common; import dmd.Statement; import dmd.Expression; import dmd.Scope; @@ -47,7 +48,7 @@ override bool hasContinue() { - assert(false); + return true; } override bool usesEH() @@ -67,7 +68,11 @@ override Expression interpret(InterState istate) { - assert(false); +version(LOG) { + printf("WhileStatement::interpret()\n"); +} + assert(false); // rewritten to ForStatement + return null; } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) diff -r 786ea1839396 -r 78bf0fe43974 dmd/WithScopeSymbol.d --- a/dmd/WithScopeSymbol.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/WithScopeSymbol.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.WithScopeSymbol; +import dmd.common; import dmd.ScopeDsymbol; import dmd.WithStatement; import dmd.Loc; @@ -12,12 +13,13 @@ this(WithStatement withstate) { - assert(false); + this.withstate = withstate; } override Dsymbol search(Loc loc, Identifier ident, int flags) { - assert(false); + // Acts as proxy to the with class declaration + return withstate.exp.type.toDsymbol(null).search(loc, ident, 0); } override WithScopeSymbol isWithScopeSymbol() { return this; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/WithStatement.d --- a/dmd/WithStatement.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/WithStatement.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,16 +1,34 @@ module dmd.WithStatement; +import dmd.common; import dmd.Statement; import dmd.Expression; import dmd.VarDeclaration; import dmd.Loc; import dmd.OutBuffer; +import dmd.ScopeDsymbol; +import dmd.TypeExp; +import dmd.TOK; +import dmd.Initializer; +import dmd.ExpInitializer; +import dmd.Id; +import dmd.ScopeExp; +import dmd.WithScopeSymbol; +import dmd.TY; +import dmd.Type; import dmd.HdrGenState; import dmd.InlineScanState; import dmd.IRState; import dmd.Scope; import dmd.BE; +import dmd.backend.Symbol; +import dmd.backend.block; +import dmd.backend.Blockx; +import dmd.backend.elem; +import dmd.backend.Util; +import dmd.backend.OPER; + class WithStatement : Statement { Expression exp; @@ -27,12 +45,74 @@ override Statement syntaxCopy() { - assert(false); + WithStatement s = new WithStatement(loc, exp.syntaxCopy(), body_ ? body_.syntaxCopy() : null); + return s; } override Statement semantic(Scope sc) { - assert(false); + ScopeDsymbol sym; + Initializer init; + + //printf("WithStatement.semantic()\n"); + exp = exp.semantic(sc); + exp = resolveProperties(sc, exp); + if (exp.op == TOKimport) + { + ScopeExp es = cast(ScopeExp)exp; + + sym = es.sds; + } + else if (exp.op == TOKtype) + { + TypeExp es = cast(TypeExp)exp; + + sym = es.type.toDsymbol(sc).isScopeDsymbol(); + if (!sym) + { + error("%s has no members", es.toChars()); + body_ = body_.semantic(sc); + return this; + } + } + else + { + Type t = exp.type; + + assert(t); + t = t.toBasetype(); + if (t.isClassHandle()) + { + init = new ExpInitializer(loc, exp); + wthis = new VarDeclaration(loc, exp.type, Id.withSym, init); + wthis.semantic(sc); + + sym = new WithScopeSymbol(this); + sym.parent = sc.scopesym; + } + else if (t.ty == Tstruct) + { + Expression e = exp.addressOf(sc); + init = new ExpInitializer(loc, e); + wthis = new VarDeclaration(loc, e.type, Id.withSym, init); + wthis.semantic(sc); + sym = new WithScopeSymbol(this); + sym.parent = sc.scopesym; + } + else + { + error("with expressions must be class objects, not '%s'", exp.type.toChars()); + return null; + } + } + sc = sc.push(sym); + + if (body_) + body_ = body_.semantic(sc); + + sc.pop(); + + return this; } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) @@ -47,7 +127,14 @@ override BE blockExit() { - assert(false); + BE result = BEnone; + if (exp.canThrow()) + result = BEthrow; + if (body_) + result |= body_.blockExit(); + else + result |= BEfallthru; + return result; } override Statement inlineScan(InlineScanState* iss) @@ -57,6 +144,34 @@ override void toIR(IRState* irs) { - assert(false); + Symbol* sp; + elem* e; + elem* ei; + ExpInitializer ie; + Blockx* blx = irs.blx; + + //printf("WithStatement.toIR()\n"); + if (exp.op == TOKimport || exp.op == TOKtype) + { + } + else + { + // Declare with handle + sp = wthis.toSymbol(); + symbol_add(sp); + + // Perform initialization of with handle + ie = wthis.init.isExpInitializer(); + assert(ie); + ei = ie.exp.toElem(irs); + e = el_var(sp); + e = el_bin(OPeq,e.Ety, e, ei); + elem_setLoc(e, loc); + incUsage(irs, loc); + block_appendexp(blx.curblock,e); + } + // Execute with block + if (body_) + body_.toIR(irs); } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/XorAssignExp.d --- a/dmd/XorAssignExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/XorAssignExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,7 @@ module dmd.XorAssignExp; +import dmd.common; +import dmd.expression.Xor; import dmd.BinExp; import dmd.Loc; import dmd.Expression; @@ -28,7 +30,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretAssignCommon(istate, &Xor); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -36,9 +38,9 @@ AssignExp_buildArrayIdent(buf, arguments, "Xor"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - assert(false); + return AssignExp_buildArrayLoop!(typeof(this))(fparams); } override Identifier opId() /* For operator overloading */ diff -r 786ea1839396 -r 78bf0fe43974 dmd/XorExp.d --- a/dmd/XorExp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/XorExp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.XorExp; +import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.InterState; @@ -47,11 +48,10 @@ else { typeCombine(sc); - if (e1.op != TOKslice && e2.op != TOKslice) - { + if (!e1.isArrayOperand()) e1.checkIntegral(); + if (!e2.isArrayOperand()) e2.checkIntegral(); - } } } return this; @@ -73,7 +73,7 @@ override Expression interpret(InterState istate) { - assert(false); + return interpretCommon(istate, &Xor); } override void buildArrayIdent(OutBuffer buf, Expressions arguments) @@ -81,14 +81,9 @@ Exp_buildArrayIdent(buf, arguments, "Xor"); } - override Expression buildArrayLoop(Arguments fparams) + override Expression buildArrayLoop(Parameters fparams) { - /* Evaluate assign expressions left to right - */ - Expression ex1 = e1.buildArrayLoop(fparams); - Expression ex2 = e2.buildArrayLoop(fparams); - Expression e = new XorExp(Loc(0), ex1, ex2); - return e; + return Exp_buildArrayLoop!(typeof(this))(fparams); } override MATCH implicitConvTo(Type t) diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/Blockx.d --- a/dmd/backend/Blockx.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/Blockx.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.Blockx; +import dmd.common; import dmd.Module; import dmd.Declaration; import dmd.ClassDeclaration; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/Classsym.d --- a/dmd/backend/Classsym.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/Classsym.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.Classsym; +import dmd.common; import dmd.backend.Symbol; alias Symbol Classsym; \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/Config.d --- a/dmd/backend/Config.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/Config.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.Config; +import dmd.common; import dmd.backend.LINKAGE; import dmd.EnumUtils; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/Configv.d --- a/dmd/backend/Configv.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/Configv.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.Configv; +import dmd.common; import dmd.backend.LANG; // Configuration that is not saved in precompiled header @@ -15,5 +16,5 @@ LANG language; // message language int errmax; // max error count } - + Configv configv; \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/Cstate.d --- a/dmd/backend/Cstate.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/Cstate.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.Cstate; +import dmd.common; import dmd.backend.Symbol; import dmd.backend.LIST; import dmd.backend.symtab_t; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/DT.d --- a/dmd/backend/DT.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/DT.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.DT; +import dmd.common; import dmd.backend.dt_t; enum DT diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/LIST.d --- a/dmd/backend/LIST.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/LIST.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.LIST; +import dmd.common; import dmd.backend.Symbol; struct LIST diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/OPER.d --- a/dmd/backend/OPER.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/OPER.d Tue Sep 14 15:46:50 2010 +0200 @@ -324,12 +324,17 @@ #define _OTboolnop 1 +/ -ubyte OTbinary(OPER op) { +ubyte OTbinary(OPER op) +{ return (optab1[op] & _OT._OTbinary); } +ubyte OTunary(OPER op) +{ + return (optab1[op] & _OT._OTunary); +} + /+ -#define OTunary(op) (optab1[op]&_OTunary) #define OTleaf(op) (!(optab1[op]&(_OTunary|_OTbinary))) #define OTcommut(op) (optab1[op]&_OTcommut) #define OTassoc(op) (optab1[op]&_OTassoc) diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/RTLSYM.d --- a/dmd/backend/RTLSYM.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/RTLSYM.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.RTLSYM; +import dmd.common; import dmd.backend.Symbol; enum RTLSYM @@ -56,6 +57,8 @@ RTLSYM_ARRAYCATNT, RTLSYM_ARRAYAPPENDT, RTLSYM_ARRAYAPPENDCT, + RTLSYM_ARRAYAPPENDCD, + RTLSYM_ARRAYAPPENDWD, RTLSYM_ARRAYSETLENGTHT, RTLSYM_ARRAYSETLENGTHIT, RTLSYM_ARRAYCOPY, diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/StringTab.d --- a/dmd/backend/StringTab.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/StringTab.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.StringTab; +import dmd.common; import dmd.Module; import dmd.backend.Symbol; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/Symbol.d --- a/dmd/backend/Symbol.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/Symbol.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.Symbol; +import dmd.common; import dmd.backend.dt_t; import dmd.backend.TYPE; import dmd.backend.LIST; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/TYFL.d --- a/dmd/backend/TYFL.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/TYFL.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.TYFL; +import dmd.common; import dmd.backend.Util; extern(C++) ubyte* get_tytab(); diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/TYPE.d --- a/dmd/backend/TYPE.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/TYPE.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.TYPE; +import dmd.common; import dmd.backend.Util; import dmd.backend.Srcpos; import dmd.backend.elem; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/Util.d --- a/dmd/backend/Util.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/Util.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.Util; +import dmd.common; import dmd.Array; import dmd.Loc; @@ -166,7 +167,7 @@ elem_p el_copytree(elem_p); int el_allbits(elem *e, int bit); block* block_goto(Blockx* bctx, BC bc, block* bn); - block* block_calloc(Blockx* blx); +// block* block_calloc(Blockx* blx); targ_size_t type_paramsize_i(type* t); int os_critsecsize(); void el_setVolatile(elem* e); @@ -174,6 +175,15 @@ elem* el_const(tym_t, eve*); elem *el_params(void** args, int length); + /**************************************** + * Allocate a new block, and set the tryblock. + */ + block *block_calloc(Blockx *blx) + { + block* b = block_calloc(); + b.Btry = blx.tryblock; + return b; + } version (SEH) { void nteh_declarvars(Blockx* bx); diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/block.d --- a/dmd/backend/block.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/block.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.block; +import dmd.common; import dmd.backend.elem; import dmd.backend.LIST; import dmd.backend.regm_t; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/code.d --- a/dmd/backend/code.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/code.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.code; +import dmd.common; import dmd.backend.targ_types; import dmd.backend.Srcpos; import dmd.backend.elem; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/con_t.d --- a/dmd/backend/con_t.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/con_t.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.con_t; +import dmd.common; import dmd.backend.cse_t; import dmd.backend.immed_t; import dmd.backend.regm_t; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/cse_t.d --- a/dmd/backend/cse_t.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/cse_t.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.cse_t; +import dmd.common; import dmd.backend.elem; import dmd.backend.regm_t; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/dt_t.d --- a/dmd/backend/dt_t.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/dt_t.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.dt_t; +import dmd.common; import dmd.backend.targ_types; import dmd.backend.Symbol; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/elem.d --- a/dmd/backend/elem.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/elem.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.elem; +import dmd.common; import dmd.Port; import dmd.Complex; @@ -11,6 +12,7 @@ import dmd.backend.TYPE; import dmd.backend.Util; import dmd.backend.Srcpos; +import dmd.backend.OPER; /********************************* * Union of all data types. Storage allocated must be the right @@ -91,8 +93,8 @@ ushort id; } - ubyte Eoper; // operator (OPxxxx) - ubyte Ecount; // # of parents of this elem - 1, + OPER Eoper; // operator (OPxxxx) + ubyte Ecount; // # of parents of this elem - 1, // always 0 until CSE elimination is done eve EV; // variants for each type of elem diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/enum_t.d --- a/dmd/backend/enum_t.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/enum_t.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.enum_t; +import dmd.common; import dmd.backend.SEN; import dmd.backend.Symbol; import dmd.backend.LIST; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/func_t.d --- a/dmd/backend/func_t.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/func_t.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.func_t; +import dmd.common; import dmd.backend.LIST; import dmd.backend.block; import dmd.backend.symtab_t; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/glue.d --- a/dmd/backend/glue.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/glue.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.glue; +import dmd.common; import dmd.Array; import dmd.Dsymbol; import dmd.File; @@ -19,12 +20,12 @@ import core.stdc.string; __gshared Array obj_symbols_towrite; +__gshared Outbuffer objbuf; version (Windows) { extern (C++) extern { - __gshared Outbuffer objbuf; int go_flag(char* cp); void util_set64(); void util_set386(); @@ -34,7 +35,6 @@ { extern (C++) { - extern(C) extern __gshared Outbuffer objbuf; int go_flag(char* cp); void util_set64(); void util_set386(); diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/iasm.d --- a/dmd/backend/iasm.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/iasm.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.iasm; +import dmd.common; import dmd.Dsymbol; import dmd.LabelDsymbol; import dmd.AsmStatement; @@ -35,6 +36,7 @@ import dmd.backend.Config; import dmd.backend.targ_types; import dmd.backend.elem; +import dmd.backend.block; import dmd.Util; import std.stdio : writef, writefln; @@ -3434,7 +3436,7 @@ error(asmstate.loc, "tuple index %u exceeds %u", index, tup.objects.dim); else { - Object o = cast(Object)tup.objects.data[index]; + Object o = tup.objects[index]; if (auto d = cast(Dsymbol)o) { o1.s = d; @@ -4339,7 +4341,7 @@ } if ((v.isConst() ///version (DMDV2) { - || v.isInvariant() || v.storage_class & STCmanifest + || v.isImmutable() || v.storage_class & STCmanifest ///} ) && !v.type.isfloating() && v.init) { @@ -4465,3 +4467,22 @@ (szReg[1] == 't' || szReg[1] == 'T')); } } + +extern(C) +{ + // backward reference from backend + + extern int refparam; + + /********************************** + * Return mask of registers used by block bp. + */ + regm_t iasm_regs(block *bp) + { + debug if (debuga) + printf("Block iasm regs = 0x%X\n", bp.usIasmregs); + + refparam |= bp.bIasmrefparam; + return bp.usIasmregs; + } +} \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/immed_t.d --- a/dmd/backend/immed_t.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/immed_t.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.immed_t; +import dmd.common; import dmd.backend.targ_types; import dmd.backend.regm_t; import dmd.backend.REGMAX; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/rel.d --- a/dmd/backend/rel.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/rel.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.rel; +import dmd.common; import dmd.backend.OPER; extern (C++) extern diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/struct_t.d --- a/dmd/backend/struct_t.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/struct_t.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.struct_t; +import dmd.common; import dmd.backend.targ_types; import dmd.backend.LIST; import dmd.backend.Symbol; diff -r 786ea1839396 -r 78bf0fe43974 dmd/backend/symtab_t.d --- a/dmd/backend/symtab_t.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/backend/symtab_t.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.backend.symtab_t; +import dmd.common; import dmd.backend.Symbol; import dmd.backend.Util; import dmd.backend.SYMIDX; diff -r 786ea1839396 -r 78bf0fe43974 dmd/codegen/Util.d --- a/dmd/codegen/Util.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/codegen/Util.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,10 +1,12 @@ module dmd.codegen.Util; +import dmd.common; import dmd.Loc; import dmd.Id; import dmd.IRState; import dmd.Type; import dmd.Array; +import dmd.Declaration; import dmd.Dsymbol; import dmd.FuncDeclaration; import dmd.Identifier; @@ -12,7 +14,7 @@ import dmd.TY; import dmd.LINK; import dmd.Expression; -import dmd.Argument; +import dmd.Parameter; import dmd.STC; import dmd.Global; import dmd.Module; @@ -53,6 +55,7 @@ import dmd.backend.RTLSYM; import dmd.backend.block; import dmd.backend.LIST; +import dmd.backend.iasm : binary; import std.string; import core.stdc.string; @@ -60,10 +63,21 @@ import core.memory; + +/* If variable var of type typ is a reference + */ +version(SARRAYVALUE) +{ + bool ISREF(Declaration var, Type tb) {return var.isOut() || var.isRef();} +} +else + bool ISREF(Declaration var, Type tb) {return (var.isParameter() && tb.ty == TY.Tsarray) || var.isOut() || var.isRef();} + + + /************************************ * Call a function. */ - elem* callfunc(Loc loc, IRState* irs, int directcall, // 1: don't do virtual call @@ -126,18 +140,16 @@ // j=1 if _arguments[] is first argument int j = (tf.linkage == LINK.LINKd && tf.varargs == 1); - for (i = 0; i < arguments.dim ; i++) + foreach (size_t i, Expression arg; arguments) { - Expression arg; elem* ea; - arg = cast(Expression)arguments.data[i]; - //printf("\targ[%d]: %s\n", i, arg.toChars()); + //writef("\targ[%d]: %s\n", i, arg.toChars()); - size_t nparams = Argument.dim(tf.parameters); + size_t nparams = Parameter.dim(tf.parameters); if (i - j < nparams && i >= j) { - Argument p = Argument.getNth(tf.parameters, i - j); + auto p = Parameter.getNth(tf.parameters, i - j); if (p.storageClass & (STC.STCout | STC.STCref)) { @@ -150,11 +162,11 @@ } ea = arg.toElem(irs); L1: - if (tybasic(ea.Ety) == TYM.TYstruct) + if (tybasic(ea.Ety) == TYM.TYstruct || tybasic(ea.Ety) == TYarray) { ea = el_una(OPER.OPstrpar, TYM.TYstruct, ea); ea.Enumbytes = ea.E1.Enumbytes; - assert(ea.Enumbytes); + //assert(ea.Enumbytes); } if (reverse) ep = el_param(ep,ea); @@ -170,10 +182,12 @@ // Don't have one, so create one type* tt; - if (tf.next.toBasetype().ty == TY.Tstruct) - tt = tf.next.toCtype(); + Type tret2 = tf.next; // in dmd tret is shadowed here, so -> tret2 + if (tret2.toBasetype().ty == Tstruct || + tret2.toBasetype().ty == Tsarray) + tt = tret2.toCtype(); else - tt = type_fake(tf.next.totym()); + tt = type_fake(tret2.totym()); Symbol* stmp = symbol_genauto(tt); ehidden = el_ptr(stmp); @@ -284,9 +298,15 @@ e = el_una(op,tyret,ep); } else if (ep) - e = el_bin(tf.ispure ? OPER.OPcallns : OPER.OPcall, tyret, ec, ep); + /* Do not do "no side effect" calls if a hidden parameter is passed, + * as the return value is stored through the hidden parameter, which + * is a side effect. + */ + e = el_bin((tf.ispure && tf.isnothrow && (retmethod != RET.RETstack)) ? + OPcallns : OPcall, tyret, ec, ep); else - e = el_una(tf.ispure ? OPER.OPucallns : OPER.OPucall, tyret, ec); + e = el_una((tf.ispure && tf.isnothrow && (retmethod != RET.RETstack)) ? + OPucallns : OPucall, tyret, ec); if (retmethod == RET.RETstack) { @@ -633,13 +653,123 @@ * Returns that operator, -1 if not an intrinsic function. */ -extern (C++) extern int intrinsic_op(char* name); - +//extern (C++) extern int intrinsic_op(char* name); + OPER intrinsic_oper(const(char)* name) { - int result = intrinsic_op(cast(char*)name); - if (result == -1) return OPER.OPMAX; - return cast(OPER)result; + version(DMDV1) + static const(char) *namearray[] = + [ + "4math3cosFeZe", + "4math3sinFeZe", + "4math4fabsFeZe", + "4math4rintFeZe", + "4math4sqrtFdZd", + "4math4sqrtFeZe", + "4math4sqrtFfZf", + "4math4yl2xFeeZe", + "4math5ldexpFeiZe", + "4math6rndtolFeZl", + "4math6yl2xp1FeeZe", + + "9intrinsic2btFPkkZi", + "9intrinsic3bsfFkZi", + "9intrinsic3bsrFkZi", + "9intrinsic3btcFPkkZi", + "9intrinsic3btrFPkkZi", + "9intrinsic3btsFPkkZi", + "9intrinsic3inpFkZh", + "9intrinsic4inplFkZk", + "9intrinsic4inpwFkZt", + "9intrinsic4outpFkhZh", + "9intrinsic5bswapFkZk", + "9intrinsic5outplFkkZk", + "9intrinsic5outpwFktZt", + ]; +else + static const(char) *namearray[] = + [ + /* The names are mangled differently because of the pure and + * nothrow attributes. + */ + "4math3cosFNaNbNfeZe", + "4math3sinFNaNbNfeZe", + "4math4fabsFNaNbNfeZe", + "4math4rintFNaNbNfeZe", + "4math4sqrtFNaNbNfdZd", + "4math4sqrtFNaNbNfeZe", + "4math4sqrtFNaNbNffZf", + "4math4yl2xFNaNbNfeeZe", + "4math5ldexpFNaNbNfeiZe", + "4math6rndtolFNaNbNfeZl", + "4math6yl2xp1FNaNbNfeeZe", + + "9intrinsic2btFNaNbxPkkZi", + "9intrinsic3bsfFNaNbkZi", + "9intrinsic3bsrFNaNbkZi", + "9intrinsic3btcFNbPkkZi", + "9intrinsic3btrFNbPkkZi", + "9intrinsic3btsFNbPkkZi", + "9intrinsic3inpFNbkZh", + "9intrinsic4inplFNbkZk", + "9intrinsic4inpwFNbkZt", + "9intrinsic4outpFNbkhZh", + "9intrinsic5bswapFNaNbkZk", + "9intrinsic5outplFNbkkZk", + "9intrinsic5outpwFNbktZt", + ]; + + static const OPER ioptab[] = + [ + OPcos, + OPsin, + OPabs, + OPrint, + OPsqrt, + OPsqrt, + OPsqrt, + OPyl2x, + OPscale, + OPrndtol, + OPyl2xp1, + + OPbt, + OPbsf, + OPbsr, + OPbtc, + OPbtr, + OPbts, + OPinp, + OPinp, + OPinp, + OPoutp, + OPbswap, + OPoutp, + OPoutp, + ]; + + debug + { + assert(namearray.length == ioptab.length); + // assume sorted namearray + for (int i = 0; i < namearray.length - 1; i++) + { + if (strcmp(namearray[i], namearray[i + 1]) >= 0) + { + printf("namearray[%d] = '%s'\n", i, namearray[i]); + assert(0); + } + } + } + + size_t length = strlen(name); + if (length < 11 || !(name[7] == 'm' || name[7] == 'i') || name[0..6] != "_D3std") + return OPMAX; + + int p = binary(name + 6, namearray.ptr, namearray.length); + if(p == -1) + return OPMAX; + return ioptab[p]; } /************************************** @@ -716,13 +846,13 @@ { for (size_t i = 0; i < td.objects.dim; i++) { - auto o = cast(Object)td.objects.data[i]; + auto o = td.objects[i]; ///if (o.dyncast() == DYNCAST_EXPRESSION) - if (Expression eo = cast(Expression)o) + if (auto eo = cast(Expression)o) { if (eo.op == TOK.TOKdsymbol) { - DsymbolExp se = cast(DsymbolExp)eo; + auto se = cast(DsymbolExp)eo; e = el_combine(e, Dsymbol_toElem(se.s, irs)); } } @@ -771,13 +901,13 @@ { elength = *pe; *pe = el_same(&elength); - elength = el_una(OPER.OP64_32, TYM.TYuint, elength); + elength = el_una(OP64_32, TYM.TYuint, elength); L3: slength = lengthVar.toSymbol(); //symbol_add(slength); - einit = el_bin(OPER.OPeq, TYM.TYuint, el_var(slength), elength); + einit = el_bin(OPeq, TYM.TYuint, el_var(slength), elength); } } return einit; @@ -792,7 +922,6 @@ * edim number of times to write evalue to eptr[] * tb type of evalue */ - elem* setArray(elem* eptr, elem* edim, Type tb, elem* evalue, IRState* irs, int op) { int r; @@ -852,7 +981,7 @@ edim = el_bin(OPER.OPmul, TYM.TYuint, edim, el_long(TYM.TYuint, sz)); } - if (tybasic(evalue.Ety) == TYM.TYstruct) + if (tybasic(evalue.Ety) == TYM.TYstruct || tybasic(evalue.Ety) == TYarray) { evalue = el_una(OPER.OPstrpar, TYM.TYstruct, evalue); evalue.Enumbytes = evalue.E1.Enumbytes; @@ -987,7 +1116,7 @@ break; case TY.Tsarray: - e = el_una(OPER.OPaddr, TYM.TYnptr, e); + e = addressElem(e, t); dim = cast(uint)(cast(TypeSArray)t).dim.toInteger(); e = el_pair(TYM.TYullong, el_long(TYM.TYint, dim), e); break; @@ -1062,12 +1191,13 @@ return el_combine(ef, e); } +/************************************ + */ elem* sarray_toDarray(Loc loc, Type tfrom, Type tto, elem* e) { //printf("sarray_toDarray()\n"); //elem_print(e); - elem* elen; uint dim = cast(uint)(cast(TypeSArray)tfrom).dim.toInteger(); if (tto) @@ -1084,8 +1214,8 @@ } L1: - elen = el_long(TYM.TYint, dim); - e = el_una(OPER.OPaddr, TYM.TYnptr, e); + elem* elen = el_long(TYM.TYint, dim); + e = addressElem(e, tfrom); e = el_pair(TYM.TYullong, elen, e); return e; } diff -r 786ea1839396 -r 78bf0fe43974 dmd/codegen/linkhelper.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/codegen/linkhelper.d Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,32 @@ +module dmd.codegen.linkhelper; + +import dmd.Loc; +import dmd.Util; + +import core.stdc.stdarg; +import std.conv; + +// help resolve some linker dependencies from the backend back into the frontend + +extern(C++) +{ + // msc.c wants to access global from out_config_init(), but it should never be called + struct Global {} + Global global; + + void error(const char *filename, uint linnum, const char *format, ...) + { + Loc loc; + loc.filename = to!string(filename); + loc.linnum = linnum; + + va_list ap; + va_start(ap, format); + + char buf[1024]; + vsprintf(buf.ptr, format, ap); + va_end( ap ); + + dmd.Util.error(loc, to!string(buf)); + } +} diff -r 786ea1839396 -r 78bf0fe43974 dmd/common.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/common.d Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,188 @@ +/** + * this module is imported in all modules in the dmd package + * and thus can be used for commonly used aliases etc. + */ +module dmd.common; + +// versions specified in a module are local to that module even if the module is imported by another one, see code at the bottom +// until a solution is found, at least check the given versions for consistency + +pragma(msg, "checking predefined versions for consistency..."); + +version(DMDV1) + version(DMDV2) + static assert(false, "DMDV1 and DMDV2 can't be set both"); + +version(DMDV2) +{ + version(STRUCTTHISREF) {} else + static assert(false, "DMDV2 requires STRUCTTHISREF. 'this' for struct is a reference"); + version(SNAN_DEFAULT_INIT) {} else + static assert(false, "DMDV2 requires SNAN_DEFAULT_INIT. floats are default initialized to signalling NaN"); + version(SARRAYVALUE) {} else + static assert(false, "DMDV2 requires SARRAYVALUE. static arrays are value types"); +} + +version(DMDV2) + version(Posix) // TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS // TODO: + version(CPP_MANGLE) {} else + static assert(false, "CPP_MANGLE must be set if DMDV2 and a Posix target is specified. C++ mangling is done by the front end"); + +version(Win32) +{ + version(_WIN32) {} else + static assert(false, "Set _WIN32 on Win32"); + version(TARGET_WINDOS) {} else + static assert(false, "TARGET_WINDOS must be specified on Windows"); + version(OMFOBJ) {} else + static assert(false, "OMFOBJ must be used on Windows"); +} +else version(Win64) +{ + static assert(false, "now we need Win64 support"); +} + +version(Posix) + version(POSIX) {} else + static assert(false, "POSIX must be set on Posix"); + +version(TARGET_LINUX) + version(ELFOBJ) {} else + static assert(false, "TARGET_LINUX requires ELFOBJ"); +version(TARGET_FREEBSD) + version(ELFOBJ) {} else + static assert(false, "TARGET_FREEBSD requires ELFOBJ"); +version(TARGET_SOLARIS) + version(ELFOBJ) {} else + static assert(false, "TARGET_SOLARIS requires ELFOBJ"); + +version(TARGET_OSX) + version(MACHOBJ) {} else + static assert(false, "TARGET_OSX requires MACHOBJ"); + +version(CCASTSYNTAX) {} else + static assert(false, `CCASTSYNTAX is needed for code like "(void*).sizeof"`); + +version(CARRAYDECL) {} else + static assert(false, "C array declarations are used in phobos so we still need CARRAYDECL"); + + +version(IN_GCC) // Changes for the GDC compiler by David Friedman +{ + static assert(false, "IN_GCC is not supported"); +} + +/+ +/* +It is very important to use version control macros correctly - the +idea is that host and target are independent. If these are done +correctly, cross compilers can be built. +The host compiler and host operating system are also different, +and are predefined by the host compiler. The ones used in +dmd are: + +Macros defined by the compiler, not the code: + + Compiler: + __DMC__ Digital Mars compiler + _MSC_VER Microsoft compiler + __GNUC__ Gnu compiler + + Host operating system: + _WIN32 Microsoft NT, Windows 95, Windows 98, Win32s, + Windows 2000, Win XP, Vista + _WIN64 Windows for AMD64 + linux Linux + __APPLE__ Mac OSX + __FreeBSD__ FreeBSD + __sun&&__SVR4 Solaris, OpenSolaris (yes, both macros are necessary) + +For the target systems, there are the target operating system and +the target object file format: + + Target operating system: + TARGET_WINDOS Covers 32 bit windows and 64 bit windows + TARGET_LINUX Covers 32 and 64 bit linux + TARGET_OSX Covers 32 and 64 bit Mac OSX + TARGET_FREEBSD Covers 32 and 64 bit FreeBSD + TARGET_SOLARIS Covers 32 and 64 bit Solaris + TARGET_NET Covers .Net + + It is expected that the compiler for each platform will be able + to generate 32 and 64 bit code from the same compiler binary. + + Target object module format: + OMFOBJ Intel Object Module Format, used on Windows + ELFOBJ Elf Object Module Format, used on linux, FreeBSD and Solaris + MACHOBJ Mach-O Object Module Format, used on Mac OSX + + There are currently no macros for byte endianness order. + */ +//version definitions from mars.h + +pragma(msg, "setting up versions..."); + +// default to DMDV2 +version(DMDV1) {} else +version = DMDV2; // Version 2.0 features +version = BREAKABI; // 0 if not ready to break the ABI just yet +version(DMDV2) +{ + version = STRUCTTHISREF; // if 'this' for struct is a reference, not a pointer + version = SNAN_DEFAULT_INIT;// if floats are default initialized to signalling NaN + version = SARRAYVALUE; // static arrays are value types +} + +// Set if C++ mangling is done by the front end +version(DMDV2) +{ + version(Posix) // TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS + version = CPP_MANGLE; +} + +/* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD and + * TARGET_SOLARIS, which are + * set on the command line via the compiler makefile. + */ + +version(Win32) +{ + version = _WIN32; + version = TARGET_WINDOS; // Windows dmd generates Windows targets + version = OMFOBJ; +} +else version(Win64) +{ + static assert(false, "now we need Win64 support"); +} + +version(Posix) + version = POSIX; + +version(TARGET_LINUX) + version = ELFOBJ; +version(TARGET_FREEBSD) + version = ELFOBJ; +version(TARGET_SOLARIS) + version = ELFOBJ; + + +version(TARGET_OSX) + version = MACHOBJ; + +/* TODO: +//Modify OutBuffer::writewchar to write the correct size of wchar +#if _WIN32 +#define writewchar writeword +#else +//This needs a configuration test... +#define writewchar write4 +#endif + +#define INTERFACE_OFFSET 0 // if 1, put classinfo as first entry +//in interface vtbl[]'s +#define INTERFACE_VIRTUAL 0 // 1 means if an interface appears +//in the inheritance graph multiple +//times, only one is used +*/ ++/ \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/condition/util/findCondition.d --- a/dmd/condition/util/findCondition.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/condition/util/findCondition.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,18 +1,19 @@ module dmd.condition.util.findCondition; +import dmd.common; import dmd.String; import dmd.Array; import dmd.Identifier; -bool findCondition(Array ids, Identifier ident) +bool findCondition(Vector!string ids, Identifier ident) { if (ids) { for (int i = 0; i < ids.dim; i++) { - String id = cast(String)ids.data[i]; + string id = ids[i]; - if (id.str == ident.toChars()) { + if (id == ident.toChars()) { return true; } } diff -r 786ea1839396 -r 78bf0fe43974 dmd/ddoc/Sections.d --- a/dmd/ddoc/Sections.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/ddoc/Sections.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.ddoc.Sections; +import dmd.common; import dmd.ddoc.DocComment; import dmd.Array; import dmd.Scope; @@ -12,10 +13,10 @@ //! class Section { - string name; - string body_; + string name; + string body_; - int nooutput; + int nooutput; void write(DocComment dc, Scope sc, Dsymbol s, OutBuffer buf) { @@ -26,7 +27,7 @@ "DEPRECATED", "EXAMPLES", "HISTORY", "LICENSE", "RETURNS", "SEE_ALSO", "STANDARDS", "THROWS", "VERSION" }; - + for (int i = 0; i < table.length; i++) { if (icmp(table[i], name, namelen) == 0) diff -r 786ea1839396 -r 78bf0fe43974 dmd/declaration/Match.d --- a/dmd/declaration/Match.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/declaration/Match.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,14 +1,15 @@ module dmd.declaration.Match; +import dmd.common; import dmd.FuncDeclaration; import dmd.MATCH; -struct Match -{ +struct Match +{ int count; // number of matches found MATCH last; // match level of lastf FuncDeclaration lastf; // last matching function we found FuncDeclaration nextf; // current matching function - FuncDeclaration anyf; // pick a func, any func, to use for error recovery -} - + FuncDeclaration anyf; // pick a func, any func, to use for error recovery +} + diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Add.d --- a/dmd/expression/Add.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Add.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Add; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/And.d --- a/dmd/expression/And.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/And.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.And; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.IntegerExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/ArrayLength.d --- a/dmd/expression/ArrayLength.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/ArrayLength.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.ArrayLength; +import dmd.common; import dmd.Type; import dmd.Expression; import dmd.StringExp; @@ -9,6 +10,17 @@ import dmd.TOK; import dmd.AssocArrayLiteralExp; import dmd.GlobalExpressions; +import dmd.XorExp; +import dmd.UshrExp; +import dmd.ShrExp; +import dmd.ShlExp; +import dmd.OrExp; +import dmd.MulExp; +import dmd.ModExp; +import dmd.MinExp; +import dmd.AddExp; +import dmd.DivExp; +import dmd.AndExp; Expression ArrayLength(Type type, Expression e1) { @@ -36,4 +48,26 @@ e = EXP_CANT_INTERPRET; return e; +} + +Expression opAssignToOp(Loc loc, TOK op, Expression e1, Expression e2) +{ + Expression e; + + switch (op) + { + case TOK.TOKaddass: e = new AddExp(loc, e1, e2); break; + case TOK.TOKminass: e = new MinExp(loc, e1, e2); break; + case TOK.TOKmulass: e = new MulExp(loc, e1, e2); break; + case TOK.TOKdivass: e = new DivExp(loc, e1, e2); break; + case TOK.TOKmodass: e = new ModExp(loc, e1, e2); break; + case TOK.TOKandass: e = new AndExp(loc, e1, e2); break; + case TOK.TOKorass: e = new OrExp (loc, e1, e2); break; + case TOK.TOKxorass: e = new XorExp(loc, e1, e2); break; + case TOK.TOKshlass: e = new ShlExp(loc, e1, e2); break; + case TOK.TOKshrass: e = new ShrExp(loc, e1, e2); break; + case TOK.TOKushrass: e = new UshrExp(loc, e1, e2); break; + default: assert(0); + } + return e; } \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Bool.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/expression/Bool.d Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,11 @@ +module dmd.expression.Bool; + +import dmd.IntegerExp; +import dmd.Loc; +import dmd.Type; +import dmd.Expression; + +Expression Bool(Type type, Expression e1) +{ + return new IntegerExp(e1.loc, e1.isBool(1), type); +} \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Cat.d --- a/dmd/expression/Cat.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Cat.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Cat; +import dmd.common; import dmd.Type; import dmd.Expression; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Cmp.d --- a/dmd/expression/Cmp.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Cmp.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Cmp; +import dmd.common; import dmd.IntegerExp; import dmd.Loc; import dmd.TOK; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Com.d --- a/dmd/expression/Com.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Com.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Com; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.IntegerExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Div.d --- a/dmd/expression/Div.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Div.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Div; +import dmd.common; import dmd.Type; import dmd.Expression; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Equal.d --- a/dmd/expression/Equal.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Equal.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Equal; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.TOK; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Identity.d --- a/dmd/expression/Identity.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Identity.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Identity; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.TOK; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Index.d --- a/dmd/expression/Index.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Index.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Index; +import dmd.common; import dmd.Type; import dmd.Loc; import dmd.StringExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Min.d --- a/dmd/expression/Min.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Min.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Min; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Mod.d --- a/dmd/expression/Mod.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Mod.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Mod; +import dmd.common; import dmd.Loc; import dmd.Type; import dmd.Expression; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Mul.d --- a/dmd/expression/Mul.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Mul.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Mul; +import dmd.common; import dmd.Type; import dmd.Expression; import dmd.RealExp; @@ -32,7 +33,7 @@ } else if (e2.type.isreal()) { - r = e2.toReal(); + r = e2.toReal(); c = e1.toComplex(); c = Complex!(real)(r * c.re, r * c.im); } diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Neg.d --- a/dmd/expression/Neg.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Neg.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Neg; +import dmd.common; import dmd.Type; import dmd.Loc; import dmd.RealExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Not.d --- a/dmd/expression/Not.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Not.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Not; +import dmd.common; import dmd.Type; import dmd.Expression; import dmd.IntegerExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Or.d --- a/dmd/expression/Or.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Or.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Or; +import dmd.common; import dmd.Type; import dmd.Expression; import dmd.IntegerExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Ptr.d --- a/dmd/expression/Ptr.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Ptr.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Ptr; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.TOK; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Shl.d --- a/dmd/expression/Shl.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Shl.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Shl; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.IntegerExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Shr.d --- a/dmd/expression/Shr.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Shr.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Shr; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Slice.d --- a/dmd/expression/Slice.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Slice.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Slice; +import dmd.common; import dmd.Expression; import dmd.Type; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Ushr.d --- a/dmd/expression/Ushr.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Ushr.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Ushr; +import dmd.common; import dmd.Type; import dmd.Expression; import dmd.Loc; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Util.d --- a/dmd/expression/Util.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Util.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Util; +import dmd.common; import dmd.Expression; import dmd.Loc; import dmd.RealExp; @@ -23,7 +24,8 @@ import dmd.IndexExp; import dmd.AssignExp; import dmd.CommaExp; -import dmd.Argument; +import dmd.CondExp; +import dmd.Parameter; import dmd.DefaultInitExp; import dmd.Identifier; import dmd.Dsymbol; @@ -62,9 +64,13 @@ import dmd.Util; import dmd.TypeAArray; import dmd.Id; +import dmd.PtrExp; +import dmd.ErrorExp; import std.stdio : writef; +import core.stdc.math; +import core.stdc.string; /*********************************** * Utility to build a function call out of this reference and argument. @@ -184,17 +190,30 @@ struct Param2 { Match* m; +version(DMDV2) { Expression ethis; + int property; // 0: unintialized + // 1: seen @property + // 2: not @property +} Expressions arguments; - int fp2(void*, FuncDeclaration f) - { + int fp2(void* param, FuncDeclaration f) + { + auto p = cast(Param2*)param; MATCH match; if (f != m.lastf) // skip duplicates { m.anyf = f; TypeFunction tf = cast(TypeFunction)f.type; + + int property = (tf.isproperty) ? 1 : 2; + if (p.property == 0) + p.property = property; + else if (p.property != property) + error(f.loc, "cannot overload both property and non-property functions"); + match = tf.callMatch(f.needThis() ? ethis : null, arguments); //printf("test: match = %d\n", match); if (match != MATCH.MATCHnomatch) @@ -212,6 +231,7 @@ else if (f.overrides(m.lastf)) goto LfIsBetter; +version(DMDV2) { /* Try to disambiguate using template-style partial ordering rules. * In essence, if f() and g() are ambiguous, if f() can call g(), * but g() cannot call f(), then pick f(). @@ -226,6 +246,7 @@ if (c1 < c2) goto LlastIsBetter; } +} Lambiguous: m.nextf = f; @@ -260,9 +281,10 @@ } version (DMDV2) { - /* Allow covariant matches, if it's just a const conversion - * of the return type - */ + /* Allow covariant matches, as long as the return type + * is just a const conversion. + * This allows things like pure functions to match with an impure function type. + */ if (t.ty == Tfunction) { TypeFunction tf = cast(TypeFunction)f.type; @@ -283,6 +305,7 @@ Param2 p; p.m = m; p.ethis = ethis; + p.property = 0; p.arguments = arguments; overloadApply(fstart, &p.fp2, &p); } @@ -324,11 +347,108 @@ } } +Expressions arrayExpressionToCommonType(Scope sc, Expressions exps, Type *pt) +{ +//version(DMDV1) { +// /* The first element sets the type +// */ +// Type *t0 = NULL; +// for (size_t i = 0; i < exps->dim; i++) +// { Expression *e = (Expression *)exps->data[i]; +// +// if (!e->type) +// { error("%s has no value", e->toChars()); +// e = new ErrorExp(); +// } +// e = resolveProperties(sc, e); +// +// if (!t0) +// t0 = e->type; +// else +// e = e->implicitCastTo(sc, t0); +// exps->data[i] = (void *)e; +// } +// +// if (!t0) +// t0 = Type::tvoid; +// if (pt) +// *pt = t0; +// +// // Eventually, we want to make this copy-on-write +// return exps; +//} +version(DMDV2) { + /* The type is determined by applying ?: to each pair. + */ + /* Still have a problem with: + * ubyte[][] = [ cast(ubyte[])"hello", [1]]; + * which works if the array literal is initialized top down with the ubyte[][] + * type, but fails with this function doing bottom up typing. + */ + //printf("arrayExpressionToCommonType()\n"); + scope integerexp = new IntegerExp(0); + scope condexp = new CondExp(Loc(0), integerexp, null, null); + + Type t0; + Expression e0; + int j0; + foreach (size_t i, Expression e; exps) + { + e = resolveProperties(sc, e); + if (!e.type) + { error("%s has no value", e.toChars()); + e = new ErrorExp(); + } + + if (t0) + { + if (t0 != e.type) + { + /* This applies ?: to merge the types. It's backwards; + * ?: should call this function to merge types. + */ + condexp.type = null; + condexp.e1 = e0; + condexp.e2 = e; + condexp.semantic(sc); + exps[j0] = condexp.e1; + e = condexp.e2; + j0 = i; + e0 = e; + t0 = e0.type; + } + } + else + { + j0 = i; + e0 = e; + t0 = e.type; + } + exps[i] = e; + } + + if (t0) + { + foreach (ref Expression e; exps) + { + e = e.implicitCastTo(sc, t0); + } + } + else + t0 = Type.tvoid; // [] is typed as void[] + if (pt) + *pt = t0; + + // Eventually, we want to make this copy-on-write + return exps; +} +} + /**************************************** * Preprocess arguments to function. */ -void preFunctionArguments(Loc loc, Scope sc, Expressions exps) +void preFunctionParameters(Loc loc, Scope sc, Expressions exps) { if (exps) { @@ -474,22 +594,24 @@ * 3. do default promotions on arguments corresponding to ... * 4. add hidden _arguments[] argument * 5. call copy constructor for struct value arguments + * Returns: + * return type from function */ -void functionArguments(Loc loc, Scope sc, TypeFunction tf, Expressions arguments) +Type functionParameters(Loc loc, Scope sc, TypeFunction tf, Expressions arguments) { - uint n; - - //printf("functionArguments()\n"); + //printf("functionParameters()\n"); assert(arguments); size_t nargs = arguments ? arguments.dim : 0; - size_t nparams = Argument.dim(tf.parameters); + size_t nparams = Parameter.dim(tf.parameters); if (nargs > nparams && tf.varargs == 0) error(loc, "expected %zu arguments, not %zu for non-variadic function type %s", nparams, nargs, tf.toChars()); - n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) + uint n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams) + uint wildmatch = 0; + int done = 0; for (size_t i = 0; i < n; i++) { @@ -504,7 +626,7 @@ if (i < nparams) { - auto p = Argument.getNth(tf.parameters, i); + auto p = Parameter.getNth(tf.parameters, i); if (!arg) { @@ -514,21 +636,13 @@ goto L2; error(loc, "expected %d function arguments, not %d", nparams, nargs); - break; + return tf.next; } arg = p.defaultArg; -version (DMDV2) { - if (arg.op == TOK.TOKdefault) - { - DefaultInitExp de = cast(DefaultInitExp)arg; - arg = de.resolve(loc, sc); - } - else - { - arg = arg.copy(); - } -} else { arg = arg.copy(); +version (DMDV2) +{ + arg = arg.resolveLoc(loc, sc); // __FILE__ and __LINE__ } arguments.push(arg); nargs++; @@ -540,7 +654,10 @@ if (arg.implicitConvTo(p.type)) { if (nargs != nparams) + { error(loc, "expected %zu function arguments, not %zu", nparams, nargs); + return tf.next; + } goto L1; } L2: @@ -565,6 +682,7 @@ Type t = new TypeSArray((cast(TypeArray)tb).next, new IntegerExp(nargs - i)); t = t.semantic(loc, sc); VarDeclaration v = new VarDeclaration(loc, t, id, new VoidInitializer(loc)); + v.storage_class |= STCctfe; v.semantic(sc); v.parent = sc.parent; //sc.insert(v); @@ -614,7 +732,7 @@ if (!arg) { error(loc, "not enough arguments"); - return; + return tf.next; } break; } @@ -631,7 +749,27 @@ if (p.type != arg.type) { //printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars()); - arg = arg.implicitCastTo(sc, p.type); + if (arg.op == TOKtype) + arg.error("cannot pass type %s as function argument", arg.toChars()); + if (p.type.isWild() && tf.next.isWild()) + { + Type t = p.type; + MATCH m = arg.implicitConvTo(t); + if (m == MATCH.MATCHnomatch) + { + t = t.constOf(); + m = arg.implicitConvTo(t); + if (m == MATCHnomatch) + { + t = t.sharedConstOf(); + m = arg.implicitConvTo(t); + } + wildmatch |= p.type.wildMatch(arg.type); + } + arg = arg.implicitCastTo(sc, t); + } + else + arg = arg.implicitCastTo(sc, p.type); arg = arg.optimize(WANT.WANTvalue); } } @@ -644,12 +782,15 @@ arg = arg.modifiableLvalue(sc, arg); } + tb = arg.type.toBasetype(); +version(SARRAYVALUE) {} else +{ // Convert static arrays to pointers - tb = arg.type.toBasetype(); if (tb.ty == TY.Tsarray) { arg = arg.checkToPointer(); } +} version (DMDV2) { if (tb.ty == TY.Tstruct && !(p.storageClass & (STC.STCref | STC.STCout))) { @@ -728,14 +869,9 @@ TypeSArray ts = cast(TypeSArray)tb; Type ta = ts.next.arrayOf(); if (ts.size(arg.loc) == 0) - { - arg = new NullExp(arg.loc); - arg.type = ta; - } + arg = new NullExp(arg.loc, ta); else - { arg = arg.castTo(sc, ta); - } } version (DMDV2) { if (tb.ty == Tstruct) @@ -769,9 +905,28 @@ // If D linkage and variadic, add _arguments[] as first argument if (tf.linkage == LINK.LINKd && tf.varargs == 1) { + assert(arguments.dim >= nparams); auto e = createTypeInfoArray(sc, &arguments[nparams], arguments.dim - nparams); arguments.insert(0, e); } + + Type tret = tf.next; + if (wildmatch) + { /* Adjust function return type based on wildmatch + */ + //printf("wildmatch = x%x\n", wildmatch); + assert(tret.isWild()); + if (wildmatch & MOD.MODconst || wildmatch & (wildmatch - 1)) + tret = tret.constOf(); + else if (wildmatch & MOD.MODimmutable) + tret = tret.invariantOf(); + else + { + assert(wildmatch & MOD.MODmutable); + tret = tret.mutableOf(); + } + } + return tret; } /****************************** @@ -945,12 +1100,12 @@ /* Create the TypeTuple corresponding to the types of args[] */ - Arguments args = new Arguments; + auto args = new Parameters; args.setDim(dim); for (size_t i = 0; i < dim; i++) { - Argument arg = new Argument(STCin, exps[i].type, null, null); - args.data[i] = cast(void*)arg; + auto arg = new Parameter(STCin, exps[i].type, null, null); + args[i] = arg; } TypeTuple tup = new TypeTuple(args); Expression e = tup.getTypeInfo(sc); @@ -1135,7 +1290,7 @@ if (!v) return e; - if (v.isConst() || v.isInvariant() || v.storage_class & STC.STCmanifest) + if (v.isConst() || v.isImmutable() || v.storage_class & STC.STCmanifest) { if (!v.type) { @@ -1265,7 +1420,7 @@ * them from the aggregate type. */ -void inferApplyArgTypes(TOK op, Arguments arguments, Expression aggr) +void inferApplyArgTypes(TOK op, Parameters arguments, Expression aggr) { if (!arguments || !arguments.dim) return; @@ -1277,14 +1432,15 @@ if (u == arguments.dim) return; - Argument arg = cast(Argument)arguments.data[u]; + auto arg = arguments[u]; if (!arg.type) break; } + Dsymbol s; AggregateDeclaration ad; - Argument arg = cast(Argument)arguments.data[0]; + auto arg = arguments[0]; Type taggr = aggr.type; if (!taggr) return; @@ -1298,7 +1454,7 @@ { if (!arg.type) arg.type = Type.tsize_t; // key type - arg = cast(Argument)arguments.data[1]; + arg = arguments[1]; } if (!arg.type && tab.ty != TY.Ttuple) arg.type = tab.nextOf(); // value type @@ -1306,13 +1462,13 @@ case TY.Taarray: { - TypeAArray taa = cast(TypeAArray)tab; + auto taa = cast(TypeAArray)tab; if (arguments.dim == 2) { if (!arg.type) arg.type = taa.index; // key type - arg = cast(Argument)arguments.data[1]; + arg = arguments[1]; } if (!arg.type) arg.type = taa.next; // value type @@ -1328,6 +1484,10 @@ goto Laggr; Laggr: + s = search_function(ad, (op == TOKforeach_reverse) ? Id.applyReverse : Id.apply); + if (s) + goto Lapply; // prefer opApply + if (arguments.dim == 1) { if (!arg.type) @@ -1335,11 +1495,11 @@ /* Look for a head() or rear() overload */ Identifier id = (op == TOK.TOKforeach) ? Id.Fhead : Id.Ftoe; - Dsymbol s = search_function(ad, id); - FuncDeclaration fd = s ? s.isFuncDeclaration() : null; + Dsymbol s1 = search_function(ad, id); + FuncDeclaration fd = s1 ? s1.isFuncDeclaration() : null; if (!fd) { - if (s && s.isTemplateDeclaration()) + if (s1 && s1.isTemplateDeclaration()) break; goto Lapply; } @@ -1353,7 +1513,6 @@ * int opApply(int delegate(ref Type [, ...]) dg); * overload */ - Dsymbol s = search_function(ad, (op == TOK.TOKforeach_reverse) ? Id.applyReverse : Id.apply); if (s) { FuncDeclaration fd = s.isFuncDeclaration(); @@ -1405,7 +1564,7 @@ int fp3(void*, FuncDeclaration f) { - TypeFunction tf = cast(TypeFunction)f.type; + auto tf = cast(TypeFunction)f.type; if (inferApplyArgTypesY(tf, arguments) == 1) return 0; @@ -1415,10 +1574,10 @@ return 0; } - Arguments arguments; + Parameters arguments; } -void inferApplyArgTypesX(FuncDeclaration fstart, Arguments arguments) +void inferApplyArgTypesX(FuncDeclaration fstart, Parameters arguments) { Param3 p3; p3.arguments = arguments; @@ -1432,15 +1591,15 @@ * 1 no match for this function */ -int inferApplyArgTypesY(TypeFunction tf, Arguments arguments) +int inferApplyArgTypesY(TypeFunction tf, Parameters arguments) { size_t nparams; - Argument p; + Parameter p; - if (Argument.dim(tf.parameters) != 1) + if (Parameter.dim(tf.parameters) != 1) goto Lnomatch; - p = Argument.getNth(tf.parameters, 0); + p = Parameter.getNth(tf.parameters, 0); if (p.type.ty != TY.Tdelegate) goto Lnomatch; @@ -1450,7 +1609,7 @@ /* We now have tf, the type of the delegate. Match it against * the arguments, filling in missing argument types. */ - nparams = Argument.dim(tf.parameters); + nparams = Parameter.dim(tf.parameters); if (nparams == 0 || tf.varargs) goto Lnomatch; // not enough parameters if (arguments.dim != nparams) @@ -1458,8 +1617,8 @@ for (size_t u = 0; u < nparams; u++) { - Argument arg = cast(Argument)arguments.data[u]; - Argument param = Argument.getNth(tf.parameters, u); + auto arg = arguments[u]; + auto param = Parameter.getNth(tf.parameters, u); if (arg.type) { if (!arg.type.equals(param.type)) @@ -1551,4 +1710,64 @@ } } } -} \ No newline at end of file +} + +void realToMangleBuffer(OutBuffer buf, real value) +{ + /* Rely on %A to get portable mangling. + * Must munge result to get only identifier characters. + * + * Possible values from %A => mangled result + * NAN => NAN + * -INF => NINF + * INF => INF + * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79 + * 0X1.9P+2 => 19P2 + */ + + if (isnan(value)) + buf.writestring("NAN"); // no -NAN bugs + else + { + char buffer[32]; + int n = sprintf(buffer.ptr, "%LA", value); + assert(n > 0 && n < buffer.sizeof); + for (int i = 0; i < n; i++) + { char c = buffer[i]; + + switch (c) + { + case '-': + buf.writeByte('N'); + break; + + case '+': + case 'X': + case '.': + break; + + case '0': + if (i < 2) + break; // skip leading 0X + default: + buf.writeByte(c); + break; + } + } + } +} + +/******************************** + * Test to see if two reals are the same. + * Regard NaN's as equivalent. + * Regard +0 and -0 as different. + */ + +int RealEquals(real x1, real x2) +{ + return (isnan(x1) && isnan(x2)) || + /* In some cases, the REALPAD bytes get garbage in them, + * so be sure and ignore them. + */ + memcmp(&x1, &x2, REALSIZE - REALPAD) == 0; +} diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/Xor.d --- a/dmd/expression/Xor.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/Xor.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.Xor; +import dmd.common; import dmd.Type; import dmd.Expression; import dmd.IntegerExp; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/shift_optimize.d --- a/dmd/expression/shift_optimize.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/shift_optimize.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.shift_optimize; +import dmd.common; import dmd.Expression; import dmd.BinExp; import dmd.Type; diff -r 786ea1839396 -r 78bf0fe43974 dmd/expression/util/arrayTypeCompatible.d --- a/dmd/expression/util/arrayTypeCompatible.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/expression/util/arrayTypeCompatible.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.expression.util.arrayTypeCompatible; +import dmd.common; import dmd.Loc; import dmd.Type; import dmd.TY; diff -r 786ea1839396 -r 78bf0fe43974 dmd/interpret/Util.d --- a/dmd/interpret/Util.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/interpret/Util.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,7 +1,9 @@ module dmd.interpret.Util; +import dmd.common; import dmd.StructDeclaration; import dmd.Expression; +import dmd.FuncDeclaration; import dmd.InterState; import dmd.ArrayTypes; import dmd.GlobalExpressions; @@ -13,76 +15,132 @@ import dmd.Loc; import dmd.ArrayLiteralExp; import dmd.TypeAArray; +import dmd.TypeFunction; import dmd.TypeSArray; +import dmd.TY; import dmd.STC; import dmd.SymbolDeclaration; import dmd.StructLiteralExp; import dmd.VarDeclaration; import dmd.Util; +version(DMDV1) +{ Expression interpret_aaLen(InterState istate, Expressions arguments) { - if (!arguments || arguments.dim != 1) + if (!arguments || arguments.dim != 1) return null; - auto earg = arguments[0]; - earg = earg.interpret(istate); - if (earg is EXP_CANT_INTERPRET) + auto earg = arguments[0]; + earg = earg.interpret(istate); + if (earg is EXP_CANT_INTERPRET) return null; - if (earg.op != TOKassocarrayliteral) + if (earg.op != TOKassocarrayliteral) return null; - auto aae = cast(AssocArrayLiteralExp)earg; - auto e = new IntegerExp(aae.loc, aae.keys.dim, Type.tsize_t); - return e; + auto aae = cast(AssocArrayLiteralExp)earg; + auto e = new IntegerExp(aae.loc, aae.keys.dim, Type.tsize_t); + return e; } Expression interpret_aaKeys(InterState istate, Expressions arguments) { version (LOG) { - printf("interpret_aaKeys()\n"); + writef("interpret_aaKeys()\n"); } - if (!arguments || arguments.dim != 2) + if (!arguments || arguments.dim != 2) return null; - auto earg = arguments[0]; - earg = earg.interpret(istate); - if (earg is EXP_CANT_INTERPRET) + auto earg = arguments[0]; + earg = earg.interpret(istate); + if (earg is EXP_CANT_INTERPRET) return null; - if (earg.op != TOKassocarrayliteral) + if (earg.op != TOKassocarrayliteral) return null; - auto aae = cast(AssocArrayLiteralExp)earg; - auto e = new ArrayLiteralExp(aae.loc, aae.keys); - Type elemType = (cast(TypeAArray)aae.type).index; - e.type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments.dim : 0)); - return e; + auto aae = cast(AssocArrayLiteralExp)earg; + auto e = new ArrayLiteralExp(aae.loc, aae.keys); + Type elemType = (cast(TypeAArray)aae.type).index; + e.type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments.dim : 0)); + return e; } Expression interpret_aaValues(InterState istate, Expressions arguments) { - //printf("interpret_aaValues()\n"); - if (!arguments || arguments.dim != 3) + //writef("interpret_aaValues()\n"); + if (!arguments || arguments.dim != 3) + return null; + auto earg = arguments[0]; + earg = earg.interpret(istate); + if (earg is EXP_CANT_INTERPRET) + return null; + if (earg.op != TOKassocarrayliteral) return null; - auto earg = arguments[0]; - earg = earg.interpret(istate); - if (earg is EXP_CANT_INTERPRET) + auto aae = cast(AssocArrayLiteralExp)earg; + auto e = new ArrayLiteralExp(aae.loc, aae.values); + Type elemType = (cast(TypeAArray)aae.type).next; + e.type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments.dim : 0)); + //writef("result is %s\n", e.toChars()); + return e; +} +} +else version(DMDV2) +{ +Expression interpret_length(InterState istate, Expression earg) +{ +// writef("interpret_length()\n"); + earg = earg.interpret(istate); + if (earg == EXP_CANT_INTERPRET) + return null; + if (earg.op != TOKassocarrayliteral) return null; - if (earg.op != TOKassocarrayliteral) + AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg; + Expression e = new IntegerExp(aae.loc, aae.keys.dim, Type.tsize_t); + return e; +} + +Expression interpret_keys(InterState istate, Expression earg, FuncDeclaration fd) +{ +version(LOG) + writef("interpret_keys()\n"); + + earg = earg.interpret(istate); + if (earg == EXP_CANT_INTERPRET) + return null; + if (earg.op != TOKassocarrayliteral) + return null; + AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg; + Expression e = new ArrayLiteralExp(aae.loc, aae.keys); + assert(fd.type.ty == Tfunction); + assert(fd.type.nextOf().ty == Tarray); + Type elemType = (cast(TypeFunction)fd.type).nextOf().nextOf(); + e.type = new TypeSArray(elemType, new IntegerExp(aae.keys.dim)); + return e; +} +Expression interpret_values(InterState istate, Expression earg, FuncDeclaration fd) +{ + //writef("interpret_values()\n"); + earg = earg.interpret(istate); + if (earg == EXP_CANT_INTERPRET) return null; - auto aae = cast(AssocArrayLiteralExp)earg; - auto e = new ArrayLiteralExp(aae.loc, aae.values); - Type elemType = (cast(TypeAArray)aae.type).next; - e.type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments.dim : 0)); - //printf("result is %s\n", e.toChars()); - return e; + if (earg.op != TOKassocarrayliteral) + return null; + AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg; + Expression e = new ArrayLiteralExp(aae.loc, aae.values); + assert(fd.type.ty == Tfunction); + assert(fd.type.nextOf().ty == Tarray); + Type elemType = (cast(TypeFunction)fd.type).nextOf().nextOf(); + e.type = new TypeSArray(elemType, new IntegerExp(aae.values.dim)); + //writef("result is %s\n", e.toChars()); + return e; +} } Expression getVarExp(Loc loc, InterState istate, Declaration d) { - Expression e = EXP_CANT_INTERPRET; - VarDeclaration v = d.isVarDeclaration(); - SymbolDeclaration s = d.isSymbolDeclaration(); - if (v) - { + Expression e = EXP_CANT_INTERPRET; + VarDeclaration v = d.isVarDeclaration(); + SymbolDeclaration s = d.isSymbolDeclaration(); + if (v) + { ///version (DMDV2) { - if ((v.isConst() || v.isInvariant() || v.storage_class & STCmanifest) && v.init && !v.value) + if ((v.isConst() || v.isImmutable() || v.storage_class & STCmanifest) && v.init && !v.value) ///} else { /// if (v.isConst() && v.init) ///} @@ -94,7 +152,7 @@ else { e = v.value; - if (v.isDataseg()) + if (v.isCTFE()) { error(loc, "static variable %s cannot be read at compile time", v.toChars()); e = EXP_CANT_INTERPRET; @@ -106,17 +164,17 @@ } if (!e) e = EXP_CANT_INTERPRET; - } - else if (s) - { + } + else if (s) + { if (s.dsym.toInitializer() == s.sym) { Expressions exps = new Expressions(); e = new StructLiteralExp(Loc(0), s.dsym, exps); e = e.semantic(null); } - } - return e; + } + return e; } /* Helper functions for BinExp.interpretAssignCommon @@ -127,16 +185,16 @@ */ Expressions changeOneElement(Expressions oldelems, size_t indexToChange, Expression newelem) { - auto expsx = new Expressions(); - expsx.setDim(oldelems.dim); - for (size_t j = 0; j < expsx.dim; j++) - { + auto expsx = new Expressions(); + expsx.setDim(oldelems.dim); + for (size_t j = 0; j < expsx.dim; j++) + { if (j == indexToChange) expsx[j] = newelem; else expsx[j] = oldelems[j]; - } - return expsx; + } + return expsx; } /*************************************** @@ -144,16 +202,16 @@ */ Expressions spliceElements(Expressions oldelems, Expressions newelems, size_t insertpoint) { - auto expsx = new Expressions(); - expsx.setDim(oldelems.dim); - for (size_t j = 0; j < expsx.dim; j++) - { + auto expsx = new Expressions(); + expsx.setDim(oldelems.dim); + for (size_t j = 0; j < expsx.dim; j++) + { if (j >= insertpoint && j < insertpoint + newelems.dim) expsx[j] = newelems[j - insertpoint]; else expsx[j] = oldelems[j]; - } - return expsx; + } + return expsx; } /****************************** @@ -161,53 +219,35 @@ */ ArrayLiteralExp createBlockDuplicatedArrayLiteral(Type type, Expression elem, size_t dim) { - auto elements = new Expressions(); - elements.setDim(dim); - for (size_t i = 0; i < dim; i++) { + auto elements = new Expressions(); + elements.setDim(dim); + for (size_t i = 0; i < dim; i++) { elements[i] = elem; } - auto ae = new ArrayLiteralExp(Loc(0), elements); - ae.type = type; - return ae; + auto ae = new ArrayLiteralExp(Loc(0), elements); + ae.type = type; + return ae; } /******************************** - * Necessary because defaultInit() for a struct is a VarExp, not a StructLiteralExp. - */ -StructLiteralExp createDefaultInitStructLiteral(Loc loc, StructDeclaration sym) -{ - Expressions structelems = new Expressions(); - structelems.setDim(sym.fields.dim); - for (size_t j = 0; j < structelems.dim; j++) - { - structelems[j] = sym.fields[j].type.defaultInit(Loc(0)); - } - StructLiteralExp structinit = new StructLiteralExp(loc, sym, structelems); - // Why doesn't the StructLiteralExp constructor do this, when - // sym.type != null ? - structinit.type = sym.type; - return structinit; -} - -/******************************** * Add v to the istate list, unless it already exists there. */ void addVarToInterstate(InterState istate, VarDeclaration v) { - if (!v.isParameter()) - { + if (!v.isParameter()) + { for (size_t i = 0; 1; i++) { if (i == istate.vars.dim) { istate.vars.push(v); - //printf("\tadding %s to istate\n", v.toChars()); + //writef("\tadding %s to istate\n", v.toChars()); break; } if (v == cast(VarDeclaration)istate.vars[i]) break; } - } + } } \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmd/templates/Util.d --- a/dmd/templates/Util.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/templates/Util.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.templates.Util; +import dmd.common; import dmd.Dsymbol; import dmd.Type; import dmd.Expression; diff -r 786ea1839396 -r 78bf0fe43974 dmd/type/Util.d --- a/dmd/type/Util.d Tue Aug 31 18:02:48 2010 +0200 +++ b/dmd/type/Util.d Tue Sep 14 15:46:50 2010 +0200 @@ -1,5 +1,6 @@ module dmd.type.Util; +import dmd.common; import dmd.TY; import dmd.Expression; import dmd.Scope; diff -r 786ea1839396 -r 78bf0fe43974 dmd2035.patch --- a/dmd2035.patch Tue Aug 31 18:02:48 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,85 +0,0 @@ -# HG changeset patch -# User trass3r -# Date 1283163123 -7200 -# Node ID 1ca9dcaadc045a9856c1c554fb2f871081df12a0 -# Parent e5248fb387cb8381af2c9ec786bd08a86d90a3a7 -fix - -diff -r e5248fb387cb -r 1ca9dcaadc04 class.c ---- a/class.c Sat Aug 28 17:24:54 2010 +0200 -+++ b/class.c Mon Aug 30 12:12:03 2010 +0200 -@@ -61,7 +61,7 @@ - if (id) - { // Look for special class names - -- if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof) -+ if (id == Id::__sizeof || id == Id::__xalignof || id == Id::mangleof) - error("illegal class name"); - - // BUG: What if this is the wrong TypeInfo, i.e. it is nested? -diff -r e5248fb387cb -r 1ca9dcaadc04 dsymbol.c ---- a/dsymbol.c Sat Aug 28 17:24:54 2010 +0200 -+++ b/dsymbol.c Mon Aug 30 12:12:03 2010 +0200 -@@ -488,7 +488,7 @@ - } - if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) - { -- if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof) -+ if (ident == Id::__sizeof || ident == Id::__xalignof || ident == Id::mangleof) - error(".%s property cannot be redefined", ident->toChars()); - } - return 1; -diff -r e5248fb387cb -r 1ca9dcaadc04 expression.c ---- a/expression.c Sat Aug 28 17:24:54 2010 +0200 -+++ b/expression.c Mon Aug 30 12:12:03 2010 +0200 -@@ -5714,7 +5714,7 @@ - } - else if (t1b->ty == Tpointer && - ident != Id::init && ident != Id::__sizeof && -- ident != Id::alignof && ident != Id::offsetof && -+ ident != Id::__xalignof && ident != Id::offsetof && - ident != Id::mangleof && ident != Id::stringof) - { /* Rewrite: - * p.ident -diff -r e5248fb387cb -r 1ca9dcaadc04 idgen.c ---- a/idgen.c Sat Aug 28 17:24:54 2010 +0200 -+++ b/idgen.c Mon Aug 30 12:12:03 2010 +0200 -@@ -45,7 +45,7 @@ - { "init" }, - { "size" }, - { "__sizeof", "sizeof" }, -- { "alignof" }, -+ { "__xalignof", "alignof" }, - { "mangleof" }, - { "stringof" }, - { "tupleof" }, -diff -r e5248fb387cb -r 1ca9dcaadc04 mtype.c ---- a/mtype.c Sat Aug 28 17:24:54 2010 +0200 -+++ b/mtype.c Mon Aug 30 12:12:03 2010 +0200 -@@ -1303,7 +1303,7 @@ - error(loc, ".size property should be replaced with .sizeof"); - e = new ErrorExp(); - } -- else if (ident == Id::alignof) -+ else if (ident == Id::__xalignof) - { - e = new IntegerExp(loc, alignsize(), Type::tsize_t); - } -@@ -5807,7 +5807,7 @@ - if (!s) - { - if (ident != Id::__sizeof && -- ident != Id::alignof && -+ ident != Id::__xalignof && - ident != Id::init && - ident != Id::mangleof && - ident != Id::stringof && -@@ -6298,7 +6298,7 @@ - { - - if (ident != Id::__sizeof && -- ident != Id::alignof && -+ ident != Id::__xalignof && - ident != Id::init && - ident != Id::mangleof && - ident != Id::stringof && diff -r 786ea1839396 -r 78bf0fe43974 dmd2036.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd2036.patch Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,98 @@ +# HG changeset patch +# User trass3r +# Date 1283292718 -7200 +# Node ID e6e22eceb1e7da03f765df9369851a6491d1b2ad +# Parent a5c1086667193606d10002efa031b316a5727450 +2.036 patch + +diff -r a5c108666719 -r e6e22eceb1e7 src/dmd/class.c +--- a/src/dmd/class.c Mon Aug 30 20:49:59 2010 +0200 ++++ b/src/dmd/class.c Wed Sep 01 00:11:58 2010 +0200 +@@ -61,7 +61,7 @@ + if (id) + { // Look for special class names + +- if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof) ++ if (id == Id::__sizeof || id == Id::_alignof || id == Id::mangleof) + error("illegal class name"); + + // BUG: What if this is the wrong TypeInfo, i.e. it is nested? +diff -r a5c108666719 -r e6e22eceb1e7 src/dmd/dsymbol.c +--- a/src/dmd/dsymbol.c Mon Aug 30 20:49:59 2010 +0200 ++++ b/src/dmd/dsymbol.c Wed Sep 01 00:11:58 2010 +0200 +@@ -488,7 +488,7 @@ + } + if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) + { +- if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof) ++ if (ident == Id::__sizeof || ident == Id::_alignof || ident == Id::mangleof) + error(".%s property cannot be redefined", ident->toChars()); + } + return 1; +diff -r a5c108666719 -r e6e22eceb1e7 src/dmd/expression.c +--- a/src/dmd/expression.c Mon Aug 30 20:49:59 2010 +0200 ++++ b/src/dmd/expression.c Wed Sep 01 00:11:58 2010 +0200 +@@ -5747,7 +5747,7 @@ + } + else if (t1b->ty == Tpointer && + ident != Id::init && ident != Id::__sizeof && +- ident != Id::alignof && ident != Id::offsetof && ++ ident != Id::_alignof && ident != Id::offsetof && + ident != Id::mangleof && ident != Id::stringof) + { /* Rewrite: + * p.ident +diff -r a5c108666719 -r e6e22eceb1e7 src/dmd/idgen.c +--- a/src/dmd/idgen.c Mon Aug 30 20:49:59 2010 +0200 ++++ b/src/dmd/idgen.c Wed Sep 01 00:11:58 2010 +0200 +@@ -45,7 +45,7 @@ + { "init" }, + { "size" }, + { "__sizeof", "sizeof" }, +- { "alignof" }, ++ { "_alignof", "alignof" }, + { "mangleof" }, + { "stringof" }, + { "tupleof" }, +diff -r a5c108666719 -r e6e22eceb1e7 src/dmd/mtype.c +--- a/src/dmd/mtype.c Mon Aug 30 20:49:59 2010 +0200 ++++ b/src/dmd/mtype.c Wed Sep 01 00:11:58 2010 +0200 +@@ -1266,7 +1266,7 @@ + error(loc, ".size property should be replaced with .sizeof"); + e = new ErrorExp(); + } +- else if (ident == Id::alignof) ++ else if (ident == Id::_alignof) + { + e = new IntegerExp(loc, alignsize(), Type::tsize_t); + } +@@ -5895,7 +5895,7 @@ + if (!s) + { + if (ident != Id::__sizeof && +- ident != Id::alignof && ++ ident != Id::_alignof && + ident != Id::init && + ident != Id::mangleof && + ident != Id::stringof && +@@ -6386,7 +6386,7 @@ + { + + if (ident != Id::__sizeof && +- ident != Id::alignof && ++ ident != Id::_alignof && + ident != Id::init && + ident != Id::mangleof && + ident != Id::stringof && +diff -r a5c108666719 -r e6e22eceb1e7 src/druntime/src/compiler/dmd/win32.mak +--- a/src/druntime/src/compiler/dmd/win32.mak Mon Aug 30 20:49:59 2010 +0200 ++++ b/src/druntime/src/compiler/dmd/win32.mak Wed Sep 01 00:11:58 2010 +0200 +@@ -163,8 +163,8 @@ + + # Patterns - asm + +-minit.obj : minit.asm +- $(CC) -c $** ++#minit.obj : minit.asm ++# $(CC) -c $** + + # Rulez \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 dmdpatch.patch --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmdpatch.patch Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,183 @@ +# HG changeset patch +# User trass3r +# Date 1284418540 -7200 +# Node ID a4ec24e030fdda493d8d1249ef966e0beed13e1e +# Parent 0ebf1721e4d32cfb38376c6688a767627aa63758 +t + +diff -r 0ebf1721e4d3 -r a4ec24e030fd src/dmd/class.c +--- a/src/dmd/class.c Mon Sep 13 15:46:31 2010 +0200 ++++ b/src/dmd/class.c Tue Sep 14 00:55:40 2010 +0200 +@@ -61,7 +61,7 @@ + if (id) + { // Look for special class names + +- if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof) ++ if (id == Id::__sizeof || id == Id::__alignof || id == Id::mangleof) + error("illegal class name"); + + // BUG: What if this is the wrong TypeInfo, i.e. it is nested? +diff -r 0ebf1721e4d3 -r a4ec24e030fd src/dmd/dsymbol.c +--- a/src/dmd/dsymbol.c Mon Sep 13 15:46:31 2010 +0200 ++++ b/src/dmd/dsymbol.c Tue Sep 14 00:55:40 2010 +0200 +@@ -488,7 +488,7 @@ + } + if (sd->isAggregateDeclaration() || sd->isEnumDeclaration()) + { +- if (ident == Id::__sizeof || ident == Id::alignof || ident == Id::mangleof) ++ if (ident == Id::__sizeof || ident == Id::__alignof || ident == Id::mangleof) + error(".%s property cannot be redefined", ident->toChars()); + } + return 1; +diff -r 0ebf1721e4d3 -r a4ec24e030fd src/dmd/expression.c +--- a/src/dmd/expression.c Mon Sep 13 15:46:31 2010 +0200 ++++ b/src/dmd/expression.c Tue Sep 14 00:55:40 2010 +0200 +@@ -5953,7 +5953,7 @@ + } + else if (t1b->ty == Tpointer && + ident != Id::init && ident != Id::__sizeof && +- ident != Id::alignof && ident != Id::offsetof && ++ ident != Id::__alignof && ident != Id::offsetof && + ident != Id::mangleof && ident != Id::stringof) + { /* Rewrite: + * p.ident +diff -r 0ebf1721e4d3 -r a4ec24e030fd src/dmd/idgen.c +--- a/src/dmd/idgen.c Mon Sep 13 15:46:31 2010 +0200 ++++ b/src/dmd/idgen.c Tue Sep 14 00:55:40 2010 +0200 +@@ -44,7 +44,7 @@ + { "init" }, + { "size" }, + { "__sizeof", "sizeof" }, +- { "alignof" }, ++ { "__alignof", "alignof" }, + { "mangleof" }, + { "stringof" }, + { "tupleof" }, +diff -r 0ebf1721e4d3 -r a4ec24e030fd src/dmd/mtype.c +--- a/src/dmd/mtype.c Mon Sep 13 15:46:31 2010 +0200 ++++ b/src/dmd/mtype.c Tue Sep 14 00:55:40 2010 +0200 +@@ -1610,7 +1610,7 @@ + error(loc, ".size property should be replaced with .sizeof"); + e = new ErrorExp(); + } +- else if (ident == Id::alignof) ++ else if (ident == Id::__alignof) + { + e = new IntegerExp(loc, alignsize(), Type::tsize_t); + } +@@ -1749,7 +1749,7 @@ + assert(sym); + + if (ident != Id::__sizeof && +- ident != Id::alignof && ++ ident != Id::__alignof && + ident != Id::init && + ident != Id::mangleof && + ident != Id::stringof && +diff -r 0ebf1721e4d3 -r a4ec24e030fd src/dmd/win32.mak +--- a/src/dmd/win32.mak Mon Sep 13 15:46:31 2010 +0200 ++++ b/src/dmd/win32.mak Tue Sep 14 00:55:40 2010 +0200 +@@ -8,7 +8,8 @@ + DMDSVN=\svnproj\dmd\trunk\src + SCROOT=$D\dm + INCLUDE=$(SCROOT)\include +-CC=\dm\bin\dmc ++CC=$(SCROOT)\bin\dmc ++LIB=$(SCROOT)\bin\lib + LIBNT=$(SCROOT)\lib + SNN=$(SCROOT)\lib\snn + DIR=\dmd2 +@@ -24,7 +25,7 @@ + XFLG= + MODEL=n + OPT= +-DEBUG=-gl -D ++DEBUG=-g -D + #PREC=-H -HItotal.h -HO + PREC= + LFLAGS= +@@ -59,11 +60,17 @@ + $(MAKE) OPT=-o "DEBUG=" LFLAGS=-L/delexe dmd.exe + # $(MAKE) OPT=-o "DEBUG=" LFLAGS=-L/ma/co/delexe dmd.exe + ++lib: ++ $(MAKE) OPT=-o "DEBUG=" dmd.lib ++ + ################ NT COMMAND LINE DEBUG ######################### + + debdmd: + $(MAKE) OPT= "DEBUG=-D -g" LFLAGS=-L/ma/co dmd.exe + ++deblib: ++ $(MAKE) OPT= "DEBUG=-D -g" dmd.lib ++ + ######################################### + + # D front end +@@ -155,8 +162,11 @@ + ######################################### + + $(TARGET).exe : $(OBJS) win32.mak +- dmc -o$(TARGET).exe $(OBJS) -cpp -mn -Ar $(LFLAGS) ++ $(CC) -o$(TARGET).exe $(OBJS) -cpp -mn -Ar $(LFLAGS) + ++$(TARGET).lib : $(OBJS) win32.mak ++ $(LIB) -c -p128 $(TARGET).lib $(OBJ8) $(ROOTOBJS) msc.obj tk.obj util.obj entity.obj ph.obj eh.obj ++ $(LIB) -d $(TARGET).lib iasm.obj + + ##################### INCLUDE MACROS ##################### + +@@ -171,11 +181,11 @@ + msgsx + + msgsx.exe : msgsx.c +- dmc msgsx -mn -D$(TARGET) $(DEFINES) $(WINLIBS) ++ $(CC) msgsx -mn -D$(TARGET) $(DEFINES) $(WINLIBS) + + elxxx.c cdxxx.c optab.c debtab.c fltables.c tytab.c : \ + $C\cdef.h $C\cc.h $C\oper.h $C\ty.h $C\optabgen.c +- dmc -cpp -ooptabgen.exe $C\optabgen -DMARS -I$(TK) $(WINLIBS) #-L$(LINKS) ++ $(CC) -cpp -ooptabgen.exe $C\optabgen -DMARS -I$(TK) $(WINLIBS) #-L$(LINKS) + optabgen + + impcnvtab.c : impcnvgen.c +@@ -183,7 +193,7 @@ + impcnvgen + + id.h id.c : idgen.c +- dmc -cpp idgen ++ $(CC) -cpp idgen + idgen + + ##################### SPECIAL BUILDS ##################### +diff -r 0ebf1721e4d3 -r a4ec24e030fd src/druntime/win32.mak +--- a/src/druntime/win32.mak Mon Sep 13 15:46:31 2010 +0200 ++++ b/src/druntime/win32.mak Tue Sep 14 00:55:40 2010 +0200 +@@ -1,5 +1,5 @@ + +-DMD=dmd ++DMD=..\..\windows\bin\dmd + + CC=dmc + +@@ -300,7 +300,7 @@ + # NOTE: a pre-compiled minit.obj has been provided in dmd for Win32 and + # minit.asm is not used by dmd for Linux + +-OBJS= errno_c.obj complex.obj critical.obj deh.obj monitor.obj src\rt\minit.obj ++OBJS= errno_c.obj complex.obj critical.obj deh.obj monitor.obj minit.obj + OBJS_TO_DELETE= errno_c.obj complex.obj critical.obj deh.obj monitor.obj + + DOCS=\ +diff -r 0ebf1721e4d3 -r a4ec24e030fd src/phobos/win32.mak +--- a/src/phobos/win32.mak Mon Sep 13 15:46:31 2010 +0200 ++++ b/src/phobos/win32.mak Tue Sep 14 00:55:40 2010 +0200 +@@ -51,7 +51,7 @@ + + DMD=$(DIR)\bin\dmd + #DMD=..\dmd +-DMD=dmd ++DMD=..\..\windows\bin\dmd + + ## Location of where to write the html documentation files + diff -r 786ea1839396 -r 78bf0fe43974 main.d --- a/main.d Tue Aug 31 18:02:48 2010 +0200 +++ b/main.d Tue Sep 14 15:46:50 2010 +0200 @@ -214,6 +214,7 @@ int status = ExitCode.EXIT_SUCCESS; int argcstart = args.length; int setdebuglib = 0; + byte noboundscheck = 0; global = new Global(); @@ -229,7 +230,7 @@ global.params.useInvariants = 1; global.params.useIn = 1; global.params.useOut = 1; - global.params.useArrayBounds = 1; + global.params.useArrayBounds = 2; // default to all functions global.params.useSwitchError = 1; global.params.useInline = 0; global.params.obj = 1; @@ -290,12 +291,17 @@ } VersionCondition.addPredefinedGlobalIdent("all"); -version (_WIN32) { - inifile(args[0], "sc.ini"); -} else version (POSIX) {///linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 - inifile(args[0], "dmd.conf"); -} else { - static assert (false, "fix this"); +version (Windows) +{ + inifile(args[0], "sc.ini"); +} + else version (Posix) ///linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4 +{ + inifile(args[0], "dmd.conf"); +} +else +{ + static assert (false, "fix this"); } args = getenv_setargv("DFLAGS", args); @@ -472,8 +478,8 @@ else if (arg == "release") global.params.release = 1; ///version (DMDV2) { - else if (arg == "safe") - global.params.safe = 1; + else if (arg == "noboundscheck") + noboundscheck = 1; ///} else if (arg == "unittest") global.params.useUnitTests = 1; @@ -578,7 +584,7 @@ } else if (memcmp(p + 1, "man".ptr, 3) == 0) { -version (_WIN32) { +version (Windows) { version (DMDV1) { browse("http://www.digitalmars.com/d/1.0/dmd-windows.html"); } else { @@ -664,14 +670,18 @@ } if (global.params.release) - { global.params.useInvariants = 0; + { + global.params.useInvariants = 0; global.params.useIn = 0; global.params.useOut = 0; global.params.useAssert = 0; global.params.useArrayBounds = 0; global.params.useSwitchError = 0; } - + + if (noboundscheck) + global.params.useArrayBounds = 0; + if (global.params.run) global.params.quiet = 1; @@ -800,7 +810,7 @@ String s = cast(String) files.data[i]; string mp = s.str; -version (_WIN32) { +version (Windows) { char[] copy = null; // Convert / to \ so linker will work foreach (j, c; mp) diff -r 786ea1839396 -r 78bf0fe43974 test.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test.d Tue Sep 14 15:46:50 2010 +0200 @@ -0,0 +1,253 @@ +import std.stdio; +import std.utf; +import std.file; +import std.path; +import std.algorithm; +import std.string; +import std.process; +import core.stdc.ctype; +import std.c.windows.windows; + +string compiler = "dmd"; + +class Test +{ + enum EXTRA_SOURCES = "EXTRA_SOURCES"; + enum COMPILE_SEPARATELY = "COMPILE_SEPARATELY"; + enum PERMUTE_ARGS = "PERMUTE_ARGS"; + enum REQUIRED_ARGS = "REQUIRED_ARGS"; + enum POST_SCRIPT = "POST_SCRIPT"; + enum EXECUTE_ARGS = "EXECUTE_ARGS"; + + this(string path, string outputDir) + { + this.outputDir = outputDir; + this.baseDir = dirname(path); + + this.baseName = getBaseName(path); + this.name = getName(baseName); + + this.fileNames ~= baseName; + + auto file = File(path); + while (true) { + auto line = file.readln(); + if (!line.startsWith("// ")) { + break; + } + + line = trim(line[3..$]); + if (line.startsWith(EXTRA_SOURCES)) { + fileNames ~= split(line[EXTRA_SOURCES.length + 2..$], " "); + } else if (line.startsWith(COMPILE_SEPARATELY)) { + compileSeparately = true; + } else if (line.startsWith(EXECUTE_ARGS)) { + executeArgs = line[EXECUTE_ARGS.length + 2..$]; + } else if (line.startsWith(PERMUTE_ARGS)) { + // ignore for now + } else if (line.startsWith(REQUIRED_ARGS)) { + requiredArgs = line[REQUIRED_ARGS.length + 2..$]; + } else if (line.startsWith(POST_SCRIPT)) { + // ignore for now + } else { + continue; + } + } + } + + private string prefix() + { + return std.string.format(compiler ~ " -od%s -I%s %s", outputDir, baseDir, requiredArgs); + } + + private string csuffix(string fileName) + { + // output to console + return ""; //std.string.format(" > %s\\%s.clog", outputDir, getBaseName(fileName)); + } + + private string lsuffix(string fileName) + { + return std.string.format(" > %s\\%s.llog", outputDir, getBaseName(fileName)); + } + + private string output() + { + return std.string.format(" -of%s\\%s.exe", outputDir, name); + } + + private void execute(string command) + { + system(command); + } + + void compile() + { + if (compileSeparately) { + string link_command = compiler ~ output(); + foreach (fileName; fileNames) { + string compile_command = prefix(); + + compile_command ~= std.string.format(" %s\\%s -c", baseDir, fileName); + compile_command ~= csuffix(fileName); + + execute(compile_command); + link_command ~= std.string.format(" %s\\%s.obj", outputDir, getName(getBaseName(fileName))); + } + + link_command ~= lsuffix(baseName); + + execute(link_command); + } else { + string compile_command = prefix(); + foreach (fileName; fileNames) { + compile_command ~= std.string.format(" %s\\%s", baseDir, fileName); + } + + compile_command ~= output(); + compile_command ~= csuffix(baseName); + + execute(compile_command); + } + } + + private string[] fileNames; + + private string name; + private string baseName; + private string outputDir; + private string baseDir; + private string requiredArgs; + private string executeArgs; + + private bool compileSeparately = false; +} + +class RunnableTest : Test +{ + this(string path, string outputDir) + { + super(path, outputDir); + } + + void run() + { + string run_command = std.string.format("%s\\%s.exe %s > %s\\%s.exe.rlog", outputDir, name, executeArgs, outputDir, name); + execute(run_command); + } +} + +int main(string[] args) +{ + auto runnable_tests = wildcard("runnable/*.d"/*, "runnable/*.html", "runnable/*.sh"*/); + auto runnable_test_results = map!q{"result/" ~ a ~ ".out"}(runnable_tests); + + auto outputDir = "result"; + + if (args.length >= 2) { + compiler = args[1]; + } else { + // compiler = "dmd"; // value by default + } + + foreach (fileName; runnable_tests) { + //fileName = "runnable\\a18.d"; + writeln("testing ", fileName); + auto test = new RunnableTest(fileName, outputDir); + test.compile(); +// test.run(); +// break; + } + + return 0; +} + +string[] wildcard(string[] paths...) +{ + string[] fileNames; + + foreach (path; paths) { + filter(path, (string fileName) { fileNames ~= fileName; return true; }); + } + + return fileNames; +} + +string trimLeft(string s) +{ + for (int i = 0; i < s.length; ++i) { + if (!isspace(s[i])) { + return s[i..$]; + } + } + + return null; +} + +string trimRight(string s) +{ + for (int i = s.length - 1; i >= 0; --i) { + if (!isspace(s[i])) { + return s[0..i + 1]; + } + } + + return null; +} + +string trim(string s) +{ + return trimLeft(trimRight(s)); +} + +version(Windows) void filter(string pattern, bool delegate(string fileName) callback) +{ + WIN32_FIND_DATAW fileinfo; + + auto h = FindFirstFileW(std.utf.toUTF16z(pattern), &fileinfo); + if (h == INVALID_HANDLE_VALUE) + return; + + auto path = dirname(pattern); + + do + { + // Skip "." and ".." + auto name = fileinfo.cFileName.ptr; + if (name[0] == '.' && (name[1] == 0 || name[1] == '.')) + continue; + + size_t clength = std.string.wcslen(fileinfo.cFileName.ptr); + auto fileName = std.path.join(path, std.utf.toUTF8(fileinfo.cFileName[0 .. clength])); + + if (!callback(fileName)) { + break; + } + } while (FindNextFileW(h, &fileinfo) != FALSE); + + FindClose(h); +} + +string getBaseName(string fullname, string extension = null) +{ + auto i = fullname.length; + for (; i > 0; i--) + { + version(Windows) + { + if (fullname[i - 1] == ':' || fullname[i - 1] == '\\' || fullname[i - 1] == '/') + break; + } + else version(Posix) + { + if (fullname[i - 1] == '/') + break; + } + else + { + static assert(0); + } + } + return chomp(fullname[i .. fullname.length], + extension.length ? extension : ""); +} \ No newline at end of file diff -r 786ea1839396 -r 78bf0fe43974 win32_lib.mak --- a/win32_lib.mak Tue Aug 31 18:02:48 2010 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,518 +0,0 @@ -#_ win32_lib.mak -# Copyright (C) 1999-2009 by Digital Mars, http://www.digitalmars.com -# Written by Walter Bright -# All Rights Reserved -# Build dmd with Digital Mars C++ compiler - -D= -DMDSVN=\svnproj\dmd\trunk\src -SCROOT=$D\dm -INCLUDE=$(SCROOT)\include -CC=\dm\bin\dmc -LIBNT=$(SCROOT)\lib -SNN=$(SCROOT)\lib\snn -DIR=\dmd2 -CP=cp - -C=backend -TK=tk -ROOT=root - -MAKE=make -fwin32_lib.mak C=$C TK=$(TK) ROOT=$(ROOT) - -TARGET=dmd -XFLG= -MODEL=n -OPT= -DEBUG=-gl -D -#PREC=-H -HItotal.h -HO -PREC= -LFLAGS= - -LINKN=$(SCROOT)\bin\link /de - -CFLAGS=-I$(ROOT);$(INCLUDE) $(XFLG) $(OPT) $(DEBUG) -cpp -D_DH -MFLAGS=-I$C;$(TK) -DMARS -cpp $(DEBUG) -e -wx -D_DH - -# Makerules: -.c.obj: - $(CC) -c $(CFLAGS) $(PREC) $* - -.asm.obj: - $(CC) -c $(CFLAGS) $* - -defaulttarget: debdmd - -################ RELEASES ######################### - -release: - $(MAKE) clean - $(MAKE) dmd - $(MAKE) clean - -################ NT COMMAND LINE RELEASE ######################### - -trace: - $(MAKE) OPT=-o "DEBUG=-gt -Nc" LFLAGS=-L/ma/co/delexe dmd.lib - -dmd: - $(MAKE) OPT=-o "DEBUG=" LFLAGS=-L/delexe dmd.lib -# $(MAKE) OPT=-o "DEBUG=" LFLAGS=-L/ma/co/delexe dmd.exe - -################ NT COMMAND LINE DEBUG ######################### - -debdmd: - $(MAKE) OPT= "DEBUG=-D -g" LFLAGS=-L/ma/co dmd.lib - -######################################### - -# D front end - -OBJ1= mars2.obj enum.obj struct.obj dsymbol.obj import.obj id.obj \ - staticassert.obj identifier.obj mtype.obj expression.obj \ - optimize.obj template.obj lexer.obj declaration.obj cast.obj \ - init.obj func.obj utf.obj unialpha.obj parse.obj statement.obj \ - constfold.obj version.obj inifile.obj typinf.obj \ - module.obj scope.obj dump.obj cond.obj inline.obj opover.obj \ - entity.obj class.obj mangle.obj attrib.obj impcnvtab.obj \ - link.obj access.obj doc.obj macro.obj hdrgen.obj delegatize.obj \ - interpret.obj traits.obj aliasthis.obj \ - builtin.obj clone.obj libomf.obj arrayop.obj irstate.obj \ - glue.obj msc.obj ph.obj tk.obj s2ir.obj todt.obj e2ir.obj tocsym.obj \ - util.obj bit.obj eh.obj toobj.obj toctype.obj tocvdebug.obj toir.obj \ - json.obj - -# from C/C++ compiler optimizer and back end - -OBJ8= go.obj gdag.obj gother.obj gflow.obj gloop.obj var.obj el.obj \ - newman.obj glocal.obj os.obj nteh.obj evalu8.obj cgcs.obj \ - rtlsym.obj html.obj cgelem.obj cgen.obj cgreg.obj out.obj \ - blockopt.obj cgobj.obj cg.obj cgcv.obj type.obj dt.obj \ - debug.obj code.obj cg87.obj cgsched.obj ee.obj csymbol.obj \ - cgcod.obj cod1.obj cod2.obj cod3.obj cod4.obj cod5.obj outbuf.obj \ - bcomplex.obj iasm.obj ptrntab.obj aa.obj ti_achar.obj md5.obj - -# from ROOT - -ROOTOBJS= lstring.obj array.obj gnuc.obj man.obj rmem.obj port.obj root.obj \ - stringtable.obj dchar.obj response.obj async.obj - -OBJS= $(OBJ1) $(OBJ8) $(ROOTOBJS) - -SRCS= mars2.c enum.c struct.c dsymbol.c import.c idgen.c impcnvgen.c utf.h \ - utf.c entity.c identifier.c mtype.c expression.c optimize.c \ - template.h template.c lexer.c declaration.c cast.c \ - cond.h cond.c link.c aggregate.h staticassert.h parse.c statement.c \ - constfold.c version.h version.c inifile.c iasm.c staticassert.c \ - module.c scope.c dump.c init.h init.c attrib.h attrib.c opover.c \ - eh.c toctype.c class.c mangle.c bit.c tocsym.c func.c inline.c \ - access.c complex_t.h unialpha.c irstate.h irstate.c glue.c msc.c \ - ph.c tk.c s2ir.c todt.c e2ir.c util.c toobj.c cppmangle.c \ - identifier.h parse.h objfile.h scope.h enum.h import.h \ - typinf.c tocvdebug.c toelfdebug.c mars.h module.h mtype.h dsymbol.h \ - declaration.h lexer.h expression.h statement.h doc.h doc.c \ - macro.h macro.c hdrgen.h hdrgen.c arraytypes.h \ - delegatize.c toir.h toir.c interpret.c traits.c builtin.c \ - clone.c lib.h libomf.c libelf.c libmach.c arrayop.c \ - aliasthis.h aliasthis.c json.h json.c - -# From C++ compiler - -BACKSRC= $C\cdef.h $C\cc.h $C\oper.h $C\ty.h $C\optabgen.c \ - $C\global.h $C\parser.h $C\code.h $C\type.h $C\dt.h $C\cgcv.h \ - $C\el.h $C\iasm.h $C\rtlsym.h $C\html.h \ - $C\bcomplex.c $C\blockopt.c $C\cg.c $C\cg87.c \ - $C\cgcod.c $C\cgcs.c $C\cgcv.c $C\cgelem.c $C\cgen.c $C\cgobj.c \ - $C\cgreg.c $C\var.c \ - $C\cgsched.c $C\cod1.c $C\cod2.c $C\cod3.c $C\cod4.c $C\cod5.c \ - $C\code.c $C\symbol.c $C\debug.c $C\dt.c $C\ee.c $C\el.c \ - $C\evalu8.c $C\go.c $C\gflow.c $C\gdag.c \ - $C\gother.c $C\glocal.c $C\gloop.c $C\html.c $C\newman.c \ - $C\nteh.c $C\os.c $C\out.c $C\outbuf.c $C\ptrntab.c $C\rtlsym.c \ - $C\type.c $C\melf.h $C\mach.h $C\bcomplex.h \ - $C\cdeflnx.h $C\outbuf.h $C\token.h $C\tassert.h \ - $C\elfobj.c $C\cv4.h $C\dwarf2.h $C\cpp.h $C\exh.h $C\go.h \ - $C\dwarf.c $C\dwarf.h $C\cppman.c $C\machobj.c \ - $C\strtold.c $C\aa.h $C\aa.c $C\tinfo.h $C\ti_achar.c \ - $C\md5.h $C\md5.c - -# From TK - -TKSRC= $(TK)\filespec.h $(TK)\mem.h $(TK)\list.h $(TK)\vec.h \ - $(TK)\filespec.c $(TK)\mem.c $(TK)\vec.c $(TK)\list.c - -# From root - -ROOTSRC= $(ROOT)\dchar.h $(ROOT)\dchar.c $(ROOT)\lstring.h \ - $(ROOT)\lstring.c $(ROOT)\root.h $(ROOT)\root.c $(ROOT)\array.c \ - $(ROOT)\rmem.h $(ROOT)\rmem.c $(ROOT)\port.h \ - $(ROOT)\stringtable.h $(ROOT)\stringtable.c \ - $(ROOT)\gnuc.h $(ROOT)\gnuc.c $(ROOT)\man.c $(ROOT)\port.c \ - $(ROOT)\response.c $(ROOT)\async.h $(ROOT)\async.c - -MAKEFILES=win32.mak win32_lib.mak linux.mak osx.mak freebsd.mak solaris.mak - -######################################### - -$(TARGET).lib : $(OBJS) win32_lib.mak - lib -c -p128 $(TARGET).lib $(OBJS) - -##################### INCLUDE MACROS ##################### - -CCH= -#TOTALH=$(CCH) total.sym -TOTALH=$(CCH) id.h -CH= $C\cc.h $C\global.h $C\parser.h $C\oper.h $C\code.h $C\type.h $C\dt.h $C\cgcv.h $C\el.h $C\iasm.h - -##################### GENERATED SOURCE ##################### - -msgs.h msgs.c sj1041.msg sj1036.msg sj1031.msg : msgsx.exe - msgsx - -msgsx.exe : msgsx.c - dmc msgsx -mn -D$(TARGET) $(DEFINES) $(WINLIBS) - -elxxx.c cdxxx.c optab.c debtab.c fltables.c tytab.c : \ - $C\cdef.h $C\cc.h $C\oper.h $C\ty.h $C\optabgen.c - dmc -cpp -ooptabgen.exe $C\optabgen -DMARS -I$(TK) $(WINLIBS) #-L$(LINKS) - optabgen - -impcnvtab.c : impcnvgen.c - $(CC) -I$(ROOT) -cpp impcnvgen - impcnvgen - -id.h id.c : idgen.c - dmc -cpp idgen - idgen - -##################### SPECIAL BUILDS ##################### - -total.sym : $(ROOT)\root.h mars.h lexer.h parse.h enum.h dsymbol.h \ - mtype.h expression.h attrib.h init.h cond.h version.h \ - declaration.h statement.h scope.h import.h module.h id.h \ - template.h aggregate.h arraytypes.h lib.h total.h - $(CC) -c $(CFLAGS) -HFtotal.sym total.h - -impcnvtab.obj : mtype.h impcnvtab.c - $(CC) -c -I$(ROOT) -cpp impcnvtab - -iasm.obj : $(CH) $(TOTALH) $C\iasm.h iasm.c - $(CC) -c $(MFLAGS) -I$(ROOT) iasm - -bcomplex.obj : $C\bcomplex.c - $(CC) -c $(MFLAGS) $C\bcomplex - -aa.obj : $C\tinfo.h $C\aa.h $C\aa.c - $(CC) -c $(MFLAGS) -I. $C\aa - -bit.obj : expression.h bit.c - $(CC) -c -I$(ROOT) $(MFLAGS) bit - -blockopt.obj : $C\blockopt.c - $(CC) -c $(MFLAGS) $C\blockopt - -cg.obj : $C\cg.c - $(CC) -c $(MFLAGS) -I. $C\cg - -cg87.obj : $C\cg87.c - $(CC) -c $(MFLAGS) $C\cg87 - -cgcod.obj : $C\cgcod.c - $(CC) -c $(MFLAGS) -I. $C\cgcod - -cgcs.obj : $C\cgcs.c - $(CC) -c $(MFLAGS) $C\cgcs - -cgcv.obj : $C\cgcv.c - $(CC) -c $(MFLAGS) $C\cgcv - -cgelem.obj : $C\rtlsym.h $C\cgelem.c - $(CC) -c $(MFLAGS) -I. $C\cgelem - -cgen.obj : $C\rtlsym.h $C\cgen.c - $(CC) -c $(MFLAGS) $C\cgen - -cgobj.obj : $C\md5.h $C\cgobj.c - $(CC) -c $(MFLAGS) $C\cgobj - -cgreg.obj : $C\cgreg.c - $(CC) -c $(MFLAGS) $C\cgreg - -cgsched.obj : $C\rtlsym.h $C\cgsched.c - $(CC) -c $(MFLAGS) $C\cgsched - -cod1.obj : $C\rtlsym.h $C\cod1.c - $(CC) -c $(MFLAGS) $C\cod1 - -cod2.obj : $C\rtlsym.h $C\cod2.c - $(CC) -c $(MFLAGS) $C\cod2 - -cod3.obj : $C\rtlsym.h $C\cod3.c - $(CC) -c $(MFLAGS) $C\cod3 - -cod4.obj : $C\cod4.c - $(CC) -c $(MFLAGS) $C\cod4 - -cod5.obj : $C\cod5.c - $(CC) -c $(MFLAGS) $C\cod5 - -code.obj : $C\code.c - $(CC) -c $(MFLAGS) $C\code - -irstate.obj : irstate.h irstate.c - $(CC) -c $(MFLAGS) irstate - -csymbol.obj : $C\symbol.c - $(CC) -c $(MFLAGS) $C\symbol -ocsymbol.obj - -debug.obj : $C\debug.c - $(CC) -c $(MFLAGS) -I. $C\debug - -dt.obj : $C\dt.h $C\dt.c - $(CC) -c $(MFLAGS) $C\dt - -ee.obj : $C\ee.c - $(CC) -c $(MFLAGS) $C\ee - -eh.obj : $C\cc.h $C\code.h $C\type.h $C\dt.h eh.c - $(CC) -c $(MFLAGS) eh - -el.obj : $C\rtlsym.h $C\el.h $C\el.c - $(CC) -c $(MFLAGS) $C\el - -evalu8.obj : $C\evalu8.c - $(CC) -c $(MFLAGS) $C\evalu8 - -go.obj : $C\go.c - $(CC) -c $(MFLAGS) $C\go - -gflow.obj : $C\gflow.c - $(CC) -c $(MFLAGS) $C\gflow - -gdag.obj : $C\gdag.c - $(CC) -c $(MFLAGS) $C\gdag - -gother.obj : $C\gother.c - $(CC) -c $(MFLAGS) $C\gother - -glocal.obj : $C\rtlsym.h $C\glocal.c - $(CC) -c $(MFLAGS) $C\glocal - -gloop.obj : $C\gloop.c - $(CC) -c $(MFLAGS) $C\gloop - -glue.obj : $(CH) $(TOTALH) $C\rtlsym.h mars.h module.h glue.c - $(CC) -c $(MFLAGS) -I$(ROOT) glue - -html.obj : $(CH) $(TOTALH) $C\html.h $C\html.c - $(CC) -c -I$(ROOT) $(MFLAGS) $C\html - -mars2.obj : $(TOTALH) module.h mars.h mars2.c - $(CC) -c $(CFLAGS) $(PREC) $* -Ae - -md5.obj : $C\md5.h $C\md5.c - $(CC) -c $(MFLAGS) $C\md5 - -module.obj : $(TOTALH) $C\html.h module.c - $(CC) -c $(CFLAGS) -I$C $(PREC) module.c - -msc.obj : $(CH) mars.h msc.c - $(CC) -c $(MFLAGS) msc - -newman.obj : $(CH) $C\newman.c - $(CC) -c $(MFLAGS) $C\newman - -nteh.obj : $C\rtlsym.h $C\nteh.c - $(CC) -c $(MFLAGS) $C\nteh - -os.obj : $C\os.c - $(CC) -c $(MFLAGS) $C\os - -out.obj : $C\out.c - $(CC) -c $(MFLAGS) $C\out - -outbuf.obj : $C\outbuf.h $C\outbuf.c - $(CC) -c $(MFLAGS) $C\outbuf - -ph.obj : ph.c - $(CC) -c $(MFLAGS) ph - -ptrntab.obj : $C\iasm.h $C\ptrntab.c - $(CC) -c $(MFLAGS) $C\ptrntab - -rtlsym.obj : $C\rtlsym.h $C\rtlsym.c - $(CC) -c $(MFLAGS) $C\rtlsym - -ti_achar.obj : $C\tinfo.h $C\ti_achar.c - $(CC) -c $(MFLAGS) -I. $C\ti_achar - -toctype.obj : $(CH) $(TOTALH) $C\rtlsym.h mars.h module.h toctype.c - $(CC) -c $(MFLAGS) -I$(ROOT) toctype - -tocvdebug.obj : $(CH) $(TOTALH) $C\rtlsym.h mars.h module.h tocvdebug.c - $(CC) -c $(MFLAGS) -I$(ROOT) tocvdebug - -toobj.obj : $(CH) $(TOTALH) mars.h module.h toobj.c - $(CC) -c $(MFLAGS) -I$(ROOT) toobj - -type.obj : $C\type.c - $(CC) -c $(MFLAGS) $C\type - -typinf.obj : $(CH) $(TOTALH) $C\rtlsym.h mars.h module.h typinf.c - $(CC) -c $(MFLAGS) -I$(ROOT) typinf - -todt.obj : mtype.h expression.h $C\dt.h todt.c - $(CC) -c -I$(ROOT) $(MFLAGS) todt - -s2ir.obj : $C\rtlsym.h statement.h s2ir.c - $(CC) -c -I$(ROOT) $(MFLAGS) s2ir - -e2ir.obj : $C\rtlsym.h expression.h toir.h e2ir.c - $(CC) -c -I$(ROOT) $(MFLAGS) e2ir - -toir.obj : $C\rtlsym.h expression.h toir.h toir.c - $(CC) -c -I$(ROOT) $(MFLAGS) toir - -tocsym.obj : $(CH) $(TOTALH) mars.h module.h tocsym.c - $(CC) -c $(MFLAGS) -I$(ROOT) tocsym - -util.obj : util.c - $(CC) -c $(MFLAGS) util - -var.obj : $C\var.c optab.c - $(CC) -c $(MFLAGS) -I. $C\var - - -tk.obj : tk.c - $(CC) -c $(MFLAGS) tk.c - -# ROOT - -array.obj : $(ROOT)\array.c - $(CC) -c $(CFLAGS) $(ROOT)\array.c - -async.obj : $(ROOT)\async.h $(ROOT)\async.c - $(CC) -c $(CFLAGS) $(ROOT)\async.c - -dchar.obj : $(ROOT)\dchar.c - $(CC) -c $(CFLAGS) $(ROOT)\dchar.c - -gnuc.obj : $(ROOT)\gnuc.c - $(CC) -c $(CFLAGS) $(ROOT)\gnuc.c - -lstring.obj : $(ROOT)\lstring.c - $(CC) -c $(CFLAGS) $(ROOT)\lstring.c - -man.obj : $(ROOT)\man.c - $(CC) -c $(CFLAGS) $(ROOT)\man.c - -rmem.obj : $(ROOT)\rmem.c - $(CC) -c $(CFLAGS) $(ROOT)\rmem.c - -port.obj : $(ROOT)\port.c - $(CC) -c $(CFLAGS) $(ROOT)\port.c - -root.obj : $(ROOT)\root.c - $(CC) -c $(CFLAGS) $(ROOT)\root.c - -response.obj : $(ROOT)\response.c - $(CC) -c $(CFLAGS) $(ROOT)\response.c - -stringtable.obj : $(ROOT)\stringtable.c - $(CC) -c $(CFLAGS) $(ROOT)\stringtable.c - - -################# Source file dependencies ############### - -access.obj : $(TOTALH) enum.h aggregate.h init.h attrib.h access.c -aliasthis.obj : $(TOTALH) aliasthis.h aliasthis.c -arrayop.obj : $(TOTALH) identifier.h declaration.h arrayop.c -attrib.obj : $(TOTALH) identifier.h declaration.h attrib.h attrib.c -builtin.obj : $(TOTALH) builtin.c -cast.obj : $(TOTALH) expression.h mtype.h cast.c -class.obj : $(TOTALH) enum.h class.c -clone.obj : $(TOTALH) clone.c -constfold.obj : $(TOTALH) expression.h constfold.c -cond.obj : $(TOTALH) identifier.h declaration.h cond.h cond.c -declaration.obj : $(TOTALH) identifier.h attrib.h declaration.h declaration.c -delegatize.obj : $(TOTALH) delegatize.c -doc.obj : $(TOTALH) doc.h doc.c -enum.obj : $(TOTALH) identifier.h enum.h enum.c -expression.obj : $(TOTALH) expression.h expression.c -func.obj : $(TOTALH) identifier.h attrib.h declaration.h func.c -hdrgen.obj : $(TOTALH) hdrgen.h hdrgen.c -id.obj : $(TOTALH) id.h id.c -identifier.obj : $(TOTALH) identifier.h identifier.c -import.obj : $(TOTALH) dsymbol.h import.h import.c -inifile.obj : $(TOTALH) inifile.c -init.obj : $(TOTALH) init.h init.c -inline.obj : $(TOTALH) inline.c -interpret.obj : $(TOTALH) interpret.c -json.obj : $(TOTALH) json.h json.c -lexer.obj : $(TOTALH) lexer.c -libomf.obj : $(TOTALH) lib.h libomf.c -link.obj : $(TOTALH) link.c -macro.obj : $(TOTALH) macro.h macro.c -mangle.obj : $(TOTALH) dsymbol.h declaration.h mangle.c -#module.obj : $(TOTALH) mars.h $C\html.h module.h module.c -opover.obj : $(TOTALH) expression.h opover.c -optimize.obj : $(TOTALH) expression.h optimize.c -parse.obj : $(TOTALH) attrib.h lexer.h parse.h parse.c -scope.obj : $(TOTALH) scope.h scope.c -statement.obj : $(TOTALH) statement.h statement.c -staticassert.obj : $(TOTALH) staticassert.h staticassert.c -struct.obj : $(TOTALH) identifier.h enum.h struct.c -traits.obj : $(TOTALH) traits.c -dsymbol.obj : $(TOTALH) identifier.h dsymbol.h dsymbol.c -mtype.obj : $(TOTALH) mtype.h mtype.c -#typinf.obj : $(TOTALH) mtype.h typinf.c -utf.obj : utf.h utf.c -template.obj : $(TOTALH) template.h template.c -version.obj : $(TOTALH) identifier.h dsymbol.h cond.h version.h version.c - -################### Utilities ################ - -clean: - del *.obj - del total.sym - del msgs.h msgs.c - del elxxx.c cdxxx.c optab.c debtab.c fltables.c tytab.c - del impcnvtab.c - -zip : $(MAKEFILES) - del dmdsrc.zip - zip32 dmdsrc $(MAKEFILES) - zip32 dmdsrc $(SRCS) - zip32 dmdsrc $(BACKSRC) - zip32 dmdsrc $(TKSRC) - zip32 dmdsrc $(ROOTSRC) - -################### Install ################ - -install: - copy dmd.exe $(DIR)\windows\bin\ - copy phobos\phobos.lib $(DIR)\windows\lib - $(CP) $(SRCS) $(DIR)\src\dmd\ - $(CP) $(ROOTSRC) $(DIR)\src\dmd\root\ - $(CP) $(TKSRC) $(DIR)\src\dmd\tk\ - $(CP) $(BACKSRC) $(DIR)\src\dmd\backend\ - $(CP) $(MAKEFILES) $(DIR)\src\dmd\ - copy gpl.txt $(DIR)\src\dmd\ - copy readme.txt $(DIR)\src\dmd\ - copy artistic.txt $(DIR)\src\dmd\ - copy backendlicense.txt $(DIR)\src\dmd\ - -################### Write to SVN ################ - -svn: - $(CP) $(SRCS) $(DMDSVN)\ - $(CP) $(ROOTSRC) $(DMDSVN)\root\ - $(CP) $(TKSRC) $(DMDSVN)\tk\ - $(CP) $(BACKSRC) $(DMDSVN)\backend\ - $(CP) $(MAKEFILES) $(DMDSVN)\ - copy gpl.txt $(DMDSVN)\ - copy readme.txt $(DMDSVN)\ - copy artistic.txt $(DMDSVN)\ - copy backendlicense.txt $(DMDSVN)\ - -###################################