# HG changeset patch
# User Trass3r
# Date 1284413340 -7200
# Node ID 09c858522d55cc5911094ece819502f56b19fd41
# Parent 9d194c848e3a31d49f0689b1286a69d32baf8281# Parent af1bebfd96a4eece91aabe1f6d92695bf39aa52d
merge
diff -r 9d194c848e3a -r 09c858522d55 commands.linux.txt
--- a/commands.linux.txt Mon Sep 13 23:27:38 2010 +0200
+++ b/commands.linux.txt Mon Sep 13 23:29:00 2010 +0200
@@ -78,6 +78,7 @@
dmd/ArrayLengthExp.d
dmd/TypeInfoConstDeclaration.d
dmd/TypeInfoInvariantDeclaration.d
+dmd/TypeInfoWildDeclaration.d
dmd/TypeInfoSharedDeclaration.d
dmd/TypeInfoStructDeclaration.d
dmd/TypeInfoInterfaceDeclaration.d
@@ -272,6 +273,7 @@
dmd/Parser.d
dmd/PostBlitDeclaration.d
dmd/PowExp.d
+dmd/PowAssignExp.d
dmd/PragmaDeclaration.d
dmd/PragmaStatement.d
dmd/ProtDeclaration.d
diff -r 9d194c848e3a -r 09c858522d55 commands.txt
--- a/commands.txt Mon Sep 13 23:27:38 2010 +0200
+++ b/commands.txt Mon Sep 13 23:29:00 2010 +0200
@@ -73,6 +73,7 @@
dmd\ArrayLengthExp.d
dmd\TypeInfoConstDeclaration.d
dmd\TypeInfoInvariantDeclaration.d
+dmd\TypeInfoWildDeclaration.d
dmd\TypeInfoSharedDeclaration.d
dmd\TypeInfoStructDeclaration.d
dmd\TypeInfoInterfaceDeclaration.d
@@ -267,6 +268,7 @@
dmd\Parser.d
dmd\PostBlitDeclaration.d
dmd\PowExp.d
+dmd\PowAssignExp.d
dmd\PragmaDeclaration.d
dmd\PragmaStatement.d
dmd\ProtDeclaration.d
diff -r 9d194c848e3a -r 09c858522d55 ddmd.visualdproj
--- a/ddmd.visualdproj Mon Sep 13 23:27:38 2010 +0200
+++ b/ddmd.visualdproj Mon Sep 13 23:29:00 2010 +0200
@@ -608,6 +608,8 @@
+
+
diff -r 9d194c848e3a -r 09c858522d55 dmd/AddrExp.d
--- a/dmd/AddrExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/AddrExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -126,6 +126,11 @@
return this;
}
+ override void checkEscape()
+ {
+ e1.checkEscapeRef();
+ }
+
override elem* toElem(IRState* irs)
{
elem* e;
diff -r 9d194c848e3a -r 09c858522d55 dmd/AliasDeclaration.d
--- a/dmd/AliasDeclaration.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/AliasDeclaration.d Mon Sep 13 23:29:00 2010 +0200
@@ -100,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:
@@ -128,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 9d194c848e3a -r 09c858522d55 dmd/ArrayLiteralExp.d
--- a/dmd/ArrayLiteralExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/ArrayLiteralExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -213,10 +213,7 @@
ex = e.interpret(istate);
if (ex is EXP_CANT_INTERPRET)
- {
- delete expsx;
- return EXP_CANT_INTERPRET;
- }
+ goto Lerror;
/* If any changes, do Copy On Write
*/
@@ -239,10 +236,7 @@
{
expandTuples(expsx);
if (expsx.dim != elements.dim)
- {
- delete expsx;
- return EXP_CANT_INTERPRET;
- }
+ goto Lerror;
ArrayLiteralExp ae = new ArrayLiteralExp(loc, expsx);
ae.type = type;
@@ -250,6 +244,12 @@
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 9d194c848e3a -r 09c858522d55 dmd/BinExp.d
--- a/dmd/BinExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/BinExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -552,6 +552,7 @@
case TOK.TOKandass:
case TOK.TOKorass:
case TOK.TOKxorass:
+ case TOK.TOKpowass:
case TOK.TOKin:
case TOK.TOKremove:
return true;
@@ -803,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;
}
}
@@ -826,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)
@@ -848,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);
}
@@ -872,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());
@@ -949,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;
@@ -997,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;
@@ -1165,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;
@@ -1188,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();
@@ -1257,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;
diff -r 9d194c848e3a -r 09c858522d55 dmd/CallExp.d
--- a/dmd/CallExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/CallExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -279,7 +279,6 @@
istemp = 0;
Lagain:
//printf("Lagain: %s\n", toChars());
- //printf("test1 %s\n", toChars());
f = null;
if (e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper)
{
@@ -509,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
@@ -518,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
@@ -795,12 +794,11 @@
Lcheckargs:
assert(tf.ty == TY.Tfunction);
- type = tf.next;
if (!arguments)
arguments = new Expressions();
- functionParameters(loc, sc, tf, arguments);
+ type = functionParameters(loc, sc, tf, arguments);
if (!type)
{
diff -r 9d194c848e3a -r 09c858522d55 dmd/Cast.d
--- a/dmd/Cast.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Cast.d Mon Sep 13 23:29:00 2010 +0200
@@ -61,6 +61,9 @@
}
}
+ if (e1.op == TOK.TOKarrayliteral && typeb == tb)
+ return e1;
+
if (e1.isConst() != 1)
return EXP_CANT_INTERPRET;
diff -r 9d194c848e3a -r 09c858522d55 dmd/CastExp.d
--- a/dmd/CastExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/CastExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -183,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*
;
@@ -425,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(')');
diff -r 9d194c848e3a -r 09c858522d55 dmd/CatExp.d
--- a/dmd/CatExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/CatExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -67,6 +67,7 @@
e2.implicitConvTo(tb1next) >= MATCHconvert)
{
e2 = e2.implicitCastTo(sc, tb1next);
+ type = tb1next.arrayOf();
if (tb2.ty == Tarray)
{
// Make e2 into [e2]
@@ -79,6 +80,7 @@
e1.implicitConvTo(tb2next) >= MATCHconvert)
{
e1 = e1.implicitCastTo(sc, tb2next);
+ type = tb2next.arrayOf();
if (tb1.ty == Tarray)
{
// Make e1 into [e1]
diff -r 9d194c848e3a -r 09c858522d55 dmd/ClassDeclaration.d
--- a/dmd/ClassDeclaration.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/ClassDeclaration.d Mon Sep 13 23:29:00 2010 +0200
@@ -258,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;
+ }
}
}
@@ -699,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);
}
diff -r 9d194c848e3a -r 09c858522d55 dmd/CommaExp.d
--- a/dmd/CommaExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/CommaExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -38,6 +38,11 @@
e2.checkEscape();
}
+ override void checkEscapeRef()
+ {
+ e2.checkEscapeRef();
+ }
+
override IntRange getIntRange()
{
assert(false);
diff -r 9d194c848e3a -r 09c858522d55 dmd/CondExp.d
--- a/dmd/CondExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/CondExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -184,6 +184,12 @@
e2.checkEscape();
}
+ override void checkEscapeRef()
+ {
+ e1.checkEscapeRef();
+ e2.checkEscapeRef();
+ }
+
override int isLvalue()
{
return e1.isLvalue() && e2.isLvalue();
diff -r 9d194c848e3a -r 09c858522d55 dmd/Declaration.d
--- a/dmd/Declaration.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Declaration.d Mon Sep 13 23:29:00 2010 +0200
@@ -158,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";
@@ -311,7 +311,7 @@
bool isConst() { return (storage_class & STC.STCconst) != 0; }
- int isInvariant() { return storage_class & STC.STCinvariant; }
+ int isImmutable() { return storage_class & STC.STCimmutable; }
int isAuto() { return storage_class & STC.STCauto; }
diff -r 9d194c848e3a -r 09c858522d55 dmd/DeclarationExp.d
--- a/dmd/DeclarationExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/DeclarationExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -148,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)
///}
diff -r 9d194c848e3a -r 09c858522d55 dmd/DotVarExp.d
--- a/dmd/DotVarExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/DotVarExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -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());
}
}
}
@@ -242,10 +242,15 @@
{
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 {
+ }
+ else
+ {
error("%s.%s is not yet implemented at compile time", ex.toChars(), var.toChars());
}
}
diff -r 9d194c848e3a -r 09c858522d55 dmd/Expression.d
--- a/dmd/Expression.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Expression.d Mon Sep 13 23:29:00 2010 +0200
@@ -657,6 +657,10 @@
{
}
+ void checkEscapeRef()
+ {
+ }
+
void checkScalar()
{
if (!type.isscalar())
diff -r 9d194c848e3a -r 09c858522d55 dmd/ForeachStatement.d
--- a/dmd/ForeachStatement.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/ForeachStatement.d Mon Sep 13 23:29:00 2010 +0200
@@ -115,6 +115,7 @@
Statement s = this;
size_t dim = arguments.dim;
TypeAArray taa = null;
+ Dsymbol sapply = null;
Type tn = null;
Type tnv = null;
@@ -255,6 +256,9 @@
sc.noctor++;
Lagain:
+ Identifier idapply = (op == TOK.TOKforeach_reverse)
+ ? Id.applyReverse : Id.apply;
+ sapply = null;
switch (tab.ty)
{
case TY.Tarray:
@@ -445,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) { ... }
@@ -454,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;
@@ -531,16 +541,9 @@
case TY.Tdelegate:
Lapply:
{
- FuncDeclaration fdapply;
- Parameters args;
Expression ec;
Expression e;
- FuncLiteralDeclaration fld;
Parameter a;
- Type t;
- Expression flde;
- Identifier id;
- Type tret;
if (!checkForArgTypes())
{
@@ -548,7 +551,7 @@
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)
@@ -566,10 +569,11 @@
/* Turn body into the function literal:
* int delegate(ref T arg) { body }
*/
- args = new Parameters();
+ auto args = new Parameters();
for (size_t i = 0; i < dim; i++)
{
auto arg = arguments[i];
+ Identifier id;
arg.type = arg.type.semantic(loc, sc);
if (arg.storageClass & STC.STCref)
@@ -577,28 +581,25 @@
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 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++)
{
auto cs = cast(CompoundStatement)gotos.data[i];
auto gs = cast(GotoStatement)cs.statements[0];
@@ -631,6 +632,7 @@
/* Call:
* _aaApply(aggr, keysize, flde)
*/
+ FuncDeclaration fdapply;
if (dim == 2)
fdapply = FuncDeclaration.genCfunc(Type.tindex, "_aaApply2");
else
@@ -674,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();
@@ -700,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)
diff -r 9d194c848e3a -r 09c858522d55 dmd/FuncDeclaration.d
--- a/dmd/FuncDeclaration.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/FuncDeclaration.d Mon Sep 13 23:29:00 2010 +0200
@@ -309,37 +309,59 @@
originalType = type;
if (!type.deco)
{
+ 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);
StorageClass stc = storage_class;
- if (type.isInvariant())
+ 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
@@ -354,7 +376,7 @@
assert(0);
}
}
- //type.print();
+ storage_class &= ~STC.STCref;
if (type.ty != TY.Tfunction)
{
error("%s must be a function", toChars());
@@ -378,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())
@@ -965,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();
@@ -1054,7 +1076,7 @@
}
}
}
-
+static if(false) {
// Propagate storage class from tuple parameters to their element-parameters.
if (f.parameters)
{
@@ -1072,7 +1094,7 @@
}
}
}
-
+}
/* Declare all the function parameters as variables
* and install them in parameters[]
*/
@@ -2399,10 +2421,10 @@
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;
}
@@ -2547,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)
{
@@ -2562,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");
@@ -3835,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 9d194c848e3a -r 09c858522d55 dmd/Global.d
--- a/dmd/Global.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Global.d Mon Sep 13 23:29:00 2010 +0200
@@ -39,7 +39,7 @@
string[] path; // Array of char*'s which form the import lookup path
string[] filePath; // Array of char*'s which form the file import lookup path
int structalign = 8;
- string version_ = "v2.037";
+ string version_ = "v2.038";
Param params;
uint errors; // number of errors reported so far
diff -r 9d194c848e3a -r 09c858522d55 dmd/Id.d
--- a/dmd/Id.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Id.d Mon Sep 13 23:29:00 2010 +0200
@@ -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" ),
@@ -217,7 +219,7 @@
ID( "opImplicitCast" ),
ID( "pow", "opPow" ),
ID( "pow_r", "opPow_r" ),
- //ID( "powass", "opPowAssign" ),
+ ID( "powass", "opPowAssign" ),
ID( "classNew", "new" ),
ID( "classDelete", "delete" ),
@@ -294,6 +296,9 @@
ID( "isVirtualFunction" ),
ID( "isAbstractFunction" ),
ID( "isFinalFunction" ),
+ ID( "isRef" ),
+ ID( "isOut" ),
+ ID( "isLazy" ),
ID( "hasMember" ),
ID( "getMember" ),
ID( "getVirtualFunctions" ),
diff -r 9d194c848e3a -r 09c858522d55 dmd/IdentityExp.d
--- a/dmd/IdentityExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/IdentityExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -53,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))
{
diff -r 9d194c848e3a -r 09c858522d55 dmd/IntegerExp.d
--- a/dmd/IntegerExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/IntegerExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -209,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 9d194c848e3a -r 09c858522d55 dmd/IsExp.d
--- a/dmd/IsExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/IsExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -146,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;
diff -r 9d194c848e3a -r 09c858522d55 dmd/Lexer.d
--- a/dmd/Lexer.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Lexer.d Mon Sep 13 23:29:00 2010 +0200
@@ -498,7 +498,7 @@
Token.tochars[TOK.TOKidentifier] = "identifier";
Token.tochars[TOK.TOKat] = "@";
Token.tochars[TOK.TOKpow] = "^^";
- //Token.tochars[TOK.TOKpowass] = "^^=";
+ Token.tochars[TOK.TOKpowass] = "^^=";
// For debugging
Token.tochars[TOKerror] = "error";
@@ -750,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;
@@ -1266,13 +1279,11 @@
p++;
if (*p == '^')
{ p++;
-//static if (false) {
-// if (*p == '=')
-// { p++;
-// t.value = TOKpowass; // ^^=
-// }
-// else
-//}
+ if (*p == '=')
+ { p++;
+ t.value = TOKpowass; // ^^=
+ }
+ else
t.value = TOKpow; // ^^
}
else if (*p == '=')
@@ -1370,23 +1381,23 @@
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);
@@ -1719,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);
diff -r 9d194c848e3a -r 09c858522d55 dmd/MOD.d
--- a/dmd/MOD.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/MOD.d Mon Sep 13 23:29:00 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 9d194c848e3a -r 09c858522d55 dmd/NullExp.d
--- a/dmd/NullExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/NullExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -21,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)
diff -r 9d194c848e3a -r 09c858522d55 dmd/Optimize.d
--- a/dmd/Optimize.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Optimize.d Mon Sep 13 23:29:00 2010 +0200
@@ -24,7 +24,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)
{
diff -r 9d194c848e3a -r 09c858522d55 dmd/PREC.d
--- a/dmd/PREC.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/PREC.d Mon Sep 13 23:29:00 2010 +0200
@@ -25,6 +25,7 @@
PREC_shift,
PREC_add,
PREC_mul,
+ PREC_pow,
PREC_unary,
PREC_primary,
}
diff -r 9d194c848e3a -r 09c858522d55 dmd/Parameter.d
--- a/dmd/Parameter.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Parameter.d Mon Sep 13 23:29:00 2010 +0200
@@ -177,6 +177,9 @@
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)
@@ -187,8 +190,6 @@
buf.writestring("lazy ");
else if (arg.storageClass & STCalias)
buf.writestring("alias ");
- else if (arg.storageClass & STCauto)
- buf.writestring("auto ");
StorageClass stc = arg.storageClass;
if (arg.type && arg.type.mod & MODshared)
diff -r 9d194c848e3a -r 09c858522d55 dmd/Parser.d
--- a/dmd/Parser.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Parser.d Mon Sep 13 23:29:00 2010 +0200
@@ -79,6 +79,7 @@
import dmd.DivAssignExp;
import dmd.AndAssignExp;
import dmd.AddAssignExp;
+import dmd.PowAssignExp;
import dmd.ModuleDeclaration;
import dmd.CaseRangeStatement;
import dmd.CommaExp;
@@ -496,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;
@@ -527,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;
@@ -534,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;
@@ -1840,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)) ||
@@ -2316,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();
@@ -2344,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);
@@ -2471,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;
@@ -2742,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();
@@ -2874,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;
@@ -3334,6 +3401,7 @@
version (DMDV2) {
case TOK.TOKimmutable:
case TOK.TOKshared:
+ case TOKwild:
case TOK.TOKnothrow:
case TOK.TOKpure:
case TOK.TOKtls:
@@ -3526,7 +3594,11 @@
Type at;
StorageClass storageClass = STC.STCundefined;
- if (token.value == TOK.TOKinout || token.value == TOK.TOKref)
+ if (token.value == TOKref
+//#if D1INOUT
+// || token.value == TOKinout
+//#endif
+ )
{ storageClass = STC.STCref;
nextToken();
}
@@ -4374,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);
}
@@ -4538,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;
@@ -4703,6 +4778,7 @@
case TOK.TOKinvariant:
case TOK.TOKimmutable:
case TOK.TOKshared:
+ case TOKwild:
case TOK.TOKpure:
case TOK.TOKnothrow:
t = peek(t);
@@ -4763,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)
{
@@ -5287,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 ||
@@ -5581,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)
@@ -5596,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)
@@ -5604,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();
@@ -5734,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;
}
@@ -5862,7 +5964,6 @@
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.TOKpow: nextToken(); e2 = parseUnaryExp(); e = new PowExp(loc,e,e2); continue;
default:
break;
@@ -6129,7 +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.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 9d194c848e3a -r 09c858522d55 dmd/PowAssignExp.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/PowAssignExp.d Mon Sep 13 23:29:00 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 9d194c848e3a -r 09c858522d55 dmd/PowExp.d
--- a/dmd/PowExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/PowExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -12,6 +12,18 @@
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) {
@@ -22,65 +34,121 @@
super(loc, TOK.TOKpow, PowExp.sizeof, e1, e2);
}
- Expression semantic(Scope sc)
+ 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;
- static int importMathChecked = 0;
- if (!importMathChecked)
- {
- importMathChecked = 1;
- for (int i = 0; i < Module.amodules.dim; i++)
- {
- auto mi = cast(Module)Module.amodules.data[i];
- //printf("\t[%d] %s\n", i, mi->toChars());
- if (mi.ident == Id.math &&
- mi.parent.ident == Id.std &&
- !mi.parent.parent)
- goto L1;
- }
- error("must import std.math to use ^^ operator");
-
- L1: ;
- }
-
assert(e1.type && e2.type);
if ( (e1.type.isintegral() || e1.type.isfloating()) &&
(e2.type.isintegral() || e2.type.isfloating()))
{
- // For built-in numeric types, there are three cases:
- // x ^^ 1 ----> x
- // x ^^ 0.5 ----> sqrt(x)
- // x ^^ y ----> pow(x, y)
+ // 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);
- if ((e2.op == TOK.TOKfloat64 && e2.toReal() == 1.0) ||
- (e2.op == TOK.TOKint64 && e2.toInteger() == 1))
+
+ // 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)
{
- return e1; // Replace x ^^ 1 with x.
+ 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;
}
- e = new IdentifierExp(loc, Id.empty);
- e = new DotIdExp(loc, e, Id.std);
- e = new DotIdExp(loc, e, Id.math);
- if (e2.op == TOKfloat64 && e2.toReal() == 0.5)
- { // Replace e1 ^^ 0.5 with .std.math.sqrt(x)
- e = new CallExp(loc, new DotIdExp(loc, e, Id._sqrt), e1);
+ 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: ;
}
- else
- { // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
- e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2);
- }
- e = e.semantic(sc);
+
+ 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() );
@@ -89,12 +157,12 @@
// For operator overloading
- Identifier opId()
+ override Identifier opId()
{
return Id.pow;
}
- Identifier opId_r()
+ override Identifier opId_r()
{
return Id.pow_r;
}
diff -r 9d194c848e3a -r 09c858522d55 dmd/PtrExp.d
--- a/dmd/PtrExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/PtrExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -85,7 +85,12 @@
{
return 1;
}
-
+
+ override void checkEscapeRef()
+ {
+ e1.checkEscape();
+ }
+
override Expression toLvalue(Scope sc, Expression e)
{
static if (false) {
diff -r 9d194c848e3a -r 09c858522d55 dmd/ReturnStatement.d
--- a/dmd/ReturnStatement.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/ReturnStatement.d Mon Sep 13 23:29:00 2010 +0200
@@ -35,6 +35,7 @@
import dmd.VarDeclaration;
import dmd.GlobalExpressions;
import dmd.BE;
+import dmd.Global;
import dmd.codegen.Util;
@@ -173,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();
@@ -290,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 9d194c848e3a -r 09c858522d55 dmd/STC.d
--- a/dmd/STC.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/STC.d Mon Sep 13 23:29:00 2010 +0200
@@ -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,7 +35,8 @@
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),
}
import dmd.EnumUtils;
@@ -46,5 +46,6 @@
enum STCsafe = 0x200000000;
enum STCtrusted = 0x400000000;
enum STCsystem = 0x800000000;
+enum STCctfe = 0x1000000000; // can be used in CTFE, even if it is static
alias ulong StorageClass;
\ No newline at end of file
diff -r 9d194c848e3a -r 09c858522d55 dmd/Scope.d
--- a/dmd/Scope.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Scope.d Mon Sep 13 23:29:00 2010 +0200
@@ -137,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;
diff -r 9d194c848e3a -r 09c858522d55 dmd/SliceExp.d
--- a/dmd/SliceExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/SliceExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -265,6 +265,11 @@
{
e1.checkEscape();
}
+
+ override void checkEscapeRef()
+ {
+ e1.checkEscapeRef();
+ }
version (DMDV2) {
override int isLvalue()
diff -r 9d194c848e3a -r 09c858522d55 dmd/StaticAssert.d
--- a/dmd/StaticAssert.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/StaticAssert.d Mon Sep 13 23:29:00 2010 +0200
@@ -68,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 9d194c848e3a -r 09c858522d55 dmd/StructDeclaration.d
--- a/dmd/StructDeclaration.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/StructDeclaration.d Mon Sep 13 23:29:00 2010 +0200
@@ -207,7 +207,22 @@
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);
@@ -412,6 +427,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);
diff -r 9d194c848e3a -r 09c858522d55 dmd/StructInitializer.d
--- a/dmd/StructInitializer.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/StructInitializer.d Mon Sep 13 23:29:00 2010 +0200
@@ -78,7 +78,6 @@
override Initializer semantic(Scope sc, Type t)
{
- TypeStruct ts;
int errors = 0;
//printf("StructInitializer.semantic(t = %s) %s\n", t.toChars(), toChars());
@@ -86,12 +85,14 @@
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 = field[i];
Initializer val = value[i];
diff -r 9d194c848e3a -r 09c858522d55 dmd/StructLiteralExp.d
--- a/dmd/StructLiteralExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/StructLiteralExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -157,8 +157,7 @@
}
else
{
- e = v.type.defaultInit(Loc(0));
- e.loc = loc;
+ e = v.type.defaultInitLiteral(loc);
}
offset = v.offset + cast(uint)v.type.size();
}
@@ -660,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 9d194c848e3a -r 09c858522d55 dmd/SwitchStatement.d
--- a/dmd/SwitchStatement.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/SwitchStatement.d Mon Sep 13 23:29:00 2010 +0200
@@ -412,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 9d194c848e3a -r 09c858522d55 dmd/SymOffExp.d
--- a/dmd/SymOffExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/SymOffExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -20,6 +20,7 @@
import dmd.ErrorExp;
import dmd.TY;
import dmd.TOK;
+import dmd.STC;
import dmd.backend.Symbol;
import dmd.backend.Util;
@@ -58,14 +59,14 @@
VarDeclaration v = var.isVarDeclaration();
if (v)
{
- if (!v.isDataseg())
+ 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 variable %s", v.toChars());
+ error("escaping reference to local %s", v.toChars());
}
}
}
diff -r 9d194c848e3a -r 09c858522d55 dmd/TOK.d
--- a/dmd/TOK.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TOK.d Mon Sep 13 23:29:00 2010 +0200
@@ -127,7 +127,7 @@
TOKshared,
TOKat,
TOKpow,
- //TOKpowass,
+ TOKpowass,
TOKMAX
}
@@ -251,5 +251,7 @@
}
}
+alias TOK.TOKinout TOKwild;
+
import dmd.EnumUtils;
mixin(BringToCurrentScope!(TOK));
\ No newline at end of file
diff -r 9d194c848e3a -r 09c858522d55 dmd/TemplateDeclaration.d
--- a/dmd/TemplateDeclaration.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TemplateDeclaration.d Mon Sep 13 23:29:00 2010 +0200
@@ -797,21 +797,7 @@
}
}
- 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;
- }
-
+ fparameters = fd.getParameters(&fvarargs);
nfparams = Parameter.dim(fparameters); // number of function parameters
nfargs = fargs ? fargs.dim : 0; // number of function arguments
@@ -1258,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;
@@ -1390,21 +1376,8 @@
if (fd)
{
paramscope.parent = fd;
- Parameters fparameters; // function parameter list
int fvarargs; // function varargs
- if (fd.type)
- {
- assert(fd.type.ty == Tfunction);
- TypeFunction fdtype = cast(TypeFunction )fd.type;
- fparameters = fdtype.parameters;
- fvarargs = fdtype.varargs;
- }
- else // Constructors don't have type's
- { CtorDeclaration fctor = fd.isCtorDeclaration();
- assert(fctor);
- fparameters = fctor.arguments;
- fvarargs = fctor.varargs;
- }
+ Parameters fparameters = fd.getParameters(&fvarargs);
size_t nfparams = Parameter.dim(fparameters); // Num function parameters
for (int i = 0; i < nfparams; i++)
{
diff -r 9d194c848e3a -r 09c858522d55 dmd/TemplateInstance.d
--- a/dmd/TemplateInstance.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TemplateInstance.d Mon Sep 13 23:29:00 2010 +0200
@@ -40,6 +40,7 @@
import dmd.TypeFunction;
import dmd.TemplateTupleParameter;
import dmd.FuncDeclaration;
+import dmd.OverloadSet;
import dmd.templates.Util;
import dmd.backend.glue;
@@ -263,6 +264,11 @@
override void semantic(Scope sc)
{
+ semantic(sc, null);
+ }
+
+ void semantic(Scope sc, Expressions fargs)
+ {
if (global.errors)
{
if (!global.gag)
@@ -364,6 +370,34 @@
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
+ }
+ }
+ }
}
}
@@ -514,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) {
@@ -610,10 +660,9 @@
if (global.errors != errorsave)
{
error("error instantiating");
- if (tinst && !global.gag)
+ if (tinst)
{
tinst.printInstantiationTrace();
- fatal();
}
errors = 1;
if (global.gag)
@@ -832,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
@@ -1024,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)
diff -r 9d194c848e3a -r 09c858522d55 dmd/TraitsExp.d
--- a/dmd/TraitsExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TraitsExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -31,6 +31,7 @@
import dmd.TemplateDeclaration;
import dmd.TemplateInstance;
import dmd.TypeClass;
+import dmd.Declaration;
import dmd.Util;
import dmd.expression.Util;
@@ -92,6 +93,7 @@
TemplateInstance.semanticTiargs(loc, sc, args, 1);
size_t dim = args ? args.dim : 0;
Object o;
+ Declaration d;
FuncDeclaration f;
string ISTYPE(string cond)
@@ -172,6 +174,20 @@
{
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)
diff -r 9d194c848e3a -r 09c858522d55 dmd/Type.d
--- a/dmd/Type.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Type.d Mon Sep 13 23:29:00 2010 +0200
@@ -59,6 +59,8 @@
import dmd.DotIdExp;
import dmd.AggregateDeclaration;
import dmd.DotTemplateInstanceExp;
+import dmd.Token;
+import dmd.TypeInfoWildDeclaration;
import dmd.expression.Util;
@@ -127,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;
@@ -143,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
@@ -173,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];
@@ -493,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:
@@ -512,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))
@@ -519,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)
@@ -628,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] = '@';
@@ -736,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]);
}
@@ -832,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) {
@@ -948,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'.
@@ -982,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();
@@ -1007,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;
}
@@ -1099,6 +1177,13 @@
/********************************
* Make type unshared.
+ * 0 => 0
+ * const => const
+ * immutable => immutable
+ * shared => 0
+ * shared const => const
+ * wild => wild
+ * shared wild => wild
*/
Type unSharedOf()
{
@@ -1109,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());
@@ -1128,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)
{
@@ -1181,7 +1299,7 @@
cto = t;
break;
- case X(MOD.MODundefined, MOD.MODinvariant):
+ case X(MOD.MODundefined, MOD.MODimmutable):
ito = t;
break;
@@ -1193,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;
@@ -1208,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;
@@ -1243,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;
@@ -1256,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();
@@ -1287,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();
@@ -1331,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();
@@ -1360,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:
@@ -1396,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)
{
@@ -1410,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;
@@ -1424,6 +1684,19 @@
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;
@@ -1436,13 +1709,15 @@
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);
@@ -1514,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());
@@ -1527,7 +1804,7 @@
}
Type t = clone();
- t.mod = MOD.MODinvariant;
+ t.mod = MOD.MODimmutable;
t.deco = null;
t.arrayof = null;
@@ -1537,6 +1814,8 @@
t.ito = null;
t.sto = null;
t.scto = null;
+ t.wto = null;
+ t.swto = null;
t.vtinfo = null;
return t;
@@ -1558,6 +1837,8 @@
t.ito = null;
t.sto = null;
t.scto = null;
+ t.wto = null;
+ t.swto = null;
t.vtinfo = null;
return t;
@@ -1579,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;
@@ -1627,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;
}
@@ -1883,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
{
@@ -1995,20 +2350,24 @@
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[i] = tt;
goto Lexact;
@@ -2016,13 +2375,20 @@
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)
{
@@ -2035,10 +2401,12 @@
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[i] = tt;
@@ -2067,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
@@ -2077,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;
@@ -2204,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 {
@@ -2261,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);
@@ -2402,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 9d194c848e3a -r 09c858522d55 dmd/TypeAArray.d
--- a/dmd/TypeAArray.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeAArray.d Mon Sep 13 23:29:00 2010 +0200
@@ -116,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)
@@ -330,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)
@@ -385,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 9d194c848e3a -r 09c858522d55 dmd/TypeBasic.d
--- a/dmd/TypeBasic.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeBasic.d Mon Sep 13 23:29:00 2010 +0200
@@ -308,6 +308,7 @@
case TY.Tcomplex80:
case TY.Timaginary80:
case TY.Tfloat80: fvalue = real.min; goto Lfvalue;
+ default:
}
}
else if (ident is Id.nan)
diff -r 9d194c848e3a -r 09c858522d55 dmd/TypeClass.d
--- a/dmd/TypeClass.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeClass.d Mon Sep 13 23:29:00 2010 +0200
@@ -486,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 9d194c848e3a -r 09c858522d55 dmd/TypeDArray.d
--- a/dmd/TypeDArray.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeDArray.d Mon Sep 13 23:29:00 2010 +0200
@@ -195,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;
}
@@ -208,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[]
@@ -226,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)
@@ -234,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)
@@ -248,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()
@@ -258,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 9d194c848e3a -r 09c858522d55 dmd/TypeDelegate.d
--- a/dmd/TypeDelegate.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeDelegate.d Mon Sep 13 23:29:00 2010 +0200
@@ -113,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 9d194c848e3a -r 09c858522d55 dmd/TypeEnum.d
--- a/dmd/TypeEnum.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeEnum.d Mon Sep 13 23:29:00 2010 +0200
@@ -189,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 9d194c848e3a -r 09c858522d55 dmd/TypeFunction.d
--- a/dmd/TypeFunction.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeFunction.d Mon Sep 13 23:29:00 2010 +0200
@@ -34,6 +34,7 @@
import dmd.Util;
import dmd.FuncDeclaration;
import dmd.Dsymbol;
+import dmd.TypeTuple;
import dmd.TemplateInstance : isTuple;
import dmd.backend.TYPE;
@@ -61,6 +62,7 @@
bool isref; // true: returns a reference
LINK linkage; // calling convention
TRUST trust; // level of trust
+ Expressions fargs; // function arguments
int inuse;
@@ -88,6 +90,7 @@
t.isproperty = isproperty;
t.isref = isref;
t.trust = trust;
+ t.fargs = fargs;
return t;
}
@@ -136,7 +139,7 @@
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,
@@ -174,6 +177,7 @@
}
}
+ bool wildreturn = false;
if (tf.next)
{
tf.next = tf.next.semantic(loc,sc);
@@ -197,8 +201,14 @@
}
if (tf.next.isauto() && !(sc.flags & SCOPE.SCOPEctor))
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
@@ -210,49 +220,97 @@
size_t dim = Parameter.dim(tf.parameters);
for (size_t i = 0; i < dim; i++)
- { auto arg = Parameter.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 = Parameter.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;
@@ -287,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;
@@ -320,7 +371,7 @@
buf.writestring("Ne");
break;
case TRUST.TRUSTsafe:
- buf.writestring("Nd");
+ buf.writestring("Nf");
break;
default:
}
@@ -348,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 ");
@@ -569,16 +619,15 @@
override Type reliesOnTident()
{
- if (parameters)
- {
- foreach (arg; parameters)
- {
- 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) {
@@ -631,6 +680,8 @@
{
//printf("TypeFunction.callMatch() %s\n", toChars());
MATCH match = MATCH.MATCHexact; // assume exact match
+ bool exactwildmatch = false;
+ bool wildmatch = false;
if (ethis)
{
@@ -640,7 +691,7 @@
if (t.mod != mod)
{
- if (mod == MOD.MODconst)
+ if (MODimplicitConv(t.mod, mod))
match = MATCH.MATCHconst;
else
return MATCH.MATCHnomatch;
@@ -690,7 +741,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();
@@ -698,15 +749,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
{
diff -r 9d194c848e3a -r 09c858522d55 dmd/TypeInfoStructDeclaration.d
--- a/dmd/TypeInfoStructDeclaration.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeInfoStructDeclaration.d Mon Sep 13 23:29:00 2010 +0200
@@ -99,7 +99,7 @@
TypeFunction tfeqptr;
{
// bool opEqual(const T*) const;
- scope Scope sc = new Scope();
+ scope sc = new Scope();
auto arguments = new Parameters;
version (STRUCTTHISREF) {
// arg type is ref const T
@@ -116,7 +116,7 @@
}
{
- Scope sc;
+ scope sc = new Scope;
auto arguments = new Parameters;
version(STRUCTTHISREF) {
// arg type is ref const T
diff -r 9d194c848e3a -r 09c858522d55 dmd/TypeInfoWildDeclaration.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeInfoWildDeclaration.d Mon Sep 13 23:29:00 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 9d194c848e3a -r 09c858522d55 dmd/TypeNext.d
--- a/dmd/TypeNext.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeNext.d Mon Sep 13 23:29:00 2010 +0200
@@ -53,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;
@@ -70,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();
@@ -90,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();
}
@@ -116,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();
@@ -142,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();
}
@@ -154,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 9d194c848e3a -r 09c858522d55 dmd/TypePointer.d
--- a/dmd/TypePointer.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypePointer.d Mon Sep 13 23:29:00 2010 +0200
@@ -108,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[]
@@ -145,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 9d194c848e3a -r 09c858522d55 dmd/TypeQualified.d
--- a/dmd/TypeQualified.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeQualified.d Mon Sep 13 23:29:00 2010 +0200
@@ -22,6 +22,7 @@
import dmd.Dsymbol;
import dmd.DYNCAST;
import dmd.Expression;
+import dmd.FuncDeclaration;
import dmd.Util;
class TypeQualified : Type
@@ -100,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;
@@ -174,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);
}
@@ -195,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 9d194c848e3a -r 09c858522d55 dmd/TypeReference.d
--- a/dmd/TypeReference.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeReference.d Mon Sep 13 23:29:00 2010 +0200
@@ -10,6 +10,7 @@
import dmd.HdrGenState;
import dmd.Expression;
import dmd.Identifier;
+import dmd.NullExp;
import dmd.CppMangleState;
import dmd.TY;
@@ -56,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 9d194c848e3a -r 09c858522d55 dmd/TypeSArray.d
--- a/dmd/TypeSArray.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeSArray.d Mon Sep 13 23:29:00 2010 +0200
@@ -367,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)
@@ -381,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
)
diff -r 9d194c848e3a -r 09c858522d55 dmd/TypeStruct.d
--- a/dmd/TypeStruct.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeStruct.d Mon Sep 13 23:29:00 2010 +0200
@@ -37,6 +37,7 @@
import dmd.VarExp;
import dmd.CommaExp;
import dmd.ThisExp;
+import dmd.StructLiteralExp;
import dmd.SymbolDeclaration;
import dmd.TypeInfoDeclaration;
import dmd.TypeInfoStructDeclaration;
@@ -377,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)
{
@@ -403,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;
@@ -480,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
@@ -503,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,
@@ -547,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 9d194c848e3a -r 09c858522d55 dmd/TypeTuple.d
--- a/dmd/TypeTuple.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeTuple.d Mon Sep 13 23:29:00 2010 +0200
@@ -28,7 +28,7 @@
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)
{
@@ -68,6 +68,7 @@
}
}
this.arguments = arguments;
+ //printf("TypeTuple() %p, %s\n", this, toChars());
}
override Type syntaxCopy()
diff -r 9d194c848e3a -r 09c858522d55 dmd/TypeTypedef.d
--- a/dmd/TypeTypedef.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeTypedef.d Mon Sep 13 23:29:00 2010 +0200
@@ -213,9 +213,6 @@
override Expression defaultInit(Loc loc)
{
- Expression e;
- Type bt;
-
version (LOGDEFAULTINIT) {
printf("TypeTypedef::defaultInit() '%s'\n", toChars());
}
@@ -224,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)
{
@@ -299,6 +296,11 @@
return toBasetype().hasPointers();
}
+ override int hasWild()
+ {
+ return mod & MOD.MODwild || toBasetype().hasWild();
+ }
+
override Type toHeadMutable()
{
assert(false);
diff -r 9d194c848e3a -r 09c858522d55 dmd/TypedefDeclaration.d
--- a/dmd/TypedefDeclaration.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypedefDeclaration.d Mon Sep 13 23:29:00 2010 +0200
@@ -71,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 9d194c848e3a -r 09c858522d55 dmd/TypeidExp.d
--- a/dmd/TypeidExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/TypeidExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -43,16 +43,19 @@
Expression e;
version (LOGSEMANTIC) {
- printf("TypeidExp.semantic()\n");
+ printf("TypeidExp.semantic() %s\n", toChars());
}
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);
@@ -63,7 +66,9 @@
}
if (!ta)
- { error("no type for typeid(%s)", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
+ {
+ //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();
}
diff -r 9d194c848e3a -r 09c858522d55 dmd/UshrExp.d
--- a/dmd/UshrExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/UshrExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -75,6 +75,12 @@
override elem* toElem(IRState* irs)
{
- return toElemBin(irs, OPER.OPshr);
+ //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 9d194c848e3a -r 09c858522d55 dmd/Util.d
--- a/dmd/Util.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/Util.d Mon Sep 13 23:29:00 2010 +0200
@@ -635,6 +635,8 @@
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;
@@ -698,7 +700,7 @@
precedence[TOK.TOKmulass] = PREC.PREC_assign;
precedence[TOK.TOKdivass] = PREC.PREC_assign;
precedence[TOK.TOKmodass] = PREC.PREC_assign;
- //precedence[TOKpowass] = PREC.PREC_assign;
+ precedence[TOK.TOKpowass] = PREC.PREC_assign;
precedence[TOK.TOKshlass] = PREC.PREC_assign;
precedence[TOK.TOKshrass] = PREC.PREC_assign;
precedence[TOK.TOKushrass] = PREC.PREC_assign;
diff -r 9d194c848e3a -r 09c858522d55 dmd/VarDeclaration.d
--- a/dmd/VarDeclaration.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/VarDeclaration.d Mon Sep 13 23:29:00 2010 +0200
@@ -343,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())
{
@@ -422,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)
@@ -438,7 +447,7 @@
}
}
- if ((isConst() || isInvariant()) && !init && !fd)
+ if ((isConst() || isImmutable()) && !init && !fd)
{
// Initialize by constructor only
storage_class |= STC.STCctorinit;
@@ -652,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
@@ -795,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)
@@ -830,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);
@@ -844,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;
@@ -992,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 9d194c848e3a -r 09c858522d55 dmd/VarExp.d
--- a/dmd/VarExp.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/VarExp.d Mon Sep 13 23:29:00 2010 +0200
@@ -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)
@@ -121,12 +121,12 @@
* If it is pure, it cannot access any mutable variables other
* than those inside itself
*/
- if (hasPureParent && 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 && !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())
@@ -142,7 +142,7 @@
} 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());
}
}
@@ -207,6 +207,16 @@
}
}
}
+
+ 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)
{
diff -r 9d194c848e3a -r 09c858522d55 dmd/WhileStatement.d
--- a/dmd/WhileStatement.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/WhileStatement.d Mon Sep 13 23:29:00 2010 +0200
@@ -68,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 9d194c848e3a -r 09c858522d55 dmd/backend/iasm.d
--- a/dmd/backend/iasm.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/backend/iasm.d Mon Sep 13 23:29:00 2010 +0200
@@ -4340,7 +4340,7 @@
}
if ((v.isConst()
///version (DMDV2) {
- || v.isInvariant() || v.storage_class & STCmanifest
+ || v.isImmutable() || v.storage_class & STCmanifest
///}
) && !v.type.isfloating() && v.init)
{
diff -r 9d194c848e3a -r 09c858522d55 dmd/codegen/Util.d
--- a/dmd/codegen/Util.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/codegen/Util.d Mon Sep 13 23:29:00 2010 +0200
@@ -297,9 +297,15 @@
e = el_una(op,tyret,ep);
}
else if (ep)
- e = el_bin((tf.ispure && tf.isnothrow) ? 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 && tf.isnothrow) ? OPER.OPucallns : OPER.OPucall, tyret, ec);
+ e = el_una((tf.ispure && tf.isnothrow && (retmethod != RET.RETstack)) ?
+ OPucallns : OPucall, tyret, ec);
if (retmethod == RET.RETstack)
{
diff -r 9d194c848e3a -r 09c858522d55 dmd/expression/Util.d
--- a/dmd/expression/Util.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/expression/Util.d Mon Sep 13 23:29:00 2010 +0200
@@ -594,12 +594,12 @@
* 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 functionParameters(Loc loc, Scope sc, TypeFunction tf, Expressions arguments)
+Type functionParameters(Loc loc, Scope sc, TypeFunction tf, Expressions arguments)
{
- uint n;
-
//printf("functionParameters()\n");
assert(arguments);
size_t nargs = arguments ? arguments.dim : 0;
@@ -608,8 +608,10 @@
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++)
{
@@ -634,7 +636,7 @@
goto L2;
error(loc, "expected %d function arguments, not %d", nparams, nargs);
- return;
+ return tf.next;
}
arg = p.defaultArg;
arg = arg.copy();
@@ -654,7 +656,7 @@
if (nargs != nparams)
{
error(loc, "expected %zu function arguments, not %zu", nparams, nargs);
- return;
+ return tf.next;
}
goto L1;
}
@@ -680,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);
@@ -729,7 +732,7 @@
if (!arg)
{
error(loc, "not enough arguments");
- return;
+ return tf.next;
}
break;
}
@@ -748,7 +751,25 @@
//printf("arg.type = %s, p.type = %s\n", arg.type.toChars(), p.type.toChars());
if (arg.op == TOKtype)
arg.error("cannot pass type %s as function argument", arg.toChars());
- arg = arg.implicitCastTo(sc, p.type);
+ 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);
}
}
@@ -848,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)
@@ -893,6 +909,24 @@
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;
}
/******************************
@@ -1256,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)
{
@@ -1403,6 +1437,7 @@
break;
}
+ Dsymbol s;
AggregateDeclaration ad;
auto arg = arguments[0];
@@ -1449,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)
@@ -1456,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;
}
@@ -1474,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();
diff -r 9d194c848e3a -r 09c858522d55 dmd/interpret/Util.d
--- a/dmd/interpret/Util.d Mon Sep 13 23:27:38 2010 +0200
+++ b/dmd/interpret/Util.d Mon Sep 13 23:29:00 2010 +0200
@@ -140,7 +140,7 @@
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)
///}
@@ -152,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;
@@ -232,24 +232,6 @@
/********************************
- * 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)