Mercurial > projects > ddmd
diff dmd/TypeFunction.d @ 135:af1bebfd96a4 dmd2037
dmd 2.038
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 13 Sep 2010 22:19:42 +0100 |
parents | c494af1dba80 |
children | 95b3ed3cddd5 |
line wrap: on
line diff
--- a/dmd/TypeFunction.d Sat Sep 11 13:03:39 2010 +0100 +++ b/dmd/TypeFunction.d Mon Sep 13 22:19:42 2010 +0100 @@ -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 {