mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-09-18 03:17:05 +02:00
[svn r23] * Updated to DMD 1.021
This commit is contained in:
@@ -192,6 +192,28 @@ void AttribDeclaration::toObjFile()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AttribDeclaration::cvMember(unsigned char *p)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
int nwritten = 0;
|
||||||
|
int n;
|
||||||
|
Array *d = include(NULL, NULL);
|
||||||
|
|
||||||
|
if (d)
|
||||||
|
{
|
||||||
|
for (i = 0; i < d->dim; i++)
|
||||||
|
{ Dsymbol *s;
|
||||||
|
|
||||||
|
s = (Dsymbol *)d->data[i];
|
||||||
|
n = s->cvMember(p);
|
||||||
|
if (p)
|
||||||
|
p += n;
|
||||||
|
nwritten += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nwritten;
|
||||||
|
}
|
||||||
|
|
||||||
int AttribDeclaration::hasPointers()
|
int AttribDeclaration::hasPointers()
|
||||||
{
|
{
|
||||||
Array *d = include(NULL, NULL);
|
Array *d = include(NULL, NULL);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ struct AttribDeclaration : Dsymbol
|
|||||||
AttribDeclaration *isAttribDeclaration() { return this; }
|
AttribDeclaration *isAttribDeclaration() { return this; }
|
||||||
|
|
||||||
void toObjFile(); // compile to .obj file
|
void toObjFile(); // compile to .obj file
|
||||||
|
int cvMember(unsigned char *p);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StorageClassDeclaration: AttribDeclaration
|
struct StorageClassDeclaration: AttribDeclaration
|
||||||
|
|||||||
+84
-85
@@ -658,77 +658,85 @@ Expression *NullExp::castTo(Scope *sc, Type *t)
|
|||||||
|
|
||||||
Expression *StringExp::castTo(Scope *sc, Type *t)
|
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;
|
StringExp *se;
|
||||||
Type *tb;
|
Type *tb;
|
||||||
int unique;
|
int copied = 0;
|
||||||
|
|
||||||
//printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed);
|
//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*");
|
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();
|
tb = t->toBasetype();
|
||||||
//printf("\ttype = %s\n", type->toChars());
|
//printf("\ttype = %s\n", type->toChars());
|
||||||
if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate)
|
if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate)
|
||||||
return Expression::castTo(sc, t);
|
return Expression::castTo(sc, t);
|
||||||
|
|
||||||
se = this;
|
Type *typeb = type->toBasetype();
|
||||||
unique = 0;
|
if (typeb == tb)
|
||||||
if (!committed)
|
|
||||||
{
|
{
|
||||||
// Copy when committing the type
|
if (!copied)
|
||||||
void *s;
|
{ se = (StringExp *)copy();
|
||||||
|
copied = 1;
|
||||||
s = (unsigned char *)mem.malloc((len + 1) * sz);
|
}
|
||||||
memcpy(s, string, (len + 1) * sz);
|
se->type = t;
|
||||||
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;
|
|
||||||
return se;
|
return se;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer)
|
if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer)
|
||||||
{ se->committed = 1;
|
{ if (!copied)
|
||||||
|
{ se = (StringExp *)copy();
|
||||||
|
copied = 1;
|
||||||
|
}
|
||||||
goto Lcast;
|
goto Lcast;
|
||||||
}
|
}
|
||||||
if (se->type->ty != Tsarray && se->type->ty != Tarray && se->type->ty != Tpointer)
|
if (typeb->ty != Tsarray && typeb->ty != Tarray && typeb->ty != Tpointer)
|
||||||
{ se->committed = 1;
|
{ if (!copied)
|
||||||
goto Lcast;
|
{ se = (StringExp *)copy();
|
||||||
}
|
copied = 1;
|
||||||
|
|
||||||
if (se->committed == 1)
|
|
||||||
{
|
|
||||||
if (se->type->next->size() == tb->next->size())
|
|
||||||
{ se->type = t;
|
|
||||||
return se;
|
|
||||||
}
|
}
|
||||||
goto Lcast;
|
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;
|
if (committed)
|
||||||
int ttty;
|
goto Lcast;
|
||||||
char *p;
|
|
||||||
size_t u;
|
|
||||||
unsigned c;
|
|
||||||
size_t newlen;
|
|
||||||
|
|
||||||
#define X(tf,tt) ((tf) * 256 + (tt))
|
#define X(tf,tt) ((tf) * 256 + (tt))
|
||||||
{
|
{
|
||||||
OutBuffer buffer;
|
OutBuffer buffer;
|
||||||
newlen = 0;
|
size_t newlen = 0;
|
||||||
tfty = se->type->next->toBasetype()->ty;
|
int tfty = typeb->nextOf()->toBasetype()->ty;
|
||||||
ttty = tb->next->toBasetype()->ty;
|
int ttty = tb->nextOf()->toBasetype()->ty;
|
||||||
switch (X(tfty, ttty))
|
switch (X(tfty, ttty))
|
||||||
{
|
{
|
||||||
case X(Tchar, Tchar):
|
case X(Tchar, Tchar):
|
||||||
@@ -737,9 +745,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case X(Tchar, Twchar):
|
case X(Tchar, Twchar):
|
||||||
for (u = 0; u < len;)
|
for (size_t u = 0; u < len;)
|
||||||
{
|
{ unsigned c;
|
||||||
p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
|
char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
|
||||||
if (p)
|
if (p)
|
||||||
error("%s", p);
|
error("%s", p);
|
||||||
else
|
else
|
||||||
@@ -750,9 +758,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
|||||||
goto L1;
|
goto L1;
|
||||||
|
|
||||||
case X(Tchar, Tdchar):
|
case X(Tchar, Tdchar):
|
||||||
for (u = 0; u < len;)
|
for (size_t u = 0; u < len;)
|
||||||
{
|
{ unsigned c;
|
||||||
p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
|
char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c);
|
||||||
if (p)
|
if (p)
|
||||||
error("%s", p);
|
error("%s", p);
|
||||||
buffer.write4(c);
|
buffer.write4(c);
|
||||||
@@ -762,9 +770,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
|||||||
goto L1;
|
goto L1;
|
||||||
|
|
||||||
case X(Twchar,Tchar):
|
case X(Twchar,Tchar):
|
||||||
for (u = 0; u < len;)
|
for (size_t u = 0; u < len;)
|
||||||
{
|
{ unsigned c;
|
||||||
p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
|
char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
|
||||||
if (p)
|
if (p)
|
||||||
error("%s", p);
|
error("%s", p);
|
||||||
else
|
else
|
||||||
@@ -775,9 +783,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
|||||||
goto L1;
|
goto L1;
|
||||||
|
|
||||||
case X(Twchar,Tdchar):
|
case X(Twchar,Tdchar):
|
||||||
for (u = 0; u < len;)
|
for (size_t u = 0; u < len;)
|
||||||
{
|
{ unsigned c;
|
||||||
p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
|
char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c);
|
||||||
if (p)
|
if (p)
|
||||||
error("%s", p);
|
error("%s", p);
|
||||||
buffer.write4(c);
|
buffer.write4(c);
|
||||||
@@ -787,9 +795,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
|||||||
goto L1;
|
goto L1;
|
||||||
|
|
||||||
case X(Tdchar,Tchar):
|
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))
|
if (!utf_isValidDchar(c))
|
||||||
error("invalid UCS-32 char \\U%08x", c);
|
error("invalid UCS-32 char \\U%08x", c);
|
||||||
else
|
else
|
||||||
@@ -801,9 +809,9 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
|||||||
goto L1;
|
goto L1;
|
||||||
|
|
||||||
case X(Tdchar,Twchar):
|
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))
|
if (!utf_isValidDchar(c))
|
||||||
error("invalid UCS-32 char \\U%08x", c);
|
error("invalid UCS-32 char \\U%08x", c);
|
||||||
else
|
else
|
||||||
@@ -815,22 +823,23 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
|||||||
goto L1;
|
goto L1;
|
||||||
|
|
||||||
L1:
|
L1:
|
||||||
if (!unique)
|
if (!copied)
|
||||||
se = new StringExp(loc, NULL, 0);
|
{ se = (StringExp *)copy();
|
||||||
|
copied = 1;
|
||||||
|
}
|
||||||
se->string = buffer.extractData();
|
se->string = buffer.extractData();
|
||||||
se->len = newlen;
|
se->len = newlen;
|
||||||
se->sz = tb->next->size();
|
se->sz = tb->nextOf()->size();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (se->type->next->size() == tb->next->size())
|
assert(typeb->nextOf()->size() != tb->nextOf()->size());
|
||||||
{ se->type = t;
|
|
||||||
return se;
|
|
||||||
}
|
|
||||||
goto Lcast;
|
goto Lcast;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef X
|
#undef X
|
||||||
|
L2:
|
||||||
|
assert(copied);
|
||||||
|
|
||||||
// See if need to truncate or extend the literal
|
// See if need to truncate or extend the literal
|
||||||
if (tb->ty == Tsarray)
|
if (tb->ty == Tsarray)
|
||||||
@@ -842,28 +851,18 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
|||||||
// Changing dimensions
|
// Changing dimensions
|
||||||
if (dim2 != se->len)
|
if (dim2 != se->len)
|
||||||
{
|
{
|
||||||
|
// Copy when changing the string literal
|
||||||
unsigned newsz = se->sz;
|
unsigned newsz = se->sz;
|
||||||
|
void *s;
|
||||||
|
int d;
|
||||||
|
|
||||||
if (unique && dim2 < se->len)
|
d = (dim2 < se->len) ? dim2 : se->len;
|
||||||
{ se->len = dim2;
|
s = (unsigned char *)mem.malloc((dim2 + 1) * newsz);
|
||||||
// Add terminating 0
|
memcpy(s, se->string, d * newsz);
|
||||||
memset((unsigned char *)se->string + dim2 * newsz, 0, newsz);
|
// Extend with 0, add terminating 0
|
||||||
}
|
memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz);
|
||||||
else
|
se->string = s;
|
||||||
{
|
se->len = dim2;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
se->type = t;
|
se->type = t;
|
||||||
@@ -871,7 +870,7 @@ Expression *StringExp::castTo(Scope *sc, Type *t)
|
|||||||
|
|
||||||
Lcast:
|
Lcast:
|
||||||
Expression *e = new CastExp(loc, se, t);
|
Expression *e = new CastExp(loc, se, t);
|
||||||
e->type = t;
|
e->type = t; // so semantic() won't be run on e
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+40
-8
@@ -668,7 +668,35 @@ Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
|||||||
|
|
||||||
assert(op == TOKequal || op == TOKnotequal);
|
assert(op == TOKequal || op == TOKnotequal);
|
||||||
|
|
||||||
if (e1->op == TOKstring && e2->op == TOKstring)
|
if (e1->op == TOKnull)
|
||||||
|
{
|
||||||
|
if (e2->op == TOKnull)
|
||||||
|
cmp = 1;
|
||||||
|
else if (e2->op == TOKstring)
|
||||||
|
{ StringExp *es2 = (StringExp *)e2;
|
||||||
|
cmp = (0 == es2->len);
|
||||||
|
}
|
||||||
|
else if (e2->op == TOKarrayliteral)
|
||||||
|
{ ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
|
||||||
|
cmp = !es2->elements || (0 == es2->elements->dim);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
|
else if (e2->op == TOKnull)
|
||||||
|
{
|
||||||
|
if (e1->op == TOKstring)
|
||||||
|
{ StringExp *es1 = (StringExp *)e1;
|
||||||
|
cmp = (0 == es1->len);
|
||||||
|
}
|
||||||
|
else if (e1->op == TOKarrayliteral)
|
||||||
|
{ ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
|
||||||
|
cmp = !es1->elements || (0 == es1->elements->dim);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
|
else if (e1->op == TOKstring && e2->op == TOKstring)
|
||||||
{ StringExp *es1 = (StringExp *)e1;
|
{ StringExp *es1 = (StringExp *)e1;
|
||||||
StringExp *es2 = (StringExp *)e2;
|
StringExp *es2 = (StringExp *)e2;
|
||||||
|
|
||||||
@@ -792,7 +820,11 @@ Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
|
|||||||
Loc loc = e1->loc;
|
Loc loc = e1->loc;
|
||||||
int cmp;
|
int cmp;
|
||||||
|
|
||||||
if (e1->op == TOKsymoff && e2->op == TOKsymoff)
|
if (e1->op == TOKnull && e2->op == TOKnull)
|
||||||
|
{
|
||||||
|
cmp = 1;
|
||||||
|
}
|
||||||
|
else if (e1->op == TOKsymoff && e2->op == TOKsymoff)
|
||||||
{
|
{
|
||||||
SymOffExp *es1 = (SymOffExp *)e1;
|
SymOffExp *es1 = (SymOffExp *)e1;
|
||||||
SymOffExp *es2 = (SymOffExp *)e2;
|
SymOffExp *es2 = (SymOffExp *)e2;
|
||||||
@@ -1051,7 +1083,7 @@ Expression *Cast(Type *type, Type *to, Expression *e1)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error("cannot cast %s to %s", e1->type->toChars(), type->toChars());
|
error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars());
|
||||||
e = new IntegerExp(loc, 0, type);
|
e = new IntegerExp(loc, 0, type);
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
@@ -1245,11 +1277,11 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
|||||||
|
|
||||||
//printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
|
//printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
|
||||||
|
|
||||||
if (e1->op == TOKnull && e2->op == TOKint64)
|
if (e1->op == TOKnull && (e2->op == TOKint64 || e2->op == TOKstructliteral))
|
||||||
{ e = e2;
|
{ e = e2;
|
||||||
goto L2;
|
goto L2;
|
||||||
}
|
}
|
||||||
else if (e1->op == TOKint64 && e2->op == TOKnull)
|
else if ((e1->op == TOKint64 || e1->op == TOKstructliteral) && e2->op == TOKnull)
|
||||||
{ e = e1;
|
{ e = e1;
|
||||||
L2:
|
L2:
|
||||||
Type *tn = e->type->toBasetype();
|
Type *tn = e->type->toBasetype();
|
||||||
@@ -1381,7 +1413,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
|||||||
e->type = type;
|
e->type = type;
|
||||||
}
|
}
|
||||||
else if (e1->op == TOKarrayliteral &&
|
else if (e1->op == TOKarrayliteral &&
|
||||||
e1->type->toBasetype()->next->equals(e2->type))
|
e1->type->toBasetype()->nextOf()->equals(e2->type))
|
||||||
{
|
{
|
||||||
ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
|
ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
|
||||||
|
|
||||||
@@ -1398,7 +1430,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
|||||||
e->type = type;
|
e->type = type;
|
||||||
}
|
}
|
||||||
else if (e2->op == TOKarrayliteral &&
|
else if (e2->op == TOKarrayliteral &&
|
||||||
e2->type->toBasetype()->next->equals(e1->type))
|
e2->type->toBasetype()->nextOf()->equals(e1->type))
|
||||||
{
|
{
|
||||||
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
|
ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
|
||||||
|
|
||||||
@@ -1425,7 +1457,7 @@ Expression *Cat(Type *type, Expression *e1, Expression *e2)
|
|||||||
t = e2->type;
|
t = e2->type;
|
||||||
L1:
|
L1:
|
||||||
Type *tb = t->toBasetype();
|
Type *tb = t->toBasetype();
|
||||||
if (tb->ty == Tarray && tb->next->equals(e->type))
|
if (tb->ty == Tarray && tb->nextOf()->equals(e->type))
|
||||||
{ Expressions *expressions = new Expressions();
|
{ Expressions *expressions = new Expressions();
|
||||||
expressions->push(e);
|
expressions->push(e);
|
||||||
e = new ArrayLiteralExp(loc, expressions);
|
e = new ArrayLiteralExp(loc, expressions);
|
||||||
|
|||||||
+24
-7
@@ -771,7 +771,12 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
//printf("Providing default initializer for '%s'\n", toChars());
|
//printf("Providing default initializer for '%s'\n", toChars());
|
||||||
if (type->ty == Tstruct &&
|
if (type->ty == Tstruct &&
|
||||||
((TypeStruct *)type)->sym->zeroInit == 1)
|
((TypeStruct *)type)->sym->zeroInit == 1)
|
||||||
{
|
{ /* If a struct is all zeros, as a special case
|
||||||
|
* set it's initializer to the integer 0.
|
||||||
|
* In AssignExp::toElem(), we check for this and issue
|
||||||
|
* a memset() to initialize the struct.
|
||||||
|
* Must do same check in interpreter.
|
||||||
|
*/
|
||||||
Expression *e = new IntegerExp(loc, 0, Type::tint32);
|
Expression *e = new IntegerExp(loc, 0, Type::tint32);
|
||||||
Expression *e1;
|
Expression *e1;
|
||||||
e1 = new VarExp(loc, this);
|
e1 = new VarExp(loc, this);
|
||||||
@@ -801,11 +806,12 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
if (init)
|
if (init)
|
||||||
{
|
{
|
||||||
ArrayInitializer *ai = init->isArrayInitializer();
|
ArrayInitializer *ai = init->isArrayInitializer();
|
||||||
if (ai && type->toBasetype()->ty == Taarray)
|
if (ai && tb->ty == Taarray)
|
||||||
{
|
{
|
||||||
init = ai->toAssocArrayInitializer();
|
init = ai->toAssocArrayInitializer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StructInitializer *si = init->isStructInitializer();
|
||||||
ExpInitializer *ei = init->isExpInitializer();
|
ExpInitializer *ei = init->isExpInitializer();
|
||||||
|
|
||||||
// See if we can allocate on the stack
|
// See if we can allocate on the stack
|
||||||
@@ -898,16 +904,25 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
* Ignore failure.
|
* Ignore failure.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (ei && !global.errors && !inferred)
|
if (!global.errors && !inferred)
|
||||||
{
|
{
|
||||||
unsigned errors = global.errors;
|
unsigned errors = global.errors;
|
||||||
global.gag++;
|
global.gag++;
|
||||||
//printf("+gag\n");
|
//printf("+gag\n");
|
||||||
Expression *e = ei->exp->syntaxCopy();
|
Expression *e;
|
||||||
|
Initializer *i2 = init;
|
||||||
inuse++;
|
inuse++;
|
||||||
e = e->semantic(sc);
|
if (ei)
|
||||||
|
{
|
||||||
|
e = ei->exp->syntaxCopy();
|
||||||
|
e = e->semantic(sc);
|
||||||
|
e = e->implicitCastTo(sc, type);
|
||||||
|
}
|
||||||
|
else if (si || ai)
|
||||||
|
{ i2 = init->syntaxCopy();
|
||||||
|
i2 = i2->semantic(sc, type);
|
||||||
|
}
|
||||||
inuse--;
|
inuse--;
|
||||||
e = e->implicitCastTo(sc, type);
|
|
||||||
global.gag--;
|
global.gag--;
|
||||||
//printf("-gag\n");
|
//printf("-gag\n");
|
||||||
if (errors != global.errors) // if errors happened
|
if (errors != global.errors) // if errors happened
|
||||||
@@ -915,7 +930,7 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
if (global.gag == 0)
|
if (global.gag == 0)
|
||||||
global.errors = errors; // act as if nothing happened
|
global.errors = errors; // act as if nothing happened
|
||||||
}
|
}
|
||||||
else
|
else if (ei)
|
||||||
{
|
{
|
||||||
e = e->optimize(WANTvalue | WANTinterpret);
|
e = e->optimize(WANTvalue | WANTinterpret);
|
||||||
if (e->op == TOKint64 || e->op == TOKstring)
|
if (e->op == TOKint64 || e->op == TOKstring)
|
||||||
@@ -923,6 +938,8 @@ void VarDeclaration::semantic(Scope *sc)
|
|||||||
ei->exp = e; // no errors, keep result
|
ei->exp = e; // no errors, keep result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
init = i2; // no errors, keep result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -775,6 +775,43 @@ char *ScopeDsymbol::kind()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************
|
||||||
|
* Look for member of the form:
|
||||||
|
* const(MemberInfo)[] getMembers(string);
|
||||||
|
* Returns NULL if not found
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if V2
|
||||||
|
FuncDeclaration *ScopeDsymbol::findGetMembers()
|
||||||
|
{
|
||||||
|
Dsymbol *s = search_function(this, Id::getmembers);
|
||||||
|
FuncDeclaration *fdx = s ? s->isFuncDeclaration() : NULL;
|
||||||
|
|
||||||
|
#if 0 // Finish
|
||||||
|
static TypeFunction *tfgetmembers;
|
||||||
|
|
||||||
|
if (!tfgetmembers)
|
||||||
|
{
|
||||||
|
Scope sc;
|
||||||
|
Arguments *arguments = new Arguments;
|
||||||
|
Arguments *arg = new Argument(STCin, Type::tchar->constOf()->arrayOf(), NULL, NULL);
|
||||||
|
arguments->push(arg);
|
||||||
|
|
||||||
|
Type *tret = NULL;
|
||||||
|
tfgetmembers = new TypeFunction(arguments, tret, 0, LINKd);
|
||||||
|
tfgetmembers = (TypeFunction *)tfgetmembers->semantic(0, &sc);
|
||||||
|
}
|
||||||
|
if (fdx)
|
||||||
|
fdx = fdx->overloadExactMatch(tfgetmembers);
|
||||||
|
#endif
|
||||||
|
if (fdx && fdx->isVirtual())
|
||||||
|
fdx = NULL;
|
||||||
|
|
||||||
|
return fdx;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/****************************** WithScopeSymbol ******************************/
|
/****************************** WithScopeSymbol ******************************/
|
||||||
|
|
||||||
WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
|
WithScopeSymbol::WithScopeSymbol(WithStatement *withstate)
|
||||||
|
|||||||
+32
-12
@@ -619,9 +619,11 @@ void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
|
|||||||
for (size_t i = 0; i < arguments->dim; i++)
|
for (size_t i = 0; i < arguments->dim; i++)
|
||||||
{ Expression *arg = (Expression *)arguments->data[i];
|
{ Expression *arg = (Expression *)arguments->data[i];
|
||||||
|
|
||||||
if (i)
|
if (arg)
|
||||||
buf->writeByte(',');
|
{ if (i)
|
||||||
expToCBuffer(buf, hgs, arg, PREC_assign);
|
buf->writeByte(',');
|
||||||
|
expToCBuffer(buf, hgs, arg, PREC_assign);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3979,9 +3981,9 @@ void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
|
|
||||||
/************************************************************/
|
/************************************************************/
|
||||||
|
|
||||||
IftypeExp::IftypeExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
|
IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
|
||||||
Type *tspec, enum TOK tok2)
|
Type *tspec, enum TOK tok2)
|
||||||
: Expression(loc, TOKis, sizeof(IftypeExp))
|
: Expression(loc, TOKis, sizeof(IsExp))
|
||||||
{
|
{
|
||||||
this->targ = targ;
|
this->targ = targ;
|
||||||
this->id = id;
|
this->id = id;
|
||||||
@@ -3990,9 +3992,9 @@ IftypeExp::IftypeExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
|
|||||||
this->tok2 = tok2;
|
this->tok2 = tok2;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *IftypeExp::syntaxCopy()
|
Expression *IsExp::syntaxCopy()
|
||||||
{
|
{
|
||||||
return new IftypeExp(loc,
|
return new IsExp(loc,
|
||||||
targ->syntaxCopy(),
|
targ->syntaxCopy(),
|
||||||
id,
|
id,
|
||||||
tok,
|
tok,
|
||||||
@@ -4000,10 +4002,10 @@ Expression *IftypeExp::syntaxCopy()
|
|||||||
tok2);
|
tok2);
|
||||||
}
|
}
|
||||||
|
|
||||||
Expression *IftypeExp::semantic(Scope *sc)
|
Expression *IsExp::semantic(Scope *sc)
|
||||||
{ Type *tded;
|
{ Type *tded;
|
||||||
|
|
||||||
//printf("IftypeExp::semantic()\n");
|
//printf("IsExp::semantic()\n");
|
||||||
if (id && !(sc->flags & SCOPEstaticif))
|
if (id && !(sc->flags & SCOPEstaticif))
|
||||||
error("can only declare type aliases within static if conditionals");
|
error("can only declare type aliases within static if conditionals");
|
||||||
|
|
||||||
@@ -4201,11 +4203,15 @@ Lno:
|
|||||||
return new IntegerExp(0);
|
return new IntegerExp(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IftypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
||||||
{
|
{
|
||||||
buf->writestring("is(");
|
buf->writestring("is(");
|
||||||
targ->toCBuffer(buf, id, hgs);
|
targ->toCBuffer(buf, id, hgs);
|
||||||
if (tspec)
|
if (tok2 != TOKreserved)
|
||||||
|
{
|
||||||
|
buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2));
|
||||||
|
}
|
||||||
|
else if (tspec)
|
||||||
{
|
{
|
||||||
if (tok == TOKcolon)
|
if (tok == TOKcolon)
|
||||||
buf->writestring(" : ");
|
buf->writestring(" : ");
|
||||||
@@ -4213,6 +4219,17 @@ void IftypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
buf->writestring(" == ");
|
buf->writestring(" == ");
|
||||||
tspec->toCBuffer(buf, NULL, hgs);
|
tspec->toCBuffer(buf, NULL, hgs);
|
||||||
}
|
}
|
||||||
|
#if V2
|
||||||
|
if (parameters)
|
||||||
|
{ // First parameter is already output, so start with second
|
||||||
|
for (int i = 1; i < parameters->dim; i++)
|
||||||
|
{
|
||||||
|
buf->writeByte(',');
|
||||||
|
TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
|
||||||
|
tp->toCBuffer(buf, hgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
buf->writeByte(')');
|
buf->writeByte(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5308,7 +5325,7 @@ Expression *CallExp::semantic(Scope *sc)
|
|||||||
int istemp;
|
int istemp;
|
||||||
|
|
||||||
#if LOGSEMANTIC
|
#if LOGSEMANTIC
|
||||||
printf("CallExp::semantic('%s')\n", toChars());
|
printf("CallExp::semantic() %s\n", toChars());
|
||||||
#endif
|
#endif
|
||||||
if (type)
|
if (type)
|
||||||
return this; // semantic() already run
|
return this; // semantic() already run
|
||||||
@@ -5443,6 +5460,9 @@ Lagain:
|
|||||||
ad = ((TypeStruct *)t1)->sym;
|
ad = ((TypeStruct *)t1)->sym;
|
||||||
if (search_function(ad, Id::call))
|
if (search_function(ad, Id::call))
|
||||||
goto L1; // overload of opCall, therefore it's a call
|
goto L1; // overload of opCall, therefore it's a call
|
||||||
|
|
||||||
|
if (e1->op != TOKtype)
|
||||||
|
error("%s %s does not overload ()", ad->kind(), ad->toChars());
|
||||||
/* It's a struct literal
|
/* It's a struct literal
|
||||||
*/
|
*/
|
||||||
Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments);
|
Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments);
|
||||||
|
|||||||
+4
-2
@@ -70,6 +70,8 @@ void inferApplyArgTypes(enum TOK op, Arguments *arguments, Expression *aggr);
|
|||||||
void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
|
void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
|
||||||
void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
|
void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs);
|
||||||
void expandTuples(Expressions *exps);
|
void expandTuples(Expressions *exps);
|
||||||
|
FuncDeclaration *hasThis(Scope *sc);
|
||||||
|
Expression *fromConstInitializer(int result, Expression *e);
|
||||||
|
|
||||||
struct Expression : Object
|
struct Expression : Object
|
||||||
{
|
{
|
||||||
@@ -622,7 +624,7 @@ struct HaltExp : Expression
|
|||||||
elem *toElem(IRState *irs);
|
elem *toElem(IRState *irs);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IftypeExp : Expression
|
struct IsExp : Expression
|
||||||
{
|
{
|
||||||
/* is(targ id tok tspec)
|
/* is(targ id tok tspec)
|
||||||
* is(targ id == tok2)
|
* is(targ id == tok2)
|
||||||
@@ -633,7 +635,7 @@ struct IftypeExp : Expression
|
|||||||
Type *tspec; // can be NULL
|
Type *tspec; // can be NULL
|
||||||
enum TOK tok2; // 'struct', 'union', 'typedef', etc.
|
enum TOK tok2; // 'struct', 'union', 'typedef', etc.
|
||||||
|
|
||||||
IftypeExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec, enum TOK tok2);
|
IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok, Type *tspec, enum TOK tok2);
|
||||||
Expression *syntaxCopy();
|
Expression *syntaxCopy();
|
||||||
Expression *semantic(Scope *sc);
|
Expression *semantic(Scope *sc);
|
||||||
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
|
||||||
|
|||||||
+10
-7
@@ -255,7 +255,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
if (!isVirtual())
|
if (!isVirtual())
|
||||||
{
|
{
|
||||||
//printf("\tnot virtual\n");
|
//printf("\tnot virtual\n");
|
||||||
return;
|
goto Ldone;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find index of existing function in vtbl[] to override
|
// Find index of existing function in vtbl[] to override
|
||||||
@@ -405,8 +405,8 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
#if 0
|
#if 0
|
||||||
if (offset)
|
if (offset)
|
||||||
ti = fdv->type;
|
ti = fdv->type;
|
||||||
else if (type->next->ty == Tclass)
|
else if (type->nextOf()->ty == Tclass)
|
||||||
{ ClassDeclaration *cdn = ((TypeClass *)type->next)->sym;
|
{ ClassDeclaration *cdn = ((TypeClass *)type->nextOf())->sym;
|
||||||
if (cdn && cdn->sizeok != 1)
|
if (cdn && cdn->sizeok != 1)
|
||||||
ti = fdv->type;
|
ti = fdv->type;
|
||||||
}
|
}
|
||||||
@@ -480,8 +480,8 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
{
|
{
|
||||||
Argument *arg0 = Argument::getNth(f->parameters, 0);
|
Argument *arg0 = Argument::getNth(f->parameters, 0);
|
||||||
if (arg0->type->ty != Tarray ||
|
if (arg0->type->ty != Tarray ||
|
||||||
arg0->type->next->ty != Tarray ||
|
arg0->type->nextOf()->ty != Tarray ||
|
||||||
arg0->type->next->next->ty != Tchar ||
|
arg0->type->nextOf()->nextOf()->ty != Tchar ||
|
||||||
arg0->storageClass & (STCout | STCref | STClazy))
|
arg0->storageClass & (STCout | STCref | STClazy))
|
||||||
goto Lmainerr;
|
goto Lmainerr;
|
||||||
break;
|
break;
|
||||||
@@ -526,6 +526,7 @@ void FuncDeclaration::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ldone:
|
||||||
/* Save scope for possible later use (if we need the
|
/* Save scope for possible later use (if we need the
|
||||||
* function internals)
|
* function internals)
|
||||||
*/
|
*/
|
||||||
@@ -2185,7 +2186,8 @@ void DtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
/********************************* StaticCtorDeclaration ****************************/
|
/********************************* StaticCtorDeclaration ****************************/
|
||||||
|
|
||||||
StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
|
StaticCtorDeclaration::StaticCtorDeclaration(Loc loc, Loc endloc)
|
||||||
: FuncDeclaration(loc, endloc, Id::staticCtor, STCstatic, NULL)
|
: FuncDeclaration(loc, endloc,
|
||||||
|
Identifier::generateId("_staticCtor"), STCstatic, NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2257,7 +2259,8 @@ void StaticCtorDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
|
|||||||
/********************************* StaticDtorDeclaration ****************************/
|
/********************************* StaticDtorDeclaration ****************************/
|
||||||
|
|
||||||
StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
|
StaticDtorDeclaration::StaticDtorDeclaration(Loc loc, Loc endloc)
|
||||||
: FuncDeclaration(loc, endloc, Id::staticDtor, STCstatic, NULL)
|
: FuncDeclaration(loc, endloc,
|
||||||
|
Identifier::generateId("_staticDtor"), STCstatic, NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,8 +12,6 @@ Identifier *Id::ctor;
|
|||||||
Identifier *Id::dtor;
|
Identifier *Id::dtor;
|
||||||
Identifier *Id::classInvariant;
|
Identifier *Id::classInvariant;
|
||||||
Identifier *Id::unitTest;
|
Identifier *Id::unitTest;
|
||||||
Identifier *Id::staticCtor;
|
|
||||||
Identifier *Id::staticDtor;
|
|
||||||
Identifier *Id::init;
|
Identifier *Id::init;
|
||||||
Identifier *Id::size;
|
Identifier *Id::size;
|
||||||
Identifier *Id::__sizeof;
|
Identifier *Id::__sizeof;
|
||||||
@@ -187,8 +185,6 @@ void Id::initialize()
|
|||||||
dtor = Lexer::idPool("_dtor");
|
dtor = Lexer::idPool("_dtor");
|
||||||
classInvariant = Lexer::idPool("__invariant");
|
classInvariant = Lexer::idPool("__invariant");
|
||||||
unitTest = Lexer::idPool("_unitTest");
|
unitTest = Lexer::idPool("_unitTest");
|
||||||
staticCtor = Lexer::idPool("_staticCtor");
|
|
||||||
staticDtor = Lexer::idPool("_staticDtor");
|
|
||||||
init = Lexer::idPool("init");
|
init = Lexer::idPool("init");
|
||||||
size = Lexer::idPool("size");
|
size = Lexer::idPool("size");
|
||||||
__sizeof = Lexer::idPool("sizeof");
|
__sizeof = Lexer::idPool("sizeof");
|
||||||
|
|||||||
@@ -14,8 +14,6 @@ struct Id
|
|||||||
static Identifier *dtor;
|
static Identifier *dtor;
|
||||||
static Identifier *classInvariant;
|
static Identifier *classInvariant;
|
||||||
static Identifier *unitTest;
|
static Identifier *unitTest;
|
||||||
static Identifier *staticCtor;
|
|
||||||
static Identifier *staticDtor;
|
|
||||||
static Identifier *init;
|
static Identifier *init;
|
||||||
static Identifier *size;
|
static Identifier *size;
|
||||||
static Identifier *__sizeof;
|
static Identifier *__sizeof;
|
||||||
|
|||||||
+9
-3
@@ -53,14 +53,20 @@ char *Identifier::toHChars2()
|
|||||||
else if (this == Id::dtor) p = "~this";
|
else if (this == Id::dtor) p = "~this";
|
||||||
else if (this == Id::classInvariant) p = "invariant";
|
else if (this == Id::classInvariant) p = "invariant";
|
||||||
else if (this == Id::unitTest) p = "unittest";
|
else if (this == Id::unitTest) p = "unittest";
|
||||||
else if (this == Id::staticCtor) p = "static this";
|
|
||||||
else if (this == Id::staticDtor) p = "static ~this";
|
|
||||||
else if (this == Id::dollar) p = "$";
|
else if (this == Id::dollar) p = "$";
|
||||||
else if (this == Id::withSym) p = "with";
|
else if (this == Id::withSym) p = "with";
|
||||||
else if (this == Id::result) p = "result";
|
else if (this == Id::result) p = "result";
|
||||||
else if (this == Id::returnLabel) p = "return";
|
else if (this == Id::returnLabel) p = "return";
|
||||||
else
|
else
|
||||||
p = toChars();
|
{ p = toChars();
|
||||||
|
if (*p == '_')
|
||||||
|
{
|
||||||
|
if (memcmp(p, "_staticCtor", 11) == 0)
|
||||||
|
p = "static this";
|
||||||
|
else if (memcmp(p, "_staticDtor", 11) == 0)
|
||||||
|
p = "static ~this";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,8 +38,6 @@ Msgtable msgtable[] =
|
|||||||
{ "dtor", "_dtor" },
|
{ "dtor", "_dtor" },
|
||||||
{ "classInvariant", "__invariant" },
|
{ "classInvariant", "__invariant" },
|
||||||
{ "unitTest", "_unitTest" },
|
{ "unitTest", "_unitTest" },
|
||||||
{ "staticCtor", "_staticCtor" },
|
|
||||||
{ "staticDtor", "_staticDtor" },
|
|
||||||
{ "init" },
|
{ "init" },
|
||||||
{ "size" },
|
{ "size" },
|
||||||
{ "__sizeof", "sizeof" },
|
{ "__sizeof", "sizeof" },
|
||||||
|
|||||||
+36
-2
@@ -235,9 +235,43 @@ Initializer *StructInitializer::semantic(Scope *sc, Type *t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***************************************
|
||||||
|
* This works by transforming a struct initializer into
|
||||||
|
* a struct literal. In the future, the two should be the
|
||||||
|
* same thing.
|
||||||
|
*/
|
||||||
Expression *StructInitializer::toExpression()
|
Expression *StructInitializer::toExpression()
|
||||||
{
|
{ Expression *e;
|
||||||
return NULL; // cannot do it
|
|
||||||
|
//printf("StructInitializer::toExpression() %s\n", toChars());
|
||||||
|
if (!ad) // if fwd referenced
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
StructDeclaration *sd = ad->isStructDeclaration();
|
||||||
|
if (!sd)
|
||||||
|
return NULL;
|
||||||
|
Expressions *elements = new Expressions();
|
||||||
|
for (size_t i = 0; i < value.dim; i++)
|
||||||
|
{
|
||||||
|
if (field.data[i])
|
||||||
|
goto Lno;
|
||||||
|
Initializer *iz = (Initializer *)value.data[i];
|
||||||
|
if (!iz)
|
||||||
|
goto Lno;
|
||||||
|
Expression *ex = iz->toExpression();
|
||||||
|
if (!ex)
|
||||||
|
goto Lno;
|
||||||
|
elements->push(ex);
|
||||||
|
}
|
||||||
|
e = new StructLiteralExp(loc, sd, elements);
|
||||||
|
e->type = sd->type;
|
||||||
|
return e;
|
||||||
|
|
||||||
|
Lno:
|
||||||
|
delete elements;
|
||||||
|
//error(loc, "struct initializers as expressions are not allowed");
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -23,6 +23,7 @@ struct Type;
|
|||||||
struct dt_t;
|
struct dt_t;
|
||||||
struct AggregateDeclaration;
|
struct AggregateDeclaration;
|
||||||
struct VoidInitializer;
|
struct VoidInitializer;
|
||||||
|
struct StructInitializer;
|
||||||
struct ArrayInitializer;
|
struct ArrayInitializer;
|
||||||
struct ExpInitializer;
|
struct ExpInitializer;
|
||||||
struct StructInitializer;
|
struct StructInitializer;
|
||||||
@@ -47,9 +48,9 @@ struct Initializer : Object
|
|||||||
virtual dt_t *toDt();
|
virtual dt_t *toDt();
|
||||||
|
|
||||||
virtual VoidInitializer *isVoidInitializer() { return NULL; }
|
virtual VoidInitializer *isVoidInitializer() { return NULL; }
|
||||||
|
virtual StructInitializer *isStructInitializer() { return NULL; }
|
||||||
virtual ArrayInitializer *isArrayInitializer() { return NULL; }
|
virtual ArrayInitializer *isArrayInitializer() { return NULL; }
|
||||||
virtual ExpInitializer *isExpInitializer() { return NULL; }
|
virtual ExpInitializer *isExpInitializer() { return NULL; }
|
||||||
virtual StructInitializer *isStructInitializer() { return NULL; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VoidInitializer : Initializer
|
struct VoidInitializer : Initializer
|
||||||
@@ -84,7 +85,7 @@ struct StructInitializer : Initializer
|
|||||||
|
|
||||||
dt_t *toDt();
|
dt_t *toDt();
|
||||||
|
|
||||||
virtual StructInitializer *isStructInitializer() { return this; }
|
StructInitializer *isStructInitializer() { return this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ArrayInitializer : Initializer
|
struct ArrayInitializer : Initializer
|
||||||
|
|||||||
+44
-18
@@ -77,6 +77,7 @@ Expression *FuncDeclaration::interpret(InterState *istate, Expressions *argument
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//printf("test2 %d, %p\n", semanticRun, scope);
|
||||||
if (semanticRun == 0 && scope)
|
if (semanticRun == 0 && scope)
|
||||||
{
|
{
|
||||||
semantic3(scope);
|
semantic3(scope);
|
||||||
@@ -276,7 +277,7 @@ Expression *ExpStatement::interpret(InterState *istate)
|
|||||||
Expression *e = exp->interpret(istate);
|
Expression *e = exp->interpret(istate);
|
||||||
if (e == EXP_CANT_INTERPRET)
|
if (e == EXP_CANT_INTERPRET)
|
||||||
{
|
{
|
||||||
//printf("cannot interpret %s\n", exp->toChars());
|
//printf("-ExpStatement::interpret(): %p\n", e);
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,20 +365,13 @@ Expression *IfStatement::interpret(InterState *istate)
|
|||||||
//if (e == EXP_CANT_INTERPRET) printf("cannot interpret\n");
|
//if (e == EXP_CANT_INTERPRET) printf("cannot interpret\n");
|
||||||
if (e != EXP_CANT_INTERPRET)
|
if (e != EXP_CANT_INTERPRET)
|
||||||
{
|
{
|
||||||
if (!e->isConst())
|
if (e->isBool(TRUE))
|
||||||
{
|
e = ifbody ? ifbody->interpret(istate) : NULL;
|
||||||
e = EXP_CANT_INTERPRET;
|
else if (e->isBool(FALSE))
|
||||||
}
|
e = elsebody ? elsebody->interpret(istate) : NULL;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (e->isBool(TRUE))
|
e = EXP_CANT_INTERPRET;
|
||||||
e = ifbody ? ifbody->interpret(istate) : NULL;
|
|
||||||
else if (e->isBool(FALSE))
|
|
||||||
e = elsebody ? elsebody->interpret(istate) : NULL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
e = EXP_CANT_INTERPRET;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return e;
|
return e;
|
||||||
@@ -957,7 +951,7 @@ Expression *getVarExp(Loc loc, InterState *istate, Declaration *d)
|
|||||||
{
|
{
|
||||||
if (v->isConst() && v->init)
|
if (v->isConst() && v->init)
|
||||||
{ e = v->init->toExpression();
|
{ e = v->init->toExpression();
|
||||||
if (!e->type)
|
if (e && !e->type)
|
||||||
e->type = v->type;
|
e->type = v->type;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -994,7 +988,7 @@ Expression *DeclarationExp::interpret(InterState *istate)
|
|||||||
#if LOG
|
#if LOG
|
||||||
printf("DeclarationExp::interpret() %s\n", toChars());
|
printf("DeclarationExp::interpret() %s\n", toChars());
|
||||||
#endif
|
#endif
|
||||||
Expression *e = EXP_CANT_INTERPRET;
|
Expression *e;
|
||||||
VarDeclaration *v = declaration->isVarDeclaration();
|
VarDeclaration *v = declaration->isVarDeclaration();
|
||||||
if (v)
|
if (v)
|
||||||
{
|
{
|
||||||
@@ -1015,6 +1009,19 @@ Expression *DeclarationExp::interpret(InterState *istate)
|
|||||||
e->type = v->type;
|
e->type = v->type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (declaration->isAttribDeclaration() ||
|
||||||
|
declaration->isTemplateMixin() ||
|
||||||
|
declaration->isTupleDeclaration())
|
||||||
|
{ // These can be made to work, too lazy now
|
||||||
|
e = EXP_CANT_INTERPRET;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Others should not contain executable code, so are trivial to evaluate
|
||||||
|
e = NULL;
|
||||||
|
}
|
||||||
|
#if LOG
|
||||||
|
printf("-DeclarationExp::interpret(): %p\n", e);
|
||||||
|
#endif
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1084,7 +1091,7 @@ Expression *ArrayLiteralExp::interpret(InterState *istate)
|
|||||||
if (!expsx)
|
if (!expsx)
|
||||||
{ expsx = new Expressions();
|
{ expsx = new Expressions();
|
||||||
expsx->setDim(elements->dim);
|
expsx->setDim(elements->dim);
|
||||||
for (size_t j = 0; j < i; j++)
|
for (size_t j = 0; j < elements->dim; j++)
|
||||||
{
|
{
|
||||||
expsx->data[j] = elements->data[j];
|
expsx->data[j] = elements->data[j];
|
||||||
}
|
}
|
||||||
@@ -1342,6 +1349,7 @@ Expression *BinExp::interpretCommon2(InterState *istate, fp2_t fp)
|
|||||||
if (e1 == EXP_CANT_INTERPRET)
|
if (e1 == EXP_CANT_INTERPRET)
|
||||||
goto Lcant;
|
goto Lcant;
|
||||||
if (e1->isConst() != 1 &&
|
if (e1->isConst() != 1 &&
|
||||||
|
e1->op != TOKnull &&
|
||||||
e1->op != TOKstring &&
|
e1->op != TOKstring &&
|
||||||
e1->op != TOKarrayliteral &&
|
e1->op != TOKarrayliteral &&
|
||||||
e1->op != TOKstructliteral)
|
e1->op != TOKstructliteral)
|
||||||
@@ -1351,6 +1359,7 @@ Expression *BinExp::interpretCommon2(InterState *istate, fp2_t fp)
|
|||||||
if (e2 == EXP_CANT_INTERPRET)
|
if (e2 == EXP_CANT_INTERPRET)
|
||||||
goto Lcant;
|
goto Lcant;
|
||||||
if (e2->isConst() != 1 &&
|
if (e2->isConst() != 1 &&
|
||||||
|
e2->op != TOKnull &&
|
||||||
e2->op != TOKstring &&
|
e2->op != TOKstring &&
|
||||||
e2->op != TOKarrayliteral &&
|
e2->op != TOKarrayliteral &&
|
||||||
e2->op != TOKstructliteral)
|
e2->op != TOKstructliteral)
|
||||||
@@ -1420,7 +1429,14 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
|||||||
if (fp)
|
if (fp)
|
||||||
e2 = (*fp)(v->type, ev, e2);
|
e2 = (*fp)(v->type, ev, e2);
|
||||||
else
|
else
|
||||||
|
{ /* Look for special case of struct being initialized with 0.
|
||||||
|
*/
|
||||||
|
if (v->type->toBasetype()->ty == Tstruct && e2->op == TOKint64)
|
||||||
|
{
|
||||||
|
e2 = v->type->defaultInit();
|
||||||
|
}
|
||||||
e2 = Cast(v->type, v->type, e2);
|
e2 = Cast(v->type, v->type, e2);
|
||||||
|
}
|
||||||
if (e2 != EXP_CANT_INTERPRET)
|
if (e2 != EXP_CANT_INTERPRET)
|
||||||
{
|
{
|
||||||
if (!v->isParameter())
|
if (!v->isParameter())
|
||||||
@@ -1453,9 +1469,15 @@ Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
|
|||||||
{ error("variable %s is used before initialization", v->toChars());
|
{ error("variable %s is used before initialization", v->toChars());
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
if (v->value->op != TOKstructliteral)
|
Expression *vie = v->value;
|
||||||
|
if (vie->op == TOKvar)
|
||||||
|
{
|
||||||
|
Declaration *d = ((VarExp *)vie)->var;
|
||||||
|
vie = getVarExp(e1->loc, istate, d);
|
||||||
|
}
|
||||||
|
if (vie->op != TOKstructliteral)
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
StructLiteralExp *se = (StructLiteralExp *)v->value;
|
StructLiteralExp *se = (StructLiteralExp *)vie;
|
||||||
int fieldi = se->getFieldIndex(type, soe->offset);
|
int fieldi = se->getFieldIndex(type, soe->offset);
|
||||||
if (fieldi == -1)
|
if (fieldi == -1)
|
||||||
return EXP_CANT_INTERPRET;
|
return EXP_CANT_INTERPRET;
|
||||||
@@ -1843,6 +1865,10 @@ Expression *ArrayLengthExp::interpret(InterState *istate)
|
|||||||
{
|
{
|
||||||
e = ArrayLength(type, e1);
|
e = ArrayLength(type, e1);
|
||||||
}
|
}
|
||||||
|
else if (e1->op == TOKnull)
|
||||||
|
{
|
||||||
|
e = new IntegerExp(loc, 0, type);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
goto Lcant;
|
goto Lcant;
|
||||||
return e;
|
return e;
|
||||||
|
|||||||
+242
-1
@@ -459,7 +459,7 @@ int Lexer::isValidIdentifier(char *p)
|
|||||||
if (!p || !*p)
|
if (!p || !*p)
|
||||||
goto Linvalid;
|
goto Linvalid;
|
||||||
|
|
||||||
if (isdigit(*p))
|
if (*p >= '0' && *p <= '9') // beware of isdigit() on signed chars
|
||||||
goto Linvalid;
|
goto Linvalid;
|
||||||
|
|
||||||
len = strlen(p);
|
len = strlen(p);
|
||||||
@@ -568,6 +568,23 @@ void Lexer::scan(Token *t)
|
|||||||
t->value = hexStringConstant(t);
|
t->value = hexStringConstant(t);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if V2
|
||||||
|
case 'q':
|
||||||
|
if (p[1] == '"')
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
t->value = delimitedStringConstant(t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (p[1] == '{')
|
||||||
|
{
|
||||||
|
p++;
|
||||||
|
t->value = tokenStringConstant(t);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
goto case_ident;
|
||||||
|
#endif
|
||||||
|
|
||||||
case '"':
|
case '"':
|
||||||
t->value = escapeStringConstant(t,0);
|
t->value = escapeStringConstant(t,0);
|
||||||
@@ -598,7 +615,11 @@ void Lexer::scan(Token *t)
|
|||||||
case 'a': case 'b': case 'c': case 'd': case 'e':
|
case 'a': case 'b': case 'c': case 'd': case 'e':
|
||||||
case 'f': case 'g': case 'h': case 'i': case 'j':
|
case 'f': case 'g': case 'h': case 'i': case 'j':
|
||||||
case 'k': case 'm': case 'n': case 'o':
|
case 'k': case 'm': case 'n': case 'o':
|
||||||
|
#if V2
|
||||||
|
case 'p': /*case 'q': case 'r':*/ case 's': case 't':
|
||||||
|
#else
|
||||||
case 'p': case 'q': /*case 'r':*/ case 's': case 't':
|
case 'p': case 'q': /*case 'r':*/ case 's': case 't':
|
||||||
|
#endif
|
||||||
case 'u': case 'v': case 'w': /*case 'x':*/ case 'y':
|
case 'u': case 'v': case 'w': /*case 'x':*/ case 'y':
|
||||||
case 'z':
|
case 'z':
|
||||||
case 'A': case 'B': case 'C': case 'D': case 'E':
|
case 'A': case 'B': case 'C': case 'D': case 'E':
|
||||||
@@ -1431,6 +1452,223 @@ TOK Lexer::hexStringConstant(Token *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if V2
|
||||||
|
/**************************************
|
||||||
|
* Lex delimited strings:
|
||||||
|
* q"(foo(xxx))" // "foo(xxx)"
|
||||||
|
* q"[foo(]" // "foo("
|
||||||
|
* q"/foo]/" // "foo]"
|
||||||
|
* q"HERE
|
||||||
|
* foo
|
||||||
|
* HERE" // "foo\n"
|
||||||
|
* Input:
|
||||||
|
* p is on the "
|
||||||
|
*/
|
||||||
|
|
||||||
|
TOK Lexer::delimitedStringConstant(Token *t)
|
||||||
|
{ unsigned c;
|
||||||
|
Loc start = loc;
|
||||||
|
unsigned delimleft = 0;
|
||||||
|
unsigned delimright = 0;
|
||||||
|
unsigned nest = 1;
|
||||||
|
unsigned nestcount;
|
||||||
|
Identifier *hereid = NULL;
|
||||||
|
unsigned blankrol = 0;
|
||||||
|
unsigned startline = 0;
|
||||||
|
|
||||||
|
p++;
|
||||||
|
stringbuffer.reset();
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
c = *p++;
|
||||||
|
//printf("c = '%c'\n", c);
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '\n':
|
||||||
|
Lnextline:
|
||||||
|
printf("Lnextline\n");
|
||||||
|
loc.linnum++;
|
||||||
|
startline = 1;
|
||||||
|
if (blankrol)
|
||||||
|
{ blankrol = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (hereid)
|
||||||
|
{
|
||||||
|
stringbuffer.writeUTF8(c);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '\r':
|
||||||
|
if (*p == '\n')
|
||||||
|
continue; // ignore
|
||||||
|
c = '\n'; // treat EndOfLine as \n character
|
||||||
|
goto Lnextline;
|
||||||
|
|
||||||
|
case 0:
|
||||||
|
case 0x1A:
|
||||||
|
goto Lerror;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (c & 0x80)
|
||||||
|
{ p--;
|
||||||
|
c = decodeUTF();
|
||||||
|
p++;
|
||||||
|
if (c == PS || c == LS)
|
||||||
|
goto Lnextline;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (delimleft == 0)
|
||||||
|
{ delimleft = c;
|
||||||
|
nest = 1;
|
||||||
|
nestcount = 1;
|
||||||
|
if (c == '(')
|
||||||
|
delimright = ')';
|
||||||
|
else if (c == '{')
|
||||||
|
delimright = '}';
|
||||||
|
else if (c == '[')
|
||||||
|
delimright = ']';
|
||||||
|
else if (c == '<')
|
||||||
|
delimright = '>';
|
||||||
|
else if (isalpha(c) || c == '_' || (c >= 0x80 && isUniAlpha(c)))
|
||||||
|
{ // Start of identifier; must be a heredoc
|
||||||
|
Token t;
|
||||||
|
p--;
|
||||||
|
scan(&t); // read in heredoc identifier
|
||||||
|
if (t.value != TOKidentifier)
|
||||||
|
{ error("identifier expected for heredoc, not %s", t.toChars());
|
||||||
|
delimright = c;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ hereid = t.ident;
|
||||||
|
printf("hereid = '%s'\n", hereid->toChars());
|
||||||
|
blankrol = 1;
|
||||||
|
}
|
||||||
|
nest = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ delimright = c;
|
||||||
|
nest = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (blankrol)
|
||||||
|
{ error("heredoc rest of line should be blank");
|
||||||
|
blankrol = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (nest == 1)
|
||||||
|
{
|
||||||
|
if (c == delimleft)
|
||||||
|
nestcount++;
|
||||||
|
else if (c == delimright)
|
||||||
|
{ nestcount--;
|
||||||
|
if (nestcount == 0)
|
||||||
|
goto Ldone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (c == delimright)
|
||||||
|
goto Ldone;
|
||||||
|
if (startline && isalpha(c))
|
||||||
|
{ Token t;
|
||||||
|
unsigned char *psave = p;
|
||||||
|
p--;
|
||||||
|
scan(&t); // read in possible heredoc identifier
|
||||||
|
printf("endid = '%s'\n", t.ident->toChars());
|
||||||
|
if (t.value == TOKidentifier && t.ident->equals(hereid))
|
||||||
|
{ /* should check that rest of line is blank
|
||||||
|
*/
|
||||||
|
printf("done\n");
|
||||||
|
goto Ldone;
|
||||||
|
}
|
||||||
|
p = psave;
|
||||||
|
}
|
||||||
|
stringbuffer.writeUTF8(c);
|
||||||
|
startline = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ldone:
|
||||||
|
if (*p == '"')
|
||||||
|
p++;
|
||||||
|
else
|
||||||
|
error("delimited string must end in %c\"", delimright);
|
||||||
|
t->len = stringbuffer.offset;
|
||||||
|
stringbuffer.writeByte(0);
|
||||||
|
t->ustring = (unsigned char *)mem.malloc(stringbuffer.offset);
|
||||||
|
memcpy(t->ustring, stringbuffer.data, stringbuffer.offset);
|
||||||
|
stringPostfix(t);
|
||||||
|
return TOKstring;
|
||||||
|
|
||||||
|
Lerror:
|
||||||
|
error("unterminated string constant starting at %s", start.toChars());
|
||||||
|
t->ustring = (unsigned char *)"";
|
||||||
|
t->len = 0;
|
||||||
|
t->postfix = 0;
|
||||||
|
return TOKstring;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************
|
||||||
|
* Lex delimited strings:
|
||||||
|
* q{ foo(xxx) } // " foo(xxx) "
|
||||||
|
* q{foo(} // "foo("
|
||||||
|
* q{{foo}"}"} // "{foo}"}""
|
||||||
|
* Input:
|
||||||
|
* p is on the q
|
||||||
|
*/
|
||||||
|
|
||||||
|
TOK Lexer::tokenStringConstant(Token *t)
|
||||||
|
{
|
||||||
|
unsigned nest = 1;
|
||||||
|
Loc start = loc;
|
||||||
|
unsigned char *pstart = ++p;
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{ Token tok;
|
||||||
|
|
||||||
|
scan(&tok);
|
||||||
|
switch (tok.value)
|
||||||
|
{
|
||||||
|
case TOKlcurly:
|
||||||
|
nest++;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case TOKrcurly:
|
||||||
|
if (--nest == 0)
|
||||||
|
goto Ldone;
|
||||||
|
continue;
|
||||||
|
|
||||||
|
case TOKeof:
|
||||||
|
goto Lerror;
|
||||||
|
|
||||||
|
default:
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ldone:
|
||||||
|
t->len = p - 1 - pstart;
|
||||||
|
t->ustring = (unsigned char *)mem.malloc(t->len + 1);
|
||||||
|
memcpy(t->ustring, pstart, t->len);
|
||||||
|
t->ustring[t->len] = 0;
|
||||||
|
stringPostfix(t);
|
||||||
|
return TOKstring;
|
||||||
|
|
||||||
|
Lerror:
|
||||||
|
error("unterminated token string constant starting at %s", start.toChars());
|
||||||
|
t->ustring = (unsigned char *)"";
|
||||||
|
t->len = 0;
|
||||||
|
t->postfix = 0;
|
||||||
|
return TOKstring;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/**************************************
|
/**************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2641,6 +2879,9 @@ static Keyword keywords[] =
|
|||||||
// Added after 1.0
|
// Added after 1.0
|
||||||
{ "ref", TOKref },
|
{ "ref", TOKref },
|
||||||
{ "macro", TOKmacro },
|
{ "macro", TOKmacro },
|
||||||
|
#if V2
|
||||||
|
{ "__traits", TOKtraits },
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
int Token::isKeyword()
|
int Token::isKeyword()
|
||||||
|
|||||||
@@ -150,6 +150,9 @@ enum TOK
|
|||||||
// Added after 1.0
|
// Added after 1.0
|
||||||
TOKref,
|
TOKref,
|
||||||
TOKmacro,
|
TOKmacro,
|
||||||
|
#if V2
|
||||||
|
TOKtraits,
|
||||||
|
#endif
|
||||||
|
|
||||||
TOKMAX
|
TOKMAX
|
||||||
};
|
};
|
||||||
@@ -266,6 +269,10 @@ struct Lexer
|
|||||||
unsigned escapeSequence();
|
unsigned escapeSequence();
|
||||||
TOK wysiwygStringConstant(Token *t, int tc);
|
TOK wysiwygStringConstant(Token *t, int tc);
|
||||||
TOK hexStringConstant(Token *t);
|
TOK hexStringConstant(Token *t);
|
||||||
|
#if V2
|
||||||
|
TOK delimitedStringConstant(Token *t);
|
||||||
|
TOK tokenStringConstant(Token *t);
|
||||||
|
#endif
|
||||||
TOK escapeStringConstant(Token *t, int wide);
|
TOK escapeStringConstant(Token *t, int wide);
|
||||||
TOK charConstant(Token *t, int wide);
|
TOK charConstant(Token *t, int wide);
|
||||||
void stringPostfix(Token *t);
|
void stringPostfix(Token *t);
|
||||||
|
|||||||
+13
-2
@@ -68,7 +68,7 @@ Global::Global()
|
|||||||
copyright = "Copyright (c) 1999-2007 by Digital Mars and Tomas Lindquist Olsen";
|
copyright = "Copyright (c) 1999-2007 by Digital Mars and Tomas Lindquist Olsen";
|
||||||
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
written = "written by Walter Bright and Tomas Lindquist Olsen";
|
||||||
llvmdc_version = "0.0.1";
|
llvmdc_version = "0.0.1";
|
||||||
version = "v1.020";
|
version = "v1.021";
|
||||||
global.structalign = 8;
|
global.structalign = 8;
|
||||||
|
|
||||||
memset(¶ms, 0, sizeof(Param));
|
memset(¶ms, 0, sizeof(Param));
|
||||||
@@ -282,6 +282,9 @@ int main(int argc, char *argv[])
|
|||||||
global.params.optimizeLevel = 2;
|
global.params.optimizeLevel = 2;
|
||||||
global.params.runtimeImppath = 0;
|
global.params.runtimeImppath = 0;
|
||||||
|
|
||||||
|
global.params.defaultlibname = "phobos";
|
||||||
|
global.params.debuglibname = global.params.defaultlibname;
|
||||||
|
|
||||||
// Predefine version identifiers
|
// Predefine version identifiers
|
||||||
#if IN_LLVM
|
#if IN_LLVM
|
||||||
VersionCondition::addPredefinedGlobalIdent("LLVM");
|
VersionCondition::addPredefinedGlobalIdent("LLVM");
|
||||||
@@ -474,7 +477,7 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
global.params.runtimeImppath = p+2;
|
global.params.runtimeImppath = p+2;
|
||||||
}
|
}
|
||||||
else if (memcmp(p + 1, "debug", 5) == 0)
|
else if (memcmp(p + 1, "debug", 5) == 0 && p[6] != 'l')
|
||||||
{
|
{
|
||||||
// Parse:
|
// Parse:
|
||||||
// -debug
|
// -debug
|
||||||
@@ -545,6 +548,14 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
global.params.linkswitches->push(p + 2);
|
global.params.linkswitches->push(p + 2);
|
||||||
}
|
}
|
||||||
|
else if (memcmp(p + 1, "defaultlib=", 11) == 0)
|
||||||
|
{
|
||||||
|
global.params.defaultlibname = p + 1 + 11;
|
||||||
|
}
|
||||||
|
else if (memcmp(p + 1, "debuglib=", 9) == 0)
|
||||||
|
{
|
||||||
|
global.params.debuglibname = p + 1 + 9;
|
||||||
|
}
|
||||||
else if (strcmp(p + 1, "run") == 0)
|
else if (strcmp(p + 1, "run") == 0)
|
||||||
{ global.params.run = 1;
|
{ global.params.run = 1;
|
||||||
global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1;
|
global.params.runargs_length = ((i >= argcstart) ? argc : argcstart) - i - 1;
|
||||||
|
|||||||
@@ -94,6 +94,11 @@ struct Param
|
|||||||
|
|
||||||
bool dump_source;
|
bool dump_source;
|
||||||
|
|
||||||
|
char *defaultlibname; // default library for non-debug builds
|
||||||
|
char *debuglibname; // default library for debug builds
|
||||||
|
|
||||||
|
char *xmlname; // filename for XML output
|
||||||
|
|
||||||
// Hidden debug switches
|
// Hidden debug switches
|
||||||
char debuga;
|
char debuga;
|
||||||
char debugb;
|
char debugb;
|
||||||
|
|||||||
+1
-1
@@ -3940,7 +3940,7 @@ Expression *Parser::parsePrimaryExp()
|
|||||||
{ error("(type identifier : specialization) expected following is");
|
{ error("(type identifier : specialization) expected following is");
|
||||||
goto Lerr;
|
goto Lerr;
|
||||||
}
|
}
|
||||||
e = new IftypeExp(loc, targ, ident, tok, tspec, tok2);
|
e = new IsExp(loc, targ, ident, tok, tspec, tok2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
-19
@@ -894,6 +894,7 @@ Statement *DoStatement::semantic(Scope *sc)
|
|||||||
sc->noctor--;
|
sc->noctor--;
|
||||||
condition = condition->semantic(sc);
|
condition = condition->semantic(sc);
|
||||||
condition = resolveProperties(sc, condition);
|
condition = resolveProperties(sc, condition);
|
||||||
|
condition = condition->optimize(WANTvalue);
|
||||||
|
|
||||||
condition = condition->checkToBoolean();
|
condition = condition->checkToBoolean();
|
||||||
|
|
||||||
@@ -979,6 +980,7 @@ Statement *ForStatement::semantic(Scope *sc)
|
|||||||
sc->noctor++;
|
sc->noctor++;
|
||||||
condition = condition->semantic(sc);
|
condition = condition->semantic(sc);
|
||||||
condition = resolveProperties(sc, condition);
|
condition = resolveProperties(sc, condition);
|
||||||
|
condition = condition->optimize(WANTvalue);
|
||||||
condition = condition->checkToBoolean();
|
condition = condition->checkToBoolean();
|
||||||
if (increment)
|
if (increment)
|
||||||
increment = increment->semantic(sc);
|
increment = increment->semantic(sc);
|
||||||
@@ -1090,7 +1092,8 @@ Statement *ForeachStatement::syntaxCopy()
|
|||||||
{
|
{
|
||||||
Arguments *args = Argument::arraySyntaxCopy(arguments);
|
Arguments *args = Argument::arraySyntaxCopy(arguments);
|
||||||
Expression *exp = aggr->syntaxCopy();
|
Expression *exp = aggr->syntaxCopy();
|
||||||
ForeachStatement *s = new ForeachStatement(loc, op, args, exp, body->syntaxCopy());
|
ForeachStatement *s = new ForeachStatement(loc, op, args, exp,
|
||||||
|
body ? body->syntaxCopy() : NULL);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1255,7 +1258,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
|||||||
/* Look for special case of parsing char types out of char type
|
/* Look for special case of parsing char types out of char type
|
||||||
* array.
|
* array.
|
||||||
*/
|
*/
|
||||||
tn = tab->next->toBasetype();
|
tn = tab->nextOf()->toBasetype();
|
||||||
if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
|
if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
|
||||||
{ Argument *arg;
|
{ Argument *arg;
|
||||||
|
|
||||||
@@ -1311,9 +1314,6 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
|||||||
error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars());
|
error("foreach: %s is not an array of %s", tab->toChars(), value->type->toChars());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value->storage_class & STCout && value->type->toBasetype()->ty == Tbit)
|
|
||||||
error("foreach: value cannot be out and type bit");
|
|
||||||
|
|
||||||
if (key &&
|
if (key &&
|
||||||
((key->type->ty != Tint32 && key->type->ty != Tuns32) ||
|
((key->type->ty != Tint32 && key->type->ty != Tuns32) ||
|
||||||
(global.params.is64bit &&
|
(global.params.is64bit &&
|
||||||
@@ -1356,7 +1356,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
|||||||
Identifier *id;
|
Identifier *id;
|
||||||
Type *tret;
|
Type *tret;
|
||||||
|
|
||||||
tret = func->type->next;
|
tret = func->type->nextOf();
|
||||||
|
|
||||||
// Need a variable to hold value from any return statements in body.
|
// Need a variable to hold value from any return statements in body.
|
||||||
if (!sc->func->vresult && tret && tret != Type::tvoid)
|
if (!sc->func->vresult && tret && tret != Type::tvoid)
|
||||||
@@ -1430,8 +1430,8 @@ Statement *ForeachStatement::semantic(Scope *sc)
|
|||||||
error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars());
|
error("foreach: index must be type %s, not %s", taa->index->toChars(), arg->type->toChars());
|
||||||
arg = (Argument *)arguments->data[1];
|
arg = (Argument *)arguments->data[1];
|
||||||
}
|
}
|
||||||
if (!arg->type->equals(taa->next))
|
if (!arg->type->equals(taa->nextOf()))
|
||||||
error("foreach: value must be type %s, not %s", taa->next->toChars(), arg->type->toChars());
|
error("foreach: value must be type %s, not %s", taa->nextOf()->toChars(), arg->type->toChars());
|
||||||
|
|
||||||
/* Call:
|
/* Call:
|
||||||
* _aaApply(aggr, keysize, flde)
|
* _aaApply(aggr, keysize, flde)
|
||||||
@@ -1982,7 +1982,7 @@ Statement *SwitchStatement::semantic(Scope *sc)
|
|||||||
// If it's not an array, cast it to one
|
// If it's not an array, cast it to one
|
||||||
if (condition->type->ty != Tarray)
|
if (condition->type->ty != Tarray)
|
||||||
{
|
{
|
||||||
condition = condition->implicitCastTo(sc, condition->type->next->arrayOf());
|
condition = condition->implicitCastTo(sc, condition->type->nextOf()->arrayOf());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2122,6 +2122,7 @@ Statement *CaseStatement::syntaxCopy()
|
|||||||
Statement *CaseStatement::semantic(Scope *sc)
|
Statement *CaseStatement::semantic(Scope *sc)
|
||||||
{ SwitchStatement *sw = sc->sw;
|
{ SwitchStatement *sw = sc->sw;
|
||||||
|
|
||||||
|
//printf("CaseStatement::semantic() %s\n", toChars());
|
||||||
exp = exp->semantic(sc);
|
exp = exp->semantic(sc);
|
||||||
if (sw)
|
if (sw)
|
||||||
{ int i;
|
{ int i;
|
||||||
@@ -2390,9 +2391,9 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Type *tret = fd->type->next;
|
Type *tret = fd->type->nextOf();
|
||||||
if (fd->tintro)
|
if (fd->tintro)
|
||||||
tret = fd->tintro->next;
|
tret = fd->tintro->nextOf();
|
||||||
Type *tbret = NULL;
|
Type *tbret = NULL;
|
||||||
|
|
||||||
if (tret)
|
if (tret)
|
||||||
@@ -2452,18 +2453,18 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
else if (fd->inferRetType)
|
else if (fd->inferRetType)
|
||||||
{
|
{
|
||||||
if (fd->type->next)
|
if (fd->type->nextOf())
|
||||||
{
|
{
|
||||||
if (!exp->type->equals(fd->type->next))
|
if (!exp->type->equals(fd->type->nextOf()))
|
||||||
error("mismatched function return type inference of %s and %s",
|
error("mismatched function return type inference of %s and %s",
|
||||||
exp->type->toChars(), fd->type->next->toChars());
|
exp->type->toChars(), fd->type->nextOf()->toChars());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fd->type->next = exp->type;
|
fd->type->next = exp->type;
|
||||||
fd->type = fd->type->semantic(loc, sc);
|
fd->type = fd->type->semantic(loc, sc);
|
||||||
if (!fd->tintro)
|
if (!fd->tintro)
|
||||||
{ tret = fd->type->next;
|
{ tret = fd->type->nextOf();
|
||||||
tbret = tret->toBasetype();
|
tbret = tret->toBasetype();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2475,11 +2476,11 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
|||||||
}
|
}
|
||||||
else if (fd->inferRetType)
|
else if (fd->inferRetType)
|
||||||
{
|
{
|
||||||
if (fd->type->next)
|
if (fd->type->nextOf())
|
||||||
{
|
{
|
||||||
if (fd->type->next->ty != Tvoid)
|
if (fd->type->nextOf()->ty != Tvoid)
|
||||||
error("mismatched function return type inference of void and %s",
|
error("mismatched function return type inference of void and %s",
|
||||||
fd->type->next->toChars());
|
fd->type->nextOf()->toChars());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2510,7 +2511,7 @@ Statement *ReturnStatement::semantic(Scope *sc)
|
|||||||
sc->fes->cases.push(this);
|
sc->fes->cases.push(this);
|
||||||
s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
|
s = new ReturnStatement(0, new IntegerExp(sc->fes->cases.dim + 1));
|
||||||
}
|
}
|
||||||
else if (fd->type->next->toBasetype() == Type::tvoid)
|
else if (fd->type->nextOf()->toBasetype() == Type::tvoid)
|
||||||
{
|
{
|
||||||
Statement *s1;
|
Statement *s1;
|
||||||
Statement *s2;
|
Statement *s2;
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ void StaticAssert::semantic2(Scope *sc)
|
|||||||
{
|
{
|
||||||
Expression *e;
|
Expression *e;
|
||||||
|
|
||||||
|
//printf("StaticAssert::semantic2() %s\n", toChars());
|
||||||
e = exp->semantic(sc);
|
e = exp->semantic(sc);
|
||||||
e = e->optimize(WANTvalue | WANTinterpret);
|
e = e->optimize(WANTvalue | WANTinterpret);
|
||||||
if (e->isBool(FALSE))
|
if (e->isBool(FALSE))
|
||||||
|
|||||||
+3
-2
@@ -1232,7 +1232,7 @@ MATCH Type::deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters,
|
|||||||
return (MATCH) implicitConvTo(at);
|
return (MATCH) implicitConvTo(at);
|
||||||
}
|
}
|
||||||
else if (ty == Tsarray && at->ty == Tarray &&
|
else if (ty == Tsarray && at->ty == Tarray &&
|
||||||
next->equals(at->nextOf()))
|
nextOf()->equals(at->nextOf()))
|
||||||
{
|
{
|
||||||
goto Lexact;
|
goto Lexact;
|
||||||
}
|
}
|
||||||
@@ -3278,7 +3278,6 @@ Identifier *TemplateInstance::genIdent()
|
|||||||
else if (ea)
|
else if (ea)
|
||||||
{ sinteger_t v;
|
{ sinteger_t v;
|
||||||
real_t r;
|
real_t r;
|
||||||
unsigned char *p;
|
|
||||||
|
|
||||||
if (ea->op == TOKvar)
|
if (ea->op == TOKvar)
|
||||||
{
|
{
|
||||||
@@ -3298,6 +3297,8 @@ Identifier *TemplateInstance::genIdent()
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if 1
|
#if 1
|
||||||
|
/* Use deco that matches what it would be for a function parameter
|
||||||
|
*/
|
||||||
buf.writestring(ea->type->deco);
|
buf.writestring(ea->type->deco);
|
||||||
#else
|
#else
|
||||||
// Use type of parameter, not type of argument
|
// Use type of parameter, not type of argument
|
||||||
|
|||||||
Reference in New Issue
Block a user