diff --git a/src/backend/rtlsym.h b/src/backend/rtlsym.h index 948e80dc80b3..65ed34f31987 100644 --- a/src/backend/rtlsym.h +++ b/src/backend/rtlsym.h @@ -93,6 +93,8 @@ SYMBOL_MARS(ARRAYCATT, FLfunc,FREGSAVED,"_d_arraycatT", 0, t) \ SYMBOL_MARS(ARRAYCATNT, FLfunc,FREGSAVED,"_d_arraycatnT", 0, t) \ SYMBOL_MARS(ARRAYAPPENDT, FLfunc,FREGSAVED,"_d_arrayappendT", 0, t) \ SYMBOL_MARS(ARRAYAPPENDCT, FLfunc,FREGSAVED,"_d_arrayappendcT", 0, t) \ +SYMBOL_MARS(ARRAYAPPENDCD, FLfunc,FREGSAVED,"_d_arrayappendcd", 0, t) \ +SYMBOL_MARS(ARRAYAPPENDWD, FLfunc,FREGSAVED,"_d_arrayappendwd", 0, t) \ SYMBOL_MARS(ARRAYSETLENGTHT,FLfunc,FREGSAVED,"_d_arraysetlengthT", 0, t) \ SYMBOL_MARS(ARRAYSETLENGTHIT,FLfunc,FREGSAVED,"_d_arraysetlengthiT", 0, t) \ SYMBOL_MARS(ARRAYCOPY, FLfunc,FREGSAVED,"_d_arraycopy", 0, t) \ diff --git a/src/e2ir.c b/src/e2ir.c index e61f9234f16d..3e1bbb61a6bc 100644 --- a/src/e2ir.c +++ b/src/e2ir.c @@ -2915,15 +2915,28 @@ elem *CatAssignExp::toElem(IRState *irs) Type *tb1 = e1->type->toBasetype(); Type *tb2 = e2->type->toBasetype(); - if (tb1->ty == Tarray || tb2->ty == Tsarray) - { elem *e1; - elem *e2; - elem *ep; + if (tb1->ty == Tarray && tb2->ty == Tdchar && + (tb1->nextOf()->ty == Tchar || tb1->nextOf()->ty == Twchar)) + { // Append dchar to char[] or wchar[] + + elem *e1 = this->e1->toElem(irs); + e1 = el_una(OPaddr, TYnptr, e1); + + elem *e2 = this->e2->toElem(irs); - e1 = this->e1->toElem(irs); + elem *ep = el_params(e2, e1, NULL); + int rtl = (tb1->nextOf()->ty == Tchar) + ? RTLSYM_ARRAYAPPENDCD + : RTLSYM_ARRAYAPPENDWD; + e = el_bin(OPcall, TYdarray, el_var(rtlsym[rtl]), ep); + el_setLoc(e,loc); + } + else if (tb1->ty == Tarray || tb2->ty == Tsarray) + { + elem *e1 = this->e1->toElem(irs); e1 = el_una(OPaddr, TYnptr, e1); - e2 = this->e2->toElem(irs); + elem *e2 = this->e2->toElem(irs); if (tybasic(e2->Ety) == TYstruct || tybasic(e2->Ety) == TYarray) { e2 = el_una(OPstrpar, TYstruct, e2); @@ -2935,23 +2948,13 @@ elem *CatAssignExp::toElem(IRState *irs) if ((tb2->ty == Tarray || tb2->ty == Tsarray) && tb1n->equals(tb2->nextOf()->toBasetype())) { // Append array -#if 1 - ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL); + elem *ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL); e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDT]), ep); -#else - ep = el_params(el_long(TYint, tb1n->size()), e2, e1, NULL); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPEND]), ep); -#endif } else { // Append element -#if 1 - ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL); + elem *ep = el_params(e2, e1, this->e1->type->getTypeInfo(NULL)->toElem(irs), NULL); e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDCT]), ep); -#else - ep = el_params(e2, el_long(TYint, tb1n->size()), e1, NULL); - e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYAPPENDC]), ep); -#endif } el_setLoc(e,loc); } diff --git a/src/expression.c b/src/expression.c index 43e387814109..4711eadac4bf 100644 --- a/src/expression.c +++ b/src/expression.c @@ -456,13 +456,44 @@ void expandTuples(Expressions *exps) Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt) { +#if DMDV1 + /* The first element sets the type + */ + Type *t0 = NULL; + for (size_t i = 0; i < exps->dim; i++) + { Expression *e = (Expression *)exps->data[i]; + + if (!e->type) + { error("%s has no value", e->toChars()); + e = new ErrorExp(); + } + e = resolveProperties(sc, e); + + if (!t0) + t0 = e->type; + else + e = e->implicitCastTo(sc, t0); + exps->data[i] = (void *)e; + } + + if (!t0) + t0 = Type::tvoid; + if (pt) + *pt = t0; + + // Eventually, we want to make this copy-on-write + return exps; +#endif +#if DMDV2 + /* The type is determined by applying ?: to each pair. + */ IntegerExp integerexp(0); CondExp condexp(0, &integerexp, NULL, NULL); Type *t0 = NULL; Expression *e0; int j0; - for (int i = 0; i < exps->dim; i++) + for (size_t i = 0; i < exps->dim; i++) { Expression *e = (Expression *)exps->data[i]; e = resolveProperties(sc, e); @@ -496,7 +527,7 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt if (t0) { - for (int i = 0; i < exps->dim; i++) + for (size_t i = 0; i < exps->dim; i++) { Expression *e = (Expression *)exps->data[i]; e = e->implicitCastTo(sc, t0); exps->data[i] = (void *)e; @@ -509,6 +540,7 @@ Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt // Eventually, we want to make this copy-on-write return exps; +#endif } /**************************************** @@ -8890,10 +8922,15 @@ Expression *CatAssignExp::semantic(Scope *sc) e2->rvalue(); + Type *tb1next = tb1->nextOf(); + if ((tb1->ty == Tarray) && (tb2->ty == Tarray || tb2->ty == Tsarray) && - (e2->implicitConvTo(e1->type) || - tb2->nextOf()->implicitConvTo(tb1->nextOf())) + (e2->implicitConvTo(e1->type) +#if DMDV2 + || tb2->nextOf()->implicitConvTo(tb1next) +#endif + ) ) { // Append array e2 = e2->castTo(sc, e1->type); @@ -8901,18 +8938,30 @@ Expression *CatAssignExp::semantic(Scope *sc) e = this; } else if ((tb1->ty == Tarray) && - e2->implicitConvTo(tb1->nextOf()) + e2->implicitConvTo(tb1next) ) { // Append element - e2 = e2->castTo(sc, tb1->nextOf()); + e2 = e2->castTo(sc, tb1next); type = e1->type; e = this; } + else if (tb1->ty == Tarray && + (tb1next->ty == Tchar || tb1next->ty == Twchar) && + e2->implicitConvTo(Type::tdchar) + ) + { // Append dchar to char[] or wchar[] + e2 = e2->castTo(sc, Type::tdchar); + type = e1->type; + e = this; + + /* Do not allow appending wchar to char[] because if wchar happens + * to be a surrogate pair, nothing good can result. + */ + } else { error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars()); - type = Type::tint32; - e = this; + e = new ErrorExp(); } return e; } @@ -8934,12 +8983,14 @@ Expression *MulAssignExp::semantic(Scope *sc) if (e) return e; +#if DMDV2 if (e1->op == TOKarraylength) { e = ArrayLengthExp::rewriteOpAssign(this); e = e->semantic(sc); return e; } +#endif if (e1->op == TOKslice) { // T[] -= ... @@ -9005,12 +9056,14 @@ Expression *DivAssignExp::semantic(Scope *sc) if (e) return e; +#if DMDV2 if (e1->op == TOKarraylength) { e = ArrayLengthExp::rewriteOpAssign(this); e = e->semantic(sc); return e; } +#endif if (e1->op == TOKslice) { // T[] -= ...