Mercurial > projects > ldc
diff dmd/cast.c @ 19:788401029ecf trunk
[svn r23] * Updated to DMD 1.021
author | lindquist |
---|---|
date | Thu, 04 Oct 2007 03:42:56 +0200 |
parents | c53b6e3fe49a |
children | 61615fa85940 |
line wrap: on
line diff
--- a/dmd/cast.c Thu Oct 04 01:47:53 2007 +0200 +++ b/dmd/cast.c Thu Oct 04 03:42:56 2007 +0200 @@ -658,77 +658,85 @@ Expression *StringExp::castTo(Scope *sc, Type *t) { + /* This follows copy-on-write; any changes to 'this' + * will result in a copy. + * The this->string member is considered immutable. + */ StringExp *se; Type *tb; - int unique; + int copied = 0; //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed); - if (!committed && t->ty == Tpointer && t->next->ty == Tvoid) + if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid) { error("cannot convert string literal to void*"); } + se = this; + if (!committed) + { se = (StringExp *)copy(); + se->committed = 1; + copied = 1; + } + + if (type == t) + { + return se; + } + tb = t->toBasetype(); //printf("\ttype = %s\n", type->toChars()); if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate) return Expression::castTo(sc, t); - se = this; - unique = 0; - if (!committed) + Type *typeb = type->toBasetype(); + if (typeb == tb) { - // Copy when committing the type - void *s; - - s = (unsigned char *)mem.malloc((len + 1) * sz); - memcpy(s, string, (len + 1) * sz); - se = new StringExp(loc, s, len); - se->type = type; - se->sz = sz; - se->committed = 0; - unique = 1; // this is the only instance - } - se->type = type->toBasetype(); - if (tb == se->type) - { se->type = t; - se->committed = 1; + if (!copied) + { se = (StringExp *)copy(); + copied = 1; + } + se->type = t; return se; } if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer) - { se->committed = 1; - goto Lcast; - } - if (se->type->ty != Tsarray && se->type->ty != Tarray && se->type->ty != Tpointer) - { se->committed = 1; + { if (!copied) + { se = (StringExp *)copy(); + copied = 1; + } goto Lcast; } - - if (se->committed == 1) - { - if (se->type->next->size() == tb->next->size()) - { se->type = t; - return se; + if (typeb->ty != Tsarray && typeb->ty != Tarray && typeb->ty != Tpointer) + { if (!copied) + { se = (StringExp *)copy(); + copied = 1; } goto Lcast; } - se->committed = 1; + if (typeb->nextOf()->size() == tb->nextOf()->size()) + { + if (!copied) + { se = (StringExp *)copy(); + copied = 1; + } + if (tb->ty == Tsarray) + goto L2; // handle possible change in static array dimension + se->type = t; + return se; + } - int tfty; - int ttty; - char *p; - size_t u; - unsigned c; - size_t newlen; + if (committed) + goto Lcast; #define X(tf,tt) ((tf) * 256 + (tt)) { OutBuffer buffer; - newlen = 0; - tfty = se->type->next->toBasetype()->ty; - ttty = tb->next->toBasetype()->ty; + size_t newlen = 0; + int tfty = typeb->nextOf()->toBasetype()->ty; + int ttty = tb->nextOf()->toBasetype()->ty; switch (X(tfty, ttty)) { case X(Tchar, Tchar): @@ -737,9 +745,9 @@ break; case X(Tchar, Twchar): - for (u = 0; u < len;) - { - p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); + for (size_t u = 0; u < len;) + { unsigned c; + char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); if (p) error("%s", p); else @@ -750,9 +758,9 @@ goto L1; case X(Tchar, Tdchar): - for (u = 0; u < len;) - { - p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); + for (size_t u = 0; u < len;) + { unsigned c; + char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); if (p) error("%s", p); buffer.write4(c); @@ -762,9 +770,9 @@ goto L1; case X(Twchar,Tchar): - for (u = 0; u < len;) - { - p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); + for (size_t u = 0; u < len;) + { unsigned c; + char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); if (p) error("%s", p); else @@ -775,9 +783,9 @@ goto L1; case X(Twchar,Tdchar): - for (u = 0; u < len;) - { - p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); + for (size_t u = 0; u < len;) + { unsigned c; + char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); if (p) error("%s", p); buffer.write4(c); @@ -787,9 +795,9 @@ goto L1; case X(Tdchar,Tchar): - for (u = 0; u < len; u++) + for (size_t u = 0; u < len; u++) { - c = ((unsigned *)se->string)[u]; + unsigned c = ((unsigned *)se->string)[u]; if (!utf_isValidDchar(c)) error("invalid UCS-32 char \\U%08x", c); else @@ -801,9 +809,9 @@ goto L1; case X(Tdchar,Twchar): - for (u = 0; u < len; u++) + for (size_t u = 0; u < len; u++) { - c = ((unsigned *)se->string)[u]; + unsigned c = ((unsigned *)se->string)[u]; if (!utf_isValidDchar(c)) error("invalid UCS-32 char \\U%08x", c); else @@ -815,22 +823,23 @@ goto L1; L1: - if (!unique) - se = new StringExp(loc, NULL, 0); + if (!copied) + { se = (StringExp *)copy(); + copied = 1; + } se->string = buffer.extractData(); se->len = newlen; - se->sz = tb->next->size(); + se->sz = tb->nextOf()->size(); break; default: - if (se->type->next->size() == tb->next->size()) - { se->type = t; - return se; - } + assert(typeb->nextOf()->size() != tb->nextOf()->size()); goto Lcast; } } #undef X +L2: + assert(copied); // See if need to truncate or extend the literal if (tb->ty == Tsarray) @@ -842,28 +851,18 @@ // Changing dimensions if (dim2 != se->len) { + // Copy when changing the string literal unsigned newsz = se->sz; + void *s; + int d; - if (unique && dim2 < se->len) - { se->len = dim2; - // Add terminating 0 - memset((unsigned char *)se->string + dim2 * newsz, 0, newsz); - } - else - { - // Copy when changing the string literal - void *s; - int d; - - d = (dim2 < se->len) ? dim2 : se->len; - s = (unsigned char *)mem.malloc((dim2 + 1) * newsz); - memcpy(s, se->string, d * newsz); - // Extend with 0, add terminating 0 - memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz); - se = new StringExp(loc, s, dim2); - se->committed = 1; // it now has a firm type - se->sz = newsz; - } + d = (dim2 < se->len) ? dim2 : se->len; + s = (unsigned char *)mem.malloc((dim2 + 1) * newsz); + memcpy(s, se->string, d * newsz); + // Extend with 0, add terminating 0 + memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz); + se->string = s; + se->len = dim2; } } se->type = t; @@ -871,7 +870,7 @@ Lcast: Expression *e = new CastExp(loc, se, t); - e->type = t; + e->type = t; // so semantic() won't be run on e return e; }