-e4f89195913be1dc638707b1abb24c4f3ae7e0bf
+c8ae4adb2eda515b09b326948e3a4aa9f489af45
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
*/
final size_t nonHiddenFields()
{
- return fields.dim - isNested() - (vthis2 !is null);
+ return fields.length - isNested() - (vthis2 !is null);
}
/***************************************
{
//printf("AggregateDeclaration::checkOverlappedFields() %s\n", toChars());
assert(sizeok == Sizeok.done);
- size_t nfields = fields.dim;
+ size_t nfields = fields.length;
if (isNested())
{
auto cd = isClassDeclaration();
const nfields = nonHiddenFields();
bool errors = false;
- size_t dim = elements.dim;
+ size_t dim = elements.length;
elements.setDim(nfields);
foreach (size_t i; dim .. nfields)
elements[i] = null;
}
}
- for (size_t i = 0; i < members.dim; i++)
+ for (size_t i = 0; i < members.length; i++)
{
auto sm = (*members)[i];
sm.apply(&SearchCtor.fp, null);
* so in order to place that member we need to compute the member's
* size and alignment.
*/
- size_t fieldstart = ad.fields.dim;
+ size_t fieldstart = ad.fields.length;
/* Hackishly hijack ad's structsize and alignsize fields
* for use in our fake anon aggregate member.
* added in ad.fields, just update *poffset for the subsequent
* field offset calculation.
*/
- if (fieldstart == ad.fields.dim)
+ if (fieldstart == ad.fields.length)
{
ad.structsize = savestructsize;
ad.alignsize = savealignsize;
// Add to the anon fields the base offset of this anonymous aggregate
//printf("anon fields, anonoffset = %d\n", anonoffset);
- foreach (const i; fieldstart .. ad.fields.dim)
+ foreach (const i; fieldstart .. ad.fields.length)
{
VarDeclaration v = ad.fields[i];
//printf("\t[%d] %s %d\n", i, v.toChars(), v.offset);
override Scope* newScope(Scope* sc)
{
Scope* sc2 = sc;
- if (atts && atts.dim)
+ if (atts && atts.length)
{
// create new one for changes
sc2 = sc.copy();
extern (D) static Expressions* concat(Expressions* udas1, Expressions* udas2)
{
Expressions* udas;
- if (!udas1 || udas1.dim == 0)
+ if (!udas1 || udas1.length == 0)
udas = udas2;
- else if (!udas2 || udas2.dim == 0)
+ else if (!udas2 || udas2.length == 0)
udas = udas1;
else
{
auto exps = new Expressions();
if (userAttribDecl && userAttribDecl !is this)
exps.push(new TupleExp(Loc.initial, userAttribDecl.getAttributes()));
- if (atts && atts.dim)
+ if (atts && atts.length)
exps.push(new TupleExp(Loc.initial, atts));
return exps;
}
override void visit(CompoundStatement cs)
{
- //printf("CompoundStatement.blockExit(%p) %d result = x%X\n", cs, cs.statements.dim, result);
+ //printf("CompoundStatement.blockExit(%p) %d result = x%X\n", cs, cs.statements.length, result);
result = BE.fallthru;
Statement slast = null;
foreach (s; *cs.statements)
ClassDeclaration cd = t.isClassHandle();
assert(cd);
- if (cd == ClassDeclaration.errorException || ClassDeclaration.errorException.isBaseOf(cd, null))
+ if (cd.isErrorException())
{
return BE.errthrow;
}
if (global.errors && !ce.e1.type)
return; // error recovery
- if (ce.f && ce.arguments.dim > 0)
+ if (ce.f && ce.arguments.length > 0)
{
Type tb = (*ce.arguments)[0].type.toBasetype();
auto tbNext = tb.nextOf();
return; // unions don't have destructors
StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
- Loc declLoc = ad.userDtors.dim ? ad.userDtors[0].loc : ad.loc;
+ Loc declLoc = ad.userDtors.length ? ad.userDtors[0].loc : ad.loc;
Loc loc; // internal code should have no loc to prevent coverage
FuncDeclaration xdtor_fwd = null;
// Build the field destructor (`ad.fieldDtor`), if needed.
// If the user dtor is an extern(C++) prototype, then we expect it performs a full-destruction and skip building.
- const bool dtorIsCppPrototype = ad.userDtors.dim && ad.userDtors[0]._linkage == LINK.cpp && !ad.userDtors[0].fbody;
+ const bool dtorIsCppPrototype = ad.userDtors.length && ad.userDtors[0]._linkage == LINK.cpp && !ad.userDtors[0].fbody;
if (!dtorIsCppPrototype)
{
Expression e = null;
- for (size_t i = 0; i < ad.fields.dim; i++)
+ for (size_t i = 0; i < ad.fields.length; i++)
{
auto v = ad.fields[i];
if (v.storage_class & STC.ref_)
}
// Set/build `ad.aggrDtor`
- switch (dtors.dim)
+ switch (dtors.length)
{
case 0:
break;
*/
FuncDeclaration buildInv(AggregateDeclaration ad, Scope* sc)
{
- switch (ad.invs.dim)
+ switch (ad.invs.length)
{
case 0:
return null;
if (sd.isUnionDeclaration())
return null;
- const hasUserDefinedPosblit = sd.postblits.dim && !sd.postblits[0].isDisabled ? true : false;
+ const hasUserDefinedPosblit = sd.postblits.length && !sd.postblits[0].isDisabled ? true : false;
// by default, the storage class of the created postblit
StorageClass stc = STC.safe | STC.nothrow_ | STC.pure_ | STC.nogc;
- Loc declLoc = sd.postblits.dim ? sd.postblits[0].loc : sd.loc;
+ Loc declLoc = sd.postblits.length ? sd.postblits[0].loc : sd.loc;
Loc loc; // internal code should have no loc to prevent coverage
// if any of the postblits are disabled, then the generated postblit
VarDeclaration[] fieldsToDestroy;
auto postblitCalls = new Statements();
// iterate through all the struct fields that are not disabled
- for (size_t i = 0; i < sd.fields.dim && !(stc & STC.disable); i++)
+ for (size_t i = 0; i < sd.fields.length && !(stc & STC.disable); i++)
{
auto structField = sd.fields[i];
if (structField.storage_class & STC.ref_)
}
// Build our own "postblit" which executes a, but only if needed.
- if (postblitCalls.dim || (stc & STC.disable))
+ if (postblitCalls.length || (stc & STC.disable))
{
//printf("Building __fieldPostBlit()\n");
checkShared();
// create __xpostblit, which is the generated postblit
FuncDeclaration xpostblit = null;
- switch (sd.postblits.dim)
+ switch (sd.postblits.length)
{
case 0:
break;
}
else
{
- assert(rangefe && parameters.dim == 1);
+ assert(rangefe && parameters.length == 1);
return new ForeachRangeStatement(loc, rangefe.op, (*parameters)[0], rangefe.lwr.syntaxCopy(), rangefe.upr.syntaxCopy(), s, loc);
}
}
private void lowerNonArrayAggregate(Scope* sc)
{
- auto nvars = aggrfe ? aggrfe.parameters.dim : 1;
+ auto nvars = aggrfe ? aggrfe.parameters.length : 1;
auto aloc = aggrfe ? aggrfe.aggr.loc : rangefe.lwr.loc;
// We need three sets of foreach loop variables because the
// lowering contains three foreach loops.
{
foreach (i; 0 .. 2)
{
- auto e = new Expressions(pparams[0].dim);
+ auto e = new Expressions(pparams[0].length);
foreach (j, ref elem; *e)
{
auto p = (*pparams[i])[j];
}
else if (ArrayLiteralExp es2 = e2.isArrayLiteralExp())
{
- cmp = !es2.elements || (0 == es2.elements.dim);
+ cmp = !es2.elements || (0 == es2.elements.length);
}
else
{
}
else if (ArrayLiteralExp es1 = e1.isArrayLiteralExp())
{
- cmp = !es1.elements || (0 == es1.elements.dim);
+ cmp = !es1.elements || (0 == es1.elements.length);
}
else
{
{
ArrayLiteralExp es1 = e1.isArrayLiteralExp();
ArrayLiteralExp es2 = e2.isArrayLiteralExp();
- if ((!es1.elements || !es1.elements.dim) && (!es2.elements || !es2.elements.dim))
+ if ((!es1.elements || !es1.elements.length) && (!es2.elements || !es2.elements.length))
cmp = 1; // both arrays are empty
else if (!es1.elements || !es2.elements)
cmp = 0;
- else if (es1.elements.dim != es2.elements.dim)
+ else if (es1.elements.length != es2.elements.length)
cmp = 0;
else
{
- for (size_t i = 0; i < es1.elements.dim; i++)
+ for (size_t i = 0; i < es1.elements.length; i++)
{
auto ee1 = es1[i];
auto ee2 = es2[i];
StringExp es1 = e1.isStringExp();
ArrayLiteralExp es2 = e2.isArrayLiteralExp();
size_t dim1 = es1.len;
- size_t dim2 = es2.elements ? es2.elements.dim : 0;
+ size_t dim2 = es2.elements ? es2.elements.length : 0;
if (dim1 != dim2)
cmp = 0;
else
StructLiteralExp es2 = e2.isStructLiteralExp();
if (es1.sd != es2.sd)
cmp = 0;
- else if ((!es1.elements || !es1.elements.dim) && (!es2.elements || !es2.elements.dim))
+ else if ((!es1.elements || !es1.elements.length) && (!es2.elements || !es2.elements.length))
cmp = 1; // both arrays are empty
else if (!es1.elements || !es2.elements)
cmp = 0;
- else if (es1.elements.dim != es2.elements.dim)
+ else if (es1.elements.length != es2.elements.length)
cmp = 0;
else
{
cmp = 1;
- for (size_t i = 0; i < es1.elements.dim; i++)
+ for (size_t i = 0; i < es1.elements.length; i++)
{
Expression ee1 = (*es1.elements)[i];
Expression ee2 = (*es2.elements)[i];
StructDeclaration sd = tb.toDsymbol(null).isStructDeclaration();
assert(sd);
auto elements = new Expressions();
- for (size_t i = 0; i < sd.fields.dim; i++)
+ for (size_t i = 0; i < sd.fields.length; i++)
{
VarDeclaration v = sd.fields[i];
UnionExp zero;
}
else if (ArrayLiteralExp ale = e1.isArrayLiteralExp())
{
- size_t dim = ale.elements ? ale.elements.dim : 0;
+ size_t dim = ale.elements ? ale.elements.length : 0;
emplaceExp!(IntegerExp)(&ue, loc, dim, type);
}
else if (AssocArrayLiteralExp ale = e1.isAssocArrayLiteralExp)
{
- size_t dim = ale.keys.dim;
+ size_t dim = ale.keys.length;
emplaceExp!(IntegerExp)(&ue, loc, dim, type);
}
else if (e1.type.toBasetype().ty == Tsarray)
uinteger_t i = e2.toInteger();
if (ArrayLiteralExp ale = e1.isArrayLiteralExp())
{
- if (i >= ale.elements.dim)
+ if (i >= ale.elements.length)
{
- e1.error("array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), cast(ulong) ale.elements.dim);
+ e1.error("array index %llu is out of bounds `%s[0 .. %llu]`", i, e1.toChars(), cast(ulong) ale.elements.length);
emplaceExp!(ErrorExp)(&ue);
}
else
{
/* Search the keys backwards, in case there are duplicate keys
*/
- for (size_t i = ae.keys.dim; i;)
+ for (size_t i = ae.keys.length; i;)
{
i--;
Expression ekey = (*ae.keys)[i];
ArrayLiteralExp es1 = e1.isArrayLiteralExp();
const uinteger_t ilwr = lwr.toInteger();
const uinteger_t iupr = upr.toInteger();
- if (sliceBoundsCheck(0, es1.elements.dim, ilwr, iupr))
+ if (sliceBoundsCheck(0, es1.elements.length, ilwr, iupr))
cantExp(ue);
else
{
void sliceAssignStringFromArrayLiteral(StringExp existingSE, ArrayLiteralExp newae, size_t firstIndex)
{
assert(existingSE.ownedByCtfe != OwnedBy.code);
- foreach (j; 0 .. newae.elements.dim)
+ foreach (j; 0 .. newae.elements.length)
{
existingSE.setCodeUnit(firstIndex + j, cast(dchar)newae[j].toInteger());
}
{
if (!ale.elements)
return;
- auto d = elems.dim;
+ auto d = elems.length;
elems.append(ale.elements);
- foreach (ref el; (*elems)[d .. elems.dim])
+ foreach (ref el; (*elems)[d .. elems.length])
{
if (!el)
el = ale.basis;
// [chars] ~ string --> [chars]
StringExp es = e2.isStringExp();
ArrayLiteralExp ea = e1.isArrayLiteralExp();
- size_t len = es.len + ea.elements.dim;
+ size_t len = es.len + ea.elements.length;
auto elems = new Expressions(len);
- for (size_t i = 0; i < ea.elements.dim; ++i)
+ for (size_t i = 0; i < ea.elements.length; ++i)
{
(*elems)[i] = ea[i];
}
emplaceExp!(ArrayLiteralExp)(&ue, e1.loc, type, elems);
ArrayLiteralExp dest = ue.exp().isArrayLiteralExp();
- sliceAssignArrayLiteralFromString(dest, es, ea.elements.dim);
+ sliceAssignArrayLiteralFromString(dest, es, ea.elements.length);
assert(ue.exp().type);
return ue;
}
// string ~ [chars] --> [chars]
StringExp es = e1.isStringExp();
ArrayLiteralExp ea = e2.isArrayLiteralExp();
- size_t len = es.len + ea.elements.dim;
+ size_t len = es.len + ea.elements.length;
auto elems = new Expressions(len);
- for (size_t i = 0; i < ea.elements.dim; ++i)
+ for (size_t i = 0; i < ea.elements.length; ++i)
{
(*elems)[es.len + i] = ea[i];
}
e = ue.exp();
if (type.toBasetype().ty == Tsarray)
{
- e.type = t1.nextOf().sarrayOf(elems.dim);
+ e.type = t1.nextOf().sarrayOf(elems.length);
}
else
e.type = type;
e = ue.exp();
if (type.toBasetype().ty == Tsarray)
{
- e.type = t1.nextOf().sarrayOf(elems.dim);
+ e.type = t1.nextOf().sarrayOf(elems.length);
}
else
e.type = type;
e = ue.exp();
if (type.toBasetype().ty == Tsarray)
{
- e.type = e2.type.sarrayOf(elems.dim);
+ e.type = e2.type.sarrayOf(elems.length);
}
else
e.type = type;
e = ue.exp();
if (type.toBasetype().ty == Tsarray)
{
- e.type = e1.type.sarrayOf(elems.dim);
+ e.type = e1.type.sarrayOf(elems.length);
}
else
e.type = type;
else if (auto tt = t.isTypeTag())
tt.mod |= MODFlags.const_;
else
- t = t.addSTC(STC.const_);
+ {
+ /* Ignore const if the result would be const pointer to mutable
+ */
+ auto tn = t.nextOf();
+ if (!tn || tn.isConst())
+ t = t.addSTC(STC.const_);
+ }
return t;
}
{
/* <template-args> ::= I <template-arg>+ E
*/
- if (!ti || ti.tiargs.dim <= firstArg) // could happen if std::basic_string is not a template
+ if (!ti || ti.tiargs.length <= firstArg) // could happen if std::basic_string is not a template
return false;
buf.writeByte('I');
- foreach (i; firstArg .. ti.tiargs.dim)
+ foreach (i; firstArg .. ti.tiargs.length)
{
TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration();
assert(td);
buf.writeByte('J'); // argument pack
// mangle the rest of the arguments as types
- foreach (j; i .. (*ti.tiargs).dim)
+ foreach (j; i .. (*ti.tiargs).length)
{
Type t = isType((*ti.tiargs)[j]);
assert(t);
return false;
Dsymbol q = getQualifier(ti);
const bool inStd = isStd(q) || isStd(this.getTiNamespace(ti));
- return inStd && ti.tiargs.dim == 1 && isChar((*ti.tiargs)[0]);
+ return inStd && ti.tiargs.length == 1 && isChar((*ti.tiargs)[0]);
}
/***
*/
bool char_std_char_traits_char(TemplateInstance ti, string st)
{
- if (ti.tiargs.dim == 2 &&
+ if (ti.tiargs.length == 2 &&
isChar((*ti.tiargs)[0]) &&
isChar_traits_char((*ti.tiargs)[1]))
{
if (ti.name == Id.basic_string)
{
// ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
- if (ti.tiargs.dim == 3 &&
+ if (ti.tiargs.length == 3 &&
isChar((*ti.tiargs)[0]) &&
isChar_traits_char((*ti.tiargs)[1]) &&
isAllocator_char((*ti.tiargs)[2]))
else if (s.ident == Id.basic_string)
{
// ::std::basic_string<char, ::std::char_traits<char>, ::std::allocator<char>>
- if (ti.tiargs.dim == 3 &&
+ if (ti.tiargs.length == 3 &&
isChar((*ti.tiargs)[0]) &&
isChar_traits_char((*ti.tiargs)[1]) &&
isAllocator_char((*ti.tiargs)[2]))
case CppOperator.OpAssign:
TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration();
assert(td);
- assert(ti.tiargs.dim >= 1);
+ assert(ti.tiargs.length >= 1);
TemplateParameter tp = (*td.parameters)[0];
TemplateValueParameter tv = tp.isTemplateValueParameter();
if (!tv || !tv.valType.isString())
this.context.res = (*analyzed_ti.tiargs)[idx];
o.visitObject(this);
}
- if (analyzed_ti.tiargs.dim > t.tiargs.dim)
+ if (analyzed_ti.tiargs.length > t.tiargs.length)
{
// If the resolved AST has more args than the parse one,
// we have default arguments
auto oparams = (cast(TemplateDeclaration)analyzed_ti.tempdecl).origParameters;
- foreach (idx, arg; (*oparams)[t.tiargs.dim .. $])
+ foreach (idx, arg; (*oparams)[t.tiargs.length .. $])
{
- this.context.res = (*analyzed_ti.tiargs)[idx + t.tiargs.dim];
+ this.context.res = (*analyzed_ti.tiargs)[idx + t.tiargs.length];
if (auto ttp = arg.isTemplateTypeParameter())
ttp.defaultType.accept(this);
{
ClassDeclaration cd = originalClass();
uint fieldsSoFar = 0;
- for (size_t j = 0; j < value.elements.dim; j++)
+ for (size_t j = 0; j < value.elements.length; j++)
{
- while (j - fieldsSoFar >= cd.fields.dim)
+ while (j - fieldsSoFar >= cd.fields.length)
{
- fieldsSoFar += cd.fields.dim;
+ fieldsSoFar += cd.fields.length;
cd = cd.baseClass;
}
VarDeclaration v2 = cd.fields[j - fieldsSoFar];
if (fieldoffset == v2.offset && fieldtype.size() == v2.type.size())
{
- return cast(int)(value.elements.dim - fieldsSoFar - cd.fields.dim + (j - fieldsSoFar));
+ return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar));
}
}
return -1;
{
ClassDeclaration cd = originalClass();
size_t fieldsSoFar = 0;
- for (size_t j = 0; j < value.elements.dim; j++)
+ for (size_t j = 0; j < value.elements.length; j++)
{
- while (j - fieldsSoFar >= cd.fields.dim)
+ while (j - fieldsSoFar >= cd.fields.length)
{
- fieldsSoFar += cd.fields.dim;
+ fieldsSoFar += cd.fields.length;
cd = cd.baseClass;
}
VarDeclaration v2 = cd.fields[j - fieldsSoFar];
if (v == v2)
{
- return cast(int)(value.elements.dim - fieldsSoFar - cd.fields.dim + (j - fieldsSoFar));
+ return cast(int)(value.elements.length - fieldsSoFar - cd.fields.length + (j - fieldsSoFar));
}
}
return -1;
if (!oldelems)
return oldelems;
incArrayAllocs();
- auto newelems = new Expressions(oldelems.dim);
+ auto newelems = new Expressions(oldelems.length);
foreach (i, el; *oldelems)
{
(*newelems)[i] = copyLiteral(el ? el : basis).copy();
* an int[4] array can be initialized with a single int.
*/
auto oldelems = sle.elements;
- auto newelems = new Expressions(oldelems.dim);
+ auto newelems = new Expressions(oldelems.length);
foreach (i, ref el; *newelems)
{
// We need the struct definition to detect block assignment
case EXP.arrayLiteral:
{
const ale = e.isArrayLiteralExp();
- return ale.elements ? ale.elements.dim : 0;
+ return ale.elements ? ale.elements.length : 0;
}
case EXP.assocArrayLiteral:
{
- return e.isAssocArrayLiteralExp().keys.dim;
+ return e.isAssocArrayLiteralExp().keys.length;
}
default:
// For structs, we only need to return 0 or 1 (< and > aren't legal).
if (es1.sd != es2.sd)
return 1;
- else if ((!es1.elements || !es1.elements.dim) && (!es2.elements || !es2.elements.dim))
+ else if ((!es1.elements || !es1.elements.length) && (!es2.elements || !es2.elements.length))
return 0; // both arrays are empty
else if (!es1.elements || !es2.elements)
return 1;
- else if (es1.elements.dim != es2.elements.dim)
+ else if (es1.elements.length != es2.elements.length)
return 1;
else
{
- foreach (size_t i; 0 .. es1.elements.dim)
+ foreach (size_t i; 0 .. es1.elements.length)
{
Expression ee1 = (*es1.elements)[i];
Expression ee2 = (*es2.elements)[i];
{
AssocArrayLiteralExp es1 = e1.isAssocArrayLiteralExp();
AssocArrayLiteralExp es2 = e2.isAssocArrayLiteralExp();
- size_t dim = es1.keys.dim;
- if (es2.keys.dim != dim)
+ size_t dim = es1.keys.length;
+ if (es2.keys.length != dim)
return 1;
bool* used = cast(bool*)mem.xmalloc(bool.sizeof * dim);
memset(used, 0, bool.sizeof * dim);
}
else if (e1.op == EXP.assocArrayLiteral && e2.op == EXP.null_)
{
- return e1.isAssocArrayLiteralExp.keys.dim != 0;
+ return e1.isAssocArrayLiteralExp.keys.length != 0;
}
else if (e1.op == EXP.null_ && e2.op == EXP.assocArrayLiteral)
{
- return e2.isAssocArrayLiteralExp.keys.dim != 0;
+ return e2.isAssocArrayLiteralExp.keys.length != 0;
}
error(loc, "CTFE internal error: bad compare of `%s` and `%s`", e1.toChars(), e2.toChars());
// [chars] ~ string => string (only valid for CTFE)
StringExp es1 = e2.isStringExp();
ArrayLiteralExp es2 = e1.isArrayLiteralExp();
- const len = es1.len + es2.elements.dim;
+ const len = es1.len + es2.elements.length;
const sz = es1.sz;
void* s = mem.xmalloc((len + 1) * sz);
const data1 = es1.peekData();
- memcpy(cast(char*)s + sz * es2.elements.dim, data1.ptr, data1.length);
- foreach (size_t i; 0 .. es2.elements.dim)
+ memcpy(cast(char*)s + sz * es2.elements.length, data1.ptr, data1.length);
+ foreach (size_t i; 0 .. es2.elements.length)
{
Expression es2e = (*es2.elements)[i];
if (es2e.op != EXP.int64)
// Concatenate the strings
StringExp es1 = e1.isStringExp();
ArrayLiteralExp es2 = e2.isArrayLiteralExp();
- const len = es1.len + es2.elements.dim;
+ const len = es1.len + es2.elements.length;
const sz = es1.sz;
void* s = mem.xmalloc((len + 1) * sz);
auto slice = es1.peekData();
memcpy(s, slice.ptr, slice.length);
- foreach (size_t i; 0 .. es2.elements.dim)
+ foreach (size_t i; 0 .. es2.elements.length)
{
Expression es2e = (*es2.elements)[i];
if (es2e.op != EXP.int64)
ArrayLiteralExp es2 = e2.isArrayLiteralExp();
emplaceExp!(ArrayLiteralExp)(&ue, es1.loc, type, copyLiteralArray(es1.elements));
es1 = ue.exp().isArrayLiteralExp();
- es1.elements.insert(es1.elements.dim, copyLiteralArray(es2.elements));
+ es1.elements.insert(es1.elements.length, copyLiteralArray(es2.elements));
return ue;
}
if (e1.op == EXP.arrayLiteral && e2.op == EXP.null_ && t1.nextOf().equals(t2.nextOf()))
{
/* Search the keys backwards, in case there are duplicate keys
*/
- for (size_t i = ae.keys.dim; i;)
+ for (size_t i = ae.keys.length; i;)
{
--i;
Expression ekey = (*ae.keys)[i];
if (auto ale = e1.isArrayLiteralExp())
{
- if (indx >= ale.elements.dim)
+ if (indx >= ale.elements.length)
{
- error(loc, "array index %llu is out of bounds `%s[0 .. %llu]`", indx, e1.toChars(), cast(ulong)ale.elements.dim);
+ error(loc, "array index %llu is out of bounds `%s[0 .. %llu]`", indx, e1.toChars(), cast(ulong)ale.elements.length);
return CTFEExp.cantexp;
}
Expression e = (*ale.elements)[cast(size_t)indx];
newelems = src.isStructLiteralExp().elements;
auto sd = dest.isStructLiteralExp().sd;
const nfields = sd.nonHiddenFields();
- const nvthis = sd.fields.dim - nfields;
- if (nvthis && oldelems.dim >= nfields && oldelems.dim < newelems.dim)
- foreach (_; 0 .. newelems.dim - oldelems.dim)
+ const nvthis = sd.fields.length - nfields;
+ if (nvthis && oldelems.length >= nfields && oldelems.length < newelems.length)
+ foreach (_; 0 .. newelems.length - oldelems.length)
oldelems.push(null);
}
else if (dest.op == EXP.arrayLiteral && src.op == EXP.arrayLiteral)
printf("invalid op %d %d\n", src.op, dest.op);
assert(0);
}
- assert(oldelems.dim == newelems.dim);
- foreach (size_t i; 0 .. oldelems.dim)
+ assert(oldelems.length == newelems.length);
+ foreach (size_t i; 0 .. oldelems.length)
{
Expression e = (*newelems)[i];
Expression o = (*oldelems)[i];
Expressions* keysx = aae.keys;
Expressions* valuesx = aae.values;
int updated = 0;
- for (size_t j = valuesx.dim; j;)
+ for (size_t j = valuesx.length; j;)
{
j--;
Expression ekey = (*aae.keys)[j];
if (elements)
{
size_t fieldsSoFar = 0;
- for (size_t i = 0; i < elements.dim; i++)
+ for (size_t i = 0; i < elements.length; i++)
{
Expression z = null;
VarDeclaration v = null;
if (i > 15)
{
- printf("...(total %d elements)\n", cast(int)elements.dim);
+ printf("...(total %d elements)\n", cast(int)elements.length);
return;
}
if (sd)
}
else if (cd)
{
- while (i - fieldsSoFar >= cd.fields.dim)
+ while (i - fieldsSoFar >= cd.fields.length)
{
- fieldsSoFar += cd.fields.dim;
+ fieldsSoFar += cd.fields.length;
cd = cd.baseClass;
for (int j = level; j > 0; --j)
printf(" ");
printf(" BASE CLASS: %s\n", cd.toChars());
}
v = cd.fields[i - fieldsSoFar];
- assert((elements.dim + i) >= (fieldsSoFar + cd.fields.dim));
- size_t indx = (elements.dim - fieldsSoFar) - cd.fields.dim + i;
- assert(indx < elements.dim);
+ assert((elements.length + i) >= (fieldsSoFar + cd.fields.length));
+ size_t indx = (elements.length - fieldsSoFar) - cd.fields.length + i;
+ assert(indx < elements.length);
z = (*elements)[indx];
}
if (!z)
else if (t.ty == Tstruct)
{
TypeStruct ts = cast(TypeStruct)t;
- auto exps = new Expressions(ts.sym.fields.dim);
- foreach (size_t i; 0 .. ts.sym.fields.dim)
+ auto exps = new Expressions(ts.sym.fields.length);
+ foreach (size_t i; 0 .. ts.sym.fields.length)
{
(*exps)[i] = voidInitLiteral(ts.sym.fields[i].type, ts.sym.fields[i]).copy();
}
{
Type tb = t.toBasetype();
Type tx = (tb.ty == Tsarray)
- ? tb.nextOf().sarrayOf(ale.elements ? ale.elements.dim : 0)
+ ? tb.nextOf().sarrayOf(ale.elements ? ale.elements.length : 0)
: tb.nextOf().arrayOf();
se.e1 = ale.implicitCastTo(sc, tx);
}
{
const size_t nparams = tf.parameterList.length;
const size_t j = tf.isDstyleVariadic(); // if TypeInfoArray was prepended
- foreach (const i; j .. args.dim)
+ foreach (const i; j .. args.length)
{
Expression earg = (*args)[i];
Type targ = earg.type.toBasetype();
if (auto tsa = tb.isTypeSArray())
{
- if (e.elements.dim != tsa.dim.toInteger())
+ if (e.elements.length != tsa.dim.toInteger())
result = MATCH.nomatch;
}
Type telement = tb.nextOf();
- if (!e.elements.dim)
+ if (!e.elements.length)
{
if (typen.ty != Tvoid)
result = typen.implicitConvTo(telement);
if (m < result)
result = m;
}
- for (size_t i = 0; i < e.elements.dim; i++)
+ for (size_t i = 0; i < e.elements.length; i++)
{
Expression el = (*e.elements)[i];
if (result == MATCH.nomatch)
TypeVector tv = tb.isTypeVector();
TypeSArray tbase = tv.basetype.isTypeSArray();
assert(tbase);
- const edim = e.elements.dim;
+ const edim = e.elements.length;
const tbasedim = tbase.dim.toInteger();
if (edim > tbasedim)
{
*/
if (!e.member && e.arguments)
{
- for (size_t i = 0; i < e.arguments.dim; ++i)
+ for (size_t i = 0; i < e.arguments.length; ++i)
{
Expression earg = (*e.arguments)[i];
if (!earg) // https://issues.dlang.org/show_bug.cgi?id=14853
{
extern (C++) static bool convertible(Expression e, ClassDeclaration cd, MOD mod)
{
- for (size_t i = 0; i < cd.fields.dim; i++)
+ for (size_t i = 0; i < cd.fields.length; i++)
{
VarDeclaration v = cd.fields[i];
Initializer _init = v._init;
{
OverExp eo = e.e1.isOverExp();
FuncDeclaration f = null;
- for (size_t i = 0; i < eo.vars.a.dim; i++)
+ for (size_t i = 0; i < eo.vars.a.length; i++)
{
auto s = eo.vars.a[i];
auto f2 = s.isFuncDeclaration();
TupleExp te = e.copy().isTupleExp();
te.e0 = e.e0 ? e.e0.copy() : null;
te.exps = e.exps.copy();
- for (size_t i = 0; i < te.exps.dim; i++)
+ for (size_t i = 0; i < te.exps.length; i++)
{
Expression ex = (*te.exps)[i];
ex = ex.castTo(sc, totuple ? (*totuple.arguments)[i].type : t);
{
if (auto tsa = tb.isTypeSArray())
{
- if (e.elements.dim != tsa.dim.toInteger())
+ if (e.elements.length != tsa.dim.toInteger())
goto L1;
}
if (e.basis)
ae.basis = e.basis.castTo(sc, tb.nextOf());
ae.elements = e.elements.copy();
- for (size_t i = 0; i < e.elements.dim; i++)
+ for (size_t i = 0; i < e.elements.length; i++)
{
Expression ex = (*e.elements)[i];
if (!ex)
TypeVector tv = tb.isTypeVector();
TypeSArray tbase = tv.basetype.isTypeSArray();
assert(tbase.ty == Tsarray);
- const edim = e.elements.dim;
+ const edim = e.elements.length;
const tbasedim = tbase.dim.toInteger();
if (edim > tbasedim)
goto L1;
AssocArrayLiteralExp ae = e.copy().isAssocArrayLiteralExp();
ae.keys = e.keys.copy();
ae.values = e.values.copy();
- assert(e.keys.dim == e.values.dim);
- for (size_t i = 0; i < e.keys.dim; i++)
+ assert(e.keys.length == e.values.length);
+ for (size_t i = 0; i < e.keys.length; i++)
{
Expression ex = (*e.values)[i];
ex = ex.castTo(sc, tb.nextOf());
Type tn = tb.nextOf();
if (ale.basis)
ale.basis = inferType(ale.basis, tn, flag);
- for (size_t i = 0; i < ale.elements.dim; i++)
+ for (size_t i = 0; i < ale.elements.length; i++)
{
if (Expression e = (*ale.elements)[i])
{
{
Type ti = taa.index;
Type tv = taa.nextOf();
- for (size_t i = 0; i < aale.keys.dim; i++)
+ for (size_t i = 0; i < aale.keys.length; i++)
{
if (Expression e = (*aale.keys)[i])
{
(*aale.keys)[i] = e;
}
}
- for (size_t i = 0; i < aale.values.dim; i++)
+ for (size_t i = 0; i < aale.values.length; i++)
{
if (Expression e = (*aale.values)[i])
{
*/
private bool isVoidArrayLiteral(Expression e, Type other)
{
- while (e.op == EXP.arrayLiteral && e.type.ty == Tarray && (e.isArrayLiteralExp().elements.dim == 1))
+ while (e.op == EXP.arrayLiteral && e.type.ty == Tarray && (e.isArrayLiteralExp().elements.length == 1))
{
auto ale = e.isArrayLiteralExp();
e = ale[0];
if (other.ty != Tsarray && other.ty != Tarray)
return false;
Type t = e.type;
- return (e.op == EXP.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && e.isArrayLiteralExp().elements.dim == 0);
+ return (e.op == EXP.arrayLiteral && t.ty == Tarray && t.nextOf().ty == Tvoid && e.isArrayLiteralExp().elements.length == 0);
}
/**
//printf("BaseClass.fillVtbl(this='%s', cd='%s')\n", sym.toChars(), cd.toChars());
if (vtbl)
- vtbl.setDim(sym.vtbl.dim);
+ vtbl.setDim(sym.vtbl.length);
// first entry is ClassInfo reference
- for (size_t j = sym.vtblOffset(); j < sym.vtbl.dim; j++)
+ for (size_t j = sym.vtblOffset(); j < sym.vtbl.length; j++)
{
FuncDeclaration ifd = sym.vtbl[j].isFuncDeclaration();
BaseClass* b = &baseInterfaces[i];
BaseClass* b2 = sym.interfaces[i];
- assert(b2.vtbl.dim == 0); // should not be filled yet
+ assert(b2.vtbl.length == 0); // should not be filled yet
memcpy(b, b2, BaseClass.sizeof);
if (i) // single inheritance is i==0
this.members = members;
- //printf("ClassDeclaration(%s), dim = %d\n", ident.toChars(), this.baseclasses.dim);
+ //printf("ClassDeclaration(%s), dim = %d\n", ident.toChars(), this.baseclasses.length);
// For forward references
type = new TypeClass(this);
cd.storage_class |= storage_class;
- cd.baseclasses.setDim(this.baseclasses.dim);
- for (size_t i = 0; i < cd.baseclasses.dim; i++)
+ cd.baseclasses.setDim(this.baseclasses.length);
+ for (size_t i = 0; i < cd.baseclasses.length; i++)
{
BaseClass* b = (*this.baseclasses)[i];
auto b2 = new BaseClass(b.type.syntaxCopy());
if (!cd)
return false;
//printf("ClassDeclaration.isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
- for (size_t i = 0; i < cd.baseclasses.dim; i++)
+ for (size_t i = 0; i < cd.baseclasses.length; i++)
{
BaseClass* b = (*cd.baseclasses)[i];
if (b.sym == this || isBaseOf2(b.sym))
if (!b.sym.alignsize)
b.sym.alignsize = target.ptrsize;
alignmember(structalign_t(cast(ushort)b.sym.alignsize), b.sym.alignsize, &offset);
- assert(bi < vtblInterfaces.dim);
+ assert(bi < vtblInterfaces.length);
BaseClass* bv = (*vtblInterfaces)[bi];
if (b.sym.interfaces.length == 0)
return 0;
}
- for (size_t i = 0; i < members.dim; i++)
+ for (size_t i = 0; i < members.length; i++)
{
auto s = (*members)[i];
if (s.apply(&func))
return 0;
}
- for (size_t i = 0; i < members.dim; i++)
+ for (size_t i = 0; i < members.length; i++)
{
auto s = (*members)[i];
s.apply(&virtualSemantic);
/* Finally, check the vtbl[]
*/
- foreach (i; 1 .. vtbl.dim)
+ foreach (i; 1 .. vtbl.length)
{
auto fd = vtbl[i].isFuncDeclaration();
//if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd.loc.toChars(), fd.toPrettyChars());
{
if (!vtblsym)
{
- auto vtype = Type.tvoidptr.immutableOf().sarrayOf(vtbl.dim);
+ auto vtype = Type.tvoidptr.immutableOf().sarrayOf(vtbl.length);
auto var = new VarDeclaration(loc, vtype, Identifier.idPool("__vtbl"), null, STC.immutable_ | STC.static_);
var.addMember(null, this);
var.isdataseg = 1;
return vtblsym;
}
+ extern (D) final bool isErrorException()
+ {
+ return errorException && (this == errorException || errorException.isBaseOf(this, null));
+ }
+
override final inout(ClassDeclaration) isClassDeclaration() inout @nogc nothrow pure @safe
{
return this;
}
bool result = false;
- for (size_t i = iStart; i < ad.fields.dim; i++)
+ for (size_t i = iStart; i < ad.fields.length; i++)
{
VarDeclaration vd = ad.fields[i];
Type tb = vd.type.baseElemOf();
{
auto sd = p.isStructDeclaration();
assert(sd);
- for (size_t i = 0; i < sd.fields.dim; i++)
+ for (size_t i = 0; i < sd.fields.length; i++)
{
auto structField = sd.fields[i];
if (structField.overlapped)
{
/* It's only a type tuple if all the Object's are types
*/
- for (size_t i = 0; i < objects.dim; i++)
+ for (size_t i = 0; i < objects.length; i++)
{
RootObject o = (*objects)[i];
if (o.dyncast() != DYNCAST.type)
/* We know it's a type tuple, so build the TypeTuple
*/
Types* types = cast(Types*)objects;
- auto args = new Parameters(objects.dim);
+ auto args = new Parameters(objects.length);
OutBuffer buf;
int hasdeco = 1;
- for (size_t i = 0; i < types.dim; i++)
+ for (size_t i = 0; i < types.length; i++)
{
Type t = (*types)[i];
//printf("type = %s\n", t.toChars());
override Dsymbol toAlias2()
{
//printf("TupleDeclaration::toAlias2() '%s' objects = %s\n", toChars(), objects.toChars());
- for (size_t i = 0; i < objects.dim; i++)
+ for (size_t i = 0; i < objects.length; i++)
{
RootObject o = (*objects)[i];
if (Dsymbol s = isDsymbol(o))
fieldState.offset = ad.structsize; // https://issues.dlang.org/show_bug.cgi?id=13613
return;
}
- for (size_t i = 0; i < ad.fields.dim; i++)
+ for (size_t i = 0; i < ad.fields.length; i++)
{
if (ad.fields[i] == this)
{
if (!vd || !pfd)
return;
// move to fd's closure when applicable
- foreach (i; 0 .. pfd.closureVars.dim)
+ foreach (i; 0 .. pfd.closureVars.length)
{
if (vd == pfd.closureVars[i])
{
version (none)
{
printf("EnumDeclaration::addMember() %s\n", toChars());
- for (size_t i = 0; i < members.dim; i++)
+ for (size_t i = 0; i < members.length; i++)
{
EnumMember em = (*members)[i].isEnumMember();
printf(" member %s\n", em.toChars());
return handleErrors();
}
- foreach (const i; 0 .. members.dim)
+ foreach (const i; 0 .. members.length)
{
EnumMember em = (*members)[i].isEnumMember();
if (em)
assert(!s);
auto si = new Import(loc, packages, id, aliasId, isstatic);
si.comment = comment;
- for (size_t i = 0; i < names.dim; i++)
+ for (size_t i = 0; i < names.length; i++)
{
si.addAlias(names[i], aliases[i]);
}
mod.checkImportDeprecation(loc, sc);
if (sc.explicitVisibility)
visibility = sc.visibility;
- if (!isstatic && !aliasId && !names.dim)
+ if (!isstatic && !aliasId && !names.length)
sc.scopesym.importScope(mod, visibility);
// Enable access to pkgs/mod as soon as posible, because compiler
// can traverse them before the import gets semantic (Issue: 21501)
- if (!aliasId && !names.dim)
+ if (!aliasId && !names.length)
addPackageAccess(sc.scopesym);
}
override void addMember(Scope* sc, ScopeDsymbol sd)
{
//printf("Import.addMember(this=%s, sd=%s, sc=%p)\n", toChars(), sd.toChars(), sc);
- if (names.dim == 0)
+ if (names.length == 0)
return Dsymbol.addMember(sc, sd);
if (aliasId)
Dsymbol.addMember(sc, sd);
/* Instead of adding the import to sd's symbol table,
* add each of the alias=name pairs
*/
- for (size_t i = 0; i < names.dim; i++)
+ for (size_t i = 0; i < names.length; i++)
{
Identifier name = names[i];
Identifier _alias = aliases[i];
override void setScope(Scope* sc)
{
Dsymbol.setScope(sc);
- if (aliasdecls.dim)
+ if (aliasdecls.length)
{
if (!mod)
importAll(sc);
public:
extern (C++) size_t stackPointer()
{
- return values.dim;
+ return values.length;
}
// The current value of 'this', or NULL if none
extern (C++) void endFrame()
{
- size_t oldframe = cast(size_t)frames[frames.dim - 1];
- localThis = savedThis[savedThis.dim - 1];
+ size_t oldframe = cast(size_t)frames[frames.length - 1];
+ localThis = savedThis[savedThis.length - 1];
popAll(framepointer);
framepointer = oldframe;
- frames.setDim(frames.dim - 1);
- savedThis.setDim(savedThis.dim - 1);
+ frames.setDim(frames.length - 1);
+ savedThis.setDim(savedThis.length - 1);
}
extern (C++) bool isInCurrentFrame(VarDeclaration v)
//printf("getValue() %s\n", v.toChars());
if ((v.isDataseg() || v.storage_class & STC.manifest) && !v.isCTFE())
{
- assert(v.ctfeAdrOnStack < globalValues.dim);
+ assert(v.ctfeAdrOnStack < globalValues.length);
return globalValues[v.ctfeAdrOnStack];
}
assert(v.ctfeAdrOnStack < stackPointer());
return;
}
savedId.push(cast(void*)cast(size_t)v.ctfeAdrOnStack);
- v.ctfeAdrOnStack = cast(uint)values.dim;
+ v.ctfeAdrOnStack = cast(uint)values.length;
vars.push(v);
values.push(null);
}
assert(!v.isReference());
const oldid = v.ctfeAdrOnStack;
v.ctfeAdrOnStack = cast(uint)cast(size_t)savedId[oldid];
- if (v.ctfeAdrOnStack == values.dim - 1)
+ if (v.ctfeAdrOnStack == values.length - 1)
{
values.pop();
vars.pop();
{
if (stackPointer() > maxStackPointer)
maxStackPointer = stackPointer();
- assert(values.dim >= stackpointer);
- for (size_t i = stackpointer; i < values.dim; ++i)
+ assert(values.length >= stackpointer);
+ for (size_t i = stackpointer; i < values.length; ++i)
{
VarDeclaration v = vars[i];
v.ctfeAdrOnStack = cast(uint)cast(size_t)savedId[i];
extern (C++) void saveGlobalConstant(VarDeclaration v, Expression e)
{
assert(v._init && (v.isConst() || v.isImmutable() || v.storage_class & STC.manifest) && !v.isCTFE());
- v.ctfeAdrOnStack = cast(uint)globalValues.dim;
+ v.ctfeAdrOnStack = cast(uint)globalValues.length;
globalValues.push(copyRegionExp(e));
}
}
auto tf = fd.type.toBasetype().isTypeFunction();
if (tf.parameterList.varargs != VarArg.none && arguments &&
- ((fd.parameters && arguments.dim != fd.parameters.dim) || (!fd.parameters && arguments.dim)))
+ ((fd.parameters && arguments.length != fd.parameters.length) || (!fd.parameters && arguments.length)))
{
fd.error("C-style variadic functions are not yet implemented in CTFE");
return CTFEExp.cantexp;
// Place to hold all the arguments to the function while
// we are evaluating them.
- size_t dim = arguments ? arguments.dim : 0;
- assert((fd.parameters ? fd.parameters.dim : 0) == dim);
+ size_t dim = arguments ? arguments.length : 0;
+ assert((fd.parameters ? fd.parameters.length : 0) == dim);
/* Evaluate all the arguments to the function,
* store the results in eargs[]
if (istate.start == s)
istate.start = null;
- const dim = s.statements ? s.statements.dim : 0;
+ const dim = s.statements ? s.statements.length : 0;
foreach (i; 0 .. dim)
{
Statement sx = (*s.statements)[i];
if (istate.start == s)
istate.start = null;
- const dim = s.statements ? s.statements.dim : 0;
+ const dim = s.statements ? s.statements.length : 0;
foreach (i; 0 .. dim)
{
Statement sx = (*s.statements)[i];
result = interpret(pue, s.exp, istate, CTFEGoal.LValue);
return;
}
- if (tf.next && tf.next.ty == Tdelegate && istate.fd.closureVars.dim > 0)
+ if (tf.next && tf.next.ty == Tdelegate && istate.fd.closureVars.length > 0)
{
// To support this, we need to copy all the closure vars
// into the delegate literal.
result = e;
}
- static bool isAnErrorException(ClassDeclaration cd)
- {
- return cd == ClassDeclaration.errorException || ClassDeclaration.errorException.isBaseOf(cd, null);
- }
-
static ThrownExceptionExp chainExceptions(ThrownExceptionExp oldest, ThrownExceptionExp newest)
{
debug (LOG)
const next = 4; // index of Throwable.next
assert((*boss.value.elements)[next].type.ty == Tclass); // Throwable.next
ClassReferenceExp collateral = newest.thrown;
- if (isAnErrorException(collateral.originalClass()) && !isAnErrorException(boss.originalClass()))
+ if (collateral.originalClass().isErrorException() && !boss.originalClass().isErrorException())
{
/* Find the index of the Error.bypassException field
*/
if (exceptionOrCant(e))
return;
- assert(e.op == EXP.classReference);
- result = ctfeEmplaceExp!ThrownExceptionExp(loc, e.isClassReferenceExp());
+ if (e.op == EXP.classReference)
+ {
+ result = ctfeEmplaceExp!ThrownExceptionExp(loc, e.isClassReferenceExp());
+ }
+ else
+ {
+ exp.error("to be thrown `%s` must be non-null", exp.toChars());
+ result = ErrorExp.get();
+ }
}
override void visit(ScopeGuardStatement s)
while (s.isAttribDeclaration())
{
auto ad = cast(AttribDeclaration)s;
- assert(ad.decl && ad.decl.dim == 1); // Currently, only one allowed when parsing
+ assert(ad.decl && ad.decl.length == 1); // Currently, only one allowed when parsing
s = (*ad.decl)[0];
}
if (VarDeclaration v = s.isVarDeclaration())
return;
auto expsx = e.elements;
- size_t dim = expsx ? expsx.dim : 0;
+ size_t dim = expsx ? expsx.length : 0;
for (size_t i = 0; i < dim; i++)
{
Expression exp = (*expsx)[i];
{
// todo: all tuple expansions should go in semantic phase.
expandTuples(expsx);
- if (expsx.dim != dim)
+ if (expsx.length != dim)
{
e.error("CTFE internal error: invalid array literal");
result = CTFEExp.cantexp;
expandTuples(keysx);
if (valuesx !is e.values)
expandTuples(valuesx);
- if (keysx.dim != valuesx.dim)
+ if (keysx.length != valuesx.length)
{
e.error("CTFE internal error: invalid AA");
result = CTFEExp.cantexp;
/* Remove duplicate keys
*/
- for (size_t i = 1; i < keysx.dim; i++)
+ for (size_t i = 1; i < keysx.length; i++)
{
auto ekey = (*keysx)[i - 1];
- for (size_t j = i; j < keysx.dim; j++)
+ for (size_t j = i; j < keysx.length; j++)
{
auto ekey2 = (*keysx)[j];
if (!ctfeEqual(e.loc, EXP.equal, ekey, ekey2))
return;
}
- size_t dim = e.elements ? e.elements.dim : 0;
+ size_t dim = e.elements ? e.elements.length : 0;
auto expsx = e.elements;
- if (dim != e.sd.fields.dim)
+ if (dim != e.sd.fields.length)
{
// guaranteed by AggregateDeclaration.fill and TypeStruct.defaultInitLiteral
- const nvthis = e.sd.fields.dim - e.sd.nonHiddenFields();
- assert(e.sd.fields.dim - dim == nvthis);
+ const nvthis = e.sd.fields.length - e.sd.nonHiddenFields();
+ assert(e.sd.fields.length - dim == nvthis);
/* If a nested struct has no initialized hidden pointer,
* set it to null to match the runtime behaviour.
++dim;
}
}
- assert(dim == e.sd.fields.dim);
+ assert(dim == e.sd.fields.length);
foreach (i; 0 .. dim)
{
if (expsx !is e.elements)
{
expandTuples(expsx);
- if (expsx.dim != e.sd.fields.dim)
+ if (expsx.length != e.sd.fields.length)
{
e.error("CTFE internal error: invalid struct literal");
result = CTFEExp.cantexp;
return lenExpr;
size_t len = cast(size_t)lenExpr.toInteger();
Type elemType = (cast(TypeArray)newtype).next;
- if (elemType.ty == Tarray && argnum < arguments.dim - 1)
+ if (elemType.ty == Tarray && argnum < arguments.length - 1)
{
Expression elem = recursivelyCreateArrayLiteral(pue, loc, elemType, istate, arguments, argnum + 1);
if (exceptionOrCantInterpret(elem))
ae.ownedByCtfe = OwnedBy.ctfe;
return ae;
}
- assert(argnum == arguments.dim - 1);
+ assert(argnum == arguments.length - 1);
if (elemType.ty.isSomeChar)
{
const ch = cast(dchar)elemType.defaultInitLiteral(loc).toInteger();
{
StructDeclaration sd = ts.sym;
auto exps = new Expressions();
- exps.reserve(sd.fields.dim);
+ exps.reserve(sd.fields.length);
if (e.arguments)
{
- exps.setDim(e.arguments.dim);
+ exps.setDim(e.arguments.length);
foreach (i, ex; *e.arguments)
{
ex = interpretRegion(ex, istate);
ClassDeclaration cd = tc.sym;
size_t totalFieldCount = 0;
for (ClassDeclaration c = cd; c; c = c.baseClass)
- totalFieldCount += c.fields.dim;
+ totalFieldCount += c.fields.length;
auto elems = new Expressions(totalFieldCount);
size_t fieldsSoFar = totalFieldCount;
for (ClassDeclaration c = cd; c; c = c.baseClass)
{
- fieldsSoFar -= c.fields.dim;
+ fieldsSoFar -= c.fields.length;
foreach (i, v; c.fields)
{
if (v.inuse)
if (e.newtype.toBasetype().isscalar())
{
Expression newval;
- if (e.arguments && e.arguments.dim)
+ if (e.arguments && e.arguments.length)
newval = (*e.arguments)[0];
else
newval = e.newtype.defaultInitLiteral(e.loc);
e.error("CTFE internal error: cannot find field `%s` in `%s`", v.toChars(), ex.toChars());
return CTFEExp.cantexp;
}
- assert(0 <= fieldi && fieldi < sle.elements.dim);
+ assert(0 <= fieldi && fieldi < sle.elements.length);
// If it's a union, set all other members of this union to void
stompOverlappedFields(sle, v);
Expressions* oldelems = oldval.isArrayLiteralExp().elements;
Expressions* newelems = newval.isArrayLiteralExp().elements;
- assert(oldelems.dim == newelems.dim);
+ assert(oldelems.length == newelems.length);
Type elemtype = oldval.type.nextOf();
foreach (i, ref oldelem; *oldelems)
if (auto ale = e1.isArrayLiteralExp())
{
lowerbound = 0;
- upperbound = ale.elements.dim;
+ upperbound = ale.elements.length;
}
else if (auto se = e1.isStringExp())
{
extern (C++) Expression assignTo(ArrayLiteralExp ae)
{
- return assignTo(ae, 0, ae.elements.dim);
+ return assignTo(ae, 0, ae.elements.length);
}
extern (C++) Expression assignTo(ArrayLiteralExp ae, size_t lwr, size_t upr)
if (fd.ident == Id.__ArrayPostblit || fd.ident == Id.__ArrayDtor)
{
- assert(e.arguments.dim == 1);
+ assert(e.arguments.length == 1);
Expression ea = (*e.arguments)[0];
// printf("1 ea = %s %s\n", ea.type.toChars(), ea.toChars());
if (auto se = ea.isSliceExp())
{
// In expressionsem.d `ea.length = eb;` got lowered to `_d_arraysetlengthT(ea, eb);`.
// The following code will rewrite it back to `ea.length = eb` and then interpret that expression.
- assert(e.arguments.dim == 2);
+ assert(e.arguments.length == 2);
Expression ea = (*e.arguments)[0];
Expression eb = (*e.arguments)[1];
// then interpret that expression.
if (fd.ident == Id._d_arrayctor)
- assert(e.arguments.dim == 3);
+ assert(e.arguments.length == 3);
else
- assert(e.arguments.dim == 2);
+ assert(e.arguments.length == 2);
Expression ea = (*e.arguments)[0];
if (ea.isCastExp)
if (fd.ident == Id._d_arrayappendT)
{
- assert(e.arguments.dim == 2);
+ assert(e.arguments.length == 2);
lhs = (*e.arguments)[0];
rhs = (*e.arguments)[1];
}
else
{
- assert(e.arguments.dim == 5);
+ assert(e.arguments.length == 5);
lhs = (*e.arguments)[3];
rhs = (*e.arguments)[4];
}
// `_d_arrayappendcTX(arr, elem), arr[arr.length - 1] = elem, elem;`.
// The following code will rewrite it back to `arr ~= elem`
// and then interpret that expression.
- assert(ce.arguments.dim == 2);
+ assert(ce.arguments.length == 2);
auto arr = (*ce.arguments)[0];
auto elem = e.e2.isConstructExp().e2;
{
ArrayLiteralExp ale = ie.e1.isArrayLiteralExp();
const indx = cast(size_t)ie.e2.toInteger();
- if (indx < ale.elements.dim)
+ if (indx < ale.elements.length)
{
if (Expression xx = (*ale.elements)[indx])
{
(*valuesx)[j - removed] = evalue;
}
}
- valuesx.dim = valuesx.dim - removed;
- keysx.dim = keysx.dim - removed;
+ valuesx.length = valuesx.length - removed;
+ keysx.length = keysx.length - removed;
result = IntegerExp.createBool(removed != 0);
}
return earg;
dinteger_t len = 0;
if (auto aae = earg.isAssocArrayLiteralExp())
- len = aae.keys.dim;
+ len = aae.keys.length;
else
assert(earg.op == EXP.null_);
emplaceExp!(IntegerExp)(pue, earg.loc, len, Type.tsize_t);
if (earg.op != EXP.assocArrayLiteral && earg.type.toBasetype().ty != Taarray)
return null;
auto aae = copyLiteral(earg).copy().isAssocArrayLiteralExp();
- for (size_t i = 0; i < aae.keys.dim; i++)
+ for (size_t i = 0; i < aae.keys.length; i++)
{
if (Expression e = evaluatePostblit(istate, (*aae.keys)[i]))
return e;
assert(fd && fd.fbody);
assert(fd.parameters);
- size_t numParams = fd.parameters.dim;
+ size_t numParams = fd.parameters.length;
assert(numParams == 1 || numParams == 2);
Parameter fparam = fd.type.isTypeFunction().parameterList[numParams - 1];
Expressions args = Expressions(numParams);
AssocArrayLiteralExp ae = aa.isAssocArrayLiteralExp();
- if (!ae.keys || ae.keys.dim == 0)
+ if (!ae.keys || ae.keys.length == 0)
return ctfeEmplaceExp!IntegerExp(deleg.loc, 0, Type.tsize_t);
Expression eresult;
- for (size_t i = 0; i < ae.keys.dim; ++i)
+ for (size_t i = 0; i < ae.keys.length; ++i)
{
Expression ekey = (*ae.keys)[i];
Expression evalue = (*ae.values)[i];
assert(fd && fd.fbody);
assert(fd.parameters);
- size_t numParams = fd.parameters.dim;
+ size_t numParams = fd.parameters.length;
assert(numParams == 1 || numParams == 2);
Type charType = (*fd.parameters)[numParams - 1].type;
Type indexType = numParams == 2 ? (*fd.parameters)[0].type : Type.tsize_t;
private Expression evaluateIfBuiltin(UnionExp* pue, InterState* istate, const ref Loc loc, FuncDeclaration fd, Expressions* arguments, Expression pthis)
{
Expression e = null;
- size_t nargs = arguments ? arguments.dim : 0;
+ size_t nargs = arguments ? arguments.length : 0;
if (!pthis)
{
if (isBuiltin(fd) != BUILTIN.unimp)
// At present, the constructors just copy their arguments into the struct.
// But we might need some magic if stack tracing gets added to druntime.
StructLiteralExp se = pthis.isClassReferenceExp().value;
- assert(arguments.dim <= se.elements.dim);
+ assert(arguments.length <= se.elements.length);
foreach (i, arg; *arguments)
{
auto elem = interpret(arg, istate);
// Remove the first three trace parameters
auto arguments = new Expressions();
- arguments.reserve(ce.arguments.dim - 3);
+ arguments.reserve(ce.arguments.length - 3);
arguments.pushSlice((*ce.arguments)[3 .. $]);
ce = ctfeEmplaceExp!CallExp(ce.loc, ctfeEmplaceExp!VarExp(ce.loc, fd, false), arguments);
mangleIdentifier(tempdecl.ident, tempdecl);
auto args = ti.tiargs;
- size_t nparams = tempdecl.parameters.dim - (tempdecl.isVariadic() ? 1 : 0);
- for (size_t i = 0; i < args.dim; i++)
+ size_t nparams = tempdecl.parameters.length - (tempdecl.isVariadic() ? 1 : 0);
+ for (size_t i = 0; i < args.length; i++)
{
auto o = (*args)[i];
Type ta = isType(o);
}
else if (va)
{
- assert(i + 1 == args.dim); // must be last one
+ assert(i + 1 == args.length); // must be last one
args = &va.objects;
i = -cast(size_t)1;
}
override void visit(ArrayLiteralExp e)
{
- const dim = e.elements ? e.elements.dim : 0;
+ const dim = e.elements ? e.elements.length : 0;
buf.writeByte('A');
buf.print(dim);
foreach (i; 0 .. dim)
override void visit(AssocArrayLiteralExp e)
{
- const dim = e.keys.dim;
+ const dim = e.keys.length;
buf.writeByte('A');
buf.print(dim);
foreach (i; 0 .. dim)
override void visit(StructLiteralExp e)
{
- const dim = e.elements ? e.elements.dim : 0;
+ const dim = e.elements ? e.elements.length : 0;
buf.writeByte('S');
buf.print(dim);
foreach (i; 0 .. dim)
m.semantic3(null);
- foreach (i; 1 .. m.aimports.dim)
+ foreach (i; 1 .. m.aimports.length)
semantic3OnDependencies(m.aimports[i]);
}
{
const p = pid.toString();
buf.writestring(p);
- if (modAliases.dim)
+ if (modAliases.length)
checkModFileAlias(p);
version (Windows)
enum FileSeparator = '\\';
buf.writeByte(FileSeparator);
}
buf.writestring(filename);
- if (modAliases.dim)
+ if (modAliases.length)
checkModFileAlias(filename);
buf.writeByte(0);
filename = buf.extractSlice()[0 .. $ - 1];
extern (D) static const(char)[] find(const(char)[] filename)
{
- return FileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null);
+ return global.fileManager.lookForSourceFile(filename, global.path ? (*global.path)[] : null);
}
extern (C++) static Module load(const ref Loc loc, Identifiers* packages, Identifier ident)
// classinst == classinst -> .object.opEquals(classinst, classinst)
// would fail inside object.d.
if (filetype != FileType.c &&
- (members.dim == 0 ||
+ (members.length == 0 ||
(*members)[0].ident != Id.object ||
(*members)[0].isImport() is null))
{
{
// Add all symbols into module's symbol table
symtab = new DsymbolTable();
- for (size_t i = 0; i < members.dim; i++)
+ for (size_t i = 0; i < members.length; i++)
{
Dsymbol s = (*members)[i];
s.addMember(sc, sc.scopesym);
* before any semantic() on any of them.
*/
setScope(sc); // remember module scope for semantic
- for (size_t i = 0; i < members.dim; i++)
+ for (size_t i = 0; i < members.length; i++)
{
Dsymbol s = (*members)[i];
s.setScope(sc);
}
- for (size_t i = 0; i < members.dim; i++)
+ for (size_t i = 0; i < members.length; i++)
{
Dsymbol s = (*members)[i];
s.importAll(sc);
__gshared int nested;
if (nested)
return;
- //if (deferred.dim) printf("+Module::runDeferredSemantic(), len = %ld\n", deferred.dim);
+ //if (deferred.length) printf("+Module::runDeferredSemantic(), len = %ld\n", deferred.length);
nested++;
size_t len;
do
{
- len = deferred.dim;
+ len = deferred.length;
if (!len)
break;
s.dsymbolSemantic(null);
//printf("deferred: %s, parent = %s\n", s.toChars(), s.parent.toChars());
}
- //printf("\tdeferred.dim = %ld, len = %ld\n", deferred.dim, len);
+ //printf("\tdeferred.length = %ld, len = %ld\n", deferred.length, len);
if (todoalloc)
free(todoalloc);
}
- while (deferred.dim != len); // while making progress
+ while (deferred.length != len); // while making progress
nested--;
- //printf("-Module::runDeferredSemantic(), len = %ld\n", deferred.dim);
+ //printf("-Module::runDeferredSemantic(), len = %ld\n", deferred.length);
}
static void runDeferredSemantic2()
Module.runDeferredSemantic();
Dsymbols* a = &Module.deferred2;
- for (size_t i = 0; i < a.dim; i++)
+ for (size_t i = 0; i < a.length; i++)
{
Dsymbol s = (*a)[i];
//printf("[%d] %s semantic2a\n", i, s.toPrettyChars());
Module.runDeferredSemantic2();
Dsymbols* a = &Module.deferred3;
- for (size_t i = 0; i < a.dim; i++)
+ for (size_t i = 0; i < a.length; i++)
{
Dsymbol s = (*a)[i];
//printf("[%d] %s semantic3a\n", i, s.toPrettyChars());
void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, OutBuffer* buf)
{
- assert(a.dim);
+ assert(a.length);
if (name.length)
{
static immutable table =
{
override void write(Loc loc, DocComment* dc, Scope* sc, Dsymbols* a, OutBuffer* buf)
{
- assert(a.dim);
+ assert(a.length);
Dsymbol s = (*a)[0]; // test
const(char)* p = body_.ptr;
size_t len = body_.length;
goto L1;
// write out last one
buf.writestring(")");
- TypeFunction tf = a.dim == 1 ? isTypeFunction(s) : null;
+ TypeFunction tf = a.length == 1 ? isTypeFunction(s) : null;
if (tf)
{
- size_t pcount = (tf.parameterList.parameters ? tf.parameterList.parameters.dim : 0) +
+ size_t pcount = (tf.parameterList.parameters ? tf.parameterList.parameters.length : 0) +
cast(int)(tf.parameterList.varargs == VarArg.variadic);
if (pcount != paramcount)
{
if (p)
global.params.ddoc.files.shift(p);
// Override with the ddoc macro files from the command line
- for (size_t i = 0; i < global.params.ddoc.files.dim; i++)
+ for (size_t i = 0; i < global.params.ddoc.files.length; i++)
{
auto buffer = readFile(m.loc, global.params.ddoc.files[i]);
// BUG: convert file contents to UTF-8 before use
if (auto imp = s.isImport())
{
// For example: `public import core.stdc.string : memcpy, memcmp;`
- if (imp.aliases.dim > 0)
+ if (imp.aliases.length > 0)
{
- for(int i = 0; i < imp.aliases.dim; i++)
+ for(int i = 0; i < imp.aliases.length; i++)
{
// Need to distinguish between
// `public import core.stdc.string : memcpy, memcmp;` and
TemplateDeclaration td = (tm && tm.tempdecl) ? tm.tempdecl.isTemplateDeclaration() : null;
if (td && td.members)
{
- for (size_t i = 0; i < td.members.dim; i++)
+ for (size_t i = 0; i < td.members.length; i++)
{
Dsymbol sm = (*td.members)[i];
TemplateMixin tmc = sm.isTemplateMixin();
buf.writestring(m);
size_t offset2 = buf.length; // to see if we write anything
sc = sc.push(sds);
- for (size_t i = 0; i < sds.members.dim; i++)
+ for (size_t i = 0; i < sds.members.length; i++)
{
Dsymbol s = (*sds.members)[i];
//printf("\ts = '%s'\n", s.toChars());
// Put previous doc comment if exists
if (DocComment* dc = sc.lastdc)
{
- assert(dc.a.dim > 0, "Expects at least one declaration for a" ~
+ assert(dc.a.length > 0, "Expects at least one declaration for a" ~
"documentation comment");
auto symbol = dc.a[0];
// Put the declaration signatures as the document 'title'
buf.writestring(ddoc_decl_s);
- for (size_t i = 0; i < dc.a.dim; i++)
+ for (size_t i = 0; i < dc.a.length; i++)
{
Dsymbol sx = dc.a[i];
// the added linebreaks in here make looking at multiple
return;
if (ed.isAnonymous() && ed.members)
{
- for (size_t i = 0; i < ed.members.dim; i++)
+ for (size_t i = 0; i < ed.members.length; i++)
{
Dsymbol s = (*ed.members)[i];
emitComment(s, *buf, sc);
Dsymbols* d = ad.include(null);
if (d)
{
- for (size_t i = 0; i < d.dim; i++)
+ for (size_t i = 0; i < d.length; i++)
{
Dsymbol s = (*d)[i];
//printf("AttribDeclaration::emitComment %s\n", s.toChars());
* a template, then include(null) will fail.
*/
Dsymbols* d = cd.decl ? cd.decl : cd.elsedecl;
- for (size_t i = 0; i < d.dim; i++)
+ for (size_t i = 0; i < d.length; i++)
{
Dsymbol s = (*d)[i];
emitComment(s, *buf, sc);
if (d.isVarDeclaration() && td)
{
buf.writeByte('(');
- if (td.origParameters && td.origParameters.dim)
+ if (td.origParameters && td.origParameters.length)
{
- for (size_t i = 0; i < td.origParameters.dim; i++)
+ for (size_t i = 0; i < td.origParameters.length; i++)
{
if (i)
buf.writestring(", ");
buf.printf("%s %s", cd.kind(), cd.toChars());
}
int any = 0;
- for (size_t i = 0; i < cd.baseclasses.dim; i++)
+ for (size_t i = 0; i < cd.baseclasses.length; i++)
{
BaseClass* bc = (*cd.baseclasses)[i];
if (bc.sym && bc.sym.ident == Id.Object)
if (!comment)
return dc;
dc.parseSections(comment);
- for (size_t i = 0; i < dc.sections.dim; i++)
+ for (size_t i = 0; i < dc.sections.length; i++)
{
Section sec = dc.sections[i];
if (iequals("copyright", sec.name))
void writeSections(Scope* sc, Dsymbols* a, OutBuffer* buf)
{
- assert(a.dim);
+ assert(a.length);
//printf("DocComment::writeSections()\n");
Loc loc = (*a)[0].loc;
if (Module m = (*a)[0].isModule())
size_t offset1 = buf.length;
buf.writestring("$(DDOC_SECTIONS ");
size_t offset2 = buf.length;
- for (size_t i = 0; i < sections.dim; i++)
+ for (size_t i = 0; i < sections.length; i++)
{
Section sec = sections[i];
if (sec.nooutput)
else
sec.write(loc, &this, sc, a, buf);
}
- for (size_t i = 0; i < a.dim; i++)
+ for (size_t i = 0; i < a.length; i++)
{
Dsymbol s = (*a)[i];
if (Dsymbol td = getEponymousParent(s))
*/
private TemplateParameter isTemplateParameter(Dsymbols* a, const(char)* p, size_t len)
{
- for (size_t i = 0; i < a.dim; i++)
+ for (size_t i = 0; i < a.length; i++)
{
TemplateDeclaration td = (*a)[i].isTemplateDeclaration();
// Check for the parent, if the current symbol is not a template declaration.
private void highlightCode(Scope* sc, Dsymbol s, ref OutBuffer buf, size_t offset)
{
auto imp = s.isImport();
- if (imp && imp.aliases.dim > 0)
+ if (imp && imp.aliases.length > 0)
{
// For example: `public import core.stdc.string : memcpy, memcmp;`
- for(int i = 0; i < imp.aliases.dim; i++)
+ for(int i = 0; i < imp.aliases.length; i++)
{
// Need to distinguish between
// `public import core.stdc.string : memcpy, memcmp;` and
size_t previ = i;
// hunt for template declarations:
- foreach (symi; 0 .. a.dim)
+ foreach (symi; 0 .. a.length)
{
FuncDeclaration fd = (*a)[symi].isFuncDeclaration();
// build the template parameters
Array!(size_t) paramLens;
- paramLens.reserve(td.parameters.dim);
+ paramLens.reserve(td.parameters.length);
OutBuffer parametersBuf;
HdrGenState hgs;
parametersBuf.writeByte('(');
- foreach (parami; 0 .. td.parameters.dim)
+ foreach (parami; 0 .. td.parameters.length)
{
TemplateParameter tp = (*td.parameters)[parami];
SCOPE.noaccesscheck | SCOPE.ignoresymbolvisibility |
SCOPE.Cfile;
-struct Scope
+extern (C++) struct Scope
{
Scope* enclosing; /// enclosing Scope
Module _module; /// Root module
ScopeDsymbol scopesym; /// current symbol
FuncDeclaration func; /// function we are in
+ VarDeclaration varDecl; /// variable we are in during semantic2
Dsymbol parent; /// parent to use
LabelStatement slabel; /// enclosing labelled statement
SwitchStatement sw; /// enclosing switch statement
return sc;
}
- extern (C++) Scope* copy()
+ extern (D) Scope* copy()
{
Scope* sc = Scope.alloc();
*sc = this;
return sc;
}
- extern (C++) Scope* push()
+ extern (D) Scope* push()
{
Scope* s = copy();
//printf("Scope::push(this = %p) new = %p\n", this, s);
return s;
}
- extern (C++) Scope* push(ScopeDsymbol ss)
+ extern (D) Scope* push(ScopeDsymbol ss)
{
//printf("Scope::push(%s)\n", ss.toChars());
Scope* s = push();
return s;
}
- extern (C++) Scope* pop()
+ extern (D) Scope* pop()
{
//printf("Scope::pop() %p nofree = %d\n", this, nofree);
if (enclosing)
pop();
}
- extern (C++) Scope* startCTFE()
+ extern (D) Scope* startCTFE()
{
Scope* sc = this.push();
sc.flags = this.flags | SCOPE.ctfe;
return sc;
}
- extern (C++) Scope* endCTFE()
+ extern (D) Scope* endCTFE()
{
assert(flags & SCOPE.ctfe);
return pop();
/********************************************
* Search enclosing scopes for ScopeDsymbol.
*/
- ScopeDsymbol getScopesym()
+ extern (D) ScopeDsymbol getScopesym()
{
for (Scope* sc = &this; sc; sc = sc.enclosing)
{
/********************************************
* Search enclosing scopes for ClassDeclaration.
*/
- extern (C++) ClassDeclaration getClassScope()
+ extern (D) ClassDeclaration getClassScope()
{
for (Scope* sc = &this; sc; sc = sc.enclosing)
{
/********************************************
* Search enclosing scopes for ClassDeclaration or StructDeclaration.
*/
- extern (C++) AggregateDeclaration getStructClassScope()
+ extern (D) AggregateDeclaration getStructClassScope()
{
for (Scope* sc = &this; sc; sc = sc.enclosing)
{
*
* Returns: the function or null
*/
- inout(FuncDeclaration) getEnclosingFunction() inout
+ extern (D) inout(FuncDeclaration) getEnclosingFunction() inout
{
if (!this.func)
return null;
}
/******************************
*/
- structalign_t alignment()
+ extern (D) structalign_t alignment()
{
if (aligndecl)
{
*
* Returns: `true` if this or any parent scope is deprecated, `false` otherwise`
*/
- extern(C++) bool isDeprecated()
+ extern (D) bool isDeprecated()
{
for (const(Dsymbol)* sp = &(this.parent); *sp; sp = &(sp.parent))
{
*
* Returns: `true` if this `Scope` is known to be from one of these speculative contexts
*/
- extern(C++) bool isFromSpeculativeSemanticContext() scope
+ extern (D) bool isFromSpeculativeSemanticContext() scope
{
return this.intypeof || this.flags & SCOPE.compile;
}
}
sizeok = Sizeok.inProcess;
- //printf("+StructDeclaration::finalizeSize() %s, fields.dim = %d, sizeok = %d\n", toChars(), fields.dim, sizeok);
+ //printf("+StructDeclaration::finalizeSize() %s, fields.length = %d, sizeok = %d\n", toChars(), fields.length, sizeok);
fields.setDim(0); // workaround
// Set the offsets of the fields and determine the size of the struct
FieldState fieldState;
bool isunion = isUnionDeclaration() !is null;
- for (size_t i = 0; i < members.dim; i++)
+ for (size_t i = 0; i < members.length; i++)
{
Dsymbol s = (*members)[i];
s.setFieldOffset(this, fieldState, isunion);
sizeok = Sizeok.done;
- //printf("-StructDeclaration::finalizeSize() %s, fields.dim = %d, structsize = %d\n", toChars(), fields.dim, structsize);
+ //printf("-StructDeclaration::finalizeSize() %s, fields.length = %d, structsize = %d\n", toChars(), fields.length, structsize);
if (errors)
return;
}
// Recursively check all fields are POD.
- for (size_t i = 0; i < fields.dim; i++)
+ for (size_t i = 0; i < fields.length; i++)
{
VarDeclaration v = fields[i];
if (v.storage_class & STC.ref_)
final uint numArgTypes() const
{
- return argTypes && argTypes.arguments ? cast(uint) argTypes.arguments.dim : 0;
+ return argTypes && argTypes.arguments ? cast(uint) argTypes.arguments.length : 0;
}
final Type argType(uint index)
case EXP.structLiteral:
{
auto sle = cast(StructLiteralExp) exp;
- foreach (i; 0 .. sle.sd.fields.dim)
+ foreach (i; 0 .. sle.sd.fields.length)
{
auto field = sle.sd.fields[i];
if (field.type.size(field.loc))
{
auto ale = cast(ArrayLiteralExp)exp;
- const dim = ale.elements ? ale.elements.dim : 0;
+ const dim = ale.elements ? ale.elements.length : 0;
if (ale.type.toBasetype().ty == Tarray) // if initializing a dynamic array
return dim == 0;
{
/* Do not use foreach, as the size of the array may expand during iteration
*/
- for (size_t i = 0; i < symbols.dim; ++i)
+ for (size_t i = 0; i < symbols.length; ++i)
{
Dsymbol s = (*symbols)[i];
const result = dg(s);
{
/* Do not use foreach, as the size of the array may expand during iteration
*/
- for (size_t i = 0; i < symbols.dim; ++i)
+ for (size_t i = 0; i < symbols.length; ++i)
{
Dsymbol s = (*symbols)[i];
dg(s);
if (a)
{
b = a.copy();
- for (size_t i = 0; i < b.dim; i++)
+ for (size_t i = 0; i < b.length; i++)
{
(*b)[i] = (*b)[i].syntaxCopy(null);
}
*/
extern (D) static bool oneMembers(Dsymbols* members, Dsymbol* ps, Identifier ident)
{
- //printf("Dsymbol::oneMembers() %d\n", members ? members.dim : 0);
+ //printf("Dsymbol::oneMembers() %d\n", members ? members.length : 0);
Dsymbol s = null;
if (!members)
{
return true;
}
- for (size_t i = 0; i < members.dim; i++)
+ for (size_t i = 0; i < members.length; i++)
{
Dsymbol sx = (*members)[i];
bool x = sx.oneMember(ps, ident);
Dsymbol s = null;
OverloadSet a = null;
// Look in imported modules
- for (size_t i = 0; i < importedScopes.dim; i++)
+ for (size_t i = 0; i < importedScopes.length; i++)
{
// If private import, don't search it
if ((flags & IgnorePrivateImports) && visibilities[i] == Visibility.Kind.private_)
if (OverloadSet os2 = s.isOverloadSet())
{
// Merge the cross-module overload set 'os2' into 'os'
- if (os.a.dim == 0)
+ if (os.a.length == 0)
{
- os.a.setDim(os2.a.dim);
- memcpy(os.a.tdata(), os2.a.tdata(), (os.a[0]).sizeof * os2.a.dim);
+ os.a.setDim(os2.a.length);
+ memcpy(os.a.tdata(), os2.a.tdata(), (os.a[0]).sizeof * os2.a.length);
}
else
{
- for (size_t i = 0; i < os2.a.dim; i++)
+ for (size_t i = 0; i < os2.a.length; i++)
{
os = mergeOverloadSet(ident, os, os2.a[i]);
}
assert(s.isOverloadable());
/* Don't add to os[] if s is alias of previous sym
*/
- for (size_t j = 0; j < os.a.dim; j++)
+ for (size_t j = 0; j < os.a.length; j++)
{
Dsymbol s2 = os.a[j];
if (s.toAlias() == s2.toAlias())
importedScopes = new Dsymbols();
else
{
- for (size_t i = 0; i < importedScopes.dim; i++)
+ for (size_t i = 0; i < importedScopes.length; i++)
{
Dsymbol ss = (*importedScopes)[i];
if (ss == s) // if already imported
}
}
importedScopes.push(s);
- visibilities = cast(Visibility.Kind*)mem.xrealloc(visibilities, importedScopes.dim * (visibilities[0]).sizeof);
- visibilities[importedScopes.dim - 1] = visibility.kind;
+ visibilities = cast(Visibility.Kind*)mem.xrealloc(visibilities, importedScopes.length * (visibilities[0]).sizeof);
+ visibilities[importedScopes.length - 1] = visibility.kind;
}
}
if (!importedScopes)
return null;
- return (() @trusted => visibilities[0 .. importedScopes.dim])();
+ return (() @trusted => visibilities[0 .. importedScopes.length])();
}
extern (D) final void addAccessiblePackage(Package p, Visibility visibility) nothrow
}
if (loc.isValid())
{
- .error(loc, "%s `%s` at %s conflicts with %s `%s` at %s",
- s1.kind(), s1.toPrettyChars(), s1.locToChars(),
- s2.kind(), s2.toPrettyChars(), s2.locToChars());
+ .error(loc, "`%s` matches conflicting symbols:", s1.ident.toChars());
+ errorSupplemental(s1.loc, "%s `%s`", s1.kind(), s1.toPrettyChars());
+ errorSupplemental(s2.loc, "%s `%s`", s2.kind(), s2.toPrettyChars());
static if (0)
{
{
if (members)
{
- for (size_t i = 0; i < members.dim; i++)
+ for (size_t i = 0; i < members.length; i++)
{
Dsymbol member = (*members)[i];
if (member.hasStaticCtorOrDtor())
return 0;
size_t n = pn ? *pn : 0; // take over index
int result = 0;
- foreach (size_t i; 0 .. members.dim)
+ foreach (size_t i; 0 .. members.length)
{
Dsymbol s = (*members)[i];
if (AttribDeclaration a = s.isAttribDeclaration())
/* $ gives the number of type entries in the type tuple
*/
auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
- Expression e = new IntegerExp(Loc.initial, tt.arguments.dim, Type.tsize_t);
+ Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t);
v._init = new ExpInitializer(Loc.initial, e);
v.storage_class |= STC.temp | STC.static_ | STC.const_;
v.dsymbolSemantic(sc);
/* $ gives the number of elements in the tuple
*/
auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
- Expression e = new IntegerExp(Loc.initial, td.objects.dim, Type.tsize_t);
+ Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t);
v._init = new ExpInitializer(Loc.initial, e);
v.storage_class |= STC.temp | STC.static_ | STC.const_;
v.dsymbolSemantic(sc);
/* It is for an expression tuple, so the
* length will be a const.
*/
- Expression e = new IntegerExp(Loc.initial, tupexp.exps.dim, Type.tsize_t);
+ Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t);
v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e));
v.storage_class |= STC.temp | STC.static_ | STC.const_;
}
* Note that it's impossible to have both template & function opDollar,
* because both take no arguments.
*/
- if (exp.op == EXP.array && (cast(ArrayExp)exp).arguments.dim != 1)
+ if (exp.op == EXP.array && (cast(ArrayExp)exp).arguments.length != 1)
{
exp.error("`%s` only defines opDollar for one dimension", ad.toChars());
return null;
auto iexps = new Expressions();
iexps.push(ie);
auto exps = new Expressions();
- for (size_t pos = 0; pos < iexps.dim; pos++)
+ for (size_t pos = 0; pos < iexps.length; pos++)
{
Lexpand1:
Expression e = (*iexps)[pos];
Parameter arg = Parameter.getNth(tt.arguments, pos);
arg.type = arg.type.typeSemantic(dsym.loc, sc);
- //printf("[%d] iexps.dim = %d, ", pos, iexps.dim);
+ //printf("[%d] iexps.length = %d, ", pos, iexps.length);
//printf("e = (%s %s, %s), ", Token.tochars[e.op], e.toChars(), e.type.toChars());
//printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
if (e != ie)
{
- if (iexps.dim > nelems)
+ if (iexps.length > nelems)
goto Lnomatch;
if (e.type.implicitConvTo(arg.type))
continue;
if (auto te = e.isTupleExp())
{
- if (iexps.dim - 1 + te.exps.dim > nelems)
+ if (iexps.length - 1 + te.exps.length > nelems)
goto Lnomatch;
iexps.remove(pos);
(*exps)[0] = ve;
expandAliasThisTuples(exps, 0);
- for (size_t u = 0; u < exps.dim; u++)
+ for (size_t u = 0; u < exps.length; u++)
{
Lexpand2:
Expression ee = (*exps)[u];
arg = Parameter.getNth(tt.arguments, pos + u);
arg.type = arg.type.typeSemantic(dsym.loc, sc);
- //printf("[%d+%d] exps.dim = %d, ", pos, u, exps.dim);
+ //printf("[%d+%d] exps.length = %d, ", pos, u, exps.length);
//printf("ee = (%s %s, %s), ", Token.tochars[ee.op], ee.toChars(), ee.type.toChars());
//printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
- size_t iexps_dim = iexps.dim - 1 + exps.dim;
+ size_t iexps_dim = iexps.length - 1 + exps.length;
if (iexps_dim > nelems)
goto Lnomatch;
if (ee.type.implicitConvTo(arg.type))
}
}
}
- if (iexps.dim < nelems)
+ if (iexps.length < nelems)
goto Lnomatch;
ie = new TupleExp(dsym._init.loc, iexps);
if (ie && ie.op == EXP.tuple)
{
auto te = ie.isTupleExp();
- size_t tedim = te.exps.dim;
+ size_t tedim = te.exps.length;
if (tedim != nelems)
{
error(dsym.loc, "tuple of %d elements cannot be assigned to tuple of %d elements", cast(int)tedim, cast(int)nelems);
else if (auto ale = ex.isArrayLiteralExp())
{
// or an array literal assigned to a `scope` variable
- if (!dsym.type.nextOf().needsDestruction())
+ if (global.params.useDIP1000 == FeatureState.enabled
+ && !dsym.type.nextOf().needsDestruction())
ale.onstack = true;
}
}
if (sc.explicitVisibility)
imp.visibility = sc.visibility;
- if (!imp.aliasId && !imp.names.dim) // neither a selective nor a renamed import
+ if (!imp.aliasId && !imp.names.length) // neither a selective nor a renamed import
{
ScopeDsymbol scopesym = sc.getScopesym();
sc = sc.push(imp.mod);
sc.visibility = imp.visibility;
- for (size_t i = 0; i < imp.aliasdecls.dim; i++)
+ for (size_t i = 0; i < imp.aliasdecls.length; i++)
{
AliasDeclaration ad = imp.aliasdecls[i];
//printf("\tImport %s alias %s = %s, scope = %p\n", toPrettyChars(), aliases[i].toChars(), names[i].toChars(), ad._scope);
{
Scope* sc2 = ad.newScope(sc);
bool errors;
- for (size_t i = 0; i < d.dim; i++)
+ for (size_t i = 0; i < d.length; i++)
{
Dsymbol s = (*d)[i];
s.dsymbolSemantic(sc2);
sc.stc &= ~(STC.auto_ | STC.scope_ | STC.static_ | STC.gshared);
sc.inunion = scd.isunion ? scd : null;
sc.flags = 0;
- for (size_t i = 0; i < scd.decl.dim; i++)
+ for (size_t i = 0; i < scd.decl.length; i++)
{
Dsymbol s = (*scd.decl)[i];
if (auto var = s.isVarDeclaration)
if (agg)
{
ad.pMangleOverride.agg = agg;
- if (pd.args.dim == 2)
+ if (pd.args.length == 2)
{
setString((*pd.args)[1]);
}
{
if (pd.ident == Id.linkerDirective)
{
- if (!pd.args || pd.args.dim != 1)
+ if (!pd.args || pd.args.length != 1)
pd.error("one string argument expected for pragma(linkerDirective)");
else
{
}
else if (pd.ident == Id.lib)
{
- if (!pd.args || pd.args.dim != 1)
+ if (!pd.args || pd.args.length != 1)
pd.error("string expected for library name");
else
{
{
if (!pd.args)
pd.args = new Expressions();
- if (pd.args.dim == 0 || pd.args.dim > 2)
+ if (pd.args.length == 0 || pd.args.length > 2)
{
- pd.error(pd.args.dim == 0 ? "string expected for mangled name"
+ pd.error(pd.args.length == 0 ? "string expected for mangled name"
: "expected 1 or 2 arguments");
pd.args.setDim(1);
(*pd.args)[0] = ErrorExp.get(); // error recovery
}
else if (pd.ident == Id.crt_constructor || pd.ident == Id.crt_destructor)
{
- if (pd.args && pd.args.dim != 0)
+ if (pd.args && pd.args.length != 0)
pd.error("takes no argument");
else
{
auto decls = ad.include(null);
if (decls)
{
- for (size_t i = 0; i < decls.dim; ++i)
+ for (size_t i = 0; i < decls.length; ++i)
nestedCount += recurse((*decls)[i], isCtor);
}
return nestedCount;
}
else if (pd.ident == Id.printf || pd.ident == Id.scanf)
{
- if (pd.args && pd.args.dim != 0)
+ if (pd.args && pd.args.length != 0)
pd.error("takes no argument");
return declarations();
}
if (pd.args)
{
const errors_save = global.startGagging();
- for (size_t i = 0; i < pd.args.dim; i++)
+ for (size_t i = 0; i < pd.args.length; i++)
{
Expression e = (*pd.args)[i];
sc = sc.startCTFE();
buf.writeByte(',');
buf.writestring(e.toChars());
}
- if (pd.args.dim)
+ if (pd.args.length)
buf.writeByte(')');
global.endGagging(errors_save);
}
if (cd._scope && cd.decl)
{
- for (size_t i = 0; i < cd.decl.dim; i++)
+ for (size_t i = 0; i < cd.decl.length; i++)
{
Dsymbol s = (*cd.decl)[i];
s.setScope(cd._scope);
{
expandTuples(te.exps);
CPPNamespaceDeclaration current = ns.cppnamespace;
- for (size_t d = 0; d < te.exps.dim; ++d)
+ for (size_t d = 0; d < te.exps.length; ++d)
{
auto exp = (*te.exps)[d];
auto prev = d ? current : ns.cppnamespace;
- current = (d + 1) != te.exps.dim
+ current = (d + 1) != te.exps.length
? new CPPNamespaceDeclaration(ns.loc, exp, null)
: ns;
current.exp = exp;
return;
}
- if (ed.members.dim == 0)
+ if (ed.members.length == 0)
{
ed.error("enum `%s` must have at least one member", ed.toChars());
ed.errors = true;
if (global.params.ddoc.doOutput)
{
- tempdecl.origParameters = new TemplateParameters(tempdecl.parameters.dim);
- for (size_t i = 0; i < tempdecl.parameters.dim; i++)
+ tempdecl.origParameters = new TemplateParameters(tempdecl.parameters.length);
+ for (size_t i = 0; i < tempdecl.parameters.length; i++)
{
TemplateParameter tp = (*tempdecl.parameters)[i];
(*tempdecl.origParameters)[i] = tp.syntaxCopy();
}
}
- for (size_t i = 0; i < tempdecl.parameters.dim; i++)
+ for (size_t i = 0; i < tempdecl.parameters.length; i++)
{
TemplateParameter tp = (*tempdecl.parameters)[i];
if (!tp.declareParameter(paramscope))
{
tempdecl.errors = true;
}
- if (i + 1 != tempdecl.parameters.dim && tp.isTemplateTupleParameter())
+ if (i + 1 != tempdecl.parameters.length && tp.isTemplateTupleParameter())
{
tempdecl.error("template tuple parameter must be last one");
tempdecl.errors = true;
/* Calculate TemplateParameter.dependent
*/
TemplateParameters tparams = TemplateParameters(1);
- for (size_t i = 0; i < tempdecl.parameters.dim; i++)
+ for (size_t i = 0; i < tempdecl.parameters.length; i++)
{
TemplateParameter tp = (*tempdecl.parameters)[i];
tparams[0] = tp;
- for (size_t j = 0; j < tempdecl.parameters.dim; j++)
+ for (size_t j = 0; j < tempdecl.parameters.length; j++)
{
// Skip cases like: X(T : T)
if (i == j)
/* Different argument list lengths happen with variadic args
*/
- if (tm.tiargs.dim != tmix.tiargs.dim)
+ if (tm.tiargs.length != tmix.tiargs.length)
continue;
- for (size_t i = 0; i < tm.tiargs.dim; i++)
+ for (size_t i = 0; i < tm.tiargs.length; i++)
{
RootObject o = (*tm.tiargs)[i];
Type ta = isType(o);
printf("\tdo semantic() on template instance members '%s'\n", tm.toChars());
}
Scope* sc2 = argscope.push(tm);
- //size_t deferred_dim = Module.deferred.dim;
+ //size_t deferred_dim = Module.deferred.length;
__gshared int nest;
//printf("%d\n", nest);
* Because the members would already call Module.addDeferredSemantic() for themselves.
* See Struct, Class, Interface, and EnumDeclaration.dsymbolSemantic().
*/
- //if (!sc.func && Module.deferred.dim > deferred_dim) {}
+ //if (!sc.func && Module.deferred.length > deferred_dim) {}
AggregateDeclaration ad = tm.isMember();
if (sc.func && !ad)
funcdecl.error("must return `void` for `pragma(%s)`", idStr.ptr);
if (funcdecl._linkage != LINK.c && f.parameterList.length != 0)
funcdecl.error("must be `extern(C)` for `pragma(%s)` when taking parameters", idStr.ptr);
+ if (funcdecl.isThis())
+ funcdecl.error("cannot be a non-static member function for `pragma(%s)`", idStr.ptr);
}
if (funcdecl.overnext && funcdecl.isCsymbol())
{
if (!funcdecl.isStatic() || funcdecl.type.nextOf().ty != Tvoid)
funcdecl.error("static constructors / destructors must be `static void`");
- if (f.arguments && f.arguments.dim)
+ if (f.arguments && f.arguments.length)
funcdecl.error("static constructors / destructors must have empty parameter list");
// BUG: check for invalid storage classes
}
goto Ldone;
bool may_override = false;
- for (size_t i = 0; i < cd.baseclasses.dim; i++)
+ for (size_t i = 0; i < cd.baseclasses.length; i++)
{
BaseClass* b = (*cd.baseclasses)[i];
ClassDeclaration cbd = b.type.toBasetype().isClassHandle();
if (!cbd)
continue;
- for (size_t j = 0; j < cbd.vtbl.dim; j++)
+ for (size_t j = 0; j < cbd.vtbl.length; j++)
{
FuncDeclaration f2 = cbd.vtbl[j].isFuncDeclaration();
if (!f2 || f2.ident != funcdecl.ident)
/* Find index of existing function in base class's vtbl[] to override
* (the index will be the same as in cd's current vtbl[])
*/
- int vi = cd.baseClass ? funcdecl.findVtblIndex(&cd.baseClass.vtbl, cast(int)cd.baseClass.vtbl.dim) : -1;
+ int vi = cd.baseClass ? funcdecl.findVtblIndex(&cd.baseClass.vtbl, cast(int)cd.baseClass.vtbl.length) : -1;
bool doesoverride = false;
switch (vi)
with offsets to each of the virtual bases.
*/
if (target.cpp.splitVBasetable && cd.classKind == ClassKind.cpp &&
- cd.baseClass && cd.baseClass.vtbl.dim)
+ cd.baseClass && cd.baseClass.vtbl.length)
{
/* if overriding an interface function, then this is not
* introducing and don't put it in the class vtbl[]
* Search for first function of overload group, and insert
* funcdecl into vtbl[] immediately before it.
*/
- funcdecl.vtblIndex = cast(int)cd.vtbl.dim;
+ funcdecl.vtblIndex = cast(int)cd.vtbl.length;
bool found;
foreach (const i, s; cd.vtbl)
{
else
{
// Append to end of vtbl[]
- vi = cast(int)cd.vtbl.dim;
+ vi = cast(int)cd.vtbl.length;
cd.vtbl.push(funcdecl);
funcdecl.vtblIndex = vi;
}
* will be updated at the end of the enclosing `if` block
* to point to the current (non-mixined) function.
*/
- auto vitmp = cast(int)cd.vtbl.dim;
+ auto vitmp = cast(int)cd.vtbl.length;
cd.vtbl.push(fdc);
fdc.vtblIndex = vitmp;
}
* vtbl, but keep the previous (non-mixined) function as
* the overriding one.
*/
- auto vitmp = cast(int)cd.vtbl.dim;
+ auto vitmp = cast(int)cd.vtbl.length;
cd.vtbl.push(funcdecl);
funcdecl.vtblIndex = vitmp;
break;
{
foreach (b; bcd.interfaces)
{
- vi = funcdecl.findVtblIndex(&b.sym.vtbl, cast(int)b.sym.vtbl.dim);
+ vi = funcdecl.findVtblIndex(&b.sym.vtbl, cast(int)b.sym.vtbl.length);
switch (vi)
{
case -1:
{
BaseClass* bc = null;
Dsymbol s = null;
- for (size_t i = 0; i < cd.baseclasses.dim; i++)
+ for (size_t i = 0; i < cd.baseclasses.length; i++)
{
bc = (*cd.baseclasses)[i];
s = bc.sym.search_correct(funcdecl.ident);
else if (!dd.isFinal())
{
// reserve the dtor slot for the destructor (which we'll create later)
- cldec.cppDtorVtblIndex = cast(int)cldec.vtbl.dim;
+ cldec.cppDtorVtblIndex = cast(int)cldec.vtbl.length;
cldec.vtbl.push(dd);
if (target.cpp.twoDtorInVtable)
cldec.vtbl.push(dd); // deleting destructor uses a second slot
cldec.baseok = Baseok.start;
// Expand any tuples in baseclasses[]
- for (size_t i = 0; i < cldec.baseclasses.dim;)
+ for (size_t i = 0; i < cldec.baseclasses.length;)
{
auto b = (*cldec.baseclasses)[i];
b.type = resolveBase(b.type.typeSemantic(cldec.loc, sc));
}
// See if there's a base class as first in baseclasses[]
- if (cldec.baseclasses.dim)
+ if (cldec.baseclasses.length)
{
BaseClass* b = (*cldec.baseclasses)[0];
Type tb = b.type.toBasetype();
int multiClassError = cldec.baseClass is null ? 0 : 1;
BCLoop:
- for (size_t i = (cldec.baseClass ? 1 : 0); i < cldec.baseclasses.dim;)
+ for (size_t i = (cldec.baseClass ? 1 : 0); i < cldec.baseclasses.length;)
{
BaseClass* b = (*cldec.baseclasses)[i];
Type tb = b.type.toBasetype();
" Use multiple interface inheritance and/or composition.", cldec.toPrettyChars());
multiClassError += 1;
- if (tc.sym.fields.dim)
+ if (tc.sym.fields.length)
errorSupplemental(cldec.loc,"`%s` has fields, consider making it a member of `%s`",
b.type.toChars(), cldec.type.toChars());
else
cldec.storage_class |= cldec.baseClass.storage_class & STC.TYPECTOR;
}
- cldec.interfaces = cldec.baseclasses.tdata()[(cldec.baseClass ? 1 : 0) .. cldec.baseclasses.dim];
+ cldec.interfaces = cldec.baseclasses.tdata()[(cldec.baseClass ? 1 : 0) .. cldec.baseclasses.length];
foreach (b; cldec.interfaces)
{
// If this is an interface, and it derives from a COM interface,
sc2.pop();
}
- for (size_t i = 0; i < cldec.baseclasses.dim; i++)
+ for (size_t i = 0; i < cldec.baseclasses.length; i++)
{
BaseClass* b = (*cldec.baseclasses)[i];
Type tb = b.type.toBasetype();
// initialize vtbl
if (cldec.baseClass)
{
- if (cldec.classKind == ClassKind.cpp && cldec.baseClass.vtbl.dim == 0)
+ if (cldec.classKind == ClassKind.cpp && cldec.baseClass.vtbl.length == 0)
{
cldec.error("C++ base class `%s` needs at least one virtual function", cldec.baseClass.toChars());
}
// Copy vtbl[] from base class
- cldec.vtbl.setDim(cldec.baseClass.vtbl.dim);
- memcpy(cldec.vtbl.tdata(), cldec.baseClass.vtbl.tdata(), (void*).sizeof * cldec.vtbl.dim);
+ cldec.vtbl.setDim(cldec.baseClass.vtbl.length);
+ memcpy(cldec.vtbl.tdata(), cldec.baseClass.vtbl.tdata(), (void*).sizeof * cldec.vtbl.length);
cldec.vthis = cldec.baseClass.vthis;
cldec.vthis2 = cldec.baseClass.vthis2;
cldec.members.foreachDsymbol( s => s.importAll(sc2) );
- // Note that members.dim can grow due to tuple expansion during semantic()
+ // Note that members.length can grow due to tuple expansion during semantic()
cldec.members.foreachDsymbol( s => s.dsymbolSemantic(sc2) );
if (!cldec.determineFields())
idec.baseok = Baseok.start;
// Expand any tuples in baseclasses[]
- for (size_t i = 0; i < idec.baseclasses.dim;)
+ for (size_t i = 0; i < idec.baseclasses.length;)
{
auto b = (*idec.baseclasses)[i];
b.type = resolveBase(b.type.typeSemantic(idec.loc, sc));
goto Lancestorsdone;
}
- if (!idec.baseclasses.dim && sc.linkage == LINK.cpp)
+ if (!idec.baseclasses.length && sc.linkage == LINK.cpp)
idec.classKind = ClassKind.cpp;
idec.cppnamespace = sc.namespace;
UserAttributeDeclaration.checkGNUABITag(idec, sc.linkage);
// Check for errors, handle forward references
BCLoop:
- for (size_t i = 0; i < idec.baseclasses.dim;)
+ for (size_t i = 0; i < idec.baseclasses.length;)
{
BaseClass* b = (*idec.baseclasses)[i];
Type tb = b.type.toBasetype();
}
idec.baseok = Baseok.done;
- idec.interfaces = idec.baseclasses.tdata()[0 .. idec.baseclasses.dim];
+ idec.interfaces = idec.baseclasses.tdata()[0 .. idec.baseclasses.length];
foreach (b; idec.interfaces)
{
// If this is an interface, and it derives from a COM interface,
if (!idec.symtab)
idec.symtab = new DsymbolTable();
- for (size_t i = 0; i < idec.baseclasses.dim; i++)
+ for (size_t i = 0; i < idec.baseclasses.length; i++)
{
BaseClass* b = (*idec.baseclasses)[i];
Type tb = b.type.toBasetype();
// Copy vtbl[] from base class
if (b.sym.vtblOffset())
{
- size_t d = b.sym.vtbl.dim;
+ size_t d = b.sym.vtbl.length;
if (d > 1)
{
idec.vtbl.pushSlice(b.sym.vtbl[1 .. d]);
// Store the place we added it to in target_symbol_list(_idx) so we can
// remove it later if we encounter an error.
Dsymbols* target_symbol_list = tempinst.appendToModuleMember();
- size_t target_symbol_list_idx = target_symbol_list ? target_symbol_list.dim - 1 : 0;
+ size_t target_symbol_list_idx = target_symbol_list ? target_symbol_list.length - 1 : 0;
// Copy the syntax trees from the TemplateDeclaration
tempinst.members = Dsymbol.arraySyntaxCopy(tempdecl.members);
// resolve TemplateThisParameter
- for (size_t i = 0; i < tempdecl.parameters.dim; i++)
+ for (size_t i = 0; i < tempdecl.parameters.length; i++)
{
if ((*tempdecl.parameters)[i].isTemplateThisParameter() is null)
continue;
* member has the same name as the template instance.
* If so, this template instance becomes an alias for that member.
*/
- //printf("members.dim = %d\n", tempinst.members.dim);
- if (tempinst.members.dim)
+ //printf("members.length = %d\n", tempinst.members.length);
+ if (tempinst.members.length)
{
Dsymbol s;
if (Dsymbol.oneMembers(tempinst.members, &s, tempdecl.ident) && s)
/* ConditionalDeclaration may introduce eponymous declaration,
* so we should find it once again after semantic.
*/
- if (tempinst.members.dim)
+ if (tempinst.members.length)
{
Dsymbol s;
if (Dsymbol.oneMembers(tempinst.members, &s, tempdecl.ident) && s)
*/
{
bool found_deferred_ad = false;
- for (size_t i = 0; i < Module.deferred.dim; i++)
+ for (size_t i = 0; i < Module.deferred.length; i++)
{
Dsymbol sd = Module.deferred[i];
AggregateDeclaration ad = sd.isAggregateDeclaration();
}
}
}
- if (found_deferred_ad || Module.deferred.dim)
+ if (found_deferred_ad || Module.deferred.length)
goto Laftersemantic;
}
//printf("Run semantic3 on %s\n", toChars());
tempinst.trySemantic3(sc2);
- for (size_t i = 0; i < deferred.dim; i++)
+ for (size_t i = 0; i < deferred.length; i++)
{
//printf("+ run deferred semantic3 on %s\n", deferred[i].toChars());
deferred[i].semantic3(null);
{
if (!td.literal)
continue;
- assert(td.members && td.members.dim == 1);
+ assert(td.members && td.members.length == 1);
s = (*td.members)[0];
}
if (auto fld = s.isFuncLiteralDeclaration())
//printf("deferred semantic3 of %p %s, ti = %s, ti.deferred = %p\n", this, toChars(), ti.toChars());
for (size_t i = 0;; i++)
{
- if (i == ti.deferred.dim)
+ if (i == ti.deferred.length)
{
ti.deferred.push(tempinst);
break;
// Selective imports are allowed to alias to the same name `import mod : sym=sym`.
if (!ds._import)
{
- if (tident.ident is ds.ident && !tident.idents.dim)
+ if (tident.ident is ds.ident && !tident.idents.length)
{
error(ds.loc, "`alias %s = %s;` cannot alias itself, use a qualified name to create an overload set",
ds.ident.toChars(), tident.ident.toChars());
private TemplateInstance isAliasSeq(Scope* sc, TypeInstance ti)
{
auto tovers = ti.tempinst.tempdecl.isOverloadSet();
- foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
+ foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
{
Dsymbol dstart = tovers ? tovers.a[oi] : ti.tempinst.tempdecl;
int r = overloadApply(dstart, (Dsymbol s)
if (ad.sizeok != Sizeok.none)
return true;
- //printf("determineFields() %s, fields.dim = %d\n", toChars(), fields.dim);
+ //printf("determineFields() %s, fields.length = %d\n", toChars(), fields.length);
// determineFields can be called recursively from one of the fields's v.semantic
ad.fields.setDim(0);
if (ad.members)
{
- for (size_t i = 0; i < ad.members.dim; i++)
+ for (size_t i = 0; i < ad.members.length; i++)
{
auto s = (*ad.members)[i];
if (s.apply(&func, ad))
*/
PINLINE evalPragmaInline(Loc loc, Scope* sc, Expressions* args)
{
- if (!args || args.dim == 0)
+ if (!args || args.length == 0)
return PINLINE.default_;
- if (args && args.dim > 1)
+ if (args && args.length > 1)
{
- .error(loc, "one boolean expression expected for `pragma(inline)`, not %llu", cast(ulong) args.dim);
+ .error(loc, "one boolean expression expected for `pragma(inline)`, not %llu", cast(ulong) args.length);
args.setDim(1);
(*args)[0] = ErrorExp.get();
}
{
if (oa1 == oa2)
return true;
- if (oa1.dim != oa2.dim)
+ if (oa1.length != oa2.length)
return false;
- immutable oa1dim = oa1.dim;
+ immutable oa1dim = oa1.length;
auto oa1d = (*oa1)[].ptr;
auto oa2d = (*oa2)[].ptr;
foreach (j; 0 .. oa1dim)
{
auto ae = e.isArrayLiteralExp();
size_t hash;
- foreach (i; 0 .. ae.elements.dim)
+ foreach (i; 0 .. ae.elements.length)
hash = mixHash(hash, expressionHash(ae[i]));
return hash;
}
{
auto ae = e.isAssocArrayLiteralExp();
size_t hash;
- foreach (i; 0 .. ae.keys.dim)
+ foreach (i; 0 .. ae.keys.length)
// reduction needs associative op as keys are unsorted (use XOR)
hash ^= mixHash(expressionHash((*ae.keys)[i]), expressionHash((*ae.values)[i]));
return hash;
version (none)
{
if (parameters)
- for (int i = 0; i < parameters.dim; i++)
+ for (int i = 0; i < parameters.length; i++)
{
TemplateParameter tp = (*parameters)[i];
//printf("\tparameter[%d] = %p\n", i, tp);
TemplateParameters* p = null;
if (parameters)
{
- p = new TemplateParameters(parameters.dim);
+ p = new TemplateParameters(parameters.length);
foreach (i, ref param; *p)
param = (*parameters)[i].syntaxCopy();
}
}
version (none)
{
- printf("dedtypes.dim = %d, parameters.dim = %d\n", dedtypes.dim, parameters.dim);
- if (ti.tiargs.dim)
- printf("ti.tiargs.dim = %d, [0] = %p\n", ti.tiargs.dim, (*ti.tiargs)[0]);
+ printf("dedtypes.length = %d, parameters.length = %d\n", dedtypes.length, parameters.length);
+ if (ti.tiargs.length)
+ printf("ti.tiargs.length = %d, [0] = %p\n", ti.tiargs.length, (*ti.tiargs)[0]);
}
MATCH nomatch()
{
return MATCH.nomatch;
}
MATCH m;
- size_t dedtypes_dim = dedtypes.dim;
+ size_t dedtypes_dim = dedtypes.length;
dedtypes.zero();
if (errors)
return MATCH.nomatch;
- size_t parameters_dim = parameters.dim;
+ size_t parameters_dim = parameters.length;
int variadic = isVariadic() !is null;
// If more arguments than parameters, no match
- if (ti.tiargs.dim > parameters_dim && !variadic)
+ if (ti.tiargs.length > parameters_dim && !variadic)
{
static if (LOGM)
{
}
assert(dedtypes_dim == parameters_dim);
- assert(dedtypes_dim >= ti.tiargs.dim || variadic);
+ assert(dedtypes_dim >= ti.tiargs.length || variadic);
assert(_scope);
{
if (!dedtype)
{
- assert(i < ti.tiargs.dim);
+ assert(i < ti.tiargs.length);
dedtype = cast(Type)(*ti.tiargs)[i];
}
}
TemplateParameter tp = (*parameters)[i];
RootObject oarg;
printf(" [%d]", i);
- if (i < ti.tiargs.dim)
+ if (i < ti.tiargs.length)
oarg = (*ti.tiargs)[i];
else
oarg = null;
// Set type arguments to dummy template instance to be types
// generated from the parameters to this template declaration
auto tiargs = new Objects();
- tiargs.reserve(parameters.dim);
+ tiargs.reserve(parameters.length);
foreach (tp; *parameters)
{
if (tp.dependent)
scope TemplateInstance ti = new TemplateInstance(Loc.initial, ident, tiargs); // create dummy template instance
// Temporary Array to hold deduced types
- Objects dedtypes = Objects(td2.parameters.dim);
+ Objects dedtypes = Objects(td2.parameters.length);
// Attempt a type deduction
MATCH m = td2.matchWithInstance(sc, ti, &dedtypes, fargs, 1);
Loc instLoc = ti.loc;
Objects* tiargs = ti.tiargs;
- auto dedargs = new Objects(parameters.dim);
+ auto dedargs = new Objects(parameters.length);
Objects* dedtypes = &ti.tdtypes; // for T:T*, the dedargs is the T*, dedtypes is the T
version (none)
{
printf("\nTemplateDeclaration.deduceFunctionTemplateMatch() %s\n", toChars());
- for (size_t i = 0; i < (fargs ? fargs.dim : 0); i++)
+ for (size_t i = 0; i < (fargs ? fargs.length : 0); i++)
{
Expression e = (*fargs)[i];
printf("\tfarg[%d] is %s, type is %s\n", i, e.toChars(), e.type.toChars());
dedargs.zero();
- dedtypes.setDim(parameters.dim);
+ dedtypes.setDim(parameters.length);
dedtypes.zero();
if (errors || fd.errors)
version (none)
{
- for (size_t i = 0; i < dedargs.dim; i++)
+ for (size_t i = 0; i < dedargs.length; i++)
{
printf("\tdedarg[%d] = ", i);
RootObject oarg = (*dedargs)[i];
if (tiargs)
{
// Set initial template arguments
- ntargs = tiargs.dim;
- size_t n = parameters.dim;
+ ntargs = tiargs.length;
+ size_t n = parameters.length;
if (tp)
n--;
if (ntargs > n)
* now form the tuple argument.
*/
auto t = new Tuple(ntargs - n);
- assert(parameters.dim);
- (*dedargs)[parameters.dim - 1] = t;
+ assert(parameters.length);
+ (*dedargs)[parameters.length - 1] = t;
- for (size_t i = 0; i < t.objects.dim; i++)
+ for (size_t i = 0; i < t.objects.length; i++)
{
t.objects[i] = (*tiargs)[n + i];
}
for (size_t i = 0; i < n; i++)
{
- assert(i < parameters.dim);
+ assert(i < parameters.length);
Declaration sparam = null;
MATCH m = (*parameters)[i].matchArg(instLoc, paramscope, dedargs, i, parameters, dedtypes, &sparam);
//printf("\tdeduceType m = %d\n", m);
if (!paramscope.insert(sparam))
return nomatch();
}
- if (n < parameters.dim && !declaredTuple)
+ if (n < parameters.length && !declaredTuple)
{
inferStart = n;
}
else
- inferStart = parameters.dim;
+ inferStart = parameters.length;
//printf("tiargs matchTiargs = %d\n", matchTiargs);
}
version (none)
{
- for (size_t i = 0; i < dedargs.dim; i++)
+ for (size_t i = 0; i < dedargs.length; i++)
{
printf("\tdedarg[%d] = ", i);
RootObject oarg = (*dedargs)[i];
fparameters = fd.getParameterList();
nfparams = fparameters.length; // number of function parameters
- nfargs = fargs ? fargs.dim : 0; // number of function arguments
+ nfargs = fargs ? fargs.length : 0; // number of function arguments
/* Check for match of function arguments with variadic template
* parameter, such as:
{
auto t = new Tuple();
//printf("t = %p\n", t);
- (*dedargs)[parameters.dim - 1] = t;
+ (*dedargs)[parameters.length - 1] = t;
declareParameter(paramscope, tp, t);
declaredTuple = t;
}
if (fparam.type.ty != Tident)
continue;
TypeIdentifier tid = cast(TypeIdentifier)fparam.type;
- if (!tp.ident.equals(tid.ident) || tid.idents.dim)
+ if (!tp.ident.equals(tid.ident) || tid.idents.length)
continue;
if (fparameters.varargs != VarArg.none) // variadic function doesn't
// Loop through the function parameters
{
- //printf("%s\n\tnfargs = %d, nfparams = %d, tuple_dim = %d\n", toChars(), nfargs, nfparams, declaredTuple ? declaredTuple.objects.dim : 0);
+ //printf("%s\n\tnfargs = %d, nfparams = %d, tuple_dim = %d\n", toChars(), nfargs, nfparams, declaredTuple ? declaredTuple.objects.length : 0);
//printf("\ttp = %p, fptupindex = %d, found = %d, declaredTuple = %s\n", tp, fptupindex, fptupindex != IDX_NOTFOUND, declaredTuple ? declaredTuple.toChars() : NULL);
size_t argi = 0;
size_t nfargs2 = nfargs; // nfargs + supplied defaultArgs
* now form the tuple argument.
*/
declaredTuple = new Tuple();
- (*dedargs)[parameters.dim - 1] = declaredTuple;
+ (*dedargs)[parameters.length - 1] = declaredTuple;
/* Count function parameters with no defaults following a tuple parameter.
* void foo(U, T...)(int y, T, U, double, int bar = 0) {} // rem == 2 (U, double)
{
break;
}
- if (!reliesOnTemplateParameters(p.type, (*parameters)[inferStart .. parameters.dim]))
+ if (!reliesOnTemplateParameters(p.type, (*parameters)[inferStart .. parameters.length]))
{
Type pt = p.type.syntaxCopy().typeSemantic(fd.loc, paramscope);
- rem += pt.ty == Ttuple ? (cast(TypeTuple)pt).arguments.dim : 1;
+ rem += pt.ty == Ttuple ? (cast(TypeTuple)pt).arguments.length : 1;
}
else
{
if (nfargs2 - argi < rem)
return nomatch();
declaredTuple.objects.setDim(nfargs2 - argi - rem);
- for (size_t i = 0; i < declaredTuple.objects.dim; i++)
+ for (size_t i = 0; i < declaredTuple.objects.length; i++)
{
farg = (*fargs)[argi + i];
// https://issues.dlang.org/show_bug.cgi?id=6810
// If declared tuple is not a type tuple,
// it cannot be function parameter types.
- for (size_t i = 0; i < declaredTuple.objects.dim; i++)
+ for (size_t i = 0; i < declaredTuple.objects.length; i++)
{
if (!isType(declaredTuple.objects[i]))
return nomatch();
}
}
assert(declaredTuple);
- argi += declaredTuple.objects.dim;
+ argi += declaredTuple.objects.length;
continue;
}
// If parameter type doesn't depend on inferred template parameters,
// semantic it to get actual type.
- if (!reliesOnTemplateParameters(prmtype, (*parameters)[inferStart .. parameters.dim]))
+ if (!reliesOnTemplateParameters(prmtype, (*parameters)[inferStart .. parameters.length]))
{
// should copy prmtype to avoid affecting semantic result
prmtype = prmtype.syntaxCopy().typeSemantic(fd.loc, paramscope);
if (prmtype.ty == Ttuple)
{
TypeTuple tt = cast(TypeTuple)prmtype;
- size_t tt_dim = tt.arguments.dim;
+ size_t tt_dim = tt.arguments.length;
for (size_t j = 0; j < tt_dim; j++, ++argi)
{
Parameter p = (*tt.arguments)[j];
dedtype = xt.tded; // 'unbox'
}
}
- for (size_t i = ntargs; i < dedargs.dim; i++)
+ for (size_t i = ntargs; i < dedargs.length; i++)
{
TemplateParameter tparam = (*parameters)[i];
/* Allow expressions that have CT-known boundaries and type [] to match with [dim]
*/
Type taai;
- if (argtype.ty == Tarray && (prmtype.ty == Tsarray || prmtype.ty == Taarray && (taai = (cast(TypeAArray)prmtype).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
+ if (argtype.ty == Tarray && (prmtype.ty == Tsarray || prmtype.ty == Taarray && (taai = (cast(TypeAArray)prmtype).index).ty == Tident && (cast(TypeIdentifier)taai).idents.length == 0))
{
if (farg.op == EXP.string_)
{
else if (farg.op == EXP.arrayLiteral)
{
ArrayLiteralExp ae = cast(ArrayLiteralExp)farg;
- argtype = ae.type.nextOf().sarrayOf(ae.elements.dim);
+ argtype = ae.type.nextOf().sarrayOf(ae.elements.length);
}
else if (farg.op == EXP.slice)
{
oarg = argtype;
}
- else if ((fparam.storageClass & STC.out_) == 0 && (argtype.ty == Tarray || argtype.ty == Tpointer) && templateParameterLookup(prmtype, parameters) != IDX_NOTFOUND && (cast(TypeIdentifier)prmtype).idents.dim == 0)
+ else if ((fparam.storageClass & STC.out_) == 0 && (argtype.ty == Tarray || argtype.ty == Tpointer) && templateParameterLookup(prmtype, parameters) != IDX_NOTFOUND && (cast(TypeIdentifier)prmtype).idents.length == 0)
{
/* The farg passing to the prmtype always make a copy. Therefore,
* we can shrink the set of the deduced type arguments for prmtype
dedtype = at.merge2();
}
}
- for (size_t i = ntargs; i < dedargs.dim; i++)
+ for (size_t i = ntargs; i < dedargs.length; i++)
{
TemplateParameter tparam = (*parameters)[i];
//printf("tparam[%d] = %s\n", i, tparam.ident.toChars());
// we're one or more arguments short (i.e. no tuple argument)
if (tparam == tp &&
fptupindex == IDX_NOTFOUND &&
- ntargs <= dedargs.dim - 1)
+ ntargs <= dedargs.length - 1)
{
// make tuple argument an empty tuple
oded = new Tuple();
* As same as the code for 7469 in findBestMatch,
* expand a Tuple in dedargs to normalize template arguments.
*/
- if (auto d = dedargs.dim)
+ if (auto d = dedargs.length)
{
if (auto va = isTuple((*dedargs)[d - 1]))
{
version (none)
{
- for (size_t i = 0; i < dedargs.dim; i++)
+ for (size_t i = 0; i < dedargs.length; i++)
{
RootObject o = (*dedargs)[i];
printf("\tdedargs[%d] = %d, %s\n", i, o.dyncast(), o.toChars());
*/
TemplateTupleParameter isVariadic()
{
- size_t dim = parameters.dim;
+ size_t dim = parameters.length;
if (dim == 0)
return null;
return (*parameters)[dim - 1].isTemplateTupleParameter();
printf(" tiargs:\n");
if (tiargs)
{
- for (size_t i = 0; i < tiargs.dim; i++)
+ for (size_t i = 0; i < tiargs.length; i++)
{
RootObject arg = (*tiargs)[i];
printf("\t%s\n", arg.toChars());
}
}
printf(" fargs:\n");
- for (size_t i = 0; i < (fargs ? fargs.dim : 0); i++)
+ for (size_t i = 0; i < (fargs ? fargs.length : 0); i++)
{
Expression arg = (*fargs)[i];
printf("\t%s %s\n", arg.type.toChars(), arg.toChars());
if (fd == m.lastf)
return 0;
// explicitly specified tiargs never match to non template function
- if (tiargs && tiargs.dim > 0)
+ if (tiargs && tiargs.length > 0)
return 0;
// constructors need a valid scope in order to detect semantic errors
if (!tiargs)
tiargs = new Objects();
auto ti = new TemplateInstance(loc, td, tiargs);
- Objects dedtypes = Objects(td.parameters.dim);
+ Objects dedtypes = Objects(td.parameters.length);
assert(td.semanticRun != PASS.initial);
MATCH mta = td.matchWithInstance(sc, ti, &dedtypes, fargs, 0);
//printf("matchWithInstance = %d\n", mta);
*/
private size_t templateIdentifierLookup(Identifier id, TemplateParameters* parameters)
{
- for (size_t i = 0; i < parameters.dim; i++)
+ for (size_t i = 0; i < parameters.length; i++)
{
TemplateParameter tp = (*parameters)[i];
if (tp.ident.equals(id))
/* Need a loc to go with the semantic routine.
*/
Loc loc;
- if (parameters.dim)
+ if (parameters.length)
{
TemplateParameter tp = (*parameters)[0];
loc = tp.loc;
TemplateParameter tp = (*parameters)[i];
TypeIdentifier tident = cast(TypeIdentifier)tparam;
- if (tident.idents.dim > 0)
+ if (tident.idents.length > 0)
{
//printf("matching %s to %s\n", tparam.toChars(), t.toChars());
Dsymbol s = t.toDsymbol(sc);
- for (size_t j = tident.idents.dim; j-- > 0;)
+ for (size_t j = tident.idents.length; j-- > 0;)
{
RootObject id = tident.idents[j];
if (id.dyncast() == DYNCAST.identifier)
/* Need a loc to go with the semantic routine.
*/
Loc loc;
- if (parameters.dim)
+ if (parameters.length)
{
TemplateParameter tp = (*parameters)[0];
loc = tp.loc;
// The "type" (it hasn't been resolved yet) of the function parameter
// does not have a location but the parameter it is related to does,
// so we use that for the resolution (better error message).
- if (inferStart < parameters.dim)
+ if (inferStart < parameters.length)
{
TemplateParameter loctp = (*parameters)[inferStart];
loc = loctp.loc;
// https://issues.dlang.org/show_bug.cgi?id=15243
// Resolve parameter type if it's not related with template parameters
- if (!reliesOnTemplateParameters(fparam.type, (*parameters)[inferStart .. parameters.dim]))
+ if (!reliesOnTemplateParameters(fparam.type, (*parameters)[inferStart .. parameters.length]))
{
auto tx = fparam.type.typeSemantic(Loc.initial, sc);
if (tx.ty == Terror)
if (fparam.type.ty != Tident)
goto L1;
TypeIdentifier tid = cast(TypeIdentifier)fparam.type;
- if (tid.idents.dim)
+ if (tid.idents.length)
goto L1;
/* Look through parameters to find tuple matching tid.ident
size_t tupi = 0;
for (; 1; tupi++)
{
- if (tupi == parameters.dim)
+ if (tupi == parameters.length)
goto L1;
TemplateParameter tx = (*parameters)[tupi];
TemplateTupleParameter tup = tx.isTemplateTupleParameter();
{
// Existing deduced argument must be a tuple, and must match
Tuple tup = isTuple(o);
- if (!tup || tup.objects.dim != tuple_dim)
+ if (!tup || tup.objects.length != tuple_dim)
{
result = MATCH.nomatch;
return;
if (tparam && tparam.ty == Tident)
{
TypeIdentifier tp = cast(TypeIdentifier)tparam;
- for (size_t i = 0; i < t.idents.dim; i++)
+ for (size_t i = 0; i < t.idents.length; i++)
{
RootObject id1 = t.idents[i];
RootObject id2 = tp.idents[i];
{
//printf("\ttest: tempinst.tiargs[%d]\n", i);
RootObject o1 = null;
- if (i < t.tempinst.tiargs.dim)
+ if (i < t.tempinst.tiargs.length)
o1 = (*t.tempinst.tiargs)[i];
- else if (i < t.tempinst.tdtypes.dim && i < tp.tempinst.tiargs.dim)
+ else if (i < t.tempinst.tdtypes.length && i < tp.tempinst.tiargs.length)
{
// Pick up default arg
o1 = t.tempinst.tdtypes[i];
}
- else if (i >= tp.tempinst.tiargs.dim)
+ else if (i >= tp.tempinst.tiargs.length)
break;
- if (i >= tp.tempinst.tiargs.dim)
+ if (i >= tp.tempinst.tiargs.length)
{
- size_t dim = tempdecl.parameters.dim - (tempdecl.isVariadic() ? 1 : 0);
+ size_t dim = tempdecl.parameters.length - (tempdecl.isVariadic() ? 1 : 0);
while (i < dim && ((*tempdecl.parameters)[i].dependent || (*tempdecl.parameters)[i].hasDefaultArg()))
{
i++;
RootObject o2 = (*tp.tempinst.tiargs)[i];
Type t2 = isType(o2);
- size_t j = (t2 && t2.ty == Tident && i == tp.tempinst.tiargs.dim - 1)
+ size_t j = (t2 && t2.ty == Tident && i == tp.tempinst.tiargs.length - 1)
? templateParameterLookup(t2, parameters) : IDX_NOTFOUND;
- if (j != IDX_NOTFOUND && j == parameters.dim - 1 &&
+ if (j != IDX_NOTFOUND && j == parameters.length - 1 &&
(*parameters)[j].isTemplateTupleParameter())
{
/* Given:
/* Create tuple from remaining args
*/
- size_t vtdim = (tempdecl.isVariadic() ? t.tempinst.tiargs.dim : t.tempinst.tdtypes.dim) - i;
+ size_t vtdim = (tempdecl.isVariadic() ? t.tempinst.tiargs.length : t.tempinst.tdtypes.length) - i;
auto vt = new Tuple(vtdim);
for (size_t k = 0; k < vtdim; k++)
{
RootObject o;
- if (k < t.tempinst.tiargs.dim)
+ if (k < t.tempinst.tiargs.length)
o = (*t.tempinst.tiargs)[i + k];
else // Pick up default arg
o = t.tempinst.tdtypes[i + k];
* S!(T).foo
*/
TypeInstance tpi = cast(TypeInstance)tparam;
- if (tpi.idents.dim)
+ if (tpi.idents.length)
{
- RootObject id = tpi.idents[tpi.idents.dim - 1];
+ RootObject id = tpi.idents[tpi.idents.length - 1];
if (id.dyncast() == DYNCAST.identifier && t.sym.ident.equals(cast(Identifier)id))
{
Type tparent = t.sym.parent.getType();
{
/* Slice off the .foo in S!(T).foo
*/
- tpi.idents.dim--;
+ tpi.idents.length--;
result = deduceType(tparent, sc, tpi, parameters, dedtypes, wm);
- tpi.idents.dim++;
+ tpi.idents.length++;
return;
}
}
if (parti)
{
// Make a temporary copy of dedtypes so we don't destroy it
- auto tmpdedtypes = new Objects(dedtypes.dim);
- memcpy(tmpdedtypes.tdata(), dedtypes.tdata(), dedtypes.dim * (void*).sizeof);
+ auto tmpdedtypes = new Objects(dedtypes.length);
+ memcpy(tmpdedtypes.tdata(), dedtypes.tdata(), dedtypes.length * (void*).sizeof);
auto t = new TypeInstance(Loc.initial, parti);
MATCH m = deduceType(t, sc, tparam, parameters, tmpdedtypes);
{
// If this is the first ever match, it becomes our best estimate
if (numBaseClassMatches == 0)
- memcpy(best.tdata(), tmpdedtypes.tdata(), tmpdedtypes.dim * (void*).sizeof);
+ memcpy(best.tdata(), tmpdedtypes.tdata(), tmpdedtypes.length * (void*).sizeof);
else
- for (size_t k = 0; k < tmpdedtypes.dim; ++k)
+ for (size_t k = 0; k < tmpdedtypes.length; ++k)
{
// If we've found more than one possible type for a parameter,
// mark it as unknown.
* S!(T).foo
*/
TypeInstance tpi = cast(TypeInstance)tparam;
- if (tpi.idents.dim)
+ if (tpi.idents.length)
{
- RootObject id = tpi.idents[tpi.idents.dim - 1];
+ RootObject id = tpi.idents[tpi.idents.length - 1];
if (id.dyncast() == DYNCAST.identifier && t.sym.ident.equals(cast(Identifier)id))
{
Type tparent = t.sym.parent.getType();
{
/* Slice off the .foo in S!(T).foo
*/
- tpi.idents.dim--;
+ tpi.idents.length--;
result = deduceType(tparent, sc, tpi, parameters, dedtypes, wm);
- tpi.idents.dim++;
+ tpi.idents.length++;
return;
}
}
int numBaseClassMatches = 0; // Have we found an interface match?
// Our best guess at dedtypes
- auto best = new Objects(dedtypes.dim);
+ auto best = new Objects(dedtypes.length);
ClassDeclaration s = t.sym;
- while (s && s.baseclasses.dim > 0)
+ while (s && s.baseclasses.length > 0)
{
// Test the base class
deduceBaseClassParameters(*(*s.baseclasses)[0], sc, tparam, parameters, dedtypes, best, numBaseClassMatches);
}
// If we got at least one match, copy the known types into dedtypes
- memcpy(dedtypes.tdata(), best.tdata(), best.dim * (void*).sizeof);
+ memcpy(dedtypes.tdata(), best.tdata(), best.length * (void*).sizeof);
result = MATCH.convert;
return;
}
{
//printf("Expression.deduceType(e = %s)\n", e.toChars());
size_t i = templateParameterLookup(tparam, parameters);
- if (i == IDX_NOTFOUND || (cast(TypeIdentifier)tparam).idents.dim > 0)
+ if (i == IDX_NOTFOUND || (cast(TypeIdentifier)tparam).idents.length > 0)
{
if (e == emptyArrayElement && tparam.ty == Tarray)
{
override void visit(StringExp e)
{
Type taai;
- if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
+ if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.length == 0))
{
// Consider compile-time known boundaries
e.type.nextOf().sarrayOf(e.len).accept(this);
override void visit(ArrayLiteralExp e)
{
// https://issues.dlang.org/show_bug.cgi?id=20092
- if (e.elements && e.elements.dim && e.type.toBasetype().nextOf().ty == Tvoid)
+ if (e.elements && e.elements.length && e.type.toBasetype().nextOf().ty == Tvoid)
{
result = deduceEmptyArrayElement();
return;
}
- if ((!e.elements || !e.elements.dim) && e.type.toBasetype().nextOf().ty == Tvoid && tparam.ty == Tarray)
+ if ((!e.elements || !e.elements.length) && e.type.toBasetype().nextOf().ty == Tvoid && tparam.ty == Tarray)
{
// tparam:T[] <- e:[] (void[])
result = deduceEmptyArrayElement();
return;
}
- if (tparam.ty == Tarray && e.elements && e.elements.dim)
+ if (tparam.ty == Tarray && e.elements && e.elements.length)
{
Type tn = (cast(TypeDArray)tparam).next;
result = MATCH.exact;
}
Type taai;
- if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
+ if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.length == 0))
{
// Consider compile-time known boundaries
- e.type.nextOf().sarrayOf(e.elements.dim).accept(this);
+ e.type.nextOf().sarrayOf(e.elements.length).accept(this);
return;
}
visit(cast(Expression)e);
override void visit(AssocArrayLiteralExp e)
{
- if (tparam.ty == Taarray && e.keys && e.keys.dim)
+ if (tparam.ty == Taarray && e.keys && e.keys.length)
{
TypeAArray taa = cast(TypeAArray)tparam;
result = MATCH.exact;
return;
auto tiargs = new Objects();
- tiargs.reserve(e.td.parameters.dim);
+ tiargs.reserve(e.td.parameters.length);
foreach (tp; *e.td.parameters)
{
if (!pto)
break;
Type t = pto.type.syntaxCopy(); // https://issues.dlang.org/show_bug.cgi?id=11774
- if (reliesOnTemplateParameters(t, (*parameters)[inferStart .. parameters.dim]))
+ if (reliesOnTemplateParameters(t, (*parameters)[inferStart .. parameters.length]))
return;
t = t.typeSemantic(e.loc, sc);
if (t.ty == Terror)
override void visit(SliceExp e)
{
Type taai;
- if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.dim == 0))
+ if (e.type.ty == Tarray && (tparam.ty == Tsarray || tparam.ty == Taarray && (taai = (cast(TypeAArray)tparam).index).ty == Tident && (cast(TypeIdentifier)taai).idents.length == 0))
{
// Consider compile-time known boundaries
if (Type tsa = toStaticArrayType(e))
*/
bool reliesOnTident(Type t, TemplateParameters* tparams, size_t iStart = 0)
{
- return reliesOnTemplateParameters(t, (*tparams)[0 .. tparams.dim]);
+ return reliesOnTemplateParameters(t, (*tparams)[0 .. tparams.length]);
}
/***********************************************************
Tuple v = isTuple(oded);
assert(v);
- //printf("|%d| ", v.objects.dim);
+ //printf("|%d| ", v.objects.length);
foreach (i, o; v.objects)
{
if (i)
Objects* a = null;
if (objs)
{
- a = new Objects(objs.dim);
+ a = new Objects(objs.length);
foreach (i, o; *objs)
(*a)[i] = objectSyntaxCopy(o);
}
final bool equalsx(TemplateInstance ti)
{
//printf("this = %p, ti = %p\n", this, ti);
- assert(tdtypes.dim == ti.tdtypes.dim);
+ assert(tdtypes.length == ti.tdtypes.length);
// Nesting must match
if (enclosing != ti.enclosing)
Parameter fparam = fparameters[j];
if (fparam.storageClass & STC.autoref) // if "auto ref"
{
- Expression farg = fargs && j < fargs.dim ? (*fargs)[j] : fparam.defaultArg;
+ Expression farg = fargs && j < fargs.length ? (*fargs)[j] : fparam.defaultArg;
if (!farg)
goto Lnotequals;
if (farg.isLvalue())
// Look for forward references
auto tovers = tempdecl.isOverloadSet();
- foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
+ foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
{
Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
int r = overloadApply(dstart, (Dsymbol s)
if (!tiargs)
return true;
bool err = false;
- for (size_t j = 0; j < tiargs.dim; j++)
+ for (size_t j = 0; j < tiargs.length; j++)
{
RootObject o = (*tiargs)[j];
Type ta = isType(o);
{
// Expand tuple
TypeTuple tt = cast(TypeTuple)ta;
- size_t dim = tt.arguments.dim;
+ size_t dim = tt.arguments.length;
tiargs.remove(j);
if (dim)
{
{
// Expand tuple
TupleExp te = cast(TupleExp)ea;
- size_t dim = te.exps.dim;
+ size_t dim = te.exps.length;
tiargs.remove(j);
if (dim)
{
version (none)
{
printf("-TemplateInstance.semanticTiargs()\n");
- for (size_t j = 0; j < tiargs.dim; j++)
+ for (size_t j = 0; j < tiargs.length; j++)
{
RootObject o = (*tiargs)[j];
Type ta = isType(o);
assert(tempdecl);
assert(tempdecl._scope);
// Deduce tdtypes
- tdtypes.setDim(tempdecl.parameters.dim);
+ tdtypes.setDim(tempdecl.parameters.length);
if (!tempdecl.matchWithInstance(sc, this, &tdtypes, fargs, 2))
{
error("incompatible arguments for template instantiation");
* name, look for the best match.
*/
auto tovers = tempdecl.isOverloadSet();
- foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
+ foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
{
TemplateDeclaration td_best;
TemplateDeclaration td_ambig;
//printf("td = %s\n", td.toPrettyChars());
// If more arguments than parameters,
// then this is no match.
- if (td.parameters.dim < tiargs.dim)
+ if (td.parameters.length < tiargs.length)
{
if (!td.isVariadic())
return 0;
}
- dedtypes.setDim(td.parameters.dim);
+ dedtypes.setDim(td.parameters.length);
dedtypes.zero();
assert(td.semanticRun != PASS.initial);
td_ambig = null;
td_best = td;
m_best = m;
- tdtypes.setDim(dedtypes.dim);
- memcpy(tdtypes.tdata(), dedtypes.tdata(), tdtypes.dim * (void*).sizeof);
+ tdtypes.setDim(dedtypes.length);
+ memcpy(tdtypes.tdata(), dedtypes.tdata(), tdtypes.length * (void*).sizeof);
return 0;
});
* S!num s; // S!1 is instantiated, not S!num
* }
*/
- size_t dim = td_last.parameters.dim - (td_last.isVariadic() ? 1 : 0);
+ size_t dim = td_last.parameters.length - (td_last.isVariadic() ? 1 : 0);
for (size_t i = 0; i < dim; i++)
{
- if (tiargs.dim <= i)
+ if (tiargs.length <= i)
tiargs.push(tdtypes[i]);
- assert(i < tiargs.dim);
+ assert(i < tiargs.length);
auto tvp = (*td_last.parameters)[i].isTemplateValueParameter();
if (!tvp)
(*tiargs)[i] = tdtypes[i];
}
- if (td_last.isVariadic() && tiargs.dim == dim && tdtypes[dim])
+ if (td_last.isVariadic() && tiargs.length == dim && tdtypes[dim])
{
Tuple va = isTuple(tdtypes[dim]);
assert(va);
{
error("%s `%s`", msg, tmsg);
- if (tdecl.parameters.dim == tiargs.dim)
+ if (tdecl.parameters.length == tiargs.length)
{
// https://issues.dlang.org/show_bug.cgi?id=7352
// print additional information, e.g. `foo` is not a type
}
}
else
- .error(loc, "%s `%s.%s` does not match any template declaration", tempdecl.kind(), tempdecl.parent.toPrettyChars(), tempdecl.ident.toChars());
+ {
+ .error(loc, "%s `%s` does not match any template declaration", kind(), toPrettyChars());
+ bool found;
+ overloadApply(tempdecl, (s){
+ if (!found)
+ errorSupplemental(loc, "Candidates are:");
+ found = true;
+ errorSupplemental(s.loc, "%s", s.toChars());
+ return 0;
+ });
+ }
return false;
}
size_t count = 0;
auto tovers = tempdecl.isOverloadSet();
- foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
+ foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
{
Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
int r = overloadApply(dstart, (Dsymbol s)
{
if (!td2.onemember || !td2.onemember.isFuncDeclaration())
return 0;
- if (tiargs.dim >= td.parameters.dim - (td.isVariadic() ? 1 : 0))
+ if (tiargs.length >= td.parameters.length - (td.isVariadic() ? 1 : 0))
return 0;
return 1;
}
/* Determine if the instance arguments, tiargs, are all that is necessary
* to instantiate the template.
*/
- //printf("tp = %p, td.parameters.dim = %d, tiargs.dim = %d\n", tp, td.parameters.dim, tiargs.dim);
+ //printf("tp = %p, td.parameters.length = %d, tiargs.length = %d\n", tp, td.parameters.length, tiargs.length);
auto tf = cast(TypeFunction)fd.type;
if (tf.parameterList.length)
{
auto tp = td.isVariadic();
- if (tp && td.parameters.dim > 1)
+ if (tp && td.parameters.length > 1)
return 1;
- if (!tp && tiargs.dim < td.parameters.dim)
+ if (!tp && tiargs.length < td.parameters.length)
{
// Can remain tiargs be filled by default arguments?
- foreach (size_t i; tiargs.dim .. td.parameters.dim)
+ foreach (size_t i; tiargs.length .. td.parameters.length)
{
if (!(*td.parameters)[i].hasDefaultArg())
return 1;
/* Calculate the need for overload resolution.
* When only one template can match with tiargs, inference is not necessary.
*/
- dedtypes.setDim(td.parameters.dim);
+ dedtypes.setDim(td.parameters.length);
dedtypes.zero();
if (td.semanticRun == PASS.initial)
{
extern (D) this(const ref Loc loc, Identifier ident, TypeQualified tqual, Objects* tiargs)
{
super(loc,
- tqual.idents.dim ? cast(Identifier)tqual.idents[tqual.idents.dim - 1] : (cast(TypeIdentifier)tqual).ident,
+ tqual.idents.length ? cast(Identifier)tqual.idents[tqual.idents.length - 1] : (cast(TypeIdentifier)tqual).ident,
tiargs ? tiargs : new Objects());
//printf("TemplateMixin(ident = '%s')\n", ident ? ident.toChars() : "");
this.ident = ident;
// Look for forward references
auto tovers = tempdecl.isOverloadSet();
- foreach (size_t oi; 0 .. tovers ? tovers.a.dim : 1)
+ foreach (size_t oi; 0 .. tovers ? tovers.a.length : 1)
{
Dsymbol dstart = tovers ? tovers.a[oi] : tempdecl;
int r = overloadApply(dstart, (Dsymbol s)
{
RootObject oarg;
- if (i < tiargs.dim)
+ if (i < tiargs.length)
oarg = (*tiargs)[i];
else
{
oarg = tp.defaultArg(instLoc, sc);
if (!oarg)
{
- assert(i < dedtypes.dim);
+ assert(i < dedtypes.length);
// It might have already been deduced
oarg = (*dedtypes)[i];
if (!oarg)
/* The rest of the actual arguments (tiargs[]) form the match
* for the variadic parameter.
*/
- assert(i + 1 == dedtypes.dim); // must be the last one
+ assert(i + 1 == dedtypes.length); // must be the last one
Tuple ovar;
if (Tuple u = isTuple((*dedtypes)[i]))
// It has already been deduced
ovar = u;
}
- else if (i + 1 == tiargs.dim && isTuple((*tiargs)[i]))
+ else if (i + 1 == tiargs.length && isTuple((*tiargs)[i]))
ovar = isTuple((*tiargs)[i]);
else
{
ovar = new Tuple();
//printf("ovar = %p\n", ovar);
- if (i < tiargs.dim)
+ if (i < tiargs.length)
{
- //printf("i = %d, tiargs.dim = %d\n", i, tiargs.dim);
- ovar.objects.setDim(tiargs.dim - i);
+ //printf("i = %d, tiargs.length = %d\n", i, tiargs.length);
+ ovar.objects.setDim(tiargs.length - i);
foreach (j, ref obj; ovar.objects)
obj = (*tiargs)[i + j];
}
}
if (tf.parameterList.varargs)
{
- if (tf.parameterList.parameters.dim && tf.parameterList.varargs == 1)
+ if (tf.parameterList.parameters.length && tf.parameterList.varargs == 1)
buf.writestring(", ");
buf.writestring("...");
}
}
if (tf.parameterList.varargs)
{
- if (tf.parameterList.parameters.dim && tf.parameterList.varargs == 1)
+ if (tf.parameterList.parameters.length && tf.parameterList.varargs == 1)
buf.writestring(", ");
buf.writestring("...");
}
* Params:
* sc = used to determine current function and module
* fdc = function being called, `null` if called indirectly
- * par = function parameter (`this` if null)
+ * parId = name of function parameter for error messages
* vPar = `VarDeclaration` corresponding to `par`
* parStc = storage classes of function parameter (may have added `scope` from `pure`)
* arg = initializer for param
* Returns:
* `true` if pointers to the stack can escape via assignment
*/
-bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Parameter par, VarDeclaration vPar, STC parStc, Expression arg, bool assertmsg, bool gag)
+bool checkParamArgumentEscape(Scope* sc, FuncDeclaration fdc, Identifier parId, VarDeclaration vPar, STC parStc, Expression arg, bool assertmsg, bool gag)
{
enum log = false;
if (log) printf("checkParamArgumentEscape(arg: %s par: %s)\n",
arg ? arg.toChars() : "null",
- par ? par.toChars() : "this");
+ parId ? parId.toChars() : "null");
//printf("type = %s, %d\n", arg.type.toChars(), arg.type.hasPointers());
if (!arg.type.hasPointers())
er.byexp.setDim(0);
}
- if (!er.byref.dim && !er.byvalue.dim && !er.byfunc.dim && !er.byexp.dim)
+ if (!er.byref.length && !er.byvalue.length && !er.byfunc.length && !er.byexp.length)
return false;
bool result = false;
{
result |= sc.setUnsafeDIP1000(gag, arg.loc,
desc ~ " `%s` assigned to non-scope parameter calling `assert()`", v);
+ return;
}
- else if (par)
- {
- if (sc.setUnsafeDIP1000(gag, arg.loc,
- desc ~ " `%s` assigned to non-scope parameter `%s` calling `%s`", v, par, fdc))
- {
- result = true;
- printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), vPar, 10);
- }
- }
- else
+ const(char)* msg =
+ (fdc && parId) ? (desc ~ " `%s` assigned to non-scope parameter `%s` calling `%s`") :
+ (fdc && !parId) ? (desc ~ " `%s` assigned to non-scope anonymous parameter calling `%s`") :
+ (!fdc && parId) ? (desc ~ " `%s` assigned to non-scope parameter `%s`") :
+ (desc ~ " `%s` assigned to non-scope anonymous parameter");
+
+ if (sc.setUnsafeDIP1000(gag, arg.loc, msg, v, parId ? parId : fdc, fdc))
{
- if (sc.setUnsafeDIP1000(gag, arg.loc,
- desc ~ " `%s` assigned to non-scope parameter `this` calling `%s`", v, fdc))
- {
- result = true;
- printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), fdc.vthis, 10);
- }
+ result = true;
+ printScopeFailure(previewSupplementalFunc(sc.isDeprecated(), global.params.useDIP1000), vPar, 10);
}
}
foreach (Expression ee; er.byexp)
{
- if (!par)
- {
- result |= sc.setUnsafeDIP1000(gag, ee.loc,
- "reference to stack allocated value returned by `%s` assigned to non-scope parameter `this`", ee);
- }
- else
- {
- result |= sc.setUnsafeDIP1000(gag, ee.loc,
- "reference to stack allocated value returned by `%s` assigned to non-scope parameter `%s`", ee, par);
- }
+ const(char)* msg = parId ?
+ "reference to stack allocated value returned by `%s` assigned to non-scope parameter `%s`" :
+ "reference to stack allocated value returned by `%s` assigned to non-scope anonymous parameter";
+
+ result |= sc.setUnsafeDIP1000(gag, ee.loc, msg, ee, parId);
}
return result;
if (!tthis.hasPointers())
return false;
- if (!ce.arguments && ce.arguments.dim)
+ if (!ce.arguments && ce.arguments.length)
return false;
DotVarExp dve = ce.e1.isDotVarExp();
TypeFunction tf = ctor.type.isTypeFunction();
const nparams = tf.parameterList.length;
- const n = ce.arguments.dim;
+ const n = ce.arguments.length;
// j=1 if _arguments[] is first argument
const j = tf.isDstyleVariadic();
else
escapeByValue(e2, &er);
- if (!er.byref.dim && !er.byvalue.dim && !er.byfunc.dim && !er.byexp.dim)
+ if (!er.byref.length && !er.byvalue.length && !er.byfunc.length && !er.byexp.length)
return false;
VarDeclaration va = expToVariable(e1);
escapeByValue(e, &er);
- if (!er.byref.dim && !er.byvalue.dim && !er.byexp.dim)
+ if (!er.byref.length && !er.byvalue.length && !er.byexp.length)
return false;
bool result = false;
escapeByValue(e, &er);
- if (!er.byref.dim && !er.byvalue.dim && !er.byexp.dim)
+ if (!er.byref.length && !er.byvalue.length && !er.byexp.length)
return false;
bool result = false;
else
escapeByValue(e, &er);
- if (!er.byref.dim && !er.byvalue.dim && !er.byexp.dim)
+ if (!er.byref.length && !er.byvalue.length && !er.byexp.length)
return false;
bool result = false;
if (!e.type.hasPointers())
return;
- if (e.arguments && e.arguments.dim)
+ if (e.arguments && e.arguments.length)
{
/* j=1 if _arguments[] is first argument,
* skip it because it is not passed by ref
*/
int j = tf.isDstyleVariadic();
- for (size_t i = j; i < e.arguments.dim; ++i)
+ for (size_t i = j; i < e.arguments.length; ++i)
{
Expression arg = (*e.arguments)[i];
size_t nparams = tf.parameterList.length;
return;
if (tf.isref)
{
- if (e.arguments && e.arguments.dim)
+ if (e.arguments && e.arguments.length)
{
/* j=1 if _arguments[] is first argument,
* skip it because it is not passed by ref
*/
int j = tf.isDstyleVariadic();
- for (size_t i = j; i < e.arguments.dim; ++i)
+ for (size_t i = j; i < e.arguments.length; ++i)
{
Expression arg = (*e.arguments)[i];
size_t nparams = tf.parameterList.length;
{
// Create and fill array[] with maybe candidates from the `this` and the parameters
VarDeclaration[10] tmp = void;
- size_t dim = (funcdecl.vthis !is null) + (funcdecl.parameters ? funcdecl.parameters.dim : 0);
+ size_t dim = (funcdecl.vthis !is null) + (funcdecl.parameters ? funcdecl.parameters.length : 0);
import dmd.common.string : SmallBuffer;
auto sb = SmallBuffer!VarDeclaration(dim, tmp[]);
// Infer STC.scope_
if (funcdecl.parameters && !funcdecl.errors)
{
- assert(f.parameterList.length == funcdecl.parameters.dim);
+ assert(f.parameterList.length == funcdecl.parameters.length);
foreach (u, p; f.parameterList)
{
auto v = (*funcdecl.parameters)[u];
if (exps is null)
return;
- for (size_t i = 0; i < exps.dim; i++)
+ for (size_t i = 0; i < exps.length; i++)
{
Expression arg = (*exps)[i];
if (!arg)
{
if (auto tt = e.type.toBasetype().isTypeTuple())
{
- if (!tt.arguments || tt.arguments.dim == 0)
+ if (!tt.arguments || tt.arguments.length == 0)
{
exps.remove(i);
- if (i == exps.dim)
+ if (i == exps.length)
return;
}
else // Expand a TypeTuple
TupleExp te = cast(TupleExp)arg;
exps.remove(i); // remove arg
exps.insert(i, te.exps); // replace with tuple contents
- if (i == exps.dim)
+ if (i == exps.length)
return; // empty tuple, no more arguments
(*exps)[i] = Expression.combine(te.e0, (*exps)[i]);
arg = (*exps)[i];
int expandAliasThisTuples(Expressions* exps, size_t starti = 0)
{
- if (!exps || exps.dim == 0)
+ if (!exps || exps.length == 0)
return -1;
- for (size_t u = starti; u < exps.dim; u++)
+ for (size_t u = starti; u < exps.length; u++)
{
Expression exp = (*exps)[u];
if (TupleDeclaration td = exp.isAliasThisTuple)
Expressions* a = null;
if (exps)
{
- a = new Expressions(exps.dim);
+ a = new Expressions(exps.length);
foreach (i, e; *exps)
{
(*a)[i] = e ? e.syntaxCopy() : null;
auto ad = cast(AggregateDeclaration) f.toParent2();
assert(ad);
- if (ad.userDtors.dim)
+ if (ad.userDtors.length)
{
if (!check(ad.userDtors[0])) // doesn't match check (e.g. is impure as well)
return;
*/
extern (D) final bool checkSafety(Scope* sc, FuncDeclaration f)
{
- if (!sc.func)
- return false;
if (sc.func == f)
return false;
if (sc.intypeof == 1)
return false;
- if (sc.flags & (SCOPE.ctfe | SCOPE.debug_))
+ if (sc.flags & SCOPE.debug_)
return false;
+ if ((sc.flags & SCOPE.ctfe) && sc.func)
+ return false;
+
+ if (!sc.func)
+ {
+ if (sc.varDecl && !f.safetyInprocess && !f.isSafe() && !f.isTrusted())
+ {
+ if (sc.varDecl.storage_class & STC.safe)
+ {
+ error("`@safe` variable `%s` cannot be initialized by calling `@system` function `%s`",
+ sc.varDecl.toChars(), f.toChars());
+ return true;
+ }
+ else
+ {
+ sc.varDecl.storage_class |= STC.system;
+ }
+ }
+ return false;
+ }
if (!f.isSafe() && !f.isTrusted())
{
super(loc, EXP.tuple, __traits(classInstanceSize, TupleExp));
this.exps = new Expressions();
- this.exps.reserve(tup.objects.dim);
+ this.exps.reserve(tup.objects.length);
foreach (o; *tup.objects)
{
if (Dsymbol s = getDsymbol(o))
if (auto e = o.isExpression())
if (auto te = e.isTupleExp())
{
- if (exps.dim != te.exps.dim)
+ if (exps.length != te.exps.length)
return false;
if (e0 && !e0.equals(te.e0) || !e0 && te.e0)
return false;
return false;
if (auto ae = e.isArrayLiteralExp())
{
- if (elements.dim != ae.elements.dim)
+ if (elements.length != ae.elements.length)
return false;
- if (elements.dim == 0 && !type.equals(ae.type))
+ if (elements.length == 0 && !type.equals(ae.type))
{
return false;
}
override Optional!bool toBool()
{
- size_t dim = elements ? elements.dim : 0;
+ size_t dim = elements ? elements.length : 0;
return typeof(return)(dim != 0);
}
override StringExp toStringExp()
{
TY telem = type.nextOf().toBasetype().ty;
- if (telem.isSomeChar || (telem == Tvoid && (!elements || elements.dim == 0)))
+ if (telem.isSomeChar || (telem == Tvoid && (!elements || elements.length == 0)))
{
ubyte sz = 1;
if (telem == Twchar)
OutBuffer buf;
if (elements)
{
- foreach (i; 0 .. elements.dim)
+ foreach (i; 0 .. elements.length)
{
auto ch = this[i];
if (ch.op != EXP.int64)
extern (D) this(const ref Loc loc, Expressions* keys, Expressions* values)
{
super(loc, EXP.assocArrayLiteral, __traits(classInstanceSize, AssocArrayLiteralExp));
- assert(keys.dim == values.dim);
+ assert(keys.length == values.length);
this.keys = keys;
this.values = values;
}
return false;
if (auto ae = e.isAssocArrayLiteralExp())
{
- if (keys.dim != ae.keys.dim)
+ if (keys.length != ae.keys.length)
return false;
size_t count = 0;
foreach (i, key; *keys)
}
}
}
- return count == keys.dim;
+ return count == keys.length;
}
return false;
}
override Optional!bool toBool()
{
- size_t dim = keys.dim;
+ size_t dim = keys.length;
return typeof(return)(dim != 0);
}
{
if (!type.equals(se.type))
return false;
- if (elements.dim != se.elements.dim)
+ if (elements.length != se.elements.length)
return false;
foreach (i, e1; *elements)
{
if (i >= sd.nonHiddenFields())
return null;
- assert(i < elements.dim);
+ assert(i < elements.length);
e = (*elements)[i];
if (e)
{
{
/* Find which field offset is by looking at the field offsets
*/
- if (elements.dim)
+ if (elements.length)
{
const sz = type.size();
if (sz == SIZE_INVALID)
if (td)
{
assert(td.literal);
- assert(td.members && td.members.dim == 1);
+ assert(td.members && td.members.length == 1);
fd = (*td.members)[0].isFuncLiteralDeclaration();
}
tok = fd.tok; // save original kind of function/delegate/(infer)
return cannotInfer(this, to, flag);
auto tiargs = new Objects();
- tiargs.reserve(td.parameters.dim);
+ tiargs.reserve(td.parameters.length);
foreach (tp; *td.parameters)
{
TemplateParameters* p = null;
if (parameters)
{
- p = new TemplateParameters(parameters.dim);
+ p = new TemplateParameters(parameters.length);
foreach (i, el; *parameters)
(*p)[i] = el.syntaxCopy();
}
return false;
if (auto ce = e.isMixinExp())
{
- if (exps.dim != ce.exps.dim)
+ if (exps.length != ce.exps.length)
return false;
foreach (i, e1; *exps)
{
if (VarDeclaration vd = var.isVarDeclaration())
{
auto ad = vd.isMember2();
- if (ad && ad.fields.dim == sc.ctorflow.fieldinit.length)
+ if (ad && ad.fields.length == sc.ctorflow.fieldinit.length)
{
foreach (i, f; ad.fields)
{
if (e.op == EXP.interval && !(slice && slice.isTemplateDeclaration()))
{
Lfallback:
- if (ae.arguments.dim == 1)
+ if (ae.arguments.length == 1)
return null;
ae.error("multi-dimensional slicing requires template `opSlice`");
return ErrorExp.get();
/* Transform:
* aa.remove(arg) into delete aa[arg]
*/
- if (!ce.arguments || ce.arguments.dim != 1)
+ if (!ce.arguments || ce.arguments.length != 1)
{
ce.error("expected key as argument to `aa.remove()`");
return ErrorExp.get();
Expressions a;
a.push(e2);
- for (size_t i = 0; i < os.a.dim; i++)
+ for (size_t i = 0; i < os.a.length; i++)
{
if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, FuncResolveFlag.quiet))
{
}
}
{
- for (size_t i = 0; i < os.a.dim; i++)
+ for (size_t i = 0; i < os.a.length; i++)
{
if (FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, FuncResolveFlag.quiet))
{
Expression e0 = null;
bool foundType;
- for (size_t i = 0; i < exps.dim; i++)
+ for (size_t i = 0; i < exps.length; i++)
{
Expression e = exps[i];
if (!e)
if (t0.ty == Terror)
return null;
- for (size_t i = 0; i < exps.dim; i++)
+ for (size_t i = 0; i < exps.length; i++)
{
Expression e = exps[i];
if (!e)
{
expandTuples(exps);
- for (size_t i = 0; i < exps.dim; i++)
+ for (size_t i = 0; i < exps.length; i++)
{
Expression arg = (*exps)[i];
arg = resolveProperties(sc, arg);
//printf("functionParameters() %s\n", fd ? fd.toChars() : "");
assert(arguments);
assert(fd || tf.next);
- size_t nargs = arguments ? arguments.dim : 0;
+ size_t nargs = arguments ? arguments.length : 0;
const size_t nparams = tf.parameterList.length;
const olderrors = global.errors;
bool err = false;
Type tret = p.isLazyArray();
auto elements = new Expressions(nargs - i);
- foreach (u; 0 .. elements.dim)
+ foreach (u; 0 .. elements.length)
{
Expression a = (*arguments)[i + u];
if (tret && a.implicitConvTo(tret))
* Check arg to see if it matters.
*/
VarDeclaration vPar = fd ? (fd.parameters ? (*fd.parameters)[i] : null) : null;
- err |= checkParamArgumentEscape(sc, fd, p, vPar, cast(STC) pStc, arg, false, false);
+ err |= checkParamArgumentEscape(sc, fd, p.ident, vPar, cast(STC) pStc, arg, false, false);
}
// Turning heap allocations into stack allocations is dangerous without dip1000, since `scope` inference
// If D linkage and variadic, add _arguments[] as first argument
if (tf.isDstyleVariadic())
{
- assert(arguments.dim >= nparams);
+ assert(arguments.length >= nparams);
- auto args = new Parameters(arguments.dim - nparams);
- for (size_t i = 0; i < arguments.dim - nparams; i++)
+ auto args = new Parameters(arguments.length - nparams);
+ for (size_t i = 0; i < arguments.length - nparams; i++)
{
auto arg = new Parameter(STC.in_, (*arguments)[nparams + i].type, null, null, null);
(*args)[i] = arg;
// Run semantic() on each argument
bool err = false;
- for (size_t i = 0; i < exp.exps.dim; i++)
+ for (size_t i = 0; i < exp.exps.length; i++)
{
Expression e = (*exp.exps)[i];
e = e.expressionSemantic(sc);
/* Disallow array literals of type void being used.
*/
- if (e.elements.dim > 0 && t0.ty == Tvoid)
+ if (e.elements.length > 0 && t0.ty == Tvoid)
{
e.error("`%s` of type `%s` has no value", e.toChars(), e.type.toChars());
return setError();
expandTuples(e.keys);
expandTuples(e.values);
- if (e.keys.dim != e.values.dim)
+ if (e.keys.length != e.values.length)
{
e.error("number of keys is %llu, must match number of values %llu",
- cast(ulong) e.keys.dim, cast(ulong) e.values.dim);
+ cast(ulong) e.keys.length, cast(ulong) e.values.length);
return setError();
}
return setError();
}
- if (checkFrameAccess(e.loc, sc, e.sd, e.elements.dim))
+ if (checkFrameAccess(e.loc, sc, e.sd, e.elements.length))
return setError();
e.type = e.stype ? e.stype : e.sd.type;
return setError();
}
- const size_t nargs = exp.arguments ? exp.arguments.dim : 0;
+ const size_t nargs = exp.arguments ? exp.arguments.length : 0;
Expression newprefix = null;
if (auto tc = tb.isTypeClass())
if (cd.isAbstract())
{
exp.error("cannot create instance of abstract class `%s`", cd.toChars());
- for (size_t i = 0; i < cd.vtbl.dim; i++)
+ for (size_t i = 0; i < cd.vtbl.length; i++)
{
FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration();
if (fd && fd.isAbstract())
exp.member = f.isCtorDeclaration();
assert(exp.member);
- if (checkFrameAccess(exp.loc, sc, sd, sd.fields.dim))
+ if (checkFrameAccess(exp.loc, sc, sd, sd.fields.length))
return setError();
}
else
if (!sd.fill(exp.loc, *exp.arguments, false))
return setError();
- if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.dim : 0))
+ if (checkFrameAccess(exp.loc, sc, sd, exp.arguments ? exp.arguments.length : 0))
return setError();
/* Since a `new` allocation may escape, check each of the arguments for escaping
//printf("td = %p, treq = %p\n", td, fd.treq);
if (exp.td)
{
- assert(exp.td.parameters && exp.td.parameters.dim);
+ assert(exp.td.parameters && exp.td.parameters.length);
exp.td.dsymbolSemantic(sc);
exp.type = Type.tvoid; // temporary type
*/
Expression callExpSemantic(FuncExp exp, Scope* sc, Expressions* arguments)
{
- if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.dim)
+ if ((!exp.type || exp.type == Type.tvoid) && exp.td && arguments && arguments.length)
{
- for (size_t k = 0; k < arguments.dim; k++)
+ for (size_t k = 0; k < arguments.length; k++)
{
Expression checkarg = (*arguments)[k];
if (checkarg.op == EXP.error)
exp.genIdent(sc);
- assert(exp.td.parameters && exp.td.parameters.dim);
+ assert(exp.td.parameters && exp.td.parameters.length);
exp.td.dsymbolSemantic(sc);
TypeFunction tfl = cast(TypeFunction)exp.fd.type;
size_t dim = tfl.parameterList.length;
- if (arguments.dim < dim)
+ if (arguments.length < dim)
{
// Default arguments are always typed, so they don't need inference.
- Parameter p = tfl.parameterList[arguments.dim];
+ Parameter p = tfl.parameterList[arguments.length];
if (p.defaultArg)
- dim = arguments.dim;
+ dim = arguments.length;
}
- if ((tfl.parameterList.varargs == VarArg.none && arguments.dim > dim) ||
- arguments.dim < dim)
+ if ((tfl.parameterList.varargs == VarArg.none && arguments.length > dim) ||
+ arguments.length < dim)
{
OutBuffer buf;
foreach (idx, ref arg; *arguments)
exp.error("function literal `%s%s` is not callable using argument types `(%s)`",
exp.fd.toChars(), parametersTypeToChars(tfl.parameterList),
buf.peekChars());
- exp.errorSupplemental("too %s arguments, expected `%d`, got `%d`",
- arguments.dim < dim ? "few".ptr : "many".ptr,
- cast(int)dim, cast(int)arguments.dim);
+ exp.errorSupplemental("too %s arguments, expected %d, got %d",
+ arguments.length < dim ? "few".ptr : "many".ptr,
+ cast(int)dim, cast(int)arguments.length);
return ErrorExp.get();
}
auto tiargs = new Objects();
- tiargs.reserve(exp.td.parameters.dim);
+ tiargs.reserve(exp.td.parameters.length);
- for (size_t i = 0; i < exp.td.parameters.dim; i++)
+ for (size_t i = 0; i < exp.td.parameters.length; i++)
{
TemplateParameter tp = (*exp.td.parameters)[i];
assert(dim <= tfl.parameterList.length);
// First look for constructor
if (exp.e1.op == EXP.type && sd.ctor)
{
- if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.dim))
+ if (!sd.noDefaultCtor && !(exp.arguments && exp.arguments.length))
goto Lx;
/* https://issues.dlang.org/show_bug.cgi?id=20695
auto sle = new StructLiteralExp(exp.loc, sd, null, exp.e1.type);
if (!sd.fill(exp.loc, *sle.elements, true))
return setError();
- if (checkFrameAccess(exp.loc, sc, sd, sle.elements.dim))
+ if (checkFrameAccess(exp.loc, sc, sd, sle.elements.length))
return setError();
// https://issues.dlang.org/show_bug.cgi?id=14556
t1 = exp.e1.type;
}
- if (!exp.arguments || exp.arguments.dim == 0)
+ if (!exp.arguments || exp.arguments.length == 0)
{
e = t1.defaultInitLiteral(exp.loc);
}
- else if (exp.arguments.dim == 1)
+ else if (exp.arguments.length == 1)
{
e = (*exp.arguments)[0];
if (!e.type.isTypeNoreturn())
}
}
- static FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc,
+ FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc,
OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments)
{
FuncDeclaration f = null;
}
}
if (!f)
- .error(loc, "no overload matches for `%s`", os.toChars());
+ {
+ .error(loc, "no overload matches for `%s`", exp.toChars());
+ errorSupplemental(loc, "Candidates are:");
+ foreach (s; os.a)
+ {
+ overloadApply(s, (ds){
+ if (auto fd = ds.isFuncDeclaration())
+ .errorSupplemental(ds.loc, "%s%s", fd.toChars(),
+ fd.type.toTypeFunction().parameterList.parametersTypeToChars());
+ else
+ .errorSupplemental(ds.loc, "%s", ds.toChars());
+ return 0;
+ });
+ }
+ }
else if (f.errors)
f = null;
return f;
auto ad2 = b.sym;
ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
ue.e1 = ue.e1.expressionSemantic(sc);
- auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim);
+ auto vi = exp.f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.length);
assert(vi >= 0);
exp.f = ad2.vtbl[vi].isFuncDeclaration();
assert(exp.f);
tthis = ue.e1.type;
if (!(exp.f.type.ty == Tfunction && (cast(TypeFunction)exp.f.type).isScopeQual))
{
- if (checkParamArgumentEscape(sc, exp.f, null, null, STC.undefined_, ethis, false, false))
+ if (checkParamArgumentEscape(sc, exp.f, Id.This, exp.f.vthis, STC.undefined_, ethis, false, false))
return setError();
}
}
AttribDeclaration ad = s.isAttribDeclaration();
if (ad)
{
- if (ad.decl && ad.decl.dim == 1)
+ if (ad.decl && ad.decl.length == 1)
{
s = (*ad.decl)[0];
continue;
{
ClassDeclaration cd = (cast(TypeClass)e.targ).sym;
auto args = new Parameters();
- args.reserve(cd.baseclasses.dim);
+ args.reserve(cd.baseclasses.length);
if (cd.semanticRun < PASS.semanticdone)
cd.dsymbolSemantic(null);
- for (size_t i = 0; i < cd.baseclasses.dim; i++)
+ for (size_t i = 0; i < cd.baseclasses.length; i++)
{
BaseClass* b = (*cd.baseclasses)[i];
args.push(new Parameter(STC.in_, b.type, null, null, null));
return yes();
return no();
}
- else if (e.tspec && !e.id && !(e.parameters && e.parameters.dim))
+ else if (e.tspec && !e.id && !(e.parameters && e.parameters.length))
{
/* Evaluate to true if targ matches tspec
* is(targ == tspec)
Identifier tid = e.id ? e.id : Identifier.generateId("__isexp_id");
e.parameters.insert(0, new TemplateTypeParameter(e.loc, tid, null, null));
- Objects dedtypes = Objects(e.parameters.dim);
+ Objects dedtypes = Objects(e.parameters.length);
dedtypes.zero();
MATCH m = deduceType(e.targ, sc, e.tspec, e.parameters, &dedtypes, null, 0, e.tok == TOK.equal);
/* Declare trailing parameters
*/
- for (size_t i = 1; i < e.parameters.dim; i++)
+ for (size_t i = 1; i < e.parameters.length; i++)
{
TemplateParameter tp = (*e.parameters)[i];
Declaration s = null;
result = expressionSemantic(e, sc);
return;
}
- }
- if (exp.arrow) // ImportC only
- exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
+ if (exp.arrow) // ImportC only
+ exp.e1 = exp.e1.expressionSemantic(sc).arrayFuncConv(sc);
- if (sc.flags & SCOPE.Cfile)
- {
if (exp.ident == Id.__xalignof && exp.e1.isTypeExp())
{
// C11 6.5.3 says _Alignof only applies to types
assert(0);
return;
}
- }
- if (sc.flags & SCOPE.Cfile && exp.ident != Id.__sizeof)
- {
- result = fieldLookup(exp.e1, sc, exp.ident);
- return;
+ if (exp.ident != Id.__sizeof)
+ {
+ result = fieldLookup(exp.e1, sc, exp.ident);
+ return;
+ }
}
Expression e = exp.semanticY(sc, 1);
Expression ev = sc.func ? extractSideEffect(sc, "__tup", e0, exp.e1) : exp.e1;
auto exps = new Expressions();
- exps.reserve(tup.objects.dim);
- for (size_t i = 0; i < tup.objects.dim; i++)
+ exps.reserve(tup.objects.length);
+ for (size_t i = 0; i < tup.objects.length; i++)
{
RootObject o = (*tup.objects)[i];
Expression e;
}
}
TupleExp te = exp.e1.isTupleExp();
- if (te.exps.dim == 1)
+ if (te.exps.length == 1)
exp.e1 = (*te.exps)[0];
}
// Check for unsafe casts
if (!isSafeCast(ex, t1b, tob))
{
- // This is an ad-hoc fix for https://issues.dlang.org/show_bug.cgi?id=19646
- // Should be replaced by a more general @system variables implementation
- if (!sc.func && sc.stc & STC.safe)
- {
- exp.error("cast from `%s` to `%s` not allowed in safe code", exp.e1.type.toChars(), exp.to.toChars());
- return setError();
- }
-
if (sc.setUnsafe(false, exp.loc, "cast from `%s` to `%s` not allowed in safe code", exp.e1.type, exp.to))
{
return setError();
{
te = cast(TupleExp)exp.e1;
tup = null;
- length = te.exps.dim;
+ length = te.exps.length;
}
else if (exp.e1.op == EXP.type) // slicing a type tuple
{
if (exp.e2.op == EXP.tuple)
{
TupleExp te = cast(TupleExp)exp.e2;
- if (te.exps && te.exps.dim == 1)
+ if (te.exps && te.exps.length == 1)
exp.e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix
}
if (sc != scx)
}
semanticTypeInfo(sc, taa);
+ checkNewEscape(sc, exp.e2, false);
exp.type = taa.next;
break;
{
te = cast(TupleExp)exp.e1;
tup = null;
- length = te.exps.dim;
+ length = te.exps.length;
}
else if (exp.e1.op == EXP.type)
{
auto sle = new StructLiteralExp(loc, sd, null, t);
if (!sd.fill(loc, *sle.elements, true))
return ErrorExp.get();
- if (checkFrameAccess(loc, sc, sd, sle.elements.dim))
+ if (checkFrameAccess(loc, sc, sd, sle.elements.length))
return ErrorExp.get();
sle.type = t;
Expression ae1old = ae.e1;
const(bool) maybeSlice =
- (ae.arguments.dim == 0 ||
- ae.arguments.dim == 1 && (*ae.arguments)[0].op == EXP.interval);
+ (ae.arguments.length == 0 ||
+ ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
IntervalExp ie = null;
- if (maybeSlice && ae.arguments.dim)
+ if (maybeSlice && ae.arguments.length)
{
assert((*ae.arguments)[0].op == EXP.interval);
ie = cast(IntervalExp)(*ae.arguments)[0];
{
TupleExp tup1 = cast(TupleExp)exp.e1;
TupleExp tup2 = cast(TupleExp)e2x;
- size_t dim = tup1.exps.dim;
+ size_t dim = tup1.exps.length;
Expression e = null;
- if (dim != tup2.exps.dim)
+ if (dim != tup2.exps.length)
{
- exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim);
+ exp.error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.length);
return setError();
}
if (dim == 0)
auto iexps = new Expressions();
iexps.push(ev);
- for (size_t u = 0; u < iexps.dim; u++)
+ for (size_t u = 0; u < iexps.length; u++)
{
Lexpand:
Expression e = (*iexps)[u];
Parameter arg = Parameter.getNth(tt.arguments, u);
- //printf("[%d] iexps.dim = %d, ", u, iexps.dim);
+ //printf("[%d] iexps.length = %d, ", u, iexps.length);
//printf("e = (%s %s, %s), ", Token.toChars[e.op], e.toChars(), e.type.toChars());
//printf("arg = (%s, %s)\n", arg.toChars(), arg.type.toChars());
// expand initializer to tuple
if (expandAliasThisTuples(iexps, u) != -1)
{
- if (iexps.dim <= u)
+ if (iexps.length <= u)
break;
goto Lexpand;
}
uinteger_t dim2 = dim1;
if (auto ale = e2x.isArrayLiteralExp())
{
- dim2 = ale.elements ? ale.elements.dim : 0;
+ dim2 = ale.elements ? ale.elements.length : 0;
}
else if (auto se = e2x.isSliceExp())
{
TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1);
TypeSArray tsa2 = null;
if (auto ale = e2x.isArrayLiteralExp())
- tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.dim);
+ tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf(ale.elements.length);
else if (auto se = e2x.isSliceExp())
tsa2 = cast(TypeSArray)toStaticArrayType(se);
else
return setError();
exp.type = exp.e1.type;
+ auto assignElem = exp.e2;
auto res = exp.reorderSettingAAElem(sc);
- if (exp.op == EXP.concatenateElemAssign || exp.op == EXP.concatenateDcharAssign)
+ if (res != exp) // `AA[k] = v` rewrite was performed
+ checkNewEscape(sc, assignElem, false);
+ else if (exp.op == EXP.concatenateElemAssign || exp.op == EXP.concatenateDcharAssign)
checkAssignEscape(sc, res, false, false);
+
result = res;
if ((exp.op == EXP.concatenateAssign || exp.op == EXP.concatenateElemAssign) &&
{
static struct Result { bool ttEmpty; bool te; }
auto tt = e.op == EXP.type ? e.isTypeExp().type.isTypeTuple() : null;
- return Result(tt && (!tt.arguments || !tt.arguments.dim), e.isTupleExp() !is null);
+ return Result(tt && (!tt.arguments || !tt.arguments.length), e.isTupleExp() !is null);
}
auto tups1 = extractTypeTupAndExpTup(exp.e1);
auto tups2 = extractTypeTupAndExpTup(exp.e2);
{
/* 'distribute' the .offsetof to each of the tuple elements.
*/
- auto exps = new Expressions(te.exps.dim);
+ auto exps = new Expressions(te.exps.length);
foreach (i, e; (*te.exps)[])
{
(*exps)[i] = new DotIdExp(e.loc, e, Id.offsetof);
if (exp.ident == Id.length)
{
// Don't evaluate te.e0 in runtime
- return new IntegerExp(exp.loc, te.exps.dim, Type.tsize_t);
+ return new IntegerExp(exp.loc, te.exps.length, Type.tsize_t);
}
}
const nfields = sd.nonHiddenFields();
size_t offset = 0;
- for (size_t i = 0; i < elements.dim; i++)
+ for (size_t i = 0; i < elements.length; i++)
{
Expression e = (*elements)[i];
if (!e)
e = resolveProperties(sc, e);
if (i >= nfields)
{
- if (i < sd.fields.dim && e.op == EXP.null_)
+ if (i < sd.fields.length && e.op == EXP.null_)
{
// CTFE sometimes creates null as hidden pointer; we'll allow this.
continue;
import dmd.root.stringtable : StringTable;
import dmd.root.file : File, Buffer;
-import dmd.root.filename : FileName;
+import dmd.root.filename : FileName, isDirSeparator;
import dmd.root.string : toDString;
import dmd.globals;
import dmd.identifier;
return FileName.equals(fileName.name, package_d) || FileName.equals(fileName.name, package_di);
}
+// A path stack that allows one to go up and down the path using directory
+// separators. `cur` is the current path, `up` goes up one path, `down` goes
+// down one path. if `up` or `down` return false, there are no further paths.
+private struct PathStack
+{
+ private const(char)[] path;
+ private size_t pos;
+
+ @safe @nogc nothrow pure:
+
+ this(const(char)[] p)
+ {
+ path = p;
+ pos = p.length;
+ }
+
+ const(char)[] cur()
+ {
+ return path[0 .. pos];
+ }
+
+ bool up()
+ {
+ if (pos == 0)
+ return false;
+ while (--pos != 0)
+ if (isDirSeparator(path[pos]))
+ return true;
+ return false;
+ }
+
+ bool down()
+ {
+ if (pos == path.length)
+ return false;
+ while (++pos != path.length)
+ if (isDirSeparator(path[pos]))
+ return true;
+ return false;
+ }
+}
+
final class FileManager
{
private StringTable!(const(ubyte)[]) files;
+ private StringTable!(bool) packageStatus;
+
+ // check if the package path of the given path exists. The input path is
+ // expected to contain the full path to the module, so the parent
+ // directories of that path are checked.
+ private bool packageExists(const(char)[] p) nothrow
+ {
+ // step 1, look for the closest parent path that is cached
+ bool exists = true;
+ auto st = PathStack(p);
+ while (st.up) {
+ if (auto cached = packageStatus.lookup(st.cur)) {
+ exists = cached.value;
+ break;
+ }
+ }
+ // found a parent that is cached (or reached the end of the stack).
+ // step 2, traverse back up the stack storing either false if the
+ // parent doesn't exist, or the result of the `exists` call if it does.
+ while (st.down) {
+ if (!exists)
+ packageStatus.insert(st.cur, false);
+ else
+ exists = packageStatus.insert(st.cur, FileName.exists(st.cur) == 2).value;
+ }
+
+ // at this point, exists should be the answer.
+ return exists;
+ }
///
public this () nothrow
{
this.files._init();
+ this.packageStatus._init();
}
nothrow:
* the found file name or
* `null` if it is not different from filename.
*/
- static const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
+ const(char)[] lookForSourceFile(const char[] filename, const char*[] path)
{
//printf("lookForSourceFile(`%.*s`)\n", cast(int)filename.length, filename.ptr);
/* Search along path[] for .di file, then .d file, then .i file, then .c file.
*/
+ // see if we should check for the module locally.
+ bool checkLocal = packageExists(filename);
const sdi = FileName.forceExt(filename, hdr_ext);
- if (FileName.exists(sdi) == 1)
+ if (checkLocal && FileName.exists(sdi) == 1)
return sdi;
scope(exit) FileName.free(sdi.ptr);
// Special file name representing `stdin`, always assume its presence
if (sd == "__stdin.d")
return sd;
- if (FileName.exists(sd) == 1)
+ if (checkLocal && FileName.exists(sd) == 1)
return sd;
scope(exit) FileName.free(sd.ptr);
const si = FileName.forceExt(filename, i_ext);
- if (FileName.exists(si) == 1)
+ if (checkLocal && FileName.exists(si) == 1)
return si;
scope(exit) FileName.free(si.ptr);
const sc = FileName.forceExt(filename, c_ext);
- if (FileName.exists(sc) == 1)
+ if (checkLocal && FileName.exists(sc) == 1)
return sc;
scope(exit) FileName.free(sc.ptr);
- if (FileName.exists(filename) == 2)
+ if (checkLocal)
{
- /* The filename exists and it's a directory.
- * Therefore, the result should be: filename/package.d
- * iff filename/package.d is a file
- */
- const ni = FileName.combine(filename, package_di);
- if (FileName.exists(ni) == 1)
- return ni;
- FileName.free(ni.ptr);
-
- const n = FileName.combine(filename, package_d);
- if (FileName.exists(n) == 1)
- return n;
- FileName.free(n.ptr);
+ auto cached = packageStatus.lookup(filename);
+ if (!cached)
+ cached = packageStatus.insert(filename, FileName.exists(filename) == 2);
+ if (cached.value)
+ {
+ /* The filename exists and it's a directory.
+ * Therefore, the result should be: filename/package.d
+ * iff filename/package.d is a file
+ */
+ const ni = FileName.combine(filename, package_di);
+ if (FileName.exists(ni) == 1)
+ return ni;
+ FileName.free(ni.ptr);
+
+ const n = FileName.combine(filename, package_d);
+ if (FileName.exists(n) == 1)
+ return n;
+ FileName.free(n.ptr);
+ }
}
+
if (FileName.absolute(filename))
return null;
if (!path.length)
const p = entry.toDString();
const(char)[] n = FileName.combine(p, sdi);
+
+ if (!packageExists(n)) {
+ FileName.free(n.ptr);
+ continue; // no need to check for anything else.
+ }
if (FileName.exists(n) == 1) {
return n;
}
const b = FileName.removeExt(filename);
n = FileName.combine(p, b);
FileName.free(b.ptr);
- if (FileName.exists(n) == 2)
+
+ scope(exit) FileName.free(n.ptr);
+
+ // also cache this if we are looking for package.d[i]
+ auto cached = packageStatus.lookup(n);
+ if (!cached) {
+ cached = packageStatus.insert(n, FileName.exists(n) == 2);
+ }
+
+ if (cached.value)
{
const n2i = FileName.combine(n, package_di);
if (FileName.exists(n2i) == 1)
}
FileName.free(n2.ptr);
}
- FileName.free(n.ptr);
}
return null;
}
}
/*************************************************
- * Find index of function in vtbl[0..dim] that
+ * Find index of function in vtbl[0..length] that
* this function overrides.
* Prefer an exact match to a covariant one.
* Params:
{
foreach (b; cd.interfaces)
{
- auto v = findVtblIndex(&b.sym.vtbl, cast(int)b.sym.vtbl.dim);
+ auto v = findVtblIndex(&b.sym.vtbl, cast(int)b.sym.vtbl.length);
if (v >= 0)
return b;
}
if (!isVirtual())
return false;
// If it's a final method, and does not override anything, then it is not virtual
- if (isFinalFunc() && foverrides.dim == 0)
+ if (isFinalFunc() && foverrides.length == 0)
{
return false;
}
if (fdthis != this)
{
bool found = false;
- for (size_t i = 0; i < siblingCallers.dim; ++i)
+ for (size_t i = 0; i < siblingCallers.length; ++i)
{
if (siblingCallers[i] == fdthis)
found = true;
if (requiresClosure)
goto Lyes;
- for (size_t i = 0; i < closureVars.dim; i++)
+ for (size_t i = 0; i < closureVars.length; i++)
{
VarDeclaration v = closureVars[i];
//printf("\tv = %s\n", v.toChars());
- for (size_t j = 0; j < v.nestedrefs.dim; j++)
+ for (size_t j = 0; j < v.nestedrefs.length; j++)
{
FuncDeclaration f = v.nestedrefs[j];
assert(f != this);
*/
final bool hasNestedFrameRefs()
{
- if (closureVars.dim)
+ if (closureVars.length)
return true;
/* If a virtual function has contracts, assume its variables are referenced
if (fdrequire || fdensure)
return true;
- if (foverrides.dim && isVirtualMethod())
+ if (foverrides.length && isVirtualMethod())
{
- for (size_t i = 0; i < foverrides.dim; i++)
+ for (size_t i = 0; i < foverrides.length; i++)
{
FuncDeclaration fdv = foverrides[i];
if (fdv.hasNestedFrameRefs())
* becomes:
* in { { statements1... } { statements2... } ... }
*/
- assert(frequires.dim);
+ assert(frequires.length);
auto loc = (*frequires)[0].loc;
auto s = new Statements;
foreach (r; *frequires)
* out(__result) { { ref id1 = __result; { statements1... } }
* { ref id2 = __result; { statements2... } } ... }
*/
- assert(fensures.dim);
+ assert(fensures.length);
auto loc = (*fensures)[0].ensure.loc;
auto s = new Statements;
foreach (r; *fensures)
printf("\tthis: %s\n", tthis.toChars());
if (fargs)
{
- for (size_t i = 0; i < fargs.dim; i++)
+ for (size_t i = 0; i < fargs.length; i++)
{
Expression arg = (*fargs)[i];
assert(arg.type);
{
// max num of overloads to print (-v overrides this).
enum int DisplayLimit = 5;
- int displayed;
const(char)* constraintsTip;
-
// determine if the first candidate was printed
- bool printed = false;
+ int printed;
- overloadApply(declaration, (Dsymbol s)
+ bool matchSymbol(Dsymbol s, bool print, bool single_candidate = false)
{
- Dsymbol nextOverload;
-
if (auto fd = s.isFuncDeclaration())
{
// Don't print overloads which have errors.
// Not that if the whole overload set has errors, we'll never reach
// this point so there's no risk of printing no candidate
if (fd.errors || fd.type.ty == Terror)
- return 0;
+ return false;
// Don't print disabled functions, or `deprecated` outside of deprecated scope
if (fd.storage_class & STC.disable || (fd.isDeprecated() && !showDeprecated))
- return 0;
-
- const single_candidate = fd.overnext is null;
+ return false;
+ if (!print)
+ return true;
auto tf = cast(TypeFunction) fd.type;
.errorSupplemental(fd.loc,
printed ? " `%s%s`" :
single_candidate ? "Candidate is: `%s%s`" : "Candidates are: `%s%s`",
fd.toPrettyChars(),
parametersTypeToChars(tf.parameterList));
- printed = true;
- nextOverload = fd.overnext;
}
else if (auto td = s.isTemplateDeclaration())
{
import dmd.staticcond;
+ if (!print)
+ return true;
const tmsg = td.toCharsNoConstraints();
const cmsg = td.getConstraintEvalError(constraintsTip);
- const single_candidate = td.overnext is null;
-
// add blank space if there are multiple candidates
// the length of the blank space is `strlen("Candidates are: ")`
printed ? " `%s`\n%s" :
single_candidate ? "Candidate is: `%s`\n%s" : "Candidates are: `%s`\n%s",
tmsg, cmsg);
- printed = true;
}
else
{
printed ? " `%s`" :
single_candidate ? "Candidate is: `%s`" : "Candidates are: `%s`",
tmsg);
- printed = true;
}
- nextOverload = td.overnext;
}
-
- if (global.params.verbose || ++displayed < DisplayLimit)
- return 0;
-
- // Too many overloads to sensibly display.
- // Just show count of remaining overloads.
- int num = 0;
- overloadApply(nextOverload, (s) { ++num; return 0; });
-
- if (num > 0)
- .errorSupplemental(loc, "... (%d more, -v to show) ...", num);
- return 1; // stop iterating
+ return true;
+ }
+ // determine if there's > 1 candidate
+ int count = 0;
+ overloadApply(declaration, (s) {
+ if (matchSymbol(s, false))
+ count++;
+ return count > 1;
+ });
+ int skipped = 0;
+ overloadApply(declaration, (s) {
+ if (global.params.verbose || printed < DisplayLimit)
+ {
+ if (matchSymbol(s, true, count == 1))
+ printed++;
+ }
+ else
+ {
+ // Too many overloads to sensibly display.
+ // Just show count of remaining overloads.
+ if (matchSymbol(s, false))
+ skipped++;
+ }
+ return 0;
});
+ if (skipped > 0)
+ .errorSupplemental(loc, "... (%d more, -v to show) ...", skipped);
// Nothing was displayed, all overloads are either disabled or deprecated
- if (!displayed)
+ if (!printed)
.errorSupplemental(loc, "All possible candidates are marked as `deprecated` or `@disable`");
// should be only in verbose mode
if (constraintsTip)
for (Dsymbol sx = f; sx && sx != outerFunc; sx = sx.toParentP(outerFunc))
{
FuncDeclaration fy = sx.isFuncDeclaration();
- if (fy && fy.closureVars.dim)
+ if (fy && fy.closureVars.length)
{
/* fy needs a closure if it has closureVars[],
* because the frame pointer in the closure will be accessed.
//printf("checkEscapingSiblings(f = %s, outerfunc = %s)\n", f.toChars(), outerFunc.toChars());
bool bAnyClosures = false;
- for (size_t i = 0; i < f.siblingCallers.dim; ++i)
+ for (size_t i = 0; i < f.siblingCallers.length; ++i)
{
FuncDeclaration g = f.siblingCallers[i];
if (g.isThis() || g.tookAddressOf)
bool gag = false, Loc loc = Loc.init, const(char)* fmt = null,
RootObject arg0 = null, RootObject arg1 = null, RootObject arg2 = null)
{
- // TODO:
- // For @system variables, unsafe initializers at global scope should mark
- // the variable @system, see https://dlang.org/dips/1035
-
- if (!sc.func)
- return false;
-
if (sc.intypeof)
return false; // typeof(cast(int*)0) is safe
if (sc.flags & SCOPE.debug_) // debug {} scopes are permissive
return false;
+ if (!sc.func)
+ {
+ if (sc.varDecl)
+ {
+ if (sc.varDecl.storage_class & STC.safe)
+ {
+ .error(loc, fmt, arg0 ? arg0.toChars() : "", arg1 ? arg1.toChars() : "", arg2 ? arg2.toChars() : "");
+ return true;
+ }
+ else if (!(sc.varDecl.storage_class & STC.system))
+ {
+ sc.varDecl.storage_class |= STC.system;
+ }
+ }
+ return false;
+ }
+
+
if (sc.flags & SCOPE.compile) // __traits(compiles, x)
{
if (sc.func.isSafeBypassingInference())
{
buf.writestring("pragma (");
buf.writestring(s.ident.toString());
- if (s.args && s.args.dim)
+ if (s.args && s.args.length)
{
buf.writestring(", ");
argsToBuffer(s.args, buf, hgs);
buf.printf("%s.", pid.toChars());
}
buf.writestring(imp.id.toString());
- if (imp.names.dim)
+ if (imp.names.length)
{
buf.writestring(" : ");
foreach (const i, const name; imp.names)
buf.writenl();
return;
}
- if (d.decl.dim == 0 || (hgs.hdrgen && d.decl.dim == 1 && (*d.decl)[0].isUnitTestDeclaration()))
+ if (d.decl.length == 0 || (hgs.hdrgen && d.decl.length == 1 && (*d.decl)[0].isUnitTestDeclaration()))
{
// hack for bugzilla 8081
if (hasSTC) buf.writeByte(' ');
buf.writestring("{}");
}
- else if (d.decl.dim == 1)
+ else if (d.decl.length == 1)
{
if (hasSTC) buf.writeByte(' ');
(*d.decl)[0].accept(this);
{
visibilityToBuffer(buf, d.visibility);
AttribDeclaration ad = cast(AttribDeclaration)d;
- if (ad.decl.dim <= 1)
+ if (ad.decl.length <= 1)
buf.writeByte(' ');
- if (ad.decl.dim == 1 && (*ad.decl)[0].isVisibilityDeclaration)
+ if (ad.decl.length == 1 && (*ad.decl)[0].isVisibilityDeclaration)
visit(cast(AttribDeclaration)(*ad.decl)[0]);
else
visit(cast(AttribDeclaration)d);
buf.writeByte(' ');
buf.printf("align (%s)", exp.toChars());
}
- if (d.decl && d.decl.dim < 2)
+ if (d.decl && d.decl.length < 2)
buf.writeByte(' ');
}
else
{
buf.writestring("pragma (");
buf.writestring(d.ident.toString());
- if (d.args && d.args.dim)
+ if (d.args && d.args.length)
{
buf.writestring(", ");
argsToBuffer(d.args, buf, hgs);
bool visitEponymousMember(TemplateDeclaration d)
{
- if (!d.members || d.members.dim != 1)
+ if (!d.members || d.members.length != 1)
return false;
Dsymbol onemember = (*d.members)[0];
if (onemember.ident != d.ident)
void visitTemplateParameters(TemplateParameters* parameters)
{
- if (!parameters || !parameters.dim)
+ if (!parameters || !parameters.length)
return;
foreach (i, p; *parameters)
{
void visitBaseClasses(ClassDeclaration d)
{
- if (!d || !d.baseclasses.dim)
+ if (!d || !d.baseclasses.length)
return;
if (!d.isAnonymous())
buf.writestring(" : ");
Statement s1;
if (f.semanticRun >= PASS.semantic3done && cs)
{
- s1 = (*cs.statements)[cs.statements.dim - 1];
+ s1 = (*cs.statements)[cs.statements.length - 1];
}
else
s1 = !cs ? f.fbody : null;
}
buf.writestring("new ");
typeToBuffer(e.newtype, null, buf, hgs);
- if (e.arguments && e.arguments.dim)
+ if (e.arguments && e.arguments.length)
{
buf.writeByte('(');
argsToBuffer(e.arguments, buf, hgs);
}
buf.writestring("new");
buf.writestring(" class ");
- if (e.arguments && e.arguments.dim)
+ if (e.arguments && e.arguments.length)
{
buf.writeByte('(');
argsToBuffer(e.arguments, buf, hgs);
buf.writestring(" == ");
typeToBuffer(e.tspec, null, buf, hgs);
}
- if (e.parameters && e.parameters.dim)
+ if (e.parameters && e.parameters.length)
{
buf.writestring(", ");
scope v = new DsymbolPrettyPrintVisitor(buf, hgs);
*/
void argExpTypesToCBuffer(OutBuffer* buf, Expressions* arguments)
{
- if (!arguments || !arguments.dim)
+ if (!arguments || !arguments.length)
return;
HdrGenState hgs;
foreach (i, arg; *arguments)
void arrayObjectsToBuffer(OutBuffer* buf, Objects* objects)
{
- if (!objects || !objects.dim)
+ if (!objects || !objects.length)
return;
HdrGenState hgs;
foreach (i, o; *objects)
parameterToBuffer(parameter, &buf, &hgs);
- if (tf.parameterList.varargs == VarArg.typesafe && parameter == tf.parameterList[tf.parameterList.parameters.dim - 1])
+ if (tf.parameterList.varargs == VarArg.typesafe && parameter == tf.parameterList[tf.parameterList.parameters.length - 1])
{
buf.writestring("...");
}
{
buf.writeByte('@');
- bool isAnonymous = p.userAttribDecl.atts.dim > 0 && !(*p.userAttribDecl.atts)[0].isCallExp();
+ bool isAnonymous = p.userAttribDecl.atts.length > 0 && !(*p.userAttribDecl.atts)[0].isCallExp();
if (isAnonymous)
buf.writeByte('(');
*/
private void argsToBuffer(Expressions* expressions, OutBuffer* buf, HdrGenState* hgs, Expression basis = null)
{
- if (!expressions || !expressions.dim)
+ if (!expressions || !expressions.length)
return;
version (all)
{
else
{
// Sparse style formatting, for debug use only
- // [0..dim: basis, 1: e1, 5: e5]
+ // [0..length: basis, 1: e1, 5: e5]
if (basis)
{
buf.writestring("0..");
- buf.print(expressions.dim);
+ buf.print(expressions.length);
buf.writestring(": ");
expToBuffer(basis, PREC.assign, buf, hgs);
}
buf.writestring("()");
return;
}
- if (ti.tiargs.dim == 1)
+ if (ti.tiargs.length == 1)
{
RootObject oarg = (*ti.tiargs)[0];
if (Type t = isType(oarg))
{
- if (t.equals(Type.tstring) || t.equals(Type.twstring) || t.equals(Type.tdstring) || t.mod == 0 && (t.isTypeBasic() || t.ty == Tident && (cast(TypeIdentifier)t).idents.dim == 0))
+ if (t.equals(Type.tstring) || t.equals(Type.twstring) || t.equals(Type.tdstring) || t.mod == 0 && (t.isTypeBasic() || t.ty == Tident && (cast(TypeIdentifier)t).idents.length == 0))
{
buf.writestring(t.toChars());
return;
// Analyse all input and output operands.
if (s.args)
{
- foreach (i; 0 .. s.args.dim)
+ foreach (i; 0 .. s.args.length)
{
Expression e = (*s.args)[i];
e = e.expressionSemantic(sc);
// Analyse all clobbers.
if (s.clobbers)
{
- foreach (i; 0 .. s.clobbers.dim)
+ foreach (i; 0 .. s.clobbers.length)
{
Expression e = (*s.clobbers)[i];
e = e.expressionSemantic(sc);
// Analyse all goto labels.
if (s.labels)
{
- foreach (i; 0 .. s.labels.dim)
+ foreach (i; 0 .. s.labels.length)
{
Identifier ident = (*s.labels)[i];
GotoStatement gs = new GotoStatement(s.loc, ident);
static Initializer copyStruct(StructInitializer vi)
{
auto si = new StructInitializer(vi.loc);
- assert(vi.field.dim == vi.value.dim);
- si.field.setDim(vi.field.dim);
- si.value.setDim(vi.value.dim);
- foreach (const i; 0 .. vi.field.dim)
+ assert(vi.field.length == vi.value.length);
+ si.field.setDim(vi.field.length);
+ si.value.setDim(vi.value.length);
+ foreach (const i; 0 .. vi.field.length)
{
si.field[i] = vi.field[i];
si.value[i] = vi.value[i].syntaxCopy();
static Initializer copyArray(ArrayInitializer vi)
{
auto ai = new ArrayInitializer(vi.loc);
- assert(vi.index.dim == vi.value.dim);
- ai.index.setDim(vi.index.dim);
- ai.value.setDim(vi.value.dim);
- foreach (const i; 0 .. vi.value.dim)
+ assert(vi.index.length == vi.value.length);
+ ai.index.setDim(vi.index.length);
+ ai.value.setDim(vi.value.length);
+ foreach (const i; 0 .. vi.value.length)
{
ai.index[i] = vi.index[i] ? vi.index[i].syntaxCopy() : null;
ai.value[i] = vi.value[i].syntaxCopy();
Expression e;
//printf("ArrayInitializer::toAssocArrayInitializer()\n");
//static int i; if (++i == 2) assert(0);
- const dim = ai.value.dim;
+ const dim = ai.value.length;
auto keys = new Expressions(dim);
auto values = new Expressions(dim);
for (size_t i = 0; i < dim; i++)
auto ie = new ExpInitializer(i.loc, sle);
return ie.initializerSemantic(sc, t, needInterpret);
}
- else if ((t.ty == Tdelegate || t.isPtrToFunction()) && i.value.dim == 0)
+ else if ((t.ty == Tdelegate || t.isPtrToFunction()) && i.value.length == 0)
{
const tok = (t.ty == Tdelegate) ? TOK.delegate_ : TOK.function_;
/* Rewrite as empty delegate literal { }
}
i.type = t;
length = 0;
- for (size_t j = 0; j < i.index.dim; j++)
+ for (size_t j = 0; j < i.index.length; j++)
{
Expression idx = i.index[j];
if (idx)
TupleExp te = ei.exp.isTupleExp();
i.index.remove(j);
i.value.remove(j);
- for (size_t k = 0; k < te.exps.dim; ++k)
+ for (size_t k = 0; k < te.exps.length; ++k)
{
Expression e = (*te.exps)[k];
i.index.insert(j + k, cast(Expression)null);
{
return i; // Failed, suppress duplicate error messages
}
- if (i.exp.type.isTypeTuple() && i.exp.type.isTypeTuple().arguments.dim == 0)
+ if (i.exp.type.isTypeTuple() && i.exp.type.isTypeTuple().arguments.length == 0)
{
Type et = i.exp.type;
i.exp = new TupleExp(i.exp.loc, new Expressions());
uinteger_t dim2 = dim1;
if (auto ale = i.exp.isArrayLiteralExp())
{
- dim2 = ale.elements ? ale.elements.dim : 0;
+ dim2 = ale.elements ? ale.elements.length : 0;
}
else if (auto se = i.exp.isSliceExp())
{
Expressions* values;
if (init.isAssociativeArray())
{
- keys = new Expressions(init.value.dim);
- values = new Expressions(init.value.dim);
- for (size_t i = 0; i < init.value.dim; i++)
+ keys = new Expressions(init.value.length);
+ values = new Expressions(init.value.length);
+ for (size_t i = 0; i < init.value.length; i++)
{
Expression e = init.index[i];
if (!e)
}
else
{
- auto elements = new Expressions(init.value.dim);
+ auto elements = new Expressions(init.value.length);
elements.zero();
- for (size_t i = 0; i < init.value.dim; i++)
+ for (size_t i = 0; i < init.value.length; i++)
{
assert(!init.index[i]); // already asserted by isAssociativeArray()
Initializer iz = init.value[i];
{
/* Calculate the length of the array literal
*/
- edim = cast(uint)init.value.dim;
+ edim = cast(uint)init.value.length;
size_t j = 0;
- foreach (i; 0 .. init.value.dim)
+ foreach (i; 0 .. init.value.length)
{
if (auto e = init.index[i])
{
auto elements = new Expressions(edim);
elements.zero();
size_t j = 0;
- foreach (i; 0 .. init.value.dim)
+ foreach (i; 0 .. init.value.length)
{
if (auto e = init.index[i])
j = cast(size_t)e.toInteger();
extern(D) void property(const char[] name, Parameters* parameters)
{
- if (parameters is null || parameters.dim == 0)
+ if (parameters is null || parameters.length == 0)
return;
propertyStart(name);
arrayStart();
if (parameters)
{
- for (size_t i = 0; i < parameters.dim; i++)
+ for (size_t i = 0; i < parameters.length; i++)
{
Parameter p = (*parameters)[i];
objectStart();
property("comment", s.comment.toDString);
propertyStart("members");
arrayStart();
- for (size_t i = 0; i < s.members.dim; i++)
+ for (size_t i = 0; i < s.members.length; i++)
{
(*s.members)[i].accept(this);
}
property("alias", s.aliasId.toString());
bool hasRenamed = false;
bool hasSelective = false;
- for (size_t i = 0; i < s.aliases.dim; i++)
+ for (size_t i = 0; i < s.aliases.length; i++)
{
// avoid empty "renamed" and "selective" sections
if (hasRenamed && hasSelective)
// import foo : alias1 = target1;
propertyStart("renamed");
objectStart();
- for (size_t i = 0; i < s.aliases.dim; i++)
+ for (size_t i = 0; i < s.aliases.length; i++)
{
const name = s.names[i];
const _alias = s.aliases[i];
Dsymbols* ds = d.include(null);
if (ds)
{
- for (size_t i = 0; i < ds.dim; i++)
+ for (size_t i = 0; i < ds.length; i++)
{
Dsymbol s = (*ds)[i];
s.accept(this);
return; // Don't visit the if/else bodies again below
}
Dsymbols* ds = d.decl ? d.decl : d.elsedecl;
- for (size_t i = 0; i < ds.dim; i++)
+ for (size_t i = 0; i < ds.length; i++)
{
Dsymbol s = (*ds)[i];
s.accept(this);
{
propertyStart("members");
arrayStart();
- for (size_t i = 0; i < d.members.dim; i++)
+ for (size_t i = 0; i < d.members.length; i++)
{
Dsymbol s = (*d.members)[i];
s.accept(this);
if (tf && tf.ty == Tfunction)
property("parameters", tf.parameterList.parameters);
property("endline", "endchar", d.endloc);
- if (d.foverrides.dim)
+ if (d.foverrides.length)
{
propertyStart("overrides");
arrayStart();
- for (size_t i = 0; i < d.foverrides.dim; i++)
+ for (size_t i = 0; i < d.foverrides.length; i++)
{
FuncDeclaration fd = d.foverrides[i];
item(fd.toPrettyChars().toDString);
jsonProperties(d);
propertyStart("parameters");
arrayStart();
- for (size_t i = 0; i < d.parameters.dim; i++)
+ for (size_t i = 0; i < d.parameters.length; i++)
{
TemplateParameter s = (*d.parameters)[i];
objectStart();
}
propertyStart("members");
arrayStart();
- for (size_t i = 0; i < d.members.dim; i++)
+ for (size_t i = 0; i < d.members.length; i++)
{
Dsymbol s = (*d.members)[i];
s.accept(this);
{
if (d.members)
{
- for (size_t i = 0; i < d.members.dim; i++)
+ for (size_t i = 0; i < d.members.length; i++)
{
Dsymbol s = (*d.members)[i];
s.accept(this);
{
propertyStart("members");
arrayStart();
- for (size_t i = 0; i < d.members.dim; i++)
+ for (size_t i = 0; i < d.members.length; i++)
{
Dsymbol s = (*d.members)[i];
s.accept(this);
requiredProperty("name", m.md ? m.md.toString() : null);
requiredProperty("file", m.srcfile.toString());
propertyBool("isRoot", m.isRoot());
- if(m.contentImportedFiles.dim > 0)
+ if(m.contentImportedFiles.length > 0)
{
propertyStart("contentImports");
arrayStart();
if (ty)
{
writeMangledName(ty.sym);
- auto dim = e.elements.dim;
+ auto dim = e.elements.length;
foreach (i; 0..dim)
{
auto elem = (*e.elements)[i];
if (p && p[0] == '#' && p[1] == '!')
{
p += 2;
- while (1)
+ for (;;p++)
{
- char c = *p++;
+ char c = *p;
switch (c)
{
+ case '\n':
+ p++;
+ goto case;
case 0:
case 0x1A:
- p--;
- goto case;
- case '\n':
break;
+
default:
+ // Note: We do allow malformed UTF-8 on shebang line.
+ // It could have a meaning if the native system
+ // encoding is not Unicode. See test compilable/test13512.d
+ // for example encoded in KOI-8.
+ // We also allow bidirectional control characters.
+ // We do not execute the shebang line, so it can't be used
+ // to conceal code. It is up to the shell to sanitize it.
continue;
}
break;
const u = decodeUTF();
if (isUniAlpha(u))
continue;
- error("char 0x%04x not allowed in identifier", u);
+ error(t.loc, "char 0x%04x not allowed in identifier", u);
p = s;
}
break;
continue;
case 0:
case 0x1A:
- error("unterminated /* */ comment");
+ error(t.loc, "unterminated /* */ comment");
p = end;
t.loc = loc();
t.value = TOK.endOfFile;
continue;
case 0:
case 0x1A:
- error("unterminated /+ +/ comment");
+ error(t.loc, "unterminated /+ +/ comment");
p = end;
t.loc = loc();
t.value = TOK.endOfFile;
}
}
if (c < 0x80 && isprint(c))
- error("character '%c' is not a valid token", c);
+ error(t.loc, "character '%c' is not a valid token", c);
else
- error("character 0x%02x is not a valid token", c);
+ error(t.loc, "character 0x%02x is not a valid token", c);
p++;
continue;
+ // assert(0);
}
}
}
stringbuffer.setsize(0);
while (1)
{
+ const s = p;
dchar c = *p++;
//printf("c = '%c'\n", c);
switch (c)
{
// Start of identifier; must be a heredoc
Token tok;
- p--;
+ p = s;
scan(&tok); // read in heredoc identifier
if (tok.value != TOK.identifier)
{
{
Token tok;
auto psave = p;
- p--;
+ p = s;
scan(&tok); // read in possible heredoc identifier
//printf("endid = '%s'\n", tok.ident.toChars());
if (tok.value == TOK.identifier && tok.ident is hereid)
*/
private uint decodeUTF()
{
+ string msg;
+ auto result = decodeUTFpure(msg);
+
+ if (msg)
+ error("%.*s", cast(int)msg.length, msg.ptr);
+ return result;
+ }
+
+ /********************************************
+ * Same as above, but the potential error message is stored to the
+ * msg parameter instead of being issued.
+ */
+ private pure uint decodeUTFpure(out string msg)
+ {
const s = p;
assert(*s & 0x80);
// Check length of remaining string up to 4 UTF-8 characters
}
size_t idx = 0;
dchar u;
- const msg = utf_decodeChar(s[0 .. len], idx, u);
+ msg = utf_decodeChar(s[0 .. len], idx, u);
p += idx - 1;
- if (msg)
- {
- error("%.*s", cast(int)msg.length, msg.ptr);
- }
+ if (!msg && isBidiControl(u))
+ msg = "Bidirectional control characters are disallowed for security reasons.";
return u;
}
Parameters* params = parameterList.parameters;
if (mod & MODFlags.wild)
params = parameterList.parameters.copy();
- for (size_t i = 0; i < params.dim; i++)
+ for (size_t i = 0; i < params.length; i++)
{
Parameter p = (*params)[i];
Type t = p.type.substWildTo(m);
if (parameterList.varargs == VarArg.none && nparams > nargs && !parameterList[nargs].defaultArg)
{
OutBuffer buf;
- buf.printf("too few arguments, expected `%d`, got `%d`", cast(int)nparams, cast(int)nargs);
+ buf.printf("too few arguments, expected %d, got %d", cast(int)nparams, cast(int)nargs);
if (pMessage)
*pMessage = buf.extractChars();
return MATCH.nomatch;
final void syntaxCopyHelper(TypeQualified t)
{
//printf("TypeQualified::syntaxCopyHelper(%s) %s\n", t.toChars(), toChars());
- idents.setDim(t.idents.dim);
- for (size_t i = 0; i < idents.dim; i++)
+ idents.setDim(t.idents.length);
+ for (size_t i = 0; i < idents.length; i++)
{
RootObject id = t.idents[i];
with (DYNCAST) final switch (id.dyncast())
override TypeInstance syntaxCopy()
{
- //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.dim);
+ //printf("TypeInstance::syntaxCopy() %s, %d\n", toChars(), idents.length);
auto t = new TypeInstance(loc, tempinst.syntaxCopy(null));
t.syntaxCopyHelper(this);
t.mod = mod;
auto structelems = new Expressions(sym.nonHiddenFields());
uint offset = 0;
- foreach (j; 0 .. structelems.dim)
+ foreach (j; 0 .. structelems.length)
{
VarDeclaration vd = sym.fields[j];
Expression e;
/* If any of the fields are const or immutable,
* then one cannot assign this struct.
*/
- for (size_t i = 0; i < sym.fields.dim; i++)
+ for (size_t i = 0; i < sym.fields.length; i++)
{
VarDeclaration v = sym.fields[i];
//printf("%s [%d] v = (%s) %s, v.offset = %d, v.parent = %s\n", sym.toChars(), i, v.kind(), v.toChars(), v.offset, v.parent.kind());
if (sym.isNested())
return true;
- for (size_t i = 0; i < sym.fields.dim; i++)
+ for (size_t i = 0; i < sym.fields.length; i++)
{
VarDeclaration v = sym.fields[i];
if (!v.isDataseg() && v.type.needsNested())
* allow the conversion.
*/
uint offset = ~0; // dead-store to prevent spurious warning
- for (size_t i = 0; i < sym.fields.dim; i++)
+ for (size_t i = 0; i < sym.fields.length; i++)
{
VarDeclaration v = sym.fields[i];
if (i == 0)
{
if (arguments)
{
- for (size_t i = 0; i < arguments.dim; i++)
+ for (size_t i = 0; i < arguments.length; i++)
{
Parameter arg = (*arguments)[i];
assert(arg && arg.type);
extern (D) this(Expressions* exps)
{
super(Ttuple);
- auto arguments = new Parameters(exps ? exps.dim : 0);
+ auto arguments = new Parameters(exps ? exps.length : 0);
if (exps)
{
- for (size_t i = 0; i < exps.dim; i++)
+ for (size_t i = 0; i < exps.length; i++)
{
Expression e = (*exps)[i];
if (e.type.ty == Ttuple)
return true;
if (auto tt = t.isTypeTuple())
{
- if (arguments.dim == tt.arguments.dim)
+ if (arguments.length == tt.arguments.length)
{
- for (size_t i = 0; i < tt.arguments.dim; i++)
+ for (size_t i = 0; i < tt.arguments.length; i++)
{
const Parameter arg1 = (*arguments)[i];
Parameter arg2 = (*tt.arguments)[i];
return MATCH.exact;
if (auto tt = to.isTypeTuple())
{
- if (arguments.dim == tt.arguments.dim)
+ if (arguments.length == tt.arguments.length)
{
MATCH m = MATCH.exact;
- for (size_t i = 0; i < tt.arguments.dim; i++)
+ for (size_t i = 0; i < tt.arguments.length; i++)
{
Parameter arg1 = (*arguments)[i];
Parameter arg2 = (*tt.arguments)[i];
Parameters* params = null;
if (parameters)
{
- params = new Parameters(parameters.dim);
- for (size_t i = 0; i < params.dim; i++)
+ params = new Parameters(parameters.length);
+ for (size_t i = 0; i < params.length; i++)
(*params)[i] = (*parameters)[i].syntaxCopy();
}
return params;
override void visit(ArrayLiteralExp e)
{
- if (e.type.ty != Tarray || !e.elements || !e.elements.dim || e.onstack)
+ if (e.type.ty != Tarray || !e.elements || !e.elements.length || e.onstack)
return;
if (f.setGC())
{
override void visit(AssocArrayLiteralExp e)
{
- if (!e.keys.dim)
+ if (!e.keys.length)
return;
if (f.setGC())
{
override void visit(IndexExp e)
{
Type t1b = e.e1.type.toBasetype();
- if (t1b.ty == Taarray)
+ if (e.modifiable && t1b.ty == Taarray)
{
if (f.setGC())
{
- e.error("indexing an associative array in `@nogc` %s `%s` may cause a GC allocation",
+ e.error("assigning an associative array element in `@nogc` %s `%s` may cause a GC allocation",
f.kind(), f.toPrettyChars());
err = true;
return;
}
- f.printGCUsage(e.loc, "indexing an associative array may cause a GC allocation");
+ f.printGCUsage(e.loc, "assigning an associative array element may cause a GC allocation");
}
}
*/
mystate.defaultBlock = s.sdefault ? newNode() : mystate.breakBlock;
- const numcases = s.cases ? s.cases.dim : 0;
+ const numcases = s.cases ? s.cases.length : 0;
/* allocate a block for each case
*/
return 1;
}
- assert(literal.elements.dim == 1);
+ assert(literal.elements.length == 1);
auto se = (*literal.elements)[0].toStringExp();
assert(se);
if (!fd.objc.selector)
return;
TypeFunction tf = cast(TypeFunction)fd.type;
- if (fd.objc.selector.paramCount != tf.parameterList.parameters.dim)
+ if (fd.objc.selector.paramCount != tf.parameterList.parameters.length)
fd.error("number of colons in Objective-C selector must match number of parameters");
if (fd.parent && fd.parent.isTemplateInstance())
fd.error("template cannot have an Objective-C selector attached");
ae.e1 = ae.e1.expressionSemantic(sc);
ae.e1 = resolveProperties(sc, ae.e1);
Expression ae1old = ae.e1;
- const(bool) maybeSlice = (ae.arguments.dim == 0 || ae.arguments.dim == 1 && (*ae.arguments)[0].op == EXP.interval);
+ const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
IntervalExp ie = null;
- if (maybeSlice && ae.arguments.dim)
+ if (maybeSlice && ae.arguments.length)
{
ie = (*ae.arguments)[0].isIntervalExp();
}
ae.e1 = ae.e1.expressionSemantic(sc);
ae.e1 = resolveProperties(sc, ae.e1);
Expression ae1old = ae.e1;
- const(bool) maybeSlice = (ae.arguments.dim == 0 || ae.arguments.dim == 1 && (*ae.arguments)[0].op == EXP.interval);
+ const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
IntervalExp ie = null;
- if (maybeSlice && ae.arguments.dim)
+ if (maybeSlice && ae.arguments.length)
{
ie = (*ae.arguments)[0].isIntervalExp();
}
return result;
}
// Convert to IndexExp
- if (ae.arguments.dim == 1)
+ if (ae.arguments.length == 1)
{
result = new IndexExp(ae.loc, ae.e1, (*ae.arguments)[0]);
result = result.expressionSemantic(sc);
* the mentioned member, then alias this may be
* used since the object will be fully initialised.
* If the struct is nested, the context pointer is considered
- * one of the members, hence the `ad1.fields.dim == 2 && ad1.vthis`
+ * one of the members, hence the `ad1.fields.length == 2 && ad1.vthis`
* condition.
*/
if (result.op != EXP.assign)
{
// i.e: Rewrote `e1 = e2` -> `e1.some.var = e2`
// Ensure that `var` is the only field member in `ad`
- if (ad.fields.dim == 1 || (ad.fields.dim == 2 && ad.vthis))
+ if (ad.fields.length == 1 || (ad.fields.length == 2 && ad.vthis))
{
if (dve.var == ad.aliasthis.sym)
return result;
{
auto tup1 = e.e1.isTupleExp();
auto tup2 = e.e2.isTupleExp();
- size_t dim = tup1.exps.dim;
- if (dim != tup2.exps.dim)
+ size_t dim = tup1.exps.length;
+ if (dim != tup2.exps.length)
{
e.error("mismatched tuple lengths, `%d` and `%d`",
- cast(int)dim, cast(int)tup2.exps.dim);
+ cast(int)dim, cast(int)tup2.exps.length);
return ErrorExp.get();
}
ae.e1 = ae.e1.expressionSemantic(sc);
ae.e1 = resolveProperties(sc, ae.e1);
Expression ae1old = ae.e1;
- const(bool) maybeSlice = (ae.arguments.dim == 0 || ae.arguments.dim == 1 && (*ae.arguments)[0].op == EXP.interval);
+ const(bool) maybeSlice = (ae.arguments.length == 0 || ae.arguments.length == 1 && (*ae.arguments)[0].op == EXP.interval);
IntervalExp ie = null;
- if (maybeSlice && ae.arguments.dim)
+ if (maybeSlice && ae.arguments.length)
{
ie = (*ae.arguments)[0].isIntervalExp();
}
*/
bool inferApplyArgTypes(ForeachStatement fes, Scope* sc, ref Dsymbol sapply)
{
- if (!fes.parameters || !fes.parameters.dim)
+ if (!fes.parameters || !fes.parameters.length)
return false;
if (sapply) // prefer opApply
{
case Tarray:
case Tsarray:
case Ttuple:
- if (fes.parameters.dim == 2)
+ if (fes.parameters.length == 2)
{
if (!p.type)
{
case Taarray:
{
TypeAArray taa = tab.isTypeAArray();
- if (fes.parameters.dim == 2)
+ if (fes.parameters.length == 2)
{
if (!p.type)
{
{
AggregateDeclaration ad = (tab.ty == Tclass) ? tab.isTypeClass().sym
: tab.isTypeStruct().sym;
- if (fes.parameters.dim == 1)
+ if (fes.parameters.length == 1)
{
if (!p.type)
{
* Fill in missing types in parameters.
*/
const nparams = tdg.parameterList.length;
- if (nparams == 0 || nparams != parameters.dim || tdg.parameterList.varargs != VarArg.none)
+ if (nparams == 0 || nparams != parameters.length || tdg.parameterList.varargs != VarArg.none)
return nomatch; // parameter mismatch
foreach (u, p; *parameters)
if (auto se = arr.isStringExp())
len = se.len;
else if (auto ale = arr.isArrayLiteralExp())
- len = ale.elements.dim;
+ len = ale.elements.length;
else
{
auto tsa = arr.type.toBasetype().isTypeSArray();
void visitAssocArrayLiteral(AssocArrayLiteralExp e)
{
- assert(e.keys.dim == e.values.dim);
+ assert(e.keys.length == e.values.length);
foreach (i, ref ekey; (*e.keys)[])
{
expOptimize(ekey, result & WANTexpand);
case TOK.traits:
Ldeclaration:
a = parseDeclarations(false, pAttrs, pAttrs.comment);
- if (a && a.dim)
- *pLastDecl = (*a)[a.dim - 1];
+ if (a && a.length)
+ *pLastDecl = (*a)[a.length - 1];
break;
case TOK.this_:
*/
if (mod.isRoot() && (global.params.useUnitTests || global.params.ddoc.doOutput || global.params.dihdr.doOutput))
{
+ linkage = LINK.d; // unittests have D linkage
s = parseUnitTest(pAttrs);
if (*pLastDecl)
(*pLastDecl).ddocUnittest = cast(AST.UnitTestDeclaration)s;
if (token.value == TOK.identifier && hasOptionalParensThen(peek(&token), TOK.assign))
{
a = parseAutoDeclarations(getStorageClass!AST(pAttrs), pAttrs.comment);
- if (a && a.dim)
- *pLastDecl = (*a)[a.dim - 1];
+ if (a && a.length)
+ *pLastDecl = (*a)[a.length - 1];
if (pAttrs.udas)
{
s = new AST.UserAttributeDeclaration(pAttrs.udas, a);
deprecation("usage of the `body` keyword is deprecated. Use `do` instead.");
a = parseDeclarations(true, pAttrs, pAttrs.comment);
- if (a && a.dim)
- *pLastDecl = (*a)[a.dim - 1];
+ if (a && a.length)
+ *pLastDecl = (*a)[a.length - 1];
if (pAttrs.udas)
{
s = new AST.UserAttributeDeclaration(pAttrs.udas, a);
if (res.idents)
{
assert(res.link == LINK.cpp);
- assert(res.idents.dim);
- for (size_t i = res.idents.dim; i;)
+ assert(res.idents.length);
+ for (size_t i = res.idents.length; i;)
{
Identifier id = (*res.idents)[--i];
if (s)
else if (res.identExps)
{
assert(res.link == LINK.cpp);
- assert(res.identExps.dim);
- for (size_t i = res.identExps.dim; i;)
+ assert(res.identExps.length);
+ for (size_t i = res.identExps.length; i;)
{
AST.Expression exp = (*res.identExps)[--i];
if (s)
decldefs.push(s);
addComment(s, pAttrs.comment);
}
- else if (a && a.dim)
+ else if (a && a.length)
{
decldefs.append(a);
}
break;
}
}
- assert(dimStack.dim > 0);
+ assert(dimStack.length > 0);
// We're good. Replay indices in the reverse order.
tid = cast(AST.TypeQualified)t;
- while (dimStack.dim)
+ while (dimStack.length)
{
tid.addIndex(dimStack.pop());
}
/* Declarations that start with `alias`
*/
bool isAliasDeclaration = false;
+ auto aliasLoc = token.loc;
if (token.value == TOK.alias_)
{
if (auto a = parseAliasDeclarations(comment))
if (ident)
checkCstyleTypeSyntax(loc, t, alt, ident);
else if (!isThis && (t != AST.Type.terror))
- error("no identifier for declarator `%s`", t.toChars());
+ noIdentifierForDeclarator(t);
if (isAliasDeclaration)
{
else
error("alias cannot have initializer");
}
- v = new AST.AliasDeclaration(loc, ident, t);
+ v = new AST.AliasDeclaration(aliasLoc, ident, t);
v.storage_class = storage_class;
if (pAttrs)
return a;
}
+ /// Report an error that a declaration of type `t` is missing an identifier
+ /// The parser is expected to sit on the next token after the type.
+ private void noIdentifierForDeclarator(AST.Type t)
+ {
+ error("no identifier for declarator `%s`", t.toChars());
+ // A common mistake is to use a reserved keyword as an identifier, e.g. `in` or `out`
+ if (token.isKeyword)
+ {
+ errorSupplemental(token.loc, "`%s` is a keyword, perhaps append `_` to make it an identifier", token.toChars());
+ nextToken();
+ }
+ }
+
/********************************
* Parse AliasReassignment:
* identifier = type;
// parseAttributes shouldn't have set these variables
assert(link == linkage && !setAlignment && ealign is null);
auto tpl_ = cast(AST.TemplateDeclaration) s;
- if (tpl_ is null || tpl_.members.dim != 1)
+ if (tpl_ is null || tpl_.members.length != 1)
{
error("user-defined attributes are not allowed on `alias` declarations");
}
{
auto fd = cast(AST.FuncLiteralDeclaration) (*tpl_.members)[0];
auto tf = cast(AST.TypeFunction) fd.type;
- assert(tf.parameterList.parameters.dim > 0);
+ assert(tf.parameterList.parameters.length > 0);
auto as = new AST.Dsymbols();
(*tf.parameterList.parameters)[0].userAttribDecl = new AST.UserAttributeDeclaration(udas, as);
}
}
at = parseType(&ai);
if (!ai)
- error("no identifier for declarator `%s`", at.toChars());
+ noIdentifierForDeclarator(at);
Larg:
auto p = new AST.Parameter(storageClass, at, ai, null, null);
parameters.push(p);
nextToken();
AST.Expression aggr = parseExpression();
- if (token.value == TOK.slice && parameters.dim == 1)
+ if (token.value == TOK.slice && parameters.length == 1)
{
AST.Parameter p = (*parameters)[0];
nextToken();
Ldeclaration:
{
AST.Dsymbols* a = parseDeclarations(false, null, null);
- if (a.dim > 1)
+ if (a.length > 1)
{
auto as = new AST.Statements();
- as.reserve(a.dim);
- foreach (i; 0 .. a.dim)
+ as.reserve(a.length);
+ foreach (i; 0 .. a.length)
{
AST.Dsymbol d = (*a)[i];
s = new AST.ExpStatement(loc, d);
}
s = new AST.CompoundDeclarationStatement(loc, as);
}
- else if (a.dim == 1)
+ else if (a.length == 1)
{
AST.Dsymbol d = (*a)[0];
s = new AST.ExpStatement(loc, d);
*/
if (token.value == TOK.slice)
{
- if (cases.dim > 1)
+ if (cases.length > 1)
error("only one `case` allowed for start of case range");
nextToken();
check(TOK.case_);
else
{
// Keep cases in order by building the case statements backwards
- for (size_t i = cases.dim; i; i--)
+ for (size_t i = cases.length; i; i--)
{
exp = cases[i - 1];
s = new AST.CaseStatement(loc, exp, s);
case TOK.leftBracket:
/* Scan ahead to see if it is an array initializer or
* an expression.
- * If it ends with a ';' ',' or '}', it is an array initializer.
+ * If it ends with a ';' ',' or ']', it is an array initializer.
*/
int brackets = 1;
for (auto t = peek(&token); 1; t = peek(t))
t = AST.Type.tdchar;
goto LabelX;
LabelX:
+ const next = peekNext();
+ if (next != TOK.leftParenthesis && next != TOK.dot)
+ {
+ // defer error for better diagnostics
+ e = new AST.TypeExp(loc, parseType);
+ break;
+ }
nextToken();
if (token.value == TOK.leftParenthesis)
{
e = new AST.CallExp(loc, e, parseArguments());
break;
}
- check(TOK.dot, t.toChars());
+ check(TOK.dot);
if (token.value != TOK.identifier)
{
error("found `%s` when expecting identifier following `%s`.", token.toChars(), t.toChars());
while (token.value != TOK.rightBracket && token.value != TOK.endOfFile)
{
e = parseAssignExp();
- if (token.value == TOK.colon && (keys || values.dim == 0))
+ if (token.value == TOK.colon && (keys || values.length == 0))
{
nextToken();
if (!keys)
}
alias opDollar = length;
- alias dim = length;
+
+ deprecated("use `.length` instead")
+ extern(D) size_t dim() const @nogc nothrow pure @safe { return length; }
}
unittest
// Check whether character is a directory separator
-private bool isDirSeparator(char c) pure nothrow @nogc @safe
+bool isDirSeparator(char c) pure nothrow @nogc @safe
{
version (Windows)
{
}
/********************************************
+ * Checks whether an Unicode code point is a bidirectional
+ * control character.
+ */
+@safe bool isBidiControl(dchar c)
+{
+ // Source: https://www.unicode.org/versions/Unicode15.0.0, table 23-3.
+ switch(c)
+ {
+ case '\u061C':
+ case '\u200E':
+ case '\u200F':
+ case '\u202A': .. case '\u202E':
+ case '\u2066': .. case '\u2069':
+ return true;
+ default:
+ return false;
+ }
+}
+
+/********************************************
* Decode a UTF-8 sequence as a single UTF-32 code point.
* Params:
* s = UTF-8 sequence
override void visit(CompoundStatement s)
{
- for (size_t i = 0; i < s.statements.dim; i++)
+ for (size_t i = 0; i < s.statements.length; i++)
if (doCond((*s.statements)[i]))
return;
applyTo(s);
override void visit(UnrolledLoopStatement s)
{
- for (size_t i = 0; i < s.statements.dim; i++)
+ for (size_t i = 0; i < s.statements.length; i++)
if (doCond((*s.statements)[i]))
return;
applyTo(s);
{
if (doCond(s._body))
return;
- for (size_t i = 0; i < s.catches.dim; i++)
+ for (size_t i = 0; i < s.catches.length; i++)
if (doCond((*s.catches)[i].handler))
return;
applyTo(s);
#include "dsymbol.h"
-enum
+enum class CSX : uint16_t
{
- CSXthis_ctor = 1, // called this()
- CSXsuper_ctor = 2, // called super()
- CSXthis = 4, // referenced this
- CSXsuper = 8, // referenced super
- CSXlabel = 0x10, // seen a label
- CSXreturn = 0x20, // seen a return statement
- CSXany_ctor = 0x40, // either this() or super() was called
- CSXhalt = 0x80, // assert(0)
+ none = 0,
+ this_ctor = 1, // called this()
+ super_ctor = 2, // called super()
+ label = 4, // seen a label
+ return_ = 8, // seen a return statement
+ any_ctor = 0x10, // either this() or super() was called
+ halt = 0x20, // assert(0)
};
-enum
+enum class SCOPE
{
// Flags that would not be inherited beyond scope nesting
- SCOPEctor = 0x0001, // constructor type
- SCOPEcondition = 0x0004, // inside static if/assert condition
- SCOPEdebug = 0x0008, // inside debug conditional
+ ctor = 0x0001, // constructor type
+ noaccesscheck = 0x0002, // don't do access checks
+ condition = 0x0004, // inside static if/assert condition
+ debug_ = 0x0008, // inside debug conditional
// Flags that would be inherited beyond scope nesting
- SCOPEnoaccesscheck = 0x0002, // don't do access checks
- SCOPEconstraint = 0x0010, // inside template constraint
- SCOPEinvariant = 0x0020, // inside invariant code
- SCOPErequire = 0x0040, // inside in contract code
- SCOPEensure = 0x0060, // inside out contract code
- SCOPEcontract = 0x0060, // [mask] we're inside contract code
- SCOPEctfe = 0x0080, // inside a ctfe-only expression
- SCOPEcompile = 0x0100, // inside __traits(compile)
- SCOPEignoresymbolvisibility = 0x0200, // ignore symbol visibility (Bugzilla 15907)
-
- SCOPEfree = 0x8000, // is on free list
- SCOPEfullinst = 0x10000, // fully instantiate templates
- SCOPEalias = 0x20000, // inside alias declaration
-
- // The following are mutually exclusive
- SCOPEprintf = 0x40000, // printf-style function
- SCOPEscanf = 0x80000, // scanf-style function
+ constraint = 0x0010, // inside template constraint
+ invariant_ = 0x0020, // inside invariant code
+ require = 0x0040, // inside in contract code
+ ensure = 0x0060, // inside out contract code
+ contract = 0x0060, // [mask] we're inside contract code
+ ctfe = 0x0080, // inside a ctfe-only expression
+ compile = 0x0100, // inside __traits(compile)
+ ignoresymbolvisibility = 0x0200, // ignore symbol visibility (Bugzilla 15907)
+
+ Cfile = 0x0800, // C semantics apply
+ free = 0x8000, // is on free list
+ fullinst = 0x10000, // fully instantiate templates
};
struct Scope
Module *_module; // Root module
ScopeDsymbol *scopesym; // current symbol
FuncDeclaration *func; // function we are in
+ VarDeclaration *varDecl; // variable we are in during semantic2
Dsymbol *parent; // parent to use
LabelStatement *slabel; // enclosing labelled statement
SwitchStatement *sw; // enclosing switch statement
Module *minst; // root module where the instantiated templates should belong to
TemplateInstance *tinst; // enclosing template instance
- unsigned char callSuper; // primitive flow analysis for constructors
- unsigned char *fieldinit;
+ CSX callSuper; // primitive flow analysis for constructors
+ CSX *fieldinit;
size_t fieldinit_dim;
AlignDeclaration *aligndecl; // alignment for struct members
AliasDeclaration *aliasAsg; // if set, then aliasAsg is being assigned a new value,
// do not set wasRead for it
- Scope();
-
- Scope *copy();
-
- Scope *push();
- Scope *push(ScopeDsymbol *ss);
- Scope *pop();
-
- Scope *startCTFE();
- Scope *endCTFE();
Dsymbol *search(const Loc &loc, Identifier *ident, Dsymbol **pscopesym, int flags = IgnoreNone);
-
- ClassDeclaration *getClassScope();
- AggregateDeclaration *getStructClassScope();
-
- structalign_t alignment();
-
- bool isDeprecated() const;
- bool isFromSpeculativeSemanticContext() const;
};
if (needGagging)
oldGaggedErrors = global.startGagging();
- for (size_t i = 0; i < tempinst.members.dim; i++)
+ for (size_t i = 0; i < tempinst.members.length; i++)
{
Dsymbol s = (*tempinst.members)[i];
static if (LOG)
sc = sc.push(tmix);
sc.tinst = tmix;
sc.minst = tmix.minst;
- for (size_t i = 0; i < tmix.members.dim; i++)
+ for (size_t i = 0; i < tmix.members.length; i++)
{
Dsymbol s = (*tmix.members)[i];
static if (LOG)
return;
//printf("VarDeclaration::semantic2('%s')\n", toChars());
+ sc.varDecl = vd;
+ scope(exit) sc.varDecl = null;
if (vd.aliassym) // if it's a tuple
{
if (mod.members)
{
// Pass 2 semantic routines: do initializers and function bodies
- for (size_t i = 0; i < mod.members.dim; i++)
+ for (size_t i = 0; i < mod.members.length; i++)
{
Dsymbol s = (*mod.members)[i];
s.semantic2(sc);
return;
Scope* sc2 = ad.newScope(sc);
- for (size_t i = 0; i < d.dim; i++)
+ for (size_t i = 0; i < d.length; i++)
{
Dsymbol s = (*d)[i];
s.semantic2(sc2);
override void visit(UserAttributeDeclaration uad)
{
- if (!uad.decl || !uad.atts || !uad.atts.dim || !uad._scope)
+ if (!uad.decl || !uad.atts || !uad.atts.length || !uad._scope)
return visit(cast(AttribDeclaration)uad);
Expression* lastTag;
ad.determineSize(ad.loc);
- for (size_t i = 0; i < ad.members.dim; i++)
+ for (size_t i = 0; i < ad.members.length; i++)
{
Dsymbol s = (*ad.members)[i];
//printf("\t[%d] %s\n", i, s.toChars());
if (needGagging)
oldGaggedErrors = global.startGagging();
- for (size_t i = 0; i < tempinst.members.dim; i++)
+ for (size_t i = 0; i < tempinst.members.length; i++)
{
Dsymbol s = (*tempinst.members)[i];
s.semantic3(sc);
uint olderrors = global.errors;
- for (size_t i = 0; i < tmix.members.dim; i++)
+ for (size_t i = 0; i < tmix.members.length; i++)
{
Dsymbol s = (*tmix.members)[i];
s.semantic3(sc);
if (mod.members)
{
// Pass 3 semantic routines: do initializers and function bodies
- for (size_t i = 0; i < mod.members.dim; i++)
+ for (size_t i = 0; i < mod.members.length; i++)
{
Dsymbol s = (*mod.members)[i];
//printf("Module %s: %s.semantic3()\n", toChars(), s.toChars());
*/
if (ad2 && funcdecl.isCtorDeclaration())
{
- sc2.ctorflow.allocFieldinit(ad2.fields.dim);
+ sc2.ctorflow.allocFieldinit(ad2.fields.length);
foreach (v; ad2.fields)
{
v.ctorinit = 0;
if (funcdecl.returns && !funcdecl.fbody.isErrorStatement())
{
- for (size_t i = 0; i < funcdecl.returns.dim;)
+ for (size_t i = 0; i < funcdecl.returns.length;)
{
Expression exp = (*funcdecl.returns)[i].exp;
if (exp.op == EXP.variable && (cast(VarExp)exp).var == funcdecl.vresult)
* ctor consts were initialized.
*/
ScopeDsymbol pd = funcdecl.toParent().isScopeDsymbol();
- for (size_t i = 0; i < pd.members.dim; i++)
+ for (size_t i = 0; i < pd.members.length; i++)
{
Dsymbol s = (*pd.members)[i];
s.checkCtorConstInit();
/* Cannot move this loop into NrvoWalker, because
* returns[i] may be in the nested delegate for foreach-body.
*/
- for (size_t i = 0; i < funcdecl.returns.dim; i++)
+ for (size_t i = 0; i < funcdecl.returns.length; i++)
{
ReturnStatement rs = (*funcdecl.returns)[i];
Expression exp = rs.exp;
// Merge in initialization of 'out' parameters
if (funcdecl.parameters)
{
- for (size_t i = 0; i < funcdecl.parameters.dim; i++)
+ for (size_t i = 0; i < funcdecl.parameters.length; i++)
{
VarDeclaration v = (*funcdecl.parameters)[i];
if (v.storage_class & STC.out_)
// Fix up forward-referenced gotos
if (funcdecl.gotos && !funcdecl.isCsymbol())
{
- for (size_t i = 0; i < funcdecl.gotos.dim; ++i)
+ for (size_t i = 0; i < funcdecl.gotos.length; ++i)
{
(*funcdecl.gotos)[i].checkLabel();
}
return;
Scope* sc2 = ad.newScope(sc);
- for (size_t i = 0; i < d.dim; i++)
+ for (size_t i = 0; i < d.length; i++)
{
Dsymbol s = (*d)[i];
s.semantic3(sc2);
auto sc2 = ad.newScope(sc);
- for (size_t i = 0; i < ad.members.dim; i++)
+ for (size_t i = 0; i < ad.members.length; i++)
{
Dsymbol s = (*ad.members)[i];
s.semantic3(sc2);
{
if (funcdecl.frequires)
{
- for (size_t i = 0; i < funcdecl.foverrides.dim; i++)
+ for (size_t i = 0; i < funcdecl.foverrides.length; i++)
{
FuncDeclaration fdv = funcdecl.foverrides[i];
if (fdv.fbody && !fdv.frequires)
override final inout(Statement) last() inout nothrow pure
{
Statement s = null;
- for (size_t i = statements.dim; i; --i)
+ for (size_t i = statements.length; i; --i)
{
s = cast(Statement)(*statements)[i - 1];
if (s)
override CompoundDeclarationStatement syntaxCopy()
{
- auto a = new Statements(statements.dim);
+ auto a = new Statements(statements.length);
foreach (i, s; *statements)
{
(*a)[i] = s ? s.syntaxCopy() : null;
override UnrolledLoopStatement syntaxCopy()
{
- auto a = new Statements(statements.dim);
+ auto a = new Statements(statements.length);
foreach (i, s; *statements)
{
(*a)[i] = s ? s.syntaxCopy() : null;
override TryCatchStatement syntaxCopy()
{
- auto a = new Catches(catches.dim);
+ auto a = new Catches(catches.length);
foreach (i, c; *catches)
{
(*a)[i] = c.syntaxCopy();
override CompoundAsmStatement syntaxCopy()
{
- auto a = new Statements(statements.dim);
+ auto a = new Statements(statements.length);
foreach (i, s; *statements)
{
(*a)[i] = s ? s.syntaxCopy() : null;
override ImportStatement syntaxCopy()
{
- auto m = new Dsymbols(imports.dim);
+ auto m = new Dsymbols(imports.length);
foreach (i, s; *imports)
{
(*m)[i] = s.syntaxCopy(null);
override void visit(CompoundStatement s)
{
- if (s.statements && s.statements.dim)
+ if (s.statements && s.statements.length)
{
- for (size_t i = 0; i < s.statements.dim; i++)
+ for (size_t i = 0; i < s.statements.length; i++)
{
if ((*s.statements)[i])
visitStmt((*s.statements)[i]);
override void visit(UnrolledLoopStatement s)
{
- if (s.statements && s.statements.dim)
+ if (s.statements && s.statements.length)
{
- for (size_t i = 0; i < s.statements.dim; i++)
+ for (size_t i = 0; i < s.statements.length; i++)
{
if ((*s.statements)[i])
visitStmt((*s.statements)[i]);
{
if (s._body)
visitStmt(s._body);
- if (s.catches && s.catches.dim)
+ if (s.catches && s.catches.length)
{
- for (size_t i = 0; i < s.catches.dim; i++)
+ for (size_t i = 0; i < s.catches.length; i++)
{
Catch c = (*s.catches)[i];
if (c && c.handler)
}
}
- for (size_t i = 0; i < cs.statements.dim;)
+ for (size_t i = 0; i < cs.statements.length;)
{
Statement s = (*cs.statements)[i];
if (!s)
return true;
}
- if (!sfinally && isEmpty((*cs.statements)[i + 1 .. cs.statements.dim]))
+ if (!sfinally && isEmpty((*cs.statements)[i + 1 .. cs.statements.length]))
{
}
else
}
else if (sfinally)
{
- if (0 && i + 1 == cs.statements.dim)
+ if (0 && i + 1 == cs.statements.length)
{
cs.statements.push(sfinally);
}
CommaExp.allow(fs.increment);
fs.increment = fs.increment.expressionSemantic(sc);
fs.increment = resolveProperties(sc, fs.increment);
+ // @@@DEPRECATED_2.112@@@
+ // remove gagging and deprecation() to turn deprecation into an error when
+ // deprecation cycle is over
+ const olderrors = global.startGagging();
+ discardValue(fs.increment);
+ if (global.endGagging(olderrors))
+ fs.increment.deprecation("`%s` has no effect", fs.increment.toChars());
if (checkNonAssignmentArrayOp(fs.increment))
fs.increment = ErrorExp.get();
fs.increment = fs.increment.optimize(WANTvalue);
}
const loc = fs.loc;
- const dim = fs.parameters.dim;
+ const dim = fs.parameters.length;
fs.func = sc.func;
if (fs.func.fes)
}
}
- //printf("dim = %d, parameters.dim = %d\n", dim, parameters.dim);
+ //printf("dim = %d, parameters.length = %d\n", dim, parameters.length);
if (foundMismatch && dim != foreachParamCount)
{
const(char)* plural = foreachParamCount > 1 ? "s" : "";
result = s;
}
- TypeAArray taa = null;
Type tn = null;
Type tnv = null;
Statement apply()
TypeFunction tfld = null;
if (sapply)
{
- FuncDeclaration fdapply = sapply.isFuncDeclaration();
- if (fdapply)
+ if (auto fdapply = sapply.isFuncDeclaration())
{
- assert(fdapply.type && fdapply.type.ty == Tfunction);
- tfld = cast(TypeFunction)fdapply.type.typeSemantic(loc, sc2);
+ assert(fdapply.type && fdapply.type.isTypeFunction());
+ tfld = fdapply.type.typeSemantic(loc, sc2).isTypeFunction();
goto Lget;
}
- else if (tab.ty == Tdelegate)
+ else if (tab.isTypeDelegate())
{
- tfld = cast(TypeFunction)tab.nextOf();
+ tfld = tab.nextOf().isTypeFunction();
Lget:
//printf("tfld = %s\n", tfld.toChars());
- if (tfld.parameterList.parameters.dim == 1)
+ if (tfld.parameterList.parameters.length == 1)
{
Parameter p = tfld.parameterList[0];
- if (p.type && p.type.ty == Tdelegate)
+ if (p.type && p.type.isTypeDelegate())
{
auto t = p.type.typeSemantic(loc, sc2);
assert(t.ty == Tdelegate);
- tfld = cast(TypeFunction)t.nextOf();
+ tfld = t.nextOf().isTypeFunction();
}
}
}
{
// 'Promote' it to this scope, and replace with a return
fs.cases.push(gs);
- ss.statement = new ReturnStatement(Loc.initial, new IntegerExp(fs.cases.dim + 1));
+ ss.statement = new ReturnStatement(Loc.initial, new IntegerExp(fs.cases.length + 1));
}
}
Expression e = null;
- Expression ec;
if (vinit)
{
e = new DeclarationExp(loc, vinit);
return null;
}
- if (taa)
- ec = applyAssocArray(fs, flde, taa);
- else if (tab.ty == Tarray || tab.ty == Tsarray)
- ec = applyArray(fs, flde, sc2, tn, tnv, tab.ty);
- else if (tab.ty == Tdelegate)
- ec = applyDelegate(fs, flde, sc2, tab);
- else
- ec = applyOpApply(fs, tab, sapply, sc2, flde);
+ Expression ec;
+ switch (tab.ty)
+ {
+ case Tarray:
+ case Tsarray: ec = applyArray (fs, flde, tab, sc2, tn, tnv); break;
+ case Tdelegate: ec = applyDelegate (fs, flde, tab, sc2); break;
+ case Taarray: ec = applyAssocArray(fs, flde, tab); break;
+ default: ec = applyOpApply (fs, flde, tab, sc2, sapply); break;
+ }
if (!ec)
return null;
+
e = Expression.combine(e, ec);
return loopReturn(e, fs.cases, loc);
}
+
switch (tab.ty)
{
case Tarray:
* 2. foreach body is lowered to _aApply (see special case below).
*/
Type tv = (*fs.parameters)[1].type.toBasetype();
- if ((tab.ty == Tarray ||
+ if ((tab.isTypeDArray() ||
(tn.ty != tv.ty && tn.ty.isSomeChar && tv.ty.isSomeChar)) &&
!Type.tsize_t.implicitConvTo(tindex))
{
return retError();
}
}
- if (tab.ty == Tsarray)
+ if (auto ta = tab.isTypeSArray())
{
- TypeSArray ta = cast(TypeSArray)tab;
IntRange dimrange = getIntRange(ta.dim);
// https://issues.dlang.org/show_bug.cgi?id=12504
dimrange.imax = SignExtendedNumber(dimrange.imax.value-1);
auto ie = new ExpInitializer(loc, new SliceExp(loc, fs.aggr, null, null));
const valueIsRef = (*fs.parameters)[$ - 1].isReference();
VarDeclaration tmp;
- if (fs.aggr.op == EXP.arrayLiteral && !valueIsRef)
+ if (fs.aggr.isArrayLiteralExp() && !valueIsRef)
{
- auto ale = cast(ArrayLiteralExp)fs.aggr;
- size_t edim = ale.elements ? ale.elements.dim : 0;
+ auto ale = fs.aggr.isArrayLiteralExp();
+ size_t edim = ale.elements ? ale.elements.length : 0;
auto telem = (*fs.parameters)[dim - 1].type;
// https://issues.dlang.org/show_bug.cgi?id=12936
if (checkForArgTypes(fs))
return retError();
- taa = cast(TypeAArray)tab;
if (dim < 1 || dim > 2)
{
fs.error("only one or two arguments for associative array `foreach`");
* }
*/
auto ad = (tab.ty == Tclass) ?
- cast(AggregateDeclaration)(cast(TypeClass)tab).sym :
- cast(AggregateDeclaration)(cast(TypeStruct)tab).sym;
+ cast(AggregateDeclaration)tab.isTypeClass().sym :
+ cast(AggregateDeclaration)tab.isTypeStruct().sym;
Identifier idfront;
Identifier idpopFront;
if (fs.op == TOK.foreach_)
*/
VarDeclaration r;
Statement _init;
- if (vinit && fs.aggr.op == EXP.variable && (cast(VarExp)fs.aggr).var == vinit)
+ if (vinit && fs.aggr.isVarExp() && fs.aggr.isVarExp().var == vinit)
{
r = vinit;
_init = new ExpStatement(loc, vinit);
}
if (!tfront || tfront.ty == Terror)
return rangeError();
- if (tfront.toBasetype().ty == Tfunction)
+ if (auto ftt = tfront.toBasetype().isTypeFunction())
{
- auto ftt = cast(TypeFunction)tfront.toBasetype();
tfront = tfront.toBasetype().nextOf();
if (!ftt.isref)
{
auto exps = new Expressions();
exps.push(ve);
int pos = 0;
- while (exps.dim < dim)
+ while (exps.length < dim)
{
pos = expandAliasThisTuples(exps, pos);
if (pos == -1)
break;
}
- if (exps.dim != dim)
+ if (exps.length != dim)
{
- const(char)* plural = exps.dim > 1 ? "s" : "";
+ const(char)* plural = exps.length > 1 ? "s" : "";
fs.error("cannot infer argument types, expected %llu argument%s, not %llu",
- cast(ulong) exps.dim, plural, cast(ulong) dim);
+ cast(ulong) exps.length, plural, cast(ulong) dim);
return retError();
}
}
}
- private static extern(D) Expression applyOpApply(ForeachStatement fs, Type tab, Dsymbol sapply,
- Scope* sc2, Expression flde)
+ private static extern(D) Expression applyOpApply(ForeachStatement fs, Expression flde,
+ Type tab, Scope* sc2, Dsymbol sapply)
{
version (none)
{
}
private static extern(D) Expression applyDelegate(ForeachStatement fs, Expression flde,
- Scope* sc2, Type tab)
+ Type tab, Scope* sc2)
{
Expression ec;
/* Call:
}
private static extern(D) Expression applyArray(ForeachStatement fs, Expression flde,
- Scope* sc2, Type tn, Type tnv, TY tabty)
+ Type tab, Scope* sc2, Type tn, Type tnv)
{
Expression ec;
- const dim = fs.parameters.dim;
+ const dim = fs.parameters.length;
const loc = fs.loc;
/* Call:
* _aApply(aggr, flde)
params.push(new Parameter(0, dgty, null, null, null));
fdapply = FuncDeclaration.genCfunc(params, Type.tint32, fdname.ptr);
- if (tabty == Tsarray)
+ if (tab.isTypeSArray())
fs.aggr = fs.aggr.castTo(sc2, tn.arrayOf());
// paint delegate argument to the type runtime expects
Expression fexp = flde;
return ec;
}
- private static extern(D) Expression applyAssocArray(ForeachStatement fs, Expression flde, TypeAArray taa)
+ private static extern(D) Expression applyAssocArray(ForeachStatement fs, Expression flde, Type tab)
{
+ auto taa = tab.isTypeAArray();
Expression ec;
- const dim = fs.parameters.dim;
+ const dim = fs.parameters.length;
// Check types
Parameter p = (*fs.parameters)[0];
bool isRef = (p.storageClass & STC.ref_) != 0;
private static extern(D) Statement loopReturn(Expression e, Statements* cases, const ref Loc loc)
{
- if (!cases.dim)
+ if (!cases.length)
{
// Easy case, a clean exit from the loop
e = new CastExp(loc, e, Type.tvoid); // https://issues.dlang.org/show_bug.cgi?id=13899
}
else
{
- if (!ps.args || ps.args.dim != 1)
+ if (!ps.args || ps.args.length != 1)
{
ps.error("`string` expected for library name");
return setError();
size_t numcases = 0;
if (ss.cases)
- numcases = ss.cases.dim;
+ numcases = ss.cases.length;
for (size_t i = 0; i < numcases; i++)
{
sw.cases.push(cs);
// Resolve any goto case's with no exp to this case statement
- for (size_t i = 0; i < sw.gotoCases.dim;)
+ for (size_t i = 0; i < sw.gotoCases.length;)
{
GotoCaseStatement gcs = sw.gotoCases[i];
if (!gcs.exp)
{
assert(rs.caseDim == 0);
sc.fes.cases.push(rs);
- result = new ReturnStatement(Loc.initial, new IntegerExp(sc.fes.cases.dim + 1));
+ result = new ReturnStatement(Loc.initial, new IntegerExp(sc.fes.cases.length + 1));
return;
}
if (fd.returnLabel)
sc.fes.cases.push(s);
// Immediately rewrite "this" return statement as:
- // return cases.dim+1;
- rs.exp = new IntegerExp(sc.fes.cases.dim + 1);
+ // return cases.length+1;
+ rs.exp = new IntegerExp(sc.fes.cases.length + 1);
if (e0)
{
result = new CompoundStatement(rs.loc, new ExpStatement(rs.loc, e0), rs);
// return exp;
// to:
// vresult = exp; retrun caseDim;
- rs.caseDim = sc.fes.cases.dim + 1;
+ rs.caseDim = sc.fes.cases.length + 1;
}
}
if (rs.exp)
* and 1 is break.
*/
sc.fes.cases.push(bs);
- result = new ReturnStatement(Loc.initial, new IntegerExp(sc.fes.cases.dim + 1));
+ result = new ReturnStatement(Loc.initial, new IntegerExp(sc.fes.cases.length + 1));
return;
}
break; // can't break to it
* and 1 is break.
*/
sc.fes.cases.push(cs);
- result = new ReturnStatement(Loc.initial, new IntegerExp(sc.fes.cases.dim + 1));
+ result = new ReturnStatement(Loc.initial, new IntegerExp(sc.fes.cases.length + 1));
return;
}
break; // can't continue to it
*/
if (!(tcs._body.blockExit(sc.func, false) & BE.throw_) && ClassDeclaration.exception)
{
- foreach_reverse (i; 0 .. tcs.catches.dim)
+ foreach_reverse (i; 0 .. tcs.catches.length)
{
Catch c = (*tcs.catches)[i];
}
}
- if (tcs.catches.dim == 0)
+ if (tcs.catches.length == 0)
{
result = tcs._body.hasCode() ? tcs._body : null;
return;
/* https://dlang.org/spec/module.html#ImportDeclaration
*/
- foreach (i; 0 .. imps.imports.dim)
+ foreach (i; 0 .. imps.imports.length)
{
Import s = (*imps.imports)[i].isImport();
- assert(!s.aliasdecls.dim);
+ assert(!s.aliasdecls.length);
foreach (j, name; s.names)
{
Identifier _alias = s.aliases[j];
}
auto loc = fs.loc;
- size_t dim = fs.parameters.dim;
+ size_t dim = fs.parameters.length;
const bool skipCheck = isStatic && needExpansion;
if (!skipCheck && (dim < 1 || dim > 2))
{
if (fs.aggr.op == EXP.tuple) // expression tuple
{
te = cast(TupleExp)fs.aggr;
- n = te.exps.dim;
+ n = te.exps.length;
}
else if (fs.aggr.op == EXP.type) // type tuple
{
{
return a;
}
- auto b = new Statements(a.dim);
+ auto b = new Statements(a.length);
foreach (i, s; *a)
{
(*b)[i] = s ? new ForwardingStatement(s.loc, fs.sym, s) : null;
if (!a)
return null;
- if (!a.dim)
+ if (!a.length)
{
a.push(new ExpStatement(ls.loc, cast(Expression)null));
}
*/
bool pragmaStartAddressSemantic(Loc loc, Scope* sc, Expressions* args)
{
- if (!args || args.dim != 1)
+ if (!args || args.length != 1)
{
.error(loc, "function name expected for start address");
return false;
*/
private Expression pointerBitmap(TraitsExp e)
{
- if (!e.args || e.args.dim != 1)
+ if (!e.args || e.args.length != 1)
{
error(e.loc, "a single type expected for trait pointerBitmap");
return ErrorExp.get();
if (sz == ulong.max)
return ErrorExp.get();
- auto exps = new Expressions(data.dim + 1);
+ auto exps = new Expressions(data.length + 1);
(*exps)[0] = new IntegerExp(e.loc, sz, Type.tsize_t);
- foreach (size_t i; 1 .. exps.dim)
+ foreach (size_t i; 1 .. exps.length)
(*exps)[i] = new IntegerExp(e.loc, data[cast(size_t) (i - 1)], Type.tsize_t);
- auto ale = new ArrayLiteralExp(e.loc, Type.tsize_t.sarrayOf(data.dim + 1), exps);
+ auto ale = new ArrayLiteralExp(e.loc, Type.tsize_t.sarrayOf(data.length + 1), exps);
return ale;
}
}
sc.stc = save;
}
- size_t dim = e.args ? e.args.dim : 0;
+ size_t dim = e.args ? e.args.length : 0;
Expression dimError(int expected)
{
}
else if (s)
{
+ // @@@DEPRECATION 2.100.2
+ if (auto fd = s.isFuncDeclaration())
+ {
+ if (fd.overnext)
+ {
+ deprecation(e.loc, "`__traits(getAttributes)` may only be used for individual functions, not overload sets such as: `%s`", fd.toChars());
+ deprecationSupplemental(e.loc, "the result of `__traits(getOverloads)` may be used to select the desired function to extract attributes from");
+ }
+ }
+
+ // @@@DEPRECATION 2.100.2
+ if (auto td = s.isTemplateDeclaration())
+ {
+ if (td.overnext || td.funcroot)
+ {
+ deprecation(e.loc, "`__traits(getAttributes)` may only be used for individual functions, not overload sets such as: `%s`", td.ident.toChars());
+ deprecationSupplemental(e.loc, "the result of `__traits(getOverloads)` may be used to select the desired function to extract attributes from");
+ }
+ }
if (s.isImport())
{
s = s.isImport().mod;
void pushBaseMembersDg(ClassDeclaration cd)
{
- for (size_t i = 0; i < cd.baseclasses.dim; i++)
+ for (size_t i = 0; i < cd.baseclasses.length; i++)
{
auto cb = (*cd.baseclasses)[i].sym;
assert(cb);
ScopeDsymbol._foreach(null, cb.members, &pushIdentsDg);
- if (cb.baseclasses.dim)
+ if (cb.baseclasses.length)
pushBaseMembersDg(cb);
}
}
return ErrorExp.get();
if (!TemplateInstance.semanticTiargs(e.loc, sc, &ob2, 0))
return ErrorExp.get();
- if (ob1.dim != ob2.dim)
+ if (ob1.length != ob2.length)
return False();
- foreach (immutable i; 0 .. ob1.dim)
+ foreach (immutable i; 0 .. ob1.length)
if (!ob1[i].isSame(ob2[i], sc))
return False();
return True();
return ErrorExp.get();
}
- Type tb = t.baseElemOf();
+ // https://issues.dlang.org/show_bug.cgi?id=23534
+ //
+ // For enums, we need to get the enum initializer
+ // (the first enum member), not the initializer of the
+ // type of the enum members.
+ Type tb = t.isTypeEnum ? t : t.baseElemOf();
return tb.isZeroInit(e.loc) ? True() : False();
}
if (e.ident == Id.getTargetInfo)
if (prependNamespaces(outer, pp.cppnamespace)) return ErrorExp.get();
size_t i = 0;
- while(i < outer.dim && ((*inner)[i]) == (*outer)[i])
+ while(i < outer.length && ((*inner)[i]) == (*outer)[i])
i++;
foreach_reverse (ns; (*inner)[][i .. $])
{
if (auto td = t.isTemplateDeclaration())
{
- if (td.members && td.members.dim == 1)
+ if (td.members && td.members.length == 1)
{
if (auto fd = (*td.members)[0].isFuncLiteralDeclaration())
return fd;
if (!overSet2)
return false;
- if (overSet1.a.dim != overSet2.a.dim)
+ if (overSet1.a.length != overSet2.a.length)
return false;
// OverloadSets contain array of Dsymbols => O(n*n)
void visitBaseClasses(AST.ClassDeclaration d)
{
//printf("Visiting ClassDeclaration\n");
- if (!d || !d.baseclasses.dim)
+ if (!d || !d.baseclasses.length)
return;
foreach (b; *d.baseclasses)
visitType(b.type);
bool visitEponymousMember(AST.TemplateDeclaration d)
{
//printf("Visiting EponymousMember\n");
- if (!d.members || d.members.dim != 1)
+ if (!d.members || d.members.length != 1)
return false;
AST.Dsymbol onemember = (*d.members)[0];
if (onemember.ident != d.ident)
void visitTemplateParameters(AST.TemplateParameters* parameters)
{
- if (!parameters || !parameters.dim)
+ if (!parameters || !parameters.length)
return;
foreach (p; *parameters)
p.accept(this);
visitType(e.targ);
if (e.tspec)
visitType(e.tspec);
- if (e.parameters && e.parameters.dim)
+ if (e.parameters && e.parameters.length)
visitTemplateParameters(e.parameters);
}
return;
}
const(uinteger_t) d = eindex.toUInteger();
- if (d >= tup.objects.dim)
+ if (d >= tup.objects.length)
{
- .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong)tup.objects.dim);
+ .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong)tup.objects.length);
pt = Type.terror;
return;
}
}
s = s.toAlias();
//printf("\t2: s = '%s' %p, kind = '%s'\n",s.toChars(), s, s.kind());
- for (size_t i = 0; i < mt.idents.dim; i++)
+ for (size_t i = 0; i < mt.idents.length; i++)
{
RootObject id = mt.idents[i];
switch (id.dyncast()) with (DYNCAST)
return error();
uinteger_t d = mtype.dim.toUInteger();
- if (d >= tup.objects.dim)
+ if (d >= tup.objects.length)
{
- .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tup.objects.dim);
+ .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tup.objects.length);
return error();
}
assert(mtype.dim);
TypeTuple tt = tbn.isTypeTuple();
uinteger_t d = mtype.dim.toUInteger();
- if (d >= tt.arguments.dim)
+ if (d >= tt.arguments.length)
{
- .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tt.arguments.dim);
+ .error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", cast(ulong)d, cast(ulong)tt.arguments.length);
return error();
}
Type telem = (*tt.arguments)[cast(size_t)d].type;
fhash = search_function(ClassDeclaration.object, Id.tohash).isFuncDeclaration();
assert(fcmp && feq && fhash);
- if (feq.vtblIndex < cd.vtbl.dim && cd.vtbl[feq.vtblIndex] == feq)
+ if (feq.vtblIndex < cd.vtbl.length && cd.vtbl[feq.vtblIndex] == feq)
{
version (all)
{
- if (fcmp.vtblIndex < cd.vtbl.dim && cd.vtbl[fcmp.vtblIndex] != fcmp)
+ if (fcmp.vtblIndex < cd.vtbl.length && cd.vtbl[fcmp.vtblIndex] != fcmp)
{
const(char)* s = (mtype.index.toBasetype().ty != Tclass) ? "bottom of " : "";
.error(loc, "%sAA key type `%s` now requires equality rather than comparison", s, cd.toChars());
if (mtype.parameterList.parameters)
{
tf.parameterList.parameters = mtype.parameterList.parameters.copy();
- for (size_t i = 0; i < mtype.parameterList.parameters.dim; i++)
+ for (size_t i = 0; i < mtype.parameterList.parameters.length; i++)
{
Parameter p = cast(Parameter)mem.xmalloc(__traits(classInstanceSize, Parameter));
memcpy(cast(void*)p, cast(void*)(*mtype.parameterList.parameters)[i], __traits(classInstanceSize, Parameter));
* the elements of TypeTuple::arguments to avoid unintended
* sharing of Parameter object among other functions.
*/
- if (tt.arguments && tt.arguments.dim)
+ if (tt.arguments && tt.arguments.length)
{
/* Propagate additional storage class from tuple parameters to their
* element-parameters.
* Make a copy, as original may be referenced elsewhere.
*/
- size_t tdim = tt.arguments.dim;
+ size_t tdim = tt.arguments.length;
auto newparams = new Parameters(tdim);
for (size_t j = 0; j < tdim; j++)
{
*/
if (eparam.storageClass & STC.auto_)
{
- Expression farg = mtype.fargs && eidx < mtype.fargs.dim ?
+ Expression farg = mtype.fargs && eidx < mtype.fargs.length ?
(*mtype.fargs)[eidx] : eparam.defaultArg;
if (farg && (eparam.storageClass & STC.ref_))
{
uinteger_t i1 = mtype.lwr.toUInteger();
uinteger_t i2 = mtype.upr.toUInteger();
- if (!(i1 <= i2 && i2 <= tt.arguments.dim))
+ if (!(i1 <= i2 && i2 <= tt.arguments.length))
{
.error(loc, "slice `[%llu..%llu]` is out of range of `[0..%llu]`",
- cast(ulong)i1, cast(ulong)i2, cast(ulong)tt.arguments.dim);
+ cast(ulong)i1, cast(ulong)i2, cast(ulong)tt.arguments.length);
return error();
}
}
if (ident == Id.length)
{
- e = new IntegerExp(loc, mt.arguments.dim, Type.tsize_t);
+ e = new IntegerExp(loc, mt.arguments.length, Type.tsize_t);
}
else if (ident == Id._init)
{
return returnError();
const d = mt.dim.toUInteger();
- if (d >= tup.objects.dim)
+ if (d >= tup.objects.length)
{
- error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong) tup.objects.dim);
+ error(loc, "tuple index `%llu` out of bounds `[0 .. %llu]`", d, cast(ulong) tup.objects.length);
return returnError();
}
error(loc, "forward reference to `%s`", mt.toChars());
goto Lerr;
}
- if (mt.idents.dim == 0)
+ if (mt.idents.length == 0)
{
returnType(t.addMod(mt.mod));
}
return returnError();
}
}
- if (mt.idents.dim == 0)
+ if (mt.idents.length == 0)
{
return returnType(t.addMod(mt.mod));
}
mt.upr = mt.upr.ctfeInterpret();
const i1 = mt.lwr.toUInteger();
const i2 = mt.upr.toUInteger();
- if (!(i1 <= i2 && i2 <= td.objects.dim))
+ if (!(i1 <= i2 && i2 <= td.objects.length))
{
- error(loc, "slice `[%llu..%llu]` is out of range of [0..%llu]", i1, i2, cast(ulong) td.objects.dim);
+ error(loc, "slice `[%llu..%llu]` is out of range of [0..%llu]", i1, i2, cast(ulong) td.objects.length);
return returnError();
}
- if (i1 == 0 && i2 == td.objects.dim)
+ if (i1 == 0 && i2 == td.objects.length)
{
return returnSymbol(td);
}
* is a slice [i1..i2] out of the old one.
*/
auto objects = new Objects(cast(size_t)(i2 - i1));
- for (size_t i = 0; i < objects.dim; i++)
+ for (size_t i = 0; i < objects.length; i++)
{
(*objects)[i] = (*td.objects)[cast(size_t)i1 + i];
}
break;
case EXP.tuple:
TupleExp te = e.isTupleExp();
- Objects* elems = new Objects(te.exps.dim);
- foreach (i; 0 .. elems.dim)
+ Objects* elems = new Objects(te.exps.length);
+ foreach (i; 0 .. elems.length)
{
auto src = (*te.exps)[i];
switch (src.op)
ev = extractSideEffect(sc, "__tup", e0, ev);
auto exps = new Expressions();
- exps.reserve(mt.sym.fields.dim);
- for (size_t i = 0; i < mt.sym.fields.dim; i++)
+ exps.reserve(mt.sym.fields.length);
+ for (size_t i = 0; i < mt.sym.fields.length; i++)
{
VarDeclaration v = mt.sym.fields[i];
Expression ex;
ev = extractSideEffect(sc, "__tup", e0, ev);
auto exps = new Expressions();
- exps.reserve(mt.sym.fields.dim);
- for (size_t i = 0; i < mt.sym.fields.dim; i++)
+ exps.reserve(mt.sym.fields.length);
+ for (size_t i = 0; i < mt.sym.fields.length; i++)
{
VarDeclaration v = mt.sym.fields[i];
// Don't include hidden 'this' pointer
{
printf("TypeTuple::defaultInit() '%s'\n", mt.toChars());
}
- auto exps = new Expressions(mt.arguments.dim);
- for (size_t i = 0; i < mt.arguments.dim; i++)
+ auto exps = new Expressions(mt.arguments.length);
+ for (size_t i = 0; i < mt.arguments.length; i++)
{
Parameter p = (*mt.arguments)[i];
assert(p.type);
Expression typeToExpressionHelper(TypeQualified t, Expression e, size_t i = 0)
{
//printf("toExpressionHelper(e = %s %s)\n", EXPtoString(e.op).ptr, e.toChars());
- foreach (id; t.idents[i .. t.idents.dim])
+ foreach (id; t.idents[i .. t.idents.length])
{
//printf("\t[%d] e: '%s', id: '%s'\n", i, e.toChars(), id.toChars());
if (ps)
{
// Replace params with a copy we can modify
- Parameters* nparams = new Parameters(parameters.dim);
+ Parameters* nparams = new Parameters(parameters.length);
foreach (j, ref np; *nparams)
{
}
bool first = true;
- for (size_t i = 0; i < ed.members.dim; i++)
+ for (size_t i = 0; i < ed.members.length; i++)
{
EnumMember em = (*ed.members)[i].isEnumMember();
if (!em)
: null_pointer_node;
this->layout_field (xhash);
- if (sd->xhash)
- {
- TypeFunction *tf = sd->xhash->type->toTypeFunction ();
- if (!tf->isnothrow () || tf->trust == TRUST::system)
- {
- warning (sd->xhash->loc, "toHash() must be declared as "
- "extern (D) size_t toHash() const nothrow @safe, "
- "not %s", tf->toChars ());
- }
- }
-
/* bool function(in void*, in void*) xopEquals; */
tree xeq = (sd->xeq) ? build_address (get_symbol_decl (sd->xeq))
: null_pointer_node;
{
/* Even when compiling without RTTI we should still be able to evaluate
TypeInfo at compile-time, just not at run-time. */
- if (!sc || !(sc->flags & SCOPEctfe))
+ if (!sc || !(sc->flags & unsigned(SCOPE::ctfe)))
{
static int warned = 0;
static assert(!__traits(compiles, delete p));
int[int] aa;
- static assert(!__traits(compiles, aa[0]));
+ static assert( __traits(compiles, aa[0]));
+ static assert(!__traits(compiles, (aa[0] = 10)));
int[] a;
static assert(!__traits(compiles, a.length = 1));
--- /dev/null
+// REQUIRED_ARGS: -unittest
+
+// https://issues.dlang.org/show_bug.cgi?id=15712
+// extern(C) attribute inside extern(C) unittest is incorrectly ignored
+
+extern(C):
+
+unittest
+{
+ extern(C) static void foo() {}
+ static assert(__traits(getLinkage, foo) == "C");
+}
--- /dev/null
+// https://issues.dlang.org/show_bug.cgi?id=23431
+// REQUIRED_ARGS: -lowmem
+void test23431()
+{
+ int a;
+ try
+ {
+ throw new Exception("test1");
+ a++;
+ }
+ finally
+ {
+ }
+}
--- /dev/null
+// https://issues.dlang.org/show_bug.cgi?id=23431
+// REQUIRED_ARGS: -lowmem
+module object;
+
+alias string = immutable(char)[];
+class Throwable { }
+class Exception : Throwable
+{
+ this(string )
+ {
+ }
+}
+
+class Error { }
+
+void test23431()
+{
+ int a;
+
+ try
+ {
+ throw new Exception("test1");
+ a++;
+ }
+ finally
+ {
+ }
+}
--- /dev/null
+// https://issues.dlang.org/show_bug.cgi?id=23433
+module object;
+
+class Throwable { }
+class Exception : Throwable { this(immutable(char)[]) { } }
+
+void test23433()
+{
+ try
+ {
+ throw new Exception("ice");
+ }
+ finally
+ {
+ }
+}
--- /dev/null
+// https://issues.dlang.org/show_bug.cgi?id=23439
+// PERMUTE_ARGS: -lowmem
+class C23439
+{
+ noreturn f23439;
+}
+
+__gshared ice23439 = new C23439();
--- /dev/null
+// https://issues.dlang.org/show_bug.cgi?id=23534
+
+enum E { a = 1, b = 2 }
+
+// `E.a` is not 0
+static assert(!__traits(isZeroInit, E));
assert(78);
else
assert(79);
- false; false
+ false;
)
if (true)
assert(80);
/*
TEST_OUTPUT:
---
-compilable/vgc2.d(102): vgc: indexing an associative array may cause a GC allocation
-compilable/vgc2.d(103): vgc: indexing an associative array may cause a GC allocation
+compilable/vgc2.d(101): vgc: assigning an associative array element may cause a GC allocation
---
*/
void testIndex(int[int] aa)
/*
TEST_OUTPUT:
---
-fail_compilation/diag14818.d(34): Error: none of the overloads of `func` are callable using argument types `(string)`
-fail_compilation/diag14818.d(12): Candidate is: `diag14818.foo(int _param_0)`
-fail_compilation/diag14818.d(13): `diag14818.bar(double _param_0)`
-fail_compilation/diag14818.d(35): Error: overload alias `diag14818.X` does not match any template declaration
-fail_compilation/diag14818.d(36): Error: overloadset `diag14818.M` does not match any template declaration
+fail_compilation/diag14818.d(40): Error: none of the overloads of `func` are callable using argument types `(string)`
+fail_compilation/diag14818.d(18): Candidates are: `diag14818.foo(int _param_0)`
+fail_compilation/diag14818.d(19): `diag14818.bar(double _param_0)`
+fail_compilation/diag14818.d(41): Error: template instance `diag14818.X!string` does not match any template declaration
+fail_compilation/diag14818.d(41): Candidates are:
+fail_compilation/diag14818.d(24): Foo(T) if (is(T == int))
+fail_compilation/diag14818.d(25): Bar(T) if (is(T == double))
+fail_compilation/diag14818.d(42): Error: template instance `diag14818.Y!string` does not match any template declaration
+fail_compilation/diag14818.d(42): Candidates are:
+fail_compilation/diag14818.d(25): Bar(T) if (is(T == double))
+fail_compilation/diag14818.d(24): Foo(T) if (is(T == int))
---
*/
TEST_OUTPUT:
---
fail_compilation/diag8101.d(57): Error: function `diag8101.f_0(int)` is not callable using argument types `()`
-fail_compilation/diag8101.d(57): too few arguments, expected `1`, got `0`
+fail_compilation/diag8101.d(57): too few arguments, expected 1, got 0
fail_compilation/diag8101.d(58): Error: none of the overloads of `f_1` are callable using argument types `()`
fail_compilation/diag8101.d(33): Candidates are: `diag8101.f_1(int)`
fail_compilation/diag8101.d(34): `diag8101.f_1(int, int)`
t_1();
t_2();
}
+
+// ignored
+deprecated void f_2(char);
TEST_OUTPUT:
---
fail_compilation/diag_funclit.d(103): Error: function literal `__lambda1(x, y, z)` is not callable using argument types `()`
-fail_compilation/diag_funclit.d(103): too few arguments, expected `3`, got `0`
+fail_compilation/diag_funclit.d(103): too few arguments, expected 3, got 0
fail_compilation/diag_funclit.d(106): Error: function literal `__lambda2(x, y, z)` is not callable using argument types `(int, string, int, int)`
-fail_compilation/diag_funclit.d(106): too many arguments, expected `3`, got `4`
+fail_compilation/diag_funclit.d(106): too many arguments, expected 3, got 4
fail_compilation/diag_funclit.d(108): Error: function literal `__lambda3(x, y, string z = "Hello")` is not callable using argument types `(int, int, string, string)`
-fail_compilation/diag_funclit.d(108): too many arguments, expected `3`, got `4`
+fail_compilation/diag_funclit.d(108): too many arguments, expected 3, got 4
fail_compilation/diag_funclit.d(110): Error: function literal `__lambda4(x, y, string z = "Hello")` is not callable using argument types `(int)`
-fail_compilation/diag_funclit.d(110): too few arguments, expected `3`, got `1`
+fail_compilation/diag_funclit.d(110): too few arguments, expected 3, got 1
fail_compilation/diag_funclit.d(112): Error: function literal `__lambda5(x, y, z)` is not callable using argument types `(int)`
-fail_compilation/diag_funclit.d(112): too few arguments, expected `3`, got `1`
+fail_compilation/diag_funclit.d(112): too few arguments, expected 3, got 1
fail_compilation/diag_funclit.d(115): Error: function literal `__lambda6(x, y, ...)` is not callable using argument types `(int)`
-fail_compilation/diag_funclit.d(115): too few arguments, expected `2`, got `1`
+fail_compilation/diag_funclit.d(115): too few arguments, expected 2, got 1
fail_compilation/diag_funclit.d(117): Error: function literal `__lambda7(x, y, string z = "Hey", ...)` is not callable using argument types `(int)`
-fail_compilation/diag_funclit.d(117): too few arguments, expected `3`, got `1`
+fail_compilation/diag_funclit.d(117): too few arguments, expected 3, got 1
---
*/
TEST_OUTPUT:
---
fail_compilation/diagin.d(14): Error: function `diagin.foo(in int)` is not callable using argument types `()`
-fail_compilation/diagin.d(14): too few arguments, expected `1`, got `0`
+fail_compilation/diagin.d(14): too few arguments, expected 1, got 0
fail_compilation/diagin.d(16): Error: none of the overloads of template `diagin.foo1` are callable using argument types `!()(bool[])`
fail_compilation/diagin.d(20): Candidate is: `foo1(T)(in T v, string)`
---
/*
TEST_OUTPUT:
---
-fail_compilation/fail12.d(17): Error: function `fail12.main.Foo!(y).abc` at fail_compilation/fail12.d(9) conflicts with function `fail12.main.Foo!(y).abc` at fail_compilation/fail12.d(9)
+fail_compilation/fail12.d(19): Error: `abc` matches conflicting symbols:
+fail_compilation/fail12.d(11): function `fail12.main.Foo!(y).abc`
+fail_compilation/fail12.d(11): function `fail12.main.Foo!(y).abc`
---
*/
template Foo(alias b)
--- /dev/null
+// https://issues.dlang.org/show_bug.cgi?id=15414
+
+// REQUIRED_ARGS: -de
+
+/*
+TEST_OUTPUT:
+---
+fail_compilation/fail15414.d(20): Deprecation: `__traits(getAttributes)` may only be used for individual functions, not overload sets such as: `fun`
+fail_compilation/fail15414.d(20): the result of `__traits(getOverloads)` may be used to select the desired function to extract attributes from
+---
+*/
+
+@("gigi")
+void fun() {}
+@("mimi")
+void fun(int) {}
+
+void main()
+{
+ auto t = __traits(getAttributes, fun);
+}
`~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
` > is(T == char)
` `~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~`
-fail_compilation/fail15616b.d(44): All possible candidates are marked as `deprecated` or `@disable`
Tip: not satisfied constraints are marked with `>`
---
*/
/*
TEST_OUTPUT:
---
-fail_compilation/fail1900.d(42): Error: template `imports.fail1900b.Bar(short n)` at fail_compilation/imports/fail1900b.d(2) conflicts with template `imports.fail1900a.Bar(int n)` at fail_compilation/imports/fail1900a.d(2)
+fail_compilation/fail1900.d(44): Error: `Bar` matches conflicting symbols:
+fail_compilation/imports/fail1900b.d(2): template `imports.fail1900b.Bar(short n)`
+fail_compilation/imports/fail1900a.d(2): template `imports.fail1900a.Bar(int n)`
---
*/
/*
TEST_OUTPUT:
---
-fail_compilation/fail1900.d(66): Error: template `fail1900.Mix2b!().Baz(int x)` at fail_compilation/fail1900.d(58) conflicts with template `fail1900.Mix2a!().Baz(byte x)` at fail_compilation/fail1900.d(54)
+fail_compilation/fail1900.d(70): Error: `Baz` matches conflicting symbols:
+fail_compilation/fail1900.d(62): template `fail1900.Mix2b!().Baz(int x)`
+fail_compilation/fail1900.d(58): template `fail1900.Mix2a!().Baz(byte x)`
---
*/
-// REQUIRED_ARGS: -dip1000
-
/*
+REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
-fail_compilation/fail22366.d(13): Error: scope variable `x` may not be copied into allocated memory
+fail_compilation/fail22366.d(22): Error: scope variable `s` may not be copied into allocated memory
+fail_compilation/fail22366.d(25): Error: scope variable `s` may not be copied into allocated memory
+fail_compilation/fail22366.d(26): Error: scope variable `s` may not be copied into allocated memory
+fail_compilation/fail22366.d(27): Error: scope variable `s` may not be copied into allocated memory
+fail_compilation/fail22366.d(28): Error: scope variable `s` may not be copied into allocated memory
+fail_compilation/fail22366.d(31): Error: scope variable `s` may not be copied into allocated memory
+fail_compilation/fail22366.d(32): Error: scope variable `s` may not be copied into allocated memory
---
*/
-int* fun(scope int* x) @safe
+// Test escaping scope variables through AA keys / values
+// https://issues.dlang.org/show_bug.cgi?id=22366
+// https://issues.dlang.org/show_bug.cgi?id=23531
+
+void fun(scope string s) @safe
{
- int*[int] aa;
- aa[0] = x; // should give an error
- return aa[0];
+ int[string] aa;
+ aa[s] ^^= 3;
+
+ string[string] saa;
+ saa[""] = s;
+ saa[""] ~= s;
+ saa[s] = "";
+ saa[s] ~= "";
+
+ string[string][string] snaa;
+ snaa[s][""] = "";
+ snaa[""][s] = "";
}
--- /dev/null
+// https://issues.dlang.org/show_bug.cgi?id=23439
+// PERMUTE_ARGS: -lowmem
+/* TEST_OUTPUT:
+---
+fail_compilation/fail23439.d(13): Error: variable `fail23439.ice23439` is a thread-local class and cannot have a static initializer. Use `static this()` to initialize instead.
+---
+*/
+class C23439
+{
+ noreturn f23439;
+}
+
+static ice23439 = new C23439();
EXTRA_FILES: imports/fail320a.d imports/fail320b.d
TEST_OUTPUT:
---
-fail_compilation/fail320.d(11): Error: no overload matches for `foo`
+fail_compilation/fail320.d(16): Error: no overload matches for `foo("")`
+fail_compilation/fail320.d(16): Candidates are:
+fail_compilation/imports/fail320b.d(1): foo(T)(string)
+fail_compilation/imports/fail320b.d(2): foo(alias a)()
+fail_compilation/imports/fail320a.d(1): foo(int)
+fail_compilation/imports/fail320a.d(2): foo(bool)
---
*/
import imports.fail320a;
import imports.fail320b;
-void main() { foo(); }
+void main() { foo(""); }
/*
TEST_OUTPUT:
---
-fail_compilation/fail54.d(22): Error: incompatible types for `(0) == (Exception)`: cannot use `==` with types
+fail_compilation/fail54.d(27): Error: incompatible types for `(0) == (Exception)`: cannot use `==` with types
+fail_compilation/fail54.d(28): Error: incompatible types for `("") == (int)`: cannot use `==` with types
+fail_compilation/fail54.d(29): Error: incompatible types for `(true) == (int)`: cannot use `==` with types
+fail_compilation/fail54.d(29): while evaluating: `static assert(true == (int))`
+fail_compilation/fail54.d(30): Error: incompatible types for `(true) == (int[string])`: cannot use `==` with types
+fail_compilation/fail54.d(30): while evaluating: `static assert(true == (int[string]))`
---
*/
void test()
{
0 == Exception;
+ "" == int;
+ static assert(is(int) == int);
+ static assert(is(int[string]) == int[string]);
}
TEST_OUTPUT:
---
fail_compilation/fail99.d(13): Error: delegate `dg(int)` is not callable using argument types `()`
-fail_compilation/fail99.d(13): too few arguments, expected `1`, got `0`
+fail_compilation/fail99.d(13): too few arguments, expected 1, got 0
---
*/
fail_compilation/fail_arrayop2.d(345): Error: array operation `[1] * 6` without destination memory not allowed
fail_compilation/fail_arrayop2.d(348): Error: array operation `[1] * 6` without destination memory not allowed
fail_compilation/fail_arrayop2.d(349): Error: array operation `[1] * 6` without destination memory not allowed
+fail_compilation/fail_arrayop2.d(350): Deprecation: `[1] * 6` has no effect
fail_compilation/fail_arrayop2.d(350): Error: array operation `[1] * 6` without destination memory not allowed
fail_compilation/fail_arrayop2.d(353): Error: array operation `[1] * 6` without destination memory not allowed
fail_compilation/fail_arrayop2.d(356): Error: array operation `[1] * 6` without destination memory not allowed
---
*/
// Test all statements, which can take arrays as their operands.
-void test15407stmt()
-{
+void test15407stmt() {
// ExpStatement - exp
[1] * 6;
REQUIRED_ARGS: -verrors=context
TEST_OUTPUT:
---
-fail_compilation/fail_pretty_errors.d(20): Error: undefined identifier `a`
+fail_compilation/fail_pretty_errors.d(24): Error: undefined identifier `a`
a = 1;
^
-fail_compilation/fail_pretty_errors.d-mixin-25(25): Error: undefined identifier `b`
-fail_compilation/fail_pretty_errors.d(30): Error: cannot implicitly convert expression `5` of type `int` to `string`
+fail_compilation/fail_pretty_errors.d-mixin-29(29): Error: undefined identifier `b`
+fail_compilation/fail_pretty_errors.d(34): Error: cannot implicitly convert expression `5` of type `int` to `string`
string x = 5;
^
-fail_compilation/fail_pretty_errors.d(35): Error: mixin `fail_pretty_errors.testMixin2.mixinTemplate!()` error instantiating
+fail_compilation/fail_pretty_errors.d(39): Error: mixin `fail_pretty_errors.testMixin2.mixinTemplate!()` error instantiating
mixin mixinTemplate;
^
+fail_compilation/fail_pretty_errors.d(45): Error: invalid array operation `"" + ""` (possible missing [])
+ auto x = ""+"";
+ ^
+fail_compilation/fail_pretty_errors.d(45): did you mean to concatenate (`"" ~ ""`) instead ?
---
*/
{
mixin mixinTemplate;
}
+
+void f()
+{
+ // check supplemental error doesn't show context
+ auto x = ""+"";
+}
TEST_OUTPUT:
---
fail_compilation/ice10922.d(10): Error: function `ice10922.__lambda4(in uint n)` is not callable using argument types `()`
-fail_compilation/ice10922.d(10): too few arguments, expected `1`, got `0`
+fail_compilation/ice10922.d(10): too few arguments, expected 1, got 0
---
*/
---
fail_compilation/ice13459.d(12): Error: undefined identifier `B`
fail_compilation/ice13459.d(18): Error: none of the overloads of `opSlice` are callable using argument types `(int, int)`
-fail_compilation/ice13459.d(11): Candidates are: `ice13459.A.opSlice()`
+fail_compilation/ice13459.d(11): Candidate is: `ice13459.A.opSlice()`
---
*/
struct A
TEST_OUTPUT:
---
fail_compilation/ice9540.d(35): Error: function `ice9540.A.test.AddFront!(this, f).AddFront.dg(int _param_0)` is not callable using argument types `()`
-fail_compilation/ice9540.d(35): too few arguments, expected `1`, got `0`
+fail_compilation/ice9540.d(35): too few arguments, expected 1, got 0
fail_compilation/ice9540.d(26): Error: template instance `ice9540.A.test.AddFront!(this, f)` error instantiating
---
*/
void foo(int) { }
+void foo(bool) { }
-void foo(T)(){}
+void foo(T)(string){}
+void foo(alias a)(){}
--- /dev/null
+/*
+TEST_OUTPUT:
+---
+fail_compilation/lexer23465.d(19): Error: char 0x1f37a not allowed in identifier
+fail_compilation/lexer23465.d(19): Error: character 0x1f37a is not a valid token
+fail_compilation/lexer23465.d(20): Error: character '\' is not a valid token
+fail_compilation/lexer23465.d(21): Error: unterminated /+ +/ comment
+fail_compilation/lexer23465.d(22): Error: found `End of File` instead of array initializer
+fail_compilation/lexer23465.d(22): Error: semicolon needed to end declaration of `arr`, instead of `End of File`
+fail_compilation/lexer23465.d(17): `arr` declared here
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=23465
+// Invalid token error points to wrong line
+
+int[] arr = [
+ 0,
+ x🍺,
+ 3\,
+ 5, /+
---
fail_compilation/misc1.d(108): Error: `5` has no effect
fail_compilation/misc1.d(109): Error: `1 + 2` has no effect
+fail_compilation/misc1.d(115): Deprecation: `1 * 1` has no effect
+fail_compilation/misc1.d(116): Deprecation: `__lambda3` has no effect
+fail_compilation/misc1.d(122): Deprecation: `false` has no effect
+fail_compilation/misc1.d(125): Deprecation: `*sp++` has no effect
+fail_compilation/misc1.d(126): Deprecation: `j` has no effect
---
*/
5, hasSideEffect12490();
1 + 2, hasSideEffect12490();
}
+
+void issue23480()
+{
+ int j;
+ for({} j; 1*1) {}
+ for({j=2; int d = 3;} j+d<7; {j++; d++;}) {}
+ for (
+ if (true) // (o_O)
+ assert(78);
+ else
+ assert(79);
+ false; false
+ ) {}
+ // unnecessary deref
+ for (ubyte* sp; 0; *sp++) {}
+ for (;; j) {}
+}
/*
TEST_OUTPUT:
---
-fail_compilation/nogc2.d(101): Error: indexing an associative array in `@nogc` function `nogc2.testIndex` may cause a GC allocation
-fail_compilation/nogc2.d(102): Error: indexing an associative array in `@nogc` function `nogc2.testIndex` may cause a GC allocation
+fail_compilation/nogc2.d(100): Error: assigning an associative array element in `@nogc` function `nogc2.testIndex` may cause a GC allocation
---
*/
@nogc void testIndex(int[int] aa)
/*
TEST_OUTPUT:
---
-fail_compilation/retscope.d(1405): Error: reference to local variable `buf` assigned to non-scope parameter `__anonymous_param` calling `myprintf`
+fail_compilation/retscope.d(1405): Error: reference to local variable `buf` assigned to non-scope anonymous parameter calling `myprintf`
---
*/
/*
TEST_OUTPUT:
---
-fail_compilation/retscope.d(1509): Error: reference to stack allocated value returned by `(*fp15)()` assigned to non-scope parameter `__anonymous_param`
+fail_compilation/retscope.d(1509): Error: reference to stack allocated value returned by `(*fp15)()` assigned to non-scope anonymous parameter
---
*/
/*
TEST_OUTPUT:
---
-fail_compilation/retscope2.d(604): Error: scope variable `_param_0` assigned to non-scope parameter `__anonymous_param` calling `foo600`
-fail_compilation/retscope2.d(604): Error: scope variable `_param_1` assigned to non-scope parameter `__anonymous_param` calling `foo600`
+fail_compilation/retscope2.d(604): Error: scope variable `_param_0` assigned to non-scope anonymous parameter calling `foo600`
+fail_compilation/retscope2.d(604): Error: scope variable `_param_1` assigned to non-scope anonymous parameter calling `foo600`
fail_compilation/retscope2.d(614): Error: template instance `retscope2.test600!(int*, int*)` error instantiating
---
*/
--- /dev/null
+/*
+TEST_OUTPUT:
+---
+fail_compilation/templateoverload.d(17): Error: template instance `T!1` does not match any template declaration
+fail_compilation/templateoverload.d(17): Candidates are:
+fail_compilation/templateoverload.d(14): T(X)
+fail_compilation/templateoverload.d(15): T()
+fail_compilation/templateoverload.d(22): Error: template instance `V!int` does not match any template declaration
+fail_compilation/templateoverload.d(22): Candidates are:
+fail_compilation/templateoverload.d(19): V(int i)
+fail_compilation/templateoverload.d(20): V(T, alias a)
+---
+*/
+template T(X) {}
+template T() {}
+
+alias t = T!1;
+
+template V(int i) {}
+template V(T, alias a) {}
+
+alias v = V!int;
/* TEST_OUTPUT:
---
fail_compilation/test19646.d(11): Error: cast from `const(int)*` to `int*` not allowed in safe code
+fail_compilation/test19646.d(17): Error: `@safe` variable `z` cannot be initialized by calling `@system` function `f`
---
https://issues.dlang.org/show_bug.cgi?id=19646
*/
@safe:
-
const x = 42;
int* y = cast(int*)&x;
+
+@system:
+
+@system int* f() { return cast(int*) 0xDEADBEEF; };
+
+@safe int* z = f();
fail_compilation/test21008.d(117): Error: need `this` for `toString` of type `string()`
fail_compilation/test21008.d(117): Error: need `this` for `toHash` of type `nothrow @trusted $?:32=uint|64=ulong$()`
fail_compilation/test21008.d(117): Error: function `object.Object.opCmp(Object o)` is not callable using argument types `()`
-fail_compilation/test21008.d(117): too few arguments, expected `1`, got `0`
+fail_compilation/test21008.d(117): too few arguments, expected 1, got 0
fail_compilation/test21008.d(117): Error: function `object.Object.opEquals(Object o)` is not callable using argument types `()`
-fail_compilation/test21008.d(117): too few arguments, expected `1`, got `0`
+fail_compilation/test21008.d(117): too few arguments, expected 1, got 0
fail_compilation/test21008.d(117): Error: `Monitor` has no effect
fail_compilation/test21008.d(117): Error: function `object.Object.factory(string classname)` is not callable using argument types `()`
-fail_compilation/test21008.d(117): too few arguments, expected `1`, got `0`
+fail_compilation/test21008.d(117): too few arguments, expected 1, got 0
fail_compilation/test21008.d(105): called from here: `handleMiddlewareAnnotation()`
fail_compilation/test21008.d(108): Error: class `test21008.C` no size because of forward reference
---
--- /dev/null
+/*
+TEST_OUTPUT:
+---
+fail_compilation/test21062.d(16): Error: no identifier for declarator `bool`
+fail_compilation/test21062.d(16): `synchronized` is a keyword, perhaps append `_` to make it an identifier
+fail_compilation/test21062.d(17): Error: no identifier for declarator `ubyte*`
+fail_compilation/test21062.d(17): `out` is a keyword, perhaps append `_` to make it an identifier
+fail_compilation/test21062.d(21): Error: no identifier for declarator `uint`
+fail_compilation/test21062.d(21): `in` is a keyword, perhaps append `_` to make it an identifier
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=21062
+// Confusing error when using a keyword as an identifier for a declaration
+
+bool synchronized;
+ubyte* out;
+
+void main()
+{
+ foreach(uint in; [])
+ {
+ }
+}
--- /dev/null
+/**
+REQUIRED_ARGS: -preview=dip1000
+TEST_OUTPUT:
+---
+fail_compilation/test23491.d(16): Error: reference to local variable `buffer` assigned to non-scope anonymous parameter
+fail_compilation/test23491.d(17): Error: reference to local variable `buffer` assigned to non-scope anonymous parameter calling `sinkF`
+fail_compilation/test23491.d(18): Error: reference to local variable `buffer` assigned to non-scope parameter `buf`
+---
+*/
+
+void sinkF(char[]) @safe;
+
+void toString(void delegate (char[]) @safe sink, void delegate(char[] buf) @safe sinkNamed) @safe
+{
+ char[20] buffer = void;
+ sink(buffer[]);
+ sinkF(buffer[]);
+ sinkNamed(buffer[]);
+}
--- /dev/null
+/* TEST_OUTPUT:
+---
+fail_compilation/test23536.d(104): Error: function `test23536.S.nonctor` cannot be a non-static member function for `pragma(crt_constructor)`
+fail_compilation/test23536.d(106): Error: function `test23536.S.nondtor` cannot be a non-static member function for `pragma(crt_destructor)`
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=23536
+
+#line 100
+
+struct S
+{
+ int x;
+ extern (C) pragma(crt_constructor) void nonctor() { } // should not compile
+ extern (C) pragma(crt_constructor) static void stactor() { } // should compile
+ extern (C) pragma(crt_destructor) void nondtor() { } // should not compile
+ extern (C) pragma(crt_destructor) static void stadtor() { } // should compile
+}
--- /dev/null
+/+ TEST_OUTPUT:
+---
+fail_compilation/throwexp.d(11): Error: to be thrown `ret()` must be non-null
+fail_compilation/throwexp.d(12): Error: to be thrown `null` must be non-null
+---
++/
+auto ret()
+{
+ return Exception.init;
+}
+enum y = throw ret();
+enum x = throw Exception.init;
+++ /dev/null
-// REQUIRED_ARGS: -o- -w
-
-/*
-TEST_OUTPUT:
----
-fail_compilation/warn14905.d(16): Warning: statement is not reachable in template instance warn14905.fun!"a".fun
-fail_compilation/warn14905.d(16): Warning: statement is not reachable in template instance warn14905.fun!"b".fun
-Error: warnings are treated as errors
- Use -wi if you wish to treat warnings only as informational.
----
-*/
-
-bool fun(string s)()
-{
- return true;
- return false;
-}
-
-void main()
-{
- cast(void)fun!"a";
- cast(void)fun!"b";
-}
/*
TEST_OUTPUT:
---
-runnable/lexer.d(81): Deprecation: `version( <integer> )` is deprecated, use version identifiers instead
-runnable/lexer.d(82): Deprecation: `debug( <integer> )` is deprecated, use debug identifiers instead
+runnable/lexer.d(86): Deprecation: `version( <integer> )` is deprecated, use version identifiers instead
+runnable/lexer.d(87): Deprecation: `debug( <integer> )` is deprecated, use debug identifiers instead
---
*/
//writefln("'%s'", s);
assert(s == "foo\n");
+ // https://issues.dlang.org/show_bug.cgi?id=19623
+ s = q"übel
+foo
+übel";
+ assert(s == "foo\n");
s = q{ foo(xxx) };
assert(s ==" foo(xxx) ");
--- /dev/null
+/* RUN_OUTPUT:
+---
+int AAAA0000
+int AAAA0001
+int AAAA0002
+int AAAA0003
+float FFFF0004
+float FFFF0005
+float FFFF0006
+float FFFF0007
+float FFFF0008
+float FFFF0009
+float FFFF0010
+float FFFF0011
+float FFFF0012
+float FFFF0013
+float FFFF0014
+float FFFF0015
+int AAAA0016
+int AAAA0017
+int AAAA0018
+int AAAA0019
+int AAAA0020
+int AAAA0021
+---
+ */
+
+// https://issues.dlang.org/show_bug.cgi?id=21301
+
+//extern (C)
+void func(
+ int p0, int[3] p1, float[3] p2, float p3, float p4, float p5, float p6, float p7,
+ float p8, float p9, float p10, float p11, int p12, int[2] p13, int p14, int p15, int p16
+) {
+ print(p0);
+
+ print(p1[0]);
+ print(p1[1]);
+ print(p1[2]);
+
+ print(p2[0]);
+ print(p2[1]);
+ print(p2[2]);
+
+ print(p3);
+ print(p4);
+ print(p5);
+ print(p6);
+ print(p7);
+ print(p8);
+ print(p9);
+ print(p10);
+ print(p11);
+ print(p12);
+ print(p13[0]);
+ print(p13[1]);
+ print(p14);
+ print(p15);
+ print(p16);
+}
+
+static if (0)
+{
+void print(int x);
+void print(float x);
+}
+else
+{
+import core.stdc.stdio;
+
+union U
+{
+ int[22] i = [
+ 0xAAAA_0000,
+ 0xAAAA_0001,
+ 0xAAAA_0002,
+ 0xAAAA_0003,
+ 0xFFFF_0004,
+ 0xFFFF_0005,
+ 0xFFFF_0006,
+ 0xFFFF_0007,
+ 0xFFFF_0008,
+ 0xFFFF_0009,
+ 0xFFFF_0010,
+ 0xFFFF_0011,
+ 0xFFFF_0012,
+ 0xFFFF_0013,
+ 0xFFFF_0014,
+ 0xFFFF_0015,
+ 0xAAAA_0016,
+ 0xAAAA_0017,
+ 0xAAAA_0018,
+ 0xAAAA_0019,
+ 0xAAAA_0020,
+ 0xAAAA_0021,
+ ];
+
+ float[22] f;
+}
+
+void print(int x) { printf("int %08X\n", x); }
+void print(float x) { printf("float %08X\n", *(cast(int*) &x)); }
+
+int main()
+{
+ func(U.init.i[0],
+ [U.init.i[1], U.init.i[2], U.init.i[3]],
+ [U.init.f[4], U.init.f[5], U.init.f[6]],
+ U.init.f[7], U.init.f[8], U.init.f[9], U.init.f[10], U.init.f[11], U.init.f[12], U.init.f[13],
+ U.init.f[14], U.init.f[15], U.init.i[16],
+ [U.init.i[17], U.init.i[18]],
+ U.init.i[19], U.init.i[20], U.init.i[21]
+ );
+ return 0;
+}
+}
--- /dev/null
+/* RUN_OUTPUT:
+---
+value: -5
+value: -5
+---
+*/
+
+// https://issues.dlang.org/show_bug.cgi?id=21506
+
+import core.stdc.stdio;
+import core.stdc.stdarg;
+
+extern(C++)
+{
+
+void print(long a, va_list args){
+ vprintf("value: %d\n", args);
+}
+void proxy0(long a, long b, long c, long d, bool e, ...){
+ va_list ap;
+ va_start(ap, e);
+ print(a, ap);
+ va_end(ap);
+// print(a, _argptr);
+}
+void proxy1(long d, bool e, ...){
+ va_list ap;
+ va_start(ap, e);
+ print(d, ap);
+ va_end(ap);
+// print(d, _argptr);
+}
+
+}
+
+void main(){
+ int var = -5;
+ proxy0(1, 2, 3, 4, true, var);
+ proxy1(4, true, var);
+}
-e4f89195913be1dc638707b1abb24c4f3ae7e0bf
+c8ae4adb2eda515b09b326948e3a4aa9f489af45
The first line of this file holds the git revision number of the last
merge done from the dlang/dmd repository.
debug(trace) import core.stdc.stdio : printf;
debug(info) import core.stdc.stdio : printf;
+extern (C) alias CXX_DEMANGLER = char* function (const char* mangled_name,
+ char* output_buffer,
+ size_t* length,
+ int* status) nothrow pure @trusted;
+
private struct NoHooks
{
// supported hooks
/**
- * Demangles D mangled names. If it is not a D mangled name, it returns its
- * argument name.
+ * Demangles D/C++ mangled names. If it is not a D/C++ mangled name, it
+ * returns its argument name.
*
* Params:
* buf = The string to demangle.
* dst = An optional destination buffer.
+ * __cxa_demangle = optional C++ demangler
*
* Returns:
- * The demangled name or the original string if the name is not a mangled D
- * name.
+ * The demangled name or the original string if the name is not a mangled
+ * D/C++ name.
*/
-char[] demangle(return scope const(char)[] buf, return scope char[] dst = null ) nothrow pure @safe
+char[] demangle(return scope const(char)[] buf, return scope char[] dst = null, CXX_DEMANGLER __cxa_demangle = null) nothrow pure @safe
{
+ if (buf.length > 2 && buf[0..2] == "_Z")
+ return demangleCXX(buf, __cxa_demangle, dst);
auto d = Demangle!()(buf, dst);
// fast path (avoiding throwing & catching exception) for obvious
// non-D mangled names
}
}
- bool parseLName(scope ref Remangle d) scope
+ bool parseLName(scope ref Remangle d) scope @trusted
{
flushPosition(d);
}
else
{
- idpos[id] = refpos;
+ idpos[id] = refpos; //! scope variable id used as AA key, makes this function @trusted
result ~= d.buf[refpos .. d.pos];
}
}
{
char[] buf = new char[i];
auto ds = demangle(s, buf);
- assert(ds == "pure nothrow @safe char[] core.demangle.demangle(scope return const(char)[], scope return char[])" ||
- ds == "pure nothrow @safe char[] core.demangle.demangle(return scope const(char)[], return scope char[])");
+ assert(ds == "pure nothrow @safe char[] core.demangle.demangle(scope return const(char)[], scope return char[], extern (C) char* function(const(char*), char*, ulong*, int*) pure nothrow @trusted*)" ||
+ ds == "pure nothrow @safe char[] core.demangle.demangle(return scope const(char)[], return scope char[], extern (C) char* function(const(char*), char*, ulong*, int*) pure nothrow @trusted*)" ||
+ ds == "pure nothrow @safe char[] core.demangle.demangle(scope return const(char)[], scope return char[], extern (C) char* function(const(char*), char*, uint*, int*) pure nothrow @trusted*)" ||
+ ds == "pure nothrow @safe char[] core.demangle.demangle(return scope const(char)[], return scope char[], extern (C) char* function(const(char*), char*, uint*, int*) pure nothrow @trusted*)", ds);
}
}
}
return null;
}
+
+private shared CXX_DEMANGLER __cxa_demangle;
+
+/**
+ * Returns:
+ * a CXX_DEMANGLER if a C++ stdlib is loaded
+ */
+
+CXX_DEMANGLER getCXXDemangler() nothrow @trusted
+{
+ if (__cxa_demangle is null)
+ version (Posix)
+ {
+ import core.sys.posix.dlfcn : dlsym;
+ version (DragonFlyBSD) import core.sys.dragonflybsd.dlfcn : RTLD_DEFAULT;
+ version (FreeBSD) import core.sys.freebsd.dlfcn : RTLD_DEFAULT;
+ version (linux) import core.sys.linux.dlfcn : RTLD_DEFAULT;
+ version (NetBSD) import core.sys.netbsd.dlfcn : RTLD_DEFAULT;
+ version (OSX) import core.sys.darwin.dlfcn : RTLD_DEFAULT;
+ version (Solaris) import core.sys.solaris.dlfcn : RTLD_DEFAULT;
+
+ if (auto found = cast(CXX_DEMANGLER) dlsym(RTLD_DEFAULT, "__cxa_demangle"))
+ __cxa_demangle = found;
+ }
+
+ if (__cxa_demangle is null)
+ __cxa_demangle = (const char* mangled_name, char* output_buffer,
+ size_t* length, int* status) nothrow pure @trusted {
+ *status = -1;
+ return null;
+ };
+
+ return __cxa_demangle;
+}
+
+/**
+ * Demangles C++ mangled names. If it is not a C++ mangled name, it
+ * returns its argument name.
+ *
+ * Params:
+ * buf = The string to demangle.
+ * __cxa_demangle = C++ demangler
+ * dst = An optional destination buffer.
+ *
+ * Returns:
+ * The demangled name or the original string if the name is not a mangled
+ * C++ name.
+ */
+private char[] demangleCXX(return scope const(char)[] buf, CXX_DEMANGLER __cxa_demangle, return scope char[] dst = null,) nothrow pure @trusted
+{
+ char[] c_string = dst; // temporarily use dst buffer if possible
+ c_string.length = buf.length + 1;
+ c_string[0 .. buf.length] = buf[0 .. buf.length];
+ c_string[buf.length] = '\0';
+
+ int status;
+ size_t demangled_length;
+ auto demangled = __cxa_demangle(&c_string[0], null, &demangled_length, &status);
+ scope (exit) {
+ import core.memory;
+ pureFree(cast(void*) demangled);
+ }
+ if (status == 0)
+ {
+ dst.length = demangled_length;
+ dst[] = demangled[0 .. demangled_length];
+ return dst;
+ }
+
+ dst.length = buf.length;
+ dst[] = buf[];
+ return dst;
+}
* Throws:
* $(LREF RangeError).
*/
-extern (C) void onRangeError( string file = __FILE__, size_t line = __LINE__ ) @trusted pure nothrow @nogc
+extern (C) noreturn onRangeError( string file = __FILE__, size_t line = __LINE__ ) @trusted pure nothrow @nogc
{
throw staticError!RangeError(file, line, null);
}
* Throws:
* $(LREF ArraySliceError).
*/
-extern (C) void onArraySliceError( size_t lower = 0, size_t upper = 0, size_t length = 0,
+extern (C) noreturn onArraySliceError( size_t lower = 0, size_t upper = 0, size_t length = 0,
string file = __FILE__, size_t line = __LINE__ ) @trusted pure nothrow @nogc
{
throw staticError!ArraySliceError(lower, upper, length, file, line, null);
* Throws:
* $(LREF ArrayIndexError).
*/
-extern (C) void onArrayIndexError( size_t index = 0, size_t length = 0,
+extern (C) noreturn onArrayIndexError( size_t index = 0, size_t length = 0,
string file = __FILE__, size_t line = __LINE__ ) @trusted pure nothrow @nogc
{
throw staticError!ArrayIndexError(index, length, file, line, null);
* Throws:
* $(LREF FinalizeError).
*/
-extern (C) void onFinalizeError( TypeInfo info, Throwable e, string file = __FILE__, size_t line = __LINE__ ) @trusted nothrow
+extern (C) noreturn onFinalizeError( TypeInfo info, Throwable e, string file = __FILE__, size_t line = __LINE__ ) @trusted nothrow
{
// This error is thrown during a garbage collection, so no allocation must occur while
// generating this object. So we use a preallocated instance
// templates even for ordinary builds instead of providing them as an
// extern(C) library.
- void onOutOfMemoryError()(void* pretend_sideffect = null) @nogc nothrow pure @trusted
+ noreturn onOutOfMemoryError()(void* pretend_sideffect = null) @nogc nothrow pure @trusted
{
assert(0, "Memory allocation failed");
}
alias onOutOfMemoryErrorNoGC = onOutOfMemoryError;
- void onInvalidMemoryOperationError()(void* pretend_sideffect = null) @nogc nothrow pure @trusted
+ noreturn onInvalidMemoryOperationError()(void* pretend_sideffect = null) @nogc nothrow pure @trusted
{
assert(0, "Invalid memory operation");
}
* Throws:
* $(LREF OutOfMemoryError).
*/
- extern (C) void onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */
+ extern (C) noreturn onOutOfMemoryError(void* pretend_sideffect = null) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */
{
// NOTE: Since an out of memory condition exists, no allocation must occur
// while generating this object.
throw staticError!OutOfMemoryError();
}
- extern (C) void onOutOfMemoryErrorNoGC() @trusted nothrow @nogc
+ extern (C) noreturn onOutOfMemoryErrorNoGC() @trusted nothrow @nogc
{
// suppress stacktrace until they are @nogc
throw staticError!OutOfMemoryError(false);
* Throws:
* $(LREF InvalidMemoryOperationError).
*/
-extern (C) void onInvalidMemoryOperationError(void* pretend_sideffect = null) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */
+extern (C) noreturn onInvalidMemoryOperationError(void* pretend_sideffect = null) @trusted pure nothrow @nogc /* dmd @@@BUG11461@@@ */
{
// The same restriction applies as for onOutOfMemoryError. The GC is in an
// undefined state, thus no allocation must occur while generating this object.
* Throws:
* $(LREF ConfigurationError).
*/
-extern (C) void onForkError( string file = __FILE__, size_t line = __LINE__ ) @trusted pure nothrow @nogc
+extern (C) noreturn onForkError( string file = __FILE__, size_t line = __LINE__ ) @trusted pure nothrow @nogc
{
throw staticError!ForkError( file, line, null );
}
* Throws:
* $(LREF UnicodeException).
*/
-extern (C) void onUnicodeError( string msg, size_t idx, string file = __FILE__, size_t line = __LINE__ ) @safe pure
+extern (C) noreturn onUnicodeError( string msg, size_t idx, string file = __FILE__, size_t line = __LINE__ ) @safe pure
{
throw new UnicodeException( msg, idx, file, line );
}
private align(2 * size_t.sizeof) void[256] _store;
// only Errors for now as those are rarely chained
-private T staticError(T, Args...)(auto ref Args args)
+package T staticError(T, Args...)(auto ref Args args)
if (is(T : Error))
{
// pure hack, what we actually need is @noreturn and allow to call that in pure functions
else if (errno == ECHILD)
return ChildStatus.done; // someone called posix.syswait
else if (waited_pid != pid || status != 0)
- {
onForkError();
- return ChildStatus.error;
- }
return ChildStatus.done;
}
{
fixbuf[0 .. symBeg] = buf[0 .. symBeg];
- auto sym = demangle(buf[symBeg .. symEnd], fixbuf[symBeg .. $]);
+ auto sym = demangle(buf[symBeg .. symEnd], fixbuf[symBeg .. $], getCXXDemangler());
if (sym.ptr !is fixbuf.ptr + symBeg)
{
public import core.sync.mutex;
public import core.time;
+import core.exception : AssertError, staticError;
+
+
version (Windows)
{
import core.sync.semaphore;
// void notifyAll();
////////////////////////////////////////////////////////////////////////////////
-
/**
* This class represents a condition variable as conceived by C.A.R. Hoare. As
* per Mesa type monitors however, "signal" has been replaced with "notify" to
* Throws:
* SyncError on error.
*/
- this( Mutex m ) nothrow @safe
+ this( Mutex m ) nothrow @safe @nogc
{
this(m, true);
}
/// ditto
- this( shared Mutex m ) shared nothrow @safe
+ this( shared Mutex m ) shared nothrow @safe @nogc
{
this(m, true);
}
//
- private this(this Q, M)( M m, bool _unused_ ) nothrow @trusted
+ private this(this Q, M)( M m, bool _unused_ ) nothrow @trusted @nogc
if ((is(Q == Condition) && is(M == Mutex)) ||
(is(Q == shared Condition) && is(M == shared Mutex)))
{
}
m_blockLock = cast(HANDLE_TYPE) CreateSemaphoreA( null, 1, 1, null );
if ( m_blockLock == m_blockLock.init )
- throw new SyncError( "Unable to initialize condition" );
+ throw staticError!AssertError("Unable to initialize condition", __FILE__, __LINE__);
scope(failure) CloseHandle( cast(void*) m_blockLock );
m_blockQueue = cast(HANDLE_TYPE) CreateSemaphoreA( null, 0, int.max, null );
if ( m_blockQueue == m_blockQueue.init )
- throw new SyncError( "Unable to initialize condition" );
+ throw staticError!AssertError("Unable to initialize condition", __FILE__, __LINE__);
scope(failure) CloseHandle( cast(void*) m_blockQueue );
InitializeCriticalSection( cast(RTL_CRITICAL_SECTION*) &m_unblockLock );
pthread_condattr_t attr = void;
int rc = pthread_condattr_init( &attr );
if ( rc )
- throw new SyncError( "Unable to initialize condition" );
+ throw staticError!AssertError("Unable to initialize condition", __FILE__, __LINE__);
rc = pthread_condattr_setclock( &attr, CLOCK_MONOTONIC );
if ( rc )
- throw new SyncError( "Unable to initialize condition" );
+ throw staticError!AssertError("Unable to initialize condition", __FILE__, __LINE__);
rc = pthread_cond_init( cast(pthread_cond_t*) &m_hndl, &attr );
if ( rc )
- throw new SyncError( "Unable to initialize condition" );
+ throw staticError!AssertError("Unable to initialize condition", __FILE__, __LINE__);
rc = pthread_condattr_destroy( &attr );
if ( rc )
- throw new SyncError( "Unable to initialize condition" );
+ throw staticError!AssertError("Unable to initialize condition", __FILE__, __LINE__);
} ();
}
else
{
int rc = pthread_cond_init( cast(pthread_cond_t*) &m_hndl, null );
if ( rc )
- throw new SyncError( "Unable to initialize condition" );
+ throw staticError!AssertError("Unable to initialize condition", __FILE__, __LINE__);
}
}
}
-
- ~this()
+ ~this() @nogc
{
version (Windows)
{
{
int rc = pthread_cond_wait( cast(pthread_cond_t*) &m_hndl, (cast(Mutex) m_assocMutex).handleAddr() );
if ( rc )
- throw new SyncError( "Unable to wait for condition" );
+ throw staticError!AssertError("Unable to wait for condition", __FILE__, __LINE__);
}
}
return true;
if ( rc == ETIMEDOUT )
return false;
- throw new SyncError( "Unable to wait for condition" );
+ throw staticError!AssertError("Unable to wait for condition", __FILE__, __LINE__);
}
}
rc = pthread_cond_signal( cast(pthread_cond_t*) &m_hndl );
} while ( rc == EAGAIN );
if ( rc )
- throw new SyncError( "Unable to notify condition" );
+ throw staticError!AssertError("Unable to notify condition", __FILE__, __LINE__);
}
}
rc = pthread_cond_broadcast( cast(pthread_cond_t*) &m_hndl );
} while ( rc == EAGAIN );
if ( rc )
- throw new SyncError( "Unable to notify condition" );
+ throw staticError!AssertError("Unable to notify condition", __FILE__, __LINE__);
}
}
package:
version (Posix)
{
- pthread_mutex_t* handleAddr()
+ pthread_mutex_t* handleAddr() @nogc
{
return &m_hndl;
}
}
else version (OpenBSD)
{
+ int waitid(idtype_t, id_t, siginfo_t*, int);
}
else version (DragonFlyBSD)
{
int setsockopt(SOCKET s, int level, int optname, const(void)* optval, socklen_t optlen);
uint inet_addr(const char* cp);
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, const(timeval)* timeout);
-@trusted char* inet_ntoa(in_addr ina);
+char* inet_ntoa(in_addr ina);
hostent* gethostbyname(const char* name);
hostent* gethostbyaddr(const(void)* addr, int len, int type);
protoent* getprotobyname(const char* name);
-@trusted protoent* getprotobynumber(int number);
+protoent* getprotobynumber(int number);
servent* getservbyname(const char* name, const char* proto);
servent* getservbyport(int port, const char* proto);
}
-3ad507b5125573c5b47736a0913105bfb1249746
+792c8b7c1d5957767e138f78d04bf175d4b92f10
The first line of this file holds the git revision number of the last
merge done from the dlang/phobos repository.
Assigns `value` to each element of input range `range`.
Alternatively, instead of using a single `value` to fill the `range`,
-a `filter` $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
+a `filler` $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
can be provided. The length of `filler` and `range` do not need to match, but
`filler` must not be empty.
{
foreach (T2; ReferenceRanges)
{
- import std.array;
+ import std.array : array;
T1 A;
T2 B;
}
/// ditto
-ForeachType!(PointerTarget!Range)[] array(Range)(Range r)
-if (isPointer!Range && isIterable!(PointerTarget!Range) && !isAutodecodableString!Range && !isInfinite!Range)
+ForeachType!(typeof((*Range).init))[] array(Range)(Range r)
+if (is(Range : U*, U) && isIterable!U && !isAutodecodableString!Range && !isInfinite!Range)
{
return array(*r);
}
Implements an output range that appends data to an array. This is
recommended over $(D array ~= data) when appending many elements because it is more
efficient. `Appender` maintains its own array metadata locally, so it can avoid
-global locking for each append where $(LREF capacity) is non-zero.
+the $(DDSUBLINK spec/arrays, capacity-reserve, performance hit of looking up slice `capacity`)
+for each append.
Params:
A = the array type to simulate.
private template canPutItem(U)
{
enum bool canPutItem =
- isImplicitlyConvertible!(Unqual!U, Unqual!T) ||
+ is(Unqual!U : Unqual!T) ||
isSomeChar!T && isSomeChar!U;
}
private template canPutConstRange(Range)
*/
void popFront()
{
- enforce(!empty, new Base64Exception("Cannot call popFront on Encoder with no data remaining"));
+ assert(!empty, "Cannot call popFront on Encoder with no data remaining");
range_.popFront();
*/
void popFront()
{
- enforce(!empty, new Base64Exception("Cannot call popFront on Encoder with no data remaining"));
+ assert(!empty, "Cannot call popFront on Encoder with no data remaining");
static if (Padding != NoPadding)
if (padding)
*/
void popFront()
{
- enforce(!empty, new Base64Exception("Cannot call popFront on Decoder with no data remaining."));
+ assert(!empty, "Cannot call popFront on Decoder with no data remaining.");
range_.popFront();
/**
Flips a single bit, specified by `pos`
*/
- void flip(size_t i) @nogc pure nothrow
+ void flip(size_t pos) @nogc pure nothrow
{
- bt(_ptr, i) ? btr(_ptr, i) : bts(_ptr, i);
+ bt(_ptr, pos) ? btr(_ptr, pos) : bts(_ptr, pos);
}
///
import core.atomic : atomicLoad, MemoryOrder;
static if (is(typeof(this.payload.atomicLoad!(MemoryOrder.acq)) P))
{
- auto payload = __ctfe ? cast(P) this.payload
+ auto localPayload = __ctfe ? cast(P) this.payload
: this.payload.atomicLoad!(MemoryOrder.acq);
}
else
{
- alias payload = this.payload;
+ alias localPayload = this.payload;
}
static if (hasMember!(Hook, "hookToHash"))
{
- return hook.hookToHash(payload);
+ return hook.hookToHash(localPayload);
}
else static if (stateSize!Hook > 0)
{
- static if (hasMember!(typeof(payload), "toHash"))
+ static if (hasMember!(typeof(localPayload), "toHash"))
{
- return payload.toHash() ^ hashOf(hook);
+ return localPayload.toHash() ^ hashOf(hook);
}
else
{
- return hashOf(payload) ^ hashOf(hook);
+ return hashOf(localPayload) ^ hashOf(hook);
}
}
- else static if (hasMember!(typeof(payload), "toHash"))
+ else static if (hasMember!(typeof(localPayload), "toHash"))
{
- return payload.toHash();
+ return localPayload.toHash();
}
else
{
- return .hashOf(payload);
+ return .hashOf(localPayload);
}
}
enum isParamsImplicitlyConvertible = false;
else static if (param1.length == i)
enum isParamsImplicitlyConvertible = true;
- else static if (isImplicitlyConvertible!(param2[i], param1[i]))
+ else static if (is(param2[i] : param1[i]))
enum isParamsImplicitlyConvertible = isParamsImplicitlyConvertible!(F1,
F2, i + 1);
else
static assert(T.length, "T must not be empty");
- static if (isImplicitlyConvertible!(T[0], Duration))
+ static if (is(T[0] : Duration))
{
alias Ops = AliasSeq!(T[1 .. $]);
alias ops = vals[1 .. $];
float[] a0;
{
import std.range : iota;
- import std.array;
+ import std.array : array;
import std.algorithm.iteration : map;
a0 = iota (0, n).map!(i => i * 1.1f).array;
}
*/
void removeBack()
{
- enforce(!empty);
+ assert(!empty);
static if (hasElaborateDestructor!T)
.destroy(_data._payload[$ - 1]);
/// Ditto
@property T front()
{
- enforce(!empty, "Attempting to access the front of an empty Array");
+ assert(!empty, "Attempting to access the front of an empty Array");
return _outer[_a];
}
/// Ditto
@property void front(bool value)
{
- enforce(!empty, "Attempting to set the front of an empty Array");
+ assert(!empty, "Attempting to set the front of an empty Array");
_outer[_a] = value;
}
/// Ditto
T moveFront()
{
- enforce(!empty, "Attempting to move the front of an empty Array");
+ assert(!empty, "Attempting to move the front of an empty Array");
return _outer.moveAt(_a);
}
/// Ditto
void popFront()
{
- enforce(!empty, "Attempting to popFront an empty Array");
+ assert(!empty, "Attempting to popFront an empty Array");
++_a;
}
/// Ditto
@property T back()
{
- enforce(!empty, "Attempting to access the back of an empty Array");
+ assert(!empty, "Attempting to access the back of an empty Array");
return _outer[_b - 1];
}
/// Ditto
@property void back(bool value)
{
- enforce(!empty, "Attempting to set the back of an empty Array");
+ assert(!empty, "Attempting to set the back of an empty Array");
_outer[_b - 1] = value;
}
/// Ditto
T moveBack()
{
- enforce(!empty, "Attempting to move the back of an empty Array");
+ assert(!empty, "Attempting to move the back of an empty Array");
return _outer.moveAt(_b - 1);
}
/// Ditto
void popBack()
{
- enforce(!empty, "Attempting to popBack an empty Array");
+ assert(!empty, "Attempting to popBack an empty Array");
--_b;
}
/// Ditto
*/
@property bool front()
{
- enforce(!empty);
+ assert(!empty);
return data.ptr[0] & 1;
}
/// Ditto
@property void front(bool value)
{
- enforce(!empty);
+ assert(!empty);
if (value) data.ptr[0] |= 1;
else data.ptr[0] &= ~cast(size_t) 1;
}
*/
@property bool back()
{
- enforce(!empty);
+ assert(!empty);
return cast(bool)(data.back & (cast(size_t) 1 << ((_store._length - 1) % bitsPerWord)));
}
/// Ditto
@property void back(bool value)
{
- enforce(!empty);
+ assert(!empty);
if (value)
{
data.back |= (cast(size_t) 1 << ((_store._length - 1) % bitsPerWord));
*/
@property ElementType!Store front()
{
- enforce(!empty, "Cannot call front on an empty heap.");
+ assert(!empty, "Cannot call front on an empty heap.");
return _store.front;
}
*/
void removeFront()
{
- enforce(!empty, "Cannot call removeFront on an empty heap.");
+ assert(!empty, "Cannot call removeFront on an empty heap.");
if (_length > 1)
{
auto t1 = _store[].moveFront();
template isEnumStrToStr(S, T)
{
- enum isEnumStrToStr = isImplicitlyConvertible!(S, T) &&
+ enum isEnumStrToStr = is(S : T) &&
is(S == enum) && isExactSomeString!T;
}
template isNullToStr(S, T)
{
- enum isNullToStr = isImplicitlyConvertible!(S, T) &&
+ enum isNullToStr = is(S : T) &&
(is(immutable S == immutable typeof(null))) && isExactSomeString!T;
}
}
to) simply performs the implicit conversion.
*/
private T toImpl(T, S)(S value)
-if (isImplicitlyConvertible!(S, T) &&
+if (is(S : T) &&
!isEnumStrToStr!(S, T) && !isNullToStr!(S, T))
{
template isSignedInt(T)
When source type supports member template function opCast, it is used.
*/
private T toImpl(T, S)(S value)
-if (!isImplicitlyConvertible!(S, T) &&
+if (!is(S : T) &&
is(typeof(S.init.opCast!T()) : T) &&
!isExactSomeString!T &&
!is(typeof(T(value))))
$(LI If target type is class, $(D new T(value)) is used.))
*/
private T toImpl(T, S)(S value)
-if (!isImplicitlyConvertible!(S, T) &&
+if (!is(S : T) &&
is(T == struct) && is(typeof(T(value))))
{
return T(value);
/// ditto
private T toImpl(T, S)(S value)
-if (!isImplicitlyConvertible!(S, T) &&
+if (!is(S : T) &&
is(T == class) && is(typeof(new T(value))))
{
return new T(value);
non-null and the target is null.
*/
private T toImpl(T, S)(S value)
-if (!isImplicitlyConvertible!(S, T) &&
+if (!is(S : T) &&
(is(S == class) || is(S == interface)) && !is(typeof(value.opCast!T()) : T) &&
(is(T == class) || is(T == interface)) && !is(typeof(new T(value))))
{
alias tgtmod = AddModifier!m2;
// Compile time convertible equals to modifier convertible.
- static if (isImplicitlyConvertible!(srcmod!Object, tgtmod!Object))
+ static if (is(srcmod!Object : tgtmod!Object))
{
// Test runtime conversions: class to class, class to interface,
// interface to class, and interface to interface
Handles type _to string conversions
*/
private T toImpl(T, S)(S value)
-if (!(isImplicitlyConvertible!(S, T) &&
+if (!(is(S : T) &&
!isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) &&
!isInfinite!S && isExactSomeString!T)
{
To string conversion for non copy-able structs
*/
private T toImpl(T, S)(ref S value)
-if (!(isImplicitlyConvertible!(S, T) &&
+if (!(is(S : T) &&
!isEnumStrToStr!(S, T) && !isNullToStr!(S, T)) &&
!isInfinite!S && isExactSomeString!T && !isCopyable!S && !isStaticArray!S)
{
fit in the narrower type.
*/
private T toImpl(T, S)(S value)
-if (!isImplicitlyConvertible!(S, T) &&
+if (!is(S : T) &&
(isNumeric!S || isSomeChar!S || isBoolean!S) &&
(isNumeric!T || isSomeChar!T || isBoolean!T) && !is(T == enum))
{
converts each element in turn by using `to`.
*/
private T toImpl(T, S)(scope S value)
-if (!isImplicitlyConvertible!(S, T) &&
+if (!is(S : T) &&
!isSomeString!S && isDynamicArray!S &&
!isExactSomeString!T && isArray!T)
{
and each value in turn.
*/
private T toImpl(T, S)(S value)
-if (!isImplicitlyConvertible!(S, T) && isAssociativeArray!S &&
+if (!is(S : T) && isAssociativeArray!S &&
isAssociativeArray!T && !is(T == enum))
{
/* This code is potentially unsafe.
static void testScope(scope ref SysTime st) @safe
{
- auto result = SysTimeToSYSTEMTIME(st);
+ auto localResult = SysTimeToSYSTEMTIME(st);
}
}
static void testScope(scope ref SysTime st) @safe
{
- auto result = SysTimeToFILETIME(st);
+ auto local_result = SysTimeToFILETIME(st);
}
}
}
import std.string : representation;
string data1 = "Hello, world", data2 = "Hola mundo";
auto hmac = HMAC!SHA1("My s3cR3T keY".representation);
- auto digest = hmac.put(data1.representation)
+ auto testDigest = hmac.put(data1.representation)
.put(data2.representation)
.finish();
static immutable expected = [
197, 57, 52, 3, 13, 194, 13,
36, 117, 228, 8, 11, 111, 51,
165, 3, 123, 31, 251, 113];
- assert(digest == expected);
+ assert(testDigest == expected);
}
}
*/
bool doesPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @nogc @trusted pure nothrow
if (__traits(isRef, source) || isDynamicArray!S ||
- isPointer!S || is(S == class))
+ is(S : U*, U) || is(S == class))
{
- static if (isPointer!S || is(S == class) || is(S == interface))
+ static if (is(S : U*, U) || is(S == class) || is(S == interface))
{
const m = *cast(void**) &source;
const b = cast(void*) ⌖
/// ditto
bool mayPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target) @trusted pure nothrow
if (__traits(isRef, source) || isDynamicArray!S ||
- isPointer!S || is(S == class))
+ is(S : U*, U) || is(S == class))
{
- static if (isPointer!S || is(S == class) || is(S == interface))
+ static if (is(S : U*, U) || is(S == class) || is(S == interface))
{
const m = *cast(void**) &source;
const b = cast(void*) ⌖
from 3585 bytes through 4072 KB are handled by a `BitmappedBlock` with a
block size of 4 KB. Sizes above that are passed direct to the `GCAllocator`.
-----
+$(RUNNABLE_EXAMPLE
+ ----
+ import std.experimental.allocator;
+ import std.algorithm.comparison : max;
+
alias FList = FreeList!(GCAllocator, 0, unbounded);
alias A = Segregator!(
8, FreeList!(GCAllocator, 0, 8),
1024, Bucketizer!(FList, 513, 1024, 128),
2048, Bucketizer!(FList, 1025, 2048, 256),
3584, Bucketizer!(FList, 2049, 3584, 512),
- 4072 * 1024, AllocatorList!(
- () => BitmappedBlock!(GCAllocator, 4096)(4072 * 1024)),
+ 4072 * 1024, AllocatorList!(n => Region!GCAllocator(max(n, 1024 * 4096))),
GCAllocator
);
A tuMalloc;
assert(tuMalloc.expand(c, 14));
tuMalloc.deallocate(b);
tuMalloc.deallocate(c);
-----
+ ----
+)
$(H2 Allocating memory for sharing across threads)
$(LREF theAllocator)
))
$(TR $(TD Class interface) $(TD
- $(LREF allocatorObject)
$(LREF CAllocatorImpl)
+ $(LREF CSharedAllocatorImpl)
$(LREF IAllocator)
+ $(LREF ISharedAllocator)
+))
+$(TR $(TD Structs) $(TD
+ $(LREF allocatorObject)
+ $(LREF RCIAllocator)
+ $(LREF RCISharedAllocator)
+ $(LREF sharedAllocatorObject)
+ $(LREF ThreadLocal)
))
)
Synopsis:
+$(RUNNABLE_EXAMPLE
---
// Allocate an int, initialize it with 42
int* p = theAllocator.make!int(42);
assert(*p == 100);
// Destroy and deallocate
processAllocator.dispose(p);
-
+---
+)
+$(RUNNABLE_EXAMPLE
+---
// Create an array of 50 doubles initialized to -1.0
double[] arr = theAllocator.makeArray!double(50, -1.0);
// Append two zeros to it
// Destroy and deallocate
theAllocator.dispose(arr);
---
+)
$(H2 Layered Structure)
{
string[] listdir(string pathname)
{
- import std.algorithm;
- import std.array;
- import std.file;
- import std.path;
+ import std.algorithm.iteration : map, filter;
+ import std.array : array;
+ import std.path : baseName;
- return std.file.dirEntries(pathname, SpanMode.shallow)
+ return dirEntries(pathname, SpanMode.shallow)
.filter!(a => a.isFile)
- .map!((return a) => std.path.baseName(a.name))
+ .map!((return a) => baseName(a.name))
.array;
}
// Can be safe only with -preview=dip1000
@safe void main(string[] args)
{
- import std.stdio;
+ import std.stdio : writefln;
string[] files = listdir(args[1]);
writefln("%s", files);
/*
`enum`s are formatted like their base value
*/
-void formatValueImpl(Writer, T, Char)(auto ref Writer w, const(T) val, scope const ref FormatSpec!Char f)
+void formatValueImpl(Writer, T, Char)(auto ref Writer w, T val, scope const ref FormatSpec!Char f)
if (is(T == enum))
{
import std.array : appender;
if (f.spec != 's')
return formatValueImpl(w, cast(OriginalType!T) val, f);
- static foreach (e; EnumMembers!T)
- {
- if (val == e)
- {
- formatValueImpl(w, __traits(identifier, e), f);
- return;
- }
- }
+ foreach (immutable member; __traits(allMembers, T))
+ if (val == __traits(getMember, T, member))
+ return formatValueImpl(w, member, f);
auto w2 = appender!string();
// val is not a member of T, output cast(T) rawValue instead.
- put(w2, "cast(");
- put(w2, T.stringof);
- put(w2, ")");
+ enum prefix = "cast(" ~ T.stringof ~ ")";
+ put(w2, prefix);
static assert(!is(OriginalType!T == T), "OriginalType!" ~ T.stringof ~
"must not be equal to " ~ T.stringof);
auto a = iota(0, 10);
auto b = iota(0, 10);
- auto p = () @trusted { auto p = &a; return p; }();
+ auto p = () @trusted { auto result = &a; return result; }();
assert(format("%s",p) != format("%s",b));
}
$(BOOKTABLE ,
$(TR $(TH Flag) $(TH Semantics))
$(TR $(TD $(B '-'))
- $(TD When the formatted result is shorter then the value
- given by the width parameter, the output is right
- justified. With the $(B '-') flag this is changed
- to left justification.
+ $(TD When the formatted result is shorter than the value
+ given by the width parameter, the output is left
+ justified. Without the $(B '-') flag, the output remains
+ right justified.
There are two exceptions where the $(B '-') flag has a
different meaning: (1) with $(B 'r') it denotes to use little
endian and (2) in case of a compound indicator it means that
no special handling of the members is applied.))
$(TR $(TD $(B '='))
- $(TD When the formatted result is shorter then the value
+ $(TD When the formatted result is shorter than the value
given by the width parameter, the output is centered.
If the central position is not possible it is moved slightly
to the right. In this case, if $(B '-') flag is present in
{
char[] buf;
size_t i;
+ void put(char c)
+ {
+ if (buf.length <= i)
+ throw new RangeError(__FILE__, __LINE__);
+
+ buf[i] = c;
+ i += 1;
+ }
void put(dchar c)
{
char[4] enc;
assert(u == v);
}
+@safe unittest // https://issues.dlang.org/show_bug.cgi?id=23488
+{
+ static struct R
+ {
+ string s = "Ü";
+ bool empty() { return s.length == 0; }
+ char front() { return s[0]; }
+ void popFront() { s = s[1 .. $]; }
+ }
+ char[2] buf;
+ assert(sformat(buf, "%s", R()) == "Ü");
+}
+
version (StdUnittest)
private void formatReflectTest(T)(ref T val, string fmt, string formatted, string fn = __FILE__, size_t ln = __LINE__)
{
writer.formatValue(a, spec);
assert(writer.data == "0");
}
+
+// https://issues.dlang.org/show_bug.cgi?id=23400
+@safe pure unittest
+{
+ import std.range : nullSink;
+ import std.format.spec : singleSpec;
+
+ static struct S
+ {
+ // non-const opEquals method
+ bool opEquals(S rhs) { return false; }
+ }
+
+ enum E { a = S() }
+
+ E e;
+ auto writer = nullSink;
+ const spec = singleSpec("%s");
+ writer.formatValue(e, spec);
+}
import std.format : format;
enum fmt = "getopt validator: %s (at position %d)";
- enum isReceiver(T) = isPointer!T || (is(T == function)) || (is(T == delegate));
+ enum isReceiver(T) = is(T : U*, U) || (is(T == function)) || (is(T == delegate));
enum isOptionStr(T) = isSomeString!T || isSomeChar!T;
auto validator()
version (D_InlineAsm_X86) version = InlineAsm_X86_Any;
version (D_InlineAsm_X86_64) version = InlineAsm_X86_Any;
-version (InlineAsm_X86_Any) version = InlineAsm_X87;
-version (InlineAsm_X87)
-{
- static assert(real.mant_dig == 64);
- version (CRuntime_Microsoft) version = InlineAsm_X87_MSVC;
-}
-
version (X86_64) version = StaticallyHaveSSE;
version (X86) version (OSX) version = StaticallyHaveSSE;
version (IeeeFlagsSupport) version = FloatingPointControlSupport;
}
-version (GNU)
-{
- // The compiler can unexpectedly rearrange floating point operations and
- // access to the floating point status flags when optimizing. This means
- // ieeeFlags tests cannot be reliably checked in optimized code.
- // See https://github.com/ldc-developers/ldc/issues/888
-}
-else
-{
- version = IeeeFlagsUnittest;
- version = FloatingPointControlUnittest;
-}
-
version (IeeeFlagsSupport)
{
}
///
-version (IeeeFlagsUnittest)
+version (StdDdoc)
@safe unittest
{
import std.math.traits : isNaN;
static void func() {
int a = 10 * 10;
}
- pragma(inline, false) static void blockopt(ref real x) {}
real a = 3.5;
// Set all the flags to zero
resetIeeeFlags();
assert(!ieeeFlags.divByZero);
- blockopt(a); // avoid constant propagation by the optimizer
// Perform a division by zero.
a /= 0.0L;
assert(a == real.infinity);
assert(ieeeFlags.divByZero);
- blockopt(a); // avoid constant propagation by the optimizer
// Create a NaN
a *= 0.0L;
assert(ieeeFlags.invalid);
assert(ieeeFlags == f);
}
-version (IeeeFlagsUnittest)
+@safe unittest
+{
+ import std.math.traits : isNaN;
+
+ static void func() {
+ int a = 10 * 10;
+ }
+ real a = 3.5;
+ // Set all the flags to zero
+ resetIeeeFlags();
+ assert(!ieeeFlags.divByZero);
+ // Perform a division by zero.
+ a = forceDivOp(a, 0.0L);
+ assert(a == real.infinity);
+ assert(ieeeFlags.divByZero);
+ // Create a NaN
+ a = forceMulOp(a, 0.0L);
+ assert(ieeeFlags.invalid);
+ assert(isNaN(a));
+
+ // Check that calling func() has no effect on the
+ // status flags.
+ IeeeFlags f = ieeeFlags;
+ func();
+ assert(ieeeFlags == f);
+}
+
@safe unittest
{
import std.meta : AliasSeq;
static foreach (T; AliasSeq!(float, double, real))
{{
- T x; /* Needs to be here to trick -O. It would optimize away the
- calculations if x were local to the function literals. */
+ T x; // Needs to be here to avoid `call without side effects` warning.
auto tests = [
Test(
- () { x = 1; x += 0.1L; },
+ () { x = forceAddOp!T(1, 0.1L); },
() => ieeeFlags.inexact
),
Test(
- () { x = T.min_normal; x /= T.max; },
+ () { x = forceDivOp!T(T.min_normal, T.max); },
() => ieeeFlags.underflow
),
Test(
- () { x = T.max; x += T.max; },
+ () { x = forceAddOp!T(T.max, T.max); },
() => ieeeFlags.overflow
),
Test(
- () { x = 1; x /= 0; },
+ () { x = forceDivOp!T(1, 0); },
() => ieeeFlags.divByZero
),
Test(
- () { x = 0; x /= 0; },
+ () { x = forceDivOp!T(0, 0); },
() => ieeeFlags.invalid
)
];
}
///
+version (StdDdoc)
@safe unittest
{
- pragma(inline, false) static void blockopt(ref real x) {}
resetIeeeFlags();
real a = 3.5;
- blockopt(a); // avoid constant propagation by the optimizer
a /= 0.0L;
- blockopt(a); // avoid constant propagation by the optimizer
+ assert(a == real.infinity);
+ assert(ieeeFlags.divByZero);
+
+ resetIeeeFlags();
+ assert(!ieeeFlags.divByZero);
+}
+
+@safe unittest
+{
+ resetIeeeFlags();
+ real a = 3.5;
+ a = forceDivOp(a, 0.0L);
assert(a == real.infinity);
assert(ieeeFlags.divByZero);
}
///
+version (StdDdoc)
@safe nothrow unittest
{
import std.math.traits : isNaN;
- pragma(inline, false) static void blockopt(ref real x) {}
resetIeeeFlags();
real a = 3.5;
- blockopt(a); // avoid constant propagation by the optimizer
a /= 0.0L;
assert(a == real.infinity);
assert(ieeeFlags.divByZero);
- blockopt(a); // avoid constant propagation by the optimizer
a *= 0.0L;
assert(isNaN(a));
assert(ieeeFlags.invalid);
}
+@safe nothrow unittest
+{
+ import std.math.traits : isNaN;
+
+ resetIeeeFlags();
+ real a = 3.5;
+
+ a = forceDivOp(a, 0.0L);
+ assert(a == real.infinity);
+ assert(ieeeFlags.divByZero);
+
+ a = forceMulOp(a, 0.0L);
+ assert(isNaN(a));
+ assert(ieeeFlags.invalid);
+}
+
} // IeeeFlagsSupport
}
///
-version (FloatingPointControlUnittest)
@safe unittest
{
import std.math.rounding : lrint;
ensureDefaults();
}
-version (FloatingPointControlUnittest)
@safe unittest // rounding
{
import std.meta : AliasSeq;
static T addRound(T)(uint rm)
{
- pragma(inline, false) static void blockopt(ref T x) {}
pragma(inline, false);
FloatingPointControl fpctrl;
fpctrl.rounding = rm;
T x = 1;
- blockopt(x); // avoid constant propagation by the optimizer
- x += 0.1L;
+ x = forceAddOp(x, 0.1L);
return x;
}
static T subRound(T)(uint rm)
{
- pragma(inline, false) static void blockopt(ref T x) {}
pragma(inline, false);
FloatingPointControl fpctrl;
fpctrl.rounding = rm;
T x = -1;
- blockopt(x); // avoid constant propagation by the optimizer
- x -= 0.1L;
+ x = forceSubOp(x, 0.1L);
return x;
}
}}
}
+} // FloatingPointControlSupport
+
+version (StdUnittest)
+{
+ // These helpers are intended to avoid constant propagation by the optimizer.
+ pragma(inline, false) private @safe
+ {
+ T forceAddOp(T)(T x, T y) { return x + y; }
+ T forceSubOp(T)(T x, T y) { return x - y; }
+ T forceMulOp(T)(T x, T y) { return x * y; }
+ T forceDivOp(T)(T x, T y) { return x / y; }
+ }
}
for (; environ[i] != null; ++i)
{
assert(e2[i] != null);
- import core.stdc.string;
+ import core.stdc.string : strcmp;
assert(strcmp(e2[i], environ[i]) == 0);
}
assert(e2[i] == null);
// Pipes
void testPipes(Config config)
{
- import std.file, std.uuid, core.thread, std.exception;
+ import std.file : tempDir, exists, remove;
+ import std.uuid : randomUUID;
+ import std.exception : collectException;
auto pipei = pipe();
auto pipeo = pipe();
auto pipee = pipe();
// Files
void testFiles(Config config)
{
- import std.ascii, std.file, std.uuid, core.thread, std.exception;
+ import std.ascii : newline;
+ import std.file : tempDir, exists, remove, readText, write;
+ import std.uuid : randomUUID;
+ import std.exception : collectException;
auto pathi = buildPath(tempDir(), randomUUID().toString());
auto patho = buildPath(tempDir(), randomUUID().toString());
auto pathe = buildPath(tempDir(), randomUUID().toString());
- std.file.write(pathi, "INPUT"~std.ascii.newline);
+ write(pathi, "INPUT" ~ newline);
auto filei = File(pathi, "r");
auto fileo = File(patho, "w");
auto filee = File(pathe, "w");
alias fun = Fun[0];
enum returnByRef_ = (functionAttributes!fun & FunctionAttribute.ref_) ? true : false;
+
+ import std.traits : hasIndirections;
+ static if (!hasIndirections!(ReturnType!fun))
+ alias RetType = Unqual!(ReturnType!fun);
+ else
+ alias RetType = ReturnType!fun;
+
static if (returnByRef_)
- ReturnType!fun *elem_;
+ RetType *elem_;
else
- ReturnType!fun elem_;
+ RetType elem_;
public:
/// Range primitives
enum empty = false;
assert(g.front == f + 5);
}
+// https://issues.dlang.org/show_bug.cgi?id=23319
+@safe pure nothrow unittest
+{
+ auto b = generate!(() => const(int)(42));
+ assert(b.front == 42);
+}
+
/**
Repeats the given forward range ad infinitum. If the original range is
infinite (fact that would make `Cycle` the identity application),
assert(!empty);
++current;
}
+ @property auto save() { return this; }
}
return Result(begin, end);
}
assert(i2.equal([3, 4, 0, 1 ]));
}
+// https://issues.dlang.org/show_bug.cgi?id=23453
+@safe unittest
+{
+ auto r = iota('a', 'z');
+ static assert(isForwardRange!(typeof(r)));
+}
+
/**
Options for the $(LREF FrontTransversal) and $(LREF Transversal) ranges
(below).
AddressFamily _family;
version (Windows)
- bool _blocking = false; /// Property to get or set whether the socket is blocking or nonblocking.
+ bool _blocking = true; /// Property to get or set whether the socket is blocking or nonblocking.
// The WinSock timeouts seem to be effectively skewed by a constant
// offset of about half a second (value in milliseconds). This has
{
if (runSlowTests)
softUnittest({
- import std.datetime.stopwatch;
- import std.typecons;
+ import std.datetime.stopwatch : StopWatch;
+ import std.typecons : Yes;
enum msecs = 1000;
auto pair = socketPair();
- auto sock = pair[0];
- sock.setOption(SocketOptionLevel.SOCKET,
+ auto testSock = pair[0];
+ testSock.setOption(SocketOptionLevel.SOCKET,
SocketOption.RCVTIMEO, dur!"msecs"(msecs));
auto sw = StopWatch(Yes.autoStart);
ubyte[1] buf;
- sock.receive(buf);
+ testSock.receive(buf);
sw.stop();
Duration readBack = void;
- sock.getOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, readBack);
+ testSock.getOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, readBack);
assert(readBack.total!"msecs" == msecs);
assert(sw.peek().total!"msecs" > msecs - 100 && sw.peek().total!"msecs" < msecs + 100);
}
/**
+ * Releases the underlying socket handle from the Socket object. Once it
+ * is released, you cannot use the Socket object's methods anymore. This
+ * also means the Socket destructor will no longer close the socket - it
+ * becomes your responsibility.
+ *
+ * To get the handle without releasing it, use the `handle` property.
+ */
+ @property socket_t release() pure nothrow @nogc
+ {
+ auto h = sock;
+ this.sock = socket_t.init;
+ return h;
+ }
+
+ /**
* Get/set socket's blocking flag.
*
* When a socket is blocking, calls to receive(), accept(), and send()
import std.meta : allSatisfy;
import std.range : ElementEncodingType, empty, front, isBidirectionalRange,
isInputRange, isSomeFiniteCharInputRange, put;
-import std.traits : isSomeChar, isSomeString, Unqual, isPointer;
+import std.traits : isSomeChar, isSomeString, Unqual;
import std.typecons : Flag, No, Yes;
/++
_name = name;
}
- @system unittest // Test changing filename
+ @safe unittest // Test changing filename
{
import std.exception : assertThrown, assertNotThrown;
static import std.file;
version (CRuntime_DigitalMars) {} else // Not implemented
version (CRuntime_Microsoft) {} else // Not implemented
- @system unittest // Test changing mode
+ @safe unittest // Test changing mode
{
import std.exception : assertThrown, assertNotThrown;
static import std.file;
}
---
*/
- S readln(S = string)(dchar terminator = '\n')
+ S readln(S = string)(dchar terminator = '\n') @safe
if (isSomeString!S)
{
Unqual!(ElementEncodingType!S)[] buf;
readln(buf, terminator);
- return cast(S) buf;
+ return (() @trusted => cast(S) buf)();
}
- @system unittest
+ @safe unittest
{
import std.algorithm.comparison : equal;
static import std.file;
}}
}
- @system unittest
+ @safe unittest
{
static import std.file;
import std.typecons : Tuple;
This is actually what $(LREF byLine) does internally, so its usage
is recommended if you want to process a complete file.
*/
- size_t readln(C)(ref C[] buf, dchar terminator = '\n')
+ size_t readln(C)(ref C[] buf, dchar terminator = '\n') @safe
if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum))
{
import std.exception : enforce;
}
}
- @system unittest
+ @safe unittest
{
- // @system due to readln
static import std.file;
auto deleteme = testFilename();
std.file.write(deleteme, "123\n456789");
}
// https://issues.dlang.org/show_bug.cgi?id=15293
- @system unittest
+ @safe unittest
{
// @system due to readln
static import std.file;
}
/** ditto */
- size_t readln(C, R)(ref C[] buf, R terminator)
+ size_t readln(C, R)(ref C[] buf, R terminator) @safe
if (isSomeChar!C && is(Unqual!C == C) && !is(C == enum) &&
isBidirectionalRange!R && is(typeof(terminator.front == dchar.init)))
{
return buf.length;
}
- @system unittest
+ @safe unittest
{
static import std.file;
import std.typecons : Tuple;
assert(f.tell == 0);
}
-@system unittest
+@safe unittest
{
- // @system due to readln
static import std.file;
import std.range : chain, only, repeat;
import std.range.primitives : isOutputRange;
}
/** Convenience functions that throw an `StdioException`. */
- static void opCall(string msg)
+ static void opCall(string msg) @safe
{
throw new StdioException(msg);
}
/// ditto
- static void opCall()
+ static void opCall() @safe
{
throw new StdioException(null, core.stdc.errno.errno);
}
size_t pos;
bool safeAppend = false;
- void initialize(char[] b)
+ void initialize(char[] b) @safe
{
buf = b;
pos = 0;
foreach (c; ubuf)
buf.ptr[pos++] = c;
}
- void putonly(char[] b) @trusted
+ void putonly(const char[] b) @trusted
{
import core.stdc.string : memcpy;
assert(pos == 0); // assume this is the only put call
}
}
-// Private implementation of readln
-private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation)
+private struct LockedFile
{
- version (DIGITAL_MARS_STDIO)
+ private @system _iobuf* fp;
+
+ this(FILE* fps) @trusted
{
_FLOCK(fps);
- scope(exit) _FUNLOCK(fps);
+ // Since fps is now locked, we can cast away shared
+ fp = cast(_iobuf*) fps;
+ }
+
+ @disable this();
+ @disable this(this);
+ @disable void opAssign(LockedFile);
- /* Since fps is now locked, we can create an "unshared" version
- * of fp.
- */
- auto fp = cast(_iobuf*) fps;
+ // these use unlocked fgetc calls
+ @trusted fgetc() { return _FGETC(fp); }
+ @trusted fgetwc() { return _FGETWC(fp); }
+ ~this() @trusted
+ {
+ _FUNLOCK(cast(FILE*) fp);
+ }
+}
+
+@safe unittest
+{
+ void f() @safe
+ {
+ FILE* fps;
+ auto lf = LockedFile(fps);
+ static assert(!__traits(compiles, lf = LockedFile(fps)));
+ version (ShouldFail)
+ {
+ lf.fps = null; // error with -preview=systemVariables
+ }
+ }
+}
+
+// Private implementation of readln
+private size_t readlnImpl(FILE* fps, ref char[] buf, dchar terminator, File.Orientation orientation) @safe
+{
+ version (DIGITAL_MARS_STDIO)
+ return () @trusted {
+ auto lf = LockedFile(fps);
ReadlnAppender app;
app.initialize(buf);
- if (__fhnd_info[fp._file] & FHND_WCHAR)
+ if (__fhnd_info[lf.fp._file] & FHND_WCHAR)
{ /* Stream is in wide characters.
* Read them and convert to chars.
*/
static assert(wchar_t.sizeof == 2);
- for (int c = void; (c = _FGETWC(fp)) != -1; )
+ for (int c = void; (c = lf.fgetwc()) != -1; )
{
if ((c & ~0x7F) == 0)
{
if (c >= 0xD800 && c <= 0xDBFF)
{
int c2 = void;
- if ((c2 = _FGETWC(fp)) != -1 ||
+ if ((c2 = lf.fgetwc()) != -1 ||
c2 < 0xDC00 && c2 > 0xDFFF)
{
StdioException("unpaired UTF-16 surrogate");
if (ferror(fps))
StdioException();
}
-
- else if (fp._flag & _IONBF)
+ else if (lf.fp._flag & _IONBF)
{
/* Use this for unbuffered I/O, when running
* across buffer boundaries, or for any but the common
*/
L1:
int c;
- while ((c = _FGETC(fp)) != -1)
+ while ((c = lf.fgetc()) != -1)
{
app.putchar(cast(char) c);
if (c == terminator)
}
else
{
- int u = fp._cnt;
- char* p = fp._ptr;
+ int u = lf.fp._cnt;
+ char* p = lf.fp._ptr;
int i;
- if (fp._flag & _IOTRAN)
+ if (lf.fp._flag & _IOTRAN)
{ /* Translated mode ignores \r and treats ^Z as end-of-file
*/
char c;
}
app.putonly(p[0 .. i]);
}
- fp._cnt -= i;
- fp._ptr += i;
+ lf.fp._cnt -= i;
+ lf.fp._ptr += i;
}
buf = app.data;
return buf.length;
- }
+ }();
else version (MICROSOFT_STDIO)
{
- _FLOCK(fps);
- scope(exit) _FUNLOCK(fps);
-
- /* Since fps is now locked, we can create an "unshared" version
- * of fp.
- */
- auto fp = cast(_iobuf*) fps;
+ auto lf = LockedFile(fps);
ReadlnAppender app;
app.initialize(buf);
int c;
- while ((c = _FGETC(fp)) != -1)
+ while ((c = lf.fgetc()) != -1)
{
app.putchar(cast(char) c);
if (c == terminator)
}
else static if (__traits(compiles, core.sys.posix.stdio.getdelim))
{
- import core.stdc.stdlib : free;
- import core.stdc.wchar_ : fwide;
-
if (orientation == File.Orientation.wide)
{
+ import core.stdc.wchar_ : fwide;
+
+ auto lf = LockedFile(fps);
/* Stream is in wide characters.
* Read them and convert to chars.
*/
- _FLOCK(fps);
- scope(exit) _FUNLOCK(fps);
- auto fp = cast(_iobuf*) fps;
version (Windows)
{
buf.length = 0;
- for (int c = void; (c = _FGETWC(fp)) != -1; )
+ for (int c = void; (c = lf.fgetwc()) != -1; )
{
if ((c & ~0x7F) == 0)
{ buf ~= c;
if (c >= 0xD800 && c <= 0xDBFF)
{
int c2 = void;
- if ((c2 = _FGETWC(fp)) != -1 ||
+ if ((c2 = lf.fgetwc()) != -1 ||
c2 < 0xDC00 && c2 > 0xDFFF)
{
StdioException("unpaired UTF-16 surrogate");
encode(buf, c);
}
}
- if (ferror(fp))
+ if (ferror(fps))
StdioException();
return buf.length;
}
else version (Posix)
{
buf.length = 0;
- for (int c; (c = _FGETWC(fp)) != -1; )
+ for (int c; (c = lf.fgetwc()) != -1; )
{
import std.utf : encode;
static assert(0);
}
}
+ return () @trusted {
+ import core.stdc.stdlib : free;
- static char *lineptr = null;
- static size_t n = 0;
- scope(exit)
- {
- if (n > 128 * 1024)
+ static char *lineptr = null;
+ static size_t n = 0;
+ scope(exit)
{
- // Bound memory used by readln
- free(lineptr);
- lineptr = null;
- n = 0;
+ if (n > 128 * 1024)
+ {
+ // Bound memory used by readln
+ free(lineptr);
+ lineptr = null;
+ n = 0;
+ }
}
- }
- auto s = core.sys.posix.stdio.getdelim(&lineptr, &n, terminator, fps);
- if (s < 0)
- {
- if (ferror(fps))
- StdioException();
- buf.length = 0; // end of file
- return 0;
- }
+ const s = core.sys.posix.stdio.getdelim(&lineptr, &n, terminator, fps);
+ if (s < 0)
+ {
+ if (ferror(fps))
+ StdioException();
+ buf.length = 0; // end of file
+ return 0;
+ }
- if (s <= buf.length)
- {
- buf = buf[0 .. s];
- buf[] = lineptr[0 .. s];
- }
- else
- {
- buf = lineptr[0 .. s].dup;
- }
- return s;
+ const line = lineptr[0 .. s];
+ if (s <= buf.length)
+ {
+ buf = buf[0 .. s];
+ buf[] = line;
+ }
+ else
+ {
+ buf = line.dup;
+ }
+ return s;
+ }();
}
else // version (NO_GETDELIM)
{
import core.stdc.wchar_ : fwide;
- _FLOCK(fps);
- scope(exit) _FUNLOCK(fps);
- auto fp = cast(_iobuf*) fps;
+ auto lf = LockedFile(fps);
if (orientation == File.Orientation.wide)
{
/* Stream is in wide characters.
version (Windows)
{
buf.length = 0;
- for (int c; (c = _FGETWC(fp)) != -1; )
+ for (int c; (c = lf.fgetwc()) != -1; )
{
if ((c & ~0x7F) == 0)
{ buf ~= c;
if (c >= 0xD800 && c <= 0xDBFF)
{
int c2 = void;
- if ((c2 = _FGETWC(fp)) != -1 ||
+ if ((c2 = lf.fgetwc()) != -1 ||
c2 < 0xDC00 && c2 > 0xDFFF)
{
StdioException("unpaired UTF-16 surrogate");
encode(buf, c);
}
}
- if (ferror(fp))
+ if (ferror(fps))
StdioException();
return buf.length;
}
{
import std.utf : encode;
buf.length = 0;
- for (int c; (c = _FGETWC(fp)) != -1; )
+ for (int c; (c = lf.fgetwc()) != -1; )
{
if ((c & ~0x7F) == 0)
buf ~= cast(char) c;
// First, fill the existing buffer
for (size_t bufPos = 0; bufPos < buf.length; )
{
- immutable c = _FGETC(fp);
+ immutable c = lf.fgetc();
if (c == -1)
{
buf.length = bufPos;
}
}
// Then, append to it
- for (int c; (c = _FGETC(fp)) != -1; )
+ for (int c; (c = lf.fgetc()) != -1; )
{
buf ~= cast(char) c;
if (c == terminator)
// An array that maps caseIds to handler indices ("hids").
enum matches = ()
{
- size_t[numCases] matches;
+ size_t[numCases] result;
// Workaround for https://issues.dlang.org/show_bug.cgi?id=19561
- foreach (ref match; matches)
+ foreach (ref match; result)
{
match = noMatch;
}
{
static if (canMatch!(handler, valueTypes!caseId))
{
- if (matches[caseId] == noMatch)
+ if (result[caseId] == noMatch)
{
- matches[caseId] = hid;
+ result[caseId] = hid;
}
}
}
}
- return matches;
+ return result;
}();
import std.algorithm.searching : canFind;
);
}
}
- else static if (isPointer!T)
+ else static if (is(T : U*, U))
{
enum fqnType = chain!(
- fqnType!(PointerTarget!T, qualifiers) ~ "*"
+ fqnType!(U, qualifiers) ~ "*"
);
}
else static if (is(T : __vector(V[N]), V, size_t N))
{
static if (__traits(hasMember, T, member))
{
- static if (isPointer!T)
- alias U = PointerTarget!T;
+ static if (is(T : V*, V))
+ alias U = V;
else
alias U = T;
{
alias Pointify(T) = void*;
- enum isStorageClassImplicitlyConvertible = isImplicitlyConvertible!(
- ModifyTypePreservingTQ!(Pointify, From),
+ enum isStorageClassImplicitlyConvertible = is(
+ ModifyTypePreservingTQ!(Pointify, From) :
ModifyTypePreservingTQ!(Pointify, To) );
}
/**
* Detect whether type `T` is a pointer.
*/
-enum bool isPointer(T) = is(T == U*, U) && __traits(isScalar, T);
+enum bool isPointer(T) = is(T == U*, U);
///
@safe unittest
static assert(__traits(compiles, getSymbolsByUDA!(mixin(__MODULE__), "Issue20054")));
}
+private template isAliasSeq(Args...)
+{
+ static if (Args.length != 1)
+ enum isAliasSeq = true;
+ else
+ enum isAliasSeq = false;
+}
+
private template getSymbolsByUDAImpl(alias symbol, alias attribute, names...)
{
import std.meta : Alias, AliasSeq, Filter;
alias member = __traits(getMember, symbol, names[0]);
// Filtering not compiled members such as alias of basic types.
- static if (!__traits(compiles, hasUDA!(member, attribute)))
+ static if (isAliasSeq!member || isType!member)
{
alias getSymbolsByUDAImpl = tail;
}
- // Get overloads for functions, in case different overloads have different sets of UDAs.
- else static if (isFunction!member)
+ // If a symbol is overloaded, get UDAs for each overload (including templated overlaods).
+ else static if (__traits(getOverloads, symbol, names[0], true).length > 0)
{
enum hasSpecificUDA(alias member) = hasUDA!(member, attribute);
alias overloadsWithUDA = Filter!(hasSpecificUDA, __traits(getOverloads, symbol, names[0]));
}
// handle each overload set
- private string generateCodeForOverloadSet(alias oset)() @property
+ string generateCodeForOverloadSet(alias oset)() @property
{
string code = "";
* "ref int a0, real a1, ..."
*/
static struct GenParams { string imports, params; }
- private GenParams generateParameters(string myFuncInfo, func...)()
+ GenParams generateParameters(string myFuncInfo, func...)()
{
alias STC = ParameterStorageClass;
alias stcs = ParameterStorageClassTuple!(func);
// Returns D code which enumerates n parameter variables using comma as the
// separator. "a0, a1, a2, a3"
- private string enumerateParameters(size_t n)() @property
+ string enumerateParameters(size_t n)() @property
{
string params = "";
{
void test(size_t size)
{
- import core.stdc.stdlib;
+ import core.stdc.stdlib : alloca;
cast(void) alloca(size);
alignmentTest();
}
}
Base opCast(B)() const
- if (isImplicitlyConvertible!(Base, B))
+ if (is(Base : B))
{
return mValue;
}
{
if (casefold_)
{
- auto range = simpleCaseFoldings(ch);
- foreach (v; range)
+ auto foldings = simpleCaseFoldings(ch);
+ foreach (v; foldings)
set |= v;
}
else
import core.exception : UnicodeException;
import std.meta : AliasSeq;
import std.range;
-import std.traits : isAutodecodableString, isConvertibleToString, isPointer,
+import std.traits : isAutodecodableString, isConvertibleToString,
isSomeChar, isSomeString, isStaticArray, Unqual;
import std.typecons : Flag, Yes, No;
collection cycle and cause a nasty bug when the C code tries to use it.
+/
template toUTFz(P)
-if (isPointer!P && isSomeChar!(typeof(*P.init)))
+if (is(P : C*, C) && isSomeChar!C)
{
P toUTFz(S)(S str) @safe pure
if (isSomeString!S)
if (i++ > 0)
break;
- import core.memory;
+ import core.memory : GC;
GC.collect();
}
assert(i == 2);